diff --git a/html-generators/locales.properties b/html-generators/locales.properties index d3e5ff9..9cee6f1 100644 --- a/html-generators/locales.properties +++ b/html-generators/locales.properties @@ -7,3 +7,4 @@ zh-CN=中文 (简体) ar=العربية fr=Français ja=日本語 +ko=한국어 diff --git a/translations/content/ko/collections/collectors-teeing.yaml b/translations/content/ko/collections/collectors-teeing.yaml new file mode 100644 index 0000000..c6f088c --- /dev/null +++ b/translations/content/ko/collections/collectors-teeing.yaml @@ -0,0 +1,17 @@ +title: "Collectors.teeing()" +oldApproach: "두 번 순회" +modernApproach: "teeing()" +summary: "스트림을 한 번만 순회하여 두 가지 집계를 동시에 계산합니다." +explanation: "Collectors.teeing()은 각 요소를 두 개의 다운스트림 컬렉터에 전달하고 결과를 병합합니다. 데이터를 두 번 스트리밍하거나 가변 누산기를 사용하지 않아도 됩니다." +whyModernWins: +- icon: "⚡" + title: "단일 순회" + desc: "스트림을 두 번 대신 한 번만 처리합니다." +- icon: "🧩" + title: "조합 가능" + desc: "병합 함수로 임의의 두 컬렉터를 결합합니다." +- icon: "🔒" + title: "불변 결과" + desc: "레코드나 값 객체로 직접 병합합니다." +support: + description: "JDK 12 (2019년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/copying-collections-immutably.yaml b/translations/content/ko/collections/copying-collections-immutably.yaml new file mode 100644 index 0000000..b3ffa2a --- /dev/null +++ b/translations/content/ko/collections/copying-collections-immutably.yaml @@ -0,0 +1,17 @@ +title: "컬렉션 불변 복사" +oldApproach: "수동 복사 + 래핑" +modernApproach: "List.copyOf()" +summary: "한 번의 호출로 모든 컬렉션의 불변 복사본을 만듭니다." +explanation: "List.copyOf(), Set.copyOf(), Map.copyOf()는 기존 컬렉션의 불변 스냅샷을 만듭니다. 원본이 이미 불변 컬렉션이라면 복사가 생략됩니다." +whyModernWins: +- icon: "⚡" + title: "스마트 복사" + desc: "원본이 이미 불변이면 복사를 건너뜁니다." +- icon: "📏" + title: "한 번의 호출" + desc: "ArrayList 수동 생성과 래핑이 필요 없습니다." +- icon: "🛡️" + title: "방어적 복사" + desc: "원본을 변경해도 복사본에 영향을 주지 않습니다." +support: + description: "JDK 10 (2018년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/immutable-list-creation.yaml b/translations/content/ko/collections/immutable-list-creation.yaml new file mode 100644 index 0000000..d21b5a3 --- /dev/null +++ b/translations/content/ko/collections/immutable-list-creation.yaml @@ -0,0 +1,17 @@ +title: "불변 리스트 생성" +oldApproach: "장황한 래핑" +modernApproach: "List.of()" +summary: "하나의 깔끔한 표현식으로 불변 리스트를 만듭니다." +explanation: "List.of()는 래핑이나 방어적 복사 없이 진정한 불변 리스트를 만듭니다. null에 비허용적(null 요소 거부)이며 구조적으로 불변입니다. 이전 방식은 세 개의 중첩 호출이 필요했습니다." +whyModernWins: +- icon: "📏" + title: "한 번의 호출" + desc: "세 개의 중첩 호출을 단일 팩토리 메서드로 대체합니다." +- icon: "🔒" + title: "진정한 불변" + desc: "단순 래퍼가 아니라 리스트 자체가 불변입니다." +- icon: "🛡️" + title: "null 안전" + desc: "생성 시점에 null 요소를 거부하여 빠른 실패를 보장합니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/immutable-map-creation.yaml b/translations/content/ko/collections/immutable-map-creation.yaml new file mode 100644 index 0000000..5f8dc5f --- /dev/null +++ b/translations/content/ko/collections/immutable-map-creation.yaml @@ -0,0 +1,17 @@ +title: "불변 맵 생성" +oldApproach: "맵 빌더 패턴" +modernApproach: "Map.of()" +summary: "빌더 없이 인라인으로 불변 맵을 만듭니다." +explanation: "Map.of()는 키-값 쌍을 인라인으로 받아 불변 맵을 반환합니다. 10개 초과 항목의 경우 Map.ofEntries()와 Map.entry() 쌍을 사용하세요." +whyModernWins: +- icon: "📏" + title: "인라인 생성" + desc: "임시 가변 맵이 필요 없습니다." +- icon: "🔒" + title: "불변 결과" + desc: "생성 후 맵을 수정할 수 없습니다." +- icon: "🚫" + title: "null 키/값 불허" + desc: "null 항목은 즉시 거부됩니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/immutable-set-creation.yaml b/translations/content/ko/collections/immutable-set-creation.yaml new file mode 100644 index 0000000..558c19d --- /dev/null +++ b/translations/content/ko/collections/immutable-set-creation.yaml @@ -0,0 +1,17 @@ +title: "불변 셋 생성" +oldApproach: "장황한 래핑" +modernApproach: "Set.of()" +summary: "단일 팩토리 호출로 불변 셋을 만듭니다." +explanation: "Set.of()는 null과 중복 요소를 생성 시점에 거부하는 진정한 불변 셋을 만듭니다. 더 이상 가변 셋을 래핑할 필요가 없습니다." +whyModernWins: +- icon: "📏" + title: "간결함" + desc: "세 개의 중첩 호출 대신 한 줄로 작성합니다." +- icon: "🚫" + title: "중복 감지" + desc: "중복 요소를 실수로 전달하면 예외를 던집니다." +- icon: "🔒" + title: "불변" + desc: "생성 후 추가/제거가 불가능합니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/map-entry-factory.yaml b/translations/content/ko/collections/map-entry-factory.yaml new file mode 100644 index 0000000..c21ab66 --- /dev/null +++ b/translations/content/ko/collections/map-entry-factory.yaml @@ -0,0 +1,17 @@ +title: "Map.entry() 팩토리" +oldApproach: "SimpleEntry" +modernApproach: "Map.entry()" +summary: "깔끔한 팩토리 메서드로 맵 항목을 만듭니다." +explanation: "Map.entry()는 장황한 AbstractMap.SimpleEntry 생성자를 대체합니다. 불변 항목을 반환하므로 Map.ofEntries()와 스트림 연산에 이상적입니다." +whyModernWins: +- icon: "📏" + title: "간결함" + desc: "세 줄 대신 더 명확한 의도로 한 줄에 작성합니다." +- icon: "🔒" + title: "불변" + desc: "반환된 항목을 수정할 수 없습니다." +- icon: "🧩" + title: "조합 가능" + desc: "대형 맵에서 Map.ofEntries()와 완벽하게 작동합니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/reverse-list-iteration.yaml b/translations/content/ko/collections/reverse-list-iteration.yaml new file mode 100644 index 0000000..517cf24 --- /dev/null +++ b/translations/content/ko/collections/reverse-list-iteration.yaml @@ -0,0 +1,17 @@ +title: "리스트 역순 반복" +oldApproach: "수동 ListIterator" +modernApproach: "reversed()" +summary: "깔끔한 향상된 for 루프로 리스트를 역순으로 반복합니다." +explanation: "SequencedCollection의 reversed() 메서드는 리스트의 역순 뷰를 반환합니다. 이 뷰는 원본 리스트와 연결되어 있어 복사가 발생하지 않습니다. 향상된 for 루프 구문으로 역순 반복이 순방향만큼 읽기 쉬워집니다." +whyModernWins: +- icon: "📖" + title: "자연스러운 문법" + desc: "장황한 ListIterator 대신 향상된 for 루프를 사용합니다." +- icon: "⚡" + title: "복사 없음" + desc: "reversed()는 뷰를 반환합니다 — 성능 오버헤드가 없습니다." +- icon: "🧩" + title: "일관된 API" + desc: "List, Deque, SortedSet에서 동일하게 작동합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/sequenced-collections.yaml b/translations/content/ko/collections/sequenced-collections.yaml new file mode 100644 index 0000000..bf8bf27 --- /dev/null +++ b/translations/content/ko/collections/sequenced-collections.yaml @@ -0,0 +1,17 @@ +title: "시퀀스 컬렉션" +oldApproach: "인덱스 산술" +modernApproach: "getFirst/getLast" +summary: "깔끔한 API 메서드로 첫/마지막 요소와 역순 뷰에 접근합니다." +explanation: "SequencedCollection은 List, Deque, SortedSet, LinkedHashSet에 getFirst(), getLast(), reversed(), addFirst(), addLast()를 추가합니다. 더 이상 size-1 산술이나 수동 역순 반복이 필요 없습니다." +whyModernWins: +- icon: "📖" + title: "자기 문서화" + desc: "getLast()는 get(size()-1)보다 훨씬 명확합니다." +- icon: "🔄" + title: "역순 뷰" + desc: "reversed()는 뷰를 제공합니다 — 복사가 필요 없습니다." +- icon: "🧩" + title: "통일된 API" + desc: "List, Deque, SortedSet에서 동일하게 작동합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/stream-toarray-typed.yaml b/translations/content/ko/collections/stream-toarray-typed.yaml new file mode 100644 index 0000000..bd5db27 --- /dev/null +++ b/translations/content/ko/collections/stream-toarray-typed.yaml @@ -0,0 +1,17 @@ +title: "타입이 지정된 스트림 toArray" +oldApproach: "수동 배열 복사" +modernApproach: "toArray(생성자)" +summary: "메서드 참조로 스트림을 타입이 지정된 배열로 변환합니다." +explanation: "toArray(IntFunction) 메서드는 스트림에서 올바르게 타입이 지정된 배열을 만듭니다. 생성자(String[]::new)는 스트림에 생성할 배열 타입을 알려줍니다." +whyModernWins: +- icon: "🎯" + title: "타입 안전" + desc: "Object[] 캐스트 없이 정확한 배열 타입을 얻습니다." +- icon: "🔗" + title: "체이닝 가능" + desc: "스트림 파이프라인의 끝에서 작동합니다." +- icon: "📏" + title: "간결함" + desc: "수동 루프를 하나의 표현식으로 대체합니다." +support: + description: "JDK 8 (2014년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/collections/unmodifiable-collectors.yaml b/translations/content/ko/collections/unmodifiable-collectors.yaml new file mode 100644 index 0000000..388092c --- /dev/null +++ b/translations/content/ko/collections/unmodifiable-collectors.yaml @@ -0,0 +1,17 @@ +title: "수정 불가능한 컬렉터" +oldApproach: "collectingAndThen" +modernApproach: "stream.toList()" +summary: "stream.toList()로 수정 불가능한 리스트에 직접 수집합니다." +explanation: "Java 10에서 toUnmodifiableList(), toUnmodifiableSet(), toUnmodifiableMap()이 추가되어 장황한 collectingAndThen 래퍼를 대체했습니다. 리스트의 경우 Java 16의 stream.toList()가 더 간단한 대안을 제공합니다 — collect() 호출 자체가 필요 없습니다. 다른 컬렉션 타입에는 toUnmodifiableSet()과 toUnmodifiableMap()을 사용하세요." +whyModernWins: +- icon: "📏" + title: "가장 짧은 형태" + desc: "stream.toList()는 collect()나 Collectors 임포트가 전혀 필요 없습니다." +- icon: "🔒" + title: "불변" + desc: "결과를 수정할 수 없어 우발적인 변경을 방지합니다." +- icon: "📖" + title: "가독성" + desc: "스트림 파이프라인의 터미널 단계로 자연스럽게 읽힙니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/concurrency/completablefuture-chaining.yaml b/translations/content/ko/concurrency/completablefuture-chaining.yaml new file mode 100644 index 0000000..d88dd25 --- /dev/null +++ b/translations/content/ko/concurrency/completablefuture-chaining.yaml @@ -0,0 +1,17 @@ +title: "CompletableFuture 체이닝" +oldApproach: "블로킹 Future.get()" +modernApproach: "CompletableFuture" +summary: "CompletableFuture를 사용하여 블로킹 없이 비동기 작업을 체이닝합니다." +explanation: "CompletableFuture는 논블로킹 비동기 파이프라인을 가능하게 합니다. thenApply, thenCompose, thenAccept로 작업을 체이닝하고, exceptionally()로 오류를 처리합니다. 여러 Future를 allOf/anyOf로 조합할 수 있습니다." +whyModernWins: +- icon: "🔗" + title: "체이닝 가능" + desc: "비동기 단계를 읽기 쉬운 파이프라인으로 구성합니다." +- icon: "🚫" + title: "논블로킹" + desc: "어떤 스레드도 결과를 기다리며 유휴 상태로 있지 않습니다." +- icon: "🛡️" + title: "오류 처리" + desc: "exceptionally()와 handle()로 깔끔한 오류 복구를 수행합니다." +support: + description: "JDK 8 (2014년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/concurrency/concurrent-http-virtual.yaml b/translations/content/ko/concurrency/concurrent-http-virtual.yaml new file mode 100644 index 0000000..398edd0 --- /dev/null +++ b/translations/content/ko/concurrency/concurrent-http-virtual.yaml @@ -0,0 +1,17 @@ +title: "가상 스레드를 이용한 동시 HTTP 요청" +oldApproach: "스레드 풀 + URLConnection" +modernApproach: "가상 스레드 + HttpClient" +summary: "가상 스레드와 HttpClient로 여러 URL을 동시에 가져옵니다." +explanation: "가상 스레드를 통해 HTTP 요청당 스레드를 하나씩 만드는 것이 현실적으로 가능해졌습니다. HttpClient와 결합하면 확장 가능한 간단한 블로킹 코드로 복잡한 비동기 콜백 패턴을 대체할 수 있습니다." +whyModernWins: +- icon: "♾️" + title: "요청당 스레드" + desc: "풀 크기 조정 없이 URL당 가상 스레드 하나를 사용합니다." +- icon: "📖" + title: "단순한 코드" + desc: "직관적인 블로킹 코드를 작성합니다." +- icon: "⚡" + title: "높은 처리량" + desc: "최소한의 리소스로 수천 개의 동시 요청을 처리합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/concurrency/executor-try-with-resources.yaml b/translations/content/ko/concurrency/executor-try-with-resources.yaml new file mode 100644 index 0000000..88ef906 --- /dev/null +++ b/translations/content/ko/concurrency/executor-try-with-resources.yaml @@ -0,0 +1,17 @@ +title: "ExecutorService 자동 닫기" +oldApproach: "수동 종료" +modernApproach: "try-with-resources" +summary: "try-with-resources로 실행기를 자동으로 종료합니다." +explanation: "Java 19부터 ExecutorService가 AutoCloseable을 구현합니다. close() 메서드가 shutdown()을 호출하고 작업 완료를 기다립니다. 더 이상 수동 try/finally 종료 패턴이 필요 없습니다." +whyModernWins: +- icon: "🧹" + title: "자동 정리" + desc: "블록이 종료될 때 자동으로 종료됩니다." +- icon: "🛡️" + title: "누수 없음" + desc: "예외가 발생해도 실행기가 항상 종료됩니다." +- icon: "📖" + title: "익숙한 패턴" + desc: "파일, 연결 등에 사용하는 동일한 try-with-resources 패턴입니다." +support: + description: "JDK 19 (2022년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/concurrency/lock-free-lazy-init.yaml b/translations/content/ko/concurrency/lock-free-lazy-init.yaml new file mode 100644 index 0000000..4f2075e --- /dev/null +++ b/translations/content/ko/concurrency/lock-free-lazy-init.yaml @@ -0,0 +1,17 @@ +title: "락 없는 지연 초기화" +oldApproach: "synchronized + volatile" +modernApproach: "StableValue" +summary: "지연 초기화 싱글톤을 위해 이중 검사 잠금을 StableValue로 대체합니다." +explanation: "StableValue는 올바른 스레드 안전성으로 지연 초기화 패턴을 캡슐화합니다. JVM은 초기화 후 읽기 경로를 최적화하여 volatile 읽기보다 빠르게 만들 수 있습니다." +whyModernWins: +- icon: "🧹" + title: "보일러플레이트 없음" + desc: "volatile, synchronized, 이중 null 확인이 필요 없습니다." +- icon: "⚡" + title: "더 빠른 읽기" + desc: "JVM이 초기화 후 상수로 최적화할 수 있습니다." +- icon: "✅" + title: "증명 가능한 정확성" + desc: "미묘한 순서 버그 없음 — JVM이 처리합니다." +support: + description: "JDK 25에서 프리뷰 (JEP 502, StableValue). --enable-preview가 필요합니다." diff --git a/translations/content/ko/concurrency/process-api.yaml b/translations/content/ko/concurrency/process-api.yaml new file mode 100644 index 0000000..2193490 --- /dev/null +++ b/translations/content/ko/concurrency/process-api.yaml @@ -0,0 +1,17 @@ +title: "모던 프로세스 API" +oldApproach: "Runtime.exec()" +modernApproach: "ProcessHandle" +summary: "ProcessHandle로 OS 프로세스를 검사하고 관리합니다." +explanation: "ProcessHandle은 PID, 프로세스 정보(명령어, 인수, 시작 시간, CPU 사용률), 부모/자식 관계, 프로세스 종료 기능을 제공합니다. 더 이상 문서화되지 않은 Process 내부를 사용할 필요가 없습니다." +whyModernWins: +- icon: "🔍" + title: "전체 정보" + desc: "PID, 명령어, 인수, 시작 시간, CPU 사용률에 접근합니다." +- icon: "🌳" + title: "프로세스 트리" + desc: "부모, 자식, 후손 프로세스를 탐색합니다." +- icon: "📊" + title: "모니터링" + desc: "onExit()가 비동기 모니터링을 위한 CompletableFuture를 반환합니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/concurrency/scoped-values.yaml b/translations/content/ko/concurrency/scoped-values.yaml new file mode 100644 index 0000000..898a421 --- /dev/null +++ b/translations/content/ko/concurrency/scoped-values.yaml @@ -0,0 +1,17 @@ +title: "스코프 값" +oldApproach: "ThreadLocal" +modernApproach: "ScopedValue" +summary: "ThreadLocal의 함정 없이 호출 스택 전반에 걸쳐 데이터를 안전하게 공유합니다." +explanation: "ScopedValue는 불변이고 상속 가능하며 스코프가 제한된 컨텍스트를 제공합니다. ThreadLocal과 달리 스코프 값은 자동으로 정리되고, 가상 스레드와 함께 작동하며, 호출자가 변경할 수 없습니다." +whyModernWins: +- icon: "🔒" + title: "불변" + desc: "호출자는 읽을 수 있지만 스코프 값을 수정할 수 없습니다." +- icon: "🧹" + title: "자동 정리" + desc: "수동 remove() 불필요 — 값은 블록 범위로 제한됩니다." +- icon: "⚡" + title: "가상 스레드 안전" + desc: "수백만 개의 가상 스레드에서 효율적으로 작동합니다." +support: + description: "JDK 25 LTS에서 확정 (JEP 506, 2025년 9월)." diff --git a/translations/content/ko/concurrency/stable-values.yaml b/translations/content/ko/concurrency/stable-values.yaml new file mode 100644 index 0000000..4ebaf01 --- /dev/null +++ b/translations/content/ko/concurrency/stable-values.yaml @@ -0,0 +1,17 @@ +title: "안정적인 값" +oldApproach: "이중 검사 잠금" +modernApproach: "StableValue" +summary: "volatile 또는 synchronized 없는 스레드 안전한 지연 초기화." +explanation: "StableValue는 내장 스레드 안전성을 갖춘 지연 초기화된 불변 값을 제공합니다. 이중 검사 잠금, volatile 필드, synchronized 블록이 필요 없습니다. JVM은 초기화 후 읽기 경로를 최적화할 수도 있습니다." +whyModernWins: +- icon: "🧹" + title: "보일러플레이트 제로" + desc: "volatile, synchronized, null 확인이 없습니다." +- icon: "⚡" + title: "JVM 최적화" + desc: "JVM이 초기화 후 값을 최적화할 수 있습니다." +- icon: "🛡️" + title: "단 한 번 보장" + desc: "공급자는 경합 상태에서도 정확히 한 번만 실행됩니다." +support: + description: "JDK 25에서 프리뷰 (JEP 502). --enable-preview가 필요합니다." diff --git a/translations/content/ko/concurrency/structured-concurrency.yaml b/translations/content/ko/concurrency/structured-concurrency.yaml new file mode 100644 index 0000000..5d9403d --- /dev/null +++ b/translations/content/ko/concurrency/structured-concurrency.yaml @@ -0,0 +1,17 @@ +title: "구조적 동시성" +oldApproach: "수동 스레드 생명주기" +modernApproach: "StructuredTaskScope" +summary: "동시 작업의 생명주기를 하나의 작업 단위로 관리합니다." +explanation: "구조적 동시성은 동시 작업 그룹을 하나의 작업으로 처리합니다. 하위 작업이 실패하면 나머지가 취소됩니다. 스코프는 스레드 누수가 없고 명확한 부모-자식 관계를 제공합니다." +whyModernWins: +- icon: "🛡️" + title: "스레드 누수 없음" + desc: "포크된 모든 작업이 스코프가 닫히기 전에 완료됩니다." +- icon: "⚡" + title: "빠른 실패" + desc: "ShutdownOnFailure는 하나가 실패하면 형제 작업을 취소합니다." +- icon: "📐" + title: "명확한 구조" + desc: "작업 생명주기가 코드의 어휘적 스코프와 일치합니다." +support: + description: "JDK 25에서 프리뷰 (다섯 번째 프리뷰, JEP 505). --enable-preview가 필요합니다." diff --git a/translations/content/ko/concurrency/thread-sleep-duration.yaml b/translations/content/ko/concurrency/thread-sleep-duration.yaml new file mode 100644 index 0000000..e8452d5 --- /dev/null +++ b/translations/content/ko/concurrency/thread-sleep-duration.yaml @@ -0,0 +1,17 @@ +title: "Duration을 사용한 Thread.sleep" +oldApproach: "밀리초" +modernApproach: "Duration" +summary: "자기 문서화 시간 값을 위해 Duration을 사용합니다." +explanation: "Thread.sleep(Duration)은 시간 단위를 명시적으로 만듭니다. 5000이 밀리초인지 마이크로초인지 더 이상 추측할 필요가 없습니다. Duration.ofSeconds, ofMillis, ofMinutes 등과 함께 작동합니다." +whyModernWins: +- icon: "📖" + title: "자기 문서화" + desc: "Duration.ofSeconds(5)는 명확합니다." +- icon: "🛡️" + title: "단위 안전" + desc: "마이크로초를 밀리초로 실수로 전달하는 일이 없습니다." +- icon: "🧩" + title: "조합 가능" + desc: "Duration 연산: plus(), multipliedBy() 등." +support: + description: "JDK 19 (2022년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/concurrency/virtual-threads.yaml b/translations/content/ko/concurrency/virtual-threads.yaml new file mode 100644 index 0000000..47c7541 --- /dev/null +++ b/translations/content/ko/concurrency/virtual-threads.yaml @@ -0,0 +1,17 @@ +title: "가상 스레드" +oldApproach: "플랫폼 스레드" +modernApproach: "가상 스레드" +summary: "무거운 OS 스레드 대신 수백만 개의 경량 가상 스레드를 생성합니다." +explanation: "가상 스레드는 OS가 아닌 JVM이 관리하는 경량 스레드입니다. 스레드 풀을 조정하지 않고 수백만 개를 만들 수 있습니다. HTTP 호출, 데이터베이스 쿼리 같은 I/O 바운드 작업에 이상적입니다." +whyModernWins: +- icon: "⚡" + title: "경량" + desc: "가상 스레드는 KB의 메모리를 사용하고, 플랫폼 스레드는 MB를 사용합니다." +- icon: "♾️" + title: "확장 가능" + desc: "수백만 개의 스레드를 생성할 수 있습니다 — 풀 크기 조정 불필요." +- icon: "🧹" + title: "단순한 모델" + desc: "비동기 코드처럼 확장되는 블로킹 코드를 작성합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/datetime/date-formatting.yaml b/translations/content/ko/datetime/date-formatting.yaml new file mode 100644 index 0000000..cbe1e30 --- /dev/null +++ b/translations/content/ko/datetime/date-formatting.yaml @@ -0,0 +1,17 @@ +title: "날짜 형식 지정" +oldApproach: "SimpleDateFormat" +modernApproach: "DateTimeFormatter" +summary: "스레드 안전하고 불변인 DateTimeFormatter로 날짜를 형식화합니다." +explanation: "DateTimeFormatter는 SimpleDateFormat과 달리 불변이고 스레드 안전합니다. 상수로 저장하고 공유할 수 있습니다. 일반적인 형식을 위한 ISO_LOCAL_DATE 같은 미리 정의된 포맷터도 사용할 수 있습니다." +whyModernWins: +- icon: "🛡️" + title: "스레드 안전" + desc: "동기화 없이 스레드 간에 포맷터를 공유합니다." +- icon: "📋" + title: "내장 형식" + desc: "표준 형식을 위한 ISO_LOCAL_DATE, ISO_INSTANT 등." +- icon: "🔒" + title: "불변" + desc: "정적 final 상수로 안전하게 저장합니다." +support: + description: "JDK 8 (2014년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/datetime/duration-and-period.yaml b/translations/content/ko/datetime/duration-and-period.yaml new file mode 100644 index 0000000..5e4035f --- /dev/null +++ b/translations/content/ko/datetime/duration-and-period.yaml @@ -0,0 +1,17 @@ +title: "Duration과 Period" +oldApproach: "밀리초 연산" +modernApproach: "Duration / Period" +summary: "타입 안전한 Duration과 Period로 시간 차이를 계산합니다." +explanation: "Duration은 시간 기반 양(시간, 분, 초)을 위한 것이고, Period는 날짜 기반 양(년, 월, 일)을 위한 것입니다. 간단한 차이에는 ChronoUnit.between()을 사용합니다. 모두 엣지 케이스를 올바르게 처리합니다." +whyModernWins: +- icon: "🎯" + title: "타입 안전" + desc: "시간에는 Duration, 날짜에는 Period — 혼동이 없습니다." +- icon: "🛡️" + title: "올바른 연산" + desc: "DST 전환, 윤년, 윤초를 올바르게 처리합니다." +- icon: "📖" + title: "가독성" + desc: "ChronoUnit.DAYS.between()은 영어처럼 읽힙니다." +support: + description: "JDK 8 (2014년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/datetime/hex-format.yaml b/translations/content/ko/datetime/hex-format.yaml new file mode 100644 index 0000000..1636711 --- /dev/null +++ b/translations/content/ko/datetime/hex-format.yaml @@ -0,0 +1,17 @@ +title: "HexFormat" +oldApproach: "수동 16진수 변환" +modernApproach: "HexFormat" +summary: "HexFormat으로 16진수 문자열과 바이트 배열을 변환합니다." +explanation: "HexFormat은 바이트, 정수, 배열에 대한 양방향 16진수 인코딩/디코딩을 제공합니다. 구분자, 접두사, 접미사, 대소문자를 설정할 수 있습니다. 더 이상 수동 형식 지정이나 파싱이 필요 없습니다." +whyModernWins: +- icon: "📐" + title: "양방향" + desc: "하나의 API로 바이트→16진수, 16진수→바이트 변환을 수행합니다." +- icon: "🔧" + title: "설정 가능" + desc: "구분자, 접두사, 접미사, 대소문자를 설정합니다." +- icon: "📦" + title: "배열 지원" + desc: "전체 바이트 배열을 한 번에 인코딩/디코딩합니다." +support: + description: "JDK 17 LTS (2021년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/datetime/instant-precision.yaml b/translations/content/ko/datetime/instant-precision.yaml new file mode 100644 index 0000000..88f384f --- /dev/null +++ b/translations/content/ko/datetime/instant-precision.yaml @@ -0,0 +1,17 @@ +title: "나노초 정밀도를 가진 Instant" +oldApproach: "밀리초" +modernApproach: "나노초" +summary: "마이크로초 또는 나노초 정밀도로 타임스탬프를 가져옵니다." +explanation: "Java 9에서 클록 해상도가 개선되어 Instant.now()가 대부분의 플랫폼에서 마이크로초 정밀도(일부에서는 나노초)를 캡처합니다. 이전의 currentTimeMillis()는 밀리초만 제공했습니다." +whyModernWins: +- icon: "🎯" + title: "더 높은 정밀도" + desc: "마이크로초/나노초 대 밀리초 타임스탬프." +- icon: "📐" + title: "타입 안전" + desc: "Instant는 정밀도를 가지고 있습니다 — 모호한 long 타입 없음." +- icon: "🌐" + title: "UTC 기반" + desc: "Instant는 항상 UTC입니다 — 타임존 혼동이 없습니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/datetime/java-time-basics.yaml b/translations/content/ko/datetime/java-time-basics.yaml new file mode 100644 index 0000000..fda058f --- /dev/null +++ b/translations/content/ko/datetime/java-time-basics.yaml @@ -0,0 +1,17 @@ +title: "java.time API 기초" +oldApproach: "Date + Calendar" +modernApproach: "java.time.*" +summary: "Date와 Calendar 대신 불변이고 명확한 날짜/시간 타입을 사용합니다." +explanation: "java.time은 LocalDate, LocalTime, LocalDateTime, Instant, ZonedDateTime을 제공합니다 — 모두 불변이고 스레드 안전합니다. 월은 1부터 시작합니다. 더 이상 Calendar.JANUARY = 0 같은 혼동이 없습니다." +whyModernWins: +- icon: "🔒" + title: "불변" + desc: "날짜/시간 값이 실수로 수정될 수 없습니다." +- icon: "📖" + title: "명확한 API" + desc: "0이 아닌 Month.JANUARY, 2가 아닌 DayOfWeek.MONDAY." +- icon: "🛡️" + title: "스레드 안전" + desc: "동기화 없이 스레드 간에 자유롭게 공유합니다." +support: + description: "JDK 8 (2014년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/datetime/math-clamp.yaml b/translations/content/ko/datetime/math-clamp.yaml new file mode 100644 index 0000000..11fb34e --- /dev/null +++ b/translations/content/ko/datetime/math-clamp.yaml @@ -0,0 +1,17 @@ +title: "Math.clamp()" +oldApproach: "중첩 min/max" +modernApproach: "Math.clamp()" +summary: "단일하고 명확한 호출로 값을 범위 내로 제한합니다." +explanation: "Math.clamp(value, min, max)는 값을 [min, max] 범위로 제한합니다. 중첩된 Math.min/Math.max보다 명확하며 int, long, float, double에서 사용 가능합니다." +whyModernWins: +- icon: "📖" + title: "자기 문서화" + desc: "clamp(value, min, max)는 명확합니다." +- icon: "🛡️" + title: "오류 감소" + desc: "더 이상 min/max 순서를 실수로 바꾸지 않습니다." +- icon: "🎯" + title: "모든 숫자 타입" + desc: "int, long, float, double에서 작동합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/ejb-timer-vs-jakarta-scheduler.yaml b/translations/content/ko/enterprise/ejb-timer-vs-jakarta-scheduler.yaml new file mode 100644 index 0000000..d566265 --- /dev/null +++ b/translations/content/ko/enterprise/ejb-timer-vs-jakarta-scheduler.yaml @@ -0,0 +1,17 @@ +title: "EJB 타이머 대 Jakarta 스케줄러" +oldApproach: "EJB TimerService" +modernApproach: "ManagedScheduledExecutorService" +summary: "ManagedScheduledExecutorService로 무거운 EJB 타이머를 대체합니다." +explanation: "EJB 타이머는 @Timeout 콜백과 ScheduleExpression을 사용하는 @Stateless 또는 @Singleton 빈이 필요합니다. ManagedScheduledExecutorService는 컨테이너 관리 스레드로 표준 ScheduledExecutorService API를 제공합니다." +whyModernWins: +- icon: "🪶" + title: "보일러플레이트 감소" + desc: "@Timeout 콜백이나 ScheduleExpression이 없습니다 — 표준 ScheduledExecutorService API를 사용합니다." +- icon: "🧪" + title: "더 나은 테스트 가능성" + desc: "일반 메서드와 실행자 목은 EJB 컨테이너 없이 단위 테스트를 간단하게 만듭니다." +- icon: "☁️" + title: "클라우드 네이티브 친화적" + desc: "관리된 실행자는 컨테이너 생명주기와 통합되고 경량 런타임에서 작동합니다." +support: + description: "Jakarta EE 10 / Concurrency 3.0 이후 사용 가능" diff --git a/translations/content/ko/enterprise/ejb-vs-cdi.yaml b/translations/content/ko/enterprise/ejb-vs-cdi.yaml new file mode 100644 index 0000000..c066307 --- /dev/null +++ b/translations/content/ko/enterprise/ejb-vs-cdi.yaml @@ -0,0 +1,17 @@ +title: "EJB 대 CDI" +oldApproach: "EJB" +modernApproach: "CDI 빈" +summary: "의존성 주입을 위해 무거운 EJB를 경량 CDI 빈으로 대체합니다." +explanation: "CDI(컨텍스트와 의존성 주입)는 EJB와 동일한 의존성 주입을 제공하지만 EJB 특정 인터페이스나 디스크립터가 있는 무거운 컨테이너 없이 작동합니다." +whyModernWins: +- icon: "🪶" + title: "경량" + desc: "CDI 빈은 EJB 특정 인터페이스나 디스크립터가 없는 일반 Java 클래스입니다." +- icon: "💉" + title: "통일된 주입" + desc: "@Inject는 모든 관리 빈, JAX-RS 리소스, Jakarta EE 컴포넌트에서 작동합니다." +- icon: "🧪" + title: "쉬운 단위 테스트" + desc: "EJB 프록시 오버헤드 없는 일반 클래스는 인스턴스화하고 목으로 대체하기 간단합니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/jdbc-resultset-vs-jpa-criteria.yaml b/translations/content/ko/enterprise/jdbc-resultset-vs-jpa-criteria.yaml new file mode 100644 index 0000000..a6a2c58 --- /dev/null +++ b/translations/content/ko/enterprise/jdbc-resultset-vs-jpa-criteria.yaml @@ -0,0 +1,17 @@ +title: "JDBC ResultSet 매핑 대 JPA Criteria API" +oldApproach: "JDBC ResultSet" +modernApproach: "JPA Criteria API" +summary: "수동 JDBC ResultSet 매핑을 JPA의 타입 안전 Criteria API로 대체합니다." +explanation: "원시 JDBC는 SQL 문자열 구축, 인덱스로 매개변수 설정, 열별 ResultSet에서 객체로의 수동 매핑이 필요합니다. JPA Criteria API는 타입 안전 쿼리 구축과 자동 엔티티 매핑을 제공합니다." +whyModernWins: +- icon: "🔒" + title: "타입 안전 쿼리" + desc: "Criteria 빌더는 컴파일 시점에 필드 이름 및 타입 불일치를 잡습니다." +- icon: "🗺️" + title: "자동 매핑" + desc: "JPA는 결과 행을 엔티티 객체에 매핑합니다 — 열별 수동 추출이 없습니다." +- icon: "🧩" + title: "조합 가능한 조건자" + desc: "동적 where 절이 and(), or()와 재사용 가능한 Predicate 객체로 깔끔하게 구축됩니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/jdbc-vs-jooq.yaml b/translations/content/ko/enterprise/jdbc-vs-jooq.yaml new file mode 100644 index 0000000..37d3921 --- /dev/null +++ b/translations/content/ko/enterprise/jdbc-vs-jooq.yaml @@ -0,0 +1,17 @@ +title: "JDBC 대 jOOQ" +oldApproach: "원시 JDBC" +modernApproach: "jOOQ SQL DSL" +summary: "원시 JDBC 문자열 기반 SQL을 jOOQ의 타입 안전하고 유창한 SQL DSL로 대체합니다." +explanation: "jOOQ(Java Object Oriented Querying)는 데이터베이스에서 Java 코드를 생성합니다. 모든 테이블, 열, 함수가 타입 안전 Java 상수가 되어 SQL 오타가 런타임 오류가 아닌 컴파일러 오류가 됩니다." +whyModernWins: +- icon: "🔒" + title: "타입 안전 열" + desc: "열 이름은 생성된 Java 상수입니다 — 오타와 타입 불일치는 런타임 실패 대신 컴파일러 오류가 됩니다." +- icon: "📖" + title: "SQL 유창성" + desc: "jOOQ DSL은 SQL 구문과 유사하여 복잡한 JOIN, 서브쿼리, CTE가 읽기 쉽게 유지됩니다." +- icon: "🛡️" + title: "설계상 인젝션 없음" + desc: "매개변수는 항상 안전하게 바인딩됩니다 — 문자열 연결이 없으면 SQL 인젝션 위험도 없습니다." +support: + description: "jOOQ 오픈소스 에디션은 모든 주요 오픈소스 데이터베이스를 지원합니다." diff --git a/translations/content/ko/enterprise/jdbc-vs-jpa.yaml b/translations/content/ko/enterprise/jdbc-vs-jpa.yaml new file mode 100644 index 0000000..32eeb1d --- /dev/null +++ b/translations/content/ko/enterprise/jdbc-vs-jpa.yaml @@ -0,0 +1,17 @@ +title: "JDBC 대 JPA" +oldApproach: "JDBC" +modernApproach: "JPA EntityManager" +summary: "장황한 JDBC 보일러플레이트를 JPA의 객체-관계 매핑으로 대체합니다." +explanation: "JPA(Jakarta Persistence API)는 Java 객체를 데이터베이스 행에 매핑하여 수동 ResultSet-to-object 변환을 제거합니다. JPQL 또는 Criteria API로 타입 안전 쿼리를 제공합니다." +whyModernWins: +- icon: "🗺️" + title: "객체 매핑" + desc: "엔티티는 일반 어노테이션된 클래스입니다 — 수동 ResultSet-to-object 변환이 없습니다." +- icon: "🔒" + title: "타입 안전 쿼리" + desc: "JPQL은 원시 테이블과 열 문자열이 아닌 엔티티 타입과 필드에서 작동합니다." +- icon: "⚡" + title: "내장 캐싱" + desc: "1차 및 2차 캐시가 자동으로 데이터베이스 왕복을 줄입니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/jndi-lookup-vs-cdi-injection.yaml b/translations/content/ko/enterprise/jndi-lookup-vs-cdi-injection.yaml new file mode 100644 index 0000000..0c494d1 --- /dev/null +++ b/translations/content/ko/enterprise/jndi-lookup-vs-cdi-injection.yaml @@ -0,0 +1,17 @@ +title: "JNDI 조회 대 CDI 주입" +oldApproach: "JNDI 조회" +modernApproach: "CDI @Inject" +summary: "취약한 JNDI 문자열 조회를 타입 안전 CDI 주입으로 대체합니다." +explanation: "전통적인 JNDI 패턴은 문자열 기반 리소스 조회를 강제하여 타입 불일치가 런타임까지 잡히지 않습니다. CDI @Inject는 컨테이너가 의존성을 해석하도록 하여 타입 불일치를 배포 시점에 잡습니다." +whyModernWins: +- icon: "🔒" + title: "타입 안전 연결" + desc: "주입 오류는 런타임 문자열 조회가 아닌 배포 시점에 잡힙니다." +- icon: "🗑️" + title: "보일러플레이트 없음" + desc: "InitialContext 생성, JNDI 이름 문자열, NamingException 처리를 제거합니다." +- icon: "🧪" + title: "테스트 가능" + desc: "의존성은 주입된 필드로, 단위 테스트에서 목으로 쉽게 대체할 수 있습니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/jpa-vs-jakarta-data.yaml b/translations/content/ko/enterprise/jpa-vs-jakarta-data.yaml new file mode 100644 index 0000000..4dec613 --- /dev/null +++ b/translations/content/ko/enterprise/jpa-vs-jakarta-data.yaml @@ -0,0 +1,17 @@ +title: "JPA 대 Jakarta Data" +oldApproach: "JPA EntityManager" +modernApproach: "Jakarta Data 리포지토리" +summary: "리포지토리 인터페이스를 선언하고 Jakarta Data가 DAO 구현을 생성하도록 합니다." +explanation: "Jakarta Data(Jakarta EE 11)는 데이터 접근을 순수 인터페이스로 만듭니다. 메서드 이름이 쿼리가 되고, 컨테이너가 구현을 생성하며, 수동 EntityManager 코드가 필요 없습니다." +whyModernWins: +- icon: "��" + title: "보일러플레이트 제로" + desc: "인터페이스를 선언합니다; 컨테이너가 배포 시점에 전체 DAO 구현을 생성합니다." +- icon: "🔍" + title: "파생 쿼리" + desc: "findByNameAndStatus 같은 메서드 이름이 자동으로 파싱됩니다 — JPQL이나 SQL이 필요 없습니다." +- icon: "🔌" + title: "이식 가능" + desc: "모든 Jakarta EE 11 호환 런타임이 벤더 종속성 없이 리포지토리 구현을 제공합니다." +support: + description: "Jakarta EE 11 / Java 21 (2024) 이후 사용 가능" diff --git a/translations/content/ko/enterprise/jsf-managed-bean-vs-cdi-named.yaml b/translations/content/ko/enterprise/jsf-managed-bean-vs-cdi-named.yaml new file mode 100644 index 0000000..f6c8637 --- /dev/null +++ b/translations/content/ko/enterprise/jsf-managed-bean-vs-cdi-named.yaml @@ -0,0 +1,17 @@ +title: "JSF 관리 빈 대 CDI Named 빈" +oldApproach: "@ManagedBean" +modernApproach: "@Named + CDI" +summary: "더 이상 사용되지 않는 JSF @ManagedBean을 통일된 의존성 주입 모델을 위한 CDI @Named로 대체합니다." +explanation: "JSF의 @ManagedBean과 @ManagedProperty는 Jakarta Faces 4.0에서 더 이상 사용되지 않으며 Jakarta EE 10에서 제거됩니다. CDI @Named는 JSF 뷰에서 빈을 노출하고 전체 CDI 에코시스템에 접근하는 표준 방법입니다." +whyModernWins: +- icon: "🔗" + title: "통일된 모델" + desc: "하나의 CDI 컨테이너가 모든 빈을 관리합니다 — JSF, REST, 서비스 레이어가 동일한 주입을 공유합니다." +- icon: "🗑️" + title: "보일러플레이트 감소" + desc: "@Inject가 @ManagedProperty와 필요한 세터 메서드를 대체합니다." +- icon: "🔮" + title: "미래 지향적" + desc: "@ManagedBean은 Jakarta EE 10에서 제거됩니다; @Named가 지원되는 대체입니다." +support: + description: "CDI @Named는 Java EE 6 이후 사용 가능; @ManagedBean은 Jakarta EE 10에서 제거됨" diff --git a/translations/content/ko/enterprise/manual-transaction-vs-declarative.yaml b/translations/content/ko/enterprise/manual-transaction-vs-declarative.yaml new file mode 100644 index 0000000..02718a0 --- /dev/null +++ b/translations/content/ko/enterprise/manual-transaction-vs-declarative.yaml @@ -0,0 +1,17 @@ +title: "수동 JPA 트랜잭션 대 선언적 @Transactional" +oldApproach: "수동 트랜잭션" +modernApproach: "@Transactional" +summary: "장황한 begin/commit/rollback 블록을 단일 @Transactional 어노테이션으로 대체합니다." +explanation: "수동 트랜잭션 관리는 명시적 begin(), commit(), rollback() 호출과 오류 처리가 필요합니다. @Transactional은 컨테이너가 경계를 관리하도록 하여 비즈니스 코드가 일관성에 집중할 수 있게 합니다." +whyModernWins: +- icon: "🗑️" + title: "보일러플레이트 없음" + desc: "하나의 어노테이션이 반복적인 begin/commit/rollback try-catch 블록을 대체합니다." +- icon: "🛡️" + title: "더 안전한 롤백" + desc: "컨테이너는 확인되지 않은 예외에서 롤백을 보장합니다 — catch 블록을 잊을 위험이 없습니다." +- icon: "📐" + title: "선언적 제어" + desc: "전파, 격리, 롤백 규칙이 어노테이션 속성으로 표현됩니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/mdb-vs-reactive-messaging.yaml b/translations/content/ko/enterprise/mdb-vs-reactive-messaging.yaml new file mode 100644 index 0000000..73a8a61 --- /dev/null +++ b/translations/content/ko/enterprise/mdb-vs-reactive-messaging.yaml @@ -0,0 +1,17 @@ +title: "Message-Driven Bean 대 Reactive Messaging" +oldApproach: "Message-Driven Bean" +modernApproach: "Reactive Messaging" +summary: "JMS Message-Driven Bean을 MicroProfile Reactive Messaging으로 대체합니다." +explanation: "Message-Driven Bean은 MessageListener 구현, 활성화 설정 구성, 무거운 EJB 컨테이너가 필요합니다. MicroProfile Reactive Messaging은 어노테이션 기반 메시지 소비를 단순화합니다." +whyModernWins: +- icon: "🪶" + title: "최소 코드" + desc: "단일 @Incoming 메서드가 MDB 클래스, MessageListener 인터페이스, 활성화 설정을 대체합니다." +- icon: "🔌" + title: "브로커 무관" + desc: "애플리케이션 코드를 변경하지 않고 설정으로 Kafka, AMQP, JMS 커넥터를 교체합니다." +- icon: "☁️" + title: "클라우드 네이티브 적합" + desc: "리액티브 스트림 백프레셔와 경량 런타임은 컨테이너화된 배포에 이상적입니다." +support: + description: "MicroProfile 4.0 / SmallRye Reactive Messaging 이후 사용 가능" diff --git a/translations/content/ko/enterprise/servlet-vs-jaxrs.yaml b/translations/content/ko/enterprise/servlet-vs-jaxrs.yaml new file mode 100644 index 0000000..e7c9ba1 --- /dev/null +++ b/translations/content/ko/enterprise/servlet-vs-jaxrs.yaml @@ -0,0 +1,17 @@ +title: "Servlet 대 JAX-RS" +oldApproach: "HttpServlet" +modernApproach: "JAX-RS 리소스" +summary: "장황한 HttpServlet 보일러플레이트를 선언적 JAX-RS 리소스 클래스로 대체합니다." +explanation: "JAX-RS(Jakarta RESTful Web Services)는 어노테이션으로 REST 엔드포인트를 노출할 수 있게 합니다. HTTP 메서드 체크, 경로 파싱, 요청/응답 마샬링이 프레임워크에 의해 처리됩니다." +whyModernWins: +- icon: "📐" + title: "선언적 라우팅" + desc: "어노테이션이 명령형 if/else 디스패치 대신 HTTP 메서드, 경로, 콘텐츠 타입을 정의합니다." +- icon: "🔄" + title: "자동 마샬링" + desc: "POJO를 직접 반환합니다; 런타임이 @Produces에 따라 JSON이나 XML로 직렬화합니다." +- icon: "🧪" + title: "더 쉬운 테스트" + desc: "리소스 클래스는 서블릿 컨테이너 없이 테스트 가능한 일반 Java 객체입니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml b/translations/content/ko/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml new file mode 100644 index 0000000..534fbdd --- /dev/null +++ b/translations/content/ko/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml @@ -0,0 +1,17 @@ +title: "Singleton EJB 대 CDI @ApplicationScoped" +oldApproach: "@Singleton EJB" +modernApproach: "@ApplicationScoped CDI" +summary: "더 간단한 공유 상태 관리를 위해 Singleton EJB를 CDI @ApplicationScoped 빈으로 대체합니다." +explanation: "Singleton EJB는 동시성 관리(@Lock, @ConcurrencyManagement)를 번들로 제공합니다. CDI @ApplicationScoped는 선택한 동시성 메커니즘과 결합된 간단한 대안입니다." +whyModernWins: +- icon: "🪶" + title: "적은 어노테이션 노이즈" + desc: "@ConcurrencyManagement, @Lock, @Startup이 없습니다 — 단일 @ApplicationScoped 어노테이션만." +- icon: "🔧" + title: "유연한 동시성" + desc: "정확히 필요한 스레드 안전성을 위해 java.util.concurrent 잠금이나 volatile을 사용합니다." +- icon: "🧪" + title: "쉬운 테스트" + desc: "일반 CDI 빈은 EJB 컨테이너 없이 테스트에서 직접 인스턴스화할 수 있습니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/soap-vs-jakarta-rest.yaml b/translations/content/ko/enterprise/soap-vs-jakarta-rest.yaml new file mode 100644 index 0000000..c25872f --- /dev/null +++ b/translations/content/ko/enterprise/soap-vs-jakarta-rest.yaml @@ -0,0 +1,17 @@ +title: "SOAP 웹 서비스 대 Jakarta REST" +oldApproach: "JAX-WS / SOAP" +modernApproach: "Jakarta REST / JSON" +summary: "무거운 SOAP/WSDL 엔드포인트를 깔끔한 Jakarta REST 리소스로 대체합니다." +explanation: "SOAP 기반 웹 서비스는 WSDL 계약, XML 마샬링, 생성된 클라이언트 스텁에 의존합니다. Jakarta REST는 표준 HTTP 메서드와 JSON 페이로드로 이를 대체합니다." +whyModernWins: +- icon: "🪶" + title: "더 가벼운 페이로드" + desc: "JSON은 SOAP XML 봉투보다 더 간결하여 대역폭과 파싱 오버헤드를 줄입니다." +- icon: "📐" + title: "단순한 어노테이션" + desc: "@GET, @Path, @Produces가 WSDL, @WebService, @WebMethod 형식을 대체합니다." +- icon: "🔌" + title: "마이크로서비스 준비" + desc: "REST/JSON은 클라우드 네이티브 아키텍처에서 서비스 간 통신의 표준입니다." +support: + description: "Jakarta EE 8 / Java 11 이후 널리 사용 가능" diff --git a/translations/content/ko/enterprise/spring-api-versioning.yaml b/translations/content/ko/enterprise/spring-api-versioning.yaml new file mode 100644 index 0000000..7cf5b0b --- /dev/null +++ b/translations/content/ko/enterprise/spring-api-versioning.yaml @@ -0,0 +1,17 @@ +title: "Spring Framework 7 API 버전 관리" +oldApproach: "수동 URL 경로 버전 관리" +modernApproach: "네이티브 API 버전 관리" +summary: "중복된 버전 접두사 컨트롤러를 Spring Framework 7의 네이티브 API 버전 관리로 대체합니다." +explanation: "Spring Framework 7 이전에는 API 버전 관리를 위해 별도의 컨트롤러 클래스나 복잡한 수동 라우팅이 필요했습니다. Spring 7의 네이티브 API 버전 관리는 이를 단순화합니다." +whyModernWins: +- icon: "🗂️" + title: "컨트롤러 중복 없음" + desc: "모든 버전이 하나의 컨트롤러 클래스에 있습니다; 개별 핸들러 메서드만 버전 속성을 가집니다." +- icon: "⚙️" + title: "중앙화된 버전 전략" + desc: "단일 configureApiVersioning 호출로 헤더에서 URL이나 쿼리 파라미터 버전 관리로 전환합니다." +- icon: "📈" + title: "점진적 진화" + desc: "관련 없는 엔드포인트나 새 컨트롤러 파일을 건드리지 않고 하나의 메서드에 새 버전을 추가합니다." +support: + description: "Spring Framework 7.0 (Java 17+ 필요) 이후 사용 가능" diff --git a/translations/content/ko/enterprise/spring-null-safety-jspecify.yaml b/translations/content/ko/enterprise/spring-null-safety-jspecify.yaml new file mode 100644 index 0000000..8a8483c --- /dev/null +++ b/translations/content/ko/enterprise/spring-null-safety-jspecify.yaml @@ -0,0 +1,17 @@ +title: "JSpecify를 사용한 Spring Null 안전성" +oldApproach: "Spring @NonNull/@Nullable" +modernApproach: "JSpecify @NullMarked" +summary: "Spring 7은 JSpecify 어노테이션을 채택하여 null이 아닌 것을 기본으로 만들고 어노테이션을 줄입니다." +explanation: "Spring 5와 6은 org.springframework.lang 패키지에 자체 null 안전성 어노테이션을 도입했습니다. Spring 7은 JSpecify 어노테이션으로 마이그레이션하여 에코시스템 전반의 null 의미론을 표준화합니다." +whyModernWins: +- icon: "✂️" + title: "기본적으로 non-null" + desc: "@NullMarked는 어노테이션 없는 모든 타입을 non-null로 만들어 nullable 예외만 어노테이션이 필요합니다." +- icon: "🌐" + title: "에코시스템 표준" + desc: "JSpecify 어노테이션은 NullAway, Error Prone, IDE가 인식하는 크로스 프레임워크 표준입니다." +- icon: "🔍" + title: "더 풍부한 도구" + desc: "모던 정적 분석기는 JSpecify의 null 모델을 이해하고 컴파일 시점에 위반을 보고합니다." +support: + description: "Spring Framework 7.0 (Java 17+ 필요) 이후 사용 가능" diff --git a/translations/content/ko/enterprise/spring-xml-config-vs-annotations.yaml b/translations/content/ko/enterprise/spring-xml-config-vs-annotations.yaml new file mode 100644 index 0000000..32cbed8 --- /dev/null +++ b/translations/content/ko/enterprise/spring-xml-config-vs-annotations.yaml @@ -0,0 +1,17 @@ +title: "Spring XML 빈 설정 대 어노테이션 기반" +oldApproach: "XML 빈 정의" +modernApproach: "어노테이션 기반 빈" +summary: "장황한 Spring XML 빈 정의를 간결한 어노테이션 기반 설정으로 대체합니다." +explanation: "전통적인 Spring 애플리케이션은 XML 설정 파일을 통해 빈을 연결했습니다. 현대 Spring Boot 애플리케이션은 컴포넌트 스캔, @Component/@Service/@Repository 어노테이션, 자동 설정을 사용합니다." +whyModernWins: +- icon: "🚫" + title: "XML 없음" + desc: "@SpringBootApplication이 컴포넌트 스캔과 자동 설정을 트리거하여 모든 XML 연결 파일을 제거합니다." +- icon: "💉" + title: "생성자 주입" + desc: "Spring이 생성자를 통해 자동으로 의존성을 주입하여 빈을 테스트하고 이해하기 쉽게 만듭니다." +- icon: "⚡" + title: "자동 설정" + desc: "Spring Boot가 클래스패스에서 DataSource, JPA, 기타 인프라를 보일러플레이트 없이 설정합니다." +support: + description: "Spring Boot 1.0 (2014년 4월) 이후 널리 사용 가능; Spring Boot 3 권장" diff --git a/translations/content/ko/errors/helpful-npe.yaml b/translations/content/ko/errors/helpful-npe.yaml new file mode 100644 index 0000000..3b5aab3 --- /dev/null +++ b/translations/content/ko/errors/helpful-npe.yaml @@ -0,0 +1,17 @@ +title: "유용한 NullPointerException" +oldApproach: "불분명한 NPE" +modernApproach: "상세한 NPE" +summary: "JVM이 어떤 변수가 null이었는지 정확히 알려줍니다." +explanation: "유용한 NPE는 어떤 표현식이 null이었고 어떤 연산이 실패했는지 설명합니다. Java 14부터 기본적으로 활성화되어 있습니다 — 코드 변경 없이 JDK를 업그레이드하기만 하면 됩니다." +whyModernWins: +- icon: "🔍" + title: "정확한 변수" + desc: "메시지가 체인에서 null인 변수를 지목합니다." +- icon: "⚡" + title: "더 빠른 디버깅" + desc: "5개의 체이닝된 호출 중 어느 것이 null인지 더 이상 추측하지 않아도 됩니다." +- icon: "🆓" + title: "무료 업그레이드" + desc: "코드 변경 없이 JDK 14 이상에서 실행하기만 하면 됩니다." +support: + description: "JDK 14 (2020년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/errors/multi-catch.yaml b/translations/content/ko/errors/multi-catch.yaml new file mode 100644 index 0000000..68efe02 --- /dev/null +++ b/translations/content/ko/errors/multi-catch.yaml @@ -0,0 +1,17 @@ +title: "다중 캐치 예외 처리" +oldApproach: "별도의 캐치 블록" +modernApproach: "다중 캐치" +summary: "단일 catch 블록에서 여러 예외 타입을 처리합니다." +explanation: "다중 캐치는 동일한 코드로 여러 예외 타입을 처리합니다. 예외 변수는 사실상 final이므로 래핑 없이 다시 던질 수 있습니다." +whyModernWins: +- icon: "📏" + title: "DRY 원칙" + desc: "동일한 처리 로직을 세 번 대신 한 번만 작성합니다." +- icon: "🔄" + title: "다시 던지기 가능" + desc: "잡힌 예외를 정확한 타입으로 다시 던질 수 있습니다." +- icon: "📖" + title: "스캔 용이" + desc: "처리되는 모든 타입이 한 곳에 표시됩니다." +support: + description: "JDK 7 (2011년 7월) 이후 널리 사용 가능" diff --git a/translations/content/ko/errors/null-in-switch.yaml b/translations/content/ko/errors/null-in-switch.yaml new file mode 100644 index 0000000..f66c492 --- /dev/null +++ b/translations/content/ko/errors/null-in-switch.yaml @@ -0,0 +1,17 @@ +title: "switch의 null 케이스" +oldApproach: "switch 전 null 가드" +modernApproach: "case null" +summary: "별도의 null 가드 없이 switch 케이스로 null을 직접 처리합니다." +explanation: "패턴 매칭 switch는 null을 케이스 레이블로 매칭할 수 있습니다. 이를 통해 switch 전에 null 확인이 필요 없어지고 null 처리가 명시적이고 가시적이 됩니다." +whyModernWins: +- icon: "🎯" + title: "명시적" + desc: "null 처리가 switch에 바로 표시됩니다." +- icon: "🛡️" + title: "NPE 없음" + desc: "null 값으로 switch해도 NullPointerException이 발생하지 않습니다." +- icon: "📐" + title: "일체형" + desc: "null을 포함한 모든 케이스가 단일 switch 표현식에 있습니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/errors/optional-chaining.yaml b/translations/content/ko/errors/optional-chaining.yaml new file mode 100644 index 0000000..a941c00 --- /dev/null +++ b/translations/content/ko/errors/optional-chaining.yaml @@ -0,0 +1,17 @@ +title: "Optional 체이닝" +oldApproach: "중첩 null 확인" +modernApproach: "Optional 파이프라인" +summary: "중첩된 null 확인을 Optional 파이프라인으로 대체합니다." +explanation: "Optional.map()은 nullable 값을 체이닝하면서 첫 번째 null에서 단락 평가합니다. orElse()는 기본값을 제공합니다. 이를 통해 피라미드형 null 확인을 제거합니다." +whyModernWins: +- icon: "🔗" + title: "체이닝 가능" + desc: "각 .map() 단계가 null을 투명하게 처리합니다." +- icon: "📖" + title: "선형 흐름" + desc: "중첩된 if 블록 대신 왼쪽에서 오른쪽으로 읽습니다." +- icon: "🛡️" + title: "NPE 방지" + desc: "각 단계에서 null이 처리됩니다 — 충돌 가능성 없음." +support: + description: "JDK 8 이상에서 사용 가능 (9 이상에서 개선)" diff --git a/translations/content/ko/errors/optional-orelsethrow.yaml b/translations/content/ko/errors/optional-orelsethrow.yaml new file mode 100644 index 0000000..2afe99f --- /dev/null +++ b/translations/content/ko/errors/optional-orelsethrow.yaml @@ -0,0 +1,17 @@ +title: "인수 없는 Optional.orElseThrow()" +oldApproach: "get() 또는 orElseThrow(공급자)" +modernApproach: "orElseThrow()" +summary: "get()의 명확하고 의도를 드러내는 대안으로 Optional.orElseThrow()를 사용합니다." +explanation: "Optional.get()은 실패 가능성을 숨기기 때문에 코드 냄새로 널리 인식됩니다. Java 10에 추가된 인수 없는 orElseThrow()는 동일한 일을 하지만 의도를 명시합니다: 개발자는 값을 기대하며 없으면 예외를 원합니다." +whyModernWins: +- icon: "📖" + title: "자기 문서화" + desc: "orElseThrow()는 값이 없는 경우가 예상치 못한 상황임을 명확히 알립니다." +- icon: "🔒" + title: "get() 회피" + desc: "정적 분석 도구는 get()을 위험하다고 표시합니다; orElseThrow()는 관용적입니다." +- icon: "⚡" + title: "보일러플레이트 감소" + desc: "기본 NoSuchElementException을 위한 공급자를 전달할 필요가 없습니다." +support: + description: "JDK 10 (2018년 3월) 이후 사용 가능." diff --git a/translations/content/ko/errors/record-based-errors.yaml b/translations/content/ko/errors/record-based-errors.yaml new file mode 100644 index 0000000..c9ac673 --- /dev/null +++ b/translations/content/ko/errors/record-based-errors.yaml @@ -0,0 +1,17 @@ +title: "레코드 기반 오류 응답" +oldApproach: "맵 또는 장황한 클래스" +modernApproach: "오류 레코드" +summary: "간결하고 불변인 오류 응답 타입에 레코드를 사용합니다." +explanation: "레코드는 오류 응답에 완벽합니다 — 불변이고, 비교를 위한 내장 equals/hashCode를 가지며, 로깅을 위한 toString도 있습니다. 커스텀 생성자로 유효성 검사나 기본값을 추가할 수 있습니다." +whyModernWins: +- icon: "📏" + title: "간결함" + desc: "오류 타입을 30줄 대신 3줄로 정의합니다." +- icon: "🔒" + title: "불변" + desc: "생성 후 오류 데이터를 실수로 수정할 수 없습니다." +- icon: "📋" + title: "자동 toString" + desc: "로깅에 완벽 — 모든 필드를 자동으로 표시합니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/errors/require-nonnull-else.yaml b/translations/content/ko/errors/require-nonnull-else.yaml new file mode 100644 index 0000000..e073ef2 --- /dev/null +++ b/translations/content/ko/errors/require-nonnull-else.yaml @@ -0,0 +1,17 @@ +title: "Objects.requireNonNullElse()" +oldApproach: "삼항 연산자 null 확인" +modernApproach: "requireNonNullElse()" +summary: "삼항 연산자 없이 명확한 기본값으로 null이 아닌 값을 가져옵니다." +explanation: "requireNonNullElse는 첫 번째 인수가 null이 아니면 그것을, 그렇지 않으면 두 번째를 반환합니다. 기본값 자체도 null이 될 수 없으며 — 둘 다 null이면 NPE를 던져 버그를 조기에 잡습니다." +whyModernWins: +- icon: "📖" + title: "명확한 의도" + desc: "메서드 이름이 정확히 무엇을 하는지 설명합니다." +- icon: "🛡️" + title: "null 안전 기본값" + desc: "기본값도 null 여부를 확인합니다." +- icon: "📏" + title: "가독성" + desc: "단순한 null-또는-기본값 로직에서 삼항 연산자보다 낫습니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/deserialization-filters.yaml b/translations/content/ko/io/deserialization-filters.yaml new file mode 100644 index 0000000..8ba64e0 --- /dev/null +++ b/translations/content/ko/io/deserialization-filters.yaml @@ -0,0 +1,17 @@ +title: "역직렬화 필터" +oldApproach: "모든 것 허용" +modernApproach: "ObjectInputFilter" +summary: "공격을 방지하기 위해 역직렬화 가능한 클래스를 제한합니다." +explanation: "ObjectInputFilter를 통해 클래스를 허용 목록/거부 목록에 추가하고, 객체 그래프 깊이, 배열 크기, 참조 횟수를 제한할 수 있습니다. 외부 라이브러리 없이 역직렬화 취약점을 방어합니다." +whyModernWins: +- icon: "🛡️" + title: "보안" + desc: "예상치 못한/악성 클래스의 역직렬화를 방지합니다." +- icon: "📐" + title: "세밀한 제어" + desc: "깊이, 배열 크기, 참조 횟수, 클래스 패턴을 제어합니다." +- icon: "🏗️" + title: "JVM 전체" + desc: "JVM의 모든 역직렬화에 대한 전역 필터를 설정합니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/file-memory-mapping.yaml b/translations/content/ko/io/file-memory-mapping.yaml new file mode 100644 index 0000000..9390a60 --- /dev/null +++ b/translations/content/ko/io/file-memory-mapping.yaml @@ -0,0 +1,17 @@ +title: "파일 메모리 매핑" +oldApproach: "MappedByteBuffer" +modernApproach: "Arena를 사용한 MemorySegment" +summary: "MemorySegment를 사용하여 결정적 정리로 2GB보다 큰 파일을 매핑합니다." +explanation: "Foreign Function & Memory API(JEP 454)는 안전하고 효율적인 메모리 접근을 위한 MemorySegment를 도입합니다. MappedByteBuffer와 달리 MemorySegment는 2GB(Integer.MAX_VALUE) 이상의 파일을 지원하고, Arena를 통한 결정적 정리를 제공하며, 현대 하드웨어에서 더 나은 성능을 발휘합니다." +whyModernWins: +- icon: "📏" + title: "크기 제한 없음" + desc: "우회 방법 없이 2GB보다 큰 파일을 매핑합니다." +- icon: "🔒" + title: "결정적 정리" + desc: "Arena는 GC 시점이 아닌 스코프 종료 시점에 메모리를 해제합니다." +- icon: "⚡" + title: "더 나은 성능" + desc: "현대 메모리 모델 및 하드웨어와 정렬됩니다." +support: + description: "JDK 22 (2024년 3월) 이후 사용 가능" diff --git a/translations/content/ko/io/files-mismatch.yaml b/translations/content/ko/io/files-mismatch.yaml new file mode 100644 index 0000000..7fd2c5b --- /dev/null +++ b/translations/content/ko/io/files-mismatch.yaml @@ -0,0 +1,17 @@ +title: "Files.mismatch()" +oldApproach: "수동 바이트 비교" +modernApproach: "Files.mismatch()" +summary: "파일을 메모리에 로드하지 않고 효율적으로 두 파일을 비교합니다." +explanation: "Files.mismatch()는 첫 번째로 다른 바이트의 위치를 반환하거나, 파일이 동일하면 -1을 반환합니다. 지연 방식으로 읽고 첫 번째 차이에서 단락 평가합니다." +whyModernWins: +- icon: "⚡" + title: "메모리 효율적" + desc: "전체 파일을 바이트 배열에 로드하지 않습니다." +- icon: "🎯" + title: "차이 지점 정확" + desc: "첫 번째 불일치의 정확한 바이트 위치를 반환합니다." +- icon: "📏" + title: "한 번의 호출" + desc: "수동 바이트 배열 비교 로직이 필요 없습니다." +support: + description: "JDK 12 (2019년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/http-client.yaml b/translations/content/ko/io/http-client.yaml new file mode 100644 index 0000000..b7d9168 --- /dev/null +++ b/translations/content/ko/io/http-client.yaml @@ -0,0 +1,17 @@ +title: "모던 HTTP 클라이언트" +oldApproach: "HttpURLConnection" +modernApproach: "HttpClient" +summary: "깔끔하고 모던한 HTTP 요청을 위한 내장 HttpClient를 사용합니다." +explanation: "HttpClient는 HTTP/1.1과 HTTP/2, 비동기 요청, WebSocket, 커스텀 실행자, 연결 풀링을 지원합니다. 더 이상 URLConnection을 캐스팅하거나 InputStream을 수동으로 읽을 필요가 없습니다." +whyModernWins: +- icon: "📐" + title: "빌더 API" + desc: "요청, 헤더, 타임아웃을 위한 유창한 빌더." +- icon: "🔄" + title: "HTTP/2 지원" + desc: "멀티플렉싱과 서버 푸시를 갖춘 내장 HTTP/2." +- icon: "⚡" + title: "비동기 준비" + desc: "sendAsync()가 CompletableFuture를 반환합니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/inputstream-transferto.yaml b/translations/content/ko/io/inputstream-transferto.yaml new file mode 100644 index 0000000..5fb2cea --- /dev/null +++ b/translations/content/ko/io/inputstream-transferto.yaml @@ -0,0 +1,17 @@ +title: "InputStream.transferTo()" +oldApproach: "수동 복사 루프" +modernApproach: "transferTo()" +summary: "한 번의 호출로 InputStream을 OutputStream에 복사합니다." +explanation: "transferTo()는 입력 스트림의 모든 바이트를 읽어 출력 스트림에 씁니다. 버퍼 관리나 루프가 필요 없습니다. 최적화된 내부 버퍼를 사용합니다." +whyModernWins: +- icon: "📏" + title: "한 줄" + desc: "전체 읽기/쓰기 루프를 단일 메서드 호출로 대체합니다." +- icon: "⚡" + title: "최적화됨" + desc: "내부 버퍼 크기가 성능을 위해 조정됩니다." +- icon: "🛡️" + title: "버그 없음" + desc: "버퍼 관리에서 오프바이원 오류가 없습니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/io-class-console-io.yaml b/translations/content/ko/io/io-class-console-io.yaml new file mode 100644 index 0000000..ed38585 --- /dev/null +++ b/translations/content/ko/io/io-class-console-io.yaml @@ -0,0 +1,17 @@ +title: "콘솔 I/O를 위한 IO 클래스" +oldApproach: "System.out / Scanner" +modernApproach: "IO 클래스" +summary: "새로운 IO 클래스는 콘솔 입출력을 위한 간단하고 간결한 메서드를 제공합니다." +explanation: "Java 25는 암묵적으로 선언된 클래스 기능의 일부로 IO 클래스(java.io.IO)를 도입합니다. println(), print(), readln(), read() 같은 정적 메서드를 제공하여 장황한 System.out과 Scanner 조합을 대체합니다. IO.readln(prompt)는 단일 호출로 프롬프트와 읽기를 모두 처리합니다. 이 클래스는 컴팩트 소스 파일에서 자동으로 사용 가능하며 전통적인 클래스에서는 import를 통해 사용할 수 있습니다." +whyModernWins: +- icon: "✨" + title: "대폭 단순화" + desc: "두 개의 메서드로 Scanner 설정, 프롬프트, 읽기, 정리의 7줄을 대체합니다." +- icon: "🔒" + title: "리소스 누수 없음" + desc: "닫아야 할 Scanner가 없습니다 — IO 메서드가 내부적으로 리소스 관리를 처리합니다." +- icon: "🎓" + title: "초보자 친화적" + desc: "새 개발자는 Scanner, System.out, import 문을 배우지 않고도 콘솔 I/O를 사용할 수 있습니다." +support: + description: "암묵적으로 선언된 클래스의 일부로 JDK 25에서 프리뷰 (JEP 495)" diff --git a/translations/content/ko/io/path-of.yaml b/translations/content/ko/io/path-of.yaml new file mode 100644 index 0000000..b448220 --- /dev/null +++ b/translations/content/ko/io/path-of.yaml @@ -0,0 +1,17 @@ +title: "Path.of() 팩토리" +oldApproach: "Paths.get()" +modernApproach: "Path.of()" +summary: "Path 인터페이스의 모던 팩토리 메서드인 Path.of()를 사용합니다." +explanation: "Path.of()는 별도의 Paths 유틸리티 클래스를 대체하여 Path 인터페이스에 직접 추가된 팩토리 메서드입니다. List.of(), Map.of() 등과 일관성이 있어 더 발견하기 쉽습니다." +whyModernWins: +- icon: "📐" + title: "일관된 API" + desc: "List.of(), Set.of()처럼 .of() 팩토리 패턴을 따릅니다." +- icon: "📖" + title: "발견 용이" + desc: "별도의 Paths 클래스가 아닌 Path 타입 자체에서 찾을 수 있습니다." +- icon: "🧹" + title: "클래스 하나 줄임" + desc: "Paths 유틸리티 클래스를 임포트할 필요가 없습니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/reading-files.yaml b/translations/content/ko/io/reading-files.yaml new file mode 100644 index 0000000..83bef54 --- /dev/null +++ b/translations/content/ko/io/reading-files.yaml @@ -0,0 +1,17 @@ +title: "파일 읽기" +oldApproach: "BufferedReader" +modernApproach: "Files.readString()" +summary: "한 줄로 전체 파일을 String으로 읽습니다." +explanation: "Files.readString()은 파일의 전체 내용을 String으로 읽습니다. 인코딩(기본값 UTF-8)과 리소스 정리를 처리합니다. 대용량 파일에는 지연 스트리밍을 위해 Files.lines()를 사용하세요." +whyModernWins: +- icon: "📏" + title: "한 줄" + desc: "BufferedReader 보일러플레이트 8줄을 대체합니다." +- icon: "🧹" + title: "자동 정리" + desc: "파일 핸들이 자동으로 닫힙니다." +- icon: "🌐" + title: "UTF-8 기본값" + desc: "기본적으로 올바른 인코딩 — 문자셋 혼동이 없습니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/try-with-resources-effectively-final.yaml b/translations/content/ko/io/try-with-resources-effectively-final.yaml new file mode 100644 index 0000000..b0c8601 --- /dev/null +++ b/translations/content/ko/io/try-with-resources-effectively-final.yaml @@ -0,0 +1,17 @@ +title: "try-with-resources 개선" +oldApproach: "변수 재선언" +modernApproach: "사실상 final" +summary: "사실상 final인 기존 변수를 try-with-resources에서 직접 사용합니다." +explanation: "Java 9는 사실상 final인 변수를 재선언 없이 try-with-resources에서 직접 사용할 수 있게 합니다. try 블록 외부에서 리소스가 생성된 경우 더 깔끔합니다." +whyModernWins: +- icon: "🧹" + title: "재선언 없음" + desc: "기존 변수 이름을 직접 사용합니다." +- icon: "📖" + title: "혼동 감소" + desc: "try 블록 내부에 별도의 변수 이름이 없습니다." +- icon: "📏" + title: "간결함" + desc: "더 적은 줄, 동일한 리소스 안전성." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/io/writing-files.yaml b/translations/content/ko/io/writing-files.yaml new file mode 100644 index 0000000..a67c0c1 --- /dev/null +++ b/translations/content/ko/io/writing-files.yaml @@ -0,0 +1,17 @@ +title: "파일 쓰기" +oldApproach: "FileWriter + BufferedWriter" +modernApproach: "Files.writeString()" +summary: "한 줄로 String을 파일에 씁니다." +explanation: "Files.writeString()은 기본적으로 UTF-8 인코딩으로 파일에 내용을 씁니다. 추가, 생성 등을 위한 옵션을 전달할 수 있습니다." +whyModernWins: +- icon: "📏" + title: "한 줄" + desc: "작성자 래핑이나 try-with-resources가 필요 없습니다." +- icon: "🛡️" + title: "안전한 기본값" + desc: "UTF-8 인코딩, 적절한 파일 핸들 정리." +- icon: "🔧" + title: "옵션" + desc: "추가, 생성 등을 위한 OpenOption 플래그를 전달합니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/compact-canonical-constructor.yaml b/translations/content/ko/language/compact-canonical-constructor.yaml new file mode 100644 index 0000000..69b268c --- /dev/null +++ b/translations/content/ko/language/compact-canonical-constructor.yaml @@ -0,0 +1,17 @@ +title: "간결한 표준 생성자" +oldApproach: "명시적 생성자 유효성 검사" +modernApproach: "간결한 생성자" +summary: "매개변수 목록을 반복하지 않고 레코드 필드를 검증하고 정규화합니다." +explanation: "레코드는 매개변수 목록과 필드 대입을 생략하는 간결한 표준 생성자를 선언할 수 있습니다. 컴파일러는 유효성 검사 로직 실행 후 자동으로 매개변수를 필드에 대입합니다. 전제 조건 확인, 방어적 복사에 이상적입니다." +whyModernWins: +- icon: "✂️" + title: "반복 감소" + desc: "매개변수 목록을 반복하거나 각 필드를 수동으로 대입할 필요가 없습니다." +- icon: "🛡️" + title: "유효성 검사" + desc: "null 확인, 범위 유효성 검사, 방어적 복사에 완벽합니다." +- icon: "📖" + title: "명확한 의도" + desc: "간결한 구문이 보일러플레이트가 아닌 유효성 검사를 강조합니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/compact-source-files.yaml b/translations/content/ko/language/compact-source-files.yaml new file mode 100644 index 0000000..8be486e --- /dev/null +++ b/translations/content/ko/language/compact-source-files.yaml @@ -0,0 +1,17 @@ +title: "컴팩트 소스 파일" +oldApproach: "메인 클래스 의식" +modernApproach: "void main()" +summary: "클래스 선언이나 public static void main 없이 완전한 프로그램을 작성합니다." +explanation: "컴팩트 소스 파일은 간단한 프로그램에서 클래스 선언과 main 메서드 서명의 형식적 절차를 제거합니다. java.io.IO의 암묵적 임포트와 결합하면 println도 직접 사용할 수 있습니다." +whyModernWins: +- icon: "🚀" + title: "의식 없음" + desc: "클래스, public static void main, String[] args가 없습니다." +- icon: "🎓" + title: "초보자 친화적" + desc: "새 프로그래머가 1행부터 유용한 코드를 작성할 수 있습니다." +- icon: "📝" + title: "스크립트 같은" + desc: "빠른 프로토타입, 스크립트, 예제에 완벽합니다." +support: + description: "JDK 25 LTS에서 확정 (JEP 512, 2025년 9월)." diff --git a/translations/content/ko/language/default-interface-methods.yaml b/translations/content/ko/language/default-interface-methods.yaml new file mode 100644 index 0000000..29adb86 --- /dev/null +++ b/translations/content/ko/language/default-interface-methods.yaml @@ -0,0 +1,17 @@ +title: "인터페이스 기본 메서드" +oldApproach: "공유 동작을 위한 추상 클래스" +modernApproach: "인터페이스의 기본 메서드" +summary: "인터페이스에 직접 메서드 구현을 추가하여 다중 동작 상속을 가능하게 합니다." +explanation: "Java 8 이전에는 관련 없는 클래스 간에 동작을 공유하려면 추상 클래스가 필요했으며, 단일 상속으로 제한되었습니다. 기본 메서드는 인터페이스가 메서드 구현을 제공할 수 있게 하여 클래스가 여러 인터페이스에서 동작을 상속받을 수 있습니다." +whyModernWins: +- icon: "🔀" + title: "다중 상속" + desc: "클래스는 단일 추상 클래스 상속과 달리 기본 메서드가 있는 여러 인터페이스를 구현할 수 있습니다." +- icon: "📦" + title: "API 진화" + desc: "기존 구현을 깨뜨리지 않고 인터페이스에 새 메서드를 추가합니다." +- icon: "🧩" + title: "조합 가능한 동작" + desc: "여러 인터페이스의 기능을 자유롭게 혼합하고 조합합니다." +support: + description: "JDK 8 (2014년 3월) 이후 사용 가능." diff --git a/translations/content/ko/language/diamond-operator.yaml b/translations/content/ko/language/diamond-operator.yaml new file mode 100644 index 0000000..53cf8bb --- /dev/null +++ b/translations/content/ko/language/diamond-operator.yaml @@ -0,0 +1,17 @@ +title: "익명 클래스의 다이아몬드 연산자" +oldApproach: "타입 인수 반복" +modernApproach: "다이아몬드 <>" +summary: "다이아몬드 연산자가 이제 익명 클래스에서도 작동합니다." +explanation: "Java 7에서 <>를 도입했지만 익명 내부 클래스에서는 작동하지 않았습니다. Java 9에서 이를 수정하여 우변에 타입 인수를 반복할 필요가 없습니다." +whyModernWins: +- icon: "📏" + title: "일관된 규칙" + desc: "다이아몬드는 생성자와 익명 클래스 어디서든 작동합니다." +- icon: "🧹" + title: "중복 감소" + desc: "타입 인수를 왼쪽에 한 번만 명시합니다." +- icon: "🔧" + title: "DRY 원칙" + desc: "컴파일러가 이미 타입을 알고 있는데 왜 두 번 써야 합니까?" +support: + description: "익명 클래스의 다이아몬드는 JDK 9 (2017년 9월) 이후 사용 가능." diff --git a/translations/content/ko/language/exhaustive-switch.yaml b/translations/content/ko/language/exhaustive-switch.yaml new file mode 100644 index 0000000..e74fd75 --- /dev/null +++ b/translations/content/ko/language/exhaustive-switch.yaml @@ -0,0 +1,17 @@ +title: "default 없는 완전한 switch" +oldApproach: "필수 default" +modernApproach: "봉인된 완전성" +summary: "컴파일러가 봉인된 모든 하위 타입이 처리되었는지 검증합니다 — default 불필요." +explanation: "봉인된 타입으로 switch할 때 컴파일러는 가능한 모든 하위 타입을 알고 모든 케이스가 처리되었는지 검증합니다. 새 하위 타입을 추가하면 컴파일러가 이제 불완전한 모든 switch를 표시합니다." +whyModernWins: +- icon: "✅" + title: "컴파일 시점 안전성" + desc: "새 하위 타입을 추가하면 컴파일러가 업데이트할 모든 위치를 표시합니다." +- icon: "🚫" + title: "죽은 코드 없음" + desc: "버그를 숨기는 도달 불가능한 default 분기가 없습니다." +- icon: "📐" + title: "대수적 타입" + desc: "봉인된 클래스 + 레코드 + 완전한 switch = Java에서 올바른 ADT." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/flexible-constructor-bodies.yaml b/translations/content/ko/language/flexible-constructor-bodies.yaml new file mode 100644 index 0000000..532c878 --- /dev/null +++ b/translations/content/ko/language/flexible-constructor-bodies.yaml @@ -0,0 +1,17 @@ +title: "유연한 생성자 본문" +oldApproach: "super() 이후 유효성 검사" +modernApproach: "super() 이전 코드" +summary: "super() 또는 this()를 호출하기 전에 값을 검증하고 계산합니다." +explanation: "Java 25는 super()가 첫 번째 문장이어야 한다는 제한을 해제합니다. 이제 부모 생성자에 위임하기 전에 인수를 검증하고, 파생 값을 계산하고, 상태를 설정할 수 있습니다." +whyModernWins: +- icon: "🛡️" + title: "빠른 실패" + desc: "슈퍼클래스 생성자가 실행되기 전에 인수를 검증합니다." +- icon: "🧮" + title: "먼저 계산" + desc: "super()를 호출하기 전에 값을 파생하고 데이터를 준비합니다." +- icon: "🧹" + title: "우회 방법 불필요" + desc: "제한을 우회하기 위한 정적 헬퍼 메서드나 팩토리 패턴이 필요 없습니다." +support: + description: "JDK 25 LTS에서 확정 (JEP 513, 2025년 9월)." diff --git a/translations/content/ko/language/guarded-patterns.yaml b/translations/content/ko/language/guarded-patterns.yaml new file mode 100644 index 0000000..fe20685 --- /dev/null +++ b/translations/content/ko/language/guarded-patterns.yaml @@ -0,0 +1,17 @@ +title: "when 가드가 있는 패턴" +oldApproach: "중첩 if" +modernApproach: "when 절" +summary: "when 가드를 사용하여 패턴 케이스에 조건을 추가합니다." +explanation: "가드된 패턴은 추가 boolean 조건으로 타입 매칭을 세밀화할 수 있습니다. 이를 통해 케이스 내부에 if 문을 중첩하지 않고 모든 분기 로직을 switch 안에 유지합니다." +whyModernWins: +- icon: "🎯" + title: "정밀한 매칭" + desc: "단일 케이스 레이블에 타입 + 조건을 결합합니다." +- icon: "📐" + title: "평탄한 구조" + desc: "switch 케이스 내부에 중첩된 if/else가 없습니다." +- icon: "📖" + title: "읽기 쉬운 의도" + desc: "when 절이 자연어처럼 읽힙니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/markdown-javadoc-comments.yaml b/translations/content/ko/language/markdown-javadoc-comments.yaml new file mode 100644 index 0000000..4be00c6 --- /dev/null +++ b/translations/content/ko/language/markdown-javadoc-comments.yaml @@ -0,0 +1,17 @@ +title: "Javadoc 주석에서 Markdown 사용" +oldApproach: "HTML 기반 Javadoc" +modernApproach: "Markdown Javadoc" +summary: "더 나은 가독성을 위해 HTML 대신 Markdown으로 Javadoc 주석을 작성합니다." +explanation: "Java 23은 전통적인 /** */ HTML 기반 형식의 대안으로 /// Markdown 스타일 Javadoc 주석을 도입합니다. Markdown 구문은 더 자연스럽게 작성하고 읽을 수 있으며, 코드 블록, 강조, 목록, 링크를 지원합니다." +whyModernWins: +- icon: "📖" + title: "자연스러운 구문" + desc: "HTML 태그 대신 인라인 코드에 백틱, 블록에 ```를 사용합니다." +- icon: "✍️" + title: "작성 용이" + desc: "{@code},
,태그 없이 Markdown으로 작성합니다." +- icon: "👁" + title: "편집기에서 더 나음" + desc: "Markdown은 모던 IDE와 텍스트 편집기에서 아름답게 렌더링됩니다." +support: + description: "JDK 23 (2024년 9월) 이후 사용 가능" diff --git a/translations/content/ko/language/module-import-declarations.yaml b/translations/content/ko/language/module-import-declarations.yaml new file mode 100644 index 0000000..1f5f22c --- /dev/null +++ b/translations/content/ko/language/module-import-declarations.yaml @@ -0,0 +1,17 @@ +title: "모듈 임포트 선언" +oldApproach: "많은 임포트" +modernApproach: "import module" +summary: "단일 선언으로 모듈의 모든 내보낸 패키지를 임포트합니다." +explanation: "모듈 임포트 선언을 통해 모듈이 내보내는 모든 것을 한 줄로 임포트할 수 있습니다. 컬렉션, I/O, 스트림 등을 다루는 java.base에 특히 유용합니다." +whyModernWins: +- icon: "🧹" + title: "한 줄" + desc: "임포트 목록을 단일 모듈 임포트로 대체합니다." +- icon: "📦" + title: "모듈 인식" + desc: "모듈 시스템을 활용하여 일관된 패키지 집합을 임포트합니다." +- icon: "🚀" + title: "빠른 시작" + desc: "임포트 목록이 번거로운 스크립트와 프로토타입에 완벽합니다." +support: + description: "JDK 25 LTS에서 확정 (JEP 511, 2025년 9월)." diff --git a/translations/content/ko/language/pattern-matching-instanceof.yaml b/translations/content/ko/language/pattern-matching-instanceof.yaml new file mode 100644 index 0000000..7910bcb --- /dev/null +++ b/translations/content/ko/language/pattern-matching-instanceof.yaml @@ -0,0 +1,17 @@ +title: "instanceof 패턴 매칭" +oldApproach: "instanceof + 캐스트" +modernApproach: "패턴 변수" +summary: "패턴 매칭으로 타입 확인과 캐스트를 한 단계로 결합합니다." +explanation: "instanceof 패턴 매칭은 타입 확인 후 중복 캐스트를 제거합니다. 변수는 패턴이 매칭되는 곳에서만 자동으로 범위가 지정되어 코드가 더 안전하고 짧아집니다." +whyModernWins: +- icon: "🔄" + title: "중복 캐스트 없음" + desc: "타입 확인과 변수 바인딩이 단일 표현식에서 이루어집니다." +- icon: "📏" + title: "줄 수 감소" + desc: "두 줄 대신 한 줄 — 캐스트 줄이 완전히 사라집니다." +- icon: "🛡️" + title: "범위 안전성" + desc: "패턴 변수는 타입이 보장되는 범위에서만 존재합니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/pattern-matching-switch.yaml b/translations/content/ko/language/pattern-matching-switch.yaml new file mode 100644 index 0000000..8ae5226 --- /dev/null +++ b/translations/content/ko/language/pattern-matching-switch.yaml @@ -0,0 +1,17 @@ +title: "switch의 패턴 매칭" +oldApproach: "if-else 체인" +modernApproach: "타입 패턴" +summary: "if-else instanceof 체인을 깔끔한 switch 타입 패턴으로 대체합니다." +explanation: "switch의 패턴 매칭은 타입 테스트, 캐스트, 바인딩을 하나의 간결한 케이스 레이블에 결합하여 타입에 직접 매칭할 수 있게 합니다. 컴파일러가 완전성을 검사합니다." +whyModernWins: +- icon: "📐" + title: "구조적 분배" + desc: "Switch는 분기 구조를 명시적이고 스캔 가능하게 만듭니다." +- icon: "🎯" + title: "표현식 형태" + desc: "값을 직접 반환합니다 — 가변 변수가 필요 없습니다." +- icon: "✅" + title: "완전성" + desc: "컴파일러가 모든 타입이 처리되었는지 확인합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/primitive-types-in-patterns.yaml b/translations/content/ko/language/primitive-types-in-patterns.yaml new file mode 100644 index 0000000..3caedef --- /dev/null +++ b/translations/content/ko/language/primitive-types-in-patterns.yaml @@ -0,0 +1,17 @@ +title: "패턴의 기본 타입" +oldApproach: "수동 범위 확인" +modernApproach: "기본 타입 패턴" +summary: "패턴 매칭이 이제 객체뿐만 아니라 기본 타입에도 작동합니다." +explanation: "Java 25는 패턴 매칭을 기본 타입으로 확장합니다. when 가드와 함께 switch 패턴에서 int, long, double 등을 사용할 수 있어 박싱이나 수동 범위 확인이 필요 없습니다." +whyModernWins: +- icon: "📦" + title: "박싱 없음" + desc: "Integer 래퍼 없이 기본 타입을 직접 매칭합니다." +- icon: "🎯" + title: "패턴 일관성" + desc: "객체와 기본 타입 모두 동일한 패턴 구문을 사용합니다." +- icon: "⚡" + title: "더 나은 성능" + desc: "패턴 매칭에서 오토박싱 오버헤드를 피합니다." +support: + description: "JDK 25에서 프리뷰 (세 번째 프리뷰, JEP 507). --enable-preview가 필요합니다." diff --git a/translations/content/ko/language/private-interface-methods.yaml b/translations/content/ko/language/private-interface-methods.yaml new file mode 100644 index 0000000..b05c8f5 --- /dev/null +++ b/translations/content/ko/language/private-interface-methods.yaml @@ -0,0 +1,17 @@ +title: "인터페이스 private 메서드" +oldApproach: "로직 중복" +modernApproach: "private 메서드" +summary: "private 메서드를 사용하여 인터페이스에서 공유 로직을 추출합니다." +explanation: "Java 9는 인터페이스에서 private 메서드를 허용하여 구현 클래스에 구현 세부 사항을 노출하지 않고 default 메서드 간에 코드를 공유할 수 있습니다." +whyModernWins: +- icon: "🧩" + title: "코드 재사용" + desc: "중복 없이 default 메서드 간에 로직을 공유합니다." +- icon: "🔐" + title: "캡슐화" + desc: "구현 세부 사항이 구현 클래스에 숨겨집니다." +- icon: "🧹" + title: "DRY 인터페이스" + desc: "더 이상 default 메서드 간에 복붙이 없습니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/record-patterns.yaml b/translations/content/ko/language/record-patterns.yaml new file mode 100644 index 0000000..96e17da --- /dev/null +++ b/translations/content/ko/language/record-patterns.yaml @@ -0,0 +1,17 @@ +title: "레코드 패턴 (구조 분해)" +oldApproach: "수동 접근" +modernApproach: "구조 분해" +summary: "패턴에서 레코드를 직접 구조 분해합니다 — 한 단계로 필드를 추출합니다." +explanation: "레코드 패턴은 instanceof와 switch에서 레코드 컴포넌트를 직접 분해할 수 있게 합니다. 중간 변수 없이 심층 매칭을 가능하게 하는 중첩 패턴도 지원됩니다." +whyModernWins: +- icon: "🎯" + title: "직접 추출" + desc: "접근자를 수동으로 호출하지 않고 레코드 컴포넌트에 접근합니다." +- icon: "🪆" + title: "중첩 가능" + desc: "패턴은 중첩될 수 있습니다 — 단일 표현식으로 내부 레코드를 매칭합니다." +- icon: "📏" + title: "간결한 코드" + desc: "5줄이 2줄이 됩니다 — 의식은 줄고 명확성은 동일합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/records-for-data-classes.yaml b/translations/content/ko/language/records-for-data-classes.yaml new file mode 100644 index 0000000..4c452c6 --- /dev/null +++ b/translations/content/ko/language/records-for-data-classes.yaml @@ -0,0 +1,17 @@ +title: "데이터 클래스를 위한 레코드" +oldApproach: "장황한 POJO" +modernApproach: "record" +summary: "한 줄이 불변 데이터 운반자를 위한 30줄 이상의 보일러플레이트를 대체합니다." +explanation: "레코드는 생성자, 접근자(x(), y()), equals(), hashCode(), toString()을 자동으로 생성합니다. 설계상 불변이며 DTO, 값 객체, 패턴 매칭에 이상적입니다." +whyModernWins: +- icon: "⚡" + title: "한 줄 정의" + desc: "한 줄이 생성자, 게터, equals, hashCode, toString을 대체합니다." +- icon: "🔒" + title: "기본적으로 불변" + desc: "모든 필드는 final입니다 — 세터로 인한 위험이 없습니다." +- icon: "🧩" + title: "패턴 친화적" + desc: "레코드는 switch와 instanceof의 구조 분해 패턴과 함께 작동합니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/sealed-classes.yaml b/translations/content/ko/language/sealed-classes.yaml new file mode 100644 index 0000000..847a4a4 --- /dev/null +++ b/translations/content/ko/language/sealed-classes.yaml @@ -0,0 +1,17 @@ +title: "타입 계층을 위한 봉인된 클래스" +oldApproach: "개방 계층" +modernApproach: "sealed permits" +summary: "어떤 클래스가 타입을 확장할 수 있는지 제한합니다 — 완전한 switch를 가능하게 합니다." +explanation: "봉인된 클래스는 닫힌 하위 타입 집합을 정의합니다. 컴파일러는 모든 가능한 케이스를 알고 있어 default 분기 없이 완전한 패턴 매칭을 가능하게 합니다. 레코드와 결합하면 대수적 데이터 타입을 모델링합니다." +whyModernWins: +- icon: "🔐" + title: "제어된 계층" + desc: "허가된 하위 타입만 확장할 수 있습니다 — 예상치 못한 서브클래스 없음." +- icon: "✅" + title: "완전한 매칭" + desc: "컴파일러가 switch가 모든 케이스를 처리하는지 검증합니다." +- icon: "📐" + title: "대수적 데이터 타입" + desc: "합 타입을 자연스럽게 모델링합니다 — 봉인된 클래스 + 레코드 = Java의 ADT." +support: + description: "JDK 17 LTS (2021년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/static-members-in-inner-classes.yaml b/translations/content/ko/language/static-members-in-inner-classes.yaml new file mode 100644 index 0000000..dc7a0a0 --- /dev/null +++ b/translations/content/ko/language/static-members-in-inner-classes.yaml @@ -0,0 +1,17 @@ +title: "내부 클래스의 정적 멤버" +oldApproach: "정적 중첩 클래스 사용 필수" +modernApproach: "내부 클래스의 정적 멤버" +summary: "정적 중첩 클래스 없이 내부 클래스에 정적 멤버를 정의합니다." +explanation: "Java 16 이전에는 정적 중첩 클래스만 정적 멤버를 포함할 수 있었습니다. 내부(비정적) 클래스는 둘러싸는 인스턴스가 필요하므로 정적 멤버를 가질 수 없었습니다. Java 16은 이 제한을 완화하여 내부 클래스에서 정적 필드, 메서드 등을 허용합니다." +whyModernWins: +- icon: "🔓" + title: "더 많은 유연성" + desc: "내부 클래스는 이제 필요할 때 정적 멤버를 가질 수 있습니다." +- icon: "🧩" + title: "공유 상태" + desc: "내부 클래스의 인스턴스 간에 공유 상태를 추적합니다." +- icon: "📐" + title: "설계 자유" + desc: "단 하나의 정적 필드를 위해 정적 중첩 클래스로 승격할 필요가 없습니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/static-methods-in-interfaces.yaml b/translations/content/ko/language/static-methods-in-interfaces.yaml new file mode 100644 index 0000000..ab5db18 --- /dev/null +++ b/translations/content/ko/language/static-methods-in-interfaces.yaml @@ -0,0 +1,17 @@ +title: "인터페이스의 정적 메서드" +oldApproach: "유틸리티 클래스" +modernApproach: "인터페이스 정적 메서드" +summary: "별도의 유틸리티 클래스 대신 인터페이스에 직접 정적 유틸리티 메서드를 추가합니다." +explanation: "Java 8 이전에는 인터페이스와 관련된 유틸리티 메서드가 별도의 클래스에 있어야 했습니다(예: Collection을 위한 Collections). 인터페이스의 정적 메서드는 관련 유틸리티를 함께 유지할 수 있게 합니다. Comparator.comparing() 같은 모던 API에서 흔히 볼 수 있습니다." +whyModernWins: +- icon: "📦" + title: "더 나은 구성" + desc: "관련 유틸리티를 별도의 클래스가 아닌 인터페이스와 함께 유지합니다." +- icon: "🔍" + title: "발견 용이성" + desc: "팩토리와 헬퍼 메서드가 예상한 곳에서 발견됩니다." +- icon: "🧩" + title: "API 응집성" + desc: "별도의 *Utils 또는 *Helper 클래스가 필요 없습니다." +support: + description: "JDK 8 (2014년 3월) 이후 사용 가능" diff --git a/translations/content/ko/language/switch-expressions.yaml b/translations/content/ko/language/switch-expressions.yaml new file mode 100644 index 0000000..5ec3144 --- /dev/null +++ b/translations/content/ko/language/switch-expressions.yaml @@ -0,0 +1,17 @@ +title: "Switch 표현식" +oldApproach: "Switch 문" +modernApproach: "Switch 표현식" +summary: "값을 반환하는 표현식으로서의 switch — break 없음, fall-through 없음." +explanation: "Switch 표현식은 값을 직접 반환하고, 화살표 구문을 사용하여 fall-through 버그를 방지하며, 컴파일러가 완전성을 검증합니다. 오류가 발생하기 쉬운 문 형태를 대체합니다." +whyModernWins: +- icon: "🎯" + title: "값 반환" + desc: "switch 결과를 직접 대입합니다 — 임시 변수가 필요 없습니다." +- icon: "🛡️" + title: "fall-through 없음" + desc: "화살표 구문은 break 누락으로 인한 우발적 fall-through 버그를 제거합니다." +- icon: "✅" + title: "완전성 검사" + desc: "컴파일러가 모든 케이스가 처리되었는지 확인합니다." +support: + description: "JDK 14 (2020년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/text-blocks-for-multiline-strings.yaml b/translations/content/ko/language/text-blocks-for-multiline-strings.yaml new file mode 100644 index 0000000..fae0b75 --- /dev/null +++ b/translations/content/ko/language/text-blocks-for-multiline-strings.yaml @@ -0,0 +1,17 @@ +title: "여러 줄 문자열을 위한 텍스트 블록" +oldApproach: "문자열 연결" +modernApproach: "텍스트 블록" +summary: "삼중 따옴표 텍스트 블록으로 여러 줄 문자열을 자연스럽게 작성합니다." +explanation: "텍스트 블록은 여러 줄 문자열을 그대로 작성할 수 있게 합니다. 더 이상 따옴표를 이스케이프하거나 \n을 추가할 필요가 없습니다. 컴파일러가 자동으로 우발적 들여쓰기를 제거합니다." +whyModernWins: +- icon: "📖" + title: "있는 그대로 읽기 가능" + desc: "JSON, SQL, HTML이 소스에서 실제 JSON, SQL, HTML처럼 보입니다." +- icon: "🚫" + title: "이스케이프 지옥 없음" + desc: "포함된 따옴표에 백슬래시 이스케이프가 필요 없습니다." +- icon: "📐" + title: "스마트 들여쓰기" + desc: "닫는 구분자 위치에 따라 앞쪽 공백이 자동으로 제거됩니다." +support: + description: "JDK 15 (2020년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/type-inference-with-var.yaml b/translations/content/ko/language/type-inference-with-var.yaml new file mode 100644 index 0000000..bd7ecad --- /dev/null +++ b/translations/content/ko/language/type-inference-with-var.yaml @@ -0,0 +1,17 @@ +title: "var를 사용한 타입 추론" +oldApproach: "명시적 타입" +modernApproach: "var 키워드" +summary: "지역 변수 타입 추론에 var를 사용합니다 — 노이즈는 줄고 안전성은 동일합니다." +explanation: "Java 10부터 컴파일러가 우변으로부터 지역 변수 타입을 추론합니다. 타입 안전성을 해치지 않고 시각적 노이즈를 줄입니다. 문맥에서 타입이 명확할 때 var를 사용하세요." +whyModernWins: +- icon: "⚡" + title: "보일러플레이트 감소" + desc: "대입문 양쪽에 복잡한 제네릭 타입을 반복할 필요가 없습니다." +- icon: "👁" + title: "가독성 향상" + desc: "타입 선언이 아닌 변수 이름과 값에 집중할 수 있습니다." +- icon: "🔒" + title: "타입 안전성 유지" + desc: "컴파일러가 컴파일 시점에 정확한 타입을 추론하고 강제합니다." +support: + description: "JDK 10 (2018년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/language/unnamed-variables.yaml b/translations/content/ko/language/unnamed-variables.yaml new file mode 100644 index 0000000..d836171 --- /dev/null +++ b/translations/content/ko/language/unnamed-variables.yaml @@ -0,0 +1,17 @@ +title: "_를 사용한 이름 없는 변수" +oldApproach: "미사용 변수" +modernApproach: "_ 플레이스홀더" +summary: "변수가 의도적으로 사용되지 않음을 표시하기 위해 _를 사용합니다." +explanation: "이름 없는 변수는 값이 의도적으로 무시됨을 독자와 도구에 전달합니다. 더 이상 'ignored' 또는 'unused' 이름 규칙이나 IDE 경고가 필요 없습니다." +whyModernWins: +- icon: "📢" + title: "명확한 의도" + desc: "_는 '이 값이 여기서 필요하지 않습니다'를 명시적으로 표현합니다." +- icon: "🔇" + title: "경고 없음" + desc: "IDE와 린터가 의도적으로 사용하지 않은 변수를 표시하지 않습니다." +- icon: "🧹" + title: "더 깔끔한 람다" + desc: "일부 매개변수만 필요할 때 다중 매개변수 람다가 더 깔끔해집니다." +support: + description: "JDK 22에서 확정 (JEP 456, 2024년 3월)." diff --git a/translations/content/ko/security/key-derivation-functions.yaml b/translations/content/ko/security/key-derivation-functions.yaml new file mode 100644 index 0000000..a4badd8 --- /dev/null +++ b/translations/content/ko/security/key-derivation-functions.yaml @@ -0,0 +1,17 @@ +title: "키 파생 함수" +oldApproach: "수동 PBKDF2" +modernApproach: "KDF API" +summary: "표준 KDF API를 사용하여 암호화 키를 파생합니다." +explanation: "KDF API는 키 파생 함수를 위한 표준 인터페이스를 제공합니다. PBKDF2와 HKDF를 지원하며 이전의 직접 KeySpec 생성자 사용을 대체합니다." +whyModernWins: +- icon: "📐" + title: "깔끔한 API" + desc: "어색한 KeySpec 생성자 대신 빌더 패턴." +- icon: "🔧" + title: "HKDF 지원" + desc: "PBKDF2와 함께 모던 HKDF 알고리즘을 지원합니다." +- icon: "🛡️" + title: "표준" + desc: "모든 키 파생 알고리즘을 위한 통일된 API." +support: + description: "JDK 25 LTS에서 확정 (JEP 510, 2025년 9월)." diff --git a/translations/content/ko/security/pem-encoding.yaml b/translations/content/ko/security/pem-encoding.yaml new file mode 100644 index 0000000..4cf2f3e --- /dev/null +++ b/translations/content/ko/security/pem-encoding.yaml @@ -0,0 +1,17 @@ +title: "PEM 인코딩/디코딩" +oldApproach: "수동 Base64 + 헤더" +modernApproach: "PEM API" +summary: "PEM 형식의 암호화 객체를 네이티브로 인코딩하고 디코딩합니다." +explanation: "PEM API는 인증서, 키, 기타 암호화 객체에 대한 표준 인코딩/디코딩을 제공합니다. 더 이상 수동 Base64 처리나 헤더 형식 지정이 필요 없습니다." +whyModernWins: +- icon: "🧹" + title: "수동 Base64 없음" + desc: "PEM 헤더, 줄 바꿈, Base64가 자동으로 처리됩니다." +- icon: "🔄" + title: "양방향" + desc: "하나의 API로 PEM으로 인코딩하고 PEM에서 디코딩합니다." +- icon: "🛡️" + title: "표준 형식" + desc: "RFC 7468 호환 PEM 출력을 생성합니다." +support: + description: "JDK 25에서 프리뷰 (JEP 470). --enable-preview가 필요합니다." diff --git a/translations/content/ko/security/random-generator.yaml b/translations/content/ko/security/random-generator.yaml new file mode 100644 index 0000000..1809f48 --- /dev/null +++ b/translations/content/ko/security/random-generator.yaml @@ -0,0 +1,17 @@ +title: "RandomGenerator 인터페이스" +oldApproach: "new Random() / ThreadLocalRandom" +modernApproach: "RandomGenerator 팩토리" +summary: "이름으로 난수 알고리즘을 선택하기 위해 RandomGenerator 인터페이스를 사용합니다." +explanation: "JDK 17은 모든 RNG 구현을 위한 공통 인터페이스로 RandomGenerator를 도입했습니다. 알고리즘을 이름으로 선택하고 코드 구조를 변경하지 않고도 교체할 수 있습니다." +whyModernWins: +- icon: "🔧" + title: "알고리즘 무관" + desc: "코드 구조를 변경하지 않고 이름으로 최적의 RNG 알고리즘을 선택합니다." +- icon: "⚡" + title: "더 나은 알고리즘" + desc: "우수한 통계적 특성을 가진 최신 LXM 생성기에 접근합니다." +- icon: "🔗" + title: "통일된 API" + desc: "하나의 인터페이스가 Random, ThreadLocalRandom, SplittableRandom 등을 모두 포괄합니다." +support: + description: "JDK 17 (2021년 9월, JEP 356) 이후 사용 가능." diff --git a/translations/content/ko/security/strong-random.yaml b/translations/content/ko/security/strong-random.yaml new file mode 100644 index 0000000..1bbe1c4 --- /dev/null +++ b/translations/content/ko/security/strong-random.yaml @@ -0,0 +1,17 @@ +title: "강력한 난수 생성" +oldApproach: "new SecureRandom()" +modernApproach: "getInstanceStrong()" +summary: "플랫폼의 가장 강력한 SecureRandom 구현을 가져옵니다." +explanation: "getInstanceStrong()은 강력한 난수 생성에 대한 보안 구성에서 설정된 SecureRandom 구현을 반환합니다. 플랫폼 보안 속성을 준수합니다." +whyModernWins: +- icon: "🛡️" + title: "가장 강력한 것" + desc: "플랫폼에 맞는 최선의 알고리즘을 자동으로 선택합니다." +- icon: "📖" + title: "명확한 의도" + desc: "강력한 난수가 필요함을 명확히 전달합니다." +- icon: "🔧" + title: "설정 가능" + desc: "관리자가 보안 속성을 통해 강력한 알고리즘을 변경할 수 있습니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/security/tls-default.yaml b/translations/content/ko/security/tls-default.yaml new file mode 100644 index 0000000..7b1f37f --- /dev/null +++ b/translations/content/ko/security/tls-default.yaml @@ -0,0 +1,17 @@ +title: "기본 TLS 1.3" +oldApproach: "수동 TLS 설정" +modernApproach: "TLS 1.3 기본값" +summary: "TLS 1.3이 기본으로 활성화되어 있습니다 — 명시적 프로토콜 설정이 필요 없습니다." +explanation: "Java 11에서 TLS 1.3 지원이 추가되었고 선호 프로토콜이 되었습니다. 기본 SSLContext는 이제 TLS 1.3을 우선시하여 수동 프로토콜 설정이 불필요합니다." +whyModernWins: +- icon: "🛡️" + title: "더 안전" + desc: "TLS 1.3은 구식 암호화 스위트와 핸드셰이크 패턴을 제거합니다." +- icon: "⚡" + title: "더 빠른 핸드셰이크" + desc: "TLS 1.3은 두 번 대신 한 번의 왕복으로 완료됩니다." +- icon: "🆓" + title: "설정 없음" + desc: "기본적으로 안전합니다 — 명시적 프로토콜 선택이 필요 없습니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/collectors-flatmapping.yaml b/translations/content/ko/streams/collectors-flatmapping.yaml new file mode 100644 index 0000000..dfc6eda --- /dev/null +++ b/translations/content/ko/streams/collectors-flatmapping.yaml @@ -0,0 +1,17 @@ +title: "Collectors.flatMapping()" +oldApproach: "중첩 flatMap" +modernApproach: "flatMapping()" +summary: "그룹화 컬렉터 내부에서 flatMapping()을 사용하여 평탄화합니다." +explanation: "Collectors.flatMapping()은 다운스트림 컬렉터로 일대다 매핑을 적용합니다. groupingBy 내부에서 평탄화 작업에 이상적입니다." +whyModernWins: +- icon: "🧩" + title: "조합 가능" + desc: "groupingBy 내부에서 다운스트림 컬렉터로 작동합니다." +- icon: "📐" + title: "단일 순회" + desc: "단일 스트림 순회로 평탄화와 그룹화를 수행합니다." +- icon: "🔗" + title: "중첩 가능" + desc: "다른 다운스트림 컬렉터와 결합합니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/optional-ifpresentorelse.yaml b/translations/content/ko/streams/optional-ifpresentorelse.yaml new file mode 100644 index 0000000..8a51b68 --- /dev/null +++ b/translations/content/ko/streams/optional-ifpresentorelse.yaml @@ -0,0 +1,17 @@ +title: "Optional.ifPresentOrElse()" +oldApproach: "Optional에 대한 if/else" +modernApproach: "ifPresentOrElse()" +summary: "하나의 호출로 Optional의 존재 및 빈 케이스를 모두 처리합니다." +explanation: "ifPresentOrElse()는 존재 케이스를 위한 Consumer와 빈 케이스를 위한 Runnable을 받습니다. 두 가지 경우를 처리하기 위해 isPresent()와 별도 동작을 결합할 필요가 없습니다." +whyModernWins: +- icon: "📏" + title: "단일 표현식" + desc: "하나의 메서드 호출로 두 케이스가 처리됩니다." +- icon: "🚫" + title: "get() 없음" + desc: "위험한 isPresent() + get() 패턴을 제거합니다." +- icon: "🔗" + title: "유창함" + desc: "findUser()나 Optional을 반환하는 메서드 뒤에 자연스럽게 체이닝됩니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/optional-or.yaml b/translations/content/ko/streams/optional-or.yaml new file mode 100644 index 0000000..b833821 --- /dev/null +++ b/translations/content/ko/streams/optional-or.yaml @@ -0,0 +1,17 @@ +title: "Optional.or() 폴백" +oldApproach: "중첩 폴백" +modernApproach: ".or() 체인" +summary: "중첩 확인 없이 Optional 폴백을 체이닝합니다." +explanation: "Optional.or()는 값이 있으면 원래 Optional을 반환하고, 그렇지 않으면 공급자에서 다른 Optional을 반환합니다. 이를 통해 여러 폴백 소스를 읽기 쉬운 파이프라인으로 체이닝할 수 있습니다." +whyModernWins: +- icon: "🔗" + title: "체이닝 가능" + desc: "읽기 쉬운 파이프라인으로 폴백을 쌓습니다." +- icon: "⚡" + title: "지연 평가" + desc: "폴백 공급자는 필요할 때만 실행됩니다." +- icon: "📖" + title: "선언적" + desc: "'기본을 시도, 또는 보조, 또는 기본값'으로 읽힙니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/predicate-not.yaml b/translations/content/ko/streams/predicate-not.yaml new file mode 100644 index 0000000..ab8f06e --- /dev/null +++ b/translations/content/ko/streams/predicate-not.yaml @@ -0,0 +1,17 @@ +title: "부정을 위한 Predicate.not()" +oldApproach: "람다 부정" +modernApproach: "Predicate.not()" +summary: "람다로 작성하는 대신 Predicate.not()을 사용하여 메서드 참조를 깔끔하게 부정합니다." +explanation: "Java 11 이전에는 메서드 참조를 부정하려면 람다로 감싸야 했습니다. Predicate.not()은 메서드 참조를 직접 부정하는 정적 팩토리 메서드입니다." +whyModernWins: +- icon: "👁" + title: "더 깔끔한 부정" + desc: "메서드 참조를 부정하기 위해 람다로 감쌀 필요가 없습니다." +- icon: "🔗" + title: "조합 가능" + desc: "모든 Predicate와 함께 작동하여 깔끔한 Predicate 체인을 가능하게 합니다." +- icon: "📖" + title: "자연스럽게 읽힘" + desc: "Predicate.not(String::isBlank)는 영어처럼 읽힙니다." +support: + description: "JDK 11 (2018년 9월) 이후 사용 가능." diff --git a/translations/content/ko/streams/stream-gatherers.yaml b/translations/content/ko/streams/stream-gatherers.yaml new file mode 100644 index 0000000..9f91080 --- /dev/null +++ b/translations/content/ko/streams/stream-gatherers.yaml @@ -0,0 +1,17 @@ +title: "스트림 수집기" +oldApproach: "커스텀 Collector" +modernApproach: "gather()" +summary: "커스텀 중간 스트림 연산을 위해 수집기를 사용합니다." +explanation: "Gatherer는 복잡한 상태 저장 중간 변환을 표현할 수 있는 새로운 중간 스트림 연산입니다. 내장 수집기로는 windowFixed, windowSliding, fold, scan이 있습니다." +whyModernWins: +- icon: "🧩" + title: "조합 가능" + desc: "수집기는 다른 스트림 연산과 조합됩니다." +- icon: "📦" + title: "내장 연산" + desc: "windowFixed, windowSliding, fold, scan이 기본 제공됩니다." +- icon: "🔧" + title: "확장 가능" + desc: "임의의 중간 변환을 위한 커스텀 수집기를 작성합니다." +support: + description: "JDK 24에서 확정 (JEP 485, 2025년 3월)." diff --git a/translations/content/ko/streams/stream-iterate-predicate.yaml b/translations/content/ko/streams/stream-iterate-predicate.yaml new file mode 100644 index 0000000..4786622 --- /dev/null +++ b/translations/content/ko/streams/stream-iterate-predicate.yaml @@ -0,0 +1,17 @@ +title: "조건자가 있는 Stream.iterate()" +oldApproach: "iterate + limit" +modernApproach: "iterate(시드, 조건자, 연산)" +summary: "반복을 중지하기 위해 조건자를 사용합니다 — 스트림 형태의 for 루프." +explanation: "세 인수 Stream.iterate(seed, hasNext, next)는 for 루프처럼 작동합니다. hasNext 조건자가 false를 반환할 때 스트림이 종료됩니다." +whyModernWins: +- icon: "🎯" + title: "자연스러운 종료" + desc: "임의의 제한 대신 조건에 따라 중지합니다." +- icon: "📐" + title: "for 루프 동등물" + desc: "for(seed; hasNext; next)와 동일한 의미론." +- icon: "🛡️" + title: "무한 스트림 위험 없음" + desc: "조건자가 종료를 보장합니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/stream-mapmulti.yaml b/translations/content/ko/streams/stream-mapmulti.yaml new file mode 100644 index 0000000..d778dec --- /dev/null +++ b/translations/content/ko/streams/stream-mapmulti.yaml @@ -0,0 +1,17 @@ +title: "Stream.mapMulti()" +oldApproach: "flatMap + 리스트" +modernApproach: "mapMulti()" +summary: "중간 스트림을 생성하지 않고 입력당 0개 이상의 요소를 방출합니다." +explanation: "mapMulti()는 각 요소마다 Stream을 생성하지 않는 flatMap의 명령형 대안입니다. 필터링이나 복잡한 조건부 확장에 더 효율적입니다." +whyModernWins: +- icon: "⚡" + title: "할당 감소" + desc: "요소당 중간 Stream이 생성되지 않습니다." +- icon: "🎯" + title: "명령형 스타일" + desc: "루프와 조건문을 직접 사용합니다." +- icon: "📐" + title: "유연함" + desc: "완전한 제어로 0개, 1개, 또는 여러 개의 요소를 방출합니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/stream-of-nullable.yaml b/translations/content/ko/streams/stream-of-nullable.yaml new file mode 100644 index 0000000..dc22501 --- /dev/null +++ b/translations/content/ko/streams/stream-of-nullable.yaml @@ -0,0 +1,17 @@ +title: "Stream.ofNullable()" +oldApproach: "null 확인" +modernApproach: "ofNullable()" +summary: "nullable 값에서 0개 또는 1개의 요소를 가진 스트림을 만듭니다." +explanation: "Stream.ofNullable()은 값이 non-null이면 단일 요소 스트림을, null이면 빈 스트림을 반환합니다. null 확인 없이 스트림 파이프라인에 nullable 값을 통합합니다." +whyModernWins: +- icon: "📏" + title: "간결함" + desc: "하나의 호출이 삼항 조건부를 대체합니다." +- icon: "🔗" + title: "flatMap 친화적" + desc: "null 값을 건너뛰기 위해 flatMap 내부에서 완벽합니다." +- icon: "🛡️" + title: "null 안전" + desc: "NPE 위험 없음 — null은 빈 스트림이 됩니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/stream-takewhile-dropwhile.yaml b/translations/content/ko/streams/stream-takewhile-dropwhile.yaml new file mode 100644 index 0000000..2e06e9b --- /dev/null +++ b/translations/content/ko/streams/stream-takewhile-dropwhile.yaml @@ -0,0 +1,17 @@ +title: "스트림 takeWhile / dropWhile" +oldApproach: "수동 루프" +modernApproach: "takeWhile/dropWhile" +summary: "조건자를 기반으로 스트림에서 요소를 가져오거나 제거합니다." +explanation: "takeWhile()은 조건자가 참인 동안 요소를 반환하고 실패 시 중지합니다. dropWhile()은 조건자가 참인 동안 요소를 건너뛰고 나머지를 반환합니다." +whyModernWins: +- icon: "🎯" + title: "단락 평가" + desc: "조건자가 실패하는 즉시 처리를 중지합니다." +- icon: "🔗" + title: "파이프라인 친화적" + desc: "다른 스트림 연산과 자연스럽게 체이닝됩니다." +- icon: "📖" + title: "선언적" + desc: "takeWhile은 영어처럼 읽힙니다: '100보다 작은 동안 가져오기'." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/stream-tolist.yaml b/translations/content/ko/streams/stream-tolist.yaml new file mode 100644 index 0000000..f25cc31 --- /dev/null +++ b/translations/content/ko/streams/stream-tolist.yaml @@ -0,0 +1,17 @@ +title: "Stream.toList()" +oldApproach: "Collectors.toList()" +modernApproach: ".toList()" +summary: "터미널 toList()가 장황한 collect(Collectors.toList())를 대체합니다." +explanation: "Stream.toList()는 수정 불가능한 리스트를 반환합니다. .collect(Collectors.toUnmodifiableList())와 동일하지만 훨씬 짧습니다." +whyModernWins: +- icon: "📏" + title: "7자 대 24자" + desc: ".toList()가 .collect(Collectors.toList())를 대체합니다." +- icon: "🔒" + title: "불변" + desc: "결과 리스트를 수정할 수 없습니다." +- icon: "��" + title: "유창함" + desc: "파이프라인 끝에서 자연스럽게 읽힙니다." +support: + description: "JDK 16 (2021년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/streams/virtual-thread-executor.yaml b/translations/content/ko/streams/virtual-thread-executor.yaml new file mode 100644 index 0000000..5d8f749 --- /dev/null +++ b/translations/content/ko/streams/virtual-thread-executor.yaml @@ -0,0 +1,17 @@ +title: "가상 스레드 실행자" +oldApproach: "고정 스레드 풀" +modernApproach: "가상 스레드 실행자" +summary: "제한 없는 경량 동시성을 위해 가상 스레드 실행자를 사용합니다." +explanation: "가상 스레드 실행자는 각 작업에 대해 새 가상 스레드를 만듭니다. 고정 풀을 완전히 포화하는 I/O 집약적 작업에 이상적입니다." +whyModernWins: +- icon: "♾️" + title: "크기 조정 없음" + desc: "풀 크기를 조정할 필요 없음 — 필요한 만큼 스레드를 만듭니다." +- icon: "⚡" + title: "경량" + desc: "가상 스레드는 MB가 아닌 KB의 메모리를 사용합니다." +- icon: "🧹" + title: "자동 닫기" + desc: "try-with-resources가 자동으로 종료를 처리합니다." +support: + description: "JDK 21 LTS (2023년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/strings/string-chars-stream.yaml b/translations/content/ko/strings/string-chars-stream.yaml new file mode 100644 index 0000000..84c7397 --- /dev/null +++ b/translations/content/ko/strings/string-chars-stream.yaml @@ -0,0 +1,17 @@ +title: "스트림으로서의 문자열 문자" +oldApproach: "수동 루프" +modernApproach: "chars() 스트림" +summary: "스트림 파이프라인으로 문자열 문자를 처리합니다." +explanation: "String.chars()는 문자 값의 IntStream을 반환하여 함수형 파이프라인 처리를 가능하게 합니다. filter, map, collect를 문자 스트림에 사용하세요." +whyModernWins: +- icon: "🔗" + title: "체이닝 가능" + desc: "문자 스트림에 filter, map, collect를 사용합니다." +- icon: "📐" + title: "선언적" + desc: "어떻게 루프를 돌릴지가 아닌 무엇을 할지를 설명합니다." +- icon: "🌐" + title: "유니코드 준비" + desc: "codePoints()는 이모지와 보조 문자를 올바르게 처리합니다." +support: + description: "JDK 8 이상에서 사용 가능 (9 이상에서 개선)" diff --git a/translations/content/ko/strings/string-formatted.yaml b/translations/content/ko/strings/string-formatted.yaml new file mode 100644 index 0000000..796d350 --- /dev/null +++ b/translations/content/ko/strings/string-formatted.yaml @@ -0,0 +1,17 @@ +title: "String.formatted()" +oldApproach: "String.format()" +modernApproach: "formatted()" +summary: "템플릿 문자열 자체에서 formatted()를 호출합니다." +explanation: "String.formatted()는 String.format()의 인스턴스 메서드 동등물입니다. 정적 메서드 호출과 템플릿 인수를 혼용하지 않고 메서드를 체이닝할 수 있습니다." +whyModernWins: +- icon: "📖" + title: "자연스럽게 읽힘" + desc: "Template.formatted(args)는 String.format(template, args)보다 더 자연스럽게 흐릅니다." +- icon: "🔗" + title: "체이닝 가능" + desc: "다른 문자열 메서드와 체이닝할 수 있습니다." +- icon: "📏" + title: "덜 장황함" + desc: "중복되는 String.format() 정적 호출을 생략합니다." +support: + description: "JDK 15 (2020년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/strings/string-indent-transform.yaml b/translations/content/ko/strings/string-indent-transform.yaml new file mode 100644 index 0000000..1be16aa --- /dev/null +++ b/translations/content/ko/strings/string-indent-transform.yaml @@ -0,0 +1,17 @@ +title: "String.indent()와 transform()" +oldApproach: "수동 들여쓰기" +modernApproach: "indent() / transform()" +summary: "텍스트 들여쓰기와 문자열 변환을 유창하게 체이닝합니다." +explanation: "indent(n)은 각 줄에 n 칸의 공백을 추가합니다. transform(fn)은 임의의 함수를 적용하여 유창한 문자열 파이프라인을 가능하게 합니다." +whyModernWins: +- icon: "📏" + title: "내장됨" + desc: "들여쓰기는 일반적인 작업입니다 — 이제 한 번의 호출로 가능합니다." +- icon: "🔗" + title: "체이닝 가능" + desc: "transform()은 문자열에서 유창한 파이프라인을 가능하게 합니다." +- icon: "🧹" + title: "깔끔한 코드" + desc: "수동 줄 분할과 StringBuilder 루프가 없습니다." +support: + description: "JDK 12 (2019년 3월) 이후 널리 사용 가능" diff --git a/translations/content/ko/strings/string-isblank.yaml b/translations/content/ko/strings/string-isblank.yaml new file mode 100644 index 0000000..6043f8d --- /dev/null +++ b/translations/content/ko/strings/string-isblank.yaml @@ -0,0 +1,17 @@ +title: "String.isBlank()" +oldApproach: "trim().isEmpty()" +modernApproach: "isBlank()" +summary: "단일 메서드 호출로 빈 문자열을 확인합니다." +explanation: "isBlank()는 문자열이 비어 있거나 공백만 포함하는 경우 true를 반환합니다. trim().isEmpty()와 달리 유니코드 공백을 올바르게 처리합니다." +whyModernWins: +- icon: "📖" + title: "자기 문서화" + desc: "isBlank()는 정확히 무엇을 확인하는지 설명합니다." +- icon: "🌐" + title: "유니코드 인식" + desc: "ASCII뿐만 아니라 모든 유니코드 공백을 처리합니다." +- icon: "⚡" + title: "할당 없음" + desc: "중간 트리밍된 문자열이 생성되지 않습니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/strings/string-lines.yaml b/translations/content/ko/strings/string-lines.yaml new file mode 100644 index 0000000..7c3453f --- /dev/null +++ b/translations/content/ko/strings/string-lines.yaml @@ -0,0 +1,17 @@ +title: "줄 분할을 위한 String.lines()" +oldApproach: 'split("\\n")' +modernApproach: "lines()" +summary: "정규식 오버헤드 없이 텍스트를 줄 스트림으로 분할하기 위해 String.lines()를 사용합니다." +explanation: "String.lines()는 \n, \r, \r\n으로 분할된 줄의 Stream
을 반환합니다. 지연 평가되므로 대용량 문자열에 효율적입니다." +whyModernWins: +- icon: "⚡" + title: "지연 스트리밍" + desc: "줄은 split()처럼 한 번에 모두가 아닌 필요에 따라 생성됩니다." +- icon: "🔧" + title: "범용 줄 끝" + desc: "정규식 없이 \n, \r, \r\n을 자동으로 처리합니다." +- icon: "🔗" + title: "스트림 통합" + desc: "filter, map, collect와 직접 사용하기 위한 Stream을 반환합니다." +support: + description: "JDK 11 (2018년 9월) 이후 사용 가능." diff --git a/translations/content/ko/strings/string-repeat.yaml b/translations/content/ko/strings/string-repeat.yaml new file mode 100644 index 0000000..dc61b74 --- /dev/null +++ b/translations/content/ko/strings/string-repeat.yaml @@ -0,0 +1,17 @@ +title: "String.repeat()" +oldApproach: "StringBuilder 루프" +modernApproach: "repeat()" +summary: "루프 없이 문자열을 n번 반복합니다." +explanation: "String.repeat(int)는 문자열을 자신과 n번 연결한 결과를 반환합니다. StringBuilder 루프를 완전히 대체합니다." +whyModernWins: +- icon: "📏" + title: "한 줄" + desc: "5줄의 StringBuilder 코드를 한 번의 호출로 대체합니다." +- icon: "⚡" + title: "최적화됨" + desc: "내부 구현이 대량 반복을 위해 최적화되어 있습니다." +- icon: "📖" + title: "명확한 의도" + desc: "repeat(3)은 목적을 즉시 전달합니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/strings/string-strip.yaml b/translations/content/ko/strings/string-strip.yaml new file mode 100644 index 0000000..6f313ed --- /dev/null +++ b/translations/content/ko/strings/string-strip.yaml @@ -0,0 +1,17 @@ +title: "String.strip() 대 trim()" +oldApproach: "trim()" +modernApproach: "strip()" +summary: "strip(), stripLeading(), stripTrailing()으로 유니코드 인식 공백 제거를 사용합니다." +explanation: "trim()은 U+0020(ASCII 제어 문자와 공백) 이하의 문자만 제거합니다. strip()은 Character.isWhitespace()를 사용하여 모든 유니코드 공백을 처리합니다." +whyModernWins: +- icon: "🌐" + title: "유니코드 정확" + desc: "모든 스크립트의 공백 문자를 처리합니다." +- icon: "🎯" + title: "방향성" + desc: "한쪽만 트리밍하기 위한 stripLeading()과 stripTrailing()." +- icon: "🛡️" + title: "버그 감소" + desc: "국제 텍스트에서 남겨진 공백이 없습니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/tooling/aot-class-preloading.yaml b/translations/content/ko/tooling/aot-class-preloading.yaml new file mode 100644 index 0000000..515526b --- /dev/null +++ b/translations/content/ko/tooling/aot-class-preloading.yaml @@ -0,0 +1,17 @@ +title: "AOT 클래스 사전 로딩" +oldApproach: "매번 콜드 스타트" +modernApproach: "AOT 캐시" +summary: "즉각적인 시작을 위해 클래스 로딩과 컴파일을 캐시합니다." +explanation: "AOT 클래스 사전 로딩은 훈련 실행에서 로드되고 링크된 클래스를 캐시합니다. 이후 실행에서 JVM은 클래스 로딩, 검증, 링크 단계를 건너뜁니다." +whyModernWins: +- icon: "⚡" + title: "더 빠른 시작" + desc: "클래스 로딩, 검증, 링크를 건너뜁니다." +- icon: "📦" + title: "캐시된 상태" + desc: "훈련 실행이 이상적인 클래스 상태를 캡처합니다." +- icon: "🔧" + title: "코드 변경 없음" + desc: "기존 애플리케이션과 함께 작동합니다 — JVM 플래그만 추가하면 됩니다." +support: + description: "JDK 25 LTS에서 표준 기능으로 사용 가능 (JEPs 514/515, 2025년 9월)." diff --git a/translations/content/ko/tooling/built-in-http-server.yaml b/translations/content/ko/tooling/built-in-http-server.yaml new file mode 100644 index 0000000..79eb279 --- /dev/null +++ b/translations/content/ko/tooling/built-in-http-server.yaml @@ -0,0 +1,17 @@ +title: "내장 HTTP 서버" +oldApproach: "외부 서버 / 프레임워크" +modernApproach: "jwebserver CLI" +summary: "Java 18에는 프로토타이핑과 파일 서빙을 위한 내장 최소 HTTP 서버가 포함되어 있습니다." +explanation: "JDK 18에는 jwebserver CLI 도구와 SimpleFileServer API를 통해 접근 가능한 간단하고 의존성 없는 HTTP 파일 서버가 추가되었습니다. 설치, 설정, 의존성이 필요 없습니다." +whyModernWins: +- icon: "🚀" + title: "설정 없음" + desc: "어느 디렉토리에서든 jwebserver를 실행합니다 — 설치, 설정, 의존성이 필요 없습니다." +- icon: "📦" + title: "JDK에 내장" + desc: "모든 JDK 18+ 설치에 포함되어 Java가 있는 모든 머신에서 항상 사용 가능합니다." +- icon: "🧪" + title: "프로토타이핑에 적합" + desc: "HTML, API, 프론트엔드 개발 테스트를 위해 정적 파일을 즉시 서빙합니다." +support: + description: "JDK 18 (2022년 3월) 이후 사용 가능" diff --git a/translations/content/ko/tooling/compact-object-headers.yaml b/translations/content/ko/tooling/compact-object-headers.yaml new file mode 100644 index 0000000..884aef2 --- /dev/null +++ b/translations/content/ko/tooling/compact-object-headers.yaml @@ -0,0 +1,17 @@ +title: "컴팩트 객체 헤더" +oldApproach: "128비트 헤더" +modernApproach: "64비트 헤더" +summary: "더 나은 메모리 밀도와 캐시 사용을 위해 객체 헤더 크기를 절반으로 줄입니다." +explanation: "컴팩트 객체 헤더는 객체당 오버헤드를 128비트에서 64비트로 줄입니다. 이는 힙 사용량을 줄이고 CPU 캐시 효율성을 향상시킵니다." +whyModernWins: +- icon: "📦" + title: "50% 작은 헤더" + desc: "객체당 16바이트 대신 8바이트." +- icon: "⚡" + title: "더 나은 캐시 사용" + desc: "더 많은 객체가 CPU 캐시 라인에 들어갑니다." +- icon: "📊" + title: "더 높은 밀도" + desc: "동일한 힙 크기에 더 많은 객체를 넣습니다." +support: + description: "JDK 25 LTS에서 확정 (JEP 519, 2025년 9월)." diff --git a/translations/content/ko/tooling/jfr-profiling.yaml b/translations/content/ko/tooling/jfr-profiling.yaml new file mode 100644 index 0000000..e7e4847 --- /dev/null +++ b/translations/content/ko/tooling/jfr-profiling.yaml @@ -0,0 +1,17 @@ +title: "프로파일링을 위한 JFR" +oldApproach: "외부 프로파일러" +modernApproach: "Java Flight Recorder" +summary: "외부 도구 없이 내장 Flight Recorder로 모든 Java 앱을 프로파일링합니다." +explanation: "Java Flight Recorder(JFR)는 모든 JDK에 내장된 저오버헤드 프로파일링 도구입니다. CPU, 메모리, GC, 스레드, I/O, 잠금, 커스텀 이벤트를 기록합니다." +whyModernWins: +- icon: "🆓" + title: "내장됨" + desc: "설치하거나 라이센스를 구입할 외부 프로파일러가 없습니다." +- icon: "⚡" + title: "낮은 오버헤드" + desc: "약 1% 성능 영향 — 프로덕션에서 안전합니다." +- icon: "📊" + title: "풍부한 이벤트" + desc: "CPU, 메모리, GC, 스레드, I/O, 잠금, 커스텀 이벤트." +support: + description: "JDK 9/11 이후 널리 사용 가능 (11에서 오픈소스화)" diff --git a/translations/content/ko/tooling/jshell-prototyping.yaml b/translations/content/ko/tooling/jshell-prototyping.yaml new file mode 100644 index 0000000..74a6403 --- /dev/null +++ b/translations/content/ko/tooling/jshell-prototyping.yaml @@ -0,0 +1,17 @@ +title: "프로토타이핑을 위한 JShell" +oldApproach: "파일 생성 + 컴파일 + 실행" +modernApproach: "jshell REPL" +summary: "파일을 만들지 않고 Java 표현식을 인터랙티브하게 시도합니다." +explanation: "JShell은 Java를 위한 Read-Eval-Print 루프입니다. 파일 없이 표현식을 테스트하고 API를 탐색하고 실험합니다. 탭 완성이 메서드와 매개변수를 발견하는 데 도움이 됩니다." +whyModernWins: +- icon: "⚡" + title: "즉각적인 피드백" + desc: "표현식을 입력하면 결과를 즉시 확인합니다." +- icon: "📝" + title: "파일 불필요" + desc: ".java 파일도, 컴파일 단계도 없습니다." +- icon: "🔍" + title: "API 탐색" + desc: "탭 완성이 메서드와 매개변수를 발견하는 데 도움이 됩니다." +support: + description: "JDK 9 (2017년 9월) 이후 널리 사용 가능" diff --git a/translations/content/ko/tooling/junit6-with-jspecify.yaml b/translations/content/ko/tooling/junit6-with-jspecify.yaml new file mode 100644 index 0000000..62ae43d --- /dev/null +++ b/translations/content/ko/tooling/junit6-with-jspecify.yaml @@ -0,0 +1,17 @@ +title: "JSpecify null 안전성을 갖춘 JUnit 6" +oldApproach: "어노테이션 없는 API" +modernApproach: "@NullMarked API" +summary: "JUnit 6은 JSpecify @NullMarked를 채택하여 전체 API에서 null 계약을 명시적으로 만듭니다." +explanation: "JUnit 5는 표준화된 null 가능성 어노테이션 없이 출시되어 어떤 매개변수가 null을 허용하는지가 불명확했습니다. JUnit 6의 JSpecify 채택은 이를 변경합니다: 전체 모듈이 @NullMarked로 표시되어 어노테이션 없는 타입이 non-null임을 의미합니다." +whyModernWins: +- icon: "📜" + title: "명시적 계약" + desc: "JUnit 6 모듈의 @NullMarked는 null 의미론을 API에 직접 문서화합니다." +- icon: "🛡️" + title: "컴파일 시점 안전성" + desc: "IDE와 분석기가 non-null이 예상되는 곳에 null이 전달될 때 경고하여 테스트 실행 전에 버그를 잡습니다." +- icon: "🌐" + title: "에코시스템 표준" + desc: "JSpecify는 Spring, Guava 등에서 채택되었습니다 — 전체 스택에서 일관된 null 의미론." +support: + description: "JUnit 6.0 (2025년 10월, Java 17+ 필요) 이후 사용 가능" diff --git a/translations/content/ko/tooling/multi-file-source.yaml b/translations/content/ko/tooling/multi-file-source.yaml new file mode 100644 index 0000000..4a232b2 --- /dev/null +++ b/translations/content/ko/tooling/multi-file-source.yaml @@ -0,0 +1,17 @@ +title: "다중 파일 소스 런처" +oldApproach: "먼저 모두 컴파일" +modernApproach: "소스 런처" +summary: "명시적 컴파일 단계 없이 다중 파일 프로그램을 실행합니다." +explanation: "Java 22 이상은 단일 파일 소스 프로그램을 실행할 때 참조된 소스 파일을 자동으로 컴파일할 수 있습니다. 소규모 다중 파일 프로그램을 스크립트처럼 실행합니다." +whyModernWins: +- icon: "🚀" + title: "설정 없음" + desc: "소규모 다중 파일 프로그램에 빌드 도구가 필요 없습니다." +- icon: "🔗" + title: "자동 해석" + desc: "참조된 클래스가 자동으로 찾아지고 컴파일됩니다." +- icon: "📝" + title: "스크립트 같은" + desc: "다중 파일 프로그램을 스크립트처럼 실행합니다." +support: + description: "JDK 22 (2024년 3월) 이후 사용 가능" diff --git a/translations/content/ko/tooling/single-file-execution.yaml b/translations/content/ko/tooling/single-file-execution.yaml new file mode 100644 index 0000000..3611e3f --- /dev/null +++ b/translations/content/ko/tooling/single-file-execution.yaml @@ -0,0 +1,17 @@ +title: "단일 파일 실행" +oldApproach: "2단계 컴파일" +modernApproach: "직접 실행" +summary: "javac 없이 단일 파일 Java 프로그램을 직접 실행합니다." +explanation: "Java 런처는 단일 소스 파일을 한 번의 명령으로 컴파일하고 실행할 수 있습니다. 빌드 도구 없이 짧은 프로그램, 스크립트, 예제를 빠르게 실행하는 데 이상적입니다." +whyModernWins: +- icon: "⚡" + title: "한 번의 명령" + desc: "java File.java가 한 단계로 컴파일하고 실행합니다." +- icon: "📝" + title: "스크립트 같은" + desc: ".java 파일을 실행 가능한 스크립트로 만들기 위해 shebang 줄을 추가합니다." +- icon: "🎓" + title: "학습 친화적" + desc: "초보자가 빌드 도구를 배우지 않고 즉시 코드를 실행할 수 있습니다." +support: + description: "JDK 11 (2018년 9월) 이후 널리 사용 가능" diff --git a/translations/strings/ko.yaml b/translations/strings/ko.yaml new file mode 100644 index 0000000..6e186e4 --- /dev/null +++ b/translations/strings/ko.yaml @@ -0,0 +1,80 @@ +site: + tagline: Java는 진화했습니다. 당신의 코드도 그럴 수 있습니다. + tagline_line1: Java는 진화했습니다. + tagline_line2: 당신의 코드도 그럴 수 있습니다. + description: 모던 Java 코드 스니펫 모음. 오래된 Java 패턴과 깔끔하고 모던한 대체 코드를 나란히 비교합니다. + heroSnippetCount: ✦ {{snippetCount}}개의 모던 패턴 · Java 8 → Java 25 + heroOld: 이전 + heroModern: 모던 + allComparisons: 모든 비교 + snippetsBadge: '{{snippetCount}}개 스니펫' +nav: + allPatterns: ← 모든 패턴 + toggleTheme: 테마 전환 + viewOnGitHub: GitHub에서 보기 + selectLanguage: 언어 선택 +breadcrumb: + home: 홈 +sections: + codeComparison: 코드 비교 + whyModernWins: 모던 방식이 더 나은 이유 + oldApproach: 이전 방식 + modernApproach: 모던 방식 + sinceJdk: JDK 버전 + difficulty: 난이도 + jdkSupport: JDK 지원 + howItWorks: 동작 원리 + relatedDocs: 관련 문서 + relatedPatterns: 관련 패턴 +filters: + show: '표시:' + all: 전체 +difficulty: + beginner: 초급 + intermediate: 중급 + advanced: 고급 +search: + placeholder: 스니펫 검색… + noResults: 검색 결과가 없습니다. + esc: ESC + searchTrigger: 검색… + navigate: 이동 + open: 열기 + close: 닫기 +cards: + old: 이전 + modern: 모던 + hoverHint: 마우스를 올려 모던 코드 보기 → + hoverHintRelated: 마우스를 올려 모던 코드 보기 ➜ + touchHint: 👆 탭하거나 스와이프 → +copy: + copy: 복사 + copied: 복사됨! +share: + label: 공유 +view: + expandAll: 모두 펼치기 + collapseAll: 모두 접기 +stats: + modernPatterns: 모던 패턴 + jdkVersions: 지원 JDK 버전 + categories: 카테고리 + linesOfPython: 필요한 Python 코드 줄 수 +footer: + tagline: Java는 진화했습니다. 당신의 코드도 그럴 수 있습니다. + madeWith: ❤️ 으로 만들었습니다 + and: 그리고 + inspiredBy: 영감을 받은 + viewOnGitHub: GitHub에서 보기 +copilot: + headline: GitHub Copilot으로 Java 코드베이스를 현대화하세요. + description: Copilot이 레거시 패턴을 모던 Java로 자동으로 마이그레이션하도록 도와줍니다. + appModernization: 앱 현대화 → + javaGuide: Java 가이드 → +support: + available: 사용 가능 + preview: 프리뷰 + experimental: 실험적 +untranslated: + notice: 이 페이지는 아직 {{localeName}}(으)로 번역되지 않았습니다. + viewInEnglish: 영어로 보기