Skip to content
Open
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
43 changes: 23 additions & 20 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,48 @@
## 2024-06-21 - 루프 λ‚΄ μ •κ·œμ‹ 컴파일
**ν•™μŠ΅:** Kotlinμ—μ„œ λ¬΄μ‹œ νŒŒμΌμ„ μ²˜λ¦¬ν•  λ•Œ 파일 반볡 루프 λ‚΄μ—μ„œ μ •κ·œμ‹(`.toRegex()`)을 μ»΄νŒŒμΌν•˜λŠ” 것은 O(N * M)의 μ‹¬κ°ν•œ μ„±λŠ₯ 병λͺ©μ„ μΌμœΌν‚΅λ‹ˆλ‹€ (N 파일 * M κ·œμΉ™).
**쑰치:** λΆˆν•„μš”ν•œ μ •κ·œμ‹ μž¬μ»΄νŒŒμΌμ„ ν”Όν•˜κΈ° μœ„ν•΄ 항상 파일 반볡 루프 μ™ΈλΆ€μ—μ„œ λ¬Έμžμ—΄ κ·œμΉ™μ„ 컴파일된 `Regex` 객체둜 λ§€ν•‘ν•©λ‹ˆλ‹€ (O(M) 컴파일).
**Learning:** Kotlinμ—μ„œ λ¬΄μ‹œ νŒŒμΌμ„ μ²˜λ¦¬ν•  λ•Œ 파일 반볡 루프 λ‚΄μ—μ„œ μ •κ·œμ‹(`.toRegex()`)을 μ»΄νŒŒμΌν•˜λŠ” 것은 O(N * M)의 μ‹¬κ°ν•œ μ„±λŠ₯ 병λͺ©μ„ μΌμœΌν‚΅λ‹ˆλ‹€ (N 파일 * M κ·œμΉ™).
**Action:** λΆˆν•„μš”ν•œ μ •κ·œμ‹ μž¬μ»΄νŒŒμΌμ„ ν”Όν•˜κΈ° μœ„ν•΄ 항상 파일 반볡 루프 μ™ΈλΆ€μ—μ„œ λ¬Έμžμ—΄ κ·œμΉ™μ„ 컴파일된 `Regex` 객체둜 λ§€ν•‘ν•©λ‹ˆλ‹€ (O(M) 컴파일).

## 2024-05-24 - 루프 λ‚΄ ν• λ‹Ή ν•« 패슀
**ν•™μŠ΅:** 디렉토리 ν•­λͺ©μ„ λ Œλ”λ§ν•  λ•Œ 반볡적인 λ¬Έμžμ—΄ μ—°κ²°κ³Ό 리슀트 기반 μ œμ™Έ 쑰회λ₯Ό μ‚¬μš©ν•˜λ©΄ λŒ€κ·œλͺ¨ λ””λ ‰ν† λ¦¬μ—μ„œ λΆˆν•„μš”ν•œ ν• λ‹Ή 및 쑰회 λΉ„μš©μ΄ λ°œμƒν•©λ‹ˆλ‹€.
**쑰치:** ν•­λͺ© λ Œλ”λ§μ— `StringBuilder`λ₯Ό μ‚¬μš©ν•˜κ³  μ œμ™Έλœ 파일 이름에 λŒ€ν•΄ `Set`을 μ‚¬μš©ν•©λ‹ˆλ‹€.
**Learning:** 디렉토리 ν•­λͺ©μ„ λ Œλ”λ§ν•  λ•Œ 반볡적인 λ¬Έμžμ—΄ μ—°κ²°κ³Ό 리슀트 기반 μ œμ™Έ 쑰회λ₯Ό μ‚¬μš©ν•˜λ©΄ λŒ€κ·œλͺ¨ λ””λ ‰ν† λ¦¬μ—μ„œ λΆˆν•„μš”ν•œ ν• λ‹Ή 및 쑰회 λΉ„μš©μ΄ λ°œμƒν•©λ‹ˆλ‹€.
**Action:** ν•­λͺ© λ Œλ”λ§μ— `StringBuilder`λ₯Ό μ‚¬μš©ν•˜κ³  μ œμ™Έλœ 파일 이름에 λŒ€ν•΄ `Set`을 μ‚¬μš©ν•©λ‹ˆλ‹€.

