<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>spring boot &amp;amp; webflux &amp;amp; devOps</title>
    <link>https://ride-wind.tistory.com/</link>
    <description>Spring boot 와 webflux 그리고 devOps 에 관심 많은 개발자 입니다.</description>
    <language>ko</language>
    <pubDate>Thu, 9 Apr 2026 09:39:45 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>바람을타고2</managingEditor>
    <item>
      <title>Toby + Spring Boot 4 + Claude Code 1</title>
      <link>https://ride-wind.tistory.com/165</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Toby 님이 Claude Code 와 Spring boot4 와 Nex.js 를 이용하여 apple reminder app 을 만드는 live 강좌 메모 입니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github : &lt;a href=&quot;https://github.com/tobyilee/tobyreminder&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/tobyilee/tobyreminder&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775348777619&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - tobyilee/tobyreminder&quot; data-og-description=&quot;Contribute to tobyilee/tobyreminder development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/tobyilee/tobyreminder&quot; data-og-url=&quot;https://github.com/tobyilee/tobyreminder&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dyhfZx/dJMb8YXL3Nx/iSkkzqJpiNsEV0uygKkHTK/img.png?width=1200&amp;amp;height=600&amp;amp;face=958_140_1019_207,https://scrap.kakaocdn.net/dn/dHnSDZ/dJMb8Z3rQat/Ow9OalUFdO15XyPIQNzgHk/img.png?width=1200&amp;amp;height=600&amp;amp;face=958_140_1019_207&quot;&gt;&lt;a href=&quot;https://github.com/tobyilee/tobyreminder&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/tobyilee/tobyreminder&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dyhfZx/dJMb8YXL3Nx/iSkkzqJpiNsEV0uygKkHTK/img.png?width=1200&amp;amp;height=600&amp;amp;face=958_140_1019_207,https://scrap.kakaocdn.net/dn/dHnSDZ/dJMb8Z3rQat/Ow9OalUFdO15XyPIQNzgHk/img.png?width=1200&amp;amp;height=600&amp;amp;face=958_140_1019_207');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - tobyilee/tobyreminder&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to tobyilee/tobyreminder development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토비의&amp;nbsp;스프링&amp;nbsp;&amp;nbsp;:&amp;nbsp;클로드&amp;nbsp;코드를&amp;nbsp;이용해&amp;nbsp;스프링&amp;nbsp;앱&amp;nbsp;개발하기&amp;nbsp;-&amp;nbsp;Live&amp;nbsp;1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gdg4DBcakIg&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=gdg4DBcakIg&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=gdg4DBcakIg&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/vcV3Q/dJMb8PGwGB8/uYLv1KSzlhtWFswgzkNB31/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/Ye9JU/dJMb8SXykrC/dcHiA0ikpPDOUtGSejNSN0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;클로드 코드를 이용해 스프링 앱 개발하기 - Live 1&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/gdg4DBcakIg&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;~/.cluade 초기화&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apple Reminder App 개발&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Baceknd : Spring Boot 4.0.x&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Frontend : Nextjs&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mobile : RN(React Native)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ghostty 고스티 터미널&lt;/p&gt;
&lt;pre id=&quot;code_1775349516174&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install --cask ghostty&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;default font 가 구려서 변경&lt;/p&gt;
&lt;pre id=&quot;code_1775350377547&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir -p ~/.config/ghostty
sudo vi ~/.config/ghostty/config&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1775350393346&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;font-family = JetBrainsMono Nerd Font
font-size = 14
font-feature = liga
font-family-fallback = Noto Sans CJK KR&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ghostty Terminal 의 장단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압도적인&amp;nbsp;성능&amp;nbsp;(GPU&amp;nbsp;가속):&amp;nbsp;GPU를&amp;nbsp;사용하여&amp;nbsp;렌더링하기&amp;nbsp;때문에&amp;nbsp;대량의&amp;nbsp;텍스트가&amp;nbsp;출력되거나&amp;nbsp;복잡한&amp;nbsp;애니메이션이&amp;nbsp;실행될&amp;nbsp;때도&amp;nbsp;CPU&amp;nbsp;점유율이&amp;nbsp;낮고&amp;nbsp;반응&amp;nbsp;속도가&amp;nbsp;매우&amp;nbsp;빠릅니다.&lt;br /&gt;내장된&amp;nbsp;멀티플렉싱:&amp;nbsp;별도의&amp;nbsp;tmux&amp;nbsp;없이도&amp;nbsp;탭과&amp;nbsp;분할&amp;nbsp;화면(Split&amp;nbsp;Pane)&amp;nbsp;기능을&amp;nbsp;강력하게&amp;nbsp;지원합니다.&lt;br /&gt;설정의&amp;nbsp;유연성:&amp;nbsp;텍스트&amp;nbsp;기반&amp;nbsp;설정&amp;nbsp;파일을&amp;nbsp;지원하여&amp;nbsp;버전&amp;nbsp;관리가&amp;nbsp;용이하며,&amp;nbsp;세밀한&amp;nbsp;커스터마이징이&amp;nbsp;가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows&amp;nbsp;미지원:&amp;nbsp;현재는&amp;nbsp;macOS와&amp;nbsp;Linux&amp;nbsp;위주로&amp;nbsp;개발되고&amp;nbsp;있어&amp;nbsp;Windows&amp;nbsp;사용자는&amp;nbsp;WSL&amp;nbsp;등을&amp;nbsp;통한&amp;nbsp;우회&amp;nbsp;사용이&amp;nbsp;필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래처럼 gemini cli 와 일반 터미널을 split 하여 사용할 수 있습니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3002&quot; data-origin-height=&quot;1498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y0WVZ/dJMcahYfehA/SGidKUngBOwRl4LBdWomkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y0WVZ/dJMcahYfehA/SGidKUngBOwRl4LBdWomkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y0WVZ/dJMcahYfehA/SGidKUngBOwRl4LBdWomkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy0WVZ%2FdJMcahYfehA%2FSGidKUngBOwRl4LBdWomkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3002&quot; height=&quot;1498&quot; data-origin-width=&quot;3002&quot; data-origin-height=&quot;1498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래처럼 질문하여, build 툴을 정함&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;782&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4tNJO/dJMcaiiycFQ/5dd7TNwreMhhIgzYIiuxlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4tNJO/dJMcaiiycFQ/5dd7TNwreMhhIgzYIiuxlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4tNJO/dJMcaiiycFQ/5dd7TNwreMhhIgzYIiuxlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4tNJO%2FdJMcaiiycFQ%2F5dd7TNwreMhhIgzYIiuxlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1304&quot; height=&quot;782&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;782&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 는 아직 25가 없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토비님왈 claude opus 4.6 model 이 java 25 를 학습하지 않아 이런것 같다고 추측 -&amp;gt; Java 17 (Recommended) 상태 임&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pmgLM/dJMcaadLUpA/tJM1hsoTvNvOq7gryc4YG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pmgLM/dJMcaadLUpA/tJM1hsoTvNvOq7gryc4YG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pmgLM/dJMcaadLUpA/tJM1hsoTvNvOq7gryc4YG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpmgLM%2FdJMcaadLUpA%2FtJM1hsoTvNvOq7gryc4YG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;982&quot; height=&quot;596&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외 패키지명도 물어보고, 샘플 엔티티/API 도 포함할 것인지 물어봄&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취소하고, instrucation 을 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;spring initializr&lt;/b&gt; 를 이용하여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot 최신버전&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA/H2/Lombok을 사용하는 프로젝트를&amp;nbsp; 생성해줘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Gradle Kotlin DSL&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- package : toby.ai.tobyreminder&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- project name : tobyreminder&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 프로젝트 생성은 자주 하니, skills 를 만들어 재사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;## Skill&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전에 했던 작업을 똑같이 반복할 때, 만들어 놓고 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spring initializr 이용하여 프로젝트 생성 등..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 21 을 사용하여, Java 25 를 사용하도록 다시 수정하도록 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context7 은 이제 잘 안씀&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build 해서 loading 해 보는데 port 8080 충돌로 실패함. ai 가 알아서 기존 사용하던 process 죽여도 되는지 물어봄&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;claude code cli 에서 idea . 으로 ide 를 실행함 신기...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;accept edits on :&amp;nbsp; project 내 파일은 ai 가 수정가능 끄면, 물어봄&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/ide 명령어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-sheets-root=&quot;1&quot;&gt;파일 수정 후 diff 별 accept 를 ide 에서 할 수 있음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-sheets-root=&quot;1&quot;&gt;ai 개발 방법&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-sheets-root=&quot;1&quot;&gt;prompt -&amp;gt; 개발 ( 간단한거에 사용)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-sheets-root=&quot;1&quot;&gt;prompt -&amp;gt; (code) plan -&amp;gt; 개발&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-sheets-root=&quot;1&quot;&gt;promt -&amp;gt; prd.md (기능, 아키텍처, 데이터구조...) -&amp;gt; 개발&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-sheets-root=&quot;1&quot;&gt;prompt -&amp;gt; spec (기능) -&amp;gt; (implmentation) plan -&amp;gt; task -&amp;gt; 단계적 개발 ( SDD )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI Coding Assistant</category>
      <category>claude code</category>
      <category>spring boot 4</category>
      <category>TOBY</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/165</guid>
      <comments>https://ride-wind.tistory.com/165#entry165comment</comments>
      <pubDate>Sun, 5 Apr 2026 09:36:35 +0900</pubDate>
    </item>
    <item>
      <title>JEP 485: Stream Gatherers</title>
      <link>https://ride-wind.tistory.com/164</link>
      <description>&lt;h3 data-end=&quot;699&quot; data-start=&quot;680&quot; data-ke-size=&quot;size23&quot;&gt;1. Gatherer란?&lt;/h3&gt;
&lt;p data-end=&quot;699&quot; data-start=&quot;680&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;Gatherer는 스트림의 요소를 &amp;ldquo;&lt;/span&gt;&lt;b&gt;수집(gather)&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;rdquo;하여, &lt;/span&gt;&lt;b&gt;상태(state)를 유지하면서 0개 이상 결과를 방출&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;하는 &lt;b&gt;중간 연산 구성요소&lt;/b&gt; 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;791&quot; data-start=&quot;789&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;857&quot; data-start=&quot;793&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;809&quot; data-start=&quot;793&quot;&gt;map보다 &lt;b&gt;강력&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;830&quot; data-start=&quot;810&quot;&gt;collect보다 &lt;b&gt;유연&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;857&quot; data-start=&quot;831&quot;&gt;중간 연산이지만 &lt;b&gt;상태를 가질 수&lt;/b&gt; 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;208&quot; data-start=&quot;178&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;208&quot; data-start=&quot;178&quot; data-ke-size=&quot;size26&quot;&gt;2. Stream Gatherers란 무엇인가?&lt;/h2&gt;
&lt;h3 data-end=&quot;236&quot; data-start=&quot;210&quot; data-ke-size=&quot;size23&quot;&gt;2-1. 기존 Stream API의 한계&lt;/h3&gt;
&lt;p data-end=&quot;274&quot; data-start=&quot;238&quot; data-ke-size=&quot;size16&quot;&gt;기존 Stream API는 다음 두 가지 연산만 제공했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;420&quot; data-start=&quot;276&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;346&quot; data-start=&quot;276&quot;&gt;중간 연산 (intermediate)&lt;br /&gt;map, filter, flatMap 등 &amp;rarr; 1:1 변환&lt;/li&gt;
&lt;li data-end=&quot;420&quot; data-start=&quot;347&quot;&gt;종단 연산 (terminal)&lt;br /&gt;forEach, reduce, collect 등 &amp;rarr; Stream 종료&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;453&quot; data-start=&quot;422&quot; data-ke-size=&quot;size16&quot;&gt;하지만 다음과 같은 패턴은 &lt;b&gt;표현하기 어려웠습니다&lt;/b&gt;.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;600&quot; data-start=&quot;455&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;497&quot; data-start=&quot;455&quot;&gt;N개의 요소를 &lt;b&gt;묶어서&lt;/b&gt; 처리 (&lt;b&gt;windowing, batching&lt;/b&gt;)&lt;/li&gt;
&lt;li data-end=&quot;528&quot; data-start=&quot;498&quot;&gt;이전 요소의 상태를 &lt;b&gt;기억하며&lt;/b&gt; 다음 요소 처리&lt;/li&gt;
&lt;li data-end=&quot;557&quot; data-start=&quot;529&quot;&gt;1개의 입력 &amp;rarr; &lt;b&gt;0개 또는 여러 개 출력&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;600&quot; data-start=&quot;558&quot;&gt;flatMap + mutable state 조합 없이 상태 기반 변환&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;  이 공백을 메우기 위해 등장한 것이 &lt;b&gt;Stream Gatherers&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;Stream Pipeline 에서 활용&lt;/p&gt;
&lt;p data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;source&amp;nbsp;&amp;rarr;&amp;nbsp;intermediate(map/filter)&amp;nbsp;&amp;rarr;&amp;nbsp;&lt;b&gt;gather(gatherer)&lt;/b&gt;&amp;nbsp;&amp;rarr;&amp;nbsp;intermediate&amp;nbsp;&amp;rarr;&amp;nbsp;terminal&lt;/p&gt;
&lt;p data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;649&quot; data-start=&quot;602&quot; data-ke-size=&quot;size26&quot;&gt;3. Stream Gathers 를 image 와 diagram 으로 표현&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vgvs2/dJMcabixswA/X2wY1Zl1KPdI8MADtK3lG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vgvs2/dJMcabixswA/X2wY1Zl1KPdI8MADtK3lG1/img.png&quot; data-alt=&quot;https://medium.com/@umeshcapg/the-gathering-revolution-jdk-24s-stream-gatherers-explained-e8727dee6877&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vgvs2/dJMcabixswA/X2wY1Zl1KPdI8MADtK3lG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvgvs2%2FdJMcabixswA%2FX2wY1Zl1KPdI8MADtK3lG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1378&quot; height=&quot;1000&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://medium.com/@umeshcapg/the-gathering-revolution-jdk-24s-stream-gatherers-explained-e8727dee6877&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2022&quot; data-origin-height=&quot;1358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnnNXV/dJMcajng7xV/AR725eETgBTrITOvT4k2ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnnNXV/dJMcajng7xV/AR725eETgBTrITOvT4k2ak/img.png&quot; data-alt=&quot;generated by Gemni&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnnNXV/dJMcajng7xV/AR725eETgBTrITOvT4k2ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnnNXV%2FdJMcajng7xV%2FAR725eETgBTrITOvT4k2ak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2022&quot; height=&quot;1358&quot; data-origin-width=&quot;2022&quot; data-origin-height=&quot;1358&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;generated by Gemni&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;연산자 사용 예&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot; data-spm-anchor-id=&quot;a2ty_o01.29997173.0.i12.468e5171dn9TKB&quot; data-ke-size=&quot;size23&quot;&gt;Gatherers.windowFixed() example&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Input:&amp;nbsp;&amp;nbsp;&amp;nbsp;[1]---[2]---[3]---[4]---[5]---[6]---[7]---[8]---[9]---&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Gatherer:&amp;nbsp;[---&amp;nbsp;windowFixed(3)&amp;nbsp;---]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Output:&amp;nbsp;&amp;nbsp;[1,2,3]------[4,5,6]------[7,8,9]------------------&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766984882920&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// windowFixed(3)
List&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; windows = Stream.of(1, 2, 3, 4, 5, 6, 7, 8)
  .gather(Gatherers.windowFixed(3))
  .toList();

