<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Java on philipjkim</title><link>https://philipjkim.cc/tags/java/</link><description>Recent content in Java on philipjkim</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Wed, 04 Mar 2026 16:20:43 +0900</lastBuildDate><atom:link href="https://philipjkim.cc/tags/java/index.xml" rel="self" type="application/rss+xml"/><item><title>AI 시대의 Spring 기술 스택 재정비: 명시성을 되찾기 위한 선택들</title><link>https://philipjkim.cc/posts/20260304-spring-stack-for-ai-era/</link><pubDate>Wed, 04 Mar 2026 16:20:43 +0900</pubDate><guid>https://philipjkim.cc/posts/20260304-spring-stack-for-ai-era/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.6 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Claude Code 같은 AI 코딩 도구를 본격적으로 활용하기 시작하면서, 그동안 당연하게 쓰던 기술 스택에 대해 다시 생각하게 되었습니다. JPA의 dirty checking이 정말 편한 건지, Lombok 없이는 못 사는 건지, RestTemplate과 Retrofit이 뒤섞인 코드베이스가 과연 합리적인 건지.&lt;/p&gt;
&lt;p&gt;결론부터 말하면, &lt;strong&gt;AI가 생성한 코드를 사람이 빠르게 읽고 검증하려면 &amp;ldquo;마법(magic)&amp;ldquo;보다 &amp;ldquo;명시성(explicitness)&amp;ldquo;이 훨씬 중요하다&lt;/strong&gt;는 생각에 도달했습니다. 이 글에서는 그 관점에서 기존 Java/Spring 기술 스택의 각 영역을 하나씩 짚어봅니다.&lt;/p&gt;</description></item><item><title>WELC ver. 2026 Part 5: 의존성 깨기 기법 카탈로그</title><link>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-05/</link><pubDate>Wed, 04 Mar 2026 10:03:52 +0900</pubDate><guid>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-05/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.6 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="도입"&gt;도입&lt;/h2&gt;
&lt;p&gt;원서 Chapter 25는 25가지 의존성 깨기(Dependency-Breaking) 기법을 카탈로그 형태로 제시합니다. 각 기법은 &amp;ldquo;테스트 하네스에 코드를 넣기 위해 의존성을 어떻게 끊을 것인가&amp;quot;라는 질문에 대한 구체적인 답입니다.&lt;/p&gt;
&lt;p&gt;다만 일부 기법은 C/C++ 전용이거나, 현대 Java에서는 불필요합니다. Link Substitution, Text Redefinition, Replace Function with Function Pointer 같은 기법이 대표적입니다. 이 파트에서는 2026년 현재 Java 개발에서 특히 유용한 핵심 기법들을 선별하여 정리합니다.&lt;/p&gt;</description></item><item><title>WELC ver. 2026 Part 4: 대규모 코드 문제 다루기</title><link>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-04/</link><pubDate>Wed, 04 Mar 2026 10:03:51 +0900</pubDate><guid>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-04/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.6 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="도입"&gt;도입&lt;/h2&gt;
&lt;p&gt;레거시 시스템에서 가장 자주 마주치는 문제는 규모의 문제입니다. 한 클래스가 수천 줄, 한 메서드가 수백 줄인 코드는 현업에서 흔히 발견됩니다. 이런 코드는 읽기 어렵고, 테스트하기 어렵고, 변경하면 예상치 못한 곳에서 장애가 발생합니다.&lt;/p&gt;
&lt;p&gt;이번 글에서는 Michael Feathers의 &lt;em&gt;Working Effectively with Legacy Code&lt;/em&gt; 14~22장을 바탕으로, 대규모 코드 문제를 다루는 전략을 JDK 25 기준의 modern Java 코드로 살펴봅니다. SOLID 원칙 중 SRP, ISP, OCP의 실전 적용이 핵심입니다.&lt;/p&gt;</description></item><item><title>WELC ver. 2026 Part 3: 테스트 하네스에 코드 넣기</title><link>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-03/</link><pubDate>Wed, 04 Mar 2026 10:03:50 +0900</pubDate><guid>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-03/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.6 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="도입"&gt;도입&lt;/h2&gt;
&lt;p&gt;레거시 코드를 변경하려면 먼저 테스트를 작성해야 합니다. 하지만 테스트를 작성하려면 코드의 의존성을 깨야 합니다. 의존성을 깨려면 코드를 변경해야 하는데, 변경의 안전성을 보장해줄 테스트가 아직 없습니다.&lt;/p&gt;
&lt;p&gt;이것이 Feathers가 말하는 &amp;ldquo;레거시 코드의 딜레마&amp;quot;입니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In legacy code, the weights work against us. We have to pull out a piece to work with because we can&amp;rsquo;t easily test it in place.
— Michael Feathers, &lt;em&gt;Working Effectively with Legacy Code&lt;/em&gt; (2004)&lt;/p&gt;</description></item><item><title>WELC ver. 2026 Part 2: 안전한 코드 변경 패턴 — Sprout와 Wrap</title><link>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-02/</link><pubDate>Wed, 04 Mar 2026 10:03:49 +0900</pubDate><guid>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-02/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.6 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="도입"&gt;도입&lt;/h2&gt;
&lt;p&gt;Part 1에서 다룬 Legacy Code Change Algorithm의 5단계 중, 이번 글은 &amp;ldquo;변경 및 리팩터링&amp;rdquo; 단계에 해당하는 실전 패턴들을 다룹니다. Michael Feathers의 &lt;em&gt;Working Effectively with Legacy Code&lt;/em&gt; 6~8장에 등장하는 핵심 기법입니다.&lt;/p&gt;
&lt;p&gt;레거시 코드에 기능을 추가해야 하는데 시간이 없을 때, 기존 코드를 전면 리팩터링하는 것은 현실적이지 않습니다. 이때 사용할 수 있는 4가지 패턴이 있습니다.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;패턴&lt;/th&gt;
 &lt;th&gt;핵심 아이디어&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Sprout Method&lt;/td&gt;
 &lt;td&gt;새 기능을 별도 메서드로 추출&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Sprout Class&lt;/td&gt;
 &lt;td&gt;새 기능을 별도 클래스로 분리&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Wrap Method&lt;/td&gt;
 &lt;td&gt;기존 메서드를 감싸서 전후 동작 추가&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Wrap Class&lt;/td&gt;
 &lt;td&gt;Decorator 패턴으로 기존 클래스를 감싸기&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이 4가지 패턴의 공통점은 &lt;strong&gt;기존 코드를 가능한 한 건드리지 않으면서 새 기능을 추가&lt;/strong&gt;한다는 것입니다.&lt;/p&gt;</description></item><item><title>WELC ver. 2026 Part 1: 레거시 코드의 정의와 변경의 역학</title><link>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-01/</link><pubDate>Wed, 04 Mar 2026 10:03:48 +0900</pubDate><guid>https://philipjkim.cc/posts/20260304-working-effectively-with-legacy-code-2026-01/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.6 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="시리즈-소개"&gt;시리즈 소개&lt;/h2&gt;