## 2024-07-26 - 쀑간 λ¬Έμžμ—΄ ν• λ‹Ή
**ν•™μŠ΅:** Kotlinμ—μ„œ λ¬Έμžμ—΄μ— μ—°κ²°λœ `.replace()` 호좜 (예: HTML μ΄μŠ€μΌ€μ΄ν”„)은 각 λ‹¨κ³„μ—μ„œ 쀑간 λ¬Έμžμ—΄μ„ ν• λ‹Ήν•˜μ—¬ μš”μ†Œκ°€ λ§Žμ€ ν•« νŒ¨μŠ€μ—μ„œ μ„±λŠ₯ 및 κ°€λΉ„μ§€ μ»¬λ ‰μ…˜μ— 큰 영ν–₯을 λ―ΈμΉ©λ‹ˆλ‹€.
**쑰치:** μ—°κ²°λœ `.replace()` ν˜ΈμΆœμ„ 문자λ₯Ό ν•œ 번만 λ°˜λ³΅ν•˜λŠ” 단일 패슀 λ£¨ν”„λ‘œ λ°”κΎΈκ³ , λ³€ν™˜λœ 좜λ ₯을 μΆ”κ°€ν•˜κΈ° μœ„ν•΄ `StringBuilder`λ₯Ό μ§€μ—° μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
**Learning:** Kotlinμ—μ„œ λ¬Έμžμ—΄μ— μ—°κ²°λœ `.replace()` 호좜 (예: HTML μ΄μŠ€μΌ€μ΄ν”„)은 각 λ‹¨κ³„μ—μ„œ 쀑간 λ¬Έμžμ—΄μ„ ν• λ‹Ήν•˜μ—¬ μš”μ†Œκ°€ λ§Žμ€ ν•« νŒ¨μŠ€μ—μ„œ μ„±λŠ₯ 및 κ°€λΉ„μ§€ μ»¬λ ‰μ…˜μ— 큰 영ν–₯을 λ―ΈμΉ©λ‹ˆλ‹€.
**Action:** μ—°κ²°λœ `.replace()` ν˜ΈμΆœμ„ 문자λ₯Ό ν•œ 번만 λ°˜λ³΅ν•˜λŠ” 단일 패슀 λ£¨ν”„λ‘œ λ°”κΎΈκ³ , λ³€ν™˜λœ 좜λ ₯을 μΆ”κ°€ν•˜κΈ° μœ„ν•΄ `StringBuilder`λ₯Ό μ§€μ—° μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.

## 2024-07-08 - URL 인코딩 λ¬Έμžμ—΄ ν• λ‹Ή 병λͺ©
**ν•™μŠ΅:** ν•« 패슀 루프 λ‚΄μ—μ„œ μ˜ˆμ•½λœ λ°”μ΄νŠΈλ‹Ή μ΅œλŒ€ 3개의 λ¬Έμžμ—΄μ„ ν• λ‹Ήν•˜λŠ” `byte.toString(16).padStart(2, '0').toUpperCase()`λŠ” μƒλ‹Ήν•œ GC μ••λ ₯을 μœ λ°œν•©λ‹ˆλ‹€. μ΄λŠ” 디렉토리 ν¬λ‘€λŸ¬μ—μ„œ λŒ€κ·œλͺ¨ λ¬Έμžμ—΄μ΄λ‚˜ μˆ˜λ§Žμ€ νŒŒμΌμ„ μ²˜λ¦¬ν•  λ•Œ Kotlinμ—μ„œ ν”νžˆ λ³Ό 수 μžˆλŠ” μœ„ν—˜ν•œ μ•ˆν‹° νŒ¨ν„΄μž…λ‹ˆλ‹€.
**쑰치:** 쀑간 λ¬Έμžμ—΄ 생성을 μ™„μ „νžˆ ν”Όν•˜κΈ° μœ„ν•΄ 포맷된 16μ§„μˆ˜ 좜λ ₯을 μž‘μ„±ν•  λ•Œ μ—°κ²°λœ λ¬Έμžμ—΄ 연산을 직접 문자 λ§€ν•‘ 및 λΉ„νŠΈ μ—°μ‚°(`ushr`, `and`)으둜 λ°”κΏ‰λ‹ˆλ‹€. 10 미만 및 9 초과의 16μ§„μˆ˜ 값을 λͺ¨λ‘ ν¬κ΄„ν•˜λŠ” ν…ŒμŠ€νŠΈ μž…λ ₯을 톡해 100% 브랜치 컀버리지λ₯Ό 보μž₯ν•©λ‹ˆλ‹€.
**Learning:** ν•« 패슀 루프 λ‚΄μ—μ„œ μ˜ˆμ•½λœ λ°”μ΄νŠΈλ‹Ή μ΅œλŒ€ 3개의 λ¬Έμžμ—΄μ„ ν• λ‹Ήν•˜λŠ” `byte.toString(16).padStart(2, '0').toUpperCase()`λŠ” μƒλ‹Ήν•œ GC μ••λ ₯을 μœ λ°œν•©λ‹ˆλ‹€. μ΄λŠ” 디렉토리 ν¬λ‘€λŸ¬μ—μ„œ λŒ€κ·œλͺ¨ λ¬Έμžμ—΄μ΄λ‚˜ μˆ˜λ§Žμ€ νŒŒμΌμ„ μ²˜λ¦¬ν•  λ•Œ Kotlinμ—μ„œ ν”νžˆ λ³Ό 수 μžˆλŠ” μœ„ν—˜ν•œ μ•ˆν‹° νŒ¨ν„΄μž…λ‹ˆλ‹€.
**Action:** 쀑간 λ¬Έμžμ—΄ 생성을 μ™„μ „νžˆ ν”Όν•˜κΈ° μœ„ν•΄ 포맷된 16μ§„μˆ˜ 좜λ ₯을 μž‘μ„±ν•  λ•Œ μ—°κ²°λœ λ¬Έμžμ—΄ 연산을 직접 문자 λ§€ν•‘ 및 λΉ„νŠΈ μ—°μ‚°(`ushr`, `and`)으둜 λ°”κΏ‰λ‹ˆλ‹€. 10 미만 및 9 초과의 16μ§„μˆ˜ 값을 λͺ¨λ‘ ν¬κ΄„ν•˜λŠ” ν…ŒμŠ€νŠΈ μž…λ ₯을 톡해 100% 브랜치 컀버리지λ₯Ό 보μž₯ν•©λ‹ˆλ‹€.

