<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>삽질탐방기</title>
    <link>https://gnnny.tistory.com/</link>
    <description>머리속에서만 존재하는 내용을 글로 정리 </description>
    <language>ko</language>
    <pubDate>Sun, 24 May 2026 02:04:39 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>그니_</managingEditor>
    <image>
      <title>삽질탐방기</title>
      <url>https://tistory1.daumcdn.net/tistory/4856875/attach/636e5e60c5904241bed48ea9f15f43b3</url>
      <link>https://gnnny.tistory.com</link>
    </image>
    <item>
      <title>2026 Microsoft AI Tour Seoul 다녀왔습니다..</title>
      <link>https://gnnny.tistory.com/25</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3월 26일, 코엑스에서 열린 마이크로소프트 AI 투어 서울에 다녀온 후기&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/belykY/dJMcajhkGE5/fTNRDqjcV84KXGQwwU2Bu1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/belykY/dJMcajhkGE5/fTNRDqjcV84KXGQwwU2Bu1/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0951.JPG&quot; style=&quot;width: 25.8507%; margin-right: 10px;&quot; data-widthpercent=&quot;26.47&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/belykY/dJMcajhkGE5/fTNRDqjcV84KXGQwwU2Bu1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbelykY%2FdJMcajhkGE5%2FfTNRDqjcV84KXGQwwU2Bu1%2Fimg.jpg&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;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nMv41/dJMcacP5FCf/uNV52dtfPKHxQCnMhyJ1FK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nMv41/dJMcacP5FCf/uNV52dtfPKHxQCnMhyJ1FK/img.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0917.JPG&quot; style=&quot;width: 45.9568%; margin-right: 10px;&quot; data-widthpercent=&quot;47.05&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nMv41/dJMcacP5FCf/uNV52dtfPKHxQCnMhyJ1FK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnMv41%2FdJMcacP5FCf%2FuNV52dtfPKHxQCnMhyJ1FK%2Fimg.jpg&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;4032&quot; height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLk9Je/dJMb99Z93LK/mgjlUkQOovHYQ96RkBbas1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLk9Je/dJMb99Z93LK/mgjlUkQOovHYQ96RkBbas1/img.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;533&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; width=&quot;534&quot; height=&quot;712&quot; data-widthpercent=&quot;26.48&quot; style=&quot;width: 25.8669%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLk9Je/dJMb99Z93LK/mgjlUkQOovHYQ96RkBbas1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLk9Je%2FdJMb99Z93LK%2FmgjlUkQOovHYQ96RkBbas1%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;400&quot; height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 갔냐면요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 말하면, 반강제로?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 다니는 회사에도 M365 Copilot이 도입되어 있는데, 막상 쓰라고 하면 뭘 어떻게 써야 하는지 막막했다. 회사에서도 AX(AI Transformation)를 연일 강조하고 있고, &quot;AI 안 쓰면 뒤처진다&quot;는 분위기가 팽배한데... 정작 현업에서 어떻게 녹여내야 할지는 감이 안 왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 MS AI Tour 세션 리스트를 봤는데, 특정 세션들이 내 환경에 너무 딱 맞았다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;폐쇄망 환경에서의 Agent 활용&lt;/li&gt;
&lt;li&gt;다중 서버 모니터링 자동화&lt;/li&gt;
&lt;li&gt;비개발 직군의 AI 접근성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;이건 가야겠다&quot;&lt;/b&gt; 싶었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;현장 분위기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아침 일찍 도착했는데, 이미 사람들이 꽤 많았다. 코엑스 오디토리움 쪽 전체가 MS 부스로 덮여 있었고, 입구부터 시작되는 등록 부스에서 뱃지를 받고 들어가니 키노트 홀이 나왔다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부스 존에서는 다양한 체험 코너가 있었다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;나만의 Agent 만들기 데모&lt;/li&gt;
&lt;li&gt;Agent를 활용한 실시간 서버 모니터링 체험&lt;/li&gt;
&lt;li&gt;이미지 생성 체험&lt;/li&gt;
&lt;li&gt;Copilot Studio로 워크플로우 자동화 구축&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자뿐 아니라 비개발 직군도 쉽게 접근할 수 있도록 구성된 게 인상적이었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;키노트: &quot;Building South Korea's AI Frontier&quot;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스콧 거스리(Scott Guthrie) MS 클라우드&amp;amp;AI 수석 부사장이 직접 왔다. 조원우 한국마이크로소프트 대표와 함께 기조연설을 진행했는데, 핵심 메시지는 명확했다:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;AI 도입은 더 이상 실험 단계가 아니다. 이제는 측정 가능한 비즈니스 성과로 전환해야 할 때다.&quot;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 AI 툴을 쓰는 게 아니라, 조직의 운영 방식 자체를 재설계해서 지속 가능한 성장을 이끌어내자는 이야기였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 사례로 KT, 현대백화점, 현대오토에버 등의 도입 사례가 소개됐다. 특히 현대백화점의 &lt;b&gt;HEYDI&lt;/b&gt;(쇼핑 큐레이션 AI 서비스)가 월 9,000건에서 8만 건으로 상호작용이 증가했다는 이야기는 꽤 충격적이었다.&lt;/p&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-filename=&quot;IMG_0902.JPG&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bawvWE/dJMcajhkGon/jZl3KxpJ9a5rizktnOrJd1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bawvWE/dJMcajhkGon/jZl3KxpJ9a5rizktnOrJd1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bawvWE/dJMcajhkGon/jZl3KxpJ9a5rizktnOrJd1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbawvWE%2FdJMcajhkGon%2FjZl3KxpJ9a5rizktnOrJd1%2Fimg.jpg&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;4032&quot; height=&quot;3024&quot; data-filename=&quot;IMG_0902.JPG&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&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;rarr; 개발 &amp;rarr; 테스트 &amp;rarr; 배포 &amp;rarr; 모니터링, 각 단계에서 에이전트가 보조하거나 아예 자동화한다. 사람은 최종 의사결정과 크리에이티브한 부분에 집중하고, 반복적인 작업은 위임한다. &quot;에이전트로 시작해 에이전트로 끝난다&quot;는 말이 과장이 아니었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WH0RR/dJMcab4H3Mz/fweg5Dmq9YXXdhVN6lbOC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WH0RR/dJMcab4H3Mz/fweg5Dmq9YXXdhVN6lbOC1/img.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;450&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;64&quot; style=&quot;width: 63.2558%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WH0RR/dJMcab4H3Mz/fweg5Dmq9YXXdhVN6lbOC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWH0RR%2FdJMcab4H3Mz%2Ffweg5Dmq9YXXdhVN6lbOC1%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;600&quot; height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ljma5/dJMcaiW1XIX/I1LTVIrYtktqnJRHtwgH21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ljma5/dJMcaiW1XIX/I1LTVIrYtktqnJRHtwgH21/img.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;800&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;36&quot; style=&quot;width: 35.5814%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ljma5/dJMcaiW1XIX/I1LTVIrYtktqnJRHtwgH21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLjma5%2FdJMcaiW1XIX%2FI1LTVIrYtktqnJRHtwgH21%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;600&quot; height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/div&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0908.JPG&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lGnmv/dJMb99Tl7Gb/pA58p43dPVvgBsmqzGtjg0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lGnmv/dJMb99Tl7Gb/pA58p43dPVvgBsmqzGtjg0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lGnmv/dJMb99Tl7Gb/pA58p43dPVvgBsmqzGtjg0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlGnmv%2FdJMb99Tl7Gb%2FpA58p43dPVvgBsmqzGtjg0%2Fimg.jpg&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;4032&quot; height=&quot;3024&quot; data-filename=&quot;IMG_0908.JPG&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&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;키노트에서 인상 깊었던 에피소드가 하나 더 있었다. 이세돌이 AI 에이전트를 활용해 18분 만에 바둑 에이전트를 만든 이야기. 한때 AI에게 역사적인 패배를 당했던 그가, 이제는 AI를 활용해 자신만의 AI를 만드는 시대가 됐다. &quot;도메인 전문가 + AI 활용 능력&quot;의 조합이 얼마나 강력한지 보여주는 사례였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0910.JPG&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/depuY1/dJMcabXW8je/yo8nePjAY5QJOULQAgVtkK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/depuY1/dJMcabXW8je/yo8nePjAY5QJOULQAgVtkK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/depuY1/dJMcabXW8je/yo8nePjAY5QJOULQAgVtkK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdepuY1%2FdJMcabXW8je%2Fyo8nePjAY5QJOULQAgVtkK%2Fimg.jpg&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;4032&quot; height=&quot;3024&quot; data-filename=&quot;IMG_0910.JPG&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들었던 세션들&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.&amp;nbsp; 인프라 관리를 위한 AI 도구 Agent 활용&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L8QZc/dJMcagEYSfW/aWwjhlGVAWmCs9bZ35G01k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L8QZc/dJMcagEYSfW/aWwjhlGVAWmCs9bZ35G01k/img.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0926.JPG&quot; style=&quot;width: 63.2558%; margin-right: 10px;&quot; data-widthpercent=&quot;64&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L8QZc/dJMcagEYSfW/aWwjhlGVAWmCs9bZ35G01k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL8QZc%2FdJMcagEYSfW%2FaWwjhlGVAWmCs9bZ35G01k%2Fimg.jpg&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;4032&quot; height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdF4E2/dJMb99Mzgnf/hKcnchrHAh1vk1D7TXordK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdF4E2/dJMb99Mzgnf/hKcnchrHAh1vk1D7TXordK/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0931.JPG&quot; style=&quot;width: 35.5814%;&quot; data-widthpercent=&quot;36&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdF4E2/dJMb99Mzgnf/hKcnchrHAh1vk1D7TXordK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdF4E2%2FdJMb99Mzgnf%2FhKcnchrHAh1vk1D7TXordK%2Fimg.jpg&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;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pnk2B/dJMcabjm4I3/JwGkIhfFrPPgukgHo65lBk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pnk2B/dJMcabjm4I3/JwGkIhfFrPPgukgHo65lBk/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0927.JPG&quot; style=&quot;width: 49.4186%; margin-right: 10px; margin-top: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pnk2B/dJMcabjm4I3/JwGkIhfFrPPgukgHo65lBk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpnk2B%2FdJMcabjm4I3%2FJwGkIhfFrPPgukgHo65lBk%2Fimg.jpg&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;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDnVrV/dJMb99Mzgne/BLhmy4mTlJCsPlvtjFgyTk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDnVrV/dJMb99Mzgne/BLhmy4mTlJCsPlvtjFgyTk/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0932.JPG&quot; style=&quot;width: 49.4186%; margin-top: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDnVrV/dJMb99Mzgne/BLhmy4mTlJCsPlvtjFgyTk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDnVrV%2FdJMb99Mzgne%2FBLhmy4mTlJCsPlvtjFgyTk%2Fimg.jpg&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;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/div&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;내가 가장 기대했던 세션. 현재 폐쇄망 환경에서 운영/개발을 하고 있는데, Agent를 어떻게 활용할 수 있을지 궁금했다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;지난 1시간 동안 CPU 80% 이상인 서버 보여줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;디스크 사용량 90% 넘는 서버에 알림 설정해&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 게 가능하다는 거다. 기존에는 Grafana + Prometheus 조합으로 대시보드 만들고, 알림 룰 직접 짜고... 했는데, 이제는 자연어로 그냥 말하면 된다.&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;2. M365 Copilot Wave 3 소개&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Wave 3의 핵심은 &lt;b&gt;Work IQ&lt;/b&gt;. 사용자의 업무 컨텍스트를 이해하고, Word/Excel/PowerPoint/Outlook 등 앱 전반에서 개인화된 경험을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Copilot Cowork&lt;/b&gt;라는 기능도 소개됐는데, 목표를 설정하면 이메일/캘린더/문서 등 M365 전반의 데이터를 기반으로 멀티스텝 작업을 계획하고 실행해준다. 아직 Frontier Program 사용자 대상 선 제공이라 실제로 써보진 못했지만, 데모 보니까 꽤 쓸만해 보였다.&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;3. Microsoft Fabric을 활용한 데이터 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 좀 생소했는데, 들어보니 꽤 강력한 플랫폼이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Microsoft Fabric&lt;/b&gt;은 한마디로:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Azure Data Factory + Synapse Analytics + Power BI를 하나로 통합한 SaaS 기반 엔드투엔드 데이터 분석 플랫폼&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 수집(Data Factory) &amp;rarr; 엔지니어링(Synapse) &amp;rarr; 분석(Power BI)까지 하나의 UI에서 가능하다. 기존에는 각각 따로 설정하고 연결해야 했는데, Fabric에서는 &lt;b&gt;OneLake&lt;/b&gt;라는 단일 데이터 레이크에 모든 워크로드가 데이터를 저장/공유한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현업에서 데이터 파이프라인 구축할 때 제일 골치 아픈 게 각 서비스 간 연결인데, 이걸 많이 줄여줄 것 같았다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;생소했던 기술/개념 정리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 하네스 엔지니어링(Harness Engineering)&lt;/h3&gt;
&lt;div data-test-render-count=&quot;1&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-is-streaming=&quot;false&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 중에 &quot;하네스 엔지니어링&quot;이라는 용어가 나왔는데, 처음 듣는 개념이라 찾아봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Harness(하네스)는 원래 말을 통제하기 위한 고삐&amp;middot;안장 등의 장비를 뜻한다. 찾아보니 하네스 엔지니어링은 AI 에이전트가 프로덕션에서 안정적으로 동작하도록 에이전트 외부 환경을 설계하는 분야라고 한다. 2026년 2월 Mitchell Hashimoto(HashiCorp 창시자)가 명명했고, OpenAI Codex 팀이 사람이 직접 작성한 코드 0줄로 100만 라인 프로덕트를 만든 사례를 공개하면서 본격적으로 주목받은 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 엔지니어링이 &quot;AI에게 뭘 시킬지&quot;에 집중한다면, 하네스 엔지니어링은 &quot;AI가 똑바로 일할 수밖에 없는 환경을 어떻게 만들지&quot;에 집중하는 느낌이다. AGENTS.md 같은 규칙 파일, 린터를 통한 아키텍처 제약 강제, 실패 시 방지책을 쌓는 피드백 루프, 고위험 작업의 사람 승인 같은 것들이 구성요소로 보인다. 인상적이었던 건 핵심 원칙인데, &quot;완벽한 하네스를 미리 설계하지 말고, 에이전트가 실수할 때마다 그 실수가 재발하지 않도록 시스템을 추가하라&quot;는 것이었다. 프롬프트를 고치는 게 아니라 구조적으로 재발을 막는다는 점이 기존 접근과 다르다고 느꼈다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-state=&quot;closed&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Microsoft Fabric&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data Factory, Synapse, Power BI 각각 설정&lt;/td&gt;
&lt;td&gt;단일 플랫폼에서 통합 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서비스 간 데이터 복제 필요&lt;/td&gt;
&lt;td&gt;OneLake에서 단일 카피로 공유&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&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;드래그앤드롭 수준의 통합&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 엔지니어, 데이터 과학자, 비즈니스 분석가 모두가 하나의 플랫폼에서 협업할 수 있다는 게 핵심이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. M365 + Copilot + Azure 연계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 원래 알고는 있었는데, 실제 데모를 보니까 연계 수준이 생각보다 깊었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Outlook에서 메일 작성 중 &amp;rarr; Copilot이 관련 문서 자동 첨부 제안&lt;/li&gt;
&lt;li&gt;Teams 미팅 중 &amp;rarr; 실시간 요약 + 액션 아이템 추출&lt;/li&gt;
&lt;li&gt;Excel 데이터 분석 &amp;rarr; 자연어로 피벗 테이블 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 앱이 개별적으로 AI 기능을 제공하는 게 아니라, &lt;b&gt;Microsoft Graph를 통해 전체 업무 컨텍스트를 공유&lt;/b&gt;하면서 일관된 경험을 제공한다는 점이 인상적이었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;재미있었던 것들&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Zava - MS의 가상 회사&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MS에서 이런 세미나를 할 때 &lt;b&gt;Zava&lt;/b&gt;라는 가상의 회사를 만들어서 데모에 활용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 방식을 &lt;b&gt;&quot;페르소나 시나리오&quot;&lt;/b&gt; 또는 데모용 가상 기업(Demo Tenant)이라고 부른다고 한다. 실제 고객 데이터를 노출하지 않으면서도 현실적인 시나리오를 보여줄 수 있어서 B2B 솔루션 데모에서 자주 쓰인다는데 몰라서 검색했음..ㅎㅎ;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연예인 데프콘이 세미나에 왔다ㅋㅋ. 유튜브 촬영인 것 같았는데, 테크 쪽에 관심 많은 것으로 알고 있어서 여기서 보니 신기했다. 예전에 IT 관련 방송도 했던 것 같은데, 이런 행사에도 오는구나.&lt;/p&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-filename=&quot;IMG_0915.JPG&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNchhC/dJMcahw6R1O/uQVGbF2Skl6uJ6kuT1xkTk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNchhC/dJMcahw6R1O/uQVGbF2Skl6uJ6kuT1xkTk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNchhC/dJMcahw6R1O/uQVGbF2Skl6uJ6kuT1xkTk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNchhC%2FdJMcahw6R1O%2FuQVGbF2Skl6uJ6kuT1xkTk%2Fimg.jpg&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;3024&quot; height=&quot;4032&quot; data-filename=&quot;IMG_0915.JPG&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;느낀 점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 에이전트로 시작해 에이전트로 끝난다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MS AI 팀의 프로젝트 데모를 보면서 느낀 건, 이제 정말 &lt;b&gt;모든 워크플로우가 에이전트 기반&lt;/b&gt;으로 재편되고 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획 &amp;rarr; 개발 &amp;rarr; 테스트 &amp;rarr; 배포 &amp;rarr; 모니터링, 각 단계에서 에이전트가 보조하거나 아예 자동화한다. 사람은 최종 의사결정과 크리에이티브한 부분에 집중하고, 반복적인 작업은 에이전트에게 위임하는 구조.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세상이 정말 빠르게 바뀌고 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 그래도 사람의 개입은 필연적&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재미있었던 건, 최근&amp;nbsp;&lt;b&gt;AWS 장애 사례&lt;/b&gt;를 언급하면서 &quot;AI에 전권을 부여하고 맹신하지 말라&quot;는 메시지를 던진 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 예로 들면서 &lt;b&gt;Human-in-the-loop&lt;/b&gt;의 중요성을 강조했다. 에이전트가 아무리 똑똑해도 최종 승인과 예외 상황 대응은 사람이 해야 한다는 이야기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 현업에서도 마찬가지다. 자동화 파이프라인 만들 때 롤백 조건이나 수동 승인 게이트를 빼먹으면 나중에 큰 사고로 이어질 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 도메인 몰라도 뭔가를 만들 수 있는 시대&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제는 특정 도메인을 몰라도 어떻게든 해결할 수 있는 시대다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전문 지식이 없어도 AI를 어떻게 활용하느냐에 따라 다양한 프로젝트를 진행할 수 있다. 물론 깊은 이해가 있으면 더 좋겠지만, &lt;b&gt;시작의 진입장벽이 현저히 낮아졌다&lt;/b&gt;는 건 분명하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 &quot;저 분야는 내 영역이 아니야&quot;라고 선을 그었던 것들도, 이제는 &quot;일단 AI한테 물어보고 시작해보자&quot;가 가능해졌다. 좋은 시대인 것 같다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;회사에 적용할 수 있을 것들&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;폐쇄망 에이전트 모니터링 PoC&lt;/b&gt;: 세션에서 본 자연어 기반 서버 모니터링 방식을 참고해서, 기존 Grafana/Prometheus 환경에 LLM 연동 검토. 온프렘 LLM(Ollama 등) + 사내 메트릭 데이터 조합으로 &quot;CPU 80% 넘는 서버 보여줘&quot; 같은 자연어 쿼리 가능한지 PoC&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반복 업무 자동화 후보 리스트업&lt;/b&gt;: 에이전트 데모 보면서 느낀 건, 결국 &quot;사람이 반복하는 일&quot;을 찾아서 자동화하는 게 핵심. 팀 내 반복 업무(배포 체크리스트, 장애 대응 초동 조치, 정기 리포트 생성 등) 리스트업하고 자동화 우선순위 정리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Human-in-the-loop 프로세스 점검&lt;/b&gt;: AWS 장애 사례 언급 들으면서, 우리 자동화 파이프라인에도 수동 승인 게이트나 롤백 조건이 제대로 있는지 점검 필요&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;a href=&quot;https://www.hankyung.com/article/202603268484g&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.hankyung.com/article/202603268484g&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1774791529693&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;MS, 서울서 AI 투어 개최&amp;hellip;韓 기업 코파일럿 도입 성과 공개&quot; data-og-description=&quot;MS, 서울서 AI 투어 개최&amp;hellip;韓 기업 코파일럿 도입 성과 공개, 홍민성 기자, IT/과학&quot; data-og-host=&quot;www.hankyung.com&quot; data-og-source-url=&quot;https://www.hankyung.com/article/202603268484g&quot; data-og-url=&quot;https://www.hankyung.com/article/202603268484g&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/7bUxV/dJMb8Rj1Th9/DMc7NI0HFKUHmkpzQU35Qk/img.jpg?width=1200&amp;amp;height=578&amp;amp;face=0_0_1200_578&quot;&gt;&lt;a href=&quot;https://www.hankyung.com/article/202603268484g&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.hankyung.com/article/202603268484g&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/7bUxV/dJMb8Rj1Th9/DMc7NI0HFKUHmkpzQU35Qk/img.jpg?width=1200&amp;amp;height=578&amp;amp;face=0_0_1200_578');&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;MS, 서울서 AI 투어 개최&amp;hellip;韓 기업 코파일럿 도입 성과 공개&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;MS, 서울서 AI 투어 개최&amp;hellip;韓 기업 코파일럿 도입 성과 공개, 홍민성 기자, IT/과학&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.hankyung.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;</description>
      <category>ETC</category>
      <category>마이크로소프트</category>
      <category>마이크로소프트 ai tour</category>
      <category>컨퍼런스</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/25</guid>
      <comments>https://gnnny.tistory.com/25#entry25comment</comments>
      <pubDate>Sun, 29 Mar 2026 23:16:20 +0900</pubDate>
    </item>
    <item>
      <title>엘라스틱서치 index_closed_exception 트러블슈팅</title>
      <link>https://gnnny.tistory.com/24</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;발단&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 스프링 앱에서 돌고 있던 스케줄 잡을 Quartz로 이관하는 작업을 맡게 됐습니다. 기존 앱을 내리기로 했고, 해당 잡을 Quartz로 옮기는 게 제 담당이었습니다.&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;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;org.elasticsearch.ElasticsearchStatusException:
  Elasticsearch exception [type=index_closed_exception, reason=closed]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 영향은 없었고 다음 실행에서 자연스럽게 복구되고 있었지만, 매일 같은 시간대에 반복된다는 게 신경 쓰여서 원인을 파악하기로 했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;p data-ke-size=&quot;size16&quot;&gt;에러 메시지를 보면 항상 특정 인덱스가 closed 상태라고 나왔습니다. 처음엔 단순 타이밍 문제인가 싶었는데, 날짜를 보니 항상 동일한 시점의 인덱스였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희는 ILM(Index Lifecycle Management)을 사용하고 있었고, warm 전환 시 인덱스가 일시적으로 close 상태로 전환됩니다. 바로 그 타이밍에 스케줄 잡이 해당 인덱스를 건드리면서 에러가 발생한 것이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index_closed_exception 자체는 ILM 외에도 수동 close, 디스크 부족, 노드 복구 과정 등 다양한 원인으로 발생할 수 있습니다. 다만 &lt;b&gt;&quot;매일 같은 시간대에, 항상 특정 일수가 지난 인덱스&quot;&lt;/b&gt; 라는 패턴이 명확하다면 ILM을 먼저 의심해보는 게 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 한 가지 더 확인한 게 있는데, 저희 검색은 alias를 통해 이루어지고 있었고 이 alias가 전체 인덱스를 바라보고 있었습니다. 쿼리에 시간 범위 필터가 있더라도 ES는 alias 하위 인덱스 전체에 요청을 브로드캐스트한 뒤 각 샤드에서 필터링하는 방식으로 동작합니다. 즉, 필터 조건과 무관하게 오래된 인덱스도 검색 대상에 포함됩니다.&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;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;[ILM] warm 전환 &amp;rarr; 인덱스 close 상태 진입
      &amp;darr;
[Quartz] alias 검색 &amp;rarr; 전체 인덱스 브로드캐스트
      &amp;darr;
[충돌] close 상태 인덱스 접근 &amp;rarr; index_closed_exception
      &amp;darr; ILM poll interval(기본 10분)마다 반복
[완료] 모든 롤오버 완료 &amp;rarr; 이후 정상&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매일 같은 시간대에 발생한 이유는 인덱스가 생성된 시간 기준으로 ILM이 트리거되기 때문입니다. 간헐적으로 여러 번 실패하는 경우는 인덱스 사이즈나 세그먼트 수에 따라 close 작업 자체가 오래 걸리는 케이스로, 그 시간 동안 잡이 연속으로 실패하는 것이었습니다. warm 전환 시 force merge가 함께 설정된 경우라면 수 분 이상 걸릴 수도 있습니다. (저희는 이 부분까지는 확인하지 못했습니다.)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;대응&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ILM 정책 수정도 검토했지만 영향 범위가 넓고, 해당 잡이 서비스에 직접적인 영향을 주는 게 아니었기 때문에 애플리케이션 레벨에서 처리하는 방향을 택했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index_closed_exception은 일시적인 상태이고 다음 실행에서 자연스럽게 복구되기 때문에, catch 후 INFO 로깅하고 skip하는 방식으로 처리했습니다.&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;div&gt;
&lt;div&gt;
&lt;pre class=&quot;java&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;try {
    SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
} catch (ElasticsearchStatusException e) {
    if (isIndexClosedException(e)) {
        log.info(&quot;[ScheduleJob] ES index temporarily closed (ILM rollover). Skipping. index={}&quot;, targetIndex);
        return;
    }
    throw e;
} catch (IOException e) {
    log.error(&quot;[ScheduleJob] ES search failed&quot;, e);
    throw new RuntimeException(e);
}

private boolean isIndexClosedException(ElasticsearchStatusException e) {
    return e.getMessage() != null
        &amp;amp;&amp;amp; e.getMessage().contains(&quot;index_closed_exception&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index_closed_exception은 항상 400 BAD_REQUEST로 오기 때문에 status 조건을 함께 체크하면 오탐 가능성을 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은 index_closed_exception만 명시적으로 구분해야 한다는 것입니다. 아래처럼 넓게 catch하면 다른 에러도 같이 묻힙니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;java&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 모든 exception을 핸들링해버리기에 취지와 맞지 않음.
} catch (Exception e) {
    log.info(&quot;에러 무시&quot;);
}

// ElasticsearchStatusException에서 index close 케이스만 처리.
} catch (ElasticsearchStatusException e) {
    if (isIndexClosedException(e)) {
        log.info(&quot;...&quot;);
        return;
    }
    log.error(&quot;[ScheduleJob] Unexpected ES error&quot;, e);
    throw e;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다른 선택지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. ignore_unavailable 옵션&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;closed 인덱스를 검색 대상에서 자동으로 제외해줍니다. 다만 데이터 누락이 발생해도 에러가 나지 않기 때문에 집계 정합성이 중요한 경우라면 적합하지 않습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;searchRequest.indicesOptions(
    IndicesOptions.fromOptions(true, true, true, false)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;2. 재시도 로직&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;close 상태가 짧게 끝나는 케이스라면 재시도로도 해결할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lisp&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;for (int i = 0; i &amp;lt; 3; i++) {
    try {
        return executeSearch();
    } catch (ElasticsearchStatusException e) {
        if (isIndexClosedException(e) &amp;amp;&amp;amp; i &amp;lt; 2) {
            log.info(&quot;[ScheduleJob] Retrying... ({}/3)&quot;, i + 1);
            Thread.sleep(3000);
            continue;
        }
        throw e;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;3.alias 검색 대상 범위 제한&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;alias가 전체 인덱스를 물고 있는 구조라면, 실제로 필요한 범위의 인덱스만 검색 대상으로 지정하는 방식으로 개선할 수 있습니다. 충돌 자체를 원천 차단할 수 있지만 인덱스 설계 변경이 수반되므로 영향 범위를 충분히 검토해야 합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 케이스의 핵심은 두 가지였습니다. ILM warm 전환 시 발생하는 일시적인 close 상태, 그리고 alias 검색이 필터 조건과 무관하게 전체 인덱스를 브로드캐스트한다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 한 가지 더 &amp;mdash; 로그 없이 예외를 삼키는 코드는 생각보다 오래 살아남습니다. 이관이나 리팩토링 작업이 이런 히스토리를 수면 위로 올리는 계기가 되기도 합니다.&lt;/p&gt;</description>
      <category>트러블슈팅 &amp;amp; 삽질기록</category>
      <category>Elasticsearch</category>
      <category>ILM</category>
      <category>엘라스틱서치</category>
      <category>트러블슈팅</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/24</guid>
      <comments>https://gnnny.tistory.com/24#entry24comment</comments>
      <pubDate>Sun, 29 Mar 2026 20:22:09 +0900</pubDate>
    </item>
    <item>
      <title>[성능개선] MongoDB 쿼리 최적화로 30% 성능 향상시키기: batchSize와 쿼리 조건 개선</title>
      <link>https://gnnny.tistory.com/23</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저는 그동안 RDBMS나 Elasticsearch처럼 익숙한 시스템들을 주로 다뤄왔고, MongoDB는 이번 프로젝트에서 처음 사용하게 되었는데요. 이 MongoDB는 실제 서비스에 등록된 사용자 데이터를 비롯한 여러 데이터들을 보관하는 용도로 사용되고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;로그수집기내에서는 이 데이터를 조회해 메모리에 캐시(Map 형태)로 적재해두고, 이후 수집된 로그 파일들에서 특정 필드를 기준으로 MongoDB의 데이터를 조인하듯 매핑해 메타데이터를 추가합니다. 그렇게 가공된 로그는 Kafka &amp;rarr; Logstash &amp;rarr; Elasticsearch로 이어지는 파이프라인을 타게 됩니다.&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;span&gt;MongoDB는 여기서 메타데이터의 원천 역할을 하고 있는 셈입니다. 이 캐시 적재 작업은 매일 새벽 한 번 실행되고 있었고, 수년간 큰 문제 없이 잘 돌아가고 있었습니다. 하지만 차세대 개발을 준비하며 기존 로직을 하나하나 살펴보는 과정에서 성능 병목 가능성이 있는 포인트를 발견했고, 직접 실험을 해보며 개선 작업을 진행해보기로 했습니다.&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;span&gt;그 결과 약 1000만 건의 데이터를 처리하는 데 걸리는 시간을 17초에서 12초로 약 32% 단축할 수 있었고, 이번 글에서는 그 개선 과정을 공유하려고 합니다.&lt;/span&gt;&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;span&gt;로컬 테스트 환경 구성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 데이터를 준비하기 위해 Docker로 MongoDB 환경을 구성했습니다. 간단한 docker-compose.yml 설정은 다음과 같습니다&lt;/p&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;version: '3.8'

services:
  mongo:
    image: mongo:8.0
    container_name: mongo-sample
    ports:
      - &quot;27017:27017&quot;
    volumes:
      - mongodb_data:/data/db
    restart: unless-stopped

volumes:
  mongodb_data:&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;데이터는 1000만 건의 고객 정보를 시딩하기 위해 아래 Java 프로그램을 작성했습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public class CustomerSeeder {
    public static void main(String[] args) {
        try (MongoClient client = MongoClients.create(&quot;mongodb://localhost:27017&quot;)) {
            MongoCollection&amp;lt;Document&amp;gt; collection = client
                    .getDatabase(&quot;example&quot;)
                    .getCollection(&quot;customer&quot;);

            int total = 10_000_000;
            int batchSize = 10_000;
            List&amp;lt;Document&amp;gt; batch = new ArrayList&amp;lt;&amp;gt;(batchSize);

            for (int seq = 0; seq &amp;lt; total; seq++) {
                String customerNo = String.format(&quot;CS%07d&quot;, seq);
                String userId = String.format(&quot;U%07d&quot;, seq);

                Document document = new Document()
                        .append(&quot;customerNo&quot;, customerNo)
                        .append(&quot;userId&quot;, userId);

                batch.add(document);

                if (batch.size() &amp;gt;= batchSize) {
                    collection.insertMany(batch);
                    batch.clear();
                }
            }

            if (!batch.isEmpty()) {
                collection.insertMany(batch);
            }

            System.out.println(&quot;생성 완료&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;이 코드는 customerNo와 userId 필드로 구성된 1000만 건의 문서를 생성하고, userId에 인덱스를 추가했습니다. 모든 userId는 null이 아닌 고유 값(U0000000 ~ U9999999)입니다.&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;기존 로직 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 시스템은 매일 새벽 1000만 건의 고객 데이터를 MongoDB에서 조회해 Java 메모리 캐시(&lt;span&gt;HashMap&lt;/span&gt;)에 적재했습니다. 사용된 쿼리는 아래 테스트 코드에서 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package org.example;

import com.mongodb.client.*;
import org.bson.Document;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import static com.mongodb.client.model.Projections.include;

public class MongoCacheLoaderTest {
    private static MongoCollection&amp;lt;Document&amp;gt; collection;

    @BeforeAll
    static void setup() {
        MongoClient client = MongoClients.create(&quot;mongodb://localhost:27017&quot;);
        MongoDatabase db = client.getDatabase(&quot;example&quot;);
        collection = db.getCollection(&quot;customer&quot;);
    }

    /* 기존 쿼리: 10,000,000건, 소요 시간: 17743ms */
    @Test
    void 기존_작성된_쿼리_및_캐시_초기화방식() {
        long start = System.currentTimeMillis();
        Map&amp;lt;String, String&amp;gt; cacheMap = new HashMap&amp;lt;&amp;gt;();

        MongoCursor&amp;lt;Document&amp;gt; cursor = collection
                .find(new Document(&quot;userId&quot;, new Document(&quot;$ne&quot;, null)))
                .projection(include(&quot;userId&quot;, &quot;customerNo&quot;))
                .iterator();

        while (cursor.hasNext()) {
            Document document = cursor.next();
            String userId = document.getString(&quot;userId&quot;);
            String customerNo = document.getString(&quot;customerNo&quot;);

            cacheMap.put(userId, customerNo);
        }

        long end = System.currentTimeMillis();
        System.out.printf(&quot;기존 쿼리: %,d건, 소요 시간: %dms%n&quot;, cacheMap.size(), (end - start));
    }
}&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;로컬 환경(Mac)에서 이 쿼리를 실행했을 때 약 17.7초가 소요되었습니다. 1일 1회 실행되는 작업이라 큰 문제는 없었지만, 성능을 개선할 여지가 있다면 의미 있는 작업이라고 판단했습니다.&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;span&gt;문제점 발견&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MongoDB 문서와 구현부의 로직들을 확인하며 파악한 문제점으 아래와 같았습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;$ne: null&lt;/span&gt; 조건의 비효율성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$ne&amp;nbsp;연산은&amp;nbsp;인덱스를&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기본 &lt;span&gt;batchSize&lt;/span&gt; (101)의 한계&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MongoDB&amp;nbsp;Java&amp;nbsp;드라이버의&amp;nbsp;기본&amp;nbsp;batchSize는&amp;nbsp;101로,&amp;nbsp;많은&amp;nbsp;네트워크&amp;nbsp;왕복을&amp;nbsp;유발하여&amp;nbsp;성능&amp;nbsp;병목이&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-pm-slice=&quot;2 4 [&amp;quot;list&amp;quot;,{&amp;quot;spread&amp;quot;:false,&amp;quot;start&amp;quot;:2679,&amp;quot;end&amp;quot;:3014}]&quot;&gt;&lt;span&gt;&lt;b&gt;try-with-resources 미사용&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기존 코드에서는 커서에 대한 리소스 해제가 누락되어 있었고, 자원 누수 가능성을 고려하면 try-with-resources 구문을 활용하는 것이 안정성 측면에서도 바람직합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;성능 개선 시도&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 세 가지를 개선했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;$ne: null 필터 제거&lt;/b&gt;&lt;/span&gt;: &lt;/b&gt;서버 측 필터링을 제거하고 클라이언트(Java)에서&amp;nbsp;null&amp;nbsp;체크를&amp;nbsp;수행했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;try-with-resources 적용&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 커서 리소스를 안전하게 해제하기 위해 try-with-resources 구문 추가 (AutoCloseable)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;batchSize 조절&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: batchSize를 10,000으로 설정해 네트워크 호출 횟수를 대폭 줄였습니다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;실제 환경에 맞춰 메모리를 고려해 1000 ~10000건의 사이즈로 구성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개선된 코드는 아래 테스트 코드에서 확인할 수 있습니다&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package org.example;

import com.mongodb.client.*;
import org.bson.Document;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import static com.mongodb.client.model.Projections.include;

public class MongoCacheLoaderTest {
    private static MongoCollection&amp;lt;Document&amp;gt; collection;

    @BeforeAll
    static void setup() {
        MongoClient client = MongoClients.create(&quot;mongodb://localhost:27017&quot;);
        MongoDatabase db = client.getDatabase(&quot;example&quot;);
        collection = db.getCollection(&quot;customer&quot;);
    }

    /* 개선 쿼리:  10,000,000건, 소요 시간: 11967ms */
    @Test
    void 개선된_쿼리_및_캐시_초기화방식() {
        long start = System.currentTimeMillis();
        Map&amp;lt;String, String&amp;gt; cacheMap = new HashMap&amp;lt;&amp;gt;();

        FindIterable&amp;lt;Document&amp;gt; cursor = collection
                .find()
                .projection(include(&quot;userId&quot;, &quot;customerNo&quot;))
                .batchSize(10000);

        try (MongoCursor&amp;lt;Document&amp;gt; it = cursor.iterator()) {
            while (it.hasNext()) {
                Document doc = it.next();
                String userId = doc.getString(&quot;userId&quot;);
                String customerNo = doc.getString(&quot;customerNo&quot;);

                if (userId != null) {
                    cacheMap.put(userId, customerNo);
                }
            }
        }

        long end = System.currentTimeMillis();
        System.out.printf(&quot;개선 쿼리: %,d건, 소요 시간: %dms%n&quot;, cacheMap.size(), (end - start));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;결과&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;개선된 쿼리를 로컬 환경에서 실행한 결과, 처리 시간이 &lt;/span&gt;&lt;span&gt;&lt;b&gt;17.7초&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;12.0초&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 약 32% 단축되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;마무리하며&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번 작업은 단순한 쿼리 하나도 어떤 조건이 인덱스에 영향을 주고 실행 계획이 어떻게 달라지는지, 실제로 데이터를 넣고 &lt;/span&gt;&lt;span&gt;explain()&lt;/span&gt;&lt;span&gt;으로 실행 계획을 확인하며 하나하나 실험해 본 과정이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;작업을 하면서 다음과 같은 인사이트가 확실히 남았습니다&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;쿼리 조건 하나로 인덱스가 무력화될 수 있다&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;batchSize 조정만으로도 눈에 띄는 성능 차이를 만들 수 있다&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;커서를 안전하게 닫는 습관은 성능보다도 안정성 측면에서 중요하다&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;없을까?&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;&lt;span&gt;비슷한 환경에서 MongoDB를 사용하는 분들께도, 이 사례가 작은 힌트라도 되었으면 합니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>성능개선</category>
      <category>index</category>
      <category>java</category>
      <category>mongodb</category>
      <category>성능개선</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/23</guid>
      <comments>https://gnnny.tistory.com/23#entry23comment</comments>
      <pubDate>Sun, 3 Aug 2025 16:07:00 +0900</pubDate>
    </item>
    <item>
      <title>Apache HTTPD 버전 업그레이드 중 MPM 이슈와 해결 과정</title>
      <link>https://gnnny.tistory.com/22</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 회사에서 보안 취약점 점검 결과, Apache HTTPD 버전 업그레이드를 진행해야 했다. 기존에 사용하던 버전은 2.4.5x였고, 2025년 초 기준으로 2.4.6x 버전으로 올려야 하는 과제가 주어졌다. 사내 환경은 httpd, Nginx, Tomcat 등등 이외에도 다양한 웹/WAS 서버로 구성되어 있는데, 서비스 영향도를 고려해 영향도가 적은 서버부터 업그레이드를 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존엔 nginx를 주로 쓰다보니 httpd 버전 업그레이드는 처음 해보는 작업이었다. 게다가 금융권 폐쇄망의 온프레미스 환경이라 설정 및 배포에 제약이 많았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소 Docker로 편하게 작업하던 터라, 사전에 준비된 설치 파일을 하나하나 업로드 후 빌드해야 하는 상황이 좀 아쉬웠다. 폐쇄망이라 외부 레포지토리 접근도 안 되고, 모든 의존성을 미리 준비해야 하니 정신없었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이슈 발생: MPM 모듈 문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업그레이드를 위해 소스 파일을 다운로드하고, 아래와 같은 &lt;span&gt;configure&lt;/span&gt; 명령어로 빌드를 진행 후 설치를 진행했다. (참고로, 이 설정은 실제 환경과 다르며, 오류 상황을 재현하기 위해 임의로 구성한 것이다.)&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-compact-layout=&quot;false&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;./configure --prefix=/home/web/httpd \
            --enable-so \
            --enable-ssl \
            --with-included-apr \
            --enable-mpms-shared=all
            
            
make &amp;amp;&amp;amp; make install&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.28.37.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bC0rJU/btsPpSZYhY8/ReBDO67jk2Yk1Oq55SXPa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bC0rJU/btsPpSZYhY8/ReBDO67jk2Yk1Oq55SXPa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bC0rJU/btsPpSZYhY8/ReBDO67jk2Yk1Oq55SXPa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbC0rJU%2FbtsPpSZYhY8%2FReBDO67jk2Yk1Oq55SXPa0%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;700&quot; height=&quot;212&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.28.37.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;466&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-compact-layout=&quot;false&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;AH00534: httpd: Configuration error: No MPM loaded.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그를 보니 MPM(Module Process Model) 모듈을 로드하지 못했다는 메시지였다. Apache HTTPD는 요청 처리 방식을 결정하는 MPM 모듈을 필수로 로드해야 하는데, 이게 제대로 설정되지 않은 게 문제였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 파악&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apache HTTPD는 MPM을 통해 프로세스와 스레드 처리 방식을 정의한다. 주요 MPM은 &lt;span&gt;prefork&lt;/span&gt;, &lt;span&gt;worker&lt;/span&gt;, &lt;span&gt;event&lt;/span&gt; 세 가지로, 각각의 특징은 아래 표와 같다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;&lt;span&gt;&lt;b&gt;prefork&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;&lt;span&gt;프로세스 기반, 안정성과 CGI 호환성이 높지만 성능은 상대적으로 느림&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;&lt;span&gt;&lt;b&gt;worker&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;&lt;span&gt;스레드 기반, 메모리 효율이 좋고 고성능을 제공&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;&lt;span&gt;&lt;b&gt;event&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td colspan=&quot;1&quot; rowspan=&quot;1&quot;&gt;&lt;span&gt;최신 방식, 비동기 Keep-Alive를 지원해 성능과 확장성이 뛰어남&lt;/span&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;우리 환경은 성능 최적화를 위해 &lt;span&gt;event&lt;/span&gt; MPM을 주로 사용하고 있었다. 그런데 &lt;span&gt;--enable-mpms-shared=all&lt;/span&gt; 옵션으로 모든 MPM을 공유 모듈로 빌드했음에도, &lt;span&gt;httpd.conf&lt;/span&gt; 파일에서 어떤 MPM도 로드되지 않은 상태였다. 확인해보니 &lt;span&gt;prefork&lt;/span&gt;, &lt;span&gt;worker&lt;/span&gt;, &lt;span&gt;event&lt;/span&gt; 모듈이 모두 주석 처리되어 있어 서버가 MPM을 선택하지 못한 상황이었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결법은 생각보다(?) 간단했다. &lt;span&gt;httpd.conf&lt;/span&gt; 파일에서 &lt;span&gt;event&lt;/span&gt; MPM 모듈을 명시적으로 로드하도록 설정하면 됐다. 아래는 해결 과정이다.&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&gt;1. httpd.conf&lt;/span&gt; 파일을 열어 MPM 관련 설정을 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.28.09.png&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnOF0d/btsPrp3f1Jr/29Ra1QyRs9PQfTsEaQKaSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnOF0d/btsPrp3f1Jr/29Ra1QyRs9PQfTsEaQKaSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnOF0d/btsPrp3f1Jr/29Ra1QyRs9PQfTsEaQKaSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnOF0d%2FbtsPrp3f1Jr%2F29Ra1QyRs9PQfTsEaQKaSk%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;700&quot; height=&quot;197&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.28.09.png&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;430&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;span&gt;2. event&lt;/span&gt; MPM 모듈을 로드하도록 아래 줄을 추가하거나, 주석 처리된 부분의 주석을 해제한다.&lt;/p&gt;
&lt;pre class=&quot;apache&quot; data-compact-layout=&quot;false&quot;&gt;&lt;code&gt;LoadModule mpm_event_module modules/mod_mpm_event.so&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;3. 다른 MPM 모듈(&lt;span&gt;prefork&lt;/span&gt;, &lt;span&gt;worker&lt;/span&gt;)은 충돌 방지를 위해 주석 처리하거나 제거한다.&lt;/p&gt;
&lt;pre class=&quot;apache&quot; data-compact-layout=&quot;false&quot;&gt;&lt;code&gt;#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.31.47.png&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RajBM/btsPpWIfTrk/71Ewicxq8ZMED8DEZdg9f0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RajBM/btsPpWIfTrk/71Ewicxq8ZMED8DEZdg9f0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RajBM/btsPpWIfTrk/71Ewicxq8ZMED8DEZdg9f0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRajBM%2FbtsPpWIfTrk%2F71Ewicxq8ZMED8DEZdg9f0%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;700&quot; height=&quot;210&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.31.47.png&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;460&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;4. 설정을 저장한 뒤 서버를 재시작한다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot; data-compact-layout=&quot;false&quot;&gt;&lt;code&gt;/home/web/httpd/bin/httpd -k restart&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배운 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 이슈를 통해 몇 가지 교훈을 얻었다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-tight=&quot;true&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;MPM 설정 점검 필수&lt;/b&gt;: &lt;span&gt;httpd.conf&lt;/span&gt;에서 MPM 모듈을 명시적으로 로드하지 않으면 이런 에러가 발생한다. 빌드 옵션과 설정 파일을 꼼꼼히 확인해야 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;폐쇄망의 고충&lt;/b&gt;: 온프레미스 폐쇄망 환경에서는 설치 파일과 의존성을 미리 준비하는 게 중요하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그&lt;/b&gt;: 에러 로그는 문제의 원인을 찾는 데 최고의 단서다.&amp;nbsp;메시지를 보고 바로 MPM 설정을 점검할 수 있었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.28.09.png&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCYHHp/btsPqAxGICL/5Y77vqpMU6lLn3dAf9eknK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCYHHp/btsPqAxGICL/5Y77vqpMU6lLn3dAf9eknK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCYHHp/btsPqAxGICL/5Y77vqpMU6lLn3dAf9eknK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCYHHp%2FbtsPqAxGICL%2F5Y77vqpMU6lLn3dAf9eknK%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;700&quot; height=&quot;197&quot; data-filename=&quot;스크린샷 2025-07-20 오후 10.28.09.png&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;430&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 비슷한 작업을 할 때는 빌드 옵션과 설정 파일을 더 꼼꼼히 확인해야겠다는 생각이 든다. 이 글을 읽는 분들도 MPM 관련 에러가 발생한다면, &lt;span&gt;httpd.conf&lt;/span&gt;에서 모듈 로드 설정을 먼저 확인해보시길 추천한다!&lt;/p&gt;</description>
      <category>트러블슈팅 &amp;amp; 삽질기록</category>
      <category>Apache</category>
      <category>httpd</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/22</guid>
      <comments>https://gnnny.tistory.com/22#entry22comment</comments>
      <pubDate>Sun, 20 Jul 2025 23:02:51 +0900</pubDate>
    </item>
    <item>
      <title>ChatGPT 채팅 삭제, 크롬 확장 프로그램으로 자동화하기</title>
      <link>https://gnnny.tistory.com/21</link>
      <description>&lt;p data-end=&quot;360&quot; data-start=&quot;260&quot; data-ke-size=&quot;size16&quot;&gt;ChatGPT를 쓰다 보면 대화 기록이 계속 사이드바에 남게 됩니다. 삭제하려면 수동으로 하나씩 지워야 하고, 대화량이 많아질수록 꽤 번거로운 작업이 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;356&quot; data-start=&quot;278&quot; data-ke-size=&quot;size16&quot;&gt;저는 ChatGPT를 자주 사용하는 편인데, 개인적으로 채팅 목록을 깔끔하게 정리하고 싶어서 직접 확장 프로그램을 만들어보기로 했습니다.&lt;/p&gt;
&lt;p data-end=&quot;501&quot; data-start=&quot;358&quot; data-ke-size=&quot;size16&quot;&gt;프론트엔드 쪽은 따로 경험이 없어서 처음부터 혼자 구현하긴 어려웠고, 기본적인 구조와 접근 방식은 &lt;b&gt;ChatGPT에게 도움을 받아&lt;/b&gt; 시작했습니다.&lt;br /&gt;그 후 실제 DOM 구조나 동작을 보면서 &lt;b&gt;디버깅하며 필요한 부분을 수정해가며 완성&lt;/b&gt;한 형태입니다.&lt;/p&gt;
&lt;p data-end=&quot;533&quot; data-start=&quot;503&quot; data-ke-size=&quot;size16&quot;&gt;이름은 chatgpt-chat-remover입니다.&lt;/p&gt;
&lt;p data-end=&quot;372&quot; data-start=&quot;273&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;549&quot; data-start=&quot;540&quot; data-ke-size=&quot;size23&quot;&gt;주요 기능&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;640&quot; data-start=&quot;551&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;599&quot; data-start=&quot;551&quot;&gt;&lt;b&gt;전체 삭제&lt;/b&gt;: 기존 채팅 목록 전체를 선택해 한 번에 삭제할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;640&quot; data-start=&quot;600&quot;&gt;&lt;b&gt;선택 삭제&lt;/b&gt;: 원하는 대화만 체크해서 개별 삭제할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;755&quot; data-start=&quot;642&quot; data-ke-size=&quot;size16&quot;&gt;참고: 이 확장 프로그램에서 사용하는 삭제 방식은 실제 데이터를 완전히 삭제하는 것이 아니라, ChatGPT 백엔드 API를 통해 is_visible: false로 설정하여 &lt;b&gt;UI에서 해당 채팅을 숨기는 방식&lt;/b&gt;입니다.&lt;br /&gt;이는 ChatGPT 자체의 기본 삭제 동작과 동일합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;771&quot; data-start=&quot;762&quot; data-ke-size=&quot;size23&quot;&gt;작동 방식&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1246&quot; data-start=&quot;773&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;853&quot; data-start=&quot;773&quot;&gt;content.js에서는 ChatGPT DOM 구조에 접근해 각 채팅 항목에 체크박스를 삽입하고, 상단에 컨트롤 버튼 UI를 추가합니다.&lt;/li&gt;
&lt;li data-end=&quot;923&quot; data-start=&quot;854&quot;&gt;선택된 채팅 ID들을 모아서 백엔드 API로 PATCH 요청을 보내 is_visible: false로 처리합니다.&lt;/li&gt;
&lt;li data-end=&quot;1058&quot; data-start=&quot;924&quot;&gt;accessToken은 script 태그 내부 문자열을 대상으로 JSON 파싱을 통해 추출합니다.&lt;br /&gt;(window.__reactRouterContext.streamController.enqueue(...) 내부 구조 사용)&lt;/li&gt;
&lt;li data-end=&quot;1163&quot; data-start=&quot;1059&quot;&gt;상태 저장은 window 객체의 플래그 변수(chatRemoverAllSelected, chatRemoverObserverInitialized)를 사용해 간단히 처리합니다.&lt;/li&gt;
&lt;li data-end=&quot;1246&quot; data-start=&quot;1164&quot;&gt;MutationObserver를 사용해 ChatGPT의 SPA 구조에서도 UI가 바뀔 때마다 체크박스와 버튼이 다시 삽입되도록 구성했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;1529&quot; data-start=&quot;1520&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동작 영상&lt;/h3&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-filename=&quot;기록.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J5NvP/btsMZXOSLRL/NviPS28GRYPr1zU2KTrBB1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J5NvP/btsMZXOSLRL/NviPS28GRYPr1zU2KTrBB1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J5NvP/btsMZXOSLRL/NviPS28GRYPr1zU2KTrBB1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/J5NvP/btsMZXOSLRL/NviPS28GRYPr1zU2KTrBB1/img.gif&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;722&quot; height=&quot;729&quot; data-filename=&quot;기록.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;606&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;h3 data-end=&quot;1529&quot; data-start=&quot;1520&quot; data-ke-size=&quot;size23&quot;&gt;개발 중 겪었던 어려움&lt;/h3&gt;
&lt;h4 data-end=&quot;1289&quot; data-start=&quot;1271&quot; data-ke-size=&quot;size20&quot;&gt;1. CORS 우회 문제&lt;/h4&gt;
&lt;p data-end=&quot;1422&quot; data-start=&quot;1290&quot; data-ke-size=&quot;size16&quot;&gt;ChatGPT 백엔드 API(&lt;a href=&quot;https://chatgpt.com/backend-api/conversation/&quot;&gt;https://chatgpt.com/backend-api/conversation/&lt;/a&gt;{id})에 직접 요청을 보내는 구조이기 때문에, 크롬 확장 프로그램의 권한 범위에서 안전하게 동작하도록 구성해야 했습니다.&lt;/p&gt;
&lt;h4 data-end=&quot;1446&quot; data-start=&quot;1424&quot; data-ke-size=&quot;size20&quot;&gt;2. accessToken 추출&lt;/h4&gt;
&lt;p data-end=&quot;1594&quot; data-start=&quot;1447&quot; data-ke-size=&quot;size16&quot;&gt;기존 웹 서비스처럼 토큰이 쿠키나 스토리지에 저장되어 있지 않고, React 내부 함수의 인자로 넘어오기 때문에 해당 스크립트에서 문자열을 직접 파싱해야 했습니다. 이 과정에서 JSON이 이중으로 인코딩되어 있어, 디버깅하며 처리 순서를 하나씩 정리해 나갔습니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1610&quot; data-start=&quot;1601&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;1610&quot; data-start=&quot;1601&quot; data-ke-size=&quot;size23&quot;&gt;향후 계획&lt;/h3&gt;
&lt;p data-end=&quot;1696&quot; data-start=&quot;1612&quot; data-ke-size=&quot;size16&quot;&gt;더 이상의 기능 추가는 예정되어 있지 않습니다.&lt;br /&gt;현재 상태에서 필요한 기능은 모두 구현되어 있고, 실제 사용 환경에서도 목적에 부합하기 때문입니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1710&quot; data-start=&quot;1703&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;1818&quot; data-start=&quot;1811&quot; data-ke-size=&quot;size23&quot;&gt;마무리&lt;/h3&gt;
&lt;p data-end=&quot;1888&quot; data-start=&quot;1820&quot; data-ke-size=&quot;size16&quot;&gt;ChatGPT 채팅을 주기적으로 정리하거나, 불필요한 대화 목록을 깔끔하게 지우고 싶은 분들에게는 꽤 실용적인 도구입니다.&lt;/p&gt;
&lt;p data-end=&quot;1976&quot; data-start=&quot;1890&quot; data-ke-size=&quot;size16&quot;&gt;현재 이 확장 프로그램은 &lt;b&gt;Chrome Web Store에 등록 완료 후 검토 중&lt;/b&gt;입니다.&lt;br /&gt;심사가 완료되면 설치 링크도 함께 업데이트할 예정입니다.&lt;/p&gt;
&lt;p data-end=&quot;2079&quot; data-start=&quot;1978&quot; data-ke-size=&quot;size16&quot;&gt;배포 전이긴 하지만, 로컬에서 크롬 확장으로 직접 설치해서 사용하기에도 가볍고 직관적인 구조입니다.&lt;br /&gt;필요하신 분들은 직접 적용해보시거나, 내부 코드 참고하셔도 좋을 것 같습니다.&lt;/p&gt;
&lt;p data-end=&quot;2079&quot; data-start=&quot;1978&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2211&quot; data-start=&quot;2081&quot; data-ke-size=&quot;size16&quot;&gt;소스코드는 아래 GitHub에서 확인하실 수 있습니다.&lt;br /&gt;  &lt;a href=&quot;https://github.com/kgggh/chatgpt-chat-remover&quot;&gt;https://github.com/kgggh/chatgpt-chat-remover&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1743414892218&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 - kgggh/chatgpt-chat-remover: ChatGPT 채팅 기록을 손쉽게 삭제할 수 있는 크롬 확장 프로그램&quot; data-og-description=&quot;ChatGPT 채팅 기록을 손쉽게 삭제할 수 있는 크롬 확장 프로그램. Contribute to kgggh/chatgpt-chat-remover development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kgggh/chatgpt-chat-remover&quot; data-og-url=&quot;https://github.com/kgggh/chatgpt-chat-remover&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bqyeWF/hyYyQYeuqu/6NqcCGajBNZwhHgKNsf7a0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/daX8iA/hyYxSvP0AS/QQtkx0bLuSYFp6TaN8ghAK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kgggh/chatgpt-chat-remover&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kgggh/chatgpt-chat-remover&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bqyeWF/hyYyQYeuqu/6NqcCGajBNZwhHgKNsf7a0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/daX8iA/hyYxSvP0AS/QQtkx0bLuSYFp6TaN8ghAK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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 - kgggh/chatgpt-chat-remover: ChatGPT 채팅 기록을 손쉽게 삭제할 수 있는 크롬 확장 프로그램&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;ChatGPT 채팅 기록을 손쉽게 삭제할 수 있는 크롬 확장 프로그램. Contribute to kgggh/chatgpt-chat-remover 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;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;업데이트 (2025.3.31 월)&lt;/b&gt;&lt;br /&gt;해당 확장 프로그램이 &lt;b&gt;오늘부로 크롬 웹 스토어에 정식 등록&lt;/b&gt;되어, 이제 누구나 다운로드 후 바로 사용하실 수 있습니다!&lt;br /&gt;  &lt;a href=&quot;https://chromewebstore.google.com/detail/chatgpt-chat-remover/phmfclnecknfopohajjkdacfhbmhjako?authuser=0&amp;amp;hl=ko&quot; data-end=&quot;635&quot; data-start=&quot;501&quot;&gt;Chrome 웹 스토어에서 설치하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1743414905747&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;ChatGPT Chat Remover - Chrome 웹 스토어&quot; data-og-description=&quot;Select and delete multiple chats in ChatGPT.&quot; data-og-host=&quot;chromewebstore.google.com&quot; data-og-source-url=&quot;https://chromewebstore.google.com/detail/chatgpt-chat-remover/phmfclnecknfopohajjkdacfhbmhjako?authuser=0&amp;amp;hl=ko&quot; data-og-url=&quot;https://chromewebstore.google.com/detail/chatgpt-chat-remover/phmfclnecknfopohajjkdacfhbmhjako&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/byETbK/hyYBbUOuIC/jMWkysk1AbZyRWAyOJC1IK/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128&quot;&gt;&lt;a href=&quot;https://chromewebstore.google.com/detail/chatgpt-chat-remover/phmfclnecknfopohajjkdacfhbmhjako?authuser=0&amp;amp;hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chromewebstore.google.com/detail/chatgpt-chat-remover/phmfclnecknfopohajjkdacfhbmhjako?authuser=0&amp;amp;hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/byETbK/hyYBbUOuIC/jMWkysk1AbZyRWAyOJC1IK/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128');&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;ChatGPT Chat Remover - Chrome 웹 스토어&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Select and delete multiple chats in ChatGPT.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chromewebstore.google.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;</description>
      <category>개발</category>
      <category>ChatGPT</category>
      <category>chatgpt 기록 삭제</category>
      <category>chatgpt 정리</category>
      <category>chatgpt 채팅 삭제</category>
      <category>chatgpt 확장 추천</category>
      <category>chatgpt 확장 프로그램</category>
      <category>chatgpt 히스토리 삭제</category>
      <category>GPT 플러그인</category>
      <category>크롬 확장 프로그램</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/21</guid>
      <comments>https://gnnny.tistory.com/21#entry21comment</comments>
      <pubDate>Fri, 28 Mar 2025 00:44:41 +0900</pubDate>
    </item>
    <item>
      <title>Spring Boot 3.4.3에서 Auto-configuration이 동작하지 않는 문제 해결</title>
      <link>https://gnnny.tistory.com/20</link>
      <description>&lt;h2 data-end=&quot;79&quot; data-start=&quot;65&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;196&quot; data-start=&quot;80&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot 3.4.3에서 라이브러리를 개발하면서 META-INF/spring.factories에 EnableAutoConfiguration을 등록했지만, 자동 설정이 적용되지 않았습니다......&lt;/p&gt;
&lt;p data-end=&quot;299&quot; data-start=&quot;198&quot; data-ke-size=&quot;size16&quot;&gt;문서를 찾아보니 &lt;b&gt;Spring Boot 2.7 Release Notes&lt;/b&gt;와 &lt;b&gt;Spring Boot 3.0 Migration Guide&lt;/b&gt;에서 관련 내용을 다루고 있었습니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;299&quot; data-start=&quot;198&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;320&quot; data-start=&quot;306&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;원인 분석&lt;/b&gt;&lt;/h2&gt;
&lt;h2 data-end=&quot;320&quot; data-start=&quot;306&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Spring Boot 2.7에서 변경된 Auto-configuration 등록 방식&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;468&quot; data-start=&quot;379&quot; data-ke-size=&quot;size16&quot;&gt;기존에는 spring.factories에 자동 구성 클래스를 쉼표로 구분하여 등록했지만, Spring Boot 2.7부터는 새로운 방식이 추가되었습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;781&quot; data-start=&quot;470&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;585&quot; data-start=&quot;470&quot;&gt;기존 방식: spring.factories에서 org.springframework.boot.autoconfigure.EnableAutoConfiguration 키 아래 등록하는 방식&lt;/li&gt;
&lt;li data-end=&quot;699&quot; data-start=&quot;586&quot;&gt;새로운 방식: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일에 한 줄씩 등록&lt;/li&gt;
&lt;li data-end=&quot;781&quot; data-start=&quot;744&quot;&gt;Spring Boot 2.7에서는 두 방식 모두 사용할 수 있었으며, 중복이 있을 경우 자동으로 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;912&quot; data-start=&quot;783&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot 2.7에서는 호환성을 위해 기존 방식과 신규 방식으로도 등록할 수 있었습니다.&lt;/p&gt;
&lt;p data-end=&quot;1052&quot; data-start=&quot;914&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; data-end=&quot;1028&quot; data-start=&quot;914&quot;&gt;Spring Boot 2.7 Release Notes&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1741510983128&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;Spring Boot 2.7 Release Notes&quot; data-og-description=&quot;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; data-og-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bBCX5R/hyYmOtXduV/6Syh6TT8balhBQN7xhfVDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cuemjB/hyYmYQQJhf/mjnzNIKAfjhd6NtzwKMfyk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bBCX5R/hyYmOtXduV/6Syh6TT8balhBQN7xhfVDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cuemjB/hyYmYQQJhf/mjnzNIKAfjhd6NtzwKMfyk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;Spring Boot 2.7 Release Notes&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&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;h3 data-end=&quot;1095&quot; data-start=&quot;1059&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;1095&quot; data-start=&quot;1059&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Spring Boot 3.0부터 기존 방식 제거&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1183&quot; data-start=&quot;1096&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot 3.0부터는 spring.factories에서 EnableAutoConfiguration 키를 이용한 등록이 삭제되었습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1412&quot; data-start=&quot;1185&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1272&quot; data-start=&quot;1185&quot;&gt;Spring Boot 2.7에서는 spring.factories와 AutoConfiguration.imports 두 방식이 모두 가능&lt;/li&gt;
&lt;li data-end=&quot;1331&quot; data-start=&quot;1273&quot;&gt;Spring Boot 3.0부터는 AutoConfiguration.imports만 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1633&quot; data-start=&quot;1488&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; data-end=&quot;1606&quot; data-start=&quot;1488&quot;&gt;Spring Boot 3.0 Migration Guide&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1741510986504&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;Spring Boot 3.0 Migration Guide&quot; data-og-description=&quot;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; data-og-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/GfMKT/hyYrRIXSDk/mARAe4R22DE1KODE50RZCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cigSZE/hyYmQZB0HW/V7Jr6w559Rso348YEUFak1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/GfMKT/hyYrRIXSDk/mARAe4R22DE1KODE50RZCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cigSZE/hyYmQZB0HW/V7Jr6w559Rso348YEUFak1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;Spring Boot 3.0 Migration Guide&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&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-end=&quot;1633&quot; data-start=&quot;1488&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1657&quot; data-start=&quot;1640&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;변경 사항 정리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot 버전지원 방식&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1928&quot; data-start=&quot;1659&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1928&quot; data-start=&quot;1726&quot;&gt;
&lt;tr data-end=&quot;1772&quot; data-start=&quot;1726&quot;&gt;
&lt;td&gt;&lt;b&gt;2.6 이하&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;spring.factories 만 지원됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1849&quot; data-start=&quot;1773&quot;&gt;
&lt;td&gt;&lt;b&gt;2.7&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;spring.factories + AutoConfiguration.imports (둘 다 사용 가능)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1928&quot; data-start=&quot;1850&quot;&gt;
&lt;td&gt;&lt;b&gt;3.0 이상&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;AutoConfiguration.imports 만 지원됩니다. (spring.factories 삭제)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-end=&quot;1992&quot; data-start=&quot;1930&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot 3.x에서는 기존 spring.factories 방식이 더 이상 동작하지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;2100&quot; data-start=&quot;1994&quot; data-ke-size=&quot;size16&quot;&gt;이제는 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일을 작성해 사용해야 합니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;2100&quot; data-start=&quot;1994&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;2121&quot; data-start=&quot;2107&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;2166&quot; data-start=&quot;2123&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;기존 방식 (Spring Boot 3.x에서 지원되지 않음)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;2210&quot; data-start=&quot;2167&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;resources/META-INF/spring.factories&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1741510777813&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gnnny.deadlock4j.spring.boot.autoconfigure.DeadlockBusterAutoConfig&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;2409&quot; data-start=&quot;2367&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;새로운 방식 (Spring Boot 3.x에서 적용 가능)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;2508&quot; data-start=&quot;2410&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1741510800998&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;com.gnnny.deadlock4j.spring.boot.autoconfigure.DeadlockBusterAutoConfig&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2663&quot; data-start=&quot;2600&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot 3.x부터는 spring.factories에 등록하는 방식이 아예 동작하지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;2724&quot; data-start=&quot;2665&quot; data-ke-size=&quot;size16&quot;&gt;AutoConfiguration.imports 파일을 만들고, 여기에 한 줄씩 등록하면 해결됩니다.&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-end=&quot;2742&quot; data-start=&quot;2731&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-end=&quot;2742&quot; data-start=&quot;2731&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;2806&quot; data-start=&quot;2744&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot 3.x에서는 기존 spring.factories 방식이 더 이상 지원되지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;2912&quot; data-start=&quot;2808&quot; data-ke-size=&quot;size16&quot;&gt;3.x 이상버전에선 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일을 사용해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;2912&quot; data-start=&quot;2808&quot; data-ke-size=&quot;size16&quot;&gt;역시 안될땐 문서를 찾아보기.....ㅎㅎ&lt;/p&gt;
&lt;p data-end=&quot;2968&quot; data-start=&quot;2914&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;2989&quot; data-start=&quot;2975&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고 문서&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-is-last-node=&quot;&quot; data-is-only-node=&quot;&quot; data-end=&quot;3232&quot; data-start=&quot;2991&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3109&quot; data-start=&quot;2991&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; data-end=&quot;3107&quot; data-start=&quot;2993&quot;&gt;Spring Boot 2.7 Release Notes&lt;/a&gt;&lt;/li&gt;
&lt;li data-is-last-node=&quot;&quot; data-end=&quot;3232&quot; data-start=&quot;3110&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; data-end=&quot;3230&quot; data-start=&quot;3112&quot;&gt;Spring Boot 3.0 Migration Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1741510832654&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;Spring Boot 3.0 Migration Guide&quot; data-og-description=&quot;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; data-og-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/GfMKT/hyYrRIXSDk/mARAe4R22DE1KODE50RZCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cigSZE/hyYmQZB0HW/V7Jr6w559Rso348YEUFak1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/GfMKT/hyYrRIXSDk/mARAe4R22DE1KODE50RZCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cigSZE/hyYmQZB0HW/V7Jr6w559Rso348YEUFak1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;Spring Boot 3.0 Migration Guide&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&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;figure id=&quot;og_1741510831002&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;Spring Boot 2.7 Release Notes&quot; data-og-description=&quot;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; data-og-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bBCX5R/hyYmOtXduV/6Syh6TT8balhBQN7xhfVDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cuemjB/hyYmYQQJhf/mjnzNIKAfjhd6NtzwKMfyk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bBCX5R/hyYmOtXduV/6Syh6TT8balhBQN7xhfVDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cuemjB/hyYmYQQJhf/mjnzNIKAfjhd6NtzwKMfyk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;Spring Boot 2.7 Release Notes&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss. - spring-projects/spring-boot&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;</description>
      <category>트러블슈팅 &amp;amp; 삽질기록</category>
      <category>autoconfiguration</category>
      <category>Spring</category>
      <category>springboot</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/20</guid>
      <comments>https://gnnny.tistory.com/20#entry20comment</comments>
      <pubDate>Sun, 9 Mar 2025 18:10:50 +0900</pubDate>
    </item>
    <item>
      <title>Java에서 Thread.UncaughtExceptionHandler 활용하기</title>
      <link>https://gnnny.tistory.com/19</link>
      <description>&lt;h2 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;Java에서 &lt;/span&gt;&lt;span&gt;Thread.UncaughtExceptionHandler&lt;/span&gt;&lt;span&gt;란?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;최근에 스프링 프레임워크를 사용하지 않고 프로젝트를 진행하면서 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Thread.UncaughtExceptionHandler&lt;/span&gt;&lt;/b&gt;&lt;span&gt;의 필요성을 몸소 체감하게 되었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기존에는 스레드 내부에서 개별적으로 예외를 처리하는 방식이 일반적이라고 생각했는데, 여러 개의 스레드에서 발생하는 예외를 효과적으로 관리하기 위해서는 보다 체계적인 접근이 필요하다는 것을 깨달았습니다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;주로 프레임워크를 사용하다 보니, 다들 아시다시피 제공해주는 &lt;/span&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;@RestControllerAdvice&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 같은 어노테이션을 활용해서 예외를 처리하는 것이 일반적이었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 이번 프로젝트를 진행하면서 프레임워크의 예외 처리 기능 외에도 &lt;/span&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;Thread.UncaughtExceptionHandler&lt;/b&gt;&lt;/span&gt;&lt;span&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;span&gt;보통은 &lt;/span&gt;&lt;span&gt;try-catch&lt;/span&gt;&lt;span&gt;를 사용해서 예외를 개별적으로 처리하지만, 모든 스레드에 일일이 &lt;/span&gt;&lt;span&gt;try-catch&lt;/span&gt;&lt;span&gt;를 적용하는 것은 현실적으로 어렵습니다. 이럴 때 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Thread.UncaughtExceptionHandler&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 사용하면 &lt;/span&gt;&lt;span&gt;스레드에서 발생하는 예외를 한 곳에서 처리&lt;/span&gt;&lt;span&gt;할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740624670159&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//이 메서드는 특정 스레드에서 발생한 미처 처리되지 않은 예외를 감지하여 처리하는 핸들러를 설정할 수 있습니다. 만약 명시적으로 설정된 핸들러가 없을 경우, 해당 스레드가 속한 ThreadGroup의 기본 핸들러가 동작합니다.
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;setUncaughtExceptionHandler 예제 코드&lt;/span&gt;&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class UncaughtExceptionTest {
    public static void main(String[] args) {
        Thread thread = new Thread(() -&amp;gt; {
            throw new RuntimeException(&quot;예외 발생~~~~~~&quot;);
        });

        thread.setUncaughtExceptionHandler((t, e) -&amp;gt; {
            System.out.println(&quot;예외 발생 스레드: &quot; + t.getName());
            System.out.println(&quot;예외 메시지 &quot; + e.getMessage());
        });

        thread.start();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;처음에는 &lt;/span&gt;&lt;span&gt;try-catch&lt;/span&gt;&lt;span&gt; 없이도 예외를 감지하고 처리할 수 있다는 점에서 흥미를 느꼈습니다. 그런데 프로젝트를 진행하면서 여러 개의 스레드가 동시에 실행될 때 예외 처리를 개별적으로 하는 것이 비효율적일 수도 있겠다는 생각이 들었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 공통적으로 처리할 수 있는 방법이 있을까 찾아보다 보니 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Thread.setDefaultUncaughtExceptionHandler&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 활용하면 app 전체에서 스레드 예외를 일괄적으로 처리할 수 있다는 점을 알게 되었습니다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 해당 메서드는 특정 스레드에 대해 별도의 핸들러가 설정되지 않았을 경우, 모든 스레드에 대해 적용되는 기본 예외 처리 핸들러를 설정합니다.
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;setDefaultUncaughtExceptionHandler&lt;span&gt;&lt;span&gt; 예제 코드&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class GlobalExceptionHandler {
    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler((t, e) -&amp;gt; {
            System.out.println(&quot;[Global] 예외 발생 in &quot; + t.getName());
            System.out.println(&quot;[Global] 예외 메시지: &quot; + e.getMessage());
        });

        Thread thread1 = new Thread(() -&amp;gt; { 
        	throw new RuntimeException(&quot;Thread1 에러~~!&quot;); 
        });
        Thread thread2 = new Thread(() -&amp;gt; { 
        	throw new RuntimeException(&quot;Thread2 에러~~!&quot;); 
        });
        
        thread1.start();
        thread2.start();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 방법을 적용했더니, 스레드 개별 예외 처리를 신경 쓰지 않아도 한 곳에서 모든 예외를 관리할 수 있어 유지보수가 훨씬 편리해졌습니다. 특히, &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;setDefaultUncaughtExceptionHandler&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 활용하면 새롭게 생성되는 모든 스레드에서 자동으로 예외가 감지되므로, 일일이 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;setUncaughtExceptionHandler&lt;/span&gt;&lt;/b&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Thread.UncaughtExceptionHandler&lt;/b&gt;&lt;span&gt; 언제 활용하면 좋을까?&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;활용하면 좋은 경우&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;멀티스레드 환경에서 예외 로깅이 필요할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;예외 발생 시 슬랙, 디스코드, 이메일 등으로 알림을 보낼 때&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;굳이 안 써도 되는 경우&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;단순한 싱글스레드 애플리케이션에서는 &lt;/span&gt;&lt;span&gt;try-catch&lt;/span&gt;&lt;span&gt;로 충분할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Spring Boot의 &lt;/span&gt;&lt;span&gt;@ControllerAdvice&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;@ExceptionHandler&lt;/span&gt;&lt;span&gt;를 활용하면 더 직관적인 예외 처리가 가능할 때&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Thread.UncaughtExceptionHandler&lt;/span&gt;&lt;/b&gt; 는 Java의 멀티스레드 환경에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;중앙 집중식 예외 처리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 할 수 있는 강력한 기능입니다. 이번 프로젝트를 진행하며 멀티스레드 환경에서 발생하는 예외를 체계적으로 관리하는 것이 얼마나 중요한지 다시 한 번 깨닫게 되었습니다.&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;[참고]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740624126707&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;Thread (Java Platform SE 8 )&quot; data-og-description=&quot;Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group, and has the specified stack size. This constructor is identical to Thread(ThreadGroup,Runnable,&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html&quot; data-og-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.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;Thread (Java Platform SE 8 )&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group, and has the specified stack size. This constructor is identical to Thread(ThreadGroup,Runnable,&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;</description>
      <category>개발</category>
      <category>java</category>
      <category>UncaughtExceptionHandler</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/19</guid>
      <comments>https://gnnny.tistory.com/19#entry19comment</comments>
      <pubDate>Thu, 27 Feb 2025 12:03:33 +0900</pubDate>
    </item>
    <item>
      <title>IntelliJ 특정 버전 JDK 21 사용 시 컴파일 오류</title>
      <link>https://gnnny.tistory.com/18</link>
      <description>&lt;h2 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;문제 환경&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;IDE 버전&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: IntelliJ IDEA 2023.1&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Java 버전&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: JDK 21&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;이슈 발생&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;최근 작업을 하다 파라미터로 TimeUnit 타입을&amp;nbsp; 전달해야 하는데 &lt;/span&gt;하기 이미지와 같이 컴파일이 안되는 상황이었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-02-22 02.01.35.jpg&quot; data-origin-width=&quot;3174&quot; data-origin-height=&quot;1922&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DDQ0j/btsMshOZ4Ap/ODRlyhfn9gB1i7JE3bhjR1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DDQ0j/btsMshOZ4Ap/ODRlyhfn9gB1i7JE3bhjR1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DDQ0j/btsMshOZ4Ap/ODRlyhfn9gB1i7JE3bhjR1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDDQ0j%2FbtsMshOZ4Ap%2FODRlyhfn9gB1i7JE3bhjR1%2Fimg.jpg&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;3174&quot; height=&quot;1922&quot; data-filename=&quot;스크린샷 2025-02-22 02.01.35.jpg&quot; data-origin-width=&quot;3174&quot; data-origin-height=&quot;1922&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-02-22 02.01.02.jpg&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;1680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QtSbP/btsMtddVZd8/syjyi514Kp5F4etgcsORJ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QtSbP/btsMtddVZd8/syjyi514Kp5F4etgcsORJ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QtSbP/btsMtddVZd8/syjyi514Kp5F4etgcsORJ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQtSbP%2FbtsMtddVZd8%2Fsyjyi514Kp5F4etgcsORJ1%2Fimg.jpg&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;1376&quot; height=&quot;1680&quot; data-filename=&quot;스크린샷 2025-02-22 02.01.02.jpg&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;1680&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;java.util.concurrent.TimeUnit&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;관련해서 컴파일 오류가 발생했다. 왠지 느낌상 버전 이슈인가..?? 싶어 찾아보니, StackOverFlow와 jetbrains issue를 확인해보니 같은 문제를 겪고 있는 사람들이 좀 있었다.&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/77551293/intellij-idea-jdk-21-issue-with-java-util-concurrent-package-timeunit-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://stackoverflow.com/questions/77551293/intellij-idea-jdk-21-issue-with-java-util-concurrent-package-timeunit-class&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740159014510&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;IntelliJ IDEA + JDK 21 issue with java.util.concurrent package - TimeUnit class not available&quot; data-og-description=&quot;I have an issue when I am trying to use TimeUnit class from java.util.concurrent. It happens with Oracle JDK 21.0.1 (configurations are below) + IntelliJ IDEA 2023.1.5 (Community Edition) - the lat...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/77551293/intellij-idea-jdk-21-issue-with-java-util-concurrent-package-timeunit-class&quot; data-og-url=&quot;https://stackoverflow.com/questions/77551293/intellij-idea-jdk-21-issue-with-java-util-concurrent-package-timeunit-class&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/MfwEV/hyYf4qi7wn/ZpoZfEWk4ADxZQpgj5vPRK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/7cYNH/hyYfGbPe3T/7Ll6kdA4hMK7mhIF8jpFC1/img.png?width=1856&amp;amp;height=770&amp;amp;face=0_0_1856_770&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/77551293/intellij-idea-jdk-21-issue-with-java-util-concurrent-package-timeunit-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/77551293/intellij-idea-jdk-21-issue-with-java-util-concurrent-package-timeunit-class&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/MfwEV/hyYf4qi7wn/ZpoZfEWk4ADxZQpgj5vPRK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/7cYNH/hyYfGbPe3T/7Ll6kdA4hMK7mhIF8jpFC1/img.png?width=1856&amp;amp;height=770&amp;amp;face=0_0_1856_770');&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;IntelliJ IDEA + JDK 21 issue with java.util.concurrent package - TimeUnit class not available&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I have an issue when I am trying to use TimeUnit class from java.util.concurrent. It happens with Oracle JDK 21.0.1 (configurations are below) + IntelliJ IDEA 2023.1.5 (Community Edition) - the lat...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;a href=&quot;https://youtrack.jetbrains.com/issue/IDEA-333976/Some-java-classes-in-OpenJDK-21-are-not-accessible&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtrack.jetbrains.com/issue/IDEA-333976/Some-java-classes-in-OpenJDK-21-are-not-accessible&lt;/a&gt;&lt;a href=&quot;https://youtrack.jetbrains.com/issue/KT-62389/JDK-21-Cannot-access-class-TimeUnit.-Check-your-module-classpath-for-missing-or-conflicting-dependencies&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;s&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740159022127&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;JDK 21: Cannot access class 'TimeUnit'. Check your module classpath for missing or conflicting dependencies : KT-62389&quot; data-og-description=&quot;Compile code with compiler 1.9.10, JVM target 20, JRE 21+9-b212.1 (JBR) and got issue: Kotlin: Cannot access class 'TimeUnit'. Check your module classpath for missing or conflicting dependencies Kotlin: Type mismatch: inferred type is java.util.concurrent.&quot; data-og-host=&quot;youtrack.jetbrains.com&quot; data-og-source-url=&quot;https://youtrack.jetbrains.com/issue/KT-62389/JDK-21-Cannot-access-class-TimeUnit.-Check-your-module-classpath-for-missing-or-conflicting-dependencies&quot; data-og-url=&quot;https://youtrack.jetbrains.com/issue/KT-62389&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://youtrack.jetbrains.com/issue/KT-62389/JDK-21-Cannot-access-class-TimeUnit.-Check-your-module-classpath-for-missing-or-conflicting-dependencies&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://youtrack.jetbrains.com/issue/KT-62389/JDK-21-Cannot-access-class-TimeUnit.-Check-your-module-classpath-for-missing-or-conflicting-dependencies&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;JDK 21: Cannot access class 'TimeUnit'. Check your module classpath for missing or conflicting dependencies : KT-62389&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Compile code with compiler 1.9.10, JVM target 20, JRE 21+9-b212.1 (JBR) and got issue: Kotlin: Cannot access class 'TimeUnit'. Check your module classpath for missing or conflicting dependencies Kotlin: Type mismatch: inferred type is java.util.concurrent.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;youtrack.jetbrains.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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;해결 방법&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;찾아보니 해결 방법은 두가지였다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;IntelliJ IDEA를 최신 버전으로 업그레이드하기&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;혹시라도 인텔리제이가 JDK 21을 완벽히 지원하지 않는다면 최신 버전으로 올리면 해결할 수 있다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;공식적으로 2023.2.2 realease 버전부터 해당건 이슈가 해소된걸로 확인된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;JDK 버전을 다운그레이드하기&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;나는 지금 당장 JDK 21까지 써야 할 이유가 없어, 그냥 JDK 17로 내려서 해결하기로 했다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;간단하게 JDK를 17로 바꾸는 방법은 다음과 같다:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt; &amp;rarr; &lt;/span&gt;&lt;span&gt;Project Structure &lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;rarr; &lt;/span&gt;&lt;span&gt;Project SDK&lt;/span&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;로 변경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Modules&lt;/span&gt;&lt;span&gt; &amp;rarr; &lt;/span&gt;&lt;span&gt;Dependencies&lt;/span&gt;&lt;span&gt;에서 JDK 17로 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Gradle/Maven 사용 시 해당 설정도 JDK 17로 변경&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;결론적으로 JDK 17로 내리니까 문제가 해결됐다. 역시나 버전 이슈였던걸로.... 추후 ide 버전업을....ㅎ&lt;/span&gt;&lt;/p&gt;</description>
      <category>트러블슈팅 &amp;amp; 삽질기록</category>
      <category>IntelliJ</category>
      <category>java</category>
      <category>timeunit</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/18</guid>
      <comments>https://gnnny.tistory.com/18#entry18comment</comments>
      <pubDate>Sat, 22 Feb 2025 02:43:04 +0900</pubDate>
    </item>
    <item>
      <title>[spring] gradle build fail</title>
      <link>https://gnnny.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;intellij로 spring 프로젝트를 신규 생성했는데 빌드가 실패하는 상황이 발생했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;해당 프로젝트 버전은 하기와 같았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;version&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;spring-boot - 3.1.4&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;java - 17&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;해당 에러&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1697608353033&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A problem occurred configuring root project 'token-bucket'.
&amp;gt; Could not resolve all files for configuration ':classpath'.
   &amp;gt; Could not resolve org.springframework.boot:spring-boot-gradle-plugin:3.1.4.
     Required by:
         project : &amp;gt; org.springframework.boot:org.springframework.boot.gradle.plugin:3.1.4
      &amp;gt; No matching variant of org.springframework.boot:spring-boot-gradle-plugin:3.1.4 was found. The consumer was configured to find a library for use during runtime, compatible with Java 11, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '8.3' but:
          - Variant 'apiElements' capability org.springframework.boot:spring-boot-gradle-plugin:3.1.4 declares a library, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component for use during compile-time, compatible with Java 17 and the consumer needed a component for use during runtime, compatible with Java 11
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.3')
          - Variant 'javadocElements' capability org.springframework.boot:spring-boot-gradle-plugin:3.1.4 declares a component for use during runtime, and its dependencies declared externally:
              - Incompatible because this component declares documentation and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about its target Java version (required compatibility with Java 11)
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.3')
          - Variant 'mavenOptionalApiElements' capability org.springframework.boot:spring-boot-gradle-plugin-maven-optional:3.1.4 declares a library, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component for use during compile-time, compatible with Java 17 and the consumer needed a component for use during runtime, compatible with Java 11
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.3')
          - Variant 'mavenOptionalRuntimeElements' capability org.springframework.boot:spring-boot-gradle-plugin-maven-optional:3.1.4 declares a library for use during runtime, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component, compatible with Java 17 and the consumer needed a component, compatible with Java 11
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.3')
          - Variant 'runtimeElements' capability org.springframework.boot:spring-boot-gradle-plugin:3.1.4 declares a library for use during runtime, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component, compatible with Java 17 and the consumer needed a component, compatible with Java 11
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.3')
          - Variant 'sourcesElements' capability org.springframework.boot:spring-boot-gradle-plugin:3.1.4 declares a component for use during runtime, and its dependencies declared externally:
              - Incompatible because this component declares documentation and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about its target Java version (required compatibility with Java 11)
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.3')
                  
      ...
      ....&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&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;콘솔에 찍힌 에러를 번역하여 분석해보니 spring-boot 3.1.4의 호환성 문제였습니다. 이전 프로젝트 진행하며 gradle version과 java sdk version을 17 -&amp;gt; 11로 다운그레이드 한게 원인이었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1697608910039&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Incompatible because this component declares a component, compatible with Java 17 and the consumer needed a component, compatible with Java 11&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;해결방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java version을 11 -&amp;gt; 17로 변경하면 됩니다. local java version은 건들지 않고, intellij에서 build시에만 반영토록 version을 변경합니&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;Settings(command +) -&amp;gt; Build, Execution, Deployment &amp;gt; Gradle &amp;gt; Gradle JVM 변경&lt;/p&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-filename=&quot;스크린샷 2023-10-18 오후 3.12.52.jpg&quot; data-origin-width=&quot;2222&quot; data-origin-height=&quot;1450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnxBR4/btsyHyiSTau/cT8RfI9EaQcss9sfJxhkN0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnxBR4/btsyHyiSTau/cT8RfI9EaQcss9sfJxhkN0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnxBR4/btsyHyiSTau/cT8RfI9EaQcss9sfJxhkN0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnxBR4%2FbtsyHyiSTau%2FcT8RfI9EaQcss9sfJxhkN0%2Fimg.jpg&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;800&quot; height=&quot;522&quot; data-filename=&quot;스크린샷 2023-10-18 오후 3.12.52.jpg&quot; data-origin-width=&quot;2222&quot; data-origin-height=&quot;1450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;번외&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 호환성 문제가 아닌 순수하게 gradle의 호환성 문제이면 알맞는 java version을 맞춰주면 됩니다.&lt;/p&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-filename=&quot;스크린샷 2023-10-18 오후 3.18.53.jpg&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;699&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7s3lD/btsyH4IDsk5/ILzRSKqVv1hyK5KQdc9EL1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7s3lD/btsyH4IDsk5/ILzRSKqVv1hyK5KQdc9EL1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7s3lD/btsyH4IDsk5/ILzRSKqVv1hyK5KQdc9EL1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7s3lD%2FbtsyH4IDsk5%2FILzRSKqVv1hyK5KQdc9EL1%2Fimg.jpg&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;400&quot; height=&quot;497&quot; data-filename=&quot;스크린샷 2023-10-18 오후 3.18.53.jpg&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;699&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;</description>
      <category>트러블슈팅 &amp;amp; 삽질기록</category>
      <category>Gradle</category>
      <category>Spring</category>
      <category>springboot</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/17</guid>
      <comments>https://gnnny.tistory.com/17#entry17comment</comments>
      <pubDate>Wed, 18 Oct 2023 15:27:56 +0900</pubDate>
    </item>
    <item>
      <title>[mac] 문제가 발생했기 때문에 컴퓨터를 종료했습니다. 경고창 뜨는 경우 대처법</title>
      <link>https://gnnny.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어떠한 이유로 하단의 이미지와 같은 경고창이 전원을 켤때 마다 매번 뜨는 경우에 대한 대처법에 정리해보고자 합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.01.41.jpg&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIGBbI/btstmsA87uk/GItDPJ9J3cpBBWMaFNYUM1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIGBbI/btstmsA87uk/GItDPJ9J3cpBBWMaFNYUM1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIGBbI/btstmsA87uk/GItDPJ9J3cpBBWMaFNYUM1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIGBbI%2FbtstmsA87uk%2FGItDPJ9J3cpBBWMaFNYUM1%2Fimg.jpg&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;373&quot; height=&quot;161&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.01.41.jpg&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;161&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;저는 USB&lt;span style=&quot;background-color: #ffffff; color: #4d5156; text-align: left;&quot;&gt;-&lt;/span&gt;C&lt;span style=&quot;background-color: #ffffff; color: #4d5156; text-align: left;&quot;&gt;&amp;nbsp;케이블 모니터를&lt;/span&gt; 뽑다가 재시동 된 후 전원을 켤때 마다 경고창이 뜨는 상황이었는데, 이러한 문제가 생기는 이유는 &lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;소프트웨어 또는 하드웨어 문제가 발생하여 생기는 경우라고 합니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left; font-family: 'Noto Serif KR';&quot;&gt;apple 공식 사이트의 고객지원을 참고해서 보면, 하단과 같이 가이드를 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.07.56.jpg&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bM1N6c/btstnvxCpzQ/WjhEdxSkkny7dpoBHPEGoK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bM1N6c/btstnvxCpzQ/WjhEdxSkkny7dpoBHPEGoK/img.jpg&quot; data-alt=&quot;출처 - 애플 https://support.apple.com/ko-kr/HT200553&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bM1N6c/btstnvxCpzQ/WjhEdxSkkny7dpoBHPEGoK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbM1N6c%2FbtstnvxCpzQ%2FWjhEdxSkkny7dpoBHPEGoK%2Fimg.jpg&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;825&quot; height=&quot;596&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.07.56.jpg&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 - 애플 https://support.apple.com/ko-kr/HT200553&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결국엔 시도하다 안되면 백업 후 macOS를 재설치 해야 되는 상황이 펼쳐지죠.........&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;046&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/046.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/046.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇지만 좀더 쉽게 접근하는 방법이 있습니다. 방법은 간단합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;터미널을 엽니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;명령어를 입력 후 라이브러리 &amp;gt; 로그 디렉토리로 이동합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DiagnosticReports 디렉토리를&amp;nbsp; 찾아 하위 파일과 함께 삭제합니다.(다시 생성되므로 삭제해도 무방)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;삭제 확인 후 맥을 재부팅 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1694082490445&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd Library/Logs
rm -rf DiagnosticReports&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.14.22.jpg&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;1062&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRqzl4/btstgjrJylI/kKXcu8Vs715fniLFbHmDpk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRqzl4/btstgjrJylI/kKXcu8Vs715fniLFbHmDpk/img.jpg&quot; data-alt=&quot;로그 디렉토리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRqzl4/btstgjrJylI/kKXcu8Vs715fniLFbHmDpk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRqzl4%2FbtstgjrJylI%2FkKXcu8Vs715fniLFbHmDpk%2Fimg.jpg&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;1326&quot; height=&quot;1062&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.14.22.jpg&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;1062&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로그 디렉토리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.23.22.jpg&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqwA2q/btstqW2v9vl/zS2Tj0mWbU0UqppHsp7KNk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqwA2q/btstqW2v9vl/zS2Tj0mWbU0UqppHsp7KNk/img.jpg&quot; data-alt=&quot;DianosticReports 로그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqwA2q/btstqW2v9vl/zS2Tj0mWbU0UqppHsp7KNk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqwA2q%2FbtstqW2v9vl%2FzS2Tj0mWbU0UqppHsp7KNk%2Fimg.jpg&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;1374&quot; height=&quot;352&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.23.22.jpg&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DianosticReports 로그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.25.45.jpg&quot; data-origin-width=&quot;2642&quot; data-origin-height=&quot;808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zcUDX/btstkwRQRNj/IrkPKLYkuf1twCDYzpgJyk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zcUDX/btstkwRQRNj/IrkPKLYkuf1twCDYzpgJyk/img.jpg&quot; data-alt=&quot;디렉토리 및 파일 삭제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zcUDX/btstkwRQRNj/IrkPKLYkuf1twCDYzpgJyk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzcUDX%2FbtstkwRQRNj%2FIrkPKLYkuf1twCDYzpgJyk%2Fimg.jpg&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;2642&quot; height=&quot;808&quot; data-filename=&quot;스크린샷 2023-09-07 오후 7.25.45.jpg&quot; data-origin-width=&quot;2642&quot; data-origin-height=&quot;808&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디렉토리 및 파일 삭제&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 방법대로 순서대로 시도해보면 정상적으로 부팅이 되며 경고창이 더이상은 뜨지 않는걸 확인 할수 있습니다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 어떠한 문제로 인해 지속적으로 경고창이 뜨는 상황에 대처하는 방법에 대해 다뤄 보았습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;도움이 되셨길 바라며 긴글 읽어 주셔서 감사합니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>트러블슈팅 &amp;amp; 삽질기록</category>
      <category>Mac</category>
      <category>경고창</category>
      <author>그니_</author>
      <guid isPermaLink="true">https://gnnny.tistory.com/16</guid>
      <comments>https://gnnny.tistory.com/16#entry16comment</comments>
      <pubDate>Thu, 7 Sep 2023 19:37:06 +0900</pubDate>
    </item>
  </channel>
</rss>