&lt;p&gt;2004년 Michael Feathers가 출판한 &lt;em&gt;Working Effectively with Legacy Code&lt;/em&gt; (a.k.a. WELC)는 레거시 코드를 안전하게 변경하는 기법들을 체계적으로 정리한 명저입니다. 출판된 지 20년이 넘었지만, 이 책이 제시하는 원칙과 알고리즘은 여전히 유효합니다. 코드베이스가 노후화되는 속도보다 개발자가 이 책을 읽는 속도가 느린 것이 문제일 뿐입니다.&lt;/p&gt;
&lt;p&gt;원서의 예제는 Java 1.4/5, C++, C 시대의 코드입니다. 이 시리즈에서는 JDK 25 (2025년 9월 GA, LTS) 기준의 modern Java로 핵심 기법들을 재현합니다. Sealed class, record, text block, pattern matching 등 최신 언어 기능을 적극 활용하여, 원서의 기법이 오늘날 어떤 형태로 적용되는지 보여드리겠습니다.&lt;/p&gt;</description></item><item><title>STITCH 스택으로 JavaScript 없이 모던 웹앱 만들기</title><link>https://philipjkim.cc/posts/20260211-to-do-with-stitch-stack/</link><pubDate>Wed, 11 Feb 2026 10:24:50 +0900</pubDate><guid>https://philipjkim.cc/posts/20260211-to-do-with-stitch-stack/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Java 백엔드 개발자가 프론트엔드 프레임워크 없이도 인터랙티브한 웹 애플리케이션을 만들 수 있다면 어떨까요? 이 글에서는 &lt;strong&gt;STITCH 스택&lt;/strong&gt;으로 JavaScript 로직을 최소화한 To-Do 앱을 처음부터 끝까지 만들어봅니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;이 글은 &lt;a href="https://philipjkim.cc/posts/20260211-to-do-app-with-modern-go-stack/"&gt;GoTHIC 스택 가이드&lt;/a&gt;의 Java/Spring 버전입니다. Go 백엔드에 관심이 있다면 GoTHIC 편도 확인해보세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="stitch-스택이란"&gt;STITCH 스택이란&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;STITCH&lt;/strong&gt;는 &lt;strong&gt;S&lt;/strong&gt;(pring Boot) + &lt;strong&gt;T&lt;/strong&gt;(hymeleaf) + &lt;strong&gt;I&lt;/strong&gt;(nteractive) + &lt;strong&gt;T&lt;/strong&gt;(ailwindCSS + DaisyUI) + &lt;strong&gt;C&lt;/strong&gt;(omponents) + &lt;strong&gt;H&lt;/strong&gt;(TMX)의 축약어입니다. &amp;ldquo;꿰매다&amp;quot;라는 뜻 그대로, 서버 사이드 렌더링과 클라이언트 인터랙션을 자연스럽게 이어붙이는 풀스택 조합입니다.&lt;/p&gt;</description></item><item><title>Java: JEP 444, 485, 506, 519 설명</title><link>https://philipjkim.cc/posts/20260122-java-4-new-features/</link><pubDate>Thu, 22 Jan 2026 14:06:58 +0900</pubDate><guid>https://philipjkim.cc/posts/20260122-java-4-new-features/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="jep-444-virtual-threads-java-21---정식-릴리스"&gt;JEP 444: Virtual Threads (Java 21 - 정식 릴리스)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;개요:&lt;/strong&gt;
경량 스레드를 제공하여 수십만~수백만 개의 동시 작업을 효율적으로 처리할 수 있게 합니다. 플랫폼 스레드와 달리 OS 스레드를 1:1로 매핑하지 않습니다.&lt;/p&gt;
&lt;h3 id="예제-1-대량의-http-요청-처리"&gt;예제 1: 대량의 HTTP 요청 처리&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Before (Platform Threads):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 스레드 풀 사용 (제한된 스레드 수)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ExecutorService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Executors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newFixedThreadPool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IntStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapToObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://api.example.com/data/&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// HTTP 요청 시뮬레이션&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 결과 수집&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 100개 스레드로 10,000개 요청 처리 → 느림&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;After (Virtual Threads):&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>AI-Native 아키텍처: Java 25와 Spring Boot 4.0 시대의 에이전트 중심 개발 패러다임</title><link>https://philipjkim.cc/posts/20260122-ai-native-changes-for-java/</link><pubDate>Thu, 22 Jan 2026 09:30:28 +0900</pubDate><guid>https://philipjkim.cc/posts/20260122-ai-native-changes-for-java/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Google Gemini Pro Deep Research 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="서론-소프트웨어-개발의-새로운-지평"&gt;서론: 소프트웨어 개발의 새로운 지평&lt;/h2&gt;
&lt;p&gt;2026년을 맞이하며 엔터프라이즈 소프트웨어 개발 생태계는 전례 없는 전환점을 맞이하고 있습니다. 인공지능(AI), 특히 대규모 언어 모델(LLM)이 단순한 코딩 보조 도구를 넘어 자율적으로 소프트웨어를 설계, 구현, 수정하는 &amp;lsquo;에이전트(Agent)&amp;lsquo;로 진화함에 따라, 우리가 코드를 작성하는 방식과 시스템을 아키텍처링하는 원칙 자체가 근본적으로 재평가되고 있습니다. 과거 10년이 마이크로서비스와 클라우드 네이티브의 시대였다면, 향후 10년은 인간 개발자와 AI 에이전트가 공존하며 협업하는 &amp;lsquo;AI-Native&amp;rsquo; 시대가 될 것입니다.&lt;/p&gt;</description></item><item><title>Java to Go: #5. 프로젝트 구조와 생태계</title><link>https://philipjkim.cc/posts/20260121-java-to-go-guide-05/</link><pubDate>Wed, 21 Jan 2026 12:28:40 +0900</pubDate><guid>https://philipjkim.cc/posts/20260121-java-to-go-guide-05/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;지금까지 Go의 철학, 문법, 에러 처리, 동시성을 살펴봤다. 이제 실제 프로젝트를 시작하는 데 필요한 것들을 다룬다. Maven/Gradle에서 Go Modules로, JUnit에서 testing 패키지로, Spring에서 Go 라이브러리 조합으로 전환하는 방법을 알아보자.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-go-modules-기초"&gt;1. Go Modules 기초&lt;/h2&gt;
&lt;h3 id="gomod와-gosum"&gt;go.mod와 go.sum&lt;/h3&gt;
&lt;p&gt;Go 1.11부터 도입된 Go Modules가 공식 의존성 관리 시스템이다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 새 모듈 초기화&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir myproject &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; myproject
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go mod init github.com/username/myproject
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;생성된 &lt;code&gt;go.mod&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;module github.com/username/myproject

