<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>보조기억장치</title>
    <link>https://hand-mk.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 04:56:22 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>hand-mk</managingEditor>
    <image>
      <title>보조기억장치</title>
      <url>https://tistory1.daumcdn.net/tistory/7472780/attach/2b0eccad3b424e6e8cdb9796187f3f42</url>
      <link>https://hand-mk.tistory.com</link>
    </image>
    <item>
      <title>[멋쟁이사자처럼] 전국 대학 연합 아이디어톤 1등 수상 회고</title>
      <link>https://hand-mk.tistory.com/27</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&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;p data-ke-size=&quot;size16&quot;&gt;대신, 학부생 시절 '멋쟁이사자처럼' 이라는 전국 대학 연합 IT 학술 동아리에 들어가 2년동안 활동했다. '멋쟁이사자처럼' 소위 말하는 '멋사' 는 연단위로 기수를 진행하고 매년 동아리에 참여한 학교들에 아이디어톤, 해커톤 참가 기회가 주어진다.&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;필자는 11기, 12기 활동을 했고 이 중 12기 아이디어톤에서 운좋게 1등을 수상하였다..!&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;h2 data-ke-size=&quot;size26&quot;&gt;2. 본론&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1. 기획&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공모전 주제는 다음과 같았다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;IT 기술을 활용하여 현대인의 건강 (wellness) 문제를 해결할 수 있는 아이디어를 제시하시오.&amp;rdquo;&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;'현대인의&amp;nbsp;건강(wellness)'&amp;nbsp;이라는&amp;nbsp;단어를&amp;nbsp;봤을&amp;nbsp;때&amp;nbsp;많은&amp;nbsp;팀들이&amp;nbsp;신체&amp;nbsp;건강과&amp;nbsp;관련된&amp;nbsp;내용을&amp;nbsp;많이&amp;nbsp;다룰거라고&amp;nbsp;예상했다.&amp;nbsp;때문에 수상을 위해서라면 단순 신체 건강이 아닌 정신 건강 문제를 해결해야 한다고 생각했다. 호기롭게 여러 논문과 기사들을 스크랩하기 시작했으나, 보통 다양한게 아니였다... 그렇게 기획이 산으로 가는 중 공모전 경험이 많은 동기가 '사회와 연관된 공모전에서는 정부 정책을 봐야 한다' 고 팁을 주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 2024 정부 정책 보고서를 확인해보니&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2024 정책보고서.png&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;1396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLJPnH/dJMcajoduHF/5KeHYYWaPdfFyktV97y3ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLJPnH/dJMcajoduHF/5KeHYYWaPdfFyktV97y3ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLJPnH/dJMcajoduHF/5KeHYYWaPdfFyktV97y3ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLJPnH%2FdJMcajoduHF%2F5KeHYYWaPdfFyktV97y3ck%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;1136&quot; height=&quot;1396&quot; data-filename=&quot;2024 정책보고서.png&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;1396&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;AI 갈등 관리 플랫폼을 구축 해서 집단간 갈등을 완화하는 것이 2024 정부의 목표였다.&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 를 접목한 갈등을 완화할 수 있는 플랫폼'&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 만드는 것을 목표로 하고 해당 아이디어톤 주제와 어떻게 연관을 지어서 기획 의도를 설명할지가 관건이였다. 갈등과 현대인 건강과의 연관관계를 증명하면 우리의 서비스가 공모전 주제에 부합하게 되는 것이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에 정말 많은 시간을 투자하였고, 당시 정권 대립이 고조 됐던 탓이라 핫 키워드였던 &lt;b&gt;확증 편향 &lt;/b&gt;현상과 연관지어 갈등의 원인과 이로 인한 정신적인 스트레스가 현대 정신 건강을 해한다는 결론으로 이어졌다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGmnVx/dJMcafsELKH/x7lYk4Xm7Ii3NVjoITLcp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGmnVx/dJMcafsELKH/x7lYk4Xm7Ii3NVjoITLcp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGmnVx/dJMcafsELKH/x7lYk4Xm7Ii3NVjoITLcp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGmnVx%2FdJMcafsELKH%2Fx7lYk4Xm7Ii3NVjoITLcp0%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;828&quot; height=&quot;412&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;412&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;/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.2. 예선 2차&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예선 1차는 본교 내에서 대표팀을 선출하는 것이였는데, 아슬아슬한 차이로 우리팀이 올라갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예선 2차는 멋쟁이사자처럼 대학이 조별로 묶어준 대학들끼리 진행하는 방식이였다. 필자를 포함한 각 학교 대표들이 초대된 톡방에서 예선 2차 진행 방식에 대해 정했고, 오프라인으로 진행하기로 결정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 학교 대표 분들이 꼼꼼하게 준비해주시고 배려해주셔서 원활히 진행할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 우리 학교가 본선에 올라갈 수 있었다!&lt;/p&gt;