// 결과: [[1, 2, 3], [4, 5, 6], [7, 8]]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot; data-spm-anchor-id=&quot;a2ty_o01.29997173.0.i14.468e5171dn9TKB&quot; data-ke-size=&quot;size23&quot;&gt;Gatherers.windowSliding() example&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Input:&amp;nbsp;&amp;nbsp;&amp;nbsp;[1]---[2]---[3]---[4]---[5]---[6]---[7]---[8]---[9]---&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Gatherer:&amp;nbsp;[---&amp;nbsp;windowSliding(3)&amp;nbsp;---]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Output:&amp;nbsp;&amp;nbsp;[1,2,3]--[2,3,4]--[3,4,5]--[4,5,6]--[5,6,7]--[6,7,8]...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연속된 숫자가 overlap 되는 차이가 있음&amp;nbsp; windowSliding(3) vs windowFixed(3)&lt;/p&gt;
&lt;pre id=&quot;code_1766984921327&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// windowSliding(3)
List&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; slidingWindows = Stream.of(1, 2, 3, 4, 5)
  .gather(Gatherers.windowSliding(3))
  .toList();

// 결과: [[1, 2, 3], [2, 3, 4], [3, 4, 5]]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot; data-spm-anchor-id=&quot;a2ty_o01.29997173.0.i16.468e5171dn9TKB&quot; data-ke-size=&quot;size23&quot;&gt;Gatherers.scan(Integer::sum) example&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Input:&amp;nbsp;&amp;nbsp;&amp;nbsp;[1]---[2]---[3]---[4]---[5]---[6]---&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Gatherer:&amp;nbsp;[---&amp;nbsp;scan(Integer::sum)&amp;nbsp;---]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Output:&amp;nbsp;&amp;nbsp;[1]---[3]---[6]---[10]--[15]--[21]--&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1st : 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2nd : 1+2 = 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3rd : 1+2+3 = 6&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4th : 1+2+3+4 = 10&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;...&lt;/p&gt;
&lt;pre id=&quot;code_1766988459661&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  List&amp;lt;Integer&amp;gt; cumulativeSum = Stream.of(1, 2, 3, 4, 5, 6)
      .gather(Gatherers.scan(() -&amp;gt; 0, Integer::sum))
      .toList();

  System.out.println(&quot;출력: &quot; + cumulativeSum);
  // 결과: [1, 3, 6, 10, 15, 21]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Gatherers.doubler example&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Input:&amp;nbsp;&amp;nbsp;&amp;nbsp;[1]---[2]---[3]---&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Gatherer:&amp;nbsp;[---&amp;nbsp;doubler&amp;nbsp;---]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Output:&amp;nbsp;&amp;nbsp;[2]---[4]---[6]--&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1766989614647&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Gatherer doubler 정의
public class doubler {
  public static final Gatherer&amp;lt;Integer, Void, Integer&amp;gt; doubler =
      ofSequential(
          (state, element, downstream) -&amp;gt; downstream.push(element * 2)
      ); // state 는 불필요하여 사용하지 않음
}


// doubler 사용
List&amp;lt;Integer&amp;gt; doublerList =
      Stream.of(1, 2, 3)
          .gather(doubler)
          .toList();