## 2026-07-10 - μ €λ ΄ν•œ λ©”λͺ¨λ¦¬ λ‚΄ 검사 μ „ λΉ„μ‹Ό OS stat 호좜
**ν•™μŠ΅:** Kotlin/Javaμ—μ„œ `java.nio.file.Files`λ₯Ό 톡해 파일 속성 (예: `isDirectory` λ˜λŠ” `isSymbolicLink`)을 ν™•μΈν•˜λ €λ©΄ `Path` 객체λ₯Ό ν• λ‹Ήν•΄μ•Ό ν•˜λ©° λΉ„μ‹Ό λ„€μ΄ν‹°λΈŒ OS stat ν˜ΈμΆœμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€. 파일 λͺ©λ‘μ„ μ²˜λ¦¬ν•  λ•Œ 파일 μ‹œμŠ€ν…œμ„ κ±΄λ“œλ¦¬λŠ” λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 μ œμ™Έ λͺ©λ‘ (μ €λ ΄ν•œ λ©”λͺ¨λ¦¬ λ‚΄ λ¬Έμžμ—΄ μ—°μ‚° μ‚¬μš©)κ³Ό λΉ„κ΅ν•˜μ—¬ 파일 μ‹œμŠ€ν…œ 검사λ₯Ό λ‹¨μΆ•ν•©λ‹ˆλ‹€.
**쑰치:** `Files.isDirectory` 및 `Files.isSymbolicLink`λ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 `exclude` μ„ΈνŠΈλ₯Ό ν™•μΈν•˜λ„λ‘ 쑰건문을 μž¬λ°°μ—΄ν–ˆμŠ΅λ‹ˆλ‹€.
**Learning:** Kotlin/Javaμ—μ„œ `java.nio.file.Files`λ₯Ό 톡해 파일 속성 (예: `isDirectory` λ˜λŠ” `isSymbolicLink`)을 ν™•μΈν•˜λ €λ©΄ `Path` 객체λ₯Ό ν• λ‹Ήν•΄μ•Ό ν•˜λ©° λΉ„μ‹Ό λ„€μ΄ν‹°λΈŒ OS stat ν˜ΈμΆœμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€. 파일 λͺ©λ‘μ„ μ²˜λ¦¬ν•  λ•Œ 파일 μ‹œμŠ€ν…œμ„ κ±΄λ“œλ¦¬λŠ” λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 μ œμ™Έ λͺ©λ‘ (μ €λ ΄ν•œ λ©”λͺ¨λ¦¬ λ‚΄ λ¬Έμžμ—΄ μ—°μ‚° μ‚¬μš©)κ³Ό λΉ„κ΅ν•˜μ—¬ 파일 μ‹œμŠ€ν…œ 검사λ₯Ό λ‹¨μΆ•ν•©λ‹ˆλ‹€.
**Action:** `Files.isDirectory` 및 `Files.isSymbolicLink`λ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 `exclude` μ„ΈνŠΈλ₯Ό ν™•μΈν•˜λ„λ‘ 쑰건문을 μž¬λ°°μ—΄ν–ˆμŠ΅λ‹ˆλ‹€.