go 1.21
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;의존성을 추가하면:&lt;/p&gt;</description></item><item><title>Java to Go: #4. 동시성: Goroutine과 Channel</title><link>https://philipjkim.cc/posts/20260121-java-to-go-guide-04/</link><pubDate>Wed, 21 Jan 2026 12:28:36 +0900</pubDate><guid>https://philipjkim.cc/posts/20260121-java-to-go-guide-04/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Go의 동시성 모델은 Java와 근본적으로 다르다. &lt;code&gt;Thread&lt;/code&gt;, &lt;code&gt;synchronized&lt;/code&gt;, &lt;code&gt;ExecutorService&lt;/code&gt;에 익숙한 개발자라면 처음엔 낯설겠지만, Go의 방식이 얼마나 우아한지 금방 알게 될 것이다. &amp;ldquo;공유 메모리로 통신하지 말고, 통신으로 메모리를 공유하라&amp;quot;는 Go의 철학을 이해해보자.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-goroutine-경량-스레드"&gt;1. Goroutine: 경량 스레드&lt;/h2&gt;
&lt;h3 id="go-키워드-하나로-시작하는-동시성"&gt;go 키워드 하나로 시작하는 동시성&lt;/h3&gt;
&lt;p&gt;Java에서 새 스레드를 만들려면:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello from thread&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 또는 ExecutorService&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ExecutorService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Executors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newFixedThreadPool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello from thread pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go에서는 &lt;code&gt;go&lt;/code&gt; 키워드 하나면 된다:&lt;/p&gt;</description></item><item><title>Java to Go: #3. 에러 처리와 Null 안전성</title><link>https://philipjkim.cc/posts/20260121-java-to-go-guide-03/</link><pubDate>Wed, 21 Jan 2026 12:28:33 +0900</pubDate><guid>https://philipjkim.cc/posts/20260121-java-to-go-guide-03/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Java 개발자가 Go를 배울 때 가장 큰 패러다임 전환이 필요한 부분이 에러 처리다. &lt;code&gt;try-catch&lt;/code&gt;에 익숙한 우리에게 &lt;code&gt;if err != nil&lt;/code&gt;의 반복은 처음엔 원시적으로 느껴진다. 하지만 이 방식에는 명확한 철학이 있다. 이번 편에서 그 철학을 이해하고, Go 방식의 에러 처리에 익숙해져 보자.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-java의-exception-vs-go의-error"&gt;1. Java의 Exception vs Go의 error&lt;/h2&gt;
&lt;h3 id="근본적인-차이"&gt;근본적인 차이&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Java:&lt;/strong&gt; 예외는 &amp;ldquo;특별한 상황&amp;quot;이다. 정상 흐름과 분리되어 throw/catch로 처리된다.&lt;/p&gt;</description></item><item><title>Java to Go: #2. 문법 전환 가이드: Java 코드를 Go로 옮기기</title><link>https://philipjkim.cc/posts/20260121-java-to-go-guide-02/</link><pubDate>Wed, 21 Jan 2026 12:28:30 +0900</pubDate><guid>https://philipjkim.cc/posts/20260121-java-to-go-guide-02/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Part 1에서 Go의 철학과 언제 Go를 선택해야 하는지 살펴봤다. 이제 실제 코드 레벨에서 Java와 Go가 어떻게 다른지 1:1로 비교해보자. Java 문법에 익숙한 개발자가 Go 코드를 읽고 쓸 수 있도록 핵심 차이점을 정리한다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-변수-선언과-타입-시스템"&gt;1. 변수 선언과 타입 시스템&lt;/h2&gt;
&lt;h3 id="기본-변수-선언"&gt;기본 변수 선언&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Java:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;14159&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Go:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.14159&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go에서는 타입이 변수명 뒤에 온다. 처음엔 어색하지만, 복잡한 타입 선언에서는 오히려 읽기 쉽다.&lt;/p&gt;</description></item><item><title>Java to Go: #1. Go 첫인상: 철학과 패러다임의 차이</title><link>https://philipjkim.cc/posts/20260121-java-to-go-guide-01/</link><pubDate>Wed, 21 Jan 2026 12:28:27 +0900</pubDate><guid>https://philipjkim.cc/posts/20260121-java-to-go-guide-01/</guid><description>&lt;p&gt;&lt;em&gt;이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Java를 수년간 써온 개발자가 Go를 처음 접하면 당혹스럽다. &amp;ldquo;왜 이렇게 만들었지?&amp;ldquo;라는 생각이 끊이지 않는다. 이 글에서는 Go의 설계 철학을 이해하고, Java에서 Go로의 전환이 언제 적절한지 판단할 수 있는 기준을 제시한다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-go의-설계-철학-less-is-more"&gt;1. Go의 설계 철학: &amp;ldquo;Less is more&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Go는 2009년 Google에서 Robert Griesemer, Rob Pike, Ken Thompson이 만들었다. 세 사람 모두 수십 년 경력의 시스템 프로그래머로, C++의 복잡성에 지쳐 있었다. Go의 탄생 배경 자체가 &amp;ldquo;복잡함에 대한 반발&amp;quot;이다.&lt;/p&gt;</description></item><item><title>번역글: ExecutorService invokeAll 과 가상 스레드 사용하기</title><link>https://philipjkim.cc/posts/20250710-using-executor-service-invoke-all-with-virtual-threads/</link><pubDate>Thu, 10 Jul 2025 09:41:55 +0900</pubDate><guid>https://philipjkim.cc/posts/20250710-using-executor-service-invoke-all-with-virtual-threads/</guid><description>&lt;p&gt;원문: &lt;a href="https://davidvlijmincx.com/posts/loom/invoke-all-with-virtual-threads/"&gt;https://davidvlijmincx.com/posts/loom/invoke-all-with-virtual-threads/&lt;/a&gt; (Translated by Google Gemini)&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="서론"&gt;서론&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;invokeAll&lt;/code&gt; 은 &lt;code&gt;ExecutorService&lt;/code&gt; 의 메서드로, 여러 제출된 작업을 동시에 시작합니다. &lt;code&gt;ExecutorService&lt;/code&gt; 는 스레드 풀에서 플랫폼 스레드를 사용하여 제출된 작업을 실행합니다. 이 비싸고 리소스 집약적인 플랫폼 스레드를 사용하는 대신, 가상 스레드를 사용하여 &lt;code&gt;ExecutorService&lt;/code&gt; 에 제출된 작업을 실행할 수도 있습니다. 이 글에서는 &lt;code&gt;invokeAll&lt;/code&gt; 메서드를 가상 스레드 (virtual threads), 구조화된 동시성 (structured concurrency) 및 플랫폼 스레드 (platform threads) 와 함께 구현하는 모든 방법을 다룰 것입니다.&lt;/p&gt;
&lt;h2 id="가상-스레드를-사용한-invokeall"&gt;가상 스레드를 사용한 &lt;code&gt;invokeAll&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;우리가 살펴볼 첫 번째 예제는 가상 스레드 (virtual threads) 를 사용합니다. 각 작업에 대해 가상 스레드를 생성하는 Executor 를 생성하는 try-with-resources 문이 있습니다. 7행에서 &lt;code&gt;invokeAll&lt;/code&gt; 메서드가 작업 목록과 함께 호출됩니다.&lt;/p&gt;</description></item><item><title>번역글: Java 스레드 성능 vs. 가상 스레드 vs. Kotlin 코루틴</title><link>https://philipjkim.cc/posts/20250630-java-thread-vs-virtual-thread-vs-kotlin-coroutine/</link><pubDate>Mon, 30 Jun 2025 14:40:25 +0900</pubDate><guid>https://philipjkim.cc/posts/20250630-java-thread-vs-virtual-thread-vs-kotlin-coroutine/</guid><description>&lt;p&gt;원문 (아래 리스트 순으로 번역되어 있음. Translated by Google Gemini) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.behzadian.info/2024-05-03/Java-Thread-Performance-vs.-Virtual-Threads"&gt;https://blog.behzadian.info/2024-05-03/Java-Thread-Performance-vs.-Virtual-Threads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.behzadian.info/2024-05-06/Java-Virtual-Threads-Performance-vs.-Kotlin-Coroutines"&gt;https://blog.behzadian.info/2024-05-06/Java-Virtual-Threads-Performance-vs.-Kotlin-Coroutines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.behzadian.info/2024-05-26/Java-Thread-Performance-vs.-Virtual-Threads-Part-2"&gt;https://blog.behzadian.info/2024-05-26/Java-Thread-Performance-vs.-Virtual-Threads-Part-2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="java-스레드-vs-가상-스레드-pt1"&gt;Java 스레드 vs. 가상 스레드 Pt.1&lt;/h2&gt;
&lt;p&gt;면접 중에 한 면접관이 저에게 Java 스레드와 가상 스레드의 성능 차이에 대해 물었습니다. 저는 가상 스레드가 실제로는 JVM이 처리하는 경량 스레드이기 때문에 더 빠를 것이라고 답했지만, 둘 사이의 정확한 성능 차이가 궁금했습니다. 그래서 가상 스레드의 성능 향상을 확인하기 위해 간단한 벤치마크를 수행했습니다.&lt;/p&gt;
&lt;p&gt;이것은 매우 간단한 테스트입니다. 저는 매우 많은 수의 스레드와 가상 스레드를 생성하며, 각각이 완료되는 데 5초가 걸리도록 했습니다. 그런 다음 앱 실행 시간을 계산합니다. 이 벤치마크에 사용한 Java 코드는 다음과 같습니다:&lt;/p&gt;</description></item><item><title>번역글: Java 23: 성능 및 생산성 향상 (2024년 9월)</title><link>https://philipjkim.cc/posts/20250625-java-23-new-features/</link><pubDate>Wed, 25 Jun 2025 15:27:23 +0900</pubDate><guid>https://philipjkim.cc/posts/20250625-java-23-new-features/</guid><description>&lt;p&gt;원문: &lt;a href="https://www.hungrycoders.com/blog/java-9-23-unleashed-the-developers-cheat-sheet-to-modern-java"&gt;https://www.hungrycoders.com/blog/java-9-23-unleashed-the-developers-cheat-sheet-to-modern-java&lt;/a&gt; (Translated by Google Gemini)&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="주요-기능"&gt;주요 기능&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;패턴, instanceof, switch에서의 Primitive Types (미리보기): 패턴 매칭을 기본 타입으로 확장하여 상용구 코드(boilerplate code)를 줄입니다.&lt;/li&gt;
&lt;li&gt;Scoped Values (세 번째 미리보기): 제한된 수명을 가진 변수를 도입하여 메모리 관리를 개선합니다.&lt;/li&gt;
&lt;li&gt;Structured Concurrency (세 번째 미리보기): 구조화된 API를 통해 스레드 관리를 강화하여 동시성 처리를 단순화합니다.&lt;/li&gt;
&lt;li&gt;Markdown Documentation Comments: Javadoc에 Markdown 지원을 추가하여 문서의 가독성을 향상시킵니다.&lt;/li&gt;
&lt;li&gt;ZGC를 기본 가비지 컬렉터로: 세대별 Z Garbage Collector (ZGC)가 기본값으로 설정되어 성능과 응답성을 향상시킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="개요-요약"&gt;개요 요약&lt;/h2&gt;
&lt;p&gt;Java 23은 성능 및 개발자 생산성 향상 추세를 이어갑니다. 기본 타입을 지원하는 패턴 매칭을 개선하고, 더 안전한 메모리 관리를 위해 Scoped Values를 도입하며, 구조화된 API를 통해 동시성을 단순화합니다. Markdown 문서화는 개발자 경험을 개선하고, ZGC가 기본 컬렉터가 되어 더 나은 성능과 낮은 지연 시간을 보장합니다.&lt;/p&gt;</description></item></channel></rss>