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
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@
## 2025-01-24 - 단일 readAttributes 호출로 파일 속성 조회 최적화
**학습:** `isDirectory`, `!it.isDirectory()`, `isSymbolicLink` 3개의 개별적인 파일 시스템 I/O 호출을 수행하면 성능 저하가 큽니다. 이를 단일 `Files.readAttributes` 호출로 변경하여 메타데이터를 한 번에 조회함으로써 I/O 오버헤드를 대폭 줄일 수 있음을 확인했습니다.
**조치:** 디렉토리 순회 시 파일의 여러 속성을 확인할 때는 개별적인 stat 호출보다 `Files.readAttributes`를 사용하여 필요한 모든 속성을 한 번에 가져오는 방식을 우선적으로 고려해야 합니다.
## 2025-01-24 - 디렉토리 순회 시 무거운 문자열 생성 및 암호화 연산 분리
**학습:** `process_dir` 안에서 매번 정적 문자열 `cssContent`를 선언하고, SHA-256 해시를 계산하는 것은 모든 폴더를 방문할 때마다 발생하여 디렉토리 크롤링 성능을 크게 떨어트립니다.
**조치:** 무거운 초기화 비용이 드는 정적 문자열과 암호화 연산은 파일의 최상위 프로퍼티로 선언하여 애플리케이션 시작 시 한 번만 계산되도록 합니다. JaCoCo에서 이 최상위 프로퍼티들의 Getter에 대한 커버리지를 100%로 유지하기 위해 명시적인 테스트를 추가합니다.
14 changes: 7 additions & 7 deletions src/main/kotlin/html4tree/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,7 @@ fun write_index_file(curr_dir: File, content: String) {
}
}

fun process_dir(curr_dir: File, excludeSet: Set<String>? = null, dirFiles: Array<File>? = null){

val exclude: Set<String> = excludeSet ?: process_ignore_file(curr_dir)

val cssContent = """
val cssContent = """
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
line-height: 1.5;
Expand Down Expand Up @@ -310,13 +306,17 @@ fun process_dir(curr_dir: File, excludeSet: Set<String>? = null, dirFiles: Array
}
"""

val styleHash = "sha256-" + Base64.getEncoder().encodeToString(MessageDigest.getInstance("SHA-256").digest(cssContent.toByteArray(Charsets.UTF_8)))
val styleHash = "sha256-" + Base64.getEncoder().encodeToString(MessageDigest.getInstance("SHA-256").digest(cssContent.toByteArray(Charsets.UTF_8)))

val css = """
val css = """
<style>
${cssContent} </style>
"""

fun process_dir(curr_dir: File, excludeSet: Set<String>? = null, dirFiles: Array<File>? = null){

val exclude: Set<String> = excludeSet ?: process_ignore_file(curr_dir)

val index_top = """<!doctype html>
<html lang="ko">
<head>
Expand Down
9 changes: 9 additions & 0 deletions src/test/kotlin/html4tree/MainTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,15 @@ class MainTest {
assertFalse(excluded.contains("test.txt1001"))
}

@Test
fun testTopLevelCssPropertiesCoverage() {
// These assertions ensure the implicit getters for top-level properties
// (cssContent, styleHash, css) are covered by JaCoCo.
assertTrue(cssContent.contains("body {"))
assertTrue(styleHash.startsWith("sha256-"))
assertTrue(css.contains("<style>"))
}

@Test
fun testToctouSymlinkSwapRejection() {
val subdir = File(tempDir, "toctou_test_dir")
Expand Down
Loading