## 2026-07-12 - 이쀑 루프 λ‚΄ νŒ¨ν„΄ λ§€μΉ­ μ‘°κΈ° μ’…λ£Œ (Short-Circuit)
**ν•™μŠ΅:** λ¬΄μ‹œν•  파일(ignore patterns)을 확인할 λ•Œ, 각 νŒŒμΌμ— λŒ€ν•΄ λͺ¨λ“  νŒ¨ν„΄μ„ 순회(`forEach`)ν•˜λŠ” 것은 λΉ„νš¨μœ¨μ μž…λ‹ˆλ‹€. 파일이 ν•˜λ‚˜μ˜ νŒ¨ν„΄μ— λ§€μΉ­λ˜μ–΄ μ œμ™Έ λͺ©λ‘μ— μΆ”κ°€λ˜λ©΄ λ‚˜λ¨Έμ§€ νŒ¨ν„΄μ„ 확인할 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 이λ₯Ό μ‘°κΈ° μ’…λ£Œ(Short-circuit)ν•˜μ§€ μ•ŠμœΌλ©΄ λΆˆν•„μš”ν•œ O(N * M) μ •κ·œμ‹/νŒ¨ν„΄ λ§€μΉ­ 평가가 λ°œμƒν•©λ‹ˆλ‹€.
**쑰치:** λ¬΄μ‹œ λͺ©λ‘ 평가 λ“± 쑰건을 λ§Œμ‘±ν•  λ•Œ 더 이상 확인이 ν•„μš” μ—†λŠ” κ²½μš°μ—λŠ” `forEach` λŒ€μ‹  일반 `for` 루프와 `break`λ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜ `any`λ₯Ό ν™œμš©ν•˜μ—¬ 연산을 λ‹¨μΆ•ν•©λ‹ˆλ‹€.
**Learning:** λ¬΄μ‹œν•  파일(ignore patterns)을 확인할 λ•Œ, 각 νŒŒμΌμ— λŒ€ν•΄ λͺ¨λ“  νŒ¨ν„΄μ„ 순회(`forEach`)ν•˜λŠ” 것은 λΉ„νš¨μœ¨μ μž…λ‹ˆλ‹€. 파일이 ν•˜λ‚˜μ˜ νŒ¨ν„΄μ— λ§€μΉ­λ˜μ–΄ μ œμ™Έ λͺ©λ‘μ— μΆ”κ°€λ˜λ©΄ λ‚˜λ¨Έμ§€ νŒ¨ν„΄μ„ 확인할 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 이λ₯Ό μ‘°κΈ° μ’…λ£Œ(Short-circuit)ν•˜μ§€ μ•ŠμœΌλ©΄ λΆˆν•„μš”ν•œ O(N * M) μ •κ·œμ‹/νŒ¨ν„΄ λ§€μΉ­ 평가가 λ°œμƒν•©λ‹ˆλ‹€.
**Action:** λ¬΄μ‹œ λͺ©λ‘ 평가 λ“± 쑰건을 λ§Œμ‘±ν•  λ•Œ 더 이상 확인이 ν•„μš” μ—†λŠ” κ²½μš°μ—λŠ” `forEach` λŒ€μ‹  일반 `for` 루프와 `break`λ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜ `any`λ₯Ό ν™œμš©ν•˜μ—¬ 연산을 λ‹¨μΆ•ν•©λ‹ˆλ‹€.