System.out.println(&quot;doubler : 출력: &quot; + doublerList);
// doubler : 출력: [2, 4, 6]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Gatherer&amp;nbsp; distinctBy 예&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Input&amp;nbsp;Stream:&amp;nbsp;&amp;nbsp;[foo]---[bar]---[baz]---[quux]---&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Gatherer:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[---&amp;nbsp;distinctBy(String::length)&amp;nbsp;---]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Output&amp;nbsp;Stream:&amp;nbsp;[foo]-----------------[quux]-------&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 예1, distinct 정의&lt;/p&gt;
&lt;pre id=&quot;code_1766988906039&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class distinctby {
  static &amp;lt;T, U&amp;gt; Gatherer&amp;lt;T, ?, T&amp;gt; distinctBy(Function&amp;lt;? super T, ? extends U&amp;gt; keyExtractor) {
    Objects.requireNonNull(keyExtractor, &quot;keyExtractor must not be null&quot;);

    return Gatherer.ofSequential(
        () -&amp;gt; new HashSet&amp;lt;U&amp;gt;(),
        Gatherer.Integrator.ofGreedy((seen, element, downstream) -&amp;gt; {
          U key = keyExtractor.apply(element); // 키 추출
          if (seen.add(key)) { // 처음 보는 키인가?
            return downstream.push(element); // 처음 이면 출력
          }
          return true;
        })
    );
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 예&lt;/p&gt;
&lt;pre id=&quot;code_1766989580958&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 사용 예 1
var distinctList = Stream.of(&quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;, &quot;quux&quot;)
      .gather(distinctBy(String::length))
      .toList();

System.out.println(&quot;distinctBy : 출력: &quot; + distinctList);
// distinctBy : 출력: [foo, quux]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 예2,&amp;nbsp; 나이별 1명 씩 distinct&lt;/p&gt;
&lt;pre id=&quot;code_1766989002397&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 사용 예2 : 나이별 1명 씩 distinct
record User(String id, String name, int age) {}

List&amp;lt;User&amp;gt; users = List.of(
    new User(&quot;1&quot;, &quot;Alice&quot;, 25),
    new User(&quot;2&quot;, &quot;Bob&quot;, 30),
    new User(&quot;3&quot;, &quot;Charlie&quot;, 25),
    new User(&quot;4&quot;, &quot;Diana&quot;, 35)
);

List&amp;lt;User&amp;gt; uniqueByAge = users.stream()
    .gather(distinctBy(User::age))
    .toList();

System.out.println(&quot;uniqueByAge : 출력: &quot; + uniqueByAge);
// uniqueByAge : 출력: [User[id=1, name=Alice, age=25], 
//                     User[id=2, name=Bob, age=30], 
//                     User[id=4, name=Diana, age=35]]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예제를 확인할 수 있는 github repository 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github : &lt;a href=&quot;https://github.com/gwagdalf/gather-example&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/gwagdalf/gather-example&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767008498014&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - gwagdalf/gather-example: Code example of Java 24&amp;rsquo;s Gather Stream API&quot; data-og-description=&quot;Code example of Java 24&amp;rsquo;s Gather Stream API. Contribute to gwagdalf/gather-example development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/gwagdalf/gather-example&quot; data-og-url=&quot;https://github.com/gwagdalf/gather-example&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bTVFv4/hyZQsoRnUC/xAaGM9a2H3p5x0fGu04Nv1/img.png?width=1200&amp;amp;height=600&amp;amp;face=993_110_1114_243,https://scrap.kakaocdn.net/dn/Vn248/hyZQzO2iCu/UYCilKMuJN83P2AUROYUHK/img.png?width=1200&amp;amp;height=600&amp;amp;face=993_110_1114_243&quot;&gt;&lt;a href=&quot;https://github.com/gwagdalf/gather-example&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/gwagdalf/gather-example&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bTVFv4/hyZQsoRnUC/xAaGM9a2H3p5x0fGu04Nv1/img.png?width=1200&amp;amp;height=600&amp;amp;face=993_110_1114_243,https://scrap.kakaocdn.net/dn/Vn248/hyZQzO2iCu/UYCilKMuJN83P2AUROYUHK/img.png?width=1200&amp;amp;height=600&amp;amp;face=993_110_1114_243');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - gwagdalf/gather-example: Code example of Java 24&amp;rsquo;s Gather Stream API&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Code example of Java 24&amp;rsquo;s Gather Stream API. Contribute to gwagdalf/gather-example development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;Visualizing the Gatherer Process&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Input&amp;nbsp;Stream:&amp;nbsp;[A]---[B]---[C]---[D]---[E]---&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+-----------------------------+&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Gatherer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;[State]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;[Integrator]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;[Downstream]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+-----------------------------+&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v&lt;br /&gt;Output&amp;nbsp;Stream:&amp;nbsp;[X]---[Y]---[Z]-----------&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공되는 메소드들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카테고리메소드&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 104px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Category&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Windowing&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;windowFixed, windowSliding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Folding&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;fold, scan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Filtering&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;filtering, takeWhile, dropWhile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Mapping&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;mapConcurrent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;Control&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;step 기반 sliding&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;official docs :&amp;nbsp;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Gatherers.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Gatherers.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767009098565&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Gatherers (Java SE 24 &amp;amp; JDK 24)&quot; data-og-description=&quot;Returns a Gatherer that performs an ordered, reduction-like, transformation for scenarios where no combiner-function can be implemented, or for reductions which are intrinsically order-dependent. Returns a Gatherer that gathers elements into windows -- enc&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Gatherers.html&quot; data-og-url=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Gatherers.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Gatherers.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Gatherers.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Gatherers (Java SE 24 &amp;amp; JDK 24)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Returns a Gatherer that performs an ordered, reduction-like, transformation for scenarios where no combiner-function can be implemented, or for reductions which are intrinsically order-dependent. Returns a Gatherer that gathers elements into windows -- enc&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발전 단계&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;1280&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;107&quot; height=&quot;28&quot;&gt;
&lt;div data-spm-anchor-id=&quot;a2ty_o01.29997173.0.i19.468e5171dn9TKB&quot;&gt;JEP 번호&lt;/div&gt;
&lt;/td&gt;
&lt;td width=&quot;108&quot;&gt;
&lt;div&gt;JDK 버전&lt;/div&gt;
&lt;/td&gt;
&lt;td width=&quot;384&quot;&gt;
&lt;div&gt;제목&lt;/div&gt;
&lt;/td&gt;
&lt;td width=&quot;681&quot;&gt;
&lt;div&gt;주요 변경 사항&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;31&quot;&gt;
&lt;div&gt;JEP 461&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;JDK 22&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;Stream Gatherers (Preview)&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;Stream API에 사용자 정의 중간 연산 기능 도입 &lt;a href=&quot;https://openjdk.org/jeps/461&quot;&gt;https://openjdk.org/jeps/461&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;31&quot;&gt;
&lt;div&gt;JEP 473&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;JDK 23&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;Stream Gatherers (Second Preview)&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;피드백 반영 및 API 조정 &lt;a href=&quot;https://openjdk.org/jeps/473&quot;&gt;https://openjdk.org/jeps/473&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;31&quot;&gt;
&lt;div&gt;JEP 485&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;JDK 24&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;Stream Gatherers&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;최종. API 변경 없이 기능 확정 &lt;a href=&quot;https://openjdk.org/jeps/485&quot;&gt;https://openjdk.org/jeps/485&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/Java25</category>
      <category>Java25</category>
      <category>JEP485</category>
      <category>Stream Gathers</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/164</guid>
      <comments>https://ride-wind.tistory.com/164#entry164comment</comments>
      <pubDate>Mon, 29 Dec 2025 14:11:27 +0900</pubDate>
    </item>
    <item>
      <title>JEP 510: Key Derivation Function API</title>
      <link>https://ride-wind.tistory.com/163</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;암호화 키 생성하기 위한 표준 API&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KeyDerivationFunction(KDF)&lt;/b&gt; 란&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 하나의 &lt;/span&gt;&lt;b&gt;비밀값(입력 키 재료, IKM)을 받아&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;, 규칙에 따라 새로운 &lt;/span&gt;&lt;b&gt;암호 키를 파생&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;하는 함수&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존&amp;nbsp;문제점&lt;/b&gt;&lt;br /&gt;기존 Java 암호 API에서&lt;br /&gt;PBKDF2, HKDF, TLS KDF 등 KDF 종류별 API가 제각각&lt;br /&gt;SecretKeyFactory, Mac, MessageDigest를 조합해야 함&lt;br /&gt;알고리즘마다 입력 파라미터 구조가 달라 실수하기 쉬움&lt;br /&gt;최신 표준(KDF in TLS 1.3, PQC 등)과의 연계가 복잡&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, &lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;양자 컴퓨팅의 출현으로 기존 암호화 알고리즘이 공격에 취약해짐에 따라, Java 플랫폼이 양자 공격에 저항하는 Post-Quantum Cryptography(PQC)를 지원하는 것이 필수적입니다. JEP 510의 KDF API는 Hybrid Public Key Encryption(HPKE) 구현을 위한 핵심 빌딩 블록 중 하나&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;JEP 478 / 510의 목표&lt;/b&gt;&lt;br /&gt;모든 KDF를 하나의 일관된 API로 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념/역할/코드예&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;개념&lt;/td&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;역할&lt;/td&gt;
&lt;td&gt;코드 예&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;KeyDerivationFunction&lt;/td&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;KDF 알고리즘 엔진&lt;/td&gt;
&lt;td&gt;KDF hkdf = KDF.getInstance(&quot;HKDF&quot;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;KDFParameterSpec&lt;/td&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;알고리즘별 파라미터&lt;/td&gt;
&lt;td&gt;HKDFParameterSpec spec =&lt;br /&gt;&amp;nbsp; HKDFParameterSpec.ofExtract()&lt;br /&gt;&amp;nbsp; &amp;nbsp; .addSalt(&quot;some salt&quot;.getBytes())&lt;br /&gt;&amp;nbsp; &amp;nbsp; .thenExpand(&quot;context info&quot;.getBytes(), 32);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;SecretKey&lt;/td&gt;
&lt;td style=&quot;color: #333333;&quot;&gt;최종 파생 키&lt;/td&gt;
&lt;td&gt;SecretKey key = hkdf.deriveKey(ikm, spec);&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 예&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HKDF (&amp;nbsp;&lt;b&gt;H&lt;/b&gt;MAC-based&amp;nbsp;Extract-and-Expand&amp;nbsp;&lt;b&gt;K&lt;/b&gt;ey&amp;nbsp;&lt;b&gt;D&lt;/b&gt;erivation&amp;nbsp;&lt;b&gt;F&lt;/b&gt;unction )&lt;/p&gt;
&lt;pre id=&quot;code_1766978497425&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import javax.crypto.KDF;
import javax.crypto.SecretKey;
import javax.crypto.spec.HKDFParameterSpec;
import javax.crypto.spec.SecretKeySpec;

byte[] ikmBytes = &quot;shared secret&quot;.getBytes();
SecretKey ikm = new SecretKeySpec(ikmBytes, &quot;HKDF&quot;);
KDF hkdf = KDF.getInstance(&quot;HKDF&quot;);

HKDFParameterSpec spec =
  HKDFParameterSpec.ofExtract()
    .addSalt(&quot;some salt&quot;.getBytes())
    .thenExpand(&quot;context info&quot;.getBytes(), 32);

SecretKey key = hkdf.deriveKey(ikm, spec);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* HMAC : &lt;b&gt;H&lt;/b&gt;ash-based &lt;b&gt;M&lt;/b&gt;essage &lt;b&gt;A&lt;/b&gt;uthentication &lt;b&gt;C&lt;/b&gt;ode ; &lt;b&gt;해시&lt;/b&gt; 함수와 &lt;b&gt;비밀 키를 결합&lt;/b&gt;해 메시지의 무결성과 인증을 검증하는 암호학적 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PBKDF2 ( &lt;span style=&quot;background-color: oklch(0.9902 0.004 106.47); color: oklch(0.3039 0.04 213.68); text-align: start;&quot;&gt;&lt;b&gt;P&lt;/b&gt;assword-&lt;b&gt;B&lt;/b&gt;ased &lt;b&gt;K&lt;/b&gt;ey &lt;b&gt;D&lt;/b&gt;erivation &lt;b&gt;F&lt;/b&gt;unction 2)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766978802542&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import javax.crypto.KDF;
import javax.crypto.SecretKey;
import javax.crypto.spec.PBKDF2ParameterSpec;
import javax.crypto.spec.SecretKeySpec;

char[] password = &quot;password&quot;.toCharArray();
byte[] salt = &quot;salt&quot;.getBytes();

SecretKey baseKey = 
  new SecretKeySpec(new String(password).getBytes(),&quot;PBKDF2&quot;);

PBKDF2ParameterSpec spec =
  new PBKDF2ParameterSpec(salt,100_000,256,&quot;HmacSHA256&quot;);

KDF pbkdf2 = KDF.getInstance(&quot;PBKDF2&quot;);

SecretKey derivedKey = pbkdf2.deriveKey(baseKey, spec);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JEP 번호&lt;/td&gt;
&lt;td&gt;JDK 버전&lt;/td&gt;
&lt;td&gt;제목&lt;/td&gt;
&lt;td&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JEP 478&lt;/td&gt;
&lt;td&gt;JDK 24&lt;/td&gt;
&lt;td&gt;Key Derivation Function API (Preview)&lt;/td&gt;
&lt;td&gt;Preview &lt;a href=&quot;https://openjdk.org/jeps/478&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openjdk.org/jeps/478&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JEP 510&lt;/td&gt;
&lt;td&gt;JDK 25&lt;/td&gt;
&lt;td&gt;Key Derivation Function API&lt;/td&gt;
&lt;td&gt;Standard&amp;nbsp; &lt;a href=&quot;https://openjdk.org/jeps/510&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openjdk.org/jeps/510&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Java/Java25</category>
      <category>Java25</category>
      <category>JEP510</category>
      <category>Key Derivation API</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/163</guid>
      <comments>https://ride-wind.tistory.com/163#entry163comment</comments>
      <pubDate>Mon, 29 Dec 2025 12:29:18 +0900</pubDate>
    </item>
    <item>
      <title>JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm (ML-DSA)</title>
      <link>https://ride-wind.tistory.com/162</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java&amp;nbsp;24에&amp;nbsp;도입되었으며,&amp;nbsp;양자컴퓨터&amp;nbsp;시대에도&amp;nbsp;안전한&amp;nbsp;&lt;b&gt;디지털&amp;nbsp;서명&lt;/b&gt;을&amp;nbsp;위한&amp;nbsp;Module-Lattice-Based&amp;nbsp;Digital&amp;nbsp;Signature&amp;nbsp;Algorithm&amp;nbsp;(ML-DSA)을&amp;nbsp;JDK&amp;nbsp;표준&amp;nbsp;API로&amp;nbsp;제공합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JEP&amp;nbsp;497은&amp;nbsp;이&amp;nbsp;알고리즘을&amp;nbsp;Java의&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KeyPairGenerator&lt;/li&gt;
&lt;li&gt;Signature&lt;/li&gt;
&lt;li&gt;KeyFactory&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API로 네이티브 제공함으로써 외부 라이브러리 없이도 안전한 서명을 가능하게 합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 적인 사용 예&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 공인 인증서가 아닌, 사설 인증서를 사용하고, 그 사설 인증서가 MS-DSA 를 사용하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 사내 용도의(Fusion) API 를 호출해야 하고, 그 사이트의&amp;nbsp; Internal 인증서가 ML-DSA 를 사용하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf : 도메인 공인된 인증서 CA 발급기관 ( DigiCert, Sectgo, GeoTrust, Thawte)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관련 : &lt;a href=&quot;https://ride-wind.tistory.com/161&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ride-wind.tistory.com/161&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766912014896&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism&quot; data-og-description=&quot;양자 컴퓨터의 발전은 기존의 RSA나 ECC 같은 공개키 암호화 체계를 무력화할 수 있는 잠재적 위협이 되고 있습니다.이에 대응하기 위해 JDK 24 에서 양자 내성 암호(Post-Quantum Cryptography, PQC) 기술인 &quot; data-og-host=&quot;ride-wind.tistory.com&quot; data-og-source-url=&quot;https://ride-wind.tistory.com/161&quot; data-og-url=&quot;https://ride-wind.tistory.com/161&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/DH0kV/hyZQvSZkS1/Zw9cwsXXLTBG6SNi1S54Fk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/XhzMD/hyZQB6JowB/R0KHN8zHSRAyS3aSj8BeqK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cXrNg5/hyZPJxvjDh/QeX6oFNkrsWKfU0RIV0VvK/img.png?width=3118&amp;amp;height=1906&amp;amp;face=0_0_3118_1906&quot;&gt;&lt;a href=&quot;https://ride-wind.tistory.com/161&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ride-wind.tistory.com/161&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/DH0kV/hyZQvSZkS1/Zw9cwsXXLTBG6SNi1S54Fk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/XhzMD/hyZQB6JowB/R0KHN8zHSRAyS3aSj8BeqK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cXrNg5/hyZPJxvjDh/QeX6oFNkrsWKfU0RIV0VvK/img.png?width=3118&amp;amp;height=1906&amp;amp;face=0_0_3118_1906');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;양자 컴퓨터의 발전은 기존의 RSA나 ECC 같은 공개키 암호화 체계를 무력화할 수 있는 잠재적 위협이 되고 있습니다.이에 대응하기 위해 JDK 24 에서 양자 내성 암호(Post-Quantum Cryptography, PQC) 기술인&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ride-wind.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 코드 예&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KeyPair 생성&lt;/p&gt;
&lt;pre id=&quot;code_1766912122897&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.spec.NamedParameterSpec;

public class MLDSAKeyGen {
  public static void main(String[] args) throws Exception {
    // 1) KeyPairGenerator 인스턴스 생성: 파라미터 세트 명시
    KeyPairGenerator kpg = KeyPairGenerator.getInstance(&quot;ML-DSA&quot;);
    kpg.initialize(NamedParameterSpec.ML_DSA_65); // ML-DSA-65 (기본 수준)

    // 2) 키 쌍 생성
    KeyPair kp = kpg.generateKeyPair();

    System.out.println(&quot;Generated keys:&quot;);
    System.out.println(&quot;  Public  : &quot; + kp.getPublic());
    System.out.println(&quot;  Private : &quot; + kp.getPrivate());
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;906&quot; data-start=&quot;891&quot;&gt;ML-DSA-44&lt;/li&gt;
&lt;li data-end=&quot;929&quot; data-start=&quot;909&quot;&gt;ML-DSA-65 (기본)&lt;/li&gt;
&lt;li data-end=&quot;1011&quot; data-start=&quot;932&quot;&gt;ML-DSA-87&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메시지에 서명(Sign)&lt;/p&gt;
&lt;pre id=&quot;code_1766912175680&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.security.PrivateKey;
import java.security.Signature;
import java.nio.charset.StandardCharsets;

public class MLDSASign {
  public static byte[] signMessage(PrivateKey priv, String message) throws Exception {
    // 1) Signature 인스턴스 생성
    Signature signer = Signature.getInstance(&quot;ML-DSA&quot;);

    // 2) PrivateKey로 서명 초기화
    signer.initSign(priv);

    // 3) 메시지를 바이트로 제공
    byte[] msgBytes = message.getBytes(StandardCharsets.UTF_8);
    signer.update(msgBytes);

    // 4) 실제 서명 생성
    return signer.sign();
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서명 검증(Verify)&lt;/p&gt;
&lt;pre id=&quot;code_1766912916088&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.security.PublicKey;
import java.security.Signature;

public class MLDSAVerify {
  public static boolean verifySignature(PublicKey pub, byte[] signature, String message) throws Exception {
    Signature verifier = Signature.getInstance(&quot;ML-DSA&quot;);

    // public key로 검증 초기화
    verifier.initVerify(pub);

    // 메시지를 다시 공급
    verifier.update(message.getBytes(StandardCharsets.UTF_8));

    // 서명 검증
    return verifier.verify(signature);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 인코딩/디코딩(Optional)&lt;/p&gt;
&lt;pre id=&quot;code_1766912945637&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;

public class MLDSAKeyFactory {
  public static PrivateKey decodePrivate(byte[] encoded) throws Exception {
    KeyFactory factory = KeyFactory.getInstance(&quot;ML-DSA&quot;);
    PKCS8EncodedKeySpec p8spec = new PKCS8EncodedKeySpec(encoded);
    return factory.generatePrivate(p8spec);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JEP 496 vs JEP 497&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff;&quot;&gt;JEP 496 (ML-KEM)&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff;&quot;&gt;JEP 497 (ML-DSA)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;이름&lt;/td&gt;
&lt;td&gt;Key Encapsulation&lt;/td&gt;
&lt;td&gt;Digital Signature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;목적&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;대칭 키 안전 교환&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;디지털 서명 및 검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;표준&lt;/td&gt;
&lt;td&gt;NIST FIPS 203&lt;/td&gt;
&lt;td&gt;NIST FIPS 204&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;주요 API&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;KeyPairGenerator, KEM, KeyFactory&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;KeyPairGenerator, Signature, KeyFactory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;Parameter Sets&lt;/td&gt;
&lt;td&gt;ML-KEM-512/768/1024&lt;/td&gt;
&lt;td&gt;ML-DSA-44/65/87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;양자 저항성&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;✔&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;✔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;TLS 지원&lt;/td&gt;
&lt;td&gt;향후 도입 예정&lt;/td&gt;
&lt;td&gt;향후 도입 예정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;Java 버전&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;JDK 24&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;JDK 24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;기본 키&lt;/td&gt;
&lt;td&gt;비대칭 키 래핑&lt;/td&gt;
&lt;td&gt;서명 생성/검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;link&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/496&quot;&gt;https://openjdk.org/jeps/496&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9;&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/497&quot;&gt;https://openjdk.org/jeps/497&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/Java25</category>
      <category>Java25</category>
      <category>JEP497</category>
      <category>ML-DSA</category>
      <category>양자내성암호</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/162</guid>
      <comments>https://ride-wind.tistory.com/162#entry162comment</comments>
      <pubDate>Sun, 28 Dec 2025 18:10:42 +0900</pubDate>
    </item>
    <item>
      <title>JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism</title>
      <link>https://ride-wind.tistory.com/161</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;양자 컴퓨터&lt;/b&gt;의 발전은 기존의 &lt;b&gt;RSA나 ECC 같은 공개키 암호화 체계를 무력화&lt;/b&gt;할 수 있는 잠재적 위협이 되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 대응하기 위해 &lt;b data-index-in-node=&quot;86&quot; data-path-to-node=&quot;0&quot;&gt;JDK 24&lt;/b&gt; 에서 양자 내성 암호(Post-Quantum Cryptography, PQC) 기술인 &lt;b data-index-in-node=&quot;142&quot; data-path-to-node=&quot;0&quot;&gt;ML-KEM&lt;/b&gt;과 &lt;b data-index-in-node=&quot;150&quot; data-path-to-node=&quot;0&quot;&gt;ML-DSA&lt;/b&gt;를 도입했습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;01. 코드 예&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Key pair 생성&lt;/p&gt;
&lt;pre id=&quot;code_1766887764471&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.security.*;
import java.security.spec.NamedParameterSpec;

public class MLKEMKeyGen {
  public static void main(String[] args) throws Exception {
    // ① 기본 ML-KEM-768 파라미터로 KeyPair 생성
    KeyPairGenerator g1 = KeyPairGenerator.getInstance(&quot;ML-KEM&quot;);
    KeyPair kp1 = g1.generateKeyPair();

    // ② ML-KEM-512 파라미터 지정
    KeyPairGenerator g2 = KeyPairGenerator.getInstance(&quot;ML-KEM&quot;);
    g2.initialize(NamedParameterSpec.ML_KEM_512);
    KeyPair kp2 = g2.generateKeyPair();

    // ③ ML-KEM-1024 직접 지정
    KeyPairGenerator g3 = KeyPairGenerator.getInstance(&quot;ML-KEM-1024&quot;);
    KeyPair kp3 = g3.generateKeyPair();

    System.out.println(&quot;Generated ML-KEM public keys:&quot;);
    System.out.println(kp1.getPublic());
    System.out.println(kp2.getPublic());
    System.out.println(kp3.getPublic());
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;default 768 이며, TLS 등 일반 서버-클라이언트용,&amp;nbsp; 1024 가 가장 높은 보안 강도&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Key Encapsulation , 송신측&lt;/p&gt;
&lt;pre id=&quot;code_1766887812922&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import javax.crypto.KEM;
import javax.crypto.SecretKey;

public class MLKEMEncapsulate {
  public static void main(String[] args) throws Exception {
    KeyPairGenerator g = KeyPairGenerator.getInstance(&quot;ML-KEM&quot;);
    KeyPair kp = g.generateKeyPair();

    // KEM 객체 가져오기 (기본 ML-KEM-768)
    KEM kemSend = KEM.getInstance(&quot;ML-KEM&quot;);

    // 공개키를 이용하여 Encapsulator 생성
    KEM.Encapsulator enc = kemSend.newEncapsulator(kp.getPublic());

    // 캡슐화: 공유 비밀키와 메시지 획득
    KEM.Encapsulated result = enc.encapsulate();

    byte[] encapsulationMessage = result.encapsulation();
    SecretKey sharedKeySender = result.key();

    System.out.println(&quot;Encapsulated message length: &quot; + encapsulationMessage.length);
    System.out.println(&quot;Sender's shared secret: &quot; + sharedKeySender);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Key Decapsulation, 수신측&lt;/p&gt;
&lt;pre id=&quot;code_1766910242853&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import javax.crypto.KEM;
import javax.crypto.SecretKey;

public class MLKEMDecapsulate {
    public static void main(String[] args) throws Exception {
        // 캡슐화 메시지가 sender에서 넘어왔다고 가정
        byte[] encapsulatedMessage = /* received bytes */;

        // 비밀키를 알고 있는 수신자 KEM 객체 생성
        KEM kemRecv = KEM.getInstance(&quot;ML-KEM&quot;);
        KEM.Decapsulator dec = kemRecv.newDecapsulator(privateKeyFromSender);

        SecretKey sharedKeyReceiver = dec.decapsulate(encapsulatedMessage);

        System.out.println(&quot;Receiver's shared secret: &quot; + sharedKeyReceiver);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Encoding/Decoding Key&lt;/p&gt;
&lt;pre id=&quot;code_1766910453082&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.security.*;
import java.security.spec.*;

public class MLKEMKeyEncoding {
  public static void main(String[] args) throws Exception {
    KeyPairGenerator g = KeyPairGenerator.getInstance(&quot;ML-KEM&quot;);
    KeyPair kp = g.generateKeyPair();

    KeyFactory keyFactory = KeyFactory.getInstance(&quot;ML-KEM&quot;);

    // PrivateKey &amp;rarr; PKCS#8 (표준 바이트 포맷,Encoding)
    PKCS8EncodedKeySpec pkcs8 = keyFactory.getKeySpec(kp.getPrivate(), PKCS8EncodedKeySpec.class);

    // PKCS#8 &amp;rarr; PrivateKey ( Decoding )
    PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8);

    // PublicKey &amp;rarr; X.509 ; X.509 표준포멧 으로 변환
    X509EncodedKeySpec x509 = keyFactory.getKeySpec(kp.getPublic(), X509EncodedKeySpec.class);

    // X.509 &amp;rarr; PublicKey : Decoding
    PublicKey publicKey2 = keyFactory.generatePublic(x509);

    System.out.println(&quot;Encoded PrivateKey size: &quot; + pkcs8.getEncoded().length);
    System.out.println(&quot;Encoded PublicKey size: &quot; + x509.getEncoded().length);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Encapsulation/Decapsulation vs Encoding/Decoding&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;724&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;148&quot; height=&quot;24&quot;&gt;구분&lt;/td&gt;
&lt;td width=&quot;288&quot;&gt;Key Encapsulation/Decapsulation&lt;/td&gt;
&lt;td width=&quot;288&quot;&gt;Key Encoding/Decoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;목적&lt;/td&gt;
&lt;td&gt;안전한 채널에서 비밀 키 교환&lt;/td&gt;
&lt;td&gt;키를 저장하거나 전송하기 위한 직렬화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;참여자&lt;/td&gt;
&lt;td&gt;송신자 + 수신자 (2명 이상)&lt;/td&gt;
&lt;td&gt;단일 사용자 (1명)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;결과물&lt;/td&gt;
&lt;td&gt;공유 비밀 키 (Shared Secret)&lt;/td&gt;
&lt;td&gt;바이트 배열 (Byte Array)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;사용 시점&lt;/td&gt;
&lt;td&gt;통신 시작 시 키 교환 단계&lt;/td&gt;
&lt;td&gt;키를 파일에 저장하거나 네트워크로 전송할 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;보안 강도&lt;/td&gt;
&lt;td&gt;양자 저항성 (Quantum-Resistant)&lt;/td&gt;
&lt;td&gt;단순한 인코딩 형식(X.509, PKCS#8) 또는 Base64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;API&lt;/td&gt;
&lt;td&gt;`KEM` 클래스 사용&lt;/td&gt;
&lt;td&gt;`KeyFactory` 클래스 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Encoding/Decoding 은 왜하나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 Key 를 Vault/DB 에 저장하거나, Network 전송 하기 위해, 객체 상태의 Key 를&amp;nbsp; 표준 Byte Array(PKCS#8, X.509)를 사용하여 Encoding 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;3&quot; data-ke-size=&quot;size26&quot;&gt;2. 배경: 왜 양자 내성 암호가 필요한가요?&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;현재 우리가 사용하는 RSA나 Elliptic Curve(EC) 암호 체계는 &lt;b&gt;거대한 정수의 소인수분해&lt;/b&gt;나 &lt;b&gt;이산 로그 문제&lt;/b&gt;에 기반합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;하지만 충분한 성능을 가진 양자 컴퓨터가 등장하면 &lt;b&gt;쇼어 알고리즘(Shor's algorithm)&lt;/b&gt;을 통해 이 암호들을 순식간에 풀 수 있게 됩니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;이를 방지하기 위해 NIST(미국 국립표준기술연구소)에서 선정한 차세대 알고리즘들을 Java에 구현한 것이 바로 JEP 496과 497입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2102&quot; data-origin-height=&quot;1438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8zNyt/dJMb99545Nn/JucUt8TKJxPBqi4DkKS3H0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8zNyt/dJMb99545Nn/JucUt8TKJxPBqi4DkKS3H0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8zNyt/dJMb99545Nn/JucUt8TKJxPBqi4DkKS3H0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8zNyt%2FdJMb99545Nn%2FJucUt8TKJxPBqi4DkKS3H0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2102&quot; height=&quot;1438&quot; data-origin-width=&quot;2102&quot; data-origin-height=&quot;1438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;1&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;중첩(Superposition)을 통한 동시 탐색&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;2,0,0&quot;&gt;디지털 컴퓨터(비트):&lt;/b&gt; 그림의 왼쪽처럼 0 또는 1의 확정된 상태만을 가집니다. 3비트 데이터(000~111, N8) 중 하나를 찾으려면 최악의 경우 8번의 연산을 통해 하나하나 확인해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;2,1,0&quot;&gt;양자 컴퓨터(큐비트):&lt;/b&gt; 0과 1의 상태를 동시에 가질 수 있는 &lt;b data-index-in-node=&quot;35&quot; data-path-to-node=&quot;2,1,0&quot;&gt;중첩&lt;/b&gt; 상태를 이용합니다. 3개의 큐비트가 있다면, 연산이 시작되는 시점에 이미 &lt;span data-index-in-node=&quot;79&quot; data-math=&quot;2^3 = 8&quot;&gt;$2^3 = 8$&lt;/span&gt;가지의 모든 가능성을 동시에 가지고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;3&quot; data-ke-size=&quot;size23&quot;&gt;양자 간섭(Quantum Interference)을 이용한 확률 조절&lt;/h3&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;이미지의 오른쪽 하단 표를 보면 '상태'와 '확률' 변화가 핵심입니다. 양자 컴퓨터는 단순히 모든 답을 나열하는 것이 아니라, 연산을 반복할수록 &lt;b data-index-in-node=&quot;81&quot; data-path-to-node=&quot;4&quot;&gt;정답일 확률은 높이고 오답일 확률은 낮추는&lt;/b&gt; 과정을 거칩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;초기 상태:&lt;/b&gt; 모든 상태(000~111)가 동일한 확률을 가지고 섞여 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;1회 양자 연산:&lt;/b&gt; 특정 알고리즘(예: 그로버 알고리즘)을 적용하여 정답인 '110' 상태의 확률 폭(진폭)을 증폭시킵니다. 이미지 표에서 1회 연산 후 '110'의 확률이 &lt;b data-index-in-node=&quot;96&quot; data-path-to-node=&quot;5,1,0&quot;&gt;0.77&lt;/b&gt;로 급격히 상승한 것을 볼 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,0&quot;&gt;2회 양자 연산:&lt;/b&gt; 같은 과정을 한 번 더 반복하면 정답 '110'의 확률이 &lt;b data-index-in-node=&quot;42&quot; data-path-to-node=&quot;5,2,0&quot;&gt;0.95&lt;/b&gt;까지 올라갑니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색에 특화된 &lt;b data-index-in-node=&quot;18&quot; data-path-to-node=&quot;7&quot;&gt;그로버(Grover) 알고리즘&lt;/b&gt;의 원리에 따르면, 찾고자 하는 데이터의 전체 개수가 &lt;b&gt;&lt;span data-index-in-node=&quot;64&quot; data-math=&quot;N&quot;&gt;$N$&lt;/span&gt;개일 때 약 $\sqrt{N}$번의 연산&lt;/b&gt;만으로 정답을 찾을 수 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;7&quot; data-ke-size=&quot;size26&quot;&gt;3. JEP 496: ML-KEM (키 메커니즘)&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;ML-KEM&lt;/b&gt;(Module-Lattice-Based Key-Encapsulation Mechanism)은 &lt;b&gt;격자 기반(Lattice-based)&lt;/b&gt; 암호화 알고리즘입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;양자&amp;nbsp;컴퓨터의&amp;nbsp;위협에&amp;nbsp;대응하기&amp;nbsp;위해&amp;nbsp;설계된&amp;nbsp;&lt;b&gt;양자&amp;nbsp;내성&amp;nbsp;암호(Post-Quantum&amp;nbsp;Cryptography,&amp;nbsp;PQC)&amp;nbsp;표준&amp;nbsp;알고리즘&lt;/b&gt;입니다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;격자 기반 암호(Lattice-based)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;ML-KEM은 격자 이론의 난제 중 하나인 &lt;b data-index-in-node=&quot;24&quot; data-path-to-node=&quot;4&quot;&gt;MLWE(Module Learning With Errors)&lt;/b&gt; 문제에 기반합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;LWE(Learning With Errors):&lt;/b&gt; 행렬 &lt;span data-index-in-node=&quot;30&quot; data-math=&quot;A&quot;&gt;$A$&lt;/span&gt;와 벡터 &lt;span data-index-in-node=&quot;36&quot; data-math=&quot;s&quot;&gt;$s$&lt;/span&gt;, 그리고 아주 작은 오차(noise) 벡터 &lt;span data-index-in-node=&quot;62&quot; data-math=&quot;e&quot;&gt;$e$&lt;/span&gt;가 있을 때, &lt;span data-index-in-node=&quot;71&quot; data-math=&quot;b = As + e&quot;&gt;$b = As + e$&lt;/span&gt; 결과값만 보고 비밀 값인 &lt;span data-index-in-node=&quot;96&quot; data-math=&quot;s&quot;&gt;$s$&lt;/span&gt;를 찾아내는 문제입니다. 오차가 없다면 단순 연산으로 풀리지만, 오차가 섞이는 순간 계산 복잡도가 기하급수적으로 증가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;Module-LWE:&lt;/b&gt; 일반 LWE보다 효율성을 높인 버전입니다. 데이터를 '모듈'이라는 구조로 묶어 처리함으로써, 보안성을 유지하면서도 키의 크기를 줄이고 연산 속도를 획기적으로 높였습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1286&quot; data-origin-height=&quot;1152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AMtAZ/dJMcaiWdkKR/q9zGAwj7a8aqkQw3sWXAj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AMtAZ/dJMcaiWdkKR/q9zGAwj7a8aqkQw3sWXAj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AMtAZ/dJMcaiWdkKR/q9zGAwj7a8aqkQw3sWXAj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAMtAZ%2FdJMcaiWdkKR%2Fq9zGAwj7a8aqkQw3sWXAj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1286&quot; height=&quot;1152&quot; data-origin-width=&quot;1286&quot; data-origin-height=&quot;1152&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;격자(Lattice)&lt;/b&gt;란 공간에서 &lt;b&gt;점들이 규칙적으로 반복 배치된 구조&lt;/b&gt;입니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학적으로는 몇 개의 &lt;b&gt;기저 벡터(basis vectors)&lt;/b&gt; 를 정수 배로 조합해 만들 수 있는 모든 점들의 집합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림은 2개의 기저 벡터 b1, b2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 점들을 아래처럼 기저 벡터 b1 과 b2 로 표현가능&lt;/p&gt;
&lt;pre id=&quot;code_1766885962810&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;2&amp;middot;b₁ + 3&amp;middot;b₂
-1&amp;middot;b₁ + 4&amp;middot;b₂&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b3는&lt;/p&gt;
&lt;pre id=&quot;code_1766886007856&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;b₃ = a&amp;middot;b₁ + c&amp;middot;b₂  (a, c는 정수)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노이즈(오차) x 를 살짝 섞어 주는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;격자에 매우 가까운점 x 가 주어졌을 때 x 와 가장 가까운 격자점 b3 를 찾아라&lt;/p&gt;
&lt;pre id=&quot;code_1766886088427&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;x = b₃ + e&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고리즘이 변경된 것이므로 동작방식은 기존의 비대칭키 암호화 방식과 동일합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘 작동 방식 (KEM)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ML-KEM은 데이터를 직접 암호화하는 방식이 아니라, 대칭 키 암호(AES 등)에 사용할 &lt;b data-index-in-node=&quot;51&quot; data-path-to-node=&quot;11&quot;&gt;공유 비밀키(Shared Secret)를 안전하게 전달&lt;/b&gt;하는 '키 캡슐화 매커니즘'입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;키 생성 (KeyGen):&lt;/b&gt; 수신자가 공개키와 비밀키를 생성합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;캡슐화 (Encapsulate):&lt;/b&gt; 송신자가 수신자의 공개키를 사용하여 임의의 '공유 비밀키'를 생성하고, 이를 암호화(캡슐화)하여 보냅니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,2,0&quot;&gt;역캡슐화 (Decapsulate):&lt;/b&gt; 수신자가 자신의 비밀키로 캡슐을 풀어 동일한 '공유 비밀키'를 얻습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;이후 양측은 이 공유된 키를 사용해 AES 등으로 본문을 암호화합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1636&quot; data-origin-height=&quot;1164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/69xhv/dJMcaaRshH4/PVuARocna3bkyZ5X0H61E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/69xhv/dJMcaaRshH4/PVuARocna3bkyZ5X0H61E0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/69xhv/dJMcaaRshH4/PVuARocna3bkyZ5X0H61E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F69xhv%2FdJMcaaRshH4%2FPVuARocna3bkyZ5X0H61E0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1636&quot; height=&quot;1164&quot; data-origin-width=&quot;1636&quot; data-origin-height=&quot;1164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;Public&amp;nbsp;Key:&amp;nbsp;공개되어도&amp;nbsp;OK&lt;br /&gt;Ciphertext: 공개되어도 OK&lt;br /&gt;Shared Secret Key: 절대 공개 ❌&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-path-to-node=&quot;13&quot; data-ke-size=&quot;size26&quot;&gt;4. 국가사이버보안센터, 마스터플랜&lt;/h2&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;양자&amp;nbsp;大전환&amp;nbsp;시대&amp;nbsp;대비,&amp;nbsp;관계부처&amp;nbsp;합동&amp;nbsp;마스터플랜&amp;nbsp;발표&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=Notification_main&amp;amp;nttId=59449&amp;amp;pageIndex=5&amp;amp;searchCnd2=%EB%B3%B4%EB%8F%84%EC%9E%90%EB%A3%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=Notification_main&amp;amp;nttId=59449&amp;amp;pageIndex=5&amp;amp;searchCnd2=%EB%B3%B4%EB%8F%84%EC%9E%90%EB%A3%8C&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766884725909&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;국가사이버안보센터&quot; data-og-description=&quot;국제 및 국가배후 해킹 조직 관련 사이버위협 예방&amp;middot;대응, 보안적합성&amp;middot;암호모듈 검증제도 등 정보수록&quot; data-og-host=&quot;www.ncsc.go.kr:4018&quot; data-og-source-url=&quot;https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=Notification_main&amp;amp;nttId=59449&amp;amp;pageIndex=5&amp;amp;searchCnd2=%EB%B3%B4%EB%8F%84%EC%9E%90%EB%A3%8C&quot; data-og-url=&quot;https://www.ncsc.go.kr:4018/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/be2X8u/hyZQxQHgXC/VUC610786KkyTLPgdv0nmk/img.png?width=168&amp;amp;height=48&amp;amp;face=0_0_168_48,https://scrap.kakaocdn.net/dn/bcQdP8/hyZQz118Me/ZVa8au7NpGBbx6Znl4ybs1/img.png?width=4000&amp;amp;height=4000&amp;amp;face=0_0_4000_4000,https://scrap.kakaocdn.net/dn/dwpSDk/hyZQAs7wic/qjqraTuVMjQH2HT9Q4W2gk/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500&quot;&gt;&lt;a href=&quot;https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=Notification_main&amp;amp;nttId=59449&amp;amp;pageIndex=5&amp;amp;searchCnd2=%EB%B3%B4%EB%8F%84%EC%9E%90%EB%A3%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=Notification_main&amp;amp;nttId=59449&amp;amp;pageIndex=5&amp;amp;searchCnd2=%EB%B3%B4%EB%8F%84%EC%9E%90%EB%A3%8C&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/be2X8u/hyZQxQHgXC/VUC610786KkyTLPgdv0nmk/img.png?width=168&amp;amp;height=48&amp;amp;face=0_0_168_48,https://scrap.kakaocdn.net/dn/bcQdP8/hyZQz118Me/ZVa8au7NpGBbx6Znl4ybs1/img.png?width=4000&amp;amp;height=4000&amp;amp;face=0_0_4000_4000,https://scrap.kakaocdn.net/dn/dwpSDk/hyZQAs7wic/qjqraTuVMjQH2HT9Q4W2gk/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;국가사이버안보센터&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;국제 및 국가배후 해킹 조직 관련 사이버위협 예방&amp;middot;대응, 보안적합성&amp;middot;암호모듈 검증제도 등 정보수록&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.ncsc.go.kr:4018&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양자내성암호 전환 추진 로드맵&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3118&quot; data-origin-height=&quot;1906&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLrsVi/dJMcagqAUC0/1KwUaTILhBthJnVmnzklxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLrsVi/dJMcagqAUC0/1KwUaTILhBthJnVmnzklxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLrsVi/dJMcagqAUC0/1KwUaTILhBthJnVmnzklxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLrsVi%2FdJMcagqAUC0%2F1KwUaTILhBthJnVmnzklxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3118&quot; height=&quot;1906&quot; data-origin-width=&quot;3118&quot; data-origin-height=&quot;1906&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JEP 496 vs JEP 497&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;항목&lt;/td&gt;
&lt;td&gt;JEP 496 (ML-KEM)&lt;/td&gt;
&lt;td&gt;JEP 497 (ML-DSA)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이름&lt;/td&gt;
&lt;td&gt;Key Encapsulation&lt;/td&gt;
&lt;td&gt;Digital Signature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;목적&lt;/td&gt;
&lt;td&gt;대칭 키 안전 교환&lt;/td&gt;
&lt;td&gt;디지털 서명 및 검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;표준&lt;/td&gt;
&lt;td&gt;NIST FIPS 203&lt;/td&gt;
&lt;td&gt;NIST FIPS 204&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주요 API&lt;/td&gt;
&lt;td&gt;KeyPairGenerator, KEM, KeyFactory&lt;/td&gt;
&lt;td&gt;KeyPairGenerator, Signature, KeyFactory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parameter Sets&lt;/td&gt;
&lt;td&gt;ML-KEM-512/768/1024&lt;/td&gt;
&lt;td&gt;ML-DSA-44/65/87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;양자 저항성&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;td&gt;✔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS 지원&lt;/td&gt;
&lt;td&gt;향후 도입 예정&lt;/td&gt;
&lt;td&gt;향후 도입 예정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java 버전&lt;/td&gt;
&lt;td&gt;JDK 24&lt;/td&gt;
&lt;td&gt;JDK 24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;기본 키&lt;/td&gt;
&lt;td&gt;비대칭 키 래핑&lt;/td&gt;
&lt;td&gt;서명 생성/검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;link&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/496&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openjdk.org/jeps/496&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/497&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openjdk.org/jeps/497&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/Java25</category>
      <category>Java25</category>
      <category>JEP496</category>
      <category>ML-KEM</category>
      <category>양자내성암호</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/161</guid>
      <comments>https://ride-wind.tistory.com/161#entry161comment</comments>
      <pubDate>Sun, 28 Dec 2025 10:42:33 +0900</pubDate>
    </item>
    <item>
      <title>JEP 511: Module Import Declarations</title>
      <link>https://ride-wind.tistory.com/160</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;모듈&amp;nbsp;전체를&amp;nbsp;한&amp;nbsp;줄로&amp;nbsp;가져오는&amp;nbsp;import&amp;nbsp;구문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1766798890920&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import module ModuleName;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 사용 예&lt;/p&gt;
&lt;pre id=&quot;code_1766800720756&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 변경 전
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

String[] fruits = new String[] { &quot;apple&quot;, &quot;berry&quot;, &quot;citrus&quot; };
Map&amp;lt;String, String&amp;gt; m =
    Stream.of(fruits)
        .collect(Collectors.toMap(s -&amp;gt; s.toUpperCase().substring(0,1),
                Function.identity()));
                
// 변경 후, module import
import module java.base;

String[] fruits = new String[] { &quot;apple&quot;, &quot;berry&quot;, &quot;citrus&quot; };
Map&amp;lt;String, String&amp;gt; m =
    Stream.of(fruits)
        .collect(Collectors.toMap(s -&amp;gt; s.toUpperCase().substring(0,1),
                Function.identity()));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java.base 모듈에 Map, Function, Collectors, Stream 등 54개의 패키지를 import 하는 효과가 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/module-summary.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/module-summary.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766801566380&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;java.base (Java SE 25 &amp;amp; JDK 25)&quot; data-og-description=&quot;Defines channels, which represent connections to entities that are capable of performing I/O operations, such as files and sockets; defines selectors, for multiplexed, non-blocking I/O operations. Defines charsets, decoders, and encoders, for translating b&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/module-summary.html&quot; data-og-url=&quot;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/module-summary.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/module-summary.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/module-summary.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;java.base (Java SE 25 &amp;amp; JDK 25)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Defines channels, which represent connections to entities that are capable of performing I/O operations, such as files and sockets; defines selectors, for multiplexed, non-blocking I/O operations. Defines charsets, decoders, and encoders, for translating b&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;2022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHY2xH/dJMcaajBYIF/YR2KVCwamvcpk8MamQGypk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHY2xH/dJMcaajBYIF/YR2KVCwamvcpk8MamQGypk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHY2xH/dJMcaajBYIF/YR2KVCwamvcpk8MamQGypk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHY2xH%2FdJMcaajBYIF%2FYR2KVCwamvcpk8MamQGypk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1848&quot; height=&quot;2022&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;2022&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 예, 중복되는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복되는 모듈은 명확하게 표시해야 합니다&lt;/p&gt;
&lt;pre id=&quot;code_1766800809968&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import module java.base;      // java.util.List 인터페이스 포함
import module java.desktop;   // java.awt.List 클래스 포함
import java.util.List;         // java.util.List를 명시적으로 임포트하여 충돌 해결

List&amp;lt;String&amp;gt; myList = new ArrayList&amp;lt;&amp;gt;(); // java.util.List로 결정됨&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 module 들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.oracle.com/en/java/javase/21/docs/api/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766801559450&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Overview (Java SE 21 &amp;amp; JDK 21)&quot; data-og-description=&quot;This document is divided into two sections: Java SE The Java Platform, Standard Edition (Java SE) APIs define the core Java platform for general-purpose computing. These APIs are in modules whose names start with java. JDK The Java Development Kit (JDK) AP&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/&quot; data-og-url=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Overview (Java SE 21 &amp;amp; JDK 21)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This document is divided into two sections: Java SE The Java Platform, Standard Edition (Java SE) APIs define the core Java platform for general-purpose computing. These APIs are in modules whose names start with java. JDK The Java Development Kit (JDK) AP&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2416&quot; data-origin-height=&quot;2264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAoL7q/dJMcafFd72S/4ZlwjcXqXQ68TmdvPP99t1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAoL7q/dJMcafFd72S/4ZlwjcXqXQ68TmdvPP99t1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAoL7q/dJMcafFd72S/4ZlwjcXqXQ68TmdvPP99t1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAoL7q%2FdJMcafFd72S%2F4ZlwjcXqXQ68TmdvPP99t1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2416&quot; height=&quot;2264&quot; data-origin-width=&quot;2416&quot; data-origin-height=&quot;2264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발전단계&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JEP 번호&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JDK 버전&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc;&quot;&gt;제목&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JEP 476&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JDK 23&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc;&quot;&gt;Module Import Declarations (Preview) &lt;a href=&quot;https://openjdk.org/jeps/476&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openjdk.org/jeps/476&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JEP 494&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JDK 24&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc;&quot;&gt;Module Import Declarations (Second Preview) &lt;a href=&quot;https://openjdk.org/jeps/494&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openjdk.org/jeps/494&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JEP 511&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc; text-align: center;&quot;&gt;JDK 25&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc;&quot;&gt;Module Import Declarations &lt;a href=&quot;https://openjdk.org/jeps/511&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openjdk.org/jeps/511&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Java/Java25</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/160</guid>
      <comments>https://ride-wind.tistory.com/160#entry160comment</comments>
      <pubDate>Sat, 27 Dec 2025 11:15:33 +0900</pubDate>
    </item>
    <item>
      <title>Lingma - Alicloud coding Assitant</title>
      <link>https://ride-wind.tistory.com/159</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Alicloud - AI Coding Assistant Lingma&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.alibabacloud.com/en/product/lingma?_p_lc=1&quot;&gt;https://www.alibabacloud.com/en/product/lingma?_p_lc=1&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766473535218&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Lingma: AI Coding Assistant - Alibaba Cloud&quot; data-og-description=&quot;An AI coding assistant that helps developers code faster and more easily&quot; data-og-host=&quot;www.alibabacloud.com&quot; data-og-source-url=&quot;https://www.alibabacloud.com/en/product/lingma?_p_lc=1&quot; data-og-url=&quot;https://www.alibabacloud.com/product/lingma&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bxK7s4/hyZP4hfxV0/Jb9nkt8YuoYDMgR6LP1Dv0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.alibabacloud.com/en/product/lingma?_p_lc=1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.alibabacloud.com/en/product/lingma?_p_lc=1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bxK7s4/hyZP4hfxV0/Jb9nkt8YuoYDMgR6LP1Dv0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Lingma: AI Coding Assistant - Alibaba Cloud&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;An AI coding assistant that helps developers code faster and more easily&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.alibabacloud.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Jetbrain plugin&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://plugins.jetbrains.com/plugin/17809-lingma--alibaba-cloud-ai-coding-assistant&quot;&gt;https://plugins.jetbrains.com/plugin/17809-lingma--alibaba-cloud-ai-coding-assistant&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;visual studio code plugin&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=Alibaba-Cloud.tongyi-lingma&quot;&gt;https://marketplace.visualstudio.com/items?itemName=Alibaba-Cloud.tongyi-lingma&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766473546400&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Lingma - Alibaba Cloud AI Coding Assistant - Visual Studio Marketplace&quot; data-og-description=&quot;Extension for Visual Studio Code - Type Less, Code More&quot; data-og-host=&quot;marketplace.visualstudio.com&quot; data-og-source-url=&quot;https://marketplace.visualstudio.com/items?itemName=Alibaba-Cloud.tongyi-lingma&quot; data-og-url=&quot;https://marketplace.visualstudio.com/items?itemName=Alibaba-Cloud.tongyi-lingma&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/guq1e/hyZP7yiMfI/ptRIYnUAkbkA16m3JmGYsK/img.png?width=401&amp;amp;height=401&amp;amp;face=0_0_401_401,https://scrap.kakaocdn.net/dn/bLt3i0/hyZP8qpNPt/W4xH74jyArjfz2TM2lyLbk/img.png?width=401&amp;amp;height=401&amp;amp;face=0_0_401_401&quot;&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=Alibaba-Cloud.tongyi-lingma&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://marketplace.visualstudio.com/items?itemName=Alibaba-Cloud.tongyi-lingma&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/guq1e/hyZP7yiMfI/ptRIYnUAkbkA16m3JmGYsK/img.png?width=401&amp;amp;height=401&amp;amp;face=0_0_401_401,https://scrap.kakaocdn.net/dn/bLt3i0/hyZP8qpNPt/W4xH74jyArjfz2TM2lyLbk/img.png?width=401&amp;amp;height=401&amp;amp;face=0_0_401_401');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Lingma - Alibaba Cloud AI Coding Assistant - Visual Studio Marketplace&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Extension for Visual Studio Code - Type Less, Code More&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;marketplace.visualstudio.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뜻&lt;/p&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Qwen&amp;nbsp;Tongyi&amp;nbsp;Lingma&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;通义灵码 통이링마&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통의 범용적 지식, 통할통&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옳을의&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;영리할 리&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마 : 코드 마&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio code plugin 설치 시 English 지원&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2276&quot; data-origin-height=&quot;2494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TAufj/dJMcajgtBUb/ezPO73pGEcv3pdvnT4vn00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TAufj/dJMcajgtBUb/ezPO73pGEcv3pdvnT4vn00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TAufj/dJMcajgtBUb/ezPO73pGEcv3pdvnT4vn00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTAufj%2FdJMcajgtBUb%2FezPO73pGEcv3pdvnT4vn00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2276&quot; height=&quot;2494&quot; data-origin-width=&quot;2276&quot; data-origin-height=&quot;2494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jetbrain 설치 시 언어를 변경할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 설정은 중국어&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2530&quot; data-origin-height=&quot;2478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kFcth/dJMcafZux1B/3BOe5EjV0XP6bcXZm1KpdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kFcth/dJMcafZux1B/3BOe5EjV0XP6bcXZm1KpdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kFcth/dJMcafZux1B/3BOe5EjV0XP6bcXZm1KpdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkFcth%2FdJMcafZux1B%2F3BOe5EjV0XP6bcXZm1KpdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2530&quot; height=&quot;2478&quot; data-origin-width=&quot;2530&quot; data-origin-height=&quot;2478&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 &amp;gt; 기타설정 &amp;gt; Lingma 에서 언어 변경&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1728&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FM0Vx/dJMcaiu6VWm/RIKkLMenLbsB5D1jk5kIJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FM0Vx/dJMcaiu6VWm/RIKkLMenLbsB5D1jk5kIJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FM0Vx/dJMcaiu6VWm/RIKkLMenLbsB5D1jk5kIJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFM0Vx%2FdJMcaiu6VWm%2FRIKkLMenLbsB5D1jk5kIJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1728&quot; height=&quot;510&quot; data-origin-width=&quot;1728&quot; data-origin-height=&quot;510&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;English 로 변경 됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2262&quot; data-origin-height=&quot;2350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWCxO7/dJMcagc2P9T/ZtKw48gdujFCa2PkaZQj0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWCxO7/dJMcagc2P9T/ZtKw48gdujFCa2PkaZQj0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWCxO7/dJMcagc2P9T/ZtKw48gdujFCa2PkaZQj0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWCxO7%2FdJMcagc2P9T%2FZtKw48gdujFCa2PkaZQj0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2262&quot; height=&quot;2350&quot; data-origin-width=&quot;2262&quot; data-origin-height=&quot;2350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Opt out&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Alibaba&amp;nbsp;Cloud의&amp;nbsp;기본&amp;nbsp;원칙&lt;br /&gt;Enterprise / Logged-in 계정 사용 시고객&amp;nbsp;코드&amp;nbsp;및&amp;nbsp;입력&amp;nbsp;데이터는&amp;nbsp;모델&amp;nbsp;학습에&amp;nbsp;사용하지&amp;nbsp;않음이&amp;nbsp;기본&amp;nbsp;정책&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766474529664&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Alibaba Cloud International Website Privacy Policy - Legal - Alibaba Cloud Documentation Center&quot; data-og-description=&quot;This Privacy Policy applies to the access and use of the Alibaba Cloud International Website currently located at&amp;nbsp;www.alibabacloud.comand the Alibaba Cloud International Marketplace Platform currently located at&amp;nbsp;https://marketplace.alibabacloud.com/(the &quot; data-og-host=&quot;www.alibabacloud.com&quot; data-og-source-url=&quot;https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy&quot; data-og-url=&quot;https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Alibaba Cloud International Website Privacy Policy - Legal - Alibaba Cloud Documentation Center&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This Privacy Policy applies to the access and use of the Alibaba Cloud International Website currently located at&amp;nbsp;www.alibabacloud.comand the Alibaba Cloud International Marketplace Platform currently located at&amp;nbsp;https://marketplace.alibabacloud.com/(the&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.alibabacloud.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 불안하다면,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Enable Cloud Model 을 꺼서, 정보를 보내지 않는다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pRLVo/dJMcagD7uUq/Uiq8uQ6gSvIJMIG98lwK41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pRLVo/dJMcagD7uUq/Uiq8uQ6gSvIJMIG98lwK41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pRLVo/dJMcagD7uUq/Uiq8uQ6gSvIJMIG98lwK41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpRLVo%2FdJMcagD7uUq%2FUiq8uQ6gSvIJMIG98lwK41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;346&quot; height=&quot;110&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ask / Agent Mode 에서 웹 도구 차단&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Web&amp;nbsp;tools:&amp;nbsp;Ask&amp;nbsp;every&amp;nbsp;time&lt;br /&gt;MCP&amp;nbsp;tools&amp;nbsp;in&amp;nbsp;Agent&amp;nbsp;mode:&amp;nbsp;Ask&amp;nbsp;every&amp;nbsp;time&lt;br /&gt;Terminal&amp;nbsp;in&amp;nbsp;Agent&amp;nbsp;mode:&amp;nbsp;Ask&amp;nbsp;every&amp;nbsp;time&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBNIuV/dJMcacV0bbR/zdqqDcGX6AKwPpxTkfAsa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBNIuV/dJMcacV0bbR/zdqqDcGX6AKwPpxTkfAsa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBNIuV/dJMcacV0bbR/zdqqDcGX6AKwPpxTkfAsa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBNIuV%2FdJMcacV0bbR%2FzdqqDcGX6AKwPpxTkfAsa0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1554&quot; height=&quot;618&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;~/.lingma/config.json 에서 추가&lt;/p&gt;
&lt;pre id=&quot;code_1766474926066&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;telemetry&quot;: false,
  &quot;enableDataCollection&quot;: false
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>AI Coding Assistant</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/159</guid>
      <comments>https://ride-wind.tistory.com/159#entry159comment</comments>
      <pubDate>Tue, 23 Dec 2025 16:08:14 +0900</pubDate>
    </item>
    <item>
      <title>Java 25 Performance Improvement</title>
      <link>https://ride-wind.tistory.com/158</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처 :&amp;nbsp;&lt;a href=&quot;https://www.youtube.com/watch?v=223_7r0H6OE&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=223_7r0H6OE&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=223_7r0H6OE&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/hIjJH/hyZPC6YRZZ/y8YKlds9k8NAWBsuSOvp8k/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=184_176_286_286,https://scrap.kakaocdn.net/dn/cc6SBV/hyZOEDHbs9/oDL9ZLkOx3JlT0dAjCogI0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=184_176_286_286&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;From JDK 21 to JDK 25 - Java Performance Update 2025&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/223_7r0H6OE&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JDK 21 -&amp;gt; JDK 25 upgrade 시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Latency 10% 향상&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Throughtput&amp;nbsp; 5% 향상&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Critical&amp;nbsp;JOPS:&amp;nbsp;시스템의&amp;nbsp;지연&amp;nbsp;시간(Latency)을&amp;nbsp;나타내는&amp;nbsp;수치&lt;br /&gt;Max&amp;nbsp;JOPS:&amp;nbsp;시스템의&amp;nbsp;전체적인&amp;nbsp;처리량(Throughput)을&amp;nbsp;나타내는&amp;nbsp;수치&lt;br /&gt;&lt;br /&gt;SPECjbb(Standard&amp;nbsp;Performance&amp;nbsp;Evaluation&amp;nbsp;Corporation&amp;nbsp;Java&amp;nbsp;Business&amp;nbsp;Benchmark)는&amp;nbsp;자바&amp;nbsp;비즈니스&amp;nbsp;로직&amp;nbsp;성능을&amp;nbsp;평가하기&amp;nbsp;위한&amp;nbsp;도구&lt;br /&gt;SPECjbb2015&amp;nbsp;:&amp;nbsp;2015년에&amp;nbsp;성능&amp;nbsp;평가도구가&amp;nbsp;개발되었음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;1030&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XDvt1/dJMcadm0ukh/0o4MfdKbojysXRJjrORAL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XDvt1/dJMcadm0ukh/0o4MfdKbojysXRJjrORAL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XDvt1/dJMcadm0ukh/0o4MfdKbojysXRJjrORAL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXDvt1%2FdJMcadm0ukh%2F0o4MfdKbojysXRJjrORAL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;1030&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;1030&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 그림에서 보듯이 JDK 17 -&amp;gt; 21 때는 성능 개선이 미미 했으나,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JDK 21 -&amp;gt; 25 는 괄목한 성과가 있었음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1042&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1UQbo/dJMcaiaP0CW/hedxakOf0xFA7e5JG2jE5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1UQbo/dJMcaiaP0CW/hedxakOf0xFA7e5JG2jE5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1UQbo/dJMcaiaP0CW/hedxakOf0xFA7e5JG2jE5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1UQbo%2FdJMcaiaP0CW%2FhedxakOf0xFA7e5JG2jE5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;966&quot; height=&quot;1042&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;1042&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;성능 개선 이유&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;01. &lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;컴팩트 객체 헤더 (Compact Object Headers)&lt;/span&gt;:&lt;/b&gt; 자바 객체가 차지하는 메모리 공간을 줄여 CPU 캐시 효율을 높이고 가비지 컬렉션(GC) 부담을 줄였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;02. &lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,0&quot;&gt;가상 스레드 및 스케줄러 개선:&lt;/b&gt; JDK 21에서 정식 도입된 가상 스레드의 관리 효율이 JDK 25에서 더욱 정교해졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;03. &lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,2,0&quot;&gt;Stable Values 도입:&lt;/b&gt; 변하지 않는 값을 더 빠르게 읽을 수 있도록 하는 내부 최적화가 적용되어 전체적인 실행 속도가 빨라졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;성능 항상 JEP lists&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HotSpot JVM&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JFR Java Flight Recorder&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;518: JFR Cooperative Sampling (25)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JFR 스택 추적 샘플링 방식은 스레드에 신호를 보내 강제로 멈추게 하는 방식(Signal-Base)였으나 이를 Cooperative 방식으로 전환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 신호 overhead 감소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;509: JFR CPU-Time Profiling (Experimental) (25)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JFR profiling 은 실제 경과 시간(Wall-clock time) 기준이였으나, 실제 CPU 를 점유한 순수 CPU 사용 시간 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 병목 지점 파악에 유리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;520: JFR Method Timing &amp;amp; Tracing (25)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 얼마나 자주 실행되고, 각 실행에 얼마나 시간이 걸리는지 매우 낮은 비용으로 추적할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Garbage Collectors&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;521: Generational Shenandoah (25)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기존 단일 세대(Non-generational) 로 운영되던 Shenedoah GC 에 세대별 수집(Generation)모드 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Old 보다 Young Generation 이 생성과 소멸이 많으므로 이를 나누어 수집하여, 메모리 사용과 처리량을 높임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;475: Late Barrier Expansion for G1 (24)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- G1 GC 의&amp;nbsp; Barrier code 생성 시점을 C2 JIT 마지막 단계로 지연 -&amp;gt; GC 구현이 단순해지고, 유지보수 개선 효과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;423: Region Pinning for G1 (22)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- G1 GC 에서 메모리 영역을 고정(Pinning)할 수 있는 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- GC 대기 시간 지연을 획기적으로 줄이고, OOM 오류를 방지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;474: ZGC: Generational Mode by Default (23)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- ZGC default 실행 모드를 Generational 로 변경, 비세대 모드는 중단(deprecated)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개발팀이 세대별 모드에만 집중&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;490: ZGC: Remove the Non-Generational Mode (24)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 위의 비세대 모드(Non-generational) ZGC 코드 제거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JIT Compilers&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;515: Ahead-of-Time Method Profiling (25)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Project Leyden 용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JIT compiler 는 code 가 얼마나 자주 실행되는지 profiling 한 뒤 최적하 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이 JEP 는 이전 실행에서 얻는 profiling 정보를 저장했다가 다음 실행에 즉시 사용하여, warm-up 시간을 획기적으로 단축&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Run-Time System&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;483: Ahead-of-Time Class Loading &amp;amp; Linking (24)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Project Leyden 용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기존 Java 는 클래스를 실행 시점(필요할 대) 읽어오고 연결함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이 JEP 는 App 실행 전 (CDS Archive생성단계)에 미리 처리함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;514: Ahead-of-Time Command-Line Ergonomics (25)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Project Leyden 용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JVM 은 실행될 때마다 현재 메모리 상황에 맞춰 힙 크기등을 계산합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이JEP는 계산 결과까지 미리 Archive 에 저장합니다. 시작 시 발생하는 미세한 지연 시간까지 최소화 합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;519: Compact Object Headers (25)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Project Lilliput (걸리버 여행기에 나오는 난쟁이 나라)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Java Object 의 &lt;b&gt;Header 에 Meta data 를&amp;nbsp; 128 bit -&amp;gt; 64 bit 로 압축&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 전체 Heap &lt;span style=&quot;color: #ee2323;&quot;&gt;Memory 사용량이 10~20% 감소&lt;/span&gt;,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Java Object 크기가 줄어들어 &lt;span style=&quot;color: #ee2323;&quot;&gt;실행 속도도 개선&lt;/span&gt;됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의 : &lt;b&gt;preview feature&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;491: Synchronize Virtual Threads without Pinning (24)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Project Loom 용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Virtual Thread 는 synchronized&amp;nbsp; block 안에서 I/O 작업을 만다면 실제 운영체제 스레드(Carrier Thread)에 고정되어 버리는 Pinning 문제가 있었습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이 JEP 는 synchronized 안에서도 가상 스레드가 자유롭게 Unmount/Yield 할 수 있게 합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- synchronized 를 사용하는 JDBC등의 라이브러리에서 수정 없이 Virtual Thred 를 고성능으로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;6&quot; data-path-to-node=&quot;0&quot;&gt;Helidon SE&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Oracle 의 프레임워크인 Helidon SE 을 사용하면 1.7 배(73%)의 성능 개선이 있다&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-path-to-node=&quot;0&quot; data-index-in-node=&quot;6&quot;&gt;Helidon SE&lt;/b&gt;는 오라클(Oracle)에서 개발한 마이크로서비스용 오픈소스&amp;nbsp; 경량형 자바 프레임워크 ( cf, spring boot )&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp; Netty 기반의 비동기 I/O 사용&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1682&quot; data-origin-height=&quot;898&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmh1sa/dJMcafrEdPf/yYmBMXxbiMzrMiuLoMaus1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmh1sa/dJMcafrEdPf/yYmBMXxbiMzrMiuLoMaus1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmh1sa/dJMcafrEdPf/yYmBMXxbiMzrMiuLoMaus1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcmh1sa%2FdJMcafrEdPf%2FyYmBMXxbiMzrMiuLoMaus1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1682&quot; height=&quot;898&quot; data-origin-width=&quot;1682&quot; data-origin-height=&quot;898&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ETC&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The Circle of Life for Java Code&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Java 의 특징&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Tiered Compilation&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: Interpreter -&amp;gt; C1 -&amp;gt; C2 로 처음엔 빨리 실행하고(C1), 나중에 최적하 하여 아주 빠르게 실행(C2) 하는 전략을 취한다&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;C1&amp;nbsp;:&amp;nbsp;자주&amp;nbsp;쓰이는&amp;nbsp;코드를&amp;nbsp;대상으로&amp;nbsp;하는&amp;nbsp;최적화&amp;nbsp;단계(빠른&amp;nbsp;컴파일&amp;nbsp;속도와&amp;nbsp;적절한&amp;nbsp;성능&amp;nbsp;향상&amp;nbsp;사이의&amp;nbsp;균형)&lt;br /&gt;C2&amp;nbsp;:&amp;nbsp;프로그램&amp;nbsp;실행&amp;nbsp;패턴을&amp;nbsp;붆석하여&amp;nbsp;공격적인&amp;nbsp;최적화&amp;nbsp;수행,&amp;nbsp;cpu/memory&amp;nbsp;를&amp;nbsp;많이&amp;nbsp;소모하지만,&amp;nbsp;결과물인&amp;nbsp;기계어의&amp;nbsp;실행&amp;nbsp;속도는&amp;nbsp;가장&amp;nbsp;빠름&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brmHKG/dJMcadtQuJY/MgZ7IeNXywc5ajkhmb0jFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brmHKG/dJMcadtQuJY/MgZ7IeNXywc5ajkhmb0jFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brmHKG/dJMcadtQuJY/MgZ7IeNXywc5ajkhmb0jFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrmHKG%2FdJMcadtQuJY%2FMgZ7IeNXywc5ajkhmb0jFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1278&quot; height=&quot;920&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;C2 최적화를 위한 Trick 을 위하여 아래 전략을 택할 수 있는데, 일반적이지 않고, 특화된 영역이므로 생략한다&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;inlining&lt;br /&gt;Loop&amp;nbsp;unrolling&amp;nbsp;&lt;br /&gt;Hoisting&lt;br /&gt;Dead&amp;nbsp;Code&amp;nbsp;Elimination&amp;nbsp;&lt;br /&gt;AutoVectorization&amp;nbsp;-&amp;nbsp;SuperWorld&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Reference&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;From&amp;nbsp;JDK&amp;nbsp;21&amp;nbsp;to&amp;nbsp;JDK&amp;nbsp;25&amp;nbsp;-&amp;nbsp;Java&amp;nbsp;Performance&amp;nbsp;Update&amp;nbsp;2025&lt;br /&gt;Per-Ake&amp;nbsp;Minborg&amp;nbsp;on&amp;nbsp;October&amp;nbsp;18,&amp;nbsp;2025&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inside.java/2025/10/18/devoxxbelgium-java-performance-update/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://inside.java/2025/10/18/devoxxbelgium-java-performance-update/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766287484106&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;From JDK 21 to JDK 25 - Java Performance Update 2025 &amp;ndash; Inside.java&quot; data-og-description=&quot;JDK 25 has just been released and is packed with performance improvements compared to JDK 21, allowing your unchanged application code to run even faster.In this talk, we will take a closer look at 13 concrete performance improvements made between J&amp;hellip;&quot; data-og-host=&quot;inside.java&quot; data-og-source-url=&quot;https://inside.java/2025/10/18/devoxxbelgium-java-performance-update/&quot; data-og-url=&quot;https://inside.java/2025/10/18/devoxxbelgium-java-performance-update/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/CbniS/hyZPrxzLfG/KGTz9wnW2jB2WX3oFR9ovk/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500&quot;&gt;&lt;a href=&quot;https://inside.java/2025/10/18/devoxxbelgium-java-performance-update/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://inside.java/2025/10/18/devoxxbelgium-java-performance-update/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/CbniS/hyZPrxzLfG/KGTz9wnW2jB2WX3oFR9ovk/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;From JDK 21 to JDK 25 - Java Performance Update 2025 &amp;ndash; Inside.java&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JDK 25 has just been released and is packed with performance improvements compared to JDK 21, allowing your unchanged application code to run even faster.In this talk, we will take a closer look at 13 concrete performance improvements made between J&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;inside.java&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/Java25</category>
      <category>Java25</category>
      <category>Performance Improvement</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/158</guid>
      <comments>https://ride-wind.tistory.com/158#entry158comment</comments>
      <pubDate>Sun, 21 Dec 2025 11:18:25 +0900</pubDate>
    </item>
    <item>
      <title>JEP 513 Flexible Constructor Bodies</title>
      <link>https://ride-wind.tistory.com/157</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자(Constructor)의 본문(body)에서 super(...) 또는 this(...) 호출 전에 임의의 안전한 코드; 를 작성할 수 있도록 허용하는 기능입니다.&lt;br /&gt;생성자에서 &lt;b&gt;인자 검증, 정제(trim), 계산, 필드 선 초기화&lt;/b&gt;를 superclass 호출보다 앞서 작성 가능 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존&amp;nbsp;Java는&amp;nbsp;생성자에서&amp;nbsp;다른&amp;nbsp;생성자(super/this)&amp;nbsp;호출이&amp;nbsp;첫&amp;nbsp;번째&amp;nbsp;문장이어야&amp;nbsp;했다(필수!)는&amp;nbsp;제약이&amp;nbsp;있었지만,&amp;nbsp;JEP&amp;nbsp;513은&amp;nbsp;이&amp;nbsp;제약을&amp;nbsp;완화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 문장은 반드시 super() 규칙을 깨고, 실질적으로 안전한 범위 내에서 자유도(유연성)가 부여 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Code Example&lt;/p&gt;
&lt;pre id=&quot;code_1766195539243&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 변경 전
public class Sub extends Super {
    public Sub(int x) {
        super(x);   // 반드시 첫 번째여야 함
        // 그 이후에 코드
    }
}


// 변경 후
public class PositiveBigInteger extends BigInteger {
    
    public PositiveBigInteger(long value) {
        // validation check 를 super 앞(pre-construction context)로  추가 가능
        if (value &amp;lt;= 0) {
            throw new IllegalArgumentException(&quot;non-positive value&quot;);
        }
        super(Long.toString(value));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, pre-construction context 에서는 객체가 완전히 초기화 되지 않았기 때문에&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; this, 인스턴스 필드 참조, 인스턴스 메서드 호출은 금지됩니다&lt;/p&gt;
&lt;pre id=&quot;code_1766195582626&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class X {
    private int value;

    X() {
        this.value++;     // ❌ 'this' 접근 불가
        System.out.println(value);  // ❌ 인스턴스 접근
        super();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Code Example 2 ; Enum&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대소문자 변경 후 생성자 호출 가능&lt;/p&gt;
&lt;pre id=&quot;code_1766204721544&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public enum Currency {
    USD(&quot;usd&quot;), KRW(&quot;  krw  &quot;), EUR(&quot;Eur&quot;);

    private final String code;

    // 보조 생성자
    Currency(String rawCode) {
        // 1. JEP 513 덕분에 this() 호출 전 로직 수행 가능
        if (rawCode == null || rawCode.isBlank()) {
            throw new IllegalArgumentException(&quot;코드 입력 필수&quot;);
        }
        String cleanedCode = rawCode.trim().toUpperCase();
        
        // 2. 가공된 데이터를 가지고 메인 생성자 호출
        this(cleanedCode); 
    }

    // 메인 생성자
    Currency(String code) {
        this.code = code;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;History&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f7f8fc; color: #1d1d1f; text-align: center; width: 21.0465%;&quot;&gt;버전&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc; color: #1d1d1f; text-align: center; width: 10.9303%;&quot;&gt;JEP 번호&lt;/td&gt;
&lt;td style=&quot;background-color: #f7f8fc; color: #1d1d1f; text-align: center; width: 67.907%;&quot;&gt;주요 변경 사항&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 21.0465%;&quot;&gt;Final (JDK 25)&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 10.9303%;&quot;&gt;JEP 513&lt;/td&gt;
&lt;td style=&quot;width: 67.907%;&quot;&gt;&lt;span&gt;정식 기능 확정. 구문 변경 및 안전성 보장 &lt;/span&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/513&quot;&gt;https://openjdk.org/jeps/513&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 21.0465%;&quot;&gt;3rd Preview (JDK 24)&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 10.9303%;&quot;&gt;JEP 492&lt;/td&gt;
&lt;td style=&quot;width: 67.907%;&quot;&gt;&lt;span&gt;세 번째 프리뷰. 변경 사항 없음, 추가 피드백 수집 &lt;/span&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/492&quot;&gt;https://openjdk.org/jeps/492&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 21.0465%;&quot;&gt;2nd Preview (JDK 23)&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 10.9303%;&quot;&gt;JEP 482&lt;/td&gt;
&lt;td style=&quot;width: 67.907%;&quot;&gt;&lt;span&gt;두 번째 프리뷰. Early Construction Context 개념 명확화 &lt;/span&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/482&quot;&gt;https://openjdk.org/jeps/482&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 21.0465%;&quot;&gt;1st Preview (JDK 22)&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff; color: #1d1d1f; width: 10.9303%;&quot;&gt;JEP 447&lt;/td&gt;
&lt;td style=&quot;width: 67.907%;&quot;&gt;&lt;span&gt;첫 번째 프리뷰. &quot;Unnamed Classes and Instance Main Methods&quot;에서 다른 제목으로 제안 &lt;/span&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/447&quot;&gt;https://openjdk.org/jeps/447&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Java/Java25</category>
      <category>Java25</category>
      <category>JEP 513</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/157</guid>
      <comments>https://ride-wind.tistory.com/157#entry157comment</comments>
      <pubDate>Sat, 20 Dec 2025 13:14:43 +0900</pubDate>
    </item>
    <item>
      <title>JEP 512 Compact Source File &amp;amp; Instance Main Method</title>
      <link>https://ride-wind.tistory.com/156</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자가&amp;nbsp;자바&amp;nbsp;프로그래밍을&amp;nbsp;시작할&amp;nbsp;때&amp;nbsp;겪는&amp;nbsp;복잡한&amp;nbsp;절차(Boilerplate&amp;nbsp;code)를&amp;nbsp;줄이고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소규모&amp;nbsp;프로그램이나&amp;nbsp;스크립트를&amp;nbsp;더&amp;nbsp;쉽고&amp;nbsp;간결하게&amp;nbsp;작성할&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;지원하는&amp;nbsp;기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Code Example&lt;/p&gt;
&lt;pre id=&quot;code_1766191414311&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 변경 전
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println(&quot;Hello, World!&quot;);
    }
}


// 변경 후
void main() {
    IO.println(&quot;Hello, World!&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;intellij 2025.3 으로 java25 클래스 처음 생성하면 만들어 주는 코드 예&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2136&quot; data-origin-height=&quot;1676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lYZru/dJMcai9GYS0/zpEqH8vA4f5G4716rCRnC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lYZru/dJMcai9GYS0/zpEqH8vA4f5G4716rCRnC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lYZru/dJMcai9GYS0/zpEqH8vA4f5G4716rCRnC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlYZru%2FdJMcai9GYS0%2FzpEqH8vA4f5G4716rCRnC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2136&quot; height=&quot;1676&quot; data-origin-width=&quot;2136&quot; data-origin-height=&quot;1676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;01. Compact Source files&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;public class HelloWorld {...} 없이도 필드와 메서드를 파일로 바로 작성 가능합니다&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;암시적 선언 클래스(implicitly Declared Class) 로 간주하여 처리합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;02. Instant Main Methods&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;public static void main(String[] args) 대신, 더 단순한 형태의 메인 메서드를 허용합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;03. Automatic Import&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;java.base module 전체 import, java.util.List, java.io.File 등 자주 사용되는 클래스들을 별도의 import 문 없이 사용할 수 있습니다&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;History&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 114px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot; data-sheets-root=&quot;1&quot; data-sheets-baot=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;color: #1f1f1f; width: 23.3721%; height: 19px;&quot;&gt;버전&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 10.5814%; height: 19px;&quot;&gt;JEP 번호&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 65.9302%; height: 19px;&quot;&gt;주요 변경 사항&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;color: #1f1f1f; width: 23.3721%; height: 19px;&quot;&gt;Final (JDK 25)&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 10.5814%; height: 19px;&quot;&gt;JEP 512&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 65.9302%; height: 19px;&quot;&gt;정식 기능 확정. &quot;Simple&quot; 대신 &quot;Compact&quot;로 명칭 변경 &lt;a href=&quot;https://openjdk.org/jeps/512&quot;&gt;https://openjdk.org/jeps/512&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;color: #1f1f1f; width: 23.3721%; height: 19px;&quot;&gt;4th Preview (JDK 24)&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 10.5814%; height: 19px;&quot;&gt;JEP 495&lt;/td&gt;
&lt;td style=&quot;color: #444746; width: 65.9302%; height: 19px;&quot;&gt;java.lang.IO 도입 및 java.base 자동 임포트 강화 &lt;a href=&quot;https://openjdk.org/jeps/495&quot;&gt;https://openjdk.org/jeps/495&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;color: #1f1f1f; width: 23.3721%; height: 19px;&quot;&gt;3rd Preview (JDK 23)&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 10.5814%; height: 19px;&quot;&gt;JEP 477&lt;/td&gt;
&lt;td style=&quot;color: #444746; width: 65.9302%; height: 19px;&quot;&gt;java.io.IO를 통한 간소화된 I/O 도입 (나중에 java.lang으로 이동) &lt;a href=&quot;https://openjdk.org/jeps/477&quot;&gt;https://openjdk.org/jeps/477&lt;/a&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;color: #1f1f1f; width: 23.3721%; height: 19px;&quot;&gt;2nd Preview (JDK 22)&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 10.5814%; height: 19px;&quot;&gt;JEP 463&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 65.9302%; height: 19px;&quot;&gt;&quot;Unnamed Classes&quot;에서 &quot;Implicitly Declared Classes&quot;로 개념 재정의 &lt;a href=&quot;https://openjdk.org/jeps/494&quot;&gt;https://openjdk.org/jeps/494&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;color: #1f1f1f; width: 23.3721%; height: 19px;&quot;&gt;1st Preview (JDK 21)&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 10.5814%; height: 19px;&quot;&gt;JEP 445&lt;/td&gt;
&lt;td style=&quot;color: #1f1f1f; width: 65.9302%; height: 19px;&quot;&gt;최초 도입. 이름 없는 클래스와 인스턴스 메인 메서드 개념 제안 &lt;a href=&quot;https://openjdk.org/jeps/445&quot;&gt;https://openjdk.org/jeps/445&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/Java25</category>
      <category>Java25</category>
      <category>JEP 512</category>
      <author>바람을타고2</author>
      <guid isPermaLink="true">https://ride-wind.tistory.com/156</guid>
      <comments>https://ride-wind.tistory.com/156#entry156comment</comments>
      <pubDate>Sat, 20 Dec 2025 09:48:07 +0900</pubDate>
    </item>
  </channel>
</rss>