Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@
## 2026-08-11 - Array의 toMutableList 할당 오버헤드 최적화
**학습:** 배열을 정렬하기 위해 `.toMutableList()`를 호출하면 새로운 `ArrayList` 객체와 내부 배열 객체가 할당되어 대규모 디렉토리를 순회할 때 가비지 컬렉션(GC) 부하를 유발합니다. 배열 복제가 필요한 경우 `.clone()`을 사용하면 하나의 배열 객체만 새로 할당되므로 더 효율적입니다.
**조치:** 디렉토리 파일 배열을 정렬하기 전에 복사할 때 `.toMutableList()` 대신 `.clone()`을 사용하여 불필요한 중간 컬렉션 할당을 제거하고 성능을 향상시켰습니다.

## 2026-09-24 - [중복된 디렉토리 목록 I/O]
**Learning:** `File.list()`는 리소스를 많이 소모하는 I/O 작업입니다. 무시 패턴을 확인하고 디렉토리를 반복할 때 `list()`를 여러 번 호출하면 대기 시간이 크게 증가합니다.
**Action:** 불필요한 시스템 I/O를 방지하기 위해 여러 필터를 반복하거나 적용하기 전에 디렉토리 목록을 한 번 가져와서 지역 변수에 캐시합니다.
9 changes: 6 additions & 3 deletions src/main/kotlin/html4tree/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array<String>? = null): S

val files_to_exclude = mutableSetOf<String>()

// ⚡ Bolt 성능 향상: 디렉토리 목록을 한 번만 가져옵니다.
// 이 함수 내에서 반복되는 File.list() 시스템 I/O 호출을 방지합니다.
val fileList = dirFilesNames ?: curr_dir.list()

// 보안 향상: .html4ignore 파일이 일반 파일인지 확인하고, 심볼릭 링크인 경우 무시하여 DoS 및 경로 조작을 방지합니다.
// 보안 향상: 파일 크기(1MB 제한) 및 줄 수(1000줄), 정규식 길이(100자)를 제한하여 ReDoS 및 메모리 고갈(OOM) 방지
// 보안 향상: 권한이 없는 파일 접근 시 발생하는 예외(DoS)를 방지하기 위해 canRead() 추가 확인
Expand All @@ -324,8 +328,7 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array<String>? = null): S
}

// ⚡ Bolt Performance Optimization: 디렉토리 목록을 Set에 추가하기 위해 필터링만 할 때는 정렬이 불필요하므로 .sorted()를 제거하여 O(N log N) 오버헤드를 방지합니다.
val list = dirFilesNames ?: curr_dir.list()
list?.forEach {
fileList?.forEach {
val current = it
val pathCurrent = try {
java.nio.file.Paths.get(current)
Expand All @@ -350,7 +353,7 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array<String>? = null): S
files_to_exclude.addAll(Constants.defaultSensitiveFiles)

// 보안 향상: dot-like prefixes and case variants of known sensitive names are excluded.
(dirFilesNames ?: curr_dir.list())?.forEach {
fileList?.forEach {
val normalizedName = it.toLowerCase(java.util.Locale.ROOT)
if (
it.isHiddenFile() ||
Expand Down