## 2024-07-28 - 디렉토리 λͺ©λ‘ λΆˆν•„μš”ν•œ μ •λ ¬ μ˜€λ²„ν—€λ“œ
**ν•™μŠ΅:** 디렉토리 λͺ©λ‘(`list()` λ˜λŠ” `listFiles()`)을 λ‹¨μˆœνžˆ ν•„ν„°λ§ν•˜μ—¬ `Set`에 μΆ”κ°€ν•˜λŠ” 경우처럼 νŠΉμ • μˆœμ„œκ°€ ν•„μš”ν•˜μ§€ μ•Šμ€ μž‘μ—…μ—μ„œ `.sorted()`λ₯Ό ν˜ΈμΆœν•˜λ©΄ λΆˆν•„μš”ν•œ O(N log N) μ˜€λ²„ν—€λ“œκ°€ λ°œμƒν•©λ‹ˆλ‹€.
**쑰치:** `Set`κ³Ό 같은 μˆœμ„œμ— λ¬΄κ΄€ν•œ μžλ£Œκ΅¬μ‘°μ— μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κΈ° μœ„ν•œ 필터링 μž‘μ—…μ—μ„œλŠ” 디렉토리 λͺ©λ‘μ—μ„œ `.sorted()` ν˜ΈμΆœμ„ μ œκ±°ν•˜μ—¬ μ„±λŠ₯을 μ΅œμ ν™”ν•©λ‹ˆλ‹€.
**Learning:** 디렉토리 λͺ©λ‘(`list()` λ˜λŠ” `listFiles()`)을 λ‹¨μˆœνžˆ ν•„ν„°λ§ν•˜μ—¬ `Set`에 μΆ”κ°€ν•˜λŠ” 경우처럼 νŠΉμ • μˆœμ„œκ°€ ν•„μš”ν•˜μ§€ μ•Šμ€ μž‘μ—…μ—μ„œ `.sorted()`λ₯Ό ν˜ΈμΆœν•˜λ©΄ λΆˆν•„μš”ν•œ O(N log N) μ˜€λ²„ν—€λ“œκ°€ λ°œμƒν•©λ‹ˆλ‹€.
**Action:** `Set`κ³Ό 같은 μˆœμ„œμ— λ¬΄κ΄€ν•œ μžλ£Œκ΅¬μ‘°μ— μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κΈ° μœ„ν•œ 필터링 μž‘μ—…μ—μ„œλŠ” 디렉토리 λͺ©λ‘μ—μ„œ `.sorted()` ν˜ΈμΆœμ„ μ œκ±°ν•˜μ—¬ μ„±λŠ₯을 μ΅œμ ν™”ν•©λ‹ˆλ‹€.

## 2024-05-18 - [디렉토리 λͺ©λ‘ 캐싱을 ν†΅ν•œ I/O μ˜€λ²„ν—€λ“œ μ΅œμ ν™”]
**Learning:** `process_dir` 및 `process_ignore_file`κ³Ό 같은 ν•¨μˆ˜μ—μ„œ λ™μΌν•œ 디렉토리에 λŒ€ν•΄ `listFiles()` λ˜λŠ” `list()`λ₯Ό 반볡적으둜 ν˜ΈμΆœν•˜λ©΄, 파일 μ‹œμŠ€ν…œ I/O둜 μΈν•œ λΆˆν•„μš”ν•œ μ„±λŠ₯ μ €ν•˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.
**Action:** 디렉토리λ₯Ό μˆœνšŒν•  λ•Œ μƒμœ„ λ£¨ν”„μ—μ„œ `listFiles()`λ₯Ό ν•œ 번만 ν˜ΈμΆœν•˜μ—¬ μΊμ‹±ν•œ ν›„, κ²°κ³Όλ₯Ό 인자둜 전달(예: `dirFiles` λ°°μ—΄)ν•˜μ—¬ μ€‘λ³΅λœ 파일 μ‹œμŠ€ν…œ ν˜ΈμΆœμ„ μ œκ±°ν•΄μ•Ό ν•©λ‹ˆλ‹€.

## 2024-08-01 - URL 인코딩 λΉŒλ” μ§€μ—° 생성
**ν•™μŠ΅:** URL 인코딩이 ν•„μš” μ—†λŠ” μ•ˆμ „ν•œ 경둜 λ¬Έμžμ—΄μ—μ„œλ„ 항상 `StringBuilder`λ₯Ό μƒμ„±ν•˜λ©΄ hot pathμ—μ„œ λΆˆν•„μš”ν•œ 할당이 λ°œμƒν•©λ‹ˆλ‹€.
**쑰치:** μ˜ˆμ•½ λ°”μ΄νŠΈλ₯Ό 처음 λ§Œλ‚¬μ„ λ•Œλ§Œ `StringBuilder`λ₯Ό λ§Œλ“€κ³ , κ·Έ μ „κΉŒμ§€λŠ” 원본 λ¬Έμžμ—΄μ„ κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜λŠ” μ§€μ—° 생성 νŒ¨ν„΄μ„ μ‚¬μš©ν•©λ‹ˆλ‹€.
**Learning:** URL 인코딩이 ν•„μš” μ—†λŠ” μ•ˆμ „ν•œ 경둜 λ¬Έμžμ—΄μ—μ„œλ„ 항상 `StringBuilder`λ₯Ό μƒμ„±ν•˜λ©΄ hot pathμ—μ„œ λΆˆν•„μš”ν•œ 할당이 λ°œμƒν•©λ‹ˆλ‹€.
**Action:** μ˜ˆμ•½ λ°”μ΄νŠΈλ₯Ό 처음 λ§Œλ‚¬μ„ λ•Œλ§Œ `StringBuilder`λ₯Ό λ§Œλ“€κ³ , κ·Έ μ „κΉŒμ§€λŠ” 원본 λ¬Έμžμ—΄μ„ κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜λŠ” μ§€μ—° 생성 νŒ¨ν„΄μ„ μ‚¬μš©ν•©λ‹ˆλ‹€.
## $(date +%Y-%m-%d) - Optimize OS stat calls in file listing
**Learning:** Replaced three separate OS stat calls (`Files.isDirectory(it.toPath(), LinkOption.NOFOLLOW_LINKS)`, `!it.isDirectory()`, and `!Files.isSymbolicLink(it.toPath())`) with a single `Files.readAttributes` call. The original code caused significant I/O overhead. This reduces file metadata fetching time significantly.
**Action:** Always consider using `Files.readAttributes` to fetch multiple file attributes at once rather than calling separate boolean checks like `isDirectory` or `isSymbolicLink` on individual files when iterating directories.
## 2025-01-24 - 단일 readAttributes 호좜둜 파일 속성 쑰회 μ΅œμ ν™”
**ν•™μŠ΅:** `isDirectory`, `!it.isDirectory()`, `isSymbolicLink` 3개의 κ°œλ³„μ μΈ 파일 μ‹œμŠ€ν…œ I/O ν˜ΈμΆœμ„ μˆ˜ν–‰ν•˜λ©΄ μ„±λŠ₯ μ €ν•˜κ°€ ν½λ‹ˆλ‹€. 이λ₯Ό 단일 `Files.readAttributes` 호좜둜 λ³€κ²½ν•˜μ—¬ 메타데이터λ₯Ό ν•œ λ²ˆμ— μ‘°νšŒν•¨μœΌλ‘œμ¨ I/O μ˜€λ²„ν—€λ“œλ₯Ό λŒ€ν­ 쀄일 수 μžˆμŒμ„ ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.
**쑰치:** 디렉토리 순회 μ‹œ 파일의 μ—¬λŸ¬ 속성을 확인할 λ•ŒλŠ” κ°œλ³„μ μΈ stat ν˜ΈμΆœλ³΄λ‹€ `Files.readAttributes`λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•„μš”ν•œ λͺ¨λ“  속성을 ν•œ λ²ˆμ— κ°€μ Έμ˜€λŠ” 방식을 μš°μ„ μ μœΌλ‘œ κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.
**Learning:** `isDirectory`, `!it.isDirectory()`, `isSymbolicLink` 3개의 κ°œλ³„μ μΈ 파일 μ‹œμŠ€ν…œ I/O ν˜ΈμΆœμ„ μˆ˜ν–‰ν•˜λ©΄ μ„±λŠ₯ μ €ν•˜κ°€ ν½λ‹ˆλ‹€. 이λ₯Ό 단일 `Files.readAttributes` 호좜둜 λ³€κ²½ν•˜μ—¬ 메타데이터λ₯Ό ν•œ λ²ˆμ— μ‘°νšŒν•¨μœΌλ‘œμ¨ I/O μ˜€λ²„ν—€λ“œλ₯Ό λŒ€ν­ 쀄일 수 μžˆμŒμ„ ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.
**Action:** 디렉토리 순회 μ‹œ 파일의 μ—¬λŸ¬ 속성을 확인할 λ•ŒλŠ” κ°œλ³„μ μΈ stat ν˜ΈμΆœλ³΄λ‹€ `Files.readAttributes`λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•„μš”ν•œ λͺ¨λ“  속성을 ν•œ λ²ˆμ— κ°€μ Έμ˜€λŠ” 방식을 μš°μ„ μ μœΌλ‘œ κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.
## 2025-01-24 - 단일 readAttributes 호좜둜 파일 속성 쑰회 μ΅œμ ν™”
**ν•™μŠ΅:** `isDirectory`, `!it.isDirectory()`, `isSymbolicLink` 3개의 κ°œλ³„μ μΈ 파일 μ‹œμŠ€ν…œ I/O ν˜ΈμΆœμ„ μˆ˜ν–‰ν•˜λ©΄ μ„±λŠ₯ μ €ν•˜κ°€ ν½λ‹ˆλ‹€. 이λ₯Ό 단일 `Files.readAttributes` 호좜둜 λ³€κ²½ν•˜μ—¬ 메타데이터λ₯Ό ν•œ λ²ˆμ— μ‘°νšŒν•¨μœΌλ‘œμ¨ I/O μ˜€λ²„ν—€λ“œλ₯Ό λŒ€ν­ 쀄일 수 μžˆμŒμ„ ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.
**쑰치:** 디렉토리 순회 μ‹œ 파일의 μ—¬λŸ¬ 속성을 확인할 λ•ŒλŠ” κ°œλ³„μ μΈ stat ν˜ΈμΆœλ³΄λ‹€ `Files.readAttributes`λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•„μš”ν•œ λͺ¨λ“  속성을 ν•œ λ²ˆμ— κ°€μ Έμ˜€λŠ” 방식을 μš°μ„ μ μœΌλ‘œ κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.
**Learning:** `isDirectory`, `!it.isDirectory()`, `isSymbolicLink` 3개의 κ°œλ³„μ μΈ 파일 μ‹œμŠ€ν…œ I/O ν˜ΈμΆœμ„ μˆ˜ν–‰ν•˜λ©΄ μ„±λŠ₯ μ €ν•˜κ°€ ν½λ‹ˆλ‹€. 이λ₯Ό 단일 `Files.readAttributes` 호좜둜 λ³€κ²½ν•˜μ—¬ 메타데이터λ₯Ό ν•œ λ²ˆμ— μ‘°νšŒν•¨μœΌλ‘œμ¨ I/O μ˜€λ²„ν—€λ“œλ₯Ό λŒ€ν­ 쀄일 수 μžˆμŒμ„ ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.
**Action:** 디렉토리 순회 μ‹œ 파일의 μ—¬λŸ¬ 속성을 확인할 λ•ŒλŠ” κ°œλ³„μ μΈ stat ν˜ΈμΆœλ³΄λ‹€ `Files.readAttributes`λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•„μš”ν•œ λͺ¨λ“  속성을 ν•œ λ²ˆμ— κ°€μ Έμ˜€λŠ” 방식을 μš°μ„ μ μœΌλ‘œ κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.
## 2026-07-14 - in-place sort 객체 생성 νšŒν”Ό
**Learning:** Kotlinμ—μ„œ `sortBy { property }`λŠ” 크기가 0μ΄λ‚˜ 1인 λ¦¬μŠ€νŠΈμ— λŒ€ν•΄ Comparator 객체 생성 및 μ •λ ¬ μ˜€λ²„ν—€λ“œλ₯Ό λ°©μ§€ν•˜λ©°, 가독성 μΈ‘λ©΄μ—μ„œλ„ 더 ꢌμž₯λ©λ‹ˆλ‹€.
**Action:** μ„±λŠ₯ ν–₯상 및 가독성 κ°œμ„ μ„ μœ„ν•΄ `sortWith(compareBy(...))` λŒ€μ‹  `sortBy`λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
4 changes: 3 additions & 1 deletion src/main/kotlin/html4tree/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ ${cssContent} </style>

val filesList = dirFiles ?: curr_dir.listFiles()
val dir_files: MutableList<File> = filesList?.toMutableList() ?: mutableListOf()
dir_files.sortWith(compareBy ({it.name}) )
// ⚑ Bolt Performance Optimization: Use sortBy { it.name } instead of sortWith(compareBy { it.name })
// to avoid Comparator creation and sorting overhead for lists of size 0 or 1.
dir_files.sortBy { it.name }
dir_files.forEach {
val fileName = it.getName()
// ⚑ Bolt Performance Optimization: Short-circuit string match before expensive OS filesystem calls
Expand Down
Loading