&lt;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/bnWm5U/dJMcaf7fYw8/x8omrhMofQoNZHDNOirLY1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnWm5U/dJMcaf7fYw8/x8omrhMofQoNZHDNOirLY1/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; style=&quot;width: 35.5814%; margin-right: 10px;&quot; data-widthpercent=&quot;36&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnWm5U/dJMcaf7fYw8/x8omrhMofQoNZHDNOirLY1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnWm5U%2FdJMcaf7fYw8%2Fx8omrhMofQoNZHDNOirLY1%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/bDULnc/dJMb99TvP4q/xRcZute4gMP0wym6K28KOK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDULnc/dJMb99TvP4q/xRcZute4gMP0wym6K28KOK/img.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; data-is-animation=&quot;false&quot; style=&quot;width: 63.2558%;&quot; data-widthpercent=&quot;64&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDULnc/dJMb99TvP4q/xRcZute4gMP0wym6K28KOK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDULnc%2FdJMb99TvP4q%2FxRcZute4gMP0wym6K28KOK%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;/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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.3. 본선&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;본선 장소는 멋쟁이사자처럼 본사 서울 종로구 청진동 246번지 디타워에서 진행됐다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;명찰.png&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMRRLO/dJMcaf0tMR2/HmtmokqKD4E7edK7P6kXDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMRRLO/dJMcaf0tMR2/HmtmokqKD4E7edK7P6kXDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMRRLO/dJMcaf0tMR2/HmtmokqKD4E7edK7P6kXDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMRRLO%2FdJMcaf0tMR2%2FHmtmokqKD4E7edK7P6kXDk%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;665&quot; height=&quot;704&quot; data-filename=&quot;명찰.png&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;704&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0f7HS/dJMb990jYBF/W9oQ6i5BhrkbZsA8EvT0u1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0f7HS/dJMb990jYBF/W9oQ6i5BhrkbZsA8EvT0u1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0f7HS/dJMb990jYBF/W9oQ6i5BhrkbZsA8EvT0u1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0f7HS%2FdJMb990jYBF%2FW9oQ6i5BhrkbZsA8EvT0u1%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;1204&quot; height=&quot;920&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;920&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 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(본사가 꽤 이뻐서 사진 찍고 싶었는데.... 발표자는 맨 앞에 앉으라고 해서......ㅠ)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; 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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제비뽑기.png&quot; data-origin-width=&quot;1263&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qZaTX/dJMcahDZP2N/kn29GX1j4BXOsUOrBN1pjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qZaTX/dJMcahDZP2N/kn29GX1j4BXOsUOrBN1pjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qZaTX/dJMcahDZP2N/kn29GX1j4BXOsUOrBN1pjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqZaTX%2FdJMcahDZP2N%2Fkn29GX1j4BXOsUOrBN1pjk%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;1263&quot; height=&quot;603&quot; data-filename=&quot;제비뽑기.png&quot; data-origin-width=&quot;1263&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;필자는 8번째 순서를 뽑았다..!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;순서.png&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;910&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBADrK/dJMcag6bImr/P48KR8fjNzdFPE5TQFOjX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBADrK/dJMcag6bImr/P48KR8fjNzdFPE5TQFOjX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBADrK/dJMcag6bImr/P48KR8fjNzdFPE5TQFOjX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBADrK%2FdJMcag6bImr%2FP48KR8fjNzdFPE5TQFOjX1%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;1258&quot; height=&quot;910&quot; data-filename=&quot;순서.png&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;910&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;본사 오면서 지인들에게 연락을 많이 받았다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;많이 떨리냐는 질문을 많이 받았는데, 에이 뭐 1차 2차 예선 때 하던 것 처럼 하면 되는건데 왜 떨리냐. 라고 말을 했다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;발표 순서가 돼서 앞에 나가고 그 말을 한 걸 후회했다. 발표 직전까지 심장 bpm 이 120 이상 찍혀서 애플워치 알람이 한번 울렸고, 발표를 시작하고 나서부터는 별로 안떨렸다.&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZ4q8s/dJMcaf7f1SH/lvhv8pdrv50hPI5hxiK6e0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZ4q8s/dJMcaf7f1SH/lvhv8pdrv50hPI5hxiK6e0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZ4q8s/dJMcaf7f1SH/lvhv8pdrv50hPI5hxiK6e0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZ4q8s%2FdJMcaf7f1SH%2Flvhv8pdrv50hPI5hxiK6e0%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-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?si=SfzB3kEg4v8UHLfC&amp;amp;v=62aRn6VFvRM&amp;amp;feature=youtu.be&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;본선 발표 영상&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;영상엔 빠져 있지만 발표 후 심사 위원분들의 QnA 시간이 있다. 길진 않고 1-2개 정도 질문을 하신다.(안한 팀들도 있긴 했다.)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 질문은 '&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;감정 분석 기능은 어떻게 구현 했나요?' 라는 질문이였고 &lt;/span&gt;어느정도 생각 해 둔 답변이 있어서 나름 유연하게 답변했던 것 같다..&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;두 번째 질문은 '&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;주요 타깃이 누구인가?' &lt;/span&gt;에 대한 질문이였다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;개인적으로 두번째 질문이 제일 어려웠는데, 공공성을 띄는 서비스라 '이걸 타깃을 확정 지을 수 있나?' 라는 생각이 들었다. 그래서 답변은 '아직 잘 모르겠습니다..!' 라고 했지만, 지금와서 생각해보면 B2B 느낌으로 정부 부처를 대상으로 판다고 했다면 어땠을까라는 아쉬움이 든다..&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;모든 대학 발표를 마치고 잠깐의 쉬는 시간을 가졌다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3등, 2등, 1등 순으로 발표가 진행됐는데, 2등까지 안나와서 올해도 떨어졌구나 하는 순간 우리 학교 이름이 1등 차례에 발표됐다..!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;137&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj84Un/dJMcahYjF9r/jAvTc0naTKarO1jdiopw0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj84Un/dJMcahYjF9r/jAvTc0naTKarO1jdiopw0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj84Un/dJMcahYjF9r/jAvTc0naTKarO1jdiopw0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj84Un%2FdJMcahYjF9r%2FjAvTc0naTKarO1jdiopw0K%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;137&quot; height=&quot;302&quot; data-origin-width=&quot;137&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(놀라는 모습을 잘 담아주신 멋사 대학 관계자 분 감사합니다...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부족한 실력에도 불구하고 좋은 평가를 받아서 너무 다행이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSVqOH/dJMcabDOmhQ/FPsFhgSHZFeerZQtdVZOi1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSVqOH/dJMcabDOmhQ/FPsFhgSHZFeerZQtdVZOi1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSVqOH/dJMcabDOmhQ/FPsFhgSHZFeerZQtdVZOi1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSVqOH%2FdJMcabDOmhQ%2FFPsFhgSHZFeerZQtdVZOi1%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-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;h2 data-ke-size=&quot;size26&quot;&gt;3. 결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀장을 맡아서 예선 탈락을 하면 어쩌나 라는 걱정도 많았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자가 발표를 맡아서 이목이 집중됐지만 사실 팀원들이 부족한 부분을 묵묵히 채워나가줘서 이런 좋은 성과를 얻을 수 있었던 것 같다. 12기 우수 수료자로 선정 될 수 있었던 것도 이 프로젝트를 정성스럽게 준비한 결과라고 생각한다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xUJ3o/dJMcagSELA6/PZOC7KP7xzRoYitSIIKJN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xUJ3o/dJMcagSELA6/PZOC7KP7xzRoYitSIIKJN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xUJ3o/dJMcagSELA6/PZOC7KP7xzRoYitSIIKJN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxUJ3o%2FdJMcagSELA6%2FPZOC7KP7xzRoYitSIIKJN1%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;1206&quot; height=&quot;690&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>회고록</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/27</guid>
      <comments>https://hand-mk.tistory.com/27#entry27comment</comments>
      <pubDate>Fri, 10 Apr 2026 18:15:17 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] AWS Certified Solutions Architect &amp;ndash; Associate 자격증 취득 회고</title>
      <link>https://hand-mk.tistory.com/26</link>
      <description>&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 AWS SAA 자격증을 합격하였다 :)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;993&quot; data-origin-height=&quot;503&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRUC7M/dJMcaax3beg/BWKnkyYeYDe0T8lJ3fbdd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRUC7M/dJMcaax3beg/BWKnkyYeYDe0T8lJ3fbdd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRUC7M/dJMcaax3beg/BWKnkyYeYDe0T8lJ3fbdd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRUC7M%2FdJMcaax3beg%2FBWKnkyYeYDe0T8lJ3fbdd0%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;993&quot; height=&quot;503&quot; data-origin-width=&quot;993&quot; data-origin-height=&quot;503&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;필자는 글을 쓰고 있는 현재 SI 업계 개발자로 딱 1년째 일하고 있다. 부족한 실력에도 불구하고 인천국제공항 공사 발주 프로젝트를 2개 담당하고 있는데, 큰 문제 없이 수행하고 있어 감사하게도 긍정적인 평가를 받고 있다.&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;현재 회사 생활에서는 큰 부담이나 걱정이 없으나, 앞으로의 나의 기술적인 비전은 걱정되는건 사실이였다. SI 특성상 안정성을 추구하기 때문에 새로운 기술을 습득하기 어렵기 때문이다. 부족한 부분을 채워 나가보고자 2026 상반기 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;빅테크&lt;span&gt; &lt;/span&gt;&lt;/span&gt;채용공고들을 보았고, 많은 부분들이 부족하지만..ㅎ 크게 AI, 클라우드 경험과 영어 스펙이 부족하다고 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 첫 자격증으로는 클라우드를 공부해보고자 마음 먹었고 이를 준비하는 방법과 느낌점을 공유하고자 회고록을 작성해보고자 한다.&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;2. 본론&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1. 왜 AWS SAA 였을까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 필자는 AWS, GCP, NCP 를 사이드 프로젝트 하면서 인스턴스 생성, 방화벽 설정 등 간단하게만 사용해본 경험이 있다. 그 중 AWS 가 가장 친밀하지 못했다.. 일단 개발 공부를 하면 'AWS 해킹썰' 하나씩은 갖고 있을거다. 본인도 마찬가지로 이유 없는 과금을 맞았던 경험이 있었고, 결국 어디서 돈이 새는지 못찾고 해당 계정을 비활성화 시켜둔 경험이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시는 이런 바보같은 짓을 하고 싶지 않았고, 나 뿐만 아니라 모두에게 빈번하게 발생하는 일이라면 더더욱 많이 써보고 공부를 해야 하지 않을까라는 생각을 했다. (물론, 가고 싶은 회사들에서도 요구하는 역량이라는 것이 가장 크다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 기회로 개발자 지인 추천을 통해 AWS 한국사용자모임-&lt;a href=&quot;https://www.awskr.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AWSKRUG&lt;/a&gt; 에 들어갈 수 있었고, 타이밍이 좋게 여기서 &lt;b&gt;AWS SAA 자격증 취득 스터디&lt;/b&gt;가&amp;nbsp;새로 생겼다. 실무에서 클라우드를 사용하지도 않아 노베이스인 내 입장에선 좋은 기회라고 생각이 들어 고민없이 스터디에 참여했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.2. SAA&amp;nbsp;스터디&amp;nbsp;-&amp;nbsp;AWSKRUG&amp;nbsp;자격증&amp;nbsp;소모임&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWSKRUG 자격증 소모임은 첫 오프라인 OT 를 제외하곤 모두 온라인으로 진행된다고 하여 직장인인 나에겐 더더욱 좋은 소모임이였다. 오프라인 OT 는 테헤란로에 있는 AWS Korea 본사에서 이뤄졌고, &lt;a href=&quot;https://www.meetup.com/awskrug/events/313093617/?utm_medium=referral&amp;amp;utm_campaign=announce_event&amp;amp;utm_source=link&amp;amp;utm_version=v2&amp;amp;member_id=276037823&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;meetup.com&lt;/a&gt; 을 통해 신청 할 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1078&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctHOUf/dJMcaarhyob/GNo2jL23p5BpfNR8BmPE9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctHOUf/dJMcaarhyob/GNo2jL23p5BpfNR8BmPE9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctHOUf/dJMcaarhyob/GNo2jL23p5BpfNR8BmPE9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctHOUf%2FdJMcaarhyob%2FGNo2jL23p5BpfNR8BmPE9K%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;1080&quot; height=&quot;1078&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1078&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엘리베이터 내리자마자 AWS 로고가 반겨주는데, 가슴이 웅장해진다..&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;입장할 때 출입증을 나눠준다. 사진으로 남기진 못했는데, 여러 다과가 준비돼 있었고 Nespresso 캡슐커피 &amp;amp; 머신이 있어 무한대로 먹을 수 있었다. 전반적인 스터디 일정을 30분 가량 설명해주시고 김선우 멘토님께서 '이런 느낌으로 나올꺼에요!' 일깨워주시기 위해 만드신 25문제 웹앱 모의고사를 풀어보는 시간도 가졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나 제외하고 대략 30명 정도 오셨다. 재학생도 있긴 했지만 거의 대부분 직장 퇴근하고 오셔서 대단하다고 생각이 들었다.&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/bhC8Cw/dJMb99Tqnv1/Jh74tJFLXBEm6jJo2Vpq01/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhC8Cw/dJMb99Tqnv1/Jh74tJFLXBEm6jJo2Vpq01/img.jpg&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot; data-is-animation=&quot;false&quot; style=&quot;width: 61.2651%; margin-right: 10px;&quot; data-widthpercent=&quot;61.99&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhC8Cw/dJMb99Tqnv1/Jh74tJFLXBEm6jJo2Vpq01/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhC8Cw%2FdJMb99Tqnv1%2FJh74tJFLXBEm6jJo2Vpq01%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;1536&quot; height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbzwRP/dJMcagLOgBQ/vS1Pwyp0dB66LQefyeD2fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbzwRP/dJMcagLOgBQ/vS1Pwyp0dB66LQefyeD2fk/img.png&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;2622&quot; data-is-animation=&quot;false&quot; style=&quot;width: 37.5722%;&quot; data-widthpercent=&quot;38.01&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbzwRP/dJMcagLOgBQ/vS1Pwyp0dB66LQefyeD2fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbzwRP%2FdJMcagLOgBQ%2FvS1Pwyp0dB66LQefyeD2fk%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;1206&quot; height=&quot;2622&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;오프라인 OT 이후 본격적인 자격증 스터디가 시작됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자격증은 3월 내 취득을 목표로 준비했고, &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;김선우 멘토님께서 정적 페이지에 Lambda 기반 스터디 기록 웹을 배포해주셔서 여기에 공부한 내용을 기록했다.&lt;/span&gt;&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/kJ1I4/dJMcadnXKvs/TKkuzr1hBWEVc8LyzBiSCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJ1I4/dJMcadnXKvs/TKkuzr1hBWEVc8LyzBiSCk/img.png&quot; data-origin-width=&quot;1871&quot; data-origin-height=&quot;783&quot; data-is-animation=&quot;false&quot; style=&quot;width: 54.0287%; margin-right: 10px;&quot; data-widthpercent=&quot;54.66&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJ1I4/dJMcadnXKvs/TKkuzr1hBWEVc8LyzBiSCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJ1I4%2FdJMcadnXKvs%2FTKkuzr1hBWEVc8LyzBiSCk%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;1871&quot; height=&quot;783&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdd7uS/dJMcafMUHet/tEnB5uNLO1FzFiNMZx0BH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdd7uS/dJMcafMUHet/tEnB5uNLO1FzFiNMZx0BH1/img.png&quot; data-origin-width=&quot;1520&quot; data-origin-height=&quot;767&quot; data-is-animation=&quot;false&quot; style=&quot;width: 44.8085%;&quot; data-widthpercent=&quot;45.34&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdd7uS/dJMcafMUHet/tEnB5uNLO1FzFiNMZx0BH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbdd7uS%2FdJMcafMUHet%2FtEnB5uNLO1FzFiNMZx0BH1%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;1520&quot; height=&quot;767&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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SApn2/dJMcaakvmbi/HmpUuE5hih03SgpgSMk8a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SApn2/dJMcaakvmbi/HmpUuE5hih03SgpgSMk8a1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SApn2/dJMcaakvmbi/HmpUuE5hih03SgpgSMk8a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSApn2%2FdJMcaakvmbi%2FHmpUuE5hih03SgpgSMk8a1%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;1436&quot; height=&quot;862&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;862&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.3. 개인 학습 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소모임에서는 AWS SkillBuilder 를 먼저 공부해보고, 추가적인 내용은 외부 강의나 블로그를 참고하여 공부하는 것을 추천했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://skillbuilder.aws/category/exam-prep/solutions-architect-associate-SAA-C03&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://skillbuilder.aws/category/exam-prep/solutions-architect-associate-SAA-C03&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775198663932&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;AWS Skill Builder&quot; data-og-description=&quot;&quot; data-og-host=&quot;skillbuilder.aws&quot; data-og-source-url=&quot;https://skillbuilder.aws/category/exam-prep/solutions-architect-associate-SAA-C03&quot; data-og-url=&quot;https://skillbuilder.aws/category/exam-prep/solutions-architect-associate-SAA-C03&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/J7yqb/dJMb9lMbW0J/UmKcACP9M2EUCoSlcSsjS1/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300&quot;&gt;&lt;a href=&quot;https://skillbuilder.aws/category/exam-prep/solutions-architect-associate-SAA-C03&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://skillbuilder.aws/category/exam-prep/solutions-architect-associate-SAA-C03&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/J7yqb/dJMb9lMbW0J/UmKcACP9M2EUCoSlcSsjS1/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300');&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;AWS Skill Builder&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;skillbuilder.aws&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGR9oj/dJMcagdX75j/A4RPw2KJdz0Q6GvTkUKKCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGR9oj/dJMcagdX75j/A4RPw2KJdz0Q6GvTkUKKCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGR9oj/dJMcagdX75j/A4RPw2KJdz0Q6GvTkUKKCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGR9oj%2FdJMcagdX75j%2FA4RPw2KJdz0Q6GvTkUKKCK%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;1044&quot; height=&quot;574&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;본격적인 서비스 공부에 앞서 아래 링크에 있는 Official Practice Question Set: AWS Certified Solutions Architect - Associate 를 한번 풀어보는 걸 추천한다. SAA 시험과 유사하게 나오는데, 이 시험을 70% 이상 맞출 수 있으면 바로 시험 보러 간다고 될 수준이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://skillbuilder.aws/learn/6NV91XYP1P/official-practice-question-set-aws-certified-solutions-architect--associate-saac03--/C4X6F66JQX&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://skillbuilder.aws/learn/6NV91XYP1P/official-practice-question-set-aws-certified-solutions-architect--associate-saac03--/C4X6F66JQX&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775199051315&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;AWS Skill Builder&quot; data-og-description=&quot;&quot; data-og-host=&quot;skillbuilder.aws&quot; data-og-source-url=&quot;https://skillbuilder.aws/learn/6NV91XYP1P/official-practice-question-set-aws-certified-solutions-architect--associate-saac03--/C4X6F66JQX&quot; data-og-url=&quot;https://skillbuilder.aws/learn/6NV91XYP1P/official-practice-question-set-aws-certified-solutions-architect--associate-saac03--/C4X6F66JQX&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b6yosE/dJMb9kmdcPT/9Tm1OFpg4XbrNSkwvinr2K/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300&quot;&gt;&lt;a href=&quot;https://skillbuilder.aws/learn/6NV91XYP1P/official-practice-question-set-aws-certified-solutions-architect--associate-saac03--/C4X6F66JQX&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://skillbuilder.aws/learn/6NV91XYP1P/official-practice-question-set-aws-certified-solutions-architect--associate-saac03--/C4X6F66JQX&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b6yosE/dJMb9kmdcPT/9Tm1OFpg4XbrNSkwvinr2K/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300');&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;AWS Skill Builder&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;skillbuilder.aws&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 결과는.... 처참했다..ㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 오답을 정리하고 조오금은 나아졌지만, 솔직히 처음 풀 때 맞췄던 5문제도 제대로 알고 푼 건 아닌거 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZnHF3/dJMcadIfTNz/TU6Zv5t4E3i8lPuvCPS0y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZnHF3/dJMcadIfTNz/TU6Zv5t4E3i8lPuvCPS0y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZnHF3/dJMcadIfTNz/TU6Zv5t4E3i8lPuvCPS0y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZnHF3%2FdJMcadIfTNz%2FTU6Zv5t4E3i8lPuvCPS0y0%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;835&quot; height=&quot;404&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위기감을 느껴 SkillBuilder 에 있는 강의들을 들어봤다. 솔직히 온프레미스 환경에서 일하고 있는 나에겐 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스에 대해 '이걸 어디에 쓰는지', '왜 쓰는지', 정리된 내용이 아니였고 '시험에서 이런 서비스들이 나오니 공부하세요.' 의 느낌이 강했다. 그래서 찾게 된게 가장 유명한 &lt;b&gt;Udemy 강의&lt;/b&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/best-aws-certified-solutions-architect-associate/?srsltid=AfmBOoqhEgHDqlrLNx2a5sLzkztiVJgF9zXae8qZ8piVJDTypUi5BnsP&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.udemy.com/course/best-aws-certified-solutions-architect-associate/?srsltid=AfmBOoqhEgHDqlrLNx2a5sLzkztiVJgF9zXae8qZ8piVJDTypUi5BnsP&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775199731272&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;【한글자막】 AWS Certified Solutions Architect Associate시험합격! 2025&quot; data-og-description=&quot;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;[2023년 3월]: &amp;lt;/strong&amp;gt;AWS UI 변경 및 시험 내용 변경에 맞춰 강의 내용이 업데이트 되었습니다! (&amp;lt;strong&amp;gt;SAA-C03)&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;AWS 초보도 &amp;lt;/strong&amp;gt;학습할 수 있는 친절한 강의!&amp;lt;&quot; data-og-host=&quot;www.udemy.com&quot; data-og-source-url=&quot;https://www.udemy.com/course/best-aws-certified-solutions-architect-associate/?srsltid=AfmBOoqhEgHDqlrLNx2a5sLzkztiVJgF9zXae8qZ8piVJDTypUi5BnsP&quot; data-og-url=&quot;https://www.udemy.com/course/best-aws-certified-solutions-architect-associate/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eV8Fz/dJMb8UHPzOB/PvMBhsLsnI2UM9DJrTclr0/img.jpg?width=480&amp;amp;height=270&amp;amp;face=267_60_341_141,https://scrap.kakaocdn.net/dn/qd7cI/dJMb9kmdcUG/c5TGIPOUNFyUmvCBmJG11k/img.jpg?width=480&amp;amp;height=270&amp;amp;face=267_60_341_141,https://scrap.kakaocdn.net/dn/so0Sy/dJMb8TB93fm/T0V5RBkWmPvH2toxR53QK1/img.jpg?width=480&amp;amp;height=270&amp;amp;face=267_60_341_141&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/best-aws-certified-solutions-architect-associate/?srsltid=AfmBOoqhEgHDqlrLNx2a5sLzkztiVJgF9zXae8qZ8piVJDTypUi5BnsP&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.udemy.com/course/best-aws-certified-solutions-architect-associate/?srsltid=AfmBOoqhEgHDqlrLNx2a5sLzkztiVJgF9zXae8qZ8piVJDTypUi5BnsP&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eV8Fz/dJMb8UHPzOB/PvMBhsLsnI2UM9DJrTclr0/img.jpg?width=480&amp;amp;height=270&amp;amp;face=267_60_341_141,https://scrap.kakaocdn.net/dn/qd7cI/dJMb9kmdcUG/c5TGIPOUNFyUmvCBmJG11k/img.jpg?width=480&amp;amp;height=270&amp;amp;face=267_60_341_141,https://scrap.kakaocdn.net/dn/so0Sy/dJMb8TB93fm/T0V5RBkWmPvH2toxR53QK1/img.jpg?width=480&amp;amp;height=270&amp;amp;face=267_60_341_141');&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;【한글자막】 AWS Certified Solutions Architect Associate시험합격! 2025&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;[2023년 3월]: &amp;lt;/strong&amp;gt;AWS UI 변경 및 시험 내용 변경에 맞춰 강의 내용이 업데이트 되었습니다! (&amp;lt;strong&amp;gt;SAA-C03)&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;AWS 초보도 &amp;lt;/strong&amp;gt;학습할 수 있는 친절한 강의!&amp;lt;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.udemy.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;사람들 후기가 많아 별 고민 없이 결제해서 퇴근하고 주중에 최소 2시간씩, 주말에는 4시간씩 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 강의에서는 단순 AWS 서비스에 대해 줄줄줄 설명만 하는게 아니라 간단하게 실습하는 영상이 있다. 때문에, 나같이 온프레미스에서 개발을 하고 있고 클라우드에 대한 지식이 전무한 분들에게 매우 추천한다.&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;Udemy 강의를 전부 듣고, 이전보단 AWS 서비스들에 대해 넓게 이해할 수 있었지만 워낙 서비스들이 많았기에 시험을 패스할 수 있겠다란 확신이 없었다. 그래서 찾아보니 유명한 dump 문제 사이트를 찾을 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://free-braindumps.com/amazon/free-saa-c03-braindumps/page-2&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://free-braindumps.com/amazon/free-saa-c03-braindumps/page-2&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1775200936004&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;Free SAA-C03 Practice Questions &amp;amp; AI Tutor | Free-Braindumps.com&quot; data-og-description=&quot;Hay! I&amp;rsquo;m your AI study assistant for the SAA-C03 exam. Ask me anything about the exam or the questions on this page, and I&amp;rsquo;ll break it down so it actually makes sense. You want it in a different language? Just say it.&quot; data-og-host=&quot;free-braindumps.com&quot; data-og-source-url=&quot;https://free-braindumps.com/amazon/free-saa-c03-braindumps/page-2&quot; data-og-url=&quot;https://free-braindumps.com/amazon/free-saa-c03-braindumps/page-2&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://free-braindumps.com/amazon/free-saa-c03-braindumps/page-2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://free-braindumps.com/amazon/free-saa-c03-braindumps/page-2&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;Free SAA-C03 Practice Questions &amp;amp; AI Tutor | Free-Braindumps.com&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Hay! I&amp;rsquo;m your AI study assistant for the SAA-C03 exam. Ask me anything about the exam or the questions on this page, and I&amp;rsquo;ll break it down so it actually makes sense. You want it in a different language? Just say it.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;free-braindumps.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;다른 분들은 600문제, 800 문제를 푸신 분들도 계셨는데, 애초에 준비기간이 3주였던 나로썬 100문제가 최선이였다.&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.4. 시험 당일&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 SRTC 에서 시험을 봤다. 오전 9시가 시험 시작이라 8시 30분에 도착했는데, 보안 서약서 작성하고 희망하면 바로 시험 응시 할 수 있다고 해서 바로 시험장으로 들어갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://maps.app.goo.gl/b4KnUybt6RiX6R7y7&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://maps.app.goo.gl/b4KnUybt6RiX6R7y7&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775201361794&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;SRTC &amp;middot; TGL 402호 KR 서울특별시 강남구 봉은사로 303 경복빌딩 4F&quot; data-og-description=&quot;★★★★☆ &amp;middot; 교육 테스트 서비스&quot; data-og-host=&quot;www.google.com&quot; data-og-source-url=&quot;https://maps.app.goo.gl/b4KnUybt6RiX6R7y7&quot; data-og-url=&quot;https://www.google.com/maps/place/SRTC/@37.509418,127.0401406,17z/data=!3m1!4b1!4m6!3m5!1s0x357ca5bca19c8f15:0xac5eb0cd56e5c8bf!8m2!3d37.509418!4d127.0401406!16s%2Fg%2F11lg2tndfq?entry=tts&amp;amp;g_ep=EgoyMDI2MDMzMS4wIPu8ASoASAFQAw%3D%3D&amp;amp;skid=540321fa-8653-4030-8134-ff064464890b&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yy7E8/dJMb82MDwx6/tXsqJDx0OV7ehKp7W62HX1/img.jpg?width=900&amp;amp;height=900&amp;amp;face=0_0_900_900&quot;&gt;&lt;a href=&quot;https://maps.app.goo.gl/b4KnUybt6RiX6R7y7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://maps.app.goo.gl/b4KnUybt6RiX6R7y7&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yy7E8/dJMb82MDwx6/tXsqJDx0OV7ehKp7W62HX1/img.jpg?width=900&amp;amp;height=900&amp;amp;face=0_0_900_900');&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;SRTC &amp;middot; TGL 402호 KR 서울특별시 강남구 봉은사로 303 경복빌딩 4F&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;★★★★☆ &amp;middot; 교육 테스트 서비스&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.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;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험장 내부는 독서실 같은 느낌이였고, 책상에 모니터가 보인다. 화면에 보이는 버튼을 누르면 시험에 응시할 수 있다. 오전 시험이라 사람들이 많이 없을 줄 알았는데, 생각보다 많이 있었다. 대략 15명정도..?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험장에 대한 걱정이 많았는데, 깨끗하고 시험을 보기엔 모자람이 없는 공간이였다. 특히 시험 감독관님들이 친절하게 응대해 주셔서 맘편히 시험을 응시할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.5. 결과 발표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 당일 저녁 8시쯤 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 시험 보고 나오면서 70%는 다시 봐야지... 생각하고 있었다. 15문제 정도 플래그를 걸어뒀는데 사실상 처음보는 서비스들이였다. 65문제 중에 15문제는 채점이 안되는 문제라고 해도 불안했다.&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;더군다나, 응시 후 5시간 이내로 메일로 결과 알려준다고 했는데 저녁 시간까지 안와서 '떨어졌구나..' 싶었다. 혹시나 하는 마음으로 &lt;a href=&quot;https://cp.certmetrics.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://cp.certmetrics.com/&lt;/a&gt; 에 들어가서 확인해보니 합격 결과가 나와있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;1050&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq6BdY/dJMcaaLz9RA/EsKzGKcLBp0duW3LKts5i1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq6BdY/dJMcaaLz9RA/EsKzGKcLBp0duW3LKts5i1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq6BdY/dJMcaaLz9RA/EsKzGKcLBp0duW3LKts5i1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq6BdY%2FdJMcaaLz9RA%2FEsKzGKcLBp0duW3LKts5i1%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;1608&quot; height=&quot;1050&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;1050&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yYgIY/dJMcacikqJA/CHqEoqghp1GDOnSKiOgc5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yYgIY/dJMcacikqJA/CHqEoqghp1GDOnSKiOgc5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yYgIY/dJMcacikqJA/CHqEoqghp1GDOnSKiOgc5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyYgIY%2FdJMcacikqJA%2FCHqEoqghp1GDOnSKiOgc5k%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;1422&quot; height=&quot;322&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;322&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;749점으로 간당간당하긴 했다..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;섹션별로 성적을 간략하게 보여주는데, 도메인 2에서 공부가 부족했던 것 같다. HA 관련 아키텍처를 좀 더 고민하고 공부해야겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvCXRF/dJMcagLOo7F/8spC2kDYYeEkUok5UaeEG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvCXRF/dJMcagLOo7F/8spC2kDYYeEkUok5UaeEG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvCXRF/dJMcagLOo7F/8spC2kDYYeEkUok5UaeEG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvCXRF%2FdJMcagLOo7F%2F8spC2kDYYeEkUok5UaeEG0%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;765&quot; height=&quot;232&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;232&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. 결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 자격증 취득이 목적이였긴 하지만, 강의 실습을 통해 왜 클라우드가 좋은지를 몸소 느꼈던 경험이였다. 로드밸런싱 실습을 할 때 버튼 딸깍으로 ALB 를 만들고, AMI, Auto-Scailing 이 적용된 EC2 인스턴스 여러개를 단 몇초만에 생성하여 물리적인 서버 없이 운영환경을 만들 수 있다는 점이 가장 큰 장점인 것 같다.&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;또한, AWS 에는 일반적으로 알고있는 EC2 서비스 외에 좋은 서비스가 너무 많다. 그런 서비스들이 운영 오버헤드를 줄임으로써 개발자가 오로지 프러덕팅에만 집중 할 수 있는게 또 하나의 장점인 것 같다. 이래서 AWS AWS 하는구나.... 서비스 운영 환경에 가서 내 지식을 토대로 기여해보고 싶은 생각이 더 확고해졌다..!&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;마지막으로 ALB 연습하다가 녹화한 영상으로 마무리..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;화면-기록-2026-03-11-오후-11.48.52.gif&quot; data-origin-width=&quot;1854&quot; data-origin-height=&quot;1006&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NUNWG/dJMcaa5U7FB/H3GtTNmPysC4UXsAmfJOQ0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NUNWG/dJMcaa5U7FB/H3GtTNmPysC4UXsAmfJOQ0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NUNWG/dJMcaa5U7FB/H3GtTNmPysC4UXsAmfJOQ0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/NUNWG/dJMcaa5U7FB/H3GtTNmPysC4UXsAmfJOQ0/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;1854&quot; height=&quot;1006&quot; data-filename=&quot;화면-기록-2026-03-11-오후-11.48.52.gif&quot; data-origin-width=&quot;1854&quot; data-origin-height=&quot;1006&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>자격증/aws</category>
      <category>AWS</category>
      <category>SAA</category>
      <category>자격증</category>
      <category>클라우드</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/26</guid>
      <comments>https://hand-mk.tistory.com/26#entry26comment</comments>
      <pubDate>Fri, 3 Apr 2026 17:00:07 +0900</pubDate>
    </item>
    <item>
      <title>[MCP] Claude + IntelliJ IDEA 2025.2.4 (Ultimate Edition) 연동</title>
      <link>https://hand-mk.tistory.com/25</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 MCP 가 개발 업계에서 매우 핫하다. 필자의 경우 Gemini 유료 구독 (3.1 Pro Model) 를 사용하여 개발을 했으나, 프롬프트에 단순히 입력하고 답변받는 구조에 지쳤다. 그래서 Claude 로 갈아타서 MCP 서버 구성을 진행해보고자 하였고 그 중 IntelliJ 연동을 첫번째로 진행하였다. 이에 관한 내용이다.&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;2. 본론&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1. MCP 란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`MCP(Model Context Protocol)` 는 AI 를 외부 시스템에 연결하기 위한 일종의 프로토콜이다. 우리가 흔히 얘기하던 HTTP 프로토콜과 같이 AI 를 다른 응용프로그램이나 서버에 연동하는 프로토콜이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP를 사용하면 Claude나 ChatGPT와 같은 AI 를 단순히 프롬프트를 웹에서 입력하고 답변 받는것이 아닌, 로컬에 있는 파일에 접근 가능하게끔 할 수 있어 일일이 복붙을 안해도 된다. 뿐만 아니라, 다른 서버에 연동 (ex. Slack, Gmail 등) 하여 업무를 시킬 수 도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 자세한 내용은 공식문서를 확인하면 이해할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://modelcontextprotocol.io/docs/getting-started/intro&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771829136126&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;What is the Model Context Protocol (MCP)? - Model Context Protocol&quot; data-og-description=&quot;What is the Model Context Protocol (MCP)?&quot; data-og-host=&quot;modelcontextprotocol.io&quot; data-og-source-url=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot; data-og-url=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dtIROZ/dJMb8RjYOsv/VkQQOXLhd3yhblE8zFKhxK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/b48iY7/dJMb8T9WjDh/HLjJfo01oti7McWTLdLcYK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/nuulg/dJMb8RjYOsx/rBaowCinPAs624RrrLCfwk/img.png?width=3840&amp;amp;height=1500&amp;amp;face=0_0_3840_1500&quot;&gt;&lt;a href=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dtIROZ/dJMb8RjYOsv/VkQQOXLhd3yhblE8zFKhxK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/b48iY7/dJMb8T9WjDh/HLjJfo01oti7McWTLdLcYK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/nuulg/dJMb8RjYOsx/rBaowCinPAs624RrrLCfwk/img.png?width=3840&amp;amp;height=1500&amp;amp;face=0_0_3840_1500');&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;What is the Model Context Protocol (MCP)? - Model Context Protocol&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What is the Model Context Protocol (MCP)?&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;modelcontextprotocol.io&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;h3 data-ke-size=&quot;size23&quot;&gt;2.2. Claude Desktop 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://claude.com/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://claude.com/download&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771829356271&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;Download Claude | Claude&quot; data-og-description=&quot;Download Claude for desktop and mobile. Access AI assistance natively on Mac, Windows, iOS, and Android across all your devices.&quot; data-og-host=&quot;claude.com&quot; data-og-source-url=&quot;https://claude.com/download&quot; data-og-url=&quot;https://claude.com/download&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/AvVdw/dJMb8865JZQ/hMfwgkB5KFqJXOSAr3u070/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cuyQaq/dJMb84XVCkn/wC2oT6pAbqycDxrgk1eyr1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://claude.com/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://claude.com/download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/AvVdw/dJMb8865JZQ/hMfwgkB5KFqJXOSAr3u070/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cuyQaq/dJMb84XVCkn/wC2oT6pAbqycDxrgk1eyr1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Download Claude | Claude&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Download Claude for desktop and mobile. Access AI assistance natively on Mac, Windows, iOS, and Android across all your devices.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;claude.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;공식 홈페이지에서 해당하는 OS 에 맞게 설치하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;994&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6DHJk/dJMcahXLa48/7ZnfErLka4cN28a0RqNV2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6DHJk/dJMcahXLa48/7ZnfErLka4cN28a0RqNV2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6DHJk/dJMcahXLa48/7ZnfErLka4cN28a0RqNV2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6DHJk%2FdJMcahXLa48%2F7ZnfErLka4cN28a0RqNV2K%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;960&quot; height=&quot;994&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;994&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;h3 data-ke-size=&quot;size23&quot;&gt;2.3. IntelliJ Plugin MCP Server 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude 에서 IntelliJ 에 연동을 하려면 `MCP Server` 플러그인을 설치해야 한다.&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;IntelliJ 상에서 다음과 같이 입력해 Setting &amp;gt; Plugins 창을 연다.&lt;/p&gt;
&lt;pre id=&quot;code_1771829511854&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 윈도우
Ctrl + Alt + S

# 맥
Command +&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;b&gt; MCP Server&lt;/b&gt; 를 입력하여 해당 플러그인을 설치한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;735&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EDzrI/dJMb996u1sW/b1WdZaXxdLkKwywalojSU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EDzrI/dJMb996u1sW/b1WdZaXxdLkKwywalojSU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EDzrI/dJMb996u1sW/b1WdZaXxdLkKwywalojSU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEDzrI%2FdJMb996u1sW%2Fb1WdZaXxdLkKwywalojSU0%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;984&quot; height=&quot;735&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;735&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 플러그인을 설치하면 &lt;b&gt;Settings&lt;/b&gt; 왼쪽 탭에 &lt;b&gt;MCP Server&amp;nbsp;&lt;/b&gt;가 생긴걸 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`Enable MCP Server` 체크 &amp;gt; Clients Auto-Configuration 하위 Claude App `Auto-Configure` 클릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하면 오른쪽에 초론색 체크표시가 뜬다. 이러면 사실상 연동이 끝이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1968&quot; data-origin-height=&quot;1470&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q4NFj/dJMcac3bO4u/nktgRBNVAlPDmENsE4OBkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q4NFj/dJMcac3bO4u/nktgRBNVAlPDmENsE4OBkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q4NFj/dJMcac3bO4u/nktgRBNVAlPDmENsE4OBkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq4NFj%2FdJMcac3bO4u%2FnktgRBNVAlPDmENsE4OBkK%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;1968&quot; height=&quot;1470&quot; data-origin-width=&quot;1968&quot; data-origin-height=&quot;1470&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;blockquote data-ke-style=&quot;style2&quot;&gt;이전 레거시 IntelliJ 의 경우 자동으로 claude_desktop_config.json 업데이트가 안된다고 알고있다.&lt;br /&gt;해당 방법으로 되지 않을 경우, 수동으로 json 파일을 수정해줘야 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.4. MCP 연동 확인 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연동을 확인하는 방법은 `Claude Desktop` 앱 상에서 확인 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽 하단 &lt;b&gt;설정 &lt;/b&gt;&amp;gt;&amp;nbsp; &lt;b&gt;커넥터 &lt;/b&gt;&amp;gt; 연동된 환경 확인 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dixhv0/dJMcabb9FFi/j3p05ej492Y5zFAleJO9X1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dixhv0/dJMcabb9FFi/j3p05ej492Y5zFAleJO9X1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dixhv0/dJMcabb9FFi/j3p05ej492Y5zFAleJO9X1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdixhv0%2FdJMcabb9FFi%2Fj3p05ej492Y5zFAleJO9X1%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;2160&quot; height=&quot;2444&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2444&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.5. 연동안됨?&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;왼쪽 하단&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;설정&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;b&gt;개발자 &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&amp;gt; &lt;b&gt;구성 편집 &lt;/b&gt;을 눌러 ` &lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;claude_desktop_config.json` 을 확인해보라고 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1ruAO/dJMcagLkF9k/4nOnoF9p9Dozk6U5UlUVLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1ruAO/dJMcagLkF9k/4nOnoF9p9Dozk6U5UlUVLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1ruAO/dJMcagLkF9k/4nOnoF9p9Dozk6U5UlUVLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1ruAO%2FdJMcagLkF9k%2F4nOnoF9p9Dozk6U5UlUVLk%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;2160&quot; height=&quot;2444&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2444&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;필자의 경우 애초에 AppData\Roaming\Claude 경로가 없다고 떴다.&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;연동이 잘 되면, 실제로 설정 json 파일에 다음과 같이 자동으로 jetbrains mcpServers 설정이 들어가 있어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1840&quot; data-origin-height=&quot;746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LS72i/dJMcabQLkSO/iYFtc2BiLvK2LVk77bgKOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LS72i/dJMcabQLkSO/iYFtc2BiLvK2LVk77bgKOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LS72i/dJMcabQLkSO/iYFtc2BiLvK2LVk77bgKOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLS72i%2FdJMcabQLkSO%2FiYFtc2BiLvK2LVk77bgKOk%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;1840&quot; height=&quot;746&quot; data-origin-width=&quot;1840&quot; data-origin-height=&quot;746&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;1218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rEMTR/dJMcahjbAfB/onB4hnKgjIgbqswdLaR7sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rEMTR/dJMcahjbAfB/onB4hnKgjIgbqswdLaR7sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rEMTR/dJMcahjbAfB/onB4hnKgjIgbqswdLaR7sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrEMTR%2FdJMcahjbAfB%2FonB4hnKgjIgbqswdLaR7sk%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;1476&quot; height=&quot;1218&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;1218&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>dev/ai</category>
      <category>claude</category>
      <category>IntelliJ</category>
      <category>mcp</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/25</guid>
      <comments>https://hand-mk.tistory.com/25#entry25comment</comments>
      <pubDate>Mon, 23 Feb 2026 16:18:31 +0900</pubDate>
    </item>
    <item>
      <title>[비동기 이벤트 처리] Inotify + RabbitMQ를 활용한 실시간 파일 감지 및 비동기 처리 파이프라인 구축</title>
      <link>https://hand-mk.tistory.com/24</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;회사에서 폐쇄망 운영 환경의 SI 사업에 투입됐다.&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;본 사업의 목표는 일 평균 10만건 데이터를 송수신 하는 인터페이스를 구축 및 고도화 하는 것이다. 보안상 상세하게 기재하진 못하지만 간단하게 운영환경을 기술하자면, &lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;총 3대의 서버 (Rocky Linux 9.5) 가 구동된다. 물리적인 서버 3대가 있는 이유는 &lt;b&gt;서버 이중화&lt;/b&gt; 와 &lt;b&gt;예비 서버 용도&lt;/b&gt;이다. 이 3대 중 한 1대만 Active 상태를 유지하고 해당 서버를 통해 항공 데이터(.txt) 가 송수신된다. &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;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;데이터 양은&lt;b&gt; 하루 평균 10만건&lt;/b&gt;이다. 또한, 데이터 종류가 8가지이고 데이터 종류별로 타깃 단위 시스템에 매핑해서 송수신 해야 하는데 이 단위 시스템 수만 118개이다.... ㄷㄷ 처음엔 막막했지만 다행히 이 중 15개 시스템에만 연계가 되게끔 인터페이스를 구현하면 된다는 얘기를 듣고 조금 괜찮아졌다.&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;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;개발이 마무리 된 시점에서 연계 시스템을 구축하면서 겪었던 문제와 고민했던 내용을 기록해보고자 블로그에 작성해보고자 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. 본론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 양을 보고 예전 &amp;lt;GAGU&amp;gt; 사이드 플젝에서 채팅 기능 구현할 때 사용했던 `RabbitMQ` 를 무조건 사용해야겠다고 생각이 들었다. 문제는 &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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1. 시스템 내 FDS (File Delivery System) 에 송신 하고자 하는 파일 삽입 -&amp;gt; Gateway 의 /*/temp 디렉토리로 파일 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2. /temp 디렉토리에서 해당 데이터 바디 값이 MDD 를 준수하였는지 유효성 검증 후 /succ 또는 /fail 폴더로 이동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3. /succ 디렉토리로 들어오는 데이터만 연계 시스템으로 전송 (.txt 파일 생성)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&amp;ordm; 보안상 문제로 System A, System B 로 정의&lt;br /&gt;&amp;ordm; System A 를 기준으로 송수신 정의됨&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1413&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wfTbl/dJMcagLSS3F/JGyYlC3t7kqqh93fMwLqV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wfTbl/dJMcagLSS3F/JGyYlC3t7kqqh93fMwLqV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wfTbl/dJMcagLSS3F/JGyYlC3t7kqqh93fMwLqV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwfTbl%2FdJMcagLSS3F%2FJGyYlC3t7kqqh93fMwLqV0%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;1413&quot; height=&quot;372&quot; data-origin-width=&quot;1413&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 1번과 2번은 레거시 FDS 시스템에 종속적이여서 바꾸기 힘들다고 해서 /succ 파일에 들어오는 데이터만 문제없이 연계하면 되는 상황이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자가 이러한 요구사항을 구현하기 위한 시나리오는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 메시지 및 타깃 시스템별 데이터를 담는 Queue 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. /*/succ 로 들어오는 데이터를 &lt;b&gt;실시간으로 감지&lt;/b&gt; (단, 중복으로 데이터를 감지하면 안됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 실시간으로 감지된 데이터를 정의된 라우팅 키로 Queue 에 삽입&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Queue 에 적재된 데이터를 타깃 시스템에서 비동기로 처리&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;실시간 감지&lt;/b&gt;였다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 리눅스 환경과 호환이 잘 되는 디렉토리 이벤트 감지 서비스를 부지런히 찾아보았고, 이 과정에서 &lt;b&gt;Polling 감지&lt;/b&gt;, &lt;b&gt;Telegraf 사용&lt;/b&gt;, &lt;b&gt;Inotify 커널 이벤트&lt;/b&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;2.1. 신규 데이터 실시간 감지&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.1.1. polling (full-scan) - 성능 이슈 염려하여 기각&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단 가장 간단하게 '구현만' 할 수 있는 방법은 polling 방식이 있을 것 같았다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;주기적으로 `linux date(서버 현재 시각)`과 파일 생성시간을 비교하여 최신 일자일 경우 신규 데이터로 감지하는 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 되면 스케줄러로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;주기적으로 현재 시간과 +- 오차 시간을 적용하여 비교 후 처리&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;할텐데, 예외 상황이 많을 것 같았다. 스케줄러가 동작하지 않거나 지연이 됐을 때 데이터가 누락되는 현상이 발생할 수 있고, polling 으로 불필요한 조회 연산을 지속적으로 호출하게끔 되어 해당 방법은 소거하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.1.2. Telegraf - Queue 삽입까지 너무 오래걸려서 기각&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링 시스템 구현 관련 라이브러리를 찾던 중 `Telegraf` + `Grafana` 조합을 많이들 사용한다는 것을 알게 되었고, 이 중 `Telegraf` 에 실시간 감지 기능이 내장돼 있다는 걸 확인했다.&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;`Telegraf`는 `InfluxData`에서 개발하였으며 데이터베이스나 서버의 데이터 (디렉토리도 가능) 를 수집하는 Agent 역할을 한다. &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Docker hub 에도 공식 이미지가 있고, `telegraf.conf` 라는 설정 파일로 Agent 를 조작하는 느낌이라 설정이 간편했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hub.docker.com/_/telegraf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://hub.docker.com/_/telegraf&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767933974109&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;telegraf - Official Image | Docker Hub&quot; data-og-description=&quot;Quick reference Supported tags and respective Dockerfile links Quick reference (cont.) What is telegraf? Telegraf is an open source agent for collecting, processing, aggregating, and writing metrics. Based on a plugin system to enable developers in the com&quot; data-og-host=&quot;hub.docker.com&quot; data-og-source-url=&quot;https://hub.docker.com/_/telegraf&quot; data-og-url=&quot;https://hub.docker.com/_/telegraf&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://hub.docker.com/_/telegraf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hub.docker.com/_/telegraf&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;telegraf - Official Image | Docker Hub&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Quick reference Supported tags and respective Dockerfile links Quick reference (cont.) What is telegraf? Telegraf is an open source agent for collecting, processing, aggregating, and writing metrics. Based on a plugin system to enable developers in the com&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hub.docker.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 용으로 해당 디렉토리에 새로 생성 + 이동 됐을 때 로그로 바디 값을 출력하는 설정을 주었다.&lt;/p&gt;
&lt;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;telegraf.conf&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1767933576489&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[agent]

# 데이터 수집 주기
interval = &quot;10s&quot; 

# 수집된 데이터 처리 주기
flush_interval = &quot;10s&quot;

[[inputs.tail]] # 파일 내용 추적 섹션

# 감시할 파일 경로
files = [&quot;/watch-data/*.txt&quot;]

# 파일 새로 생겼을 때 조작
from_beginning = true

# 파일 안에 있는 값 그대로 사용
data_format = &quot;value&quot;

# 데이터 타입 지정
data_type = &quot;string&quot;
name_override = &quot;txtfile_monitor&quot;

[[outputs.file]]

# 파일 바디 값 출력
files = [&quot;stdout&quot;]
data_format=&quot;json&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;이후 Docker hub 에 기재돼 있는대로 container 구동을 하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1767935184612&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker run -d --name telegraf
  -v {telegraf.conf 실제 경로}:/etc/telegraf/telegraf.conf:ro \
  -v {타겟 디렉토리 경로}:/watch-data \
  telegraf&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 data-ke-size=&quot;size16&quot;&gt;1. 새로운 txt 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. /test 폴더 mv 명령어로 이동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 로그 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3288&quot; data-origin-height=&quot;1750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvPrSF/dJMcadOb1jh/FktGXHXtFDMKRCb92s0Kf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvPrSF/dJMcadOb1jh/FktGXHXtFDMKRCb92s0Kf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvPrSF/dJMcadOb1jh/FktGXHXtFDMKRCb92s0Kf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvPrSF%2FdJMcadOb1jh%2FFktGXHXtFDMKRCb92s0Kf1%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;3288&quot; height=&quot;1750&quot; data-origin-width=&quot;3288&quot; data-origin-height=&quot;1750&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;이후 단순 출력하는 부분을 RabbitMQ Queue 로 삽입 되게끔 수정하여 테스트 했을 때, 정상적으로 삽입되어 원하는 기능을 테스트 해볼 수 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1767940579646&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[agent]
interval = &quot;10s&quot;
flush_interval = &quot;10s&quot;
metric_batch_size = 1

[[inputs.tail]]
files = [&quot;/watch-data/*.txt&quot;]
from_beginning = true
data_format = &quot;value&quot;
data_type = &quot;string&quot;
name_override = &quot;txtfile_monitor&quot;

[[outputs.amqp]] # rabbitMQ 로 삽입
brokers = [&quot;amqp://guest:guest@{서버 IP}:5672&quot;]
data_format = &quot;json&quot;
exchange = &quot;test.exchange&quot;
exchange_type = &quot;direct&quot;
routing_key = &quot;test.routing.key&quot;
delivery_mode = &quot;persistent&quot;
exchange_durability = &quot;durable&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1562&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lVX3n/dJMcachvrrD/Qb9IXq1S9QHBQQyIPytSfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lVX3n/dJMcachvrrD/Qb9IXq1S9QHBQQyIPytSfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lVX3n/dJMcachvrrD/Qb9IXq1S9QHBQQyIPytSfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlVX3n%2FdJMcachvrrD%2FQb9IXq1S9QHBQQyIPytSfk%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;1562&quot; height=&quot;752&quot; data-origin-width=&quot;1562&quot; data-origin-height=&quot;752&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;다만 아쉬운건 이벤트 감지는 즉각적으로 일어나지만, Queue 까지 가기까지의 시간이 너무 오래 걸렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 데이터 1건을 이벤트 감지하고 Queue 에 삽입하는데 10초가 소요됐다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqkoqA/dJMcab4QNB5/MTQiwVL1wUWHGUdAnzmI0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqkoqA/dJMcab4QNB5/MTQiwVL1wUWHGUdAnzmI0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqkoqA/dJMcab4QNB5/MTQiwVL1wUWHGUdAnzmI0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqkoqA%2FdJMcab4QNB5%2FMTQiwVL1wUWHGUdAnzmI0k%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;858&quot; height=&quot;640&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 `Telegraf` 가 `Node-exporter` 처럼 메트릭 수집 도구 용도로 만들어졌기 때문이다. 어떤 데이터가 들어오든 내부적으로 `Telegraf Metric` 이라는 타입의 데이터로 변환한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;`데이터 읽기` -&amp;gt; `Telegraf Metric 변환` -&amp;gt; `버퍼에 저장` -&amp;gt; `Output 플러그인에서 다시 JSON으로 변환` -&amp;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;단순히 데이터를 감지하고 Queue 에 삽입하는 것이 아닌 앞단에 데이터 변환 과정이 있어 오래 걸린다고 한다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 커스텀 하는 것이 어려워 보였고, 만약 &lt;b&gt;10만건이 동시에 몰렸을 때 수행&lt;/b&gt;된다고 한다면 &lt;b&gt;병목현상&lt;/b&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;또 다른 문제는 Queue 에 보낼 때이다. '하나 보낼 때 오래걸리면, 대량을 묶어서 보내면 되지 않나?' 라고 생각이 들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`Telegraf` 는 효율성을 위해 &lt;b&gt;기본적으로 데이터를 Batch 로 묶어&lt;/b&gt; 보낸다. 그래서 앞선 `Telegraf.conf` 에서 `metric_batch_size = 1` 로 설정을 할 수 있고 만약 전송 성능을 향상 시키려면 이 값을 높이면 된다.&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;만약 1000개를 한 배치로 보내는데 이 중 100번째 데이터가 문제가 있다고 하면 데이터 정합성 문제가 발생할 수 있겠다 싶었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러 저러한 이유로 `Telegraf` 도 아쉽게 기각됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.1.3. Linux Inotify - 제일 적합&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`Telegraf` 를 떠나보내고.. 지친 상태로 README.md 를 읽던 중 Telegraf 가 Linux-Inotify 기반으로 만들어진 것을 알게 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/tail/README.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/tail/README.md&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767943864109&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;telegraf/plugins/inputs/tail/README.md at master &amp;middot; influxdata/telegraf&quot; data-og-description=&quot;Agent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data. - influxdata/telegraf&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/tail/README.md&quot; data-og-url=&quot;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/tail/README.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Itvc0/hyZRp5SLdN/zmwpyvaDUCkJoojnMc4ZJk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bhWRQ8/hyZRgOD1HS/bDjCEBkpKSjOE08sDWzb9k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/tail/README.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/influxdata/telegraf/blob/master/plugins/inputs/tail/README.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Itvc0/hyZRp5SLdN/zmwpyvaDUCkJoojnMc4ZJk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bhWRQ8/hyZRgOD1HS/bDjCEBkpKSjOE08sDWzb9k/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;telegraf/plugins/inputs/tail/README.md at master &amp;middot; influxdata/telegraf&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Agent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data. - influxdata/telegraf&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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eAeKiL/dJMcacu2LJu/ELdTPBRIXKx24ZXgPoFkVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eAeKiL/dJMcacu2LJu/ELdTPBRIXKx24ZXgPoFkVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eAeKiL/dJMcacu2LJu/ELdTPBRIXKx24ZXgPoFkVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeAeKiL%2FdJMcacu2LJu%2FELdTPBRIXKx24ZXgPoFkVk%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;709&quot; height=&quot;498&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이래서 README.md 를 잘 읽어야.....)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 이유로 Inotify 를 써보게 됐다.&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;`Inotify` 는 리눅스 커널에 &lt;b&gt;내장된 파일 시스템 감시 서브시스템&lt;/b&gt;으로 별도의 설치가 필요 없지만, 이를 특정 디렉토리를 감시하게끔 커스텀하고 RabbitMQ 와 연동하기 위해선 `inotify-tools` 패키지를 써야 된다고 한다.&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;Linux 내장 기능이기 때문에, Docker 기본 이미지는 가벼운 Linux 이미지를 사용하였고 관련된 패키지들을 빌드할 때 설치하였다.&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;Dockerfile&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1767944548684&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1. Alpine Linux 기반
FROM alpine:3.18

# 2. inotify-tools, python3, pip 설치
RUN apk add --no-cache inotify-tools python3 py3-pip

# Python 전용 RabbitMQ 통신 프로토콜 라이브러리 패키지
RUN pip3 install pika --break-system-packages

# 이벤트 발생시 RabbitMQ Queue 삽입 로직
COPY publisher.py /publisher.py

# Inotify-tools 스크립트
COPY watch-and-publish.sh /watch-and-publish.sh
RUN chmod +x /watch-and-publish.sh

# 실행
CMD [&quot;/watch-and-publish.sh&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;`Dockerfile` 에 있는 `/watch-and-publish.sh` 가 `inotify-tools` 를 사용해 특정 디렉토리에 신규 파일 생성 이벤트를 감지하는 스크립트고, `publisher.py` 가 Linux - RabbitMQ 서버 간 연동을 해주는 파이썬 코드다.&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;watch-and-publish.sh&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1767945150984&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/sh

WATCH_DIR_INSIDE_CONTAINER=${WATCH_DIR:-&quot;/data&quot;}

echo &quot;&amp;gt;&amp;gt;&amp;gt; File Watcher started.&quot;
echo &quot;&amp;gt;&amp;gt;&amp;gt; Watching: $WATCH_DIR_INSIDE_CONTAINER&quot;
echo &quot;&amp;gt;&amp;gt;&amp;gt; Target RabbitMQ: $RMQ_HOST (AMQP)&quot;

# WATCH_DIR_INSIDE_CONTAINER 를 관측해라
inotifywait -m -q -e close_write -e moved_to --format '%w%f' &quot;$WATCH_DIR_INSIDE_CONTAINER&quot; | \
python3 -u /publisher.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서 inotifywait이 특정 디렉토리를 관측하다가, 이동 이벤트를 감지하면 해당 파일 경로를 stdout 하고 파이프 구조를 통해 publisher.py 이 stdin으로 받는 구조다. 결국 python 에는 이벤트가 감지된 파일 경로가 들어간다.&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;publisher.py&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1767945203048&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import sys
import os
import pika
import json
import time
import select

# RabbitMQ 연결 설정
RMQ_HOST = os.environ.get('RMQ_HOST', 'localhost')
RMQ_PORT = int(os.environ.get('RMQ_PORT', 5672))
RMQ_USER = os.environ.get('RMQ_USER', 'guest')
RMQ_PASS = os.environ.get('RMQ_PASS', 'guest')
EXCHANGE = os.environ.get('RMQ_EXCHANGE', 'file.events')
ROUTING_KEY = os.environ.get('RMQ_ROUTING_KEY', 'file.new')

credentials = pika.PlainCredentials(RMQ_USER, RMQ_PASS)
parameters = pika.ConnectionParameters(host=RMQ_HOST, port=RMQ_PORT, credentials=credentials, heartbeat=60)

print(f&quot;&amp;gt;&amp;gt;&amp;gt; Python Publisher connecting to {RMQ_HOST}:{RMQ_PORT} (AMQP)...&quot;)

connection = None

# pika 패키지로 RabbitMQ 연결
try:
    connection = pika.BlockingConnection(parameters)
    channel = connection.channel()
    
    channel.exchange_declare(exchange=EXCHANGE, exchange_type='direct', durable=True)
  
    channel.confirm_delivery()

    print(&quot;&amp;gt;&amp;gt;&amp;gt; Connection established. Waiting for input...&quot;)

    # stdin 으로 받은 파일명
    while True:
        rlist, _, _ = select.select([sys.stdin], [], [], 1.0)

        if rlist:
            
            line = sys.stdin.readline()
            if not line:
                break
			
            file_path = line.strip()
            if not file_path:
                continue
			
            # 파일을 직접 읽음
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                # RabbitMQ 로 보낼 Payload 로 구성
                payload = {
                    &quot;filePath&quot;: file_path,
                    &quot;fileContent&quot;: content
                }
                body = json.dumps(payload)
				
                # 해당 라우팅 키로 전송
                channel.basic_publish(
                    exchange=EXCHANGE,
                    routing_key=ROUTING_KEY,
                    body=body,
                    properties=pika.BasicProperties(
                        delivery_mode=2,
                        content_type='application/json'
                    )
                )
                print(f&quot;Sent: {file_path}&quot;)

            except Exception as e:
                print(f&quot;Error processing file {file_path}: {e}&quot;, file=sys.stderr)
        else:
            connection.process_data_events()

except KeyboardInterrupt:
    print(&quot;Stopping...&quot;)
except Exception as e:
    print(f&quot;Critical Connection Error: {e}&quot;, file=sys.stderr)
finally:
    if connection and connection.is_open:
        connection.close()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`publisher.py` 에서 stdin 으로 받은 파일명으로 직접 읽어서 해당 바디값을 페이로드로 Queue 에 삽입하는 구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 스트립트들을 구성하고 docker container 로 구동시켰다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2184&quot; data-origin-height=&quot;36&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mt7mY/dJMcafsDVHA/okTSkJJVkDsb9J56XN6Npk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mt7mY/dJMcafsDVHA/okTSkJJVkDsb9J56XN6Npk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mt7mY/dJMcafsDVHA/okTSkJJVkDsb9J56XN6Npk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmt7mY%2FdJMcafsDVHA%2FokTSkJJVkDsb9J56XN6Npk%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;2184&quot; height=&quot;36&quot; data-origin-width=&quot;2184&quot; data-origin-height=&quot;36&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;그리고 발주처에서 제공한 파일들을 mv 명령어로 이동 됐을 때 Queue 에 정상적으로 삽입 되는 걸 확인 할 수 있었다..!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lbQRB/dJMcabqhhxh/O66XFMUPLKutxKyICCC640/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lbQRB/dJMcabqhhxh/O66XFMUPLKutxKyICCC640/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lbQRB/dJMcabqhhxh/O66XFMUPLKutxKyICCC640/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlbQRB%2FdJMcabqhhxh%2FO66XFMUPLKutxKyICCC640%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;710&quot; height=&quot;294&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;437&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kR7qt/dJMcafzq8zH/qYiCgABcNeOS61ENyPVeb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kR7qt/dJMcafzq8zH/qYiCgABcNeOS61ENyPVeb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kR7qt/dJMcafzq8zH/qYiCgABcNeOS61ENyPVeb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkR7qt%2FdJMcafzq8zH%2FqYiCgABcNeOS61ENyPVeb0%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;698&quot; height=&quot;437&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;437&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3652&quot; data-origin-height=&quot;1192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxhWDn/dJMcaarmcVT/y9SUGudPgT9JibMNQ4KbSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxhWDn/dJMcaarmcVT/y9SUGudPgT9JibMNQ4KbSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxhWDn/dJMcaarmcVT/y9SUGudPgT9JibMNQ4KbSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxhWDn%2FdJMcaarmcVT%2Fy9SUGudPgT9JibMNQ4KbSk%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;3652&quot; height=&quot;1192&quot; data-origin-width=&quot;3652&quot; data-origin-height=&quot;1192&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.1.4. 부하 테스트 후 개선&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;22&quot;&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 기술했다시피 꽤 대량의 데이터가 송수신된다. 그렇기 때문에 부하테스트를 해보기로 했고, 발주처에서 정의한 부하 정도는 3천건이라고 얘기하긴 했지만 필자는 발주처에서 제공한 데이터 전부를 넣어보고 부하테스트를 진행하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;1632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JCJpP/dJMcadatnt5/y95rvtImvfOy6Gn1rLEc7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JCJpP/dJMcadatnt5/y95rvtImvfOy6Gn1rLEc7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JCJpP/dJMcadatnt5/y95rvtImvfOy6Gn1rLEc7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJCJpP%2FdJMcadatnt5%2Fy95rvtImvfOy6Gn1rLEc7k%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;1522&quot; height=&quot;1632&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;1632&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;20781 건을 동시에 감시 디렉토리로 이동하는 테스트를 진행했고, 결과는 처참했다ㅋㅋㅋㅋㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;old-1.png&quot; data-origin-width=&quot;1021&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l67ok/dJMcaibRNs8/DE5k9Ddxem2BEgGqMIMPNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l67ok/dJMcaibRNs8/DE5k9Ddxem2BEgGqMIMPNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l67ok/dJMcaibRNs8/DE5k9Ddxem2BEgGqMIMPNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl67ok%2FdJMcaibRNs8%2FDE5k9Ddxem2BEgGqMIMPNK%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;1021&quot; height=&quot;432&quot; data-filename=&quot;old-1.png&quot; data-origin-width=&quot;1021&quot; data-origin-height=&quot;432&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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;old-2.png&quot; data-origin-width=&quot;1059&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNA8bc/dJMcadO4Xko/5pIcj2mqXJkfZhNQNB9Gx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNA8bc/dJMcadO4Xko/5pIcj2mqXJkfZhNQNB9Gx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNA8bc/dJMcadO4Xko/5pIcj2mqXJkfZhNQNB9Gx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNA8bc%2FdJMcadO4Xko%2F5pIcj2mqXJkfZhNQNB9Gx0%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;1059&quot; height=&quot;464&quot; data-filename=&quot;old-2.png&quot; data-origin-width=&quot;1059&quot; data-origin-height=&quot;464&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;초당 약 148건의 속도로 삽입됐는데 약 2분정도? 소요됐다. 근데 데이터는 2,465 건 누락됐다..ㅎ&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 가 알려준 문제로는 크게 3가지였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 동기 ACK 대기: 데이터 하나 송신 후 제대로 갔는지 체크하는 대기 시간 발생하여 대량 전송 시 병목현상 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. readLine(): readline()은&amp;nbsp;한&amp;nbsp;줄씩&amp;nbsp;시스템콜을&amp;nbsp;발생시켜&amp;nbsp;대량&amp;nbsp;입력&amp;nbsp;시&amp;nbsp;I/O&amp;nbsp;오버헤드가&amp;nbsp;큼.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. max_queued_events: inotify 이벤트 큐에 적재할 수 있는 최대 이벤트 수가 기본 값으로 2만건 수용이 안됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결 하기 위해서 다음과 같은 개선 사항을 알려줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 동기 ACK 대기 제거 (Publisher Confirm 비활성화)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pika 패키지의 confirm_delivery()는 메시지를 1건 보낼 때마다 RabbitMQ broker가 &quot;잘 받았어&quot;라고 응답(ACK)을 줄 때까지 기다리는 기능이다. 비유하자면 택배를 보내는데, 한 박스 보내고 &amp;rarr; 상대방이 &quot;받았습니다&quot; 전화할 때까지 기다리고 &amp;rarr; 다음 박스 보내고 &amp;rarr; 또 전화 기다리고&amp;hellip; 이걸 2만번 반복하는 셈이다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;# Before: 매 건마다 broker ACK를 동기적으로 기다림
channel.confirm_delivery()

# After: ACK 대기 없이 연속 전송 (fire-and-forget)
# channel.confirm_delivery()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 끄면 택배를 쉬지 않고 연속으로 보내는 것과 같다. 대신 1000건마다 process_data_events()로 broker와 상태를 한번씩 확인하여 연결이 막히지 않게 했다. 참고로 confirm을 꺼도 TCP 연결 위에서 AMQP 프로토콜로 통신하기 때문에 메시지가 broker에 도달하는 것 자체는 보장된다.&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;2. readline() &amp;rarr; os.read() 청크 단위 읽기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sys.stdin.readline()은 파이프에서 데이터를 &lt;b&gt;한 줄씩&lt;/b&gt; 읽는다. 파일 경로가 2만건 들어오면 시스템콜이 2만번 발생한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;# Before: readline() - 한 줄씩 읽기
# 파이프에 &quot;file1\nfile2\nfile3\n...&quot; 이 들어오면
#   1번째 시스템콜 &amp;rarr; &quot;file1\n&quot; 획득
#   2번째 시스템콜 &amp;rarr; &quot;file2\n&quot; 획득
#   3번째 시스템콜 &amp;rarr; &quot;file3\n&quot; 획득
#   ... 2만번 반복

line = sys.stdin.readline()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;# After: os.read() - 1MB를 한번에 읽기
# 파이프에 &quot;file1\nfile2\nfile3\n...&quot; 이 들어오면
#   1번째 시스템콜 &amp;rarr; &quot;file1\nfile2\nfile3\n...file800\n&quot; 한번에 획득
#   직접 \n 기준으로 split해서 처리

chunk = os.read(sys.stdin.fileno(), 1024 * 1024)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마트에서 장바구니 없이 물건 하나 집고 계산하고, 다시 하나 집고 계산하는 것(readline)과, 카트에 한번에 담아서 한번에 계산하는 것(os.read)의 차이다. 시스템콜 횟수가 줄어드니 당연히 빨라진다.&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;3. max_queued_events 파라미터 변경&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;max_queued_events는 inotify 이벤트 큐에 적재할 수 있는 **최대 이벤트 수(건수)**다. 기본값은 16,384건인데, 2만건을 한번에 mv하면 이 큐가 넘쳐서 초과분 이벤트가 버려진다. 2,465건이 누락된 원인이 바로 이것이다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;# 기본값 확인
cat /proc/sys/fs/inotify/max_queued_events
# 16384

# 영구 적용 (reboot 후에도 유지)
echo &quot;fs.inotify.max_queued_events = 49152&quot; | sudo tee /etc/sysctl.d/99-inotify.conf
sudo sysctl -p /etc/sysctl.d/99-inotify.conf&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설정은 호스트 커널 레벨 파라미터이므로, Docker 컨테이너 안이 아니라 &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;다시 테스트 해봤을 때 초당 2520건 삽입 되는 걸 확인 할 수 있었고, 데이터 누락없이 10초만에 모두 Queue 에 삽입 된 걸 볼 수 있었다. 대략 2분 -&amp;gt; 10초로 감소된 셈이다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;latest-1.png&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;399&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4MhWP/dJMcagE7N7A/R48yiKufZGJyvpwvYbEK91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4MhWP/dJMcagE7N7A/R48yiKufZGJyvpwvYbEK91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4MhWP/dJMcagE7N7A/R48yiKufZGJyvpwvYbEK91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4MhWP%2FdJMcagE7N7A%2FR48yiKufZGJyvpwvYbEK91%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;1052&quot; height=&quot;399&quot; data-filename=&quot;latest-1.png&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;399&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;latest-2.png&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCfvyF/dJMb990i4yz/CPOr17aBtj1X63dD571KPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCfvyF/dJMb990i4yz/CPOr17aBtj1X63dD571KPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCfvyF/dJMb990i4yz/CPOr17aBtj1X63dD571KPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCfvyF%2FdJMb990i4yz%2FCPOr17aBtj1X63dD571KPk%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;1055&quot; height=&quot;346&quot; data-filename=&quot;latest-2.png&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;latest-3.png&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUKfWF/dJMcaiv699z/5kG1rKE9L3xCkcetGuuPY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUKfWF/dJMcaiv699z/5kG1rKE9L3xCkcetGuuPY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUKfWF/dJMcaiv699z/5kG1rKE9L3xCkcetGuuPY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUKfWF%2FdJMcaiv699z%2F5kG1rKE9L3xCkcetGuuPY0%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;842&quot; height=&quot;357&quot; data-filename=&quot;latest-3.png&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;357&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;h2 data-ke-size=&quot;size26&quot;&gt;3. 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누군가에겐 간단한 문제였을 수 있지만.. 처음 실시간 연계 파이프라인을 구축해보는 입장에서 꽤 어려웠고, 그만큼 많이 고민하면서 시스템 설계를 하였다. 이런 경험들이 쌓여서 다음 유사한 케이스에선 좀 더 삽질을 덜 해서 더욱 탄탄한 구조를 만들 수 있음 좋겠다!&lt;/p&gt;</description>
      <category>dev/backend</category>
      <category>inotify</category>
      <category>linux</category>
      <category>RabbitMQ</category>
      <category>telegraf</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/24</guid>
      <comments>https://hand-mk.tistory.com/24#entry24comment</comments>
      <pubDate>Fri, 9 Jan 2026 17:06:56 +0900</pubDate>
    </item>
    <item>
      <title>[WSL] Windows 부팅 후 WSL 자동 구동</title>
      <link>https://hand-mk.tistory.com/23</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;회사에서 폐쇄망 운영 환경의 SI 사업에 투입되게 되었다. 운영 환경에는 서버가 총 4대(Rocky-Linux 9.5 3대, &lt;b&gt;Windows 11 pro 1대&lt;/b&gt;) 가 있고, 그 중 Windows 11 pro 서버는 모니터링 서버로 `SpringBoot + Thymeleaf` 웹, `PostgreSQL DB`, `RabbitMQ`, 그 외 기타 WAS 가 &lt;b&gt;Docker Container 로 구동&lt;/b&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 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;환경 구축 및 배포 후 테스트를 정상적으로 마쳤다. 하지만 다음날 출근해보니 &lt;b&gt;모든 서버가 죽어&lt;/b&gt;있었다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1094&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6HqN1/dJMcacBM1DI/K5WJmGtpf1Vii5pSD4cz6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6HqN1/dJMcacBM1DI/K5WJmGtpf1Vii5pSD4cz6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6HqN1/dJMcacBM1DI/K5WJmGtpf1Vii5pSD4cz6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6HqN1%2FdJMcacBM1DI%2FK5WJmGtpf1Vii5pSD4cz6K%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;2880&quot; height=&quot;1094&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1094&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 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;확인해보니 &lt;b&gt;`WSL` 상태가 Stopped&lt;/b&gt; 로 되어 있었다. 만약 서버를 재부팅할 경우 WSL 을 &lt;b&gt;수동으로 켜주지 않는 이상 WSL 상에 있는 Docker Container 가 구동할 수 없는 문제&lt;/b&gt;가 발생한 것이였다. 물론 수동으로 하면 되지만, 개발자가 아닌 사용자 입장에서 번거로운 일이다.&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;'Windows 가 부팅 할 때 같이 켜지면 안되나?' 라는 의문으로 시작하여 해결한 내용을 기술하였다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 본론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wsl&amp;nbsp;은&amp;nbsp;pc&amp;nbsp;가&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;a href=&quot;https://wikidocs.net/219903&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://wikidocs.net/219903&lt;/a&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;다만, 필자의 경우 작업 스케줄러에 등록하는 방법은 성공하지 못했다. 해당 글에서 'vbs와 Windows 작업 스케줄러를 이용' 한 방법으론 성공하지 못했다고 한다. 필자의 경우 vbs (VB스크립트) 를 작성하여 `Windows 시작 프로그램` 에 등록하는 방법으로 성공하였다.&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.1. vbs 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;VBS(Visual Basic Script) &lt;/b&gt;는 Microsoft 가 만든 `Windows 운영체제 전용 자동화 스크립트` 이다. 리눅스에서의 `쉘 스크립트(.sh)` 와 비슷하다. 이 스크립트를 작성하여 시작프로그램으로 등록해두면 스크립트에 작성된 명령어를 실행한다.&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;윈도우 키 + `R` 을 눌러 `shell:startup (시작 프로그램 파일 탐색기)` 을 연다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;399&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czYlNH/dJMcahC5kAs/axFVZC84fcH3ZksOE32CJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czYlNH/dJMcahC5kAs/axFVZC84fcH3ZksOE32CJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czYlNH/dJMcahC5kAs/axFVZC84fcH3ZksOE32CJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczYlNH%2FdJMcahC5kAs%2FaxFVZC84fcH3ZksOE32CJ0%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;399&quot; height=&quot;206&quot; data-origin-width=&quot;399&quot; data-origin-height=&quot;206&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;해당 폴더에 처음엔 txt 파일로 생성하여 WSL 구동 스크립트를 기입한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767621882196&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Windows Script Host Shell 도구를 불러옴
Set WshShell = CreateObject(&quot;WScript.Shell&quot;)

# wsl 실행 명령을 실행하되, 0 을 붙여 백그라운드로 실행
# 이때 Ubuntu-22.04 은 실제 WSL 설치된 리눅스 배포판 명을 입력
WshShell.Run &quot;wsl.exe -d Ubuntu-22.04&quot;, 0

# 메모리 해제
Set WshShell = Nothing&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;141&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FSXPc/dJMcajt5uPH/kI2KA8ecXJngqnLEyIjB41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FSXPc/dJMcajt5uPH/kI2KA8ecXJngqnLEyIjB41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FSXPc/dJMcajt5uPH/kI2KA8ecXJngqnLEyIjB41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFSXPc%2FdJMcajt5uPH%2FkI2KA8ecXJngqnLEyIjB41%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;646&quot; height=&quot;141&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;141&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;이후 `.txt` &amp;gt; `.vbs` 로 변경해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bR5LNI/dJMcagEcWee/B8cm7nKe7vz1cPaKPjyjOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bR5LNI/dJMcagEcWee/B8cm7nKe7vz1cPaKPjyjOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bR5LNI/dJMcagEcWee/B8cm7nKe7vz1cPaKPjyjOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbR5LNI%2FdJMcagEcWee%2FB8cm7nKe7vz1cPaKPjyjOk%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;651&quot; height=&quot;102&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;102&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;이후 재부팅하여 테스트 해보면 자동으로 WSL 이 구동중인걸 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1115&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfTQMQ/dJMcaiaWar8/FBlc7IsmZtNK8zptj8EVJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfTQMQ/dJMcaiaWar8/FBlc7IsmZtNK8zptj8EVJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfTQMQ/dJMcaiaWar8/FBlc7IsmZtNK8zptj8EVJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfTQMQ%2FdJMcaiaWar8%2FFBlc7IsmZtNK8zptj8EVJK%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;1115&quot; height=&quot;628&quot; data-origin-width=&quot;1115&quot; data-origin-height=&quot;628&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>dev/se</category>
      <category>docker</category>
      <category>vbs</category>
      <category>windows</category>
      <category>WSL</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/23</guid>
      <comments>https://hand-mk.tistory.com/23#entry23comment</comments>
      <pubDate>Mon, 5 Jan 2026 23:34:31 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] Windows 11 폐쇄망 환경 Docker 설치 (Docker Desktop x)</title>
      <link>https://hand-mk.tistory.com/22</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* OS: Windows 11 Pro (이지만, 자택에서 해보니 그냥 Windows 11 에서도 무방)&lt;br /&gt;* WSL: v2.6.3.0&lt;br /&gt;* containerd.io: v2.2.1-1&lt;br /&gt;* docker-buildx-plugin: v0.30.1-1&lt;br /&gt;* docker-ce: v29.1.3-1&lt;br /&gt;* docker-ce-cli: v29.1.3-1&lt;br /&gt;* docker-compose-plugin: v5.0.0-1&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 폐쇄망 운영 환경의 SI 사업에 투입됐다. 운영 환경에서 총 4대의 서버 (Windows 11 Pro OS 1대, Rocky Linux 9.5 3대) 가 투입 되었고 각 서버에 필자가 개발한 소프트웨어를 프로세스로 띄워야 하는 상황이였다. 특히 Windows 11 에는 DB서버와 RabbitMQ 서버, 모니터링 웹서버를 띄워야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 web(Thymeleaf) 하나만 띄운다고 한다면 jdk 설치 파일과 jar 빌드 파일만 갖고 가면 되지만, 여러 설치 파일을 설치해야만 했고 그 과정에서 의존성 충돌이 많이 일어날 것 같아 &lt;b&gt;Docker&amp;nbsp;가 필수&lt;/b&gt;라고 생각했다. 회사 선배들에게 물어보니, Linux 폐쇄망 환경에서의 Docker 설치 경험은 있으나 Windows 11 환경에서 Docker 를 사용해본 경험은 없다고 했다.. 그래서 '내가 한번 해봐?' 라는 생각으로 여러 시행착오 끝에 나만의 매뉴얼을 만들었다. 이에 대해 기술한 내용이다.&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;2. 본론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 windows 에 docker engine 을 직접 구동하는 것은 불가능하다. 이러한 이유로 microsoft 는 &lt;b&gt;wsl(windows subsystem for linux)&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;다음은 wsl 을 구성하는 방법이다.&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.1. 리눅스 서브 시스템 활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼭 &lt;b&gt;cmd 관리자 모드로 실행&lt;/b&gt;해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;635&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0lyk4/dJMcajniX0E/XYKmL6TRVyhhB5G4RzZBm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0lyk4/dJMcajniX0E/XYKmL6TRVyhhB5G4RzZBm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0lyk4/dJMcajniX0E/XYKmL6TRVyhhB5G4RzZBm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0lyk4%2FdJMcajniX0E%2FXYKmL6TRVyhhB5G4RzZBm1%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;752&quot; height=&quot;635&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;635&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;Microsoft WSL 2 공식문서에 따르면 WSL2를 설치하기 전에 `Linux용 Windows 하위 시스템`, `Virtual Machine Platform` 선택적 기능을 사용하도록 설정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#step-1---enable-the-windows-subsystem-for-linux&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#step-1---enable-the-windows-subsystem-for-linux&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767417966944&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;이전 버전의 WSL에 대한 수동 설치 단계&quot; data-og-description=&quot;wsl install 명령을 사용하는 대신 이전 버전의 Windows에 WSL을 수동으로 설치하는 단계별 지침입니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#step-1---enable-the-windows-subsystem-for-linux&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b6WiLk/hyZRaOJjCn/1PiDILcHic8jm6ZVNR8LR1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/czEU1P/hyZPOsrmxT/nmamJNGkannqOPP1kyPhbK/img.png?width=1672&amp;amp;height=935&amp;amp;face=0_0_1672_935,https://scrap.kakaocdn.net/dn/sK5ZL/hyZPFI3k9I/KYkzE7G5EqkgaMUmatJP5K/img.png?width=1200&amp;amp;height=932&amp;amp;face=0_0_1200_932&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#step-1---enable-the-windows-subsystem-for-linux&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#step-1---enable-the-windows-subsystem-for-linux&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b6WiLk/hyZRaOJjCn/1PiDILcHic8jm6ZVNR8LR1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/czEU1P/hyZPOsrmxT/nmamJNGkannqOPP1kyPhbK/img.png?width=1672&amp;amp;height=935&amp;amp;face=0_0_1672_935,https://scrap.kakaocdn.net/dn/sK5ZL/hyZPFI3k9I/KYkzE7G5EqkgaMUmatJP5K/img.png?width=1200&amp;amp;height=932&amp;amp;face=0_0_1200_932');&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;이전 버전의 WSL에 대한 수동 설치 단계&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;wsl install 명령을 사용하는 대신 이전 버전의 Windows에 WSL을 수동으로 설치하는 단계별 지침입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 명령어를 통해 활성화 해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1767418016658&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 윈도우 서브시스템 활성화
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

# 가상머신 플랫폼 활성화
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOL4bt/dJMcacV4i2G/XJk7Yn7pjPPC9bhzmQOKR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOL4bt/dJMcacV4i2G/XJk7Yn7pjPPC9bhzmQOKR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOL4bt/dJMcacV4i2G/XJk7Yn7pjPPC9bhzmQOKR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOL4bt%2FdJMcacV4i2G%2FXJk7Yn7pjPPC9bhzmQOKR1%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;954&quot; height=&quot;664&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;h3 data-ke-size=&quot;size23&quot;&gt;2.2. WSL 2 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 windows 10 까지는 wsl_update_x64.msi legecy 를 설치하여 wsl 을 수동으로 설치할 수 있었으나, 최신 Windows 11 설정과 충돌이 나서 이런 문구가 뜰것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`계속하려면 Linux용 Windows 하위 시스템 최신 버전으로 업데이트해야 합니다. 'wsl.exe --update'를 실행하여 업데이트할 수 있습니다. 자세한&amp;nbsp;내용은&amp;nbsp;&lt;a href=&quot;https://aka.ms/wslinstall&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://aka.ms/wslinstall &lt;/a&gt;참조하세요. Linux용 Windows 하위 시스템 설치하려면 아무 키나 누르세요. CTRL-C 누르거나 이 창을 닫아 취소하세요. 이 프롬프트는 60초 후 시간이 초과됩니다. 서버&amp;nbsp;이름이나&amp;nbsp;주소를&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;없습니다.`&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제를 해결하기 위해 microsoft 에서 최신 wsl 엔진 패키지를 배포하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;온라인 환경에서 아래 microsoft 공식 github 에서 wsl 설치 msixbundle 을 다운로드 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/WSL&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/microsoft/WSL&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767418469831&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 - microsoft/WSL: Windows Subsystem for Linux&quot; data-og-description=&quot;Windows Subsystem for Linux. Contribute to microsoft/WSL development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/WSL&quot; data-og-url=&quot;https://github.com/microsoft/WSL&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/PzITN/hyZQ2QGAZP/7JbdrHESvCicgLWosxTeBk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bERhZb/hyZQ57IevJ/7bupDUmFbwnV1y1A7vwaKk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/WSL&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/WSL&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/PzITN/hyZQ2QGAZP/7JbdrHESvCicgLWosxTeBk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bERhZb/hyZQ57IevJ/7bupDUmFbwnV1y1A7vwaKk/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 - microsoft/WSL: Windows Subsystem for Linux&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Windows Subsystem for Linux. Contribute to microsoft/WSL 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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;787&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uGlKl/dJMcafrJvwr/ULUvItJuT4MFoDCg1LO38k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uGlKl/dJMcafrJvwr/ULUvItJuT4MFoDCg1LO38k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uGlKl/dJMcafrJvwr/ULUvItJuT4MFoDCg1LO38k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuGlKl%2FdJMcafrJvwr%2FULUvItJuT4MFoDCg1LO38k%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;945&quot; height=&quot;787&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;787&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;441&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXEk8a/dJMcabQorjQ/R6KhAQfTnbyHJmUjUlAjJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXEk8a/dJMcabQorjQ/R6KhAQfTnbyHJmUjUlAjJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXEk8a/dJMcabQorjQ/R6KhAQfTnbyHJmUjUlAjJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXEk8a%2FdJMcabQorjQ%2FR6KhAQfTnbyHJmUjUlAjJ0%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;790&quot; height=&quot;441&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;441&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;물론 wsl 빌드 파일을 포함하여 모든 설치 파일은 폐쇄망 환경에 cd나 usb 로 가져간다는 전제다.&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;이후 `powershell` 에서 wsl 설치 명령어를 호출한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767418694196&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Add-AppxPackage -Path &quot;{msixbundle 실제 경로}&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1115&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TkGkq/dJMcahpyFqi/HsZGsKsamIAVyooCmELDd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TkGkq/dJMcahpyFqi/HsZGsKsamIAVyooCmELDd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TkGkq/dJMcahpyFqi/HsZGsKsamIAVyooCmELDd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTkGkq%2FdJMcahpyFqi%2FHsZGsKsamIAVyooCmELDd1%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;1115&quot; height=&quot;628&quot; data-origin-width=&quot;1115&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cM51UT/dJMcaaqp6pd/aStU8NKIMT8BIB1jCPKc51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cM51UT/dJMcaaqp6pd/aStU8NKIMT8BIB1jCPKc51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cM51UT/dJMcaaqp6pd/aStU8NKIMT8BIB1jCPKc51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcM51UT%2FdJMcaaqp6pd%2FaStU8NKIMT8BIB1jCPKc51%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;887&quot; height=&quot;176&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;176&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;`wsl -v` 하여 버전을 찍어봤을 때 정상적으로 출력되어야 한다.&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.3. Ubuntu 배포판 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;온라인&amp;nbsp;환경에선&amp;nbsp;microsoft&amp;nbsp;store&amp;nbsp;를&amp;nbsp;이용하면&amp;nbsp;되나,&amp;nbsp;오프라인&amp;nbsp;환경에서&amp;nbsp;설치하기&amp;nbsp;위해선&amp;nbsp;AppBundle&amp;nbsp;파일이&amp;nbsp;필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;온라인 환경에서 microsoft 공식 wsl 문서에서 Ubuntu 22.04LTS 버전 다운로드 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#downloading-distributions&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#downloading-distributions&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767418876014&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;이전 버전의 WSL에 대한 수동 설치 단계&quot; data-og-description=&quot;wsl install 명령을 사용하는 대신 이전 버전의 Windows에 WSL을 수동으로 설치하는 단계별 지침입니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#downloading-distributions&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gOYEO/hyZQ8wzwlw/z7bTgxfTWnWbiq5Pfhs4f1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/BGSGa/hyZRaOJzae/XCDsqtcDrAPcEFX2F7HN90/img.png?width=1672&amp;amp;height=935&amp;amp;face=0_0_1672_935,https://scrap.kakaocdn.net/dn/dQnips/hyZQ4OvUOs/1pwOKnE3AcOfxfQYjwi0J1/img.png?width=1200&amp;amp;height=932&amp;amp;face=0_0_1200_932&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#downloading-distributions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install-manual#downloading-distributions&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gOYEO/hyZQ8wzwlw/z7bTgxfTWnWbiq5Pfhs4f1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/BGSGa/hyZRaOJzae/XCDsqtcDrAPcEFX2F7HN90/img.png?width=1672&amp;amp;height=935&amp;amp;face=0_0_1672_935,https://scrap.kakaocdn.net/dn/dQnips/hyZQ4OvUOs/1pwOKnE3AcOfxfQYjwi0J1/img.png?width=1200&amp;amp;height=932&amp;amp;face=0_0_1200_932');&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;이전 버전의 WSL에 대한 수동 설치 단계&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;wsl install 명령을 사용하는 대신 이전 버전의 Windows에 WSL을 수동으로 설치하는 단계별 지침입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvTzwI/dJMcafSN2Lq/qPXO74FwuS94RIn9IYPIaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvTzwI/dJMcafSN2Lq/qPXO74FwuS94RIn9IYPIaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvTzwI/dJMcafSN2Lq/qPXO74FwuS94RIn9IYPIaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvTzwI%2FdJMcafSN2Lq%2FqPXO74FwuS94RIn9IYPIaK%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;748&quot; height=&quot;235&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 `.AppxBundle` 을 `zip` 확장자로 변경하고 압축을 풀어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/moIs9/dJMcahb0kSx/EEozobd3uOURT461SmVrL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/moIs9/dJMcahb0kSx/EEozobd3uOURT461SmVrL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/moIs9/dJMcahb0kSx/EEozobd3uOURT461SmVrL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmoIs9%2FdJMcahb0kSx%2FEEozobd3uOURT461SmVrL1%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;772&quot; height=&quot;96&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압축을 푼 이후 해당 디렉토리에 들어가 `Ubuntu_2204.1.7.0_x64.appx` 를 다시 `zip` 확장자로 변경하여 압축을 풀어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;854&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c77eJk/dJMcai9L99g/0QCh7nkk2cPFdKkcBW4p71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c77eJk/dJMcai9L99g/0QCh7nkk2cPFdKkcBW4p71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c77eJk/dJMcai9L99g/0QCh7nkk2cPFdKkcBW4p71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc77eJk%2FdJMcai9L99g%2F0QCh7nkk2cPFdKkcBW4p71%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;1556&quot; height=&quot;854&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;854&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압축이 풀린 디렉토리에 들어가보면 `install.tar.gz` 파일이 있다. 이 압축 파일을 통해 Ubuntu 를 설치할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp4o92/dJMcaiPtCwG/BKOtlzUqKOJoRFfj9a0xCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp4o92/dJMcaiPtCwG/BKOtlzUqKOJoRFfj9a0xCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp4o92/dJMcaiPtCwG/BKOtlzUqKOJoRFfj9a0xCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp4o92%2FdJMcaiPtCwG%2FBKOtlzUqKOJoRFfj9a0xCK%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;679&quot; height=&quot;451&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;451&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;cmd 에서 install.tar.gz import 하는 명령어를 호출한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767419201873&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wsl --import Ubuntu-22.04 C:\WSL\Ubuntu2204 &quot;{실제 install.tar.gz 경로}&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xdein/dJMcadHpAUP/ccdDRtuShL2GtLJIUOiQhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xdein/dJMcadHpAUP/ccdDRtuShL2GtLJIUOiQhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xdein/dJMcadHpAUP/ccdDRtuShL2GtLJIUOiQhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxdein%2FdJMcadHpAUP%2FccdDRtuShL2GtLJIUOiQhK%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;961&quot; height=&quot;102&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;102&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;/p&gt;
&lt;pre id=&quot;code_1767419234632&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 설치된 wsl 버전 확인
wsl -l -v&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7UWQz/dJMcaiva0le/t6D1vj2aKBQWz0DDikfMwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7UWQz/dJMcaiva0le/t6D1vj2aKBQWz0DDikfMwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7UWQz/dJMcaiva0le/t6D1vj2aKBQWz0DDikfMwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7UWQz%2FdJMcaiva0le%2Ft6D1vj2aKBQWz0DDikfMwk%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;436&quot; height=&quot;248&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;248&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;이제 설치된 wsl (Ubuntu 환경) 에 Docker 를 설치하면 된다.&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.4. Docker engine 설치 및 구동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`docker desktop` 이 기업 라이센스가 생겨 1년에 1,000만달러 이상의 이익이 발생하는 경우 사용료를 지불해야 한다. 이러한 이유로 `docker engine` 설치 파일을 다운 받아 구동시켜야 한다. 필자의 경우 `docker desktop` 을 설치하면 안되는 상황이였다.&lt;br /&gt;만약 자택이나 기업 라이센스에 걸리지 않을 경우 그냥 `docker desktop` 만 설치하면 매우 과정이 쉬워지니 이후 과정을 보지 않아도 된다.&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;docker 공식 문서에 따르면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-from-a-package&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.docker.com/engine/install/ubuntu/#install-from-a-package&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767419476935&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;Ubuntu&quot; data-og-description=&quot;Jumpstart your client-side server applications with Docker Engine on Ubuntu. This guide details prerequisites and multiple methods to install Docker Engine on Ubuntu.&quot; data-og-host=&quot;docs.docker.com&quot; data-og-source-url=&quot;https://docs.docker.com/engine/install/ubuntu/#install-from-a-package&quot; data-og-url=&quot;https://docs.docker.com/engine/install/ubuntu/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oBIyz/hyZQ2C9Qq7/lh8AfRKPHhJOrjsxVVRMc1/img.jpg?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260&quot;&gt;&lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-from-a-package&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.docker.com/engine/install/ubuntu/#install-from-a-package&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oBIyz/hyZQ2C9Qq7/lh8AfRKPHhJOrjsxVVRMc1/img.jpg?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260');&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;Ubuntu&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jumpstart your client-side server applications with Docker Engine on Ubuntu. This guide details prerequisites and multiple methods to install Docker Engine on Ubuntu.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.docker.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;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;containerd.io__.deb&lt;/li&gt;
&lt;li&gt;docker-ce__.deb&lt;/li&gt;
&lt;li&gt;docker-ce-cli__.deb&lt;/li&gt;
&lt;li&gt;docker-buildx-plugin__.deb&lt;/li&gt;
&lt;li&gt;docker-compose-plugin__.deb&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상기 5개의 파일을&amp;nbsp; &lt;a href=&quot;https://download.docker.com/linux/ubuntu/dists/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://download.docker.com/linux/ubuntu/dists/&lt;/a&gt; 에서 다운받으면 된다고 한다.&lt;/p&gt;
&lt;figure id=&quot;og_1767419577949&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;Index of linux/ubuntu/dists/&quot; data-og-description=&quot;&quot; data-og-host=&quot;download.docker.com&quot; data-og-source-url=&quot;https://download.docker.com/linux/ubuntu/dists/&quot; data-og-url=&quot;https://download.docker.com/linux/ubuntu/dists/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://download.docker.com/linux/ubuntu/dists/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://download.docker.com/linux/ubuntu/dists/&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;Index of linux/ubuntu/dists/&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;download.docker.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;OS 별 이후 경로가 다르다. Ubuntu 의 경우 `/jammy/poll/stable/amd64/` 이다. 때문에 Docker engine 설치 &lt;b&gt;공식문서에서 OS 별 경로를 잘 확인&lt;/b&gt;해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 주의할 점은 레거시 버전도 존재하는데 버전을 어느정도는 맞춰서 설치해야 의존성 충돌이 발생하지 않는다. 필자의&amp;nbsp;경우&amp;nbsp;각&amp;nbsp;파일별&amp;nbsp;가장&amp;nbsp;최신&amp;nbsp;버전으로&amp;nbsp;맞춰&amp;nbsp;다운받았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;949&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boU8bX/dJMb99SAkY9/6NbWsAqAwQQdlMGOyO4PwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boU8bX/dJMb99SAkY9/6NbWsAqAwQQdlMGOyO4PwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boU8bX/dJMb99SAkY9/6NbWsAqAwQQdlMGOyO4PwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboU8bX%2FdJMb99SAkY9%2F6NbWsAqAwQQdlMGOyO4PwK%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;1920&quot; height=&quot;949&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;949&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YEJhP/dJMb9957mX7/Y4XZdxG5aFGBu0cR6KfvKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YEJhP/dJMb9957mX7/Y4XZdxG5aFGBu0cR6KfvKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YEJhP/dJMb9957mX7/Y4XZdxG5aFGBu0cR6KfvKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYEJhP%2FdJMb9957mX7%2FY4XZdxG5aFGBu0cR6KfvKK%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;692&quot; height=&quot;213&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 .deb 파일들이 있는 디렉토리 경로에서 cmd 를 열고 wsl 쉘을 열어 다음 명령어로 설치한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767419745918&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo dpkg -i *.deb&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;이후 docker 명령어를 실행해보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory` 라고 뜰 것이다.&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;이는 Docker engine 을 구동시키지 않았기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker engine 을 구동하기 전, `systemctl` 에 등록하여 wsl 부팅시 자동으로 docker engine 이 켜지게끔 설정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`systemctl` 을 등록하려면 `systemd` 가 켜져있어야 하는데 wsl 은 켜져있지 않아 부팅시 켜져있게끔 설정해야 한다.&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;wsl 부팅시 설정을 하려면 wsl.conf 를 생성해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767420086214&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /etc
sudo nano wsl.conf&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;nano 명령어로 열어 wsl 이 systemd 를 사용하게끔 지정해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767420276278&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[boot]
systemd=true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 변경사항을 적용하기 위해 `wsl` 을 재부팅 하고 `docker` 가 자동으로 실행되게끔 `systemctl` 에 등록해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767420331001&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;exit # wsl 쉘에서
   
wsl --shutdown # 윈도우 cmd 에서&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1767420342003&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo systemctl start docker // 등록
sudo systemctl status docker // 등록 상태 확인&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwB0av/dJMcaihGL9J/x04XxbzsSmFguAXlkEjLtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwB0av/dJMcaihGL9J/x04XxbzsSmFguAXlkEjLtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwB0av/dJMcaihGL9J/x04XxbzsSmFguAXlkEjLtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwB0av%2FdJMcaihGL9J%2Fx04XxbzsSmFguAXlkEjLtk%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;900&quot; height=&quot;239&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;active 상태가 떠야 docker engine 이 정상적으로 구동되고 있다는것이다.&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;이제 docker 명령어가 정상적으로 호출된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;937&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CKMiy/dJMcacBL8dy/awbQ6lOUGTUtcilBJUTXs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CKMiy/dJMcacBL8dy/awbQ6lOUGTUtcilBJUTXs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CKMiy/dJMcacBL8dy/awbQ6lOUGTUtcilBJUTXs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCKMiy%2FdJMcacBL8dy%2FawbQ6lOUGTUtcilBJUTXs1%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;937&quot; height=&quot;92&quot; data-origin-width=&quot;937&quot; data-origin-height=&quot;92&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;h2 data-ke-size=&quot;size26&quot;&gt;3. 결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폐쇄망 환경에서 windows 에 docker 를 설치하는 것은 흔치 않지만, 필자와 같은 국가사업에 투입되어 있는 분이라면 꼭 한번쯤은 경험해 봐야 하는 것 같다. 부디 필자의 경험이 부족하지만 좋은 레퍼런스가 되길 기원한다..!&lt;/p&gt;</description>
      <category>dev/se</category>
      <category>docker</category>
      <category>ubuntu</category>
      <category>WSL</category>
      <category>폐쇄망</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/22</guid>
      <comments>https://hand-mk.tistory.com/22#entry22comment</comments>
      <pubDate>Sat, 3 Jan 2026 15:10:44 +0900</pubDate>
    </item>
    <item>
      <title>[Ollama] Ollama 사용기 (2)</title>
      <link>https://hand-mk.tistory.com/21</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* 운영 서버 스펙: Cent OS7, RAM: 16GB, GPU X&lt;br /&gt;* Python: v3.13&lt;br /&gt;* Flask: 3.1.0&lt;br /&gt;* Langchain: 0.3.25&lt;br /&gt;* ollama: 0.4.8&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hand-mk.tistory.com/19&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;이전 포스팅: https://hand-mk.tistory.com/19&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767245854134&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;[Ollama] Ollama 사용기 (1)&quot; data-og-description=&quot;* OS: Windows 11 pro* RAM: 64GB* CPU: Intel(R) Core(TM) i7-14700* GPU: 내장 그래픽 1. 서론회사 백오피스 서비스 개발에서 항공 전문에 대한 AI 해석 및 요약 기능 구현 담당을 맡았다..!내 주전공은 데이터 사이&quot; data-og-host=&quot;hand-mk.tistory.com&quot; data-og-source-url=&quot;https://hand-mk.tistory.com/19&quot; data-og-url=&quot;https://hand-mk.tistory.com/19&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dkGIye/hyZQY1nMLG/9JElmKXXGI1qUwPKfdSyg0/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/YYxy7/hyZQBUiq8T/hKCk3ZUYj81NzEzLbr2ry1/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/FmmYT/hyZQFI8w7z/bVJNCFK6Ie5IbLrZ1GFAlk/img.png?width=1920&amp;amp;height=1032&amp;amp;face=0_0_1920_1032&quot;&gt;&lt;a href=&quot;https://hand-mk.tistory.com/19&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hand-mk.tistory.com/19&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dkGIye/hyZQY1nMLG/9JElmKXXGI1qUwPKfdSyg0/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/YYxy7/hyZQBUiq8T/hKCk3ZUYj81NzEzLbr2ry1/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/FmmYT/hyZQFI8w7z/bVJNCFK6Ie5IbLrZ1GFAlk/img.png?width=1920&amp;amp;height=1032&amp;amp;face=0_0_1920_1032');&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;[Ollama] Ollama 사용기 (1)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;* OS: Windows 11 pro* RAM: 64GB* CPU: Intel(R) Core(TM) i7-14700* GPU: 내장 그래픽 1. 서론회사 백오피스 서비스 개발에서 항공 전문에 대한 AI 해석 및 요약 기능 구현 담당을 맡았다..!내 주전공은 데이터 사이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hand-mk.tistory.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;background-color: #ffffff; color: #353638; text-align: start;&quot;&gt;회사 백오피스 서비스 개발에서 항공 전문에 대한&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;AI 해석 및 요약 기능 구현&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: start;&quot;&gt;담당을 맡았다. 항공 전문을 AI 가 이해하기 쉽게 한국어로 해석하고 요약하는데 있어, 가장 어려운 점은 &lt;b&gt;AI 가 항공 전문에서 사용하는 코드(ICAO 공항 코드, 날씨코드 등) 를 모른다는 것&lt;/b&gt;이다. 물론 OpenAPI 나 Gemini 클라우드 환경에서 전문넣고 해석해 달라고 하면 웹 전반을 RAG 화 하여 사용하기 때문에 성능이 괜찮지만, &lt;b&gt;본 AI 모델은 온프레미스 서버에 설치하고 사용&lt;/b&gt;해야 하기 때문에 어려움을 겪었다. 그래서 필자가 생각한 방법은 어느정도 해석에 필요한 핵심 단어들을 전처리하고 이를 Ollama 모델을 통해 문장화 시키는 방식이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: start;&quot;&gt;어찌저찌 ICAO, 항공기상업무지침 pdf 등 디코딩 문서를 확인하여 파서 로직을 구현하여 이제 RESTful 하게 만드는 단계이다. 이에 대해 기술한 내용이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 본론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 사용자 &amp;gt; `Python (Flask)` &amp;gt; `AI (Ollama)` &amp;gt; 의 파이프라인으로 구성하였다. Flask 에서 AI 요청 및 응답을 받기 위해선 Ollama 를 Docker Container 으로 구동시켜야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F12HH/dJMcahQBKxp/tYPpcovAIO3IEcBKPz97p1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F12HH/dJMcahQBKxp/tYPpcovAIO3IEcBKPz97p1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F12HH/dJMcahQBKxp/tYPpcovAIO3IEcBKPz97p1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF12HH%2FdJMcahQBKxp%2FtYPpcovAIO3IEcBKPz97p1%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;2880&quot; height=&quot;662&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1. 운영 서버 Ollama Docker Container 구동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker Image 는 Docker Hub 공식 이미지를 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hub.docker.com/r/ollama/ollama&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hub.docker.com/r/ollama/ollama&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767253661326&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;ollama/ollama - Docker Image&quot; data-og-description=&quot;&quot; data-og-host=&quot;hub.docker.com&quot; data-og-source-url=&quot;https://hub.docker.com/r/ollama/ollama&quot; data-og-url=&quot;https://hub.docker.com/r/ollama/ollama&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://hub.docker.com/r/ollama/ollama&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hub.docker.com/r/ollama/ollama&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;ollama/ollama - Docker Image&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hub.docker.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker-compose.yml&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1767253583166&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;services:
    ollama:
        volumes:
            - ollama:/root/.ollama
        ports:
            - 11434:11434
        container_name: ollama
        image: ollama/ollama
volumes:
    ollama:
        external: true
        name: ollama&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.2. Python 에서 Ollama 호출&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ollama 는 python 과의 통합사용을 적극 장려하고 있어, 관련 패키지를 공유하고 있고 이에 대한 내용은 공식 organization 에서 확인 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ollama/ollama-python&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/ollama/ollama-python&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767254050512&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 - ollama/ollama-python: Ollama Python library&quot; data-og-description=&quot;Ollama Python library. Contribute to ollama/ollama-python development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ollama/ollama-python&quot; data-og-url=&quot;https://github.com/ollama/ollama-python&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/HoYVL/hyZRcrOr8z/lvQpAFxVuyrwmKPMp04XtK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/W6c4n/hyZQJQuTqg/4fJnXYsGVnsNKJiTaGDK11/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ollama/ollama-python&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ollama/ollama-python&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/HoYVL/hyZRcrOr8z/lvQpAFxVuyrwmKPMp04XtK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/W6c4n/hyZQJQuTqg/4fJnXYsGVnsNKJiTaGDK11/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 - ollama/ollama-python: Ollama Python library&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ollama Python library. Contribute to ollama/ollama-python 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;Python 에서 Ollama 서버를 호출하고 제어하려면 `ollama`, `ollama-langchain` 패키지를 설치해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767253932167&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install langchain-ollama

pip install ollama&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 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;div style=&quot;background-color: #191a1c; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;from langchain_ollama import OllamaLLM

llm = OllamaLLM(model=&quot;exaone3.5:7.8b&quot;,
                base_url=&quot;http://ollama:11434&quot; # 동일 Docker network 상에서 구동될 예정
)&lt;/code&gt;&lt;/pre&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;공식문서 상에서는 ollama 패키지의 `chat` 을 통해 생성했다.&lt;/p&gt;
&lt;pre id=&quot;code_1767254433644&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from ollama import chat
from ollama import ChatResponse

response: ChatResponse = chat(model='gemma3', messages=[
  {
    'role': 'user',
    'content': 'Why is the sky blue?',
  },
])
print(response['message']['content'])
# or access fields directly from the response object
print(response.message.content)&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;이 방법도 '가능' 하다. 하지만 프롬프트나 vectorDB 를 chain 형식으로 묶어 호출하지 못하고 직접 개발자가 구현해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비행계획서 (FPL) 전문에 대한 질문 프롬프트를 다음과 같이 작성했을 때&lt;/p&gt;
&lt;div style=&quot;background-color: #191a1c; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;FPL_TEMPLATE =  &quot;&quot;&quot;
아래는 ICAO 비행계획서 최초 제출 시 전문에 들어간 정보야.
콜사인 : {aircraft_id},
비행 일자 : {flight_date},            
출발 공항 : {departure_airport},
출발 예정 시간 : {departure_time},
도착 공항 : {arrival_airport},
도착 예정 시간 : {arrival_time},
대체 공항 : {alternate_airport},
출발 공항 부터 도착 공항까지 소요 시간 : {duration_time},
비행 경로 : {flight_route},
비행 종류 : {flight_method}

'{flight_date}, {departure_airport}에서 {arrival_airport}으로 운행 예정인 {aircraft_id}편은 {flight_method}으로, 출발 예정 시각은 {departure_time}이고, 도착 예정 시각은 {arrival_time}이며, 비행 경로는 {flight_route}이고, 대체 공항은 {alternate_airport}로 지정 돼 있습니다.'
위 정보들만 전부 사용해서 최초 제출 비행 계획서를 위 예시대로 한국어로 한문장으로 요약해줘.
경로는 누락되면 안돼.
&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&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;`langchain` 을 사용할 경우 템플릿에 변수를 자동으로 넣은 다음, `|` 로 추가하여 응답을 요청하면 된다.&lt;/p&gt;
&lt;div style=&quot;background-color: #191a1c; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 전문 전처리 함수
result = fpl_split(code)

summary_template = FPL_TEMPLATE
summary_kwargs = {
    &quot;aircraft_id&quot;: result.get(&quot;aircraft_id&quot;, &quot;&quot;),
    &quot;flight_date&quot;: result.get(&quot;flight_date&quot;, &quot;&quot;),
    &quot;departure_airport&quot;: result.get(&quot;departure_airport&quot;, &quot;&quot;),
    &quot;departure_time&quot;: result.get(&quot;departure_time&quot;, &quot;&quot;),
    &quot;arrival_airport&quot;: result.get(&quot;arrival_airport&quot;, &quot;&quot;),
    &quot;arrival_time&quot;: result.get(&quot;arrival_time&quot;, &quot;&quot;),
    &quot;alternate_airport&quot;: result.get(&quot;alternate_airport&quot;, &quot;&quot;),
    &quot;duration_time&quot;: result.get(&quot;duration&quot;, &quot;&quot;),
    &quot;flight_route&quot;: result.get(&quot;flight_route&quot;, &quot;&quot;),
    &quot;flight_method&quot;: result.get(&quot;flight_method&quot;, &quot;&quot;),
}

# 프롬프트에 자동으로 변수 기입
prompt = ChatPromptTemplate.from_template(
        summary_template
    )
    
chain = prompt | llm # 프롬프트 체이닝
response = chain.invoke(summary_kwargs)&lt;/code&gt;&lt;/pre&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;만약 `chat` 으로 생성할 경우에는 변수를 직접 지정하고, 응답 결과에 대해서 포맷팅 또한 이후 전처리 과정을 추가해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767255398812&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 사용자가 직접 문자열을 조립해야 함
formatted_prompt = summary_template.format(
    aircraft_id=data['id'], 
    flight_route=data['route'],
    ... # 모든 변수를 일일이 나열
)
ollama.chat(messages=[{'role': 'user', 'content': formatted_prompt}])

# 이후 '네 요약해드리겠습니다.' 와 같은 불필요한 응답 값 전처리 해야함.&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;gt; 해석에 필요한 전처리 함수로 AI 해석 및 요약 전체 코드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1767265714181&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def fpl_llm(code: str):
    print(&quot;[fpl_llm] model called!&quot;)

    content = fpl_extract_message(code)

    message_type = extract_message_type(content)

    print(f&quot;[fpl_llm] message type : {message_type}&quot;)
	
    # 비행 계획서
    if message_type == &quot;FPL&quot;:
        result = fpl_split(code)
        summary_template = FPL_TEMPLATE
        summary_kwargs = {
            &quot;aircraft_id&quot;: result.get(&quot;aircraft_id&quot;, &quot;&quot;),
            &quot;flight_date&quot;: result.get(&quot;flight_date&quot;, &quot;&quot;),
            &quot;departure_airport&quot;: result.get(&quot;departure_airport&quot;, &quot;&quot;),
            &quot;departure_time&quot;: result.get(&quot;departure_time&quot;, &quot;&quot;),
            &quot;arrival_airport&quot;: result.get(&quot;arrival_airport&quot;, &quot;&quot;),
            &quot;arrival_time&quot;: result.get(&quot;arrival_time&quot;, &quot;&quot;),
            &quot;alternate_airport&quot;: result.get(&quot;alternate_airport&quot;, &quot;&quot;),
            &quot;duration_time&quot;: result.get(&quot;duration&quot;, &quot;&quot;),
            &quot;flight_route&quot;: result.get(&quot;flight_route&quot;, &quot;&quot;),
            &quot;flight_method&quot;: result.get(&quot;flight_method&quot;, &quot;&quot;),
        }
        
    # 일정 변경 계획서    
    elif message_type == &quot;CHG&quot;:
        result = chg_split(code)
        summary_template = CHG_TEMPLATE
        summary_kwargs = {
            &quot;aircraft_id&quot;: result.get(&quot;aircraft_id&quot;, &quot;&quot;),
            &quot;flight_date&quot;: result.get(&quot;flight_date&quot;, &quot;&quot;),
            &quot;departure_airport&quot;: result.get(&quot;departure_airport&quot;, &quot;&quot;),
            &quot;departure_time&quot;: result.get(&quot;departure_time&quot;, &quot;&quot;),
            &quot;arrival_airport&quot;: result.get(&quot;arrival_airport&quot;, &quot;&quot;),
            &quot;changed_callsign&quot;: result.get(&quot;changed_callsign&quot;, &quot;&quot;),
            &quot;changed_flight_method&quot;: result.get(&quot;changed_flight_method&quot;, &quot;&quot;),
            &quot;changed_flight_num&quot;: result.get(&quot;changed_flight_num&quot;, &quot;&quot;),
            &quot;changed_flight_equip&quot;: result.get(&quot;changed_flight_equip&quot;, &quot;&quot;),
            &quot;changed_dep_airport&quot;: result.get(&quot;changed_dep_airport&quot;, &quot;&quot;),
            &quot;changed_dep_time&quot;: result.get(&quot;changed_dep_time&quot;, &quot;&quot;),
            &quot;changed_route&quot;: result.get(&quot;changed_route&quot;, &quot;&quot;),
            &quot;changed_alternative_airport&quot;: result.get(&quot;changed_alternative_airport&quot;, &quot;&quot;),
            &quot;changed_arr_airport&quot;: result.get(&quot;changed_arr_airport&quot;, &quot;&quot;),
            &quot;changed_arr_time&quot;: result.get(&quot;changed_arr_time&quot;, &quot;&quot;),
            &quot;changed_dof&quot;: result.get(&quot;changed_dof&quot;, &quot;&quot;)
        }
        
    # 지연 계획서    
    elif message_type == &quot;DLA&quot;:
        result = dla_split(code)
        summary_template = DLA_TEMPLATE
        summary_kwargs = {
            &quot;flight_date&quot;: result.get(&quot;flight_date&quot;, &quot;&quot;),
            &quot;aircraft_id&quot;: result.get(&quot;aircraft_id&quot;, &quot;&quot;),
            &quot;departure_airport&quot;: result.get(&quot;departure_airport&quot;, &quot;&quot;),
            &quot;arrival_airport&quot;: result.get(&quot;arrival_airport&quot;, &quot;&quot;),
            &quot;changed_time&quot;: result.get(&quot;changed_time&quot;, &quot;&quot;),
        }
    # 취소 계획서    
    elif message_type == &quot;CNL&quot;:
        result = cnl_split(code)
        summary_template = CNL_TEMPLATE
        summary_kwargs = {
            &quot;flight_date&quot;: result.get(&quot;flight_date&quot;, &quot;&quot;),
            &quot;aircraft_id&quot;: result.get(&quot;aircraft_id&quot;, &quot;&quot;),
            &quot;departure_airport&quot;: result.get(&quot;departure_airport&quot;, &quot;&quot;),
            &quot;arrival_airport&quot;: result.get(&quot;arrival_airport&quot;, &quot;&quot;),
            &quot;departure_time&quot;: result.get(&quot;departure_time&quot;, &quot;&quot;),
        }
        
    # 출발 계획서    
    elif message_type == &quot;DEP&quot;:
        result = dep_split(code)
        summary_template = DEP_TEMPLATE
        summary_kwargs = {
            &quot;flight_date&quot;: result.get(&quot;flight_date&quot;, &quot;&quot;),
            &quot;aircraft_id&quot;: result.get(&quot;aircraft_id&quot;, &quot;&quot;),
            &quot;departure_airport&quot;: result.get(&quot;departure_airport&quot;, &quot;&quot;),
            &quot;arrival_airport&quot;: result.get(&quot;arrival_airport&quot;, &quot;&quot;),
            &quot;departure_time&quot;: result.get(&quot;departure_time&quot;, &quot;&quot;),
        }
        
    # 도착 계획서    
    else:
        result = arr_split(code)
        summary_template = ARR_TEMPLATE
        summary_kwargs = {
            &quot;aircraft_id&quot;: result.get(&quot;aircraft_id&quot;, &quot;&quot;),
            &quot;departure_time&quot;: result.get(&quot;departure_time&quot;, &quot;&quot;),
            &quot;departure_airport&quot;: result.get(&quot;departure_airport&quot;, &quot;&quot;),
            &quot;arrival_airport&quot;: result.get(&quot;arrival_airport&quot;, &quot;&quot;),
            &quot;arrive_time&quot;: result.get(&quot;arrive_time&quot;, &quot;&quot;),
        }

    print(f&quot;[fpl_llm] result : {result}&quot;)

    prompt = ChatPromptTemplate.from_template(
        summary_template
    )

    chain = prompt | llm
    response = chain.invoke(summary_kwargs)
	
    # 응답 값 DB 저장
    try:
        orm = SessionLocal()
        new_fpl_rst = FplAiResult(code, response)
        orm.add(new_fpl_rst)
        orm.commit()
        print(f&quot;[fpl_llm] saved result successfully!&quot;)
    except Exception as e:
        orm.rollback()
        print(f&quot;[fpl_llm] fail to save result! cause : {str(e)}&quot;)
    finally:
        orm.close()

    return success_response(response)&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;이 `fpl_llm` 을 /fpl 엔드포인트에서 호출되게끔 flask 라우터를 설정하여 Ollama 를 호출 할 수 있게 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이하 항공 고시보 (Notam), 날씨 (Metar, Taf) 또한 동일한 파이프라인으로 구성하였다.&lt;/p&gt;
&lt;div style=&quot;background-color: #191a1c; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;fpl_model = api.model('FplModel', {
    'fpl': fields.String(required=True, description='Fpl Contents'),
})
@api.route(&quot;/fpl&quot;)
class Fpl(Resource):
    @api.expect(fpl_model)
    def post(self):
        body = request.get_json()
        code = body.get(&quot;fpl&quot;)

        return fpl_llm(code)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;625&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qGO5v/dJMcabCQtI9/myqbDmhIKra2wYbhD2tPpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qGO5v/dJMcabCQtI9/myqbDmhIKra2wYbhD2tPpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qGO5v/dJMcabCQtI9/myqbDmhIKra2wYbhD2tPpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqGO5v%2FdJMcabCQtI9%2FmyqbDmhIKra2wYbhD2tPpk%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;1410&quot; height=&quot;625&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;625&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1412&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ykDdA/dJMcaiPs1bE/cxT8nNUAFHIhsUnXZksUJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ykDdA/dJMcaiPs1bE/cxT8nNUAFHIhsUnXZksUJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ykDdA/dJMcaiPs1bE/cxT8nNUAFHIhsUnXZksUJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FykDdA%2FdJMcaiPs1bE%2FcxT8nNUAFHIhsUnXZksUJK%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;1412&quot; height=&quot;312&quot; data-origin-width=&quot;1412&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 서버(CentOS 7) 기준 응답 테스트시 다음과 같이 속도가 나왔다. 회사 선배들을 대상으로 실제 단위 테스트에서 100개의 전문을 테스트 했을 때 약 65개의 응답에 대해 100% &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;해석&lt;span&gt; &lt;/span&gt;&lt;/span&gt;만족도가 있다고 답변했고, 나머지 응답에 대해서 약간의 이상치(한국어랑 영어 섞임)가 보였다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;[GIN] 2025/05/26 - 03:00:55 | 200 | 58.96749926s | 172.21.0.7 | POST &quot;/api/generate&quot; &lt;br /&gt;[GIN] 2025/05/26 - 04:57:22 | 200 | 37.214435283s | 172.21.0.7 | POST &quot;/api/generate&quot;&lt;br /&gt;[GIN] 2025/05/26 - 05:00:29 | 200 | 19.606718973s | 172.21.0.7 | POST &quot;/api/generate&quot; &lt;br /&gt;[GIN] 2025/05/26 - 05:11:35 | 200 | 12.929574367s | 172.21.0.7 | POST &quot;/api/generate&quot;&lt;br /&gt;[GIN] 2025/05/26 - 05:01:36 | 200 | 12.077014236s | 172.21.0.7 | POST &quot;/api/generate&quot; &lt;br /&gt;[GIN] 2025/05/26 - 05:03:29 | 200 | 10.600447629s | 172.21.0.7 | POST &quot;/api/generate&quot;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;987&quot; data-origin-height=&quot;70&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t2QQf/dJMb99Zlv5c/KzorQAS8E6ka6qX8jCJkA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t2QQf/dJMb99Zlv5c/KzorQAS8E6ka6qX8jCJkA1/img.png&quot; data-alt=&quot;김포공항 -&amp;amp;gt; kim포공항이라고 답변&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t2QQf/dJMb99Zlv5c/KzorQAS8E6ka6qX8jCJkA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft2QQf%2FdJMb99Zlv5c%2FKzorQAS8E6ka6qX8jCJkA1%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;987&quot; height=&quot;70&quot; data-origin-width=&quot;987&quot; data-origin-height=&quot;70&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;김포공항 -&amp;gt; kim포공항이라고 답변&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.3. vectorDB 화&lt;/h3&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;이전에는 ICAO 공항코드, 날씨(구름양, 강수량등) 코드와 같은 룩업 데이터를 txt 파일에 수집하였다. 이를 파싱시 line 으로 읽어 한국 라벨값을 찾는 방식이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이전방식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;airport_codes.txt (ICAO 공항코드) 약 5100개&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1767267894582&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LECO: 아코루냐 공항
EKYT: 올보르 공항
EKAH: 오르후스 공항
BGAA: 아시아앗 공항
HAJM: 아바 세구드 공항
HADR: 아바 테나 데자즈마흐 일마 국제공항
OIAA: 아바단 공항
NGAB: 아바이앙 공항
UNAA: 아바칸 공항
CYXX: 애버츠퍼드 국제공항
DAOB: 압델하피드 부수프 부 체키프 공항
RKRR: 인천비행정보구역
WARA: 압둘 라흐만 살레 공항
HCMR: 압둘라히 유수프 국제공항
FTTC: 아베셰 공항
HTZA: 아베이드 아마니 카루메 국제공항
MUSC: 아벨 산타마리아 공항
NGTB: 아베마마 아톨 공항
EGPD: 애버딘 국제공항
KABR: 애버딘 지역 공항
OEAB: 아바 공항
KABI: 애빌린 지역 공항
MMCS: 아브라함 곤잘레스 국제 공항
KSPI: 에이브러햄 링컨 캐피털 공항
LIBP: 아브루초 공항
OMAA: 아부다비 국제공항
OIBA: 아부무사 공항
HEBL: 아부심벨 공항
KARA: 아카디아나 지역공항
SKAD: 아칸디 알시데스 페르난데스 공항
MMAA: 아카풀코 알바레스 국제공항
DGAA: 아크라 코토카 국제공항
WAHS: 아흐마드 야니 국제공항&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1767267938782&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def lookup_code(key, file):
    with open(file, encoding=&quot;UTF-8&quot;) as f:
        for line in f:
            if line.startswith(f&quot;{key}:&quot;):
                print(f&quot;[lookup_code] found code! : {key}&quot;)
                return line.split(&quot;:&quot;, 1)[1].strip()
        print(f&quot;[lookup_code] not found code! : {key}&quot;)
        return None&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;공항코드 일부분만 발취하였으나, 얼추 세어보니 전문 해석용 룩업 데이터가 모두 취합시 약 7만건 정도 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이들을 모두 vectorDB 화 하여, 전문 타입별로 해석시 임베딩 하는 방법으로 변경해 보았다.&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;공항 ICAO 코드 vectorDB화 (2분 46초 소요)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1767268051981&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import os
from langchain_community.document_loaders import TextLoader
from langchain_core.documents import Document
from langchain_ollama import OllamaEmbeddings
from langchain_chroma import Chroma

def create_airport_vectordb():
    # 데이터 로드 (airport_codes.txt)
    file_path = &quot;airport_codes.txt&quot;
    documents = []
    
    with open(file_path, &quot;r&quot;, encoding=&quot;UTF-8&quot;) as f:
        for line in f:
            if &quot;:&quot; in line:
                code, name = line.split(&quot;:&quot;, 1)
                # 텍스트는 공항 이름으로, 메타데이터에 코드를 저장
                doc = Document(
                    page_content=f&quot;{code.strip()}: {name.strip()}&quot;,
                    metadata={&quot;code&quot;: code.strip(), &quot;name&quot;: name.strip()}
                )
                documents.append(doc)

    # 임베딩 모델 설정 (Ollama 사용)
    embeddings = OllamaEmbeddings(model=&quot;mxbai-embed-large&quot;)

    # VectorDB 생성 및 로컬 저장
    vector_db = Chroma.from_documents(
        documents=documents,
        embedding=embeddings,
        persist_directory=&quot;./airport_db&quot; # 로컬 폴더에 DB 저장
    )
    print(&quot;Airport VectorDB 구축 완료!&quot;)
    return vector_db&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;36&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PV6bp/dJMb9956INT/CnBnCB7Nos6AoXNGtC8DVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PV6bp/dJMb9956INT/CnBnCB7Nos6AoXNGtC8DVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PV6bp/dJMb9956INT/CnBnCB7Nos6AoXNGtC8DVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPV6bp%2FdJMb9956INT%2FCnBnCB7Nos6AoXNGtC8DVk%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;853&quot; height=&quot;36&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;36&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;기존의 라인으로 읽던 방식을 생성한 vectorDB 기반으로 데이터 값을 추론할 수 있게끔 하여, AI 에게 던져준다.&lt;/p&gt;
&lt;pre id=&quot;code_1767268497639&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def lookup_airport(code):
    
    # 기존의 파일 읽기 방식(lookup_code)을 VectorDB 방식으로 대체 
    # VectorDB에서 유사도 기반 검색
    results = vector_db.similarity_search(code, k=1)
    
    if results:
        # 검색된 결과의 메타데이터에서 공항명을 반환
        return results[0].metadata[&quot;name&quot;]
    
    return code # 못 찾으면 원래 코드라도 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 했을 때 확실히 응답 속도에서 향상된 모습을 확인 할 수 있었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;[GIN] 2025/06/25 - 14:22:15 | 200 | 15.423s | 172.21.0.7 | POST &quot;/api/generate&quot; &lt;br /&gt;[GIN] 2025/06/25 - 14:25:42 | 200 | 12.112s | 172.21.0.7 | POST &quot;/api/generate&quot; &lt;br /&gt;[GIN] 2025/06/25 - 14:30:08 | 200 | 9.876s | 172.21.0.7 | POST &quot;/api/generate&quot; &lt;br /&gt;[GIN] 2025/06/25 - 14:35:12 | 200 | 8.543s | 172.21.0.7 | POST &quot;/api/generate&quot;&lt;br /&gt;[GIN] 2025/06/25 - 14:42:55 | 200 | 7.210s | 172.21.0.7 | POST &quot;/api/generate&quot; &lt;br /&gt;[GIN] 2025/06/25 - 14:50:33 | 200 | 6.836s | 172.21.0.7 | POST &quot;/api/generate&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 아쉬운 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 아쉬운 점은 파인튜닝을 못해본 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 LLM 모델을 로컬에 받아서 파인튜닝을 하고 싶었지만, 그렇게 하려면 {전문: 해석결과} 의 데이터셋이 필요하다. 이 데이터셋이 없을까? 없다... 왜냐면 전문을 한국어 자연어 문장으로 보는 경우가 생각보다 많지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통은 이렇게 문단별로 중요 키워드의 값을 본다. 그래서 문장화 하기 위한 전처리 과정이 오래 걸려 파인튜닝을 못해본 것이 아쉽다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwXt0y/dJMcabQnPil/nNdvNRvwI2soBPiFrqtt9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwXt0y/dJMcabQnPil/nNdvNRvwI2soBPiFrqtt9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwXt0y/dJMcabQnPil/nNdvNRvwI2soBPiFrqtt9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwXt0y%2FdJMcabQnPil%2FnNdvNRvwI2soBPiFrqtt9k%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;646&quot; height=&quot;346&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;346&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;두번째는 데이터가 많이 없다. 물론 전문은 맘만 먹으면 수집 모듈을 만들어서(한국 한정) DB 에 쌓아둘 수 있을 것 같다. 문제는 해석 한국어 라벨링 데이터이다. 항공 도메인은 보안상의 문제로 폐쇄적이여서 항적, 항로와 같은 특정 데이터는 구매해서 사용해야 한다. 그렇기 때문에 한국어로 해석을 한다? 문제를 풀고 답이 맞는지 검사를 해야 하는데 정답지가 부족하다.&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 를 다룰 수 있는 기회가 생긴다면 그땐 더 딥하고 재밌는 튜닝을 해보고 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/ai</category>
      <category>ollama</category>
      <category>rag</category>
      <category>vectordb</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/21</guid>
      <comments>https://hand-mk.tistory.com/21#entry21comment</comments>
      <pubDate>Thu, 1 Jan 2026 21:17:22 +0900</pubDate>
    </item>
    <item>
      <title>[GitLab] Windows 11 GitLab 연동</title>
      <link>https://hand-mk.tistory.com/20</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학부생 때는 `Github` 로만 프로젝트를 업로드하고 관리해서 몰랐는데, 실제 회사에 가보니 보안을 위해 GitLab 을 온프레미스 서버에 설치하여 사내망에서 관리하였다. 이를 위해 GitLab 연동이 필요했고, 온프레미스 환경 뿐 아니라 클라우드 GitLab 에서도 동일하게 적용 가능하여 `ssh key` 로 인증 및 연동하는 방법에 대해 기술한 내용이다.&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;2. 본론&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1. SSH Key 생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공개키 (Public Key) 와 개인키 (Private Key) 쌍을 생성해야 한다. 과거에는 윈도우에 기본 SSH 도구가 없어서 `Git Bash` 를 사용하곤 했으나 윈도우 10 이상부터는 그냥 PowerShell 에서도 `ssh-keygen` 명령어 사용이 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFzsjr/dJMcac9yfal/ylvO090pmC54yvggEIsK30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFzsjr/dJMcac9yfal/ylvO090pmC54yvggEIsK30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFzsjr/dJMcac9yfal/ylvO090pmC54yvggEIsK30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFzsjr%2FdJMcac9yfal%2FylvO090pmC54yvggEIsK30%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;658&quot; height=&quot;431&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;431&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;ssh 키 값은 \Users\{사용자 명}\.ssh 경로에 생성된다. .pub 확장자 파일이 공개키, 없는것이 개인키이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Izuqj/dJMcaf6j1Fu/yQHl8S8BlrkeTrGrgrwYIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Izuqj/dJMcaf6j1Fu/yQHl8S8BlrkeTrGrgrwYIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Izuqj/dJMcaf6j1Fu/yQHl8S8BlrkeTrGrgrwYIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIzuqj%2FdJMcaf6j1Fu%2FyQHl8S8BlrkeTrGrgrwYIK%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;635&quot; height=&quot;164&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;164&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;h3 data-ke-size=&quot;size23&quot;&gt;2.2. 공개키 GitLab 등록&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공개키를 메모장 or VSCode 로 열어 복사 후&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sCRrv/dJMcagjQ5fX/tOkSXs1meAFEKK9Wtnb1pK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sCRrv/dJMcagjQ5fX/tOkSXs1meAFEKK9Wtnb1pK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sCRrv/dJMcagjQ5fX/tOkSXs1meAFEKK9Wtnb1pK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsCRrv%2FdJMcagjQ5fX%2FtOkSXs1meAFEKK9Wtnb1pK%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;2400&quot; height=&quot;1600&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&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;GitLab 홈페이지 &amp;gt; Edit Profile&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPygD9/dJMcaaxbbGE/p4s4QETqhaO4YAqZ7Kgtg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPygD9/dJMcaaxbbGE/p4s4QETqhaO4YAqZ7Kgtg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPygD9/dJMcaaxbbGE/p4s4QETqhaO4YAqZ7Kgtg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPygD9%2FdJMcaaxbbGE%2Fp4s4QETqhaO4YAqZ7Kgtg0%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;294&quot; height=&quot;329&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;329&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;좌측 탭에 SSH KEY 클릭&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 widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chBLnc/dJMcahXoi8i/rJ36T8PWSiedWiY6EcP2a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chBLnc/dJMcahXoi8i/rJ36T8PWSiedWiY6EcP2a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chBLnc/dJMcahXoi8i/rJ36T8PWSiedWiY6EcP2a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchBLnc%2FdJMcahXoi8i%2FrJ36T8PWSiedWiY6EcP2a0%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;232&quot; height=&quot;532&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;532&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;`Add new key` 클릭하여 복사한 공개키 삽입&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2602&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ikmtm/dJMcaaRt1Mw/LejEHArk7WWAfRILKf2F6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ikmtm/dJMcaaRt1Mw/LejEHArk7WWAfRILKf2F6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ikmtm/dJMcaaRt1Mw/LejEHArk7WWAfRILKf2F6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIkmtm%2FdJMcaaRt1Mw%2FLejEHArk7WWAfRILKf2F6k%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;2602&quot; height=&quot;1440&quot; data-origin-width=&quot;2602&quot; data-origin-height=&quot;1440&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;이제 로컬에서 GitLab 레포지토리를 클론할 수 있다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.3. GitLab 레포지토리 클론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 `Code` 버튼을 누르면 다음과 같은 박스가 뜨고, 이때 `Clone with SSH` 를 사용해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;742&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dd6rZ3/dJMcabbMzol/jXL0no6P3rkpCKoW74KB3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dd6rZ3/dJMcabbMzol/jXL0no6P3rkpCKoW74KB3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dd6rZ3/dJMcabbMzol/jXL0no6P3rkpCKoW74KB3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdd6rZ3%2FdJMcabbMzol%2FjXL0no6P3rkpCKoW74KB3K%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;680&quot; height=&quot;742&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;742&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;원하는 디렉토리 경로 cmd 에서 다음과 같은 명령어를 호출한다.&lt;/p&gt;
&lt;pre id=&quot;code_1767249758709&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone {복사한 SSH}&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;Key 등록 후 처음 Clone 시 다음과 같은 질문이 나올 수 있다. yes 로 환대해주면 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Are you sure you want to continue connecting (yes/no/[fingerprint])? yes&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;모든 프로세스가 끝나면 정상적으로 Clone 이 되어 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1767249919965&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;remote: Total 83 (delta 0), reused 0 (delta 0), pack-reused 83 (from 1)
Receiving objects: 100% (83/83), 11.53 MiB | 5.20 MiB/s, done.
Resolving deltas: 100% (4/4), done.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/scm</category>
      <category>gitlab</category>
      <category>PowerShell</category>
      <category>SSH</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/20</guid>
      <comments>https://hand-mk.tistory.com/20#entry20comment</comments>
      <pubDate>Thu, 1 Jan 2026 15:46:42 +0900</pubDate>
    </item>
    <item>
      <title>[Ollama] Ollama 사용기 (1)</title>
      <link>https://hand-mk.tistory.com/19</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* OS: Windows 11 pro&lt;br /&gt;* RAM: 64GB&lt;br /&gt;* CPU: Intel(R) Core(TM) i7-14700&lt;br /&gt;* GPU: 내장 그래픽&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yUuFT/dJMcacocNzn/Icf31ZmPi78cuVWVnVCgn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yUuFT/dJMcacocNzn/Icf31ZmPi78cuVWVnVCgn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yUuFT/dJMcacocNzn/Icf31ZmPi78cuVWVnVCgn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyUuFT%2FdJMcacocNzn%2FIcf31ZmPi78cuVWVnVCgn0%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;1474&quot; height=&quot;438&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;회사 백오피스 서비스 개발에서 항공 전문에 대한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;AI 해석 및 요약 기능 구현&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;담당을 맡았다..!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;내 주전공은 데이터 사이언스이기는... 하나.. 주로 데이터 분석을 공부하였고, 모델을 만들어본건 랜덤 포레스트 같이 기본적인 알고리즘을 사용한 지도 학습 머신러닝 정도가 학부생 때 지식의 끝이다.. 멘토님께서 나를 너무 전적으로 신뢰하셔서 '이것도 먹어봐' 주셨으니 너무 감사한 일이지만 막막했다. 그러던 중 Ollama 를 발견하였고, 이를 활용해 요구사항을 충족하는데 성공했고 꽤 만족스러운 결과물이 나왔다. 이에 대해 기술한 내용이다.&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;2. 본론&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;p data-ke-size=&quot;size16&quot;&gt;선택지는 4가지가 있었고 &lt;b&gt;2개월 내로 다른 기능들과 같이 구현&lt;/b&gt;하기 위해선 Ollama 가 적합하다고 판단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1. OpenAI 와 같은 AI API 를 사용하여 해석 및 요약시키기. (제일쉬움, but 유료)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2. 항공 전문 해석 AI 찾아서 사용하기. (없거나 회사에서 오픈소스로 공유 안함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3. 생성형 AI 모델을 받아 직접 파인튜닝하기. (지식 및 시간 부족)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;4. Ollama 를 받아 전처리 후 요약 시키고 나온 데이터들을 기반으로 RAG 적용&lt;/b&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;2.1. Ollama 설치&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;a href=&quot;https://ollama.com/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ollama.com/download&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766990438462&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;Download Ollama on macOS&quot; data-og-description=&quot;Download Ollama for macOS&quot; data-og-host=&quot;ollama.com&quot; data-og-source-url=&quot;https://ollama.com/download&quot; data-og-url=&quot;https://ollama.com/download/mac&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/beToUU/hyZQtBfapg/RfTA1eMqx65vrfMI2bv4hK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/CDPPB/hyZQF2JPTV/ayQSc3BlTvTKcnheGVOYAK/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256&quot;&gt;&lt;a href=&quot;https://ollama.com/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ollama.com/download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/beToUU/hyZQtBfapg/RfTA1eMqx65vrfMI2bv4hK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/CDPPB/hyZQF2JPTV/ayQSc3BlTvTKcnheGVOYAK/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256');&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;Download Ollama on macOS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Download Ollama for macOS&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ollama.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;Docker Image 를 받아 컨테이너로 구동시킬 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hub.docker.com/r/ollama/ollama&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hub.docker.com/r/ollama/ollama&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766990516167&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;ollama/ollama - Docker Image&quot; data-og-description=&quot;&quot; data-og-host=&quot;hub.docker.com&quot; data-og-source-url=&quot;https://hub.docker.com/r/ollama/ollama&quot; data-og-url=&quot;https://hub.docker.com/r/ollama/ollama&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://hub.docker.com/r/ollama/ollama&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hub.docker.com/r/ollama/ollama&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;ollama/ollama - Docker Image&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hub.docker.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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.2. Ollama 모델&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ollama.com/library&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ollama.com/library&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766991563046&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;library&quot; data-og-description=&quot;Browse Ollama's library of models.&quot; data-og-host=&quot;ollama.com&quot; data-og-source-url=&quot;https://ollama.com/library&quot; data-og-url=&quot;https://ollama.com/library&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cOLMmt/hyZQx4IuiQ/suqZoDkmZW62esW7g9FuN0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ccoEz1/hyZQJ3P6CA/axXNmVc2VbgmLQ1szEgTBK/img.png?width=4096&amp;amp;height=4096&amp;amp;face=0_0_4096_4096,https://scrap.kakaocdn.net/dn/cp0ho7/hyZQQomipP/SiqEJtoTz37W7zALpaCANK/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256&quot;&gt;&lt;a href=&quot;https://ollama.com/library&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ollama.com/library&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cOLMmt/hyZQx4IuiQ/suqZoDkmZW62esW7g9FuN0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ccoEz1/hyZQJ3P6CA/axXNmVc2VbgmLQ1szEgTBK/img.png?width=4096&amp;amp;height=4096&amp;amp;face=0_0_4096_4096,https://scrap.kakaocdn.net/dn/cp0ho7/hyZQQomipP/SiqEJtoTz37W7zALpaCANK/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256');&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;library&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Browse Ollama's library of models.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ollama.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;Ollama 에 올라와 있는 모델을 Docker 이미지 받는것처럼 받아서 사용하는 형태이다. 모델을 설명하는 상세페이지에 들어가보면 스펙이 기재되어 있는데, 이때 size 는 해당 모델을 구동시키기 위해 최소로 요구하는 &lt;b&gt;RAM&lt;/b&gt; &lt;b&gt;용량&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델을 불러오고 사용하는 방법은 다음과 같다. Docker 사용 명령어와 유사하여 사용하기 편리하다.&lt;/p&gt;
&lt;pre id=&quot;code_1767243000787&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 모델 로컬 저장
ollama pull {모델명}

# 모델 구동
ollama run {모델명}&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;모델을 구동시키면, 우리가 흔히 GUI 로 AI 와 소통하던 모습을 CLI 에서 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1990&quot; data-origin-height=&quot;660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yluBY/dJMcafSNjV4/ENJURerVocfpEY692fWk6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yluBY/dJMcafSNjV4/ENJURerVocfpEY692fWk6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yluBY/dJMcafSNjV4/ENJURerVocfpEY692fWk6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyluBY%2FdJMcafSNjV4%2FENJURerVocfpEY692fWk6K%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;1990&quot; height=&quot;660&quot; data-origin-width=&quot;1990&quot; data-origin-height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zt9on/dJMcacV2uAp/mbACV0uyAAsvpIW18fxGTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zt9on/dJMcacV2uAp/mbACV0uyAAsvpIW18fxGTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zt9on/dJMcacV2uAp/mbACV0uyAAsvpIW18fxGTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZt9on%2FdJMcacV2uAp%2FmbACV0uyAAsvpIW18fxGTk%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;810&quot; height=&quot;230&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 호출 테스트 해본 모델은 총 4개 (phi4, lamma3, lamma4, exaone) 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통적으로 4개 모델 모두 클라우드 모델이 아닌 로컬에 설치된 모델이기 때문에, 답변 속도의 차이와 RAM 점유율의 차이만 있었을 뿐 해석 내용이 원문과 거의 일치하지 않았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1753&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNaBsA/dJMcadABp0J/yoUf7YhaMeUzR1O1BPlt81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNaBsA/dJMcadABp0J/yoUf7YhaMeUzR1O1BPlt81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNaBsA/dJMcadABp0J/yoUf7YhaMeUzR1O1BPlt81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNaBsA%2FdJMcadABp0J%2FyoUf7YhaMeUzR1O1BPlt81%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;1753&quot; height=&quot;793&quot; data-origin-width=&quot;1753&quot; data-origin-height=&quot;793&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;특히 그당시 성능이 좋다던 llama 4 의 경우 RAM 점유율이 높아 64GB 을 사용하는 나의 개발 컴도 원문 하나를 넣으면 답변을 듣는데까지 1분이나 소요됐다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQpP0M/dJMcafSMaul/1zksCPpqBJGyikymnL5gUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQpP0M/dJMcafSMaul/1zksCPpqBJGyikymnL5gUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQpP0M/dJMcafSMaul/1zksCPpqBJGyikymnL5gUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQpP0M%2FdJMcafSMaul%2F1zksCPpqBJGyikymnL5gUk%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;1920&quot; height=&quot;1032&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어짜피 학습이 어렵고, 전처리를 기반으로 한 데이터로 해석하는 걸 요청할 꺼라면 한국어에 특화되고 가벼운 모델을 사용하는것이 적합해 보였다. 그래서 선택한 모델이 &lt;b&gt;exaone3.5&lt;/b&gt; 이다. &lt;span data-teams=&quot;true&quot;&gt;exaone3.5 는&lt;b&gt; LG &lt;/b&gt;에서&lt;b&gt; llama 를 한국어 특화되게 만든&lt;/b&gt; &lt;b&gt;모델&lt;/b&gt;이다. 가동을 위한 &lt;b&gt;최소 메모리도 8GB&lt;/b&gt; 이고, &lt;b&gt;디스크 용량도 4GB&lt;/b&gt; 정도 밖에 소모 되지 않아, 경량 모델이다. 해당 요구사항을 충족하기엔 충분한 스펙이라고 생각하였고 어짜피 추후에 RAG Vector DB 를 도입할 예정이라 이 모델을 선택하게 되었다.&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 data-teams=&quot;true&quot;&gt;2.3. LLM 엔진 메모리 관리 전략 + 캐싱 메커니즘&lt;/span&gt;&lt;span data-teams=&quot;true&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-teams=&quot;true&quot;&gt;호출 테스트 해보다가 특이한 점을 발견했다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tYsIj/dJMcabpiedp/9S3lMJEjfdcBNkQdQTmOKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tYsIj/dJMcabpiedp/9S3lMJEjfdcBNkQdQTmOKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tYsIj/dJMcabpiedp/9S3lMJEjfdcBNkQdQTmOKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtYsIj%2FdJMcabpiedp%2F9S3lMJEjfdcBNkQdQTmOKK%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;851&quot; height=&quot;240&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;240&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;docker image 로 띄운 ollama container 로그를 찍어보면 응답을 하는데까지 걸린 시간들을 표출해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교적 길게 소요된 응답은 '첫번째 호출' 이고 비교적 짧게 소요된 응답은 'n번째 호출' 이다. 즉, 여러번 호출할 수록 응답 속도가 빨라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;가장 처음 실행할 때 시간이 오래 걸리는 이유는 &lt;b data-index-in-node=&quot;27&quot; data-path-to-node=&quot;4&quot;&gt;모델 가중치(Weights)를 디스크에서 RAM으로 올리는 과정&lt;/b&gt; 때문이다. 처음 호출하게 되면 다음과 같은 과정을 거치게 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Ollama는 사용자의 요청이 들어오면 비로소 ~/.ollama/models에 있는 수 GB의 GGUF 파일 (모델의 수십억 개 파라미터가 저장되는 공간) 을 읽는다.&lt;/li&gt;
&lt;li&gt;GGUF 파일 (전체 모델 데이터) 를 &lt;b&gt;RAM에 상주&lt;/b&gt;시킨다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매번 호출때마다 Disk 에서 가져오면 속도가 너무 느림.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;신경망 그래프를 구성(이전 대화 및 프롬프트 기억 공간 미리 RAM 확보).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n번째 호출에선 신경망 그래프 구성 중 생성된 &lt;b&gt;KV Cache&lt;/b&gt; (이전 대화 및 프롬프트 기억 공간) 와 앞선 &lt;b&gt;RAM&lt;/b&gt; &lt;b&gt;할당&lt;/b&gt;으로 인해 응답 식속도가 현저히 줄게 되는 것이다. 다만, 항상 RAM 에 할당 해두면 리소스를 너무 많이 먹기 때문에 &lt;b&gt;5분 동안만 &lt;/b&gt;RAM 에 할당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 실제 운영 또는 사용 시 리소스 여유가 있다면 항상 상주하게 하거나, polling 방식으로 RAM 에 불러와야 한다.&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;3. 참고자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ollama: &lt;a href=&quot;https://ollama.com/library&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ollama.com/library&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ollama 메모리 관리 전략: &lt;a href=&quot;https://ollama.com/blog/multimodal-models&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ollama.com/blog/multimodal-models&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/ai</category>
      <category>exaone3.5</category>
      <category>ollama</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/19</guid>
      <comments>https://hand-mk.tistory.com/19#entry19comment</comments>
      <pubDate>Mon, 29 Dec 2025 17:26:19 +0900</pubDate>
    </item>
    <item>
      <title>[Python] KoNLPy 자연어 형태소 분석</title>
      <link>https://hand-mk.tistory.com/18</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* Python: v3.13&amp;nbsp;&lt;br /&gt;* 개발 환경 OS: Windows 11 Pro&lt;br /&gt;* 운영 환경 OS: CentOS 7&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;245&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efCv7p/dJMcaa4ZpVl/FdMrNGuXdkaYsWGOcF04P0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efCv7p/dJMcaa4ZpVl/FdMrNGuXdkaYsWGOcF04P0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efCv7p/dJMcaa4ZpVl/FdMrNGuXdkaYsWGOcF04P0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefCv7p%2FdJMcaa4ZpVl%2FFdMrNGuXdkaYsWGOcF04P0%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;633&quot; height=&quot;245&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;245&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;회사 백오피스 서비스 개발에서 뉴스기사 크롤링 모듈 개발을 담당 하였다. 이와 연관지어 대시보드 페이지에 수집한 기사들의 &lt;b&gt;키워드&lt;/b&gt;를 &lt;b&gt;워드클라우드&lt;/b&gt;로 표출해야 하는 요구사항이 있다. 요구사항을 충족하기 위해선 뉴스 기사의 단어 빈도수를 분석하고 빈도수 기준 워드클라우드를 표출해야 한다. 자연어 문장에서 &lt;b&gt;단어를 추출하는 로직을 직접 구현하는 것은 생각보다 복잡한 일&lt;/b&gt;이다. 한국어의 모든 조사, 부사 등을 갖고 있어야 하고 문장의 모든 배치 케이스를 적용해야 한다. 하지만 Python 에는 이를 직접 구현하지 않고 단어만 이쁘게 추출해주는 패키지 &lt;b&gt;KoNLPy&lt;/b&gt; 가 존재한다. 이에 대해 기술한 내용이다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 본론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #3e4349; text-align: start;&quot;&gt;KoNLPy는 한국어 정보처리를 위한 파이썬 패키지이다. 해당 패키지를 통해 한국어 자연어 문장에서 문장 또는 단어를 추출할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #3e4349; text-align: start;&quot;&gt;다음은 공식문서의 예시이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766974429165&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from konlpy.tag import Kkma
&amp;gt;&amp;gt;&amp;gt; from konlpy.utils import pprint
&amp;gt;&amp;gt;&amp;gt; kkma = Kkma()
&amp;gt;&amp;gt;&amp;gt; pprint(kkma.sentences(u'네, 안녕하세요. 반갑습니다.'))
[네, 안녕하세요..,
 반갑습니다.]
&amp;gt;&amp;gt;&amp;gt; pprint(kkma.nouns(u'질문이나 건의사항은 깃헙 이슈 트래커에 남겨주세요.'))
[질문,
 건의,
 건의사항,
 사항,
 깃헙,
 이슈,
 트래커]
&amp;gt;&amp;gt;&amp;gt; pprint(kkma.pos(u'오류보고는 실행환경, 에러메세지와함께 설명을 최대한상세히!^^'))
[(오류, NNG),
 (보고, NNG),
 (는, JX),
 (실행, NNG),
 (환경, NNG),
 (,, SP),
 (에러, NNG),
 (메세지, NNG),
 (와, JKM),
 (함께, MAG),
 (설명, NNG),
 (을, JKO),
 (최대한, NNG),
 (상세히, MAG),
 (!, SF),
 (^^, EMO)]&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;2.1. 패키지 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 개발환경 OS 는 Windows 11 pro, 운영환경 OS 는 CentOS 7 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서에 기재되어 있다시피, Windows 환경에서는 로컬에 JDK 1.7 이상이 설치되어 있어야 한다. &lt;b&gt;KoNLPy&lt;/b&gt;는 독자적인 형태소 분석 &lt;b&gt;알고리즘을 파이썬으로 직접 구현한 것이 아니다&lt;/b&gt;. 이미 &lt;b&gt;Java &lt;/b&gt;로 &lt;b&gt;아주 잘 만들어진 기존의 형태소 분석기&lt;/b&gt;들을 파이썬에서 편하게 쓸 수 있도록 묶어 놓은 &lt;b&gt;Wrapper&lt;/b&gt; 라이브러리 이다. 즉, KoNLPy 를 &lt;b&gt;구동&lt;/b&gt;시키려면&lt;b&gt; JVM 이 있어야 한다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.1.1. JDK 설치 및 환경변수 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 Oracle jdk 17 을 설치하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766975017360&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Java Archive Downloads - Java SE 17.0.12 and earlier&quot; data-og-description=&quot;WARNING: Older versions of the JDK are provided to help developers debug issues in older systems. They are not updated with the latest security patches and are not recommended for use in production. For production use Oracle recommends downloading the late&quot; data-og-host=&quot;www.oracle.com&quot; data-og-source-url=&quot;https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html&quot; data-og-url=&quot;https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java Archive Downloads - Java SE 17.0.12 and earlier&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;WARNING: Older versions of the JDK are provided to help developers debug issues in older systems. They are not updated with the latest security patches and are not recommended for use in production. For production use Oracle recommends downloading the late&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 JDK 를 직접 설치 해야 하는 경우는 Windows 환경에서만 적용되기 때문에, 밑에 &lt;b&gt;Windows x64 Installer&amp;nbsp;&lt;/b&gt;를 다운 받는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sOSxE/dJMcacuYwgS/yIsXAuh5r0jla0RH2L0dtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sOSxE/dJMcacuYwgS/yIsXAuh5r0jla0RH2L0dtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sOSxE/dJMcacuYwgS/yIsXAuh5r0jla0RH2L0dtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsOSxE%2FdJMcacuYwgS%2FyIsXAuh5r0jla0RH2L0dtk%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;995&quot; height=&quot;416&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;416&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;해당 exe 파일을 실행시켜 jdk 를 설치한다. 설치 중 설치 경로를 변경 할 수 있지만 보통 &quot;C:\Program Files\&quot; 에 설치한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CtkvH/dJMcaiopBEC/ypSiwbuzH1x1hnwQnuAb0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CtkvH/dJMcaiopBEC/ypSiwbuzH1x1hnwQnuAb0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CtkvH/dJMcaiopBEC/ypSiwbuzH1x1hnwQnuAb0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCtkvH%2FdJMcaiopBEC%2FypSiwbuzH1x1hnwQnuAb0k%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;774&quot; height=&quot;47&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;47&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 jdk 환경 변수를 지정해야 한다. windows 검색 &amp;gt; 시스템 환경 변수 편집 을 연다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WQjG9/dJMcachq6yt/mbOkkFBXYS90ZVgY7Ner1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WQjG9/dJMcachq6yt/mbOkkFBXYS90ZVgY7Ner1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WQjG9/dJMcachq6yt/mbOkkFBXYS90ZVgY7Ner1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWQjG9%2FdJMcachq6yt%2FmbOkkFBXYS90ZVgY7Ner1K%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;307&quot; height=&quot;274&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 속성 &amp;gt; 고급 탭 &amp;gt; 하단 환경변수 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bM37Ou/dJMcagqBfAQ/lZB0GwZPW1XBHnhICdWg4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bM37Ou/dJMcagqBfAQ/lZB0GwZPW1XBHnhICdWg4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bM37Ou/dJMcagqBfAQ/lZB0GwZPW1XBHnhICdWg4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbM37Ou%2FdJMcagqBfAQ%2FlZB0GwZPW1XBHnhICdWg4k%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;479&quot; height=&quot;533&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;533&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKO0LX/dJMcaiPrL7P/eXPKuy0DlwbxYYqJywe2HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKO0LX/dJMcaiPrL7P/eXPKuy0DlwbxYYqJywe2HK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKO0LX/dJMcaiPrL7P/eXPKuy0DlwbxYYqJywe2HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKO0LX%2FdJMcaiPrL7P%2FeXPKuy0DlwbxYYqJywe2HK%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;618&quot; height=&quot;585&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA_HOME 변수에 변수 값은 실제 다운받은 jdk 경로를 기입해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtMCDv/dJMcaihEUJP/KxBG5XYqkvOoUUDeyCLAqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtMCDv/dJMcaihEUJP/KxBG5XYqkvOoUUDeyCLAqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtMCDv/dJMcaihEUJP/KxBG5XYqkvOoUUDeyCLAqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdtMCDv%2FdJMcaihEUJP%2FKxBG5XYqkvOoUUDeyCLAqK%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;653&quot; height=&quot;165&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;165&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 시스템 변수 중 &lt;b&gt;Path&amp;nbsp;&lt;/b&gt;를 찾아 편집 버튼을 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdUDK3/dJMcagKUWGh/SrXKTq7RTBFOskafITx4SK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdUDK3/dJMcagKUWGh/SrXKTq7RTBFOskafITx4SK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdUDK3/dJMcagKUWGh/SrXKTq7RTBFOskafITx4SK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdUDK3%2FdJMcagKUWGh%2FSrXKTq7RTBFOskafITx4SK%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;618&quot; height=&quot;585&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;585&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA32wU/dJMcaihEUKY/FF8iMGSp3B6ixhCeu9vY91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA32wU/dJMcaihEUKY/FF8iMGSp3B6ixhCeu9vY91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA32wU/dJMcaihEUKY/FF8iMGSp3B6ixhCeu9vY91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA32wU%2FdJMcaihEUKY%2FFF8iMGSp3B6ixhCeu9vY91%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;527&quot; height=&quot;501&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;501&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;이후 제대로 적용 됐는지 확인을 위해 cmd 에서 java version 을 찍어본다. 정상적으로 출력되면 문제없다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/slJKS/dJMcabixss0/JrYWbkjxNxESQ9nizV6ey1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/slJKS/dJMcabixss0/JrYWbkjxNxESQ9nizV6ey1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/slJKS/dJMcabixss0/JrYWbkjxNxESQ9nizV6ey1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FslJKS%2FdJMcabixss0%2FJrYWbkjxNxESQ9nizV6ey1%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;748&quot; height=&quot;98&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;98&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;만약 Python 프로젝트 실행시 다음과 같은 에러 문구가 발생하면 java 환경변수를 잘못 지정했거나, 적용이 안된것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #282a2c; color: #e3e3e3; text-align: start;&quot;&gt;jpype._jvmfinder.JVMNotFoundException: No JVM shared library file (jvm.dll) found. Try setting up the JAVA_HOME environment variable properly.&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;환경 변수 지정 후 IDE 를 껐다 키거나, 시스템 재부팅 하여 변경사항을 적용해야 정상적으로 작동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.1.2. jpype 설치&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 기술했던 것처럼 KoNLPy 는 JVM 을 기반으로 구동된다. 그렇기 때문에 &lt;b&gt;Python 에서 JVM 이 동작할 수 있게끔&lt;/b&gt; 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 가능하게 해주는 것이 &lt;b&gt;jpype&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;Jpype는 Python 프로세스 내에 JVM(Java Virtual Machine)을 임베딩하여 파이썬이 자바 라이브러리를 직접 호출할 수 있게 해주는 Bridge 역할의 라이브러리이다. 실제로 KoNLPy 에서도 설치를 권장하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;583&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mvV0F/dJMcabCPe0W/aV0ZWU3cfDfZxuNODkuXrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mvV0F/dJMcabCPe0W/aV0ZWU3cfDfZxuNODkuXrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mvV0F/dJMcabCPe0W/aV0ZWU3cfDfZxuNODkuXrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmvV0F%2FdJMcabCPe0W%2FaV0ZWU3cfDfZxuNODkuXrk%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;1080&quot; height=&quot;583&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;583&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;명령어를 통해 JPype 를 설치 할 수도 있으나, 간혹 Windows 환경에서 실패하는 경우가 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1766982998695&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install JPype1&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;실패하는 경우 직접 릴리즈 패키징 파일을 github 에서 다운받을 수도 있다.&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://github.com/cgohlke/win_arm64-wheels/releases/tag/v2025.7.7&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/cgohlke/win_arm64-wheels/releases/tag/v2025.7.7&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766983063522&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;Release v2025.7.7 &amp;middot; cgohlke/win_arm64-wheels&quot; data-og-description=&quot;Experimental Wheels for Python for Windows on ARM64 Notes 140 packages for Python 3.13 for Windows on ARM64 Updates the v2025.3.31 release Wheels Binary wheels for the following packages for Pyth...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/cgohlke/win_arm64-wheels/releases/tag/v2025.7.7&quot; data-og-url=&quot;https://github.com/cgohlke/win_arm64-wheels/releases/tag/v2025.7.7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lDJDJ/hyZPLvqw7w/kxMFsXqrnR9jrpxh4ZnTa0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bdPlp3/hyZQDDMh2k/kgLBybI35iFxoSckQLRpdk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/cgohlke/win_arm64-wheels/releases/tag/v2025.7.7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/cgohlke/win_arm64-wheels/releases/tag/v2025.7.7&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lDJDJ/hyZPLvqw7w/kxMFsXqrnR9jrpxh4ZnTa0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bdPlp3/hyZQDDMh2k/kgLBybI35iFxoSckQLRpdk/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;Release v2025.7.7 &amp;middot; cgohlke/win_arm64-wheels&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Experimental Wheels for Python for Windows on ARM64 Notes 140 packages for Python 3.13 for Windows on ARM64 Updates the v2025.3.31 release Wheels Binary wheels for the following packages for Pyth...&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;필자의 경우 Python v3.13 을 사용하기 때문에, &lt;b&gt;jpype1-1.5.2-cp313-cp313-win_amd64&lt;/b&gt; 을 다운받았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2430&quot; data-origin-height=&quot;1652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mKHk7/dJMcai2Ynuh/iyFIdNXXkuIYgcTwR4KbeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mKHk7/dJMcai2Ynuh/iyFIdNXXkuIYgcTwR4KbeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mKHk7/dJMcai2Ynuh/iyFIdNXXkuIYgcTwR4KbeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmKHk7%2FdJMcai2Ynuh%2FiyFIdNXXkuIYgcTwR4KbeK%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;2430&quot; height=&quot;1652&quot; data-origin-width=&quot;2430&quot; data-origin-height=&quot;1652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TIKQz/dJMcahpwSYZ/Uqfnpc5mA1ooTCMsmrwTP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TIKQz/dJMcahpwSYZ/Uqfnpc5mA1ooTCMsmrwTP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TIKQz/dJMcahpwSYZ/Uqfnpc5mA1ooTCMsmrwTP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTIKQz%2FdJMcahpwSYZ%2FUqfnpc5mA1ooTCMsmrwTP1%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;799&quot; height=&quot;431&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;431&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;로컬에 해당 파일을 직접 다운받았다고 하면 꼭 pip 로 설치과정이 필요하다.&lt;/p&gt;
&lt;pre id=&quot;code_1766983561063&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install jpype1-1.5.2-cp313-cp313-win_amd64.whl&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;이제 KoNLPy 를 사용할 사전 준비가 끝났다.&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.2. 모듈 선택&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일전에 기술했다시피, KoNLPy 은 여러 형태소 분석기(Hannanum, Kkma, Komoran, Mecab, Okt) 들을 한데 모아둔 패키지이다.&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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dofOFw/dJMcabQmAEb/VSfQ95q2K8e5ba3lr18bXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dofOFw/dJMcabQmAEb/VSfQ95q2K8e5ba3lr18bXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dofOFw/dJMcabQmAEb/VSfQ95q2K8e5ba3lr18bXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdofOFw%2FdJMcabQmAEb%2FVSfQ95q2K8e5ba3lr18bXK%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;698&quot; height=&quot;402&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bI0IHk/dJMcabQmADQ/VKoKkTUa9z8h0e8wfDRkuk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bI0IHk/dJMcabQmADQ/VKoKkTUa9z8h0e8wfDRkuk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bI0IHk/dJMcabQmADQ/VKoKkTUa9z8h0e8wfDRkuk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbI0IHk%2FdJMcabQmADQ%2FVKoKkTUa9z8h0e8wfDRkuk%2Fimg.webp&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;1072&quot; height=&quot;836&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속도로만 봤을 때, Mecab 이 좀 더 성능이 좋아보이긴 하나, 자연어에 대한 형태소 분석 정확도에선 Okt 가 더 좋아보였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;1478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceOPm2/dJMcaiWd7G4/wTg7dXtwh8rNm9BiLbFy3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceOPm2/dJMcaiWd7G4/wTg7dXtwh8rNm9BiLbFy3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceOPm2/dJMcaiWd7G4/wTg7dXtwh8rNm9BiLbFy3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceOPm2%2FdJMcaiWd7G4%2FwTg7dXtwh8rNm9BiLbFy3K%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;1480&quot; height=&quot;1478&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;1478&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;이러한 이유로 필자는 Okt 를 사용하였다.&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.3. 사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KoNLPy 공문서에서 친절하게 워드 클라우드에 대한 예제도 있어 어렵지 않게 구현이 가능하다.&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://konlpy.org/ko/latest/examples/wordcloud/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://konlpy.org/ko/latest/examples/wordcloud/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제에선 Hannanum 을 사용하였으나, 필자의 Okt 로 인스턴스를 생성하면 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1766984699460&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 인스턴스 생성
okt = Okt()&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;명사를 추출하고 싶을 때 nouns 함수를 호출하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1766984834087&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 명사만 추출
noun_results = okt.nouns(contents)&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;명사만 추출함에도 불구하고 길이 1짜리 조사들이나, 불용 목록으로 기재되지 않아 걸러지지 않는 단어들이 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1766985199181&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;곳
며
점
선
더
층
내
칼
위
명
개&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 data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766985284546&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;Korean Stopwords&quot; data-og-description=&quot;Korean Stopwords. GitHub Gist: instantly share code, notes, and snippets.&quot; data-og-host=&quot;gist.github.com&quot; data-og-source-url=&quot;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&quot; data-og-url=&quot;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/brKYyA/hyZQEQftc0/XTfd1Uo0XkVLnSARBMEik0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/tfjNO/hyZPEb0fd8/jpeZ6JGvflp566CZRDcIU1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/brKYyA/hyZQEQftc0/XTfd1Uo0XkVLnSARBMEik0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/tfjNO/hyZPEb0fd8/jpeZ6JGvflp566CZRDcIU1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&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;Korean Stopwords&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Korean Stopwords. GitHub Gist: instantly share code, notes, and snippets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;gist.github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1766985308572&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; # 불용어 및 길이 1개인 조사 제거
final_results = [n for n in noun_results if n not in STOPWORDS and len(n) &amp;gt; 1]&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;결국 단어의 빈도수를 구하고, chart js 의 워드클라우드를 생성하기 위해선 {key: value} 형태로 데이터를 던져줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불용어 처리까지 끝난 단어 리스트에 Pandas 라이브러리를 사용하여 한 단어당 빈도수를 구하고 상위 100개만 추출하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1766985468454&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;words_frequency = pd.Series(final_results).value_counts().head(100)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RiE0N/dJMcaihEXl1/ra50JxA3wdIgIcsP6DtRgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RiE0N/dJMcaihEXl1/ra50JxA3wdIgIcsP6DtRgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RiE0N/dJMcaihEXl1/ra50JxA3wdIgIcsP6DtRgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRiE0N%2FdJMcaihEXl1%2Fra50JxA3wdIgIcsP6DtRgK%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;367&quot; height=&quot;684&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;684&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;형태소 빈도수 분석 결과 값을 그대로 chart js 워드클라우드를 사용하여 띄우면 다음과 같이 표출된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2674&quot; data-origin-height=&quot;638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l4TrK/dJMcahJPgXt/TZw6jYGNvhVYsRhwfxksyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l4TrK/dJMcahJPgXt/TZw6jYGNvhVYsRhwfxksyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l4TrK/dJMcahJPgXt/TZw6jYGNvhVYsRhwfxksyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl4TrK%2FdJMcahJPgXt%2FTZw6jYGNvhVYsRhwfxksyk%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;2674&quot; height=&quot;638&quot; data-origin-width=&quot;2674&quot; data-origin-height=&quot;638&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;h2 data-ke-size=&quot;size26&quot;&gt;3. 참고자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KoNLPy: &lt;a href=&quot;https://konlpy.org/ko/latest/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://konlpy.org/ko/latest/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 환경변수: &lt;a href=&quot;https://languagestory.tistory.com/11&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://languagestory.tistory.com/11&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불용어 리스트: &lt;a href=&quot;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;chat js 워드클라우드: &lt;a href=&quot;https://www.sgratzl.com/chartjs-chart-wordcloud/examples/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.sgratzl.com/chartjs-chart-wordcloud/examples/&lt;/a&gt;&lt;/p&gt;</description>
      <category>dev/backend</category>
      <category>KoNLPy</category>
      <category>워드클라우드</category>
      <category>자연어 처리</category>
      <author>hand-mk</author>
      <guid isPermaLink="true">https://hand-mk.tistory.com/18</guid>
      <comments>https://hand-mk.tistory.com/18#entry18comment</comments>
      <pubDate>Mon, 29 Dec 2025 14:38:11 +0900</pubDate>
    </item>
  </channel>
</rss>