<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>yulee</title>
    <link>https://yulee.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 21 Jul 2026 02:46:15 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>yulee_to</managingEditor>
    <image>
      <title>yulee</title>
      <url>https://tistory1.daumcdn.net/tistory/4900437/attach/8c721157838a4c00b0aeec64746be855</url>
      <link>https://yulee.tistory.com</link>
    </image>
    <item>
      <title>[Claude Code] harness vs 순수 Claude Code: macOS Dynamic Island 앱을 만들기</title>
      <link>https://yulee.tistory.com/192</link>
      <description>&lt;blockquote style=&quot;background-color: #ffffff; color: #777777; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Claude Code의 harness(에이전트 팀 구조)가 순수 Claude Code 대화보다 실제로 얼마나 빠르고 좋은 결과를 낼까? &lt;br /&gt;직접 실험해봤다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;실험 배경&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Claude Code를 쓰다 보니 자연스럽게 생기는 의문이 있었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #777777; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&quot;harness(CLAUDE.md + 에이전트 팀 + 스킬)를 미리 잘 설계해두면 진짜 더 잘 만들어줄까? 아니면 그냥 프롬프트 한 방이 낫나?&quot;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 질문에 답하기 위해 동일한 앱을 두 가지 방식으로 동시에 만들어보는 실험을 설계했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;마침 만들고 싶었던 앱이 있어서 같은 앱을 어떻게 만들어내는지 비교하고자 했다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;harness Github 주소: &lt;a href=&quot;https://github.com/revfactory/harness&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/revfactory/harness&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1779957389330&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 - revfactory/harness: A meta-skill that designs domain-specific agent teams, defines specialized agents, and generates th&quot; data-og-description=&quot;A meta-skill that designs domain-specific agent teams, defines specialized agents, and generates the skills they use. - revfactory/harness&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/revfactory/harness&quot; data-og-url=&quot;https://github.com/revfactory/harness&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/RZGcd/dJMb8PGCOLK/feO1m6KOXFA4RsXo1B4LlK/img.png?width=1200&amp;amp;height=600&amp;amp;face=980_116_1038_179,https://scrap.kakaocdn.net/dn/cy75mQ/dJMb8ZvH6Y0/9WmdWkzWHf41Qj1xgdKNx1/img.png?width=1200&amp;amp;height=600&amp;amp;face=980_116_1038_179,https://scrap.kakaocdn.net/dn/ebwueI/dJMb83kzEDq/aKYCeEPI7qeTZk2ycMkShk/img.jpg?width=2752&amp;amp;height=1536&amp;amp;face=0_0_2752_1536&quot;&gt;&lt;a href=&quot;https://github.com/revfactory/harness&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/revfactory/harness&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/RZGcd/dJMb8PGCOLK/feO1m6KOXFA4RsXo1B4LlK/img.png?width=1200&amp;amp;height=600&amp;amp;face=980_116_1038_179,https://scrap.kakaocdn.net/dn/cy75mQ/dJMb8ZvH6Y0/9WmdWkzWHf41Qj1xgdKNx1/img.png?width=1200&amp;amp;height=600&amp;amp;face=980_116_1038_179,https://scrap.kakaocdn.net/dn/ebwueI/dJMb83kzEDq/aKYCeEPI7qeTZk2ycMkShk/img.jpg?width=2752&amp;amp;height=1536&amp;amp;face=0_0_2752_1536');&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 - revfactory/harness: A meta-skill that designs domain-specific agent teams, defines specialized agents, and generates th&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A meta-skill that designs domain-specific agent teams, defines specialized agents, and generates the skills they use. - revfactory/harness&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;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;만들려고 한 것&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;macOS 노치 위에 Dynamic Island 스타일 AI 상태 오버레이&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #333333; text-align: start;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;노치 위에 검정색 NSWindow&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Claude 활성 시 compact 인디케이터 상시 표시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;마우스 호버 &amp;rarr; spring 애니메이션으로 확장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;마우스 이탈 &amp;rarr; 자동 축소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;확장 시 Claude 사용량(%), 티어(MAX/PRO), 새로고침 버튼 표시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Claude뿐 아니라 Codex, Cursor 등 다양한 AI Provider를 추가할 수 있는 플러그인 구조&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;마일스톤은 M1(빌드 성공)부터 M7(MockCodexProvider로 확장성 검증)까지 7단계로 정의했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;두 가지 접근 방식&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;vanilla&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #333333; text-align: start;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;순수 Claude Code CLI (&lt;/span&gt;&lt;span&gt;claude --dangerously-skip-permissions&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CLAUDE.md 없음, 에이전트 정의 없음, 스킬 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;빈 SPM 프로젝트에서 시작&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;revfactory (harness)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #333333; text-align: start;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;CLAUDE.md에 7개 에이전트 팀 사전 정의&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;notch-orchestrator&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;swift-architect&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;plugin-engineer&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;animation-engineer&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ui-composer&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;system-integrator&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;qa-verifier&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;6개 도메인별 스킬 파일 (&lt;/span&gt;&lt;span&gt;build-run&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;plugin-scaffold&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;animation-design&lt;/span&gt;&lt;span&gt; 등)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;동일한 SPM 구조에서 시작 (스캐폴드 포함)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;두 세션을 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;동시에&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 실행해서 총 소요 시간을 실시간으로 비교했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;결과&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;타임라인 비교&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;text-align: left; border-collapse: collapse; width: 100%; height: 114px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;이벤트&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;vanilla&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;revfactory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;세션 시작&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;15:59:30&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;15:59:34&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f8f8; height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;M1 첫 빌드 성공&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;16:09:23 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;(+9분 53초)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;15:59:49 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;(+15초)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;M2~M7 전부 달성&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;16:25:58&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;16:07:55&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f8f8; height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;육안 확인 완료&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;16:25:58&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;16:27:56&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;총 소요 시간&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;26분 28초&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;28분 22초&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;revfactory는 &lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;기존 스캐폴드 코드 덕분에&amp;nbsp;&lt;/span&gt;첫 빌드를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;15초&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 만에 성공했다. 반면 vanilla는 약 10분이 걸렸다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 결승선을 통과한 건 vanilla가 먼저였다. 육안 확인까지 포함하면 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;총 시간 차이는 2분도 안 된다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;코드 규모&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;text-align: left; border-collapse: collapse; width: 100%; height: 95px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;vanilla&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;revfactory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;총 LOC&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;293줄&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;1,272줄&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f8f8; height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;Swift 파일 수&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;7개&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;20개&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;빌드 에러&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;2건&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;1건&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f8f8; height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;구현 중 버그 수정&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;2건&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;4건&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;에이전트 팀이 역할별로 파일을 분리하고 프로토콜&amp;middot;레이어를 추가해서 revfactory가 4.3배 더 많은 코드를 생성했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;버그 내역&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;vanilla (빌드 에러 2건)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;text-align: left; border-collapse: collapse; width: 100%; height: 57px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;회차&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;원인&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;해결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;#1&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;Swift 6 concurrency &amp;mdash; &lt;/span&gt;&lt;span&gt;any AIProvider&lt;/span&gt;&lt;span&gt;가 non-Sendable로 Task 클로저에 전달 불가&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;AIProvider&lt;/span&gt;&lt;span&gt;에 &lt;/span&gt;&lt;span&gt;@MainActor&lt;/span&gt;&lt;span&gt; 추가&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f8f8; height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;#2&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;Info.plist&lt;/span&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;.copy&lt;/span&gt;&lt;span&gt; 리소스로 등록 시 SPM이 거부&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;.exclude&lt;/span&gt;&lt;span&gt;로 전환&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;revfactory (구현 중 버그 4건)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;AnimationStateMachine&lt;/span&gt;&lt;span&gt; 알림 미발송 &amp;rarr; &lt;/span&gt;&lt;span&gt;$overlaySize.sink&lt;/span&gt;&lt;span&gt; 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;NSWindowController cascade 덮어쓰기 &amp;rarr; &lt;/span&gt;&lt;span&gt;shouldCascadeWindows = false&lt;/span&gt;&lt;span&gt; + 지연 재배치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;NSHostingView 불투명 배경 &amp;rarr; &lt;/span&gt;&lt;span&gt;wantsLayer = true&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;layer.backgroundColor = .clear&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;compact view usage 변경 미반영 &amp;rarr; &lt;/span&gt;&lt;span&gt;@ObservedObject&lt;/span&gt;&lt;span&gt; 래퍼 추가&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;최종 결과물 비교&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;vanilla&lt;/span&gt;&lt;/b&gt;&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/PpHce/dJMcadoznB2/XOIYduu4TwTlM7T6bQAWg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PpHce/dJMcadoznB2/XOIYduu4TwTlM7T6bQAWg0/img.png&quot; data-origin-width=&quot;930&quot; data-origin-height=&quot;306&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.612%; margin-right: 10px;&quot; data-widthpercent=&quot;52.22&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PpHce/dJMcadoznB2/XOIYduu4TwTlM7T6bQAWg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPpHce%2FdJMcadoznB2%2FXOIYduu4TwTlM7T6bQAWg0%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;930&quot; height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsOXyB/dJMcacXzcAk/Skt7RXsmAHnH2Iyv5hlCV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsOXyB/dJMcacXzcAk/Skt7RXsmAHnH2Iyv5hlCV0/img.png&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;356&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.2252%;&quot; data-widthpercent=&quot;47.78&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsOXyB/dJMcacXzcAk/Skt7RXsmAHnH2Iyv5hlCV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsOXyB%2FdJMcacXzcAk%2FSkt7RXsmAHnH2Iyv5hlCV0%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;990&quot; height=&quot;356&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #333333; text-align: start;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;창 형태: 전체 너비 검정 바 (pill 미구현)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;compact 상태: 흰 점 인디케이터&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;확장 UI: Usage/Tier/Window/새로고침 버튼 &amp;mdash; &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;실제 Claude 데이터 연동&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기능 완성도: 높음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시각 디자인: 다소 아쉬움&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;revfactory&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKbTN5/dJMb99NgSEj/3OnFidqJfgMTpiAvU42Z70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKbTN5/dJMb99NgSEj/3OnFidqJfgMTpiAvU42Z70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKbTN5/dJMb99NgSEj/3OnFidqJfgMTpiAvU42Z70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKbTN5%2FdJMb99NgSEj%2F3OnFidqJfgMTpiAvU42Z70%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;505&quot; height=&quot;168&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #333333; text-align: start;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;창 형태: &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;완벽한 pill 형태&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; (Dynamic Island처럼 둥근 모양)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;compact 상태: 오렌지 점 + &lt;/span&gt;&lt;span&gt;73%&lt;/span&gt;&lt;span&gt; 사용량 표시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;확장 UI: 구현됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시각 디자인: 높음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기능 완성도: 낮음(창 위치와 마우스 호버시 확장되는 윈도우 깨짐)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;분석&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;harness가 빠른 건 맞다 &amp;mdash; 단, 초반에만&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;revfactory의 첫 빌드 15초는 인상적이다. 하지만 그건 스캐폴드가 이미 존재했기 때문이고, 이후 4건의 버그 수정이 그 시간을 잡아먹었다. 총합이 거의 같아진 이유이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;많은 코드 &amp;ne; 좋은 코드&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;revfactory는 293줄짜리 문제를 1,272줄로 풀었다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;에이전트 팀이 역할을 분리하고 추상화 레이어를 추가한 결과다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이게 좋은 설계일 수도 있지만, 단기 실험 기준으론 오버엔지니어링이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;각자 잘하는 게 달랐다&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #333333; text-align: start;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;revfactory &amp;rarr; UI/UX 형태 (pill 디자인, 컬러 인디케이터)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;vanilla &amp;rarr; 실제 기능 연동 (Claude API 데이터 끌어오기)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;harness가 UI 컴포넌트 설계에 더 집중하고, vanilla는 &quot;어쨌든 동작하게&quot; 만드는 방향으로 수렴한 것 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;table style=&quot;text-align: left; border-collapse: collapse; width: 100%; height: 95px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;상황&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;추천 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;빠르게 PoC 만들기&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;vanilla&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f8f8; height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;팀 규모 확장, 장기 프로젝트&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;revfactory (harness)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;반복 작업, 패턴이 명확한 도메인&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;revfactory (스킬 재사용 효과)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f8f8; height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;기능 연동, 데이터 파이프라인&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span&gt;&lt;span&gt;vanilla&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;harness의 진짜 가치는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;속도&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;보다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;재사용성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 있는 것 같다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번처럼 단발성 실험에서는 vanilla와 큰 차이가 없지만, 동일한 스킬과 에이전트 정의를 여러 프로젝트에 반복 적용하면 누적 이득이 커질 수 있지 않을까 예상한다.&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>Develop/기타</category>
      <category>Claude</category>
      <category>claudecode</category>
      <category>HARNESS</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/192</guid>
      <comments>https://yulee.tistory.com/192#entry192comment</comments>
      <pubDate>Thu, 28 May 2026 17:45:44 +0900</pubDate>
    </item>
    <item>
      <title>[Claude Code] AI와 함께 macOS 알림 배너 툴 만들기 &amp;mdash; 실패와 재시도에서 배운 것들</title>
      <link>https://yulee.tistory.com/188</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-27 오후 2.25.51.png&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l0wCS/dJMcabRP0Be/Kg2ZuMXdMk7mjyKwaJFbkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l0wCS/dJMcabRP0Be/Kg2ZuMXdMk7mjyKwaJFbkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l0wCS/dJMcabRP0Be/Kg2ZuMXdMk7mjyKwaJFbkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl0wCS%2FdJMcabRP0Be%2FKg2ZuMXdMk7mjyKwaJFbkk%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;856&quot; data-filename=&quot;스크린샷 2026-05-27 오후 2.25.51.png&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;856&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;Claude Code를 쓰다 보면 긴 작업을 돌려놓고 다른 일을 하다가, 작업이 끝났는지 확인하려고 계속 터미널로 눈길을 보내게 된다. 권한 요청이나 질문이 생겼을 때 눈치채지 못하면 한참이 지나서야 &quot;아, Claude가 기다리고 있었구나&quot; 하는 상황이 반복됐다. 그래서 직접 만들어보기로 했다. 작업 완료, 질문, 권한 요청을 macOS 화면 우측 상단 배너로 실시간 알려주는 툴이다. 만드는 과정이 순탄하지 않았고, 오히려 그 과정에서 배운 게 많아서 정리해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub: &lt;a href=&quot;https://github.com/uri010/claude-notifier&quot;&gt;https://github.com/uri010/claude-notifier&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;만든 것&lt;/h2&gt;
&lt;p&gt;&lt;img style=&quot;max-width: 560px; width: 389px; display: block; margin: 16px auto; border-radius: 8px;&quot; src=&quot;https://blog.kakaocdn.net/dna/cyLWtc/dJMcabqPMI2/AAAAAAAAAAAAAAAAAAAAAHG-jzLU5DEVtlEY3LhOwcjYItKq92nfi6KK_C3tcLI1/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&amp;amp;expires=1780239599&amp;amp;allow_ip=&amp;amp;allow_referer=&amp;amp;signature=ozJafgue5HKPBmMpxuz6pLih4tU%3D&quot; alt=&quot;permission 배너&quot; height=&quot;182&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 도구를 실행할지 배너로 표시하고, Yes / Session / No 버튼으로 즉시 응답할 수 있다. Claude Code가 결과를 받아 계속 진행한다.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;max-width: 560px; width: 396px; display: block; margin: 16px auto; border-radius: 8px;&quot; src=&quot;https://blog.kakaocdn.net/dna/cYCRCm/dJMcadhSwyy/AAAAAAAAAAAAAAAAAAAAANXU_nkgq-9y67gnacAq_wKIiHk3pbA4ZRvDnC-Sha3h/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&amp;amp;expires=1780239599&amp;amp;allow_ip=&amp;amp;allow_referer=&amp;amp;signature=vauOhg5%2BRoJGJ2mUlNx4GK%2BPAGc%3D&quot; alt=&quot;stop 배너&quot; height=&quot;101&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 처리가 끝나면 완료 메시지를 배너로 표시한다. 클릭하면 해당 터미널 탭으로 자동 포커스된다.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;max-width: 560px; width: 410px; display: block; margin: 16px auto; border-radius: 8px;&quot; src=&quot;https://blog.kakaocdn.net/dna/Tekd1/dJMcahq3Inn/AAAAAAAAAAAAAAAAAAAAAOmcUFy1KVBnXtrcp4TMkX87q2z2Q1-hEXkHLqIwFBMR/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&amp;amp;expires=1780239599&amp;amp;allow_ip=&amp;amp;allow_referer=&amp;amp;signature=nWd%2FRuyw94Lafeyg%2B8XP4KSkluA%3D&quot; alt=&quot;question 배너&quot; height=&quot;199&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 질문할 때 배너에 요약을 표시한다. 클릭하면 터미널로 이동해 직접 답변할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널이 이미 포커스 상태라면 배너를 띄우지 않는다. 다른 앱을 사용 중일 때만 알림을 표시하고, 터미널로 전환하는 순간 모든 배너가 자동으로 닫힌다. &quot;Claude is waiting&quot; 같은 단순 대기 메시지는 필터링해서 실제 응답이 필요한 알림만 뜨도록 했다.&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;첫 번째 시도 &amp;mdash; 방향이 다섯 번 뒤집혔다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 메시지는 이랬다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&quot;클로드 실행하다가 사용자한테 권한 확인을 받을 때 알람이 안떠서 불편해요. 이걸 해결할 방법을 모색해주세요.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 정확히 짚었지만, 내가 원하는 것이 무엇인지는 하나도 전달하지 않은 셈이었다. AI는 해결책을 제안했고, 나는 쓰다 보니 마음에 안 들었고, 또 다른 방향을 요청했다. 이 사이클이 무려 다섯 번 반복됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1단계 &amp;mdash; osascript 소리 알림:&lt;/b&gt; AI가 소리로 알려주는 방식을 제안했다. 평소에 소리를 끄고 생활하는 터라 바로 거절했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2단계 &amp;mdash; 메뉴바 아이콘 + 드롭다운 메뉴:&lt;/b&gt; 메뉴바에 아이콘을 띄우고 클릭하면 내용이 나오는 방식이었다. 막상 써보니 &quot;아이콘을 눌러야만 하나요? 제가 원하는 건 알림이 발생하면 아이콘 바로 밑으로 내용이 뜨길 바랬어요&quot;가 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3단계 &amp;mdash; Dock 옆 캐릭터 점프 애니메이션:&lt;/b&gt; Claude 캐릭터가 Dock 옆에서 점프하는 방식을 요청했다. 외부 모니터를 연결 해제하니 아예 사라졌다. 환경을 미리 말하지 않았으니 당연한 결과였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4단계 &amp;mdash; terminal-notifier:&lt;/b&gt; macOS 알림처럼 보이는 외부 도구를 사용했는데, &quot;배너가 안 떴어요. 맥 기본 배너를 이용하는 방법은 없나요?&quot;가 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5단계 &amp;mdash; macOS 스타일 커스텀 배너:&lt;/b&gt; 결국 이 방향으로 결정됐다. 처음 메시지를 보낸 지 한참이 지나서야.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술적인 에러도 중간중간 터졌다. Python rumps 라이브러리를 쓰다가 AttributeError가 반복됐고, 배너가 표시되지 않거나 클릭해도 터미널로 이동하지 않는 문제가 이어졌다. 세션이 끝날 무렵에는 이렇게 요청하고 있었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&quot;그냥 직접 배너 뜨면 허용, 항상 허용, 거부 테스트하고 계속 디버깅하면서 고쳐서 저한테 알려줄 수 없나요?&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 자율 디버깅을 맡긴 채 세션을 닫았다. 69개의 사용자 메시지를 주고받고도 완성되지 않았다.&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;두 번째 시도 &amp;mdash; 요구사항 인터뷰부터&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 시작할 때는 접근 방식을 바꿨다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&quot;클로드 코드를 사용하면서 권한을 확인하거나, 일을 완료했을 때 알림을 받을 수 있는 기능이 필요합니다. 이 기능을 구현하기 위해 정해야 할 사항들을 인터뷰 방식으로 물어봐주세요.&quot;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 하나씩 물어봤다. 어떤 터미널 앱을 쓰는지, tmux를 사용하는지, 터미널이 화면 앞에 있을 때도 배너를 띄워야 하는지, 권한 요청은 어떻게 처리할지, 배너를 클릭하면 어떤 동작을 해야 하는지. 이렇게 먼저 정리하고 나니 설계가 처음부터 내 환경에 맞게 잡혔다. &quot;이건 내 환경에 안 맞아&quot;로 방향을 뒤집는 일이 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 권한을 부여하고 AI가 직접 빌드&amp;middot;실행&amp;middot;테스트까지 반복하도록 했다. 사람이 중간에 개입하는 루프 없이 초안이 만들어졌다. 다만 이 시도도 버그가 적지 않았다. 116개의 메시지를 주고받으며 디버깅을 이어갔고, 컨텍스트가 넘치면서 세션이 여러 번 나뉘었다. 결국 디렉터리를 새로 만들고 완전히 정리된 프로젝트로 다시 시작했다. 그게 지금의 claude-notifier다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;만들면서 나온 버그들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① 'Claude is waiting' 메시지가 배너로 떴다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 시도 때도 마찬가지였다. &quot;아무것도 안 하고 있는데 Claude is waiting 어쩌고 하는 질문 배너가 뜹니다&quot;라는 문제가 그대로 이어졌다. 메시지 내용을 검사해서 해당 패턴을 필터링하는 방식으로 해결했다.&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;macOS를 한국어로 설정하면 Terminal.app이 &quot;터미널&quot;로 표시된다. 영어 이름만 체크하고 있었으니 포커스 감지 자체가 작동하지 않았다.&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;&quot;배너를 누르면 해당 터미널로 이동 안 함, 2~3번 클릭 필요&quot;는 두 번째 시도 때부터 있던 문제였다. NSPanel의 acceptsFirstMouse를 재정의해서 첫 클릭부터 바로 동작하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;④ tmux 포커스가 엉뚱한 패널로 이동했다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;정확히 5번째 탭의 6이라는 tmux session에 3번째 터미널에서 알림이 왔는데 다른 곳으로 넘어갔습니다&quot;는 두 번째 시도의 마지막 메시지였다. display-message가 현재 클라이언트 기준으로 동작하다 보니 실제 Claude가 있는 pane이 아닌 다른 위치로 이동하는 문제였다. pane의 TTY를 역조회해서 정확한 위치를 찾는 방식으로 해결했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⑤ allowSession이 즉시 반영되지 않았다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;이 세션 동안 허용&quot; 버튼을 눌러도 다음 요청에 또 배너가 떴다. 세션 캐시 기록 로직이 Swift 앱과 bash 훅 양쪽에 이중으로 있었고 타이밍 문제가 있었다. 훅이 단독으로 처리하도록 정리했다.&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;보안 문제 &amp;mdash; 나중에 발견해서 다행이었다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능을 다 구현한 뒤, push 전에 보안 검토를 별도로 요청했다. 배너 클릭 시 터미널로 포커스를 복원하는 기능에서, HTTP 페이로드의 tty 필드가 검증 없이 AppleScript 문자열에 직접 삽입되고 있었다. 이론적으로 악의적인 tty 값이 들어오면 임의 스크립트를 실행할 수 있는 상태였다. /dev/[a-zA-Z0-9/]+ 정규식으로 TTY 경로를 먼저 검증한 뒤 AppleScript에 전달하도록 수정했다. 배너 상한 초과 시 메모리 누수도 같이 잡혔다. 배너가 20개 한도를 넘어 드롭될 때 resolve만 호출하고 remove를 누락해서 pending 항목이 앱 재시작 전까지 남아 있던 문제였다. 기능 구현 중에는 전혀 신경 쓰지 못했던 부분들이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결국 배운 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 시도에서 69개의 메시지를 주고받고도 완성하지 못한 건, AI가 부족해서가 아니라 내가 뭘 원하는지를 전달하지 않은 것이 문제였다. 소리가 꺼져 있다는 것도, tmux를 쓴다는 것도, 외부 모니터가 있다는 것도. AI는 그걸 알 방법이 없었다. 인터뷰 방식으로 먼저 환경과 요구사항을 정리하고 전권을 준 뒤 자율 진행시켰더니 훨씬 수월하게 만들어졌다. 보안과 테스트는 기능 완성 후 별도 체크포인트를 두는 것이 효과적이었다. 구현 중에 같이 하려면 흐름이 끊기는 반면, 마지막에 집중적으로 검토하면 놓쳤던 부분이 잘 드러났다.&lt;/p&gt;</description>
      <category>Develop/기타</category>
      <category>AI</category>
      <category>Claude</category>
      <category>claudecode</category>
      <category>Notification</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/188</guid>
      <comments>https://yulee.tistory.com/188#entry188comment</comments>
      <pubDate>Wed, 27 May 2026 14:16:48 +0900</pubDate>
    </item>
    <item>
      <title>[Develop] MySQL Fulltext Index 적용해보며 성능 차이 직접 측정해보기</title>
      <link>https://yulee.tistory.com/185</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1년 반 전의 실수를 다시 실험해보다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약 1년 반 전에 대학 졸업 프로젝트였던 '메디레디'에서 의약품 검색 기능을 구현했었다. 약 5만개 정도의 의약품 데이터를 이름으로 검색할 때 2글자 이상 입력시 검색할 수 있도록 구현했었다. 나름 그 때는 검색 성능을 높여 보고자 MySQL의 역인덱싱 기능인 Fulltext Index를 적용해보고 LIKE와 성능 비교를 했었는데, 이상하게도 쿼리 수행 속도가 비슷했다. 뭐지 데이터가 적어서 그런가?하고 안일하게 넘어갔던 그때의 바보같은 나...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우연한 기회로 이게 잘못된 테스트였다는 걸 알아차렸다. 그래서 다시 테스트를 수행해봤다. 여러번 해볼 필요도 없었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 해보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 그때와 비슷한 환경을 만들어주기 위해서 Docker를 이용해 MySQL을 컨테이너로 실행하고, '의약품 안전나라' 사이트에서 데이터를 다운로드 받아서 일부만 넣어주었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넣어준 데이터는 정확히 44006행이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ncj0h/dJMcagKAOqv/Xlg6z9jL9JDkHkxwk27NjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ncj0h/dJMcagKAOqv/Xlg6z9jL9JDkHkxwk27NjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ncj0h/dJMcagKAOqv/Xlg6z9jL9JDkHkxwk27NjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fncj0h%2FdJMcagKAOqv%2FXlg6z9jL9JDkHkxwk27NjK%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;589&quot; height=&quot;194&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;194&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;그러고 나서 LIKE 문으로 데이터를 검색해봤다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPLHYa/dJMcakzsvRK/KGsEBZYksAiTtrQxV8nshK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPLHYa/dJMcakzsvRK/KGsEBZYksAiTtrQxV8nshK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPLHYa/dJMcakzsvRK/KGsEBZYksAiTtrQxV8nshK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPLHYa%2FdJMcakzsvRK%2FKGsEBZYksAiTtrQxV8nshK%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;626&quot; height=&quot;150&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예상대로 전체 스캔을 수행했고 43.3ms가 걸렸다.&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;이번에는 Fulltext를 적용해주었다. 적용하기 전에 ngram 값을 확인해줘야 한다. ngram은 몇글자 단위로 끊어서 인덱싱을 적용할 것인지에 대한 옵션인데, 기본적으로 2로 설정되어 있어 그대로 진행했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caWQ07/dJMcagKAOGW/t3IkJY58Nh3VxgW4C44F0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caWQ07/dJMcagKAOGW/t3IkJY58Nh3VxgW4C44F0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caWQ07/dJMcagKAOGW/t3IkJY58Nh3VxgW4C44F0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaWQ07%2FdJMcagKAOGW%2Ft3IkJY58Nh3VxgW4C44F0k%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;595&quot; height=&quot;230&quot; data-origin-width=&quot;595&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;이번에는 확실히 줄어든 것을 볼 수 있다. 약 19ms 내에 완료되었다..!! 심지어 105개의 행만 탐색했다는 것도 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 결과&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 다른 검색어도 테스트해본 결과이다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 189px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&lt;b&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;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;&lt;b&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;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;실제 수행 시간 (actual time)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;스캔한 행 수 (rows)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&lt;b&gt;타이&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;LIKE&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;40.5 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;&lt;b&gt;44,006행 전체 스캔&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;FULLTEXT&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;19 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;✅ 105행만 스캔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&lt;b&gt;이레&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;LIKE&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;37.9 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;&lt;b&gt;44,006행 전체 스캔&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;FULLTEXT&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;4.58 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;✅ 39행만 스캔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&lt;b&gt;레놀&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;LIKE&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;35.6 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;&lt;b&gt;44,006행 전체 스캔&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;FULLTEXT&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;1.46 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;✅ 16행만 스캔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&lt;b&gt;이지&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;LIKE&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;37.9 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;&lt;b&gt;44,006행 전체 스캔&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 12.5581%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 18.2558%;&quot;&gt;FULLTEXT&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 40.1163%;&quot;&gt;11.1 ms&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 28.9535%;&quot;&gt;✅ 124행만 스캔&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 비교해봐도 확실히 Fulltext를 적용한 것이 빠르게 수행된 것을 알 수 있다.&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;결국 중요한 건 &amp;lsquo;데이터 특성&amp;rsquo;과 &amp;lsquo;설계&amp;rsquo;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 왜 '타이'와 '이지'는 10ms가 넘어가는걸까?&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;Fulltext 인덱스에서는 검색어의 길이보다는 해당 단어의 '출현 빈도'가 더 중요하다. 의약품 데이터에는 비슷한 이름들이 많기 때문에 어떤 검색어냐에 따라 성능이 달라질 수 밖에 없다.&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;결국 Fulltext 인덱스는 만능 검색 최적화가 아니며, 데이터 특성과 검색 패턴을 이해한 설계가 핵심이라는 것을 느꼈다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;졸업 프로젝트 당시에 테스트했던 자료가 충분하지 않아 어느 부분에서 문제가 생겼는지는 모르겠지만, 그래도 이번에 확실히 그때 무언가 잘못되었음을 인지하였고 어떤 결과가 나왔어야 했는지를 확인해볼 수 있었다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Develop</category>
      <category>fulltext</category>
      <category>index</category>
      <category>like</category>
      <category>MySQL</category>
      <category>ngram</category>
      <category>검색</category>
      <category>검색성능</category>
      <category>성능</category>
      <category>테스트</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/185</guid>
      <comments>https://yulee.tistory.com/185#entry185comment</comments>
      <pubDate>Fri, 7 Nov 2025 22:45:56 +0900</pubDate>
    </item>
    <item>
      <title>[에스넷시스템 부트캠프] 온라인 네트워크 엔지니어 부트캠프 수료 및 후기</title>
      <link>https://yulee.tistory.com/184</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;88일간의 여정&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;764&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TWCKB/btsQQHudSJz/UOI2QPU0bVDxu1avDYBYvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TWCKB/btsQQHudSJz/UOI2QPU0bVDxu1avDYBYvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TWCKB/btsQQHudSJz/UOI2QPU0bVDxu1avDYBYvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTWCKB%2FbtsQQHudSJz%2FUOI2QPU0bVDxu1avDYBYvK%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;340&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;764&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 88일간의 교육 과정을 마무리했다.  &lt;br /&gt;단 하루도 빠짐없이 출석률 100%를 달성하고자 했던 목표를 지켜낸 것도 뿌듯하다.&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, Kubernetes, Ansible, VMware 등 다양한 기술을 배울 수 있었고, 프로젝트를 통해 AWS와 Kubernetes, Terraform으로 고가용성 서비스를 직접 구축해보았다. 써보고 싶었던 AWS 리소스를 다뤄본 경험도 의미 있었고, ArgoCD나 EFK처럼 실제 현업에서 자주 쓰이는 배포 자동화 및 모니터링 기술을 적용할 수 있었던 점이 큰 성장으로 다가왔다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최우수상 수상&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;1420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Uzwqz/btsQN8Unc5w/92YqlUJu2n2wF3x4TJXmV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Uzwqz/btsQN8Unc5w/92YqlUJu2n2wF3x4TJXmV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Uzwqz/btsQN8Unc5w/92YqlUJu2n2wF3x4TJXmV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUzwqz%2FbtsQN8Unc5w%2F92YqlUJu2n2wF3x4TJXmV0%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;434&quot; height=&quot;615&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;1420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에서 최우수상을 수상했다!&lt;br /&gt;그동안 열심히 달려온 노력이 인정받은 것 같아 큰 보람을 느낄 수 있었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;온라인 교육의 장단점&lt;/h3&gt;
&lt;p data-end=&quot;718&quot; data-start=&quot;582&quot; data-ke-size=&quot;size16&quot;&gt;온라인 교육의 장점은 분명했다. 이동 시간과 교통비, 식비를 아낄 수 있었고, 피곤한 날에는 점심이나 쉬는 시간을 활용해 쪽잠을 잘 수 있었다. 남는 시간에는 자격증 공부나 배운 내용을 정리하며 효율적으로 활용할 수 있었던 것도 장점이었다.&lt;/p&gt;
&lt;p data-end=&quot;718&quot; data-start=&quot;582&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;909&quot; data-start=&quot;720&quot; data-ke-size=&quot;size16&quot;&gt;하지만 단점도 만만치 않았다. 집중력이 떨어지기 쉽고, 화면으로만 보는 수업은 몰입도가 낮았다. 질문 역시 Slack을 통해 진행하다 보니 즉각적인 해결이 어렵고, 화면 공유만으로는 한계가 있었다. 강사님 입장에서도 수강생의 이해도를 파악하기 어려워 진도를 그대로 나가는 경우가 많았고, 필요한 복습 영상이 녹화되지 않은 적도 있었다.&lt;/p&gt;
&lt;p data-end=&quot;1064&quot; data-start=&quot;911&quot; data-ke-size=&quot;size16&quot;&gt;무엇보다 프로젝트 기간에 단점이 크게 드러났다. 각자가 무슨 일을 하고 있는지 확인하기 어렵고, 역할 분담이 명확하지 않으면 일하는 사람만 계속 부담을 지게 되는 구조였다. 오프라인에서도 있을 수 있는 문제지만, 온라인 환경에서는 그 차이가 더 뚜렷하게 드러난 것 같다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비전공자에게 추천? 비추천?&amp;nbsp;&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-end=&quot;543&quot; data-start=&quot;272&quot; data-ke-size=&quot;size16&quot;&gt;전공자에게는 꽤 괜찮은 과정일 수 있다. 특히 네트워크 엔지니어나 클라우드 분야에 관심 있는 사람이라면 실질적으로 도움이 된다. 다만 모두가 적극적인 팀플을 기대하지는 않았으면 한다. 나처럼 &quot;써보고 싶은 기술이 있다&quot;거나 &quot;AWS 같은 비용이 드는 리소스를 직접 다뤄보고 싶다&quot;는 목표가 있거나, 팀플 경험이 많아 Jira나 GitHub Projects, Notion 등을 활용해 작업을 공유하고 비전공자 팀원을 서포트할 수 있는 리더십이 있다면 충분히 가치 있는 과정이 될 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;앞으로의 계획&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;br /&gt;다음 주부터는 다시 AWS SAA 자격증 공부를 하고,&amp;nbsp;SAA를 취득한 뒤에는 CKA에 도전할 예정이다. Kubernetes를 공부하고 직접 다뤄보면서, 생각보다 훨씬 복잡하고 알아야 할 것이 많다는 걸 느꼈다. 관심을 갖게 된 만큼 제대로 공부해 자격증으로 증명하는 게 좋을 것 같다.&lt;/p&gt;
&lt;p data-end=&quot;894&quot; data-start=&quot;842&quot; data-ke-size=&quot;size16&quot;&gt;또한 매일 조금씩 영어 공부를 이어가면서, OPIc도 만료되기 전에 다시 취득하려고 한다.&lt;/p&gt;
&lt;p data-end=&quot;894&quot; data-start=&quot;842&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;88일간의 과정을 끝냈지만, 이제는 진짜 시작이다.&lt;br /&gt;취업해서 사회의 일원으로서 일하게 되는 그날까지, 꾸준히 성장하며 달려 나가야겠다. 파이팅!  &lt;/p&gt;</description>
      <category>TIL</category>
      <category>TiL</category>
      <category>멀티캠퍼스it부트캠프</category>
      <category>부트캠프후기</category>
      <category>비전공자 부트캠프</category>
      <category>에스넷시스템 부트캠프</category>
      <category>전공자 부트캠프</category>
      <category>클라우드 부트캠프</category>
      <category>후기</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/184</guid>
      <comments>https://yulee.tistory.com/184#entry184comment</comments>
      <pubDate>Thu, 25 Sep 2025 16:49:45 +0900</pubDate>
    </item>
    <item>
      <title>[에스넷시스템 부트캠프] TIL Day 86~88 - 프로젝트 발표 및 최우수상 수상</title>
      <link>https://yulee.tistory.com/183</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 86 - 마지막 발표 준비&lt;/h2&gt;
&lt;p data-end=&quot;264&quot; data-start=&quot;144&quot; data-ke-size=&quot;size16&quot;&gt;PPT를 어느 정도 완성하고 발표 스크립트도 짜봤다. 실제로 발표처럼 연습해보니 예상보다 시간이 많이 남아 비상이 걸렸다. 부랴부랴 지웠던 시연 영상을 다시 추가하고, Terraform 시연 영상도 새로 찍었다.&lt;/p&gt;
&lt;p data-end=&quot;264&quot; data-start=&quot;144&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;432&quot; data-start=&quot;266&quot; data-ke-size=&quot;size16&quot;&gt;페이지 수도 많고 할 얘기도 많았기 때문에 시간이 부족할까 걱정했지만 내가 말이 빠른 편이라 오히려 시간이 남았다. 시간 부족 때문에 뺐던 내용들도 모두 추가하고 나니 안정적으로 25분 이상 발표할 수 있었다. 이제 진짜 내일이면 프로젝트가 끝난다는 생각에 긴장과 기대가 교차했다.&lt;/p&gt;

            &lt;figure class=&quot;unsupported component-kakaotv&quot; contenteditable=&quot;false&quot; style=&quot;background:#000;margin:16px 0;min-height:72px;padding:10px 16px;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;width:100%;max-width:100%;&quot;&gt;
                &lt;p contenteditable=&quot;false&quot; style=&quot;margin:0;color:#8a8a8a;font-size:13px;line-height:1.6;user-select:none;pointer-events:none;&quot;&gt;동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.&lt;/p&gt;
            &lt;/figure&gt;
        
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 87 - 프로젝트 발표 및 최우수상 수상&lt;/h2&gt;
&lt;p data-end=&quot;273&quot; data-start=&quot;163&quot; data-ke-size=&quot;size16&quot;&gt;드디어 프로젝트 발표 날이다. 온라인 환경이라 대본을 외우지 않고 준비한 대본을 보면서 발표를 진행했다. 혹시 몰라 스톱워치도 켜 두고, 말이 빨라지지 않도록 속도를 조절하며 차근차근 진행했다.&lt;/p&gt;
&lt;p data-end=&quot;359&quot; data-start=&quot;275&quot; data-ke-size=&quot;size16&quot;&gt;발표 시작 전에는 긴장이 심했지만, 막상 시작하고 나니 긴장이 풀렸다. 준비했던 내용을 차근차근 발표하고 심사평까지 들으니 홀가분한 기분이 들었다.&lt;/p&gt;
&lt;p data-end=&quot;556&quot; data-start=&quot;361&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;556&quot; data-start=&quot;361&quot; data-ke-size=&quot;size16&quot;&gt;심사평에서는 대부분 긍정적인 평가를 받았다.&lt;/p&gt;
&lt;p data-end=&quot;556&quot; data-start=&quot;361&quot; data-ke-size=&quot;size16&quot;&gt;다양한 기술 스택을 활용한 점, AI를 이용해 이미지 생성 기능을 구현한 점이 다른 팀과 차별화되었다는 점, 자동화와 확장성을 적용해 유지보수와 비용 최적화를 고려한 점, 그리고 협업 툴을 잘 활용한 점이 좋게 평가되었다. 또한 PPT 자료의 가독성과 발표자의 말 속도, 딕션도 좋다는 평가를 받았다.&lt;/p&gt;
&lt;p data-end=&quot;621&quot; data-start=&quot;558&quot; data-ke-size=&quot;size16&quot;&gt;개인적으로는 프로젝트에서 아쉬움이 많이 남았기 때문에, 좀 더 실무적인 조언을 듣지 못한 점이 조금 아쉬웠다.&lt;/p&gt;
&lt;p data-end=&quot;621&quot; data-start=&quot;558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;664&quot; data-start=&quot;623&quot; data-ke-size=&quot;size16&quot;&gt;그리고 결국 상을 받았다! 한 팀만 받을 수 있는 상이라 더욱 뜻깊었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 88 - 직무 특강&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 마지막 수업인 직무 특강을 듣는 날이었다. 최근 하반기 공채가 많이 열리면서 여러 서류를 준비하던 시기라 더욱 기대가 됐다.&lt;/p&gt;
&lt;p data-end=&quot;405&quot; data-start=&quot;189&quot; data-ke-size=&quot;size16&quot;&gt;수업은 각자의 현재 상황을 공유하는 것으로 시작되었다. 어떤 직무를 목표로 하고 있는지, 취준 과정에서 어떤 고민이 있는지를 나누자, 강사님께서 그에 맞는 조언을 해주셨다. 이어서 이력서, 자기소개서, 포트폴리오 작성 방법은 물론이고 면접 준비 팁까지 세세하게 알려주셨다. 특히 실제 개선된 사례를 직접 보여주셔서, 어떤 식으로 글을 다듬어야 하는지 훨씬 명확하게 이해할 수 있었다.&lt;/p&gt;
&lt;p data-end=&quot;405&quot; data-start=&quot;189&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;521&quot; data-start=&quot;407&quot; data-ke-size=&quot;size16&quot;&gt;나 역시 미리 작성해둔 이력서와 포트폴리오에 대한 피드백을 받을 수 있었고, 그 과정에서 부족한 부분과 보완해야 할 점을 발견했다. 덕분에 앞으로 어떤 방향으로 개선해야 할지 구체적인 그림이 그려졌다.&lt;/p&gt;
&lt;p data-end=&quot;521&quot; data-start=&quot;407&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;603&quot; data-start=&quot;523&quot; data-ke-size=&quot;size16&quot;&gt;아쉽게도 몇몇 기업은 이미 공고가 마감된 상태였지만, 배운 내용을 바탕으로 자료를 보완해 앞으로 더 많은 기업에 자신 있게 지원해보려 한다.&lt;/p&gt;</description>
      <category>TIL</category>
      <category>TiL</category>
      <category>멀티캠퍼스it부트캠프</category>
      <category>발표</category>
      <category>부트캠프후기</category>
      <category>수상</category>
      <category>에스넷시스템 부트캠프</category>
      <category>직무특강</category>
      <category>최우수상</category>
      <category>클라우드 활용 네트워크 엔지니어 부트캠프</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/183</guid>
      <comments>https://yulee.tistory.com/183#entry183comment</comments>
      <pubDate>Tue, 23 Sep 2025 21:30:15 +0900</pubDate>
    </item>
    <item>
      <title>[에스넷시스템 부트캠프] TIL Day 81~85 - 프로젝트 8주차</title>
      <link>https://yulee.tistory.com/182</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 81 - 모니터링 환경 구성&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CloudWatch 구동 확인&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1862&quot; data-origin-height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/weW9s/btsQAhqfyF6/OFO8qepD8VkYj8tvyGSgEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/weW9s/btsQAhqfyF6/OFO8qepD8VkYj8tvyGSgEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/weW9s/btsQAhqfyF6/OFO8qepD8VkYj8tvyGSgEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FweW9s%2FbtsQAhqfyF6%2FOFO8qepD8VkYj8tvyGSgEK%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;789&quot; height=&quot;212&quot; data-origin-width=&quot;1862&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;이번 주의 시작은 지난주에 설치했던 CloudWatch가 정상적으로 작동하는지부터 확인하는 것으로 열었다. 다행히 Pod들을 잘 감지하고 있는 것을 확인할 수 있었고, 기본적인 모니터링 환경이 안정적으로 구동되고 있다는 사실에 조금 안심이 되었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;EFK 스택 구성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이어서 로깅 환경을 마련하기 위해 EFK 스택을 구성했다. Fluent Bit를 DaemonSet으로 배포해 각 노드에서 실행 중인 Pod들의 로그를 수집하도록 했고, 수집된 로그는 Elasticsearch에 저장되도록 연결했다. 이후 Kibana를 통해 로그를 시각화할 수 있는 환경까지 갖추면서 기본적인 로깅 파이프라인이 완성되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 메트릭과 로그 모니터링을 완성하고 나니 프로젝트가 점점 실서비스 환경에 가까워지는 것 같아 뿌듯했다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0915_EFK 인덱스 green.png&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;467&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2DLIE/btsQyoqpfHZ/AErasN2kg0EnJJKHnNR3zK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2DLIE/btsQyoqpfHZ/AErasN2kg0EnJJKHnNR3zK/img.png&quot; data-alt=&quot;인덱스 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2DLIE/btsQyoqpfHZ/AErasN2kg0EnJJKHnNR3zK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2DLIE%2FbtsQyoqpfHZ%2FAErasN2kg0EnJJKHnNR3zK%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;428&quot; height=&quot;209&quot; data-filename=&quot;0915_EFK 인덱스 green.png&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;467&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인덱스 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0915_EFK 스택 구성.png&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;937&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMEVbz/btsQBld9qTz/GMbUDnaKfEiAHa4ICA4UXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMEVbz/btsQBld9qTz/GMbUDnaKfEiAHa4ICA4UXK/img.png&quot; data-alt=&quot;Kibana 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMEVbz/btsQBld9qTz/GMbUDnaKfEiAHa4ICA4UXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMEVbz%2FbtsQBld9qTz%2FGMbUDnaKfEiAHa4ICA4UXK%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;533&quot; height=&quot;261&quot; data-filename=&quot;0915_EFK 스택 구성.png&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;937&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Kibana 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 82 - SNS 연동 &amp;amp; Jenkins 설치 시도&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SNS 연동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CloudWatch에서 설정한 알람을 SNS와 연동하여 특정 임계치를 넘었을 때 내 Gmail로 알림 메일을 받을 수 있도록 구성했다. 이제는 단순히 메트릭을 보는 것에서 그치지 않고 실제로 이상 징후가 감지되었을 때 빠르게 대응할 수 있는 체계를 갖추게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vB9o5/btsQJ97uLqR/ygA32GH4D4SFIB4ELdoDF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vB9o5/btsQJ97uLqR/ygA32GH4D4SFIB4ELdoDF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vB9o5/btsQJ97uLqR/ygA32GH4D4SFIB4ELdoDF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvB9o5%2FbtsQJ97uLqR%2FygA32GH4D4SFIB4ELdoDF1%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;345&quot; height=&quot;372&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;682&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;Jenkins 설치 시도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이어서 Jenkins 설치도 시도해보았다. 그러나 플러그인 설치 과정에서 일본이나 중국의 미러 서버로 연결되는 문제가 발생하면서 설치가 계속 실패했다. 직접 플러그인 파일을 다운로드해 옮겨보기도 하고, 구글링으로 찾은 다른 방법들을 적용해보기도 했지만 결국 문제를 해결하지는 못했다. 다른 대안적인 방법도 있었지만 프로젝트 마감까지 시간이 얼마 남지 않은 상황에서 안정적으로 진행하는 것이 더 중요하다고 판단했다. 결국 조금 더 익숙하고 빠르게 파이프라인을 구성할 수 있는 GitHub Actions를 활용하기로 결정했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 83 - CI/CD 파이프라인 구축&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Github Actions 워크플로우 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub Actions 워크플로우를 작성해 특정 브랜치와 디렉토리에 코드가 push되면 이를 자동으로 감지하고 동작하도록 구성했다. 이 워크플로우는 FastAPI 애플리케이션의 테스트를 실행하고, Docker 이미지를 빌드한 뒤 ECR에 업로드하도록 설계되었으며, 이후 Kubernetes manifest 파일의 이미지 버전을 자동으로 갱신하도록 했다. 이를 통해 코드 변경이 발생했을 때 배포까지 이어지는 과정이 수동 개입 없이 자연스럽게 이어질 수 있게 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/th7F4/btsQJ88Bm8w/kNzrtJ4ykY8VYMhZOvBoc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/th7F4/btsQJ88Bm8w/kNzrtJ4ykY8VYMhZOvBoc0/img.png&quot; data-alt=&quot;GitHub Actions&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/th7F4/btsQJ88Bm8w/kNzrtJ4ykY8VYMhZOvBoc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fth7F4%2FbtsQJ88Bm8w%2FkNzrtJ4ykY8VYMhZOvBoc0%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;717&quot; height=&quot;340&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GitHub Actions&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRZUJO/btsQMRqA38Z/Yuhu2JmrpzH3W9bYHvhKK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRZUJO/btsQMRqA38Z/Yuhu2JmrpzH3W9bYHvhKK1/img.png&quot; data-alt=&quot;ECR&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRZUJO/btsQMRqA38Z/Yuhu2JmrpzH3W9bYHvhKK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRZUJO%2FbtsQMRqA38Z%2FYuhu2JmrpzH3W9bYHvhKK1%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;497&quot; height=&quot;218&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;244&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ECR&lt;/figcaption&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;ArgoCD 설치 및 구성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ArgoCD를 설치하고 Kubernetes 환경에 맞게 구성했다. ArgoCD는 manifest의 변경 사항을 감지하고 새로운 이미지 버전에 맞춰 Pod를 자동으로 교체하는 역할을 하도록 설정했다. 이로써 코드 수정에서 배포까지 전 과정을 자동화하는 CI/CD 흐름이 완성되었고, 안정적이고 일관성 있는 배포가 가능해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;934&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pEz3p/btsQD2sqXTH/FZyiQpb2yzkn6O612BYPkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pEz3p/btsQD2sqXTH/FZyiQpb2yzkn6O612BYPkk/img.png&quot; data-alt=&quot;ArgoCD&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pEz3p/btsQD2sqXTH/FZyiQpb2yzkn6O612BYPkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpEz3p%2FbtsQD2sqXTH%2FFZyiQpb2yzkn6O612BYPkk%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;519&quot; height=&quot;414&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;934&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ArgoCD&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1870&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKGJh8/btsQBYxVkRS/VrHqR4tdioYZ6zrj610nlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKGJh8/btsQBYxVkRS/VrHqR4tdioYZ6zrj610nlK/img.png&quot; data-alt=&quot;news-collector 애플리케이션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKGJh8/btsQBYxVkRS/VrHqR4tdioYZ6zrj610nlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKGJh8%2FbtsQBYxVkRS%2FVrHqR4tdioYZ6zrj610nlK%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;669&quot; height=&quot;291&quot; data-origin-width=&quot;1870&quot; data-origin-height=&quot;814&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;news-collector 애플리케이션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1905&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r49Tq/btsQBYdyUfQ/TBOdDB9HuVmcBJo7sk2aX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r49Tq/btsQBYdyUfQ/TBOdDB9HuVmcBJo7sk2aX0/img.png&quot; data-alt=&quot;news-api 애플리케이션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r49Tq/btsQBYdyUfQ/TBOdDB9HuVmcBJo7sk2aX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr49Tq%2FbtsQBYdyUfQ%2FTBOdDB9HuVmcBJo7sk2aX0%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;662&quot; height=&quot;321&quot; data-origin-width=&quot;1905&quot; data-origin-height=&quot;923&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;news-api 애플리케이션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 84 - 발표 자료 및 시연 영상 제&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;발표 준비&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 본격적으로 발표 준비에 돌입했다. 가장 먼저 발표 자료의 전반적인 디자인 테마를 정하고, 기본적인 목차를 구성했다. 발표의 큰 흐름은 프로젝트 개요 &amp;rarr; 기술 설명 &amp;rarr; 프로젝트 관리 순서로 잡았으며, 가급적 글보다는 그림 위주의 구성으로 청중이 이해하기 쉽도록 구성하려고 했다. 아직 초기 단계라 채워 넣은 부분은 많지 않지만, 틀을 마련해둔 만큼 차근차근 완성해 나갈 계획이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1851&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGx1WX/btsQK18ZiMV/HYWCdg0pPKd1GCTrkuPS70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGx1WX/btsQK18ZiMV/HYWCdg0pPKd1GCTrkuPS70/img.png&quot; data-alt=&quot;발표 ppt&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGx1WX/btsQK18ZiMV/HYWCdg0pPKd1GCTrkuPS70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGx1WX%2FbtsQK18ZiMV%2FHYWCdg0pPKd1GCTrkuPS70%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;677&quot; height=&quot;303&quot; data-origin-width=&quot;1851&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;발표 ppt&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CI/CD 시연 영상 준비&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI/CD 시연 영상을 준비했다. 영상을 제작하면서 몇 가지 오류가 드러났는데, ArgoCD에서 자동 감지가 되지 않았던 문제는 Auto Sync 기능이 꺼져 있었기 때문이었고, Kubernetes Manifest의 이미지 버전 수정도 정상적으로 반영되지 않아 수정 작업을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 해결한 뒤, 시연 영상에는 테스트용 API를 추가한 뒤 실제 CI/CD 과정을 거쳐 배포가 정상적으로 이루어졌는지 확인하는 과정을 담았다. 최종적으로는 API 실행 결과와 로그 모니터링 화면을 함께 보여주어 CI/CD 파이프라인의 흐름을 명확히 전달할 수 있도록 구성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;

            &lt;figure class=&quot;unsupported component-kakaotv&quot; contenteditable=&quot;false&quot; style=&quot;background:#000;margin:16px 0;min-height:72px;padding:10px 16px;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;width:100%;max-width:100%;&quot;&gt;
                &lt;p contenteditable=&quot;false&quot; style=&quot;margin:0;color:#8a8a8a;font-size:13px;line-height:1.6;user-select:none;pointer-events:none;&quot;&gt;동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.&lt;/p&gt;
            &lt;/figure&gt;
        
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 85 - 발표 준&lt;/h2&gt;
&lt;p data-end=&quot;141&quot; data-start=&quot;56&quot; data-ke-size=&quot;size16&quot;&gt;오늘도 어제에 이어 발표 준비를 이어갔다. 다가오는 주말에는 네트워크 관리사 2급 실기 시험 준비로 바쁠 예정이라 발표 자료는 조금 서둘러 진행했다.&lt;/p&gt;
&lt;p data-end=&quot;141&quot; data-start=&quot;56&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;353&quot; data-start=&quot;143&quot; data-ke-size=&quot;size16&quot;&gt;준비 과정에서 가장 만족스러웠던 부분은 CI/CD 다이어그램이었다. 지금까지의 구현 과정을 시각적으로 잘 표현해낸 것 같아 개인적으로 가장 잘 만든 자료라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clvhVl/btsQLcvNbxt/BycV5Y8cP4JbE8OHKkztr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clvhVl/btsQLcvNbxt/BycV5Y8cP4JbE8OHKkztr0/img.png&quot; data-alt=&quot;CI/CD 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clvhVl/btsQLcvNbxt/BycV5Y8cP4JbE8OHKkztr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclvhVl%2FbtsQLcvNbxt%2FBycV5Y8cP4JbE8OHKkztr0%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;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CI/CD 과정&lt;/figcaption&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;9333&quot; data-origin-height=&quot;5250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v2ksy/btsQL7U0fkp/y02hSHHyO4tEjSgMx4LK8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v2ksy/btsQL7U0fkp/y02hSHHyO4tEjSgMx4LK8k/img.png&quot; data-alt=&quot;전체 아키텍처&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v2ksy/btsQL7U0fkp/y02hSHHyO4tEjSgMx4LK8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv2ksy%2FbtsQL7U0fkp%2Fy02hSHHyO4tEjSgMx4LK8k%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;9333&quot; height=&quot;5250&quot; data-origin-width=&quot;9333&quot; data-origin-height=&quot;5250&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전체 아키텍처&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✍️ 주간 회고&lt;/h2&gt;
&lt;p data-end=&quot;150&quot; data-start=&quot;57&quot; data-ke-size=&quot;size16&quot;&gt;이번 주는 프로젝트의 마무리 단계라는 느낌이 강하게 들었다. 다행히 목표로 삼았던 모니터링 환경과 CI/CD를 모두 완성할 수 있어 성취감을 느꼈다.&lt;/p&gt;
&lt;p data-end=&quot;305&quot; data-start=&quot;152&quot; data-ke-size=&quot;size16&quot;&gt;하지만 아쉬움도 남았다. Jenkins를 사용하지 못했고, 로그 모니터링 대시보드 구성이 다채롭지 못했으며, 알람은 단순히 리소스 사용량 기준으로만 설정했다. 또한 비용 최적화를 충분히 고려하지 못했고, ArgoCD를 Helm Chart로 구성해보지 못한 점도 아쉬웠다.&lt;/p&gt;
&lt;p data-end=&quot;305&quot; data-start=&quot;152&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;393&quot; data-start=&quot;307&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;</description>
      <category>TIL</category>
      <category>argocd</category>
      <category>CI/CD</category>
      <category>EFK</category>
      <category>TiL</category>
      <category>멀티캠퍼스it부트캠프</category>
      <category>모니터링</category>
      <category>발표 준비</category>
      <category>부트캠프후기</category>
      <category>에스넷시스템 부트캠프</category>
      <category>클라우드 활용 네트워크 엔지니어 부트캠프</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/182</guid>
      <comments>https://yulee.tistory.com/182#entry182comment</comments>
      <pubDate>Sun, 21 Sep 2025 00:17:59 +0900</pubDate>
    </item>
    <item>
      <title>[에스넷시스템 부트캠프] TIL Day 76~80 - 프로젝트 7주차</title>
      <link>https://yulee.tistory.com/181</link>
      <description>&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Day 76 - 모니터링 환경 재시도&amp;nbsp;&lt;/h2&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;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;문제&amp;nbsp;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;peration error EC2: CreateVolume, get identity: get credentials: request canceled, context canceled&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CSI Driver Controller 파드에서 해당 에러 발&lt;/p&gt;
&lt;h4 data-end=&quot;395&quot; data-start=&quot;387&quot; data-ke-size=&quot;size20&quot;&gt;원인&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;526&quot; data-start=&quot;396&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;455&quot; data-start=&quot;396&quot;&gt;CSI Driver Controller 파드가 EC2 볼륨 생성 권한을 제대로 획득하지 못함&lt;/li&gt;
&lt;li data-end=&quot;526&quot; data-start=&quot;456&quot;&gt;IAM Role과 Policy는 정상적으로 생성되어 있었고, Pod에도 ServiceAccount로 잘 매핑되어 있었음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;537&quot; data-start=&quot;528&quot; data-ke-size=&quot;size20&quot;&gt;미해결&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;627&quot; data-start=&quot;538&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;571&quot; data-start=&quot;538&quot;&gt;권한과 설정을 여러 번 확인했지만 끝내 해결하지 못함&lt;/li&gt;
&lt;li data-end=&quot;627&quot; data-start=&quot;572&quot;&gt;내부 네트워크 문제까지 겹쳐 결국 기존 Cluster를 삭제하고 새로 생성하기로 결정&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Day 77 - Cluster 재생성&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;어제의 문제를 결국 해결하지 못하고 Cluster를 다시 만들었다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Terraform 주석 처리로 Cluster와 관련된 모든 리소스를 삭제하고, 다시 주석을 풀어 생성하는데만 2시간이 걸린 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 네트워크 문제 없이 Pod들이 정상적으로 DynamoDB나 S3에 접속하여 API 호출에 문제가 없었다.&amp;nbsp;&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;그렇게 정상적으로 동작하는 것을 확인하고 나니 마음이 편해졌다. 그리고 조금 미뤄왔던 namespace 구분을 하기 위해 다시 삭제했다.  데이터 조회용 서비스와 데이터 수집용 서비스를 나누기 위해 news-api와 news-collector namespace를 생성하고 기존 리소스들을 할당해주었다. 이 과정은 kubectl apply -f news-service.yaml 을 실행해놓고 저녁 먹고 강아지랑 산책까지 하고 왔더니 Route53에 고정 도메인도 생성되어 있었고 정상적으로 Pod들이 동작하는 걸 확인할 수 있었다.&amp;nbsp;&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;이번 Cluster 재생성 과정에서 내가 깨달은 건 &lt;b&gt;생각보다 Kubernetes 내부에서 리소스 변경 감지가 오래 걸린다는 것&lt;/b&gt;이었다. 물론 어떤 리소스냐에 따라 다른 것 같긴 하지만 Ingress 부분은 확실히 오래 기다려야 했다. 정상 작동되는지 빨리 확인하려는 마음에 조금 조급해서 rollout이나 삭제하고 다시 올려볼까를 고민하다가 조금만 더 기다려보니 정상적으로 동작했다! 기다림이 필요한 작업이었던 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNYq9k/btsQzesPF4l/SWgcgkwt02K5ghe9en17Z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNYq9k/btsQzesPF4l/SWgcgkwt02K5ghe9en17Z0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNYq9k/btsQzesPF4l/SWgcgkwt02K5ghe9en17Z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNYq9k%2FbtsQzesPF4l%2FSWgcgkwt02K5ghe9en17Z0%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;737&quot; height=&quot;156&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 78 - 고가용성 확보&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HPA 구성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고가용성을 구성하기 위해 news-api 서비스를 위한 HPA와 PB를 생성했다.&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;HPA는 Horizontal Pod Autoscaler로 리소스 사용량이 기준치를 넘었을 때 Pod를 자동으로 늘려주는 역할을 한다. 덕분에 서비스가 갑자기 많은 요청을 받더라도 안정적으로 대응할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PB는 Pod Disruption Budget으로&amp;nbsp;최소 몇 개의 Pod가 반드시 살아있어야 하는지를 정해주는 정책인데, 이를 통해 클러스터 운영 과정에서 불필요하게 Pod가 모두 사라지는 상황을 막을 수 있다. 예를 들어 3개의 노드에 Pod가 각각 1개씩 배치되어 있을 때, 노드 2개를 삭제하려는 시도가 있더라도 PB에 최소 2개의 Pod를 유지하라는 조건을 걸어두면 일부는 지워지더라도 나머지는 반드시 남게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HPA가 제대로 동작하기 위해서는 리소스 사용량을 감시할 수 있는 Metrics Server도 필요해서 함께 설치했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;82&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv0xgZ/btsQwH399ql/TlQN83NSwrrTaDLlDtwFZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv0xgZ/btsQwH399ql/TlQN83NSwrrTaDLlDtwFZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv0xgZ/btsQwH399ql/TlQN83NSwrrTaDLlDtwFZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv0xgZ%2FbtsQwH399ql%2FTlQN83NSwrrTaDLlDtwFZk%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;577&quot; height=&quot;82&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Karpenter 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드의 Auto Scaling을 위해 Karpenter를 설치했다.&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;쿠버네티스 초창기에는 Cluster Autoscaler(CA)라는 오픈소스를 사용했다고 한다. 아무래도 오래되었다보니 기본적으로 여러 클라우드 벤더와 호환이 가능하다는 장점이 있지만 새로운 노드를 프로비저닝하기 위해 ASG를 거쳐야 하다보니 상대적으로 좀 느리고 노드 그룹은 하나의 노드 타입과 크기를 정할 수 있다보니 리소스를 낭비한다는 단점이 있다.&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;Karpenter는 AWS가 개발한 오픈소스이며 Kubernetes-Native로 동작한다. Pending Pod를 감지해서 구동할 수 있는 최적화된 노드를 선택해 프로비저닝해준다. CA보다 빠르게 프로비저닝이 트리거되고, CRD를 통해 다양한 노드 타입, 크기 후보군을 정할 수 있어 최적의 노드를 자동으로 선택해 프로비저닝해준다는 장점이 있다. 무엇보다 최근에는 안정화된 버전도 많이 나왔고, AWS에서도 권장하는 방식이라 고민 없이 Karpenter를 도입했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/suaml/btsQAp8t1FT/kQdVc6u7TpgEmM9oT4K8EK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/suaml/btsQAp8t1FT/kQdVc6u7TpgEmM9oT4K8EK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/suaml/btsQAp8t1FT/kQdVc6u7TpgEmM9oT4K8EK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsuaml%2FbtsQAp8t1FT%2FkQdVc6u7TpgEmM9oT4K8EK%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;598&quot; height=&quot;180&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 79 - Karpenter 에러 고치기&amp;nbsp; &amp;amp; 모니터링 환경&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Karpenter 에러 고치기&lt;/h3&gt;
&lt;h4 id=&quot;1.-NodeClass-설정-문제&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;34&quot; data-ke-size=&quot;size20&quot;&gt;1. NodeClass 설정 문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 id=&quot;문제&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;54&quot; data-ke-size=&quot;size20&quot;&gt;문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;증상&lt;/b&gt;: NodeClaim이 생성되지만 NodeClassReady=False 상태 지속&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오류 메시지&lt;/b&gt;: failed to discover any AMIs for alias (alias=al2023@2023.4.20240401.1)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;원인&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;193&quot; data-ke-size=&quot;size20&quot;&gt;원인&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;존재하지 않는 AMI 별칭 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;해결&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;220&quot; data-ke-size=&quot;size20&quot;&gt;해결&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;올바른 AMI 별칭으로 수정: al2023@latest&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-renderer-start-pos=&quot;261&quot; data-ke-size=&quot;size16&quot;&gt;AL2(Amazon Linux 2)의 경우 2025년 11월에 서비스 종료 예정이라 AL2023 사용&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;2.-Bootstrap-스크립트-호환성-문제&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;320&quot; data-ke-size=&quot;size20&quot;&gt;2. Bootstrap 스크립트 호환성 문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 id=&quot;문제.1&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;346&quot; data-ke-size=&quot;size20&quot;&gt;문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;증상&lt;/b&gt;: EC2 인스턴스는 실행되지만 EKS 클러스터에 조인 실패&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오류 메시지&lt;/b&gt;: bootstrap.sh has been removed from AL2023-based EKS AMIs&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;원인.1&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;459&quot; data-ke-size=&quot;size20&quot;&gt;원인&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Amazon Linux 2023에서는 bootstrap.sh 대신 nodeadm 사용&lt;/li&gt;
&lt;li&gt;기존 AL2 방식의 UserData 스크립트가 AL2023에서 작동하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;해결.1&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;562&quot; data-ke-size=&quot;size20&quot;&gt;해결&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UserData를 완전히 제거하여 Karpenter가 자동으로 nodeadm 설정 생성하도록 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3.-IAM-권한-문제&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;626&quot; data-ke-size=&quot;size20&quot;&gt;3. IAM 권한 문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 id=&quot;문제.2&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;640&quot; data-ke-size=&quot;size20&quot;&gt;문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;증상&lt;/b&gt;: kubelet이 Unauthorized 오류로 EKS API 서버 접근 실패&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오류 메시지&lt;/b&gt;: Unable to register node with API server&quot; err=&quot;Unauthorized&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;원인.2&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;767&quot; data-ke-size=&quot;size20&quot;&gt;원인&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;aws-auth ConfigMap에 Karpenter 노드 IAM 역할이 등록되지 않음&lt;/li&gt;
&lt;li&gt;EKS 클러스터가 Karpenter 노드를 신뢰하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;해결.2&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;860&quot; data-ke-size=&quot;size23&quot;&gt;해결&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;864&quot; data-ke-size=&quot;size16&quot;&gt;aws-auth ConfigMap에 Karpenter 노드 역할 추가&lt;/p&gt;
&lt;h4 id=&quot;4.-DNS-해석-실패-문제&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;907&quot; data-ke-size=&quot;size20&quot;&gt;4. DNS 해석 실패 문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 id=&quot;문제.3&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;924&quot; data-ke-size=&quot;size20&quot;&gt;문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;증상&lt;/b&gt;: Pod에서 외부 DNS 해석 실패&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오류 메시지&lt;/b&gt;: Could not connect to the endpoint URL: &quot;&lt;a href=&quot;https://sts.ap-northeast-2.amazonaws.com/&quot;&gt;https://sts.ap-northeast-2.amazonaws.com/&lt;/a&gt;&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트 결과&lt;/b&gt;: curl: (28) Resolving timed out after 5000 milliseconds&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;원인.3&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;1116&quot; data-ke-size=&quot;size20&quot;&gt;원인&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Karpenter 노드에서 CoreDNS Pod로의 UDP 53 포트 통신이 보안그룹에서 차단됨&lt;/li&gt;
&lt;li&gt;CoreDNS는 관리형 노드에만 배포되어 있었고, Karpenter 노드에서 DNS 쿼리가 실패&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;해결.3&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;1236&quot; data-ke-size=&quot;size20&quot;&gt;해결&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot;&gt;Terraform 보안그룹에 DNS 포트 추가&lt;/span&gt;&lt;/p&gt;
&lt;h4 id=&quot;5.-Karpenter-Pod-안정성-문제&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;1565&quot; data-ke-size=&quot;size20&quot;&gt;5. Karpenter Pod 안정성 문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 id=&quot;문제.4&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;1590&quot; data-ke-size=&quot;size20&quot;&gt;문제&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;증상&lt;/b&gt;: Karpenter Pod가 CrashLoopBackOff 상태로 재시작 반복&lt;/li&gt;
&lt;li&gt;&lt;b&gt;원인&lt;/b&gt;: Pod Anti-Affinity 규칙으로 인해 동일 노드에 여러 Pod 배치 불가&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;해결.4&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;1699&quot; data-ke-size=&quot;size20&quot;&gt;해결&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Karpenter deployment replicas를 1로 조정하여 안정성 확보&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CloudWatch Agent 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메트릭 수집과 모니터링 환경을 구성하기 위해 CloudWatch를 사용하기로 했다.&amp;nbsp;&lt;br /&gt;EKS Addon 중에 CloudWatch Observability를 설치하면 CloudWatch Agent와 FluentBit가 같이 설치되는데, 이를 통해 메트릭을 수집하고 모니터링 환경을 구성할 수 있다.&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분 넘게 기다린 후에 명령어로 메트릭 수집 현황을 확인해봤는데 아주 대표적인 값들도 수집이 안되고 있어서 당황했다. 처음엔 권한이 부족해서 생긴 문제였고, 두번째는 내가 메트릭 수집 확인하는 명령어를 공홈에서 그대로 가져와서 사용해서 확인이 안된 문제였다....  빨리 끝내고 싶은 마음에 좀 많이 서둘렀나보다 ㅠㅠ 다행히 권한과 명령어를 바로잡고 나니 메트릭 수집이 잘 되었고, CloudWatch Container Insights 대시보드도 정상적으로 구성되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blzxcX/btsQzf6kH95/VQztcvKiMKBUOlMYeHvwW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blzxcX/btsQzf6kH95/VQztcvKiMKBUOlMYeHvwW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blzxcX/btsQzf6kH95/VQztcvKiMKBUOlMYeHvwW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblzxcX%2FbtsQzf6kH95%2FVQztcvKiMKBUOlMYeHvwW1%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;570&quot; height=&quot;317&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;774&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;아키텍처 다이어그램 수정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 크게 바뀔 부분은 없었지만, EKS 내부 구성을 조금 더 반영해야 해서 수정 작업이 필요했다. 프로젝트 일정이 바쁘다 보니 멘토링 전날 밤늦게까지 급히 작업을 했고, 그 덕분에 자격증 공부는 거의 못 했다  그래도 다이어그램이 정리되니 마음은 한결 놓였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tfHpM/btsQyErSgNv/96zPSD8jyNKvLKZWWoOHdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tfHpM/btsQyErSgNv/96zPSD8jyNKvLKZWWoOHdK/img.png&quot; data-alt=&quot;다운로드 시간으로 볼 수 있는 야근(?)시간&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tfHpM/btsQyErSgNv/96zPSD8jyNKvLKZWWoOHdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtfHpM%2FbtsQyErSgNv%2F96zPSD8jyNKvLKZWWoOHdK%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;429&quot; height=&quot;58&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다운로드 시간으로 볼 수 있는 야근(?)시간&lt;/figcaption&gt;
&lt;/figure&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/TI5Rc/btsQyopjpcc/CYFJVagpJAYKyad9GnBn21/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TI5Rc/btsQyopjpcc/CYFJVagpJAYKyad9GnBn21/img.jpg&quot; data-origin-width=&quot;5333&quot; data-origin-height=&quot;3000&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TI5Rc/btsQyopjpcc/CYFJVagpJAYKyad9GnBn21/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTI5Rc%2FbtsQyopjpcc%2FCYFJVagpJAYKyad9GnBn21%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;5333&quot; height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCcZ5y/btsQx6Cpby6/gELLkVLTTG4gKt5KtuWdY1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCcZ5y/btsQx6Cpby6/gELLkVLTTG4gKt5KtuWdY1/img.jpg&quot; data-origin-width=&quot;5333&quot; data-origin-height=&quot;3000&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCcZ5y/btsQx6Cpby6/gELLkVLTTG4gKt5KtuWdY1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCcZ5y%2FbtsQx6Cpby6%2FgELLkVLTTG4gKt5KtuWdY1%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;5333&quot; height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 80 - 멘토링 &amp;amp; 모의면접&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;멘토링 피드백&lt;/h3&gt;
&lt;h4 id=&quot;CI/CD-전략&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;1&quot; data-ke-size=&quot;size20&quot;&gt;CI/CD 전략&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;도입 툴:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ArgoCD: GitOps 기반 배포 관리에 활용&lt;/li&gt;
&lt;li&gt;Github Actions: 익숙하고 빠르게 파이프라인 구성 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;추가-고려사항&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;91&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추가 고려사항&lt;/b&gt;&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 팀처럼 시연 영상 준비 (검증 &amp;amp; 공유 목적)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;IaC-(Terraform)-관리-범위&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;134&quot; data-ke-size=&quot;size20&quot;&gt;IaC (Terraform) 관리 범위&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;157&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;관리 범위:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로 네트워크 리소스 + EKS 클러스터 생성까지만 Terraform으로 관리 (멘토님 의견)&lt;/li&gt;
&lt;li&gt;그 외 어플리케이션 레벨 리소스는 Helm, ArgoCD 등으로 분리 관리 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;274&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문서화 &amp;amp; 자동화:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Terraform 내에서 Markdown 활용 &amp;rarr; 코드 변경 시 문서 자동 반영&lt;/li&gt;
&lt;li&gt;문서/코드 동기화 관리로 유지보수성 향상&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모의면접&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난번에 받았던 피드백을 반영해 프로젝트별 설명을 보강했고, 자유 양식으로 포트폴리오를 작성해 준비했다. 취업용 사진도 새로 찍어서 첨부했는데, SAA 자격증을 땄다면 더 좋았을 텐데라는 아쉬움이 남았다. 프로젝트 과정에서 예상치 못한 에러가 자주 발생하다 보니, 교육이 끝나는 오후 6시 이후에도 문제를 파악하고 해결하는 데 시간을 거의 다 쓰게 되었고, 그만큼 자격증 공부에 투자할 시간이 부족했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 이번에 지원한 에스넷 그룹의 채용 공고에는 클라우드나 개발자 직무가 없어서, 내가 진행한 프로젝트 내용을 크게 어필할 기회가 없었던 것 같다. 관련 직무 공고가 하루빨리 올라오기를 바랄 수밖에 없다. 면접에서 간단한 기술 질문도 받았는데, 대답을 하다 보니 조금 두서 없이 말하게 된 것 같아 아쉬움이 남았다. 확실히 머릿속으로 공부한 내용과 실제로 말로 풀어내는 것은 차이가 크다는 걸 다시 한번 느꼈다. 이제는 클라우드 관련 기술 면접에 대해서도 본격적으로 대비해야겠다고 다짐하게 되었다. .&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✍️ 주간 회고&lt;/h2&gt;
&lt;p data-end=&quot;305&quot; data-start=&quot;76&quot; data-ke-size=&quot;size16&quot;&gt;이번 주는 문제 상황이 생겨도 빠르게 원인을 파악하고 해결해나가면서, 계획했던 일들을 대부분 해낼 수 있었다는 점에서 나름 성과가 있었다. 다만 Prometheus와 Grafana로 모니터링 환경을 끝내 구축하지 못한 건 정말 아쉽게 남는다. 이미 한 차례 실패를 경험했던 터라 프로젝트가 얼마 남지 않은 지금, 다시 도전하기에는 부담이 컸다. 그래서 안정적인 진행을 위해 무리한 시도는 하지 않기로 했다.&lt;/p&gt;
&lt;p data-end=&quot;305&quot; data-start=&quot;76&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;644&quot; data-start=&quot;307&quot; data-ke-size=&quot;size16&quot;&gt;요구사항은 어느 정도 충족해 나가고 있지만 아직 해야 할 일들이 많이 남아 있다. 특히 EFK 스택 구축과 CI/CD 파이프라인 정리, 발표 준비까지 고려하면 평일 기준 7일밖에 남지 않은 일정이 상당히 촉박하게 느껴진다. 게다가 다음 주 일요일에는 네트워크 관리사 2급 실기 시험까지 예정되어 있어 프로젝트와 자격증 시험, 그리고 하반기 채용 준비가 한꺼번에 맞물려 하루 종일 책상 앞을 지켜야 하는 상황이다. 체력적으로도 정신적으로도 쉽지 않지만, 남은 며칠만 더 집중해서 버티고 하루 이틀 정도는 꼭 쉬어야겠다고 마음먹었다. 이후에는 다시 SAA와 CKA 자격증 준비에 집중해 나갈 계획이다.&lt;/p&gt;</description>
      <category>TIL</category>
      <category>CloudWatch</category>
      <category>EKS</category>
      <category>HPA</category>
      <category>karpenter</category>
      <category>TiL</category>
      <category>멀티캠퍼스it부트캠프</category>
      <category>부트캠프후기</category>
      <category>에스넷시스템 부트캠프</category>
      <category>클라우드 활용 네트워크 엔지니어 부트캠프</category>
      <category>프로젝트</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/181</guid>
      <comments>https://yulee.tistory.com/181#entry181comment</comments>
      <pubDate>Fri, 12 Sep 2025 21:56:48 +0900</pubDate>
    </item>
    <item>
      <title>[에스넷시스템 부트캠프] TIL Day 72~75 - 프로젝트 6주차</title>
      <link>https://yulee.tistory.com/180</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 72 - 추가 학습&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bib5Nu/btsQnYyttza/2UmPQWrnKkkr86vZDPhGz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bib5Nu/btsQnYyttza/2UmPQWrnKkkr86vZDPhGz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bib5Nu/btsQnYyttza/2UmPQWrnKkkr86vZDPhGz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbib5Nu%2FbtsQnYyttza%2F2UmPQWrnKkkr86vZDPhGz1%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;674&quot; height=&quot;312&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 설정 과정에서 내가 놓친 부분이 있을까 싶어, 교육 과정 중 받았던 책을 다시 펼쳐보았다. 앞부분의 이론 위주로 읽으며 헷갈리는 부분은 따로 Notion에 정리했고, EKS Cluster 구성에서 수정할 만한 부분이 있는지도 고민해보았다. 책을 보기 전에 Ingress 부분이 조금 헷갈렸는데 개념을 정리할 수 있는 좋은 기회였다.&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #292a2e; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 73 - &lt;span style=&quot;background-color: #ffffff; color: #292a2e; text-align: left;&quot;&gt;문서화&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292a2e; text-align: left;&quot;&gt;Outputs 파일 수정하기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Terraform의 outputs.tf 파일을 보완했다.&lt;br /&gt;기존에는 단순히 VPC 정보 정도만 출력했지만, Terraform을 사용하는 만큼 리소스의 ARN, 이름, ID 같은 필수 정보를 바로 확인할 수 있도록 output을 추가했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;366&quot; data-start=&quot;329&quot;&gt;terraform output으로 전체 정보를 확인 가능&lt;/li&gt;
&lt;li data-end=&quot;391&quot; data-start=&quot;367&quot;&gt;특정 리소스만 지정해서 볼 수도 있음&lt;/li&gt;
&lt;li data-end=&quot;485&quot; data-start=&quot;392&quot;&gt;단, 지정하려면 outputs.tf에 정의된 리소스명을 알아야 하지만 &amp;rarr; Ctrl+F나 VS Code 개요 기능으로 쉽게 찾을 수 있&lt;/li&gt;
&lt;/ul&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 style=&quot;background-color: #ffffff; color: #292a2e; text-align: left;&quot;&gt;EKS 구성 문서화&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dn5MgQ/btsQryq4wUq/rYGkk1xevn3BsSkOmMJbf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dn5MgQ/btsQryq4wUq/rYGkk1xevn3BsSkOmMJbf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dn5MgQ/btsQryq4wUq/rYGkk1xevn3BsSkOmMJbf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdn5MgQ%2FbtsQryq4wUq%2FrYGkk1xevn3BsSkOmMJbf1%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;440&quot; height=&quot;364&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀원들과 공유하기 위해 EKS Cluster 내부에 생성한 리소스에 대한 문서를 작성했다.&lt;br /&gt;ServiceAccount와 연결된 IAM Role, Deployment 구성 방식 등을 다시 점검하면서, 동시에 전체 구조를 다시 한 번 정리할 수 있었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 74 - 네트워킹 및 외부 노출 설정하기&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;External-DNS 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 조회용 서비스의 Pod를 외부에 노출하기 위해 External-DNS를 설치했다.&lt;br /&gt;External-DNS는 Route53 같은 Public DNS 서비스에 자동으로 레코드를 생성&amp;middot;관리해주어, 내부 클러스터 리소스와 외부 도메인을 연결하는 작업을 단순화한다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;External-DNS 파드가 Route53에 접근할 수 있도록 IAM 역할 생성&lt;/li&gt;
&lt;li&gt;Route53 호스팅 존에 대한 읽기/쓰기 권한 부여&lt;/li&gt;
&lt;li&gt;ServiceAccount를 통해 권한 연결&lt;/li&gt;
&lt;li&gt;helm을 이용해 External-DNS 설치 및 환경 변수 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AWS Load Balancer Controller 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ingress와 Service 리소스를 AWS ALB로 프로비저닝하기 위해 AWS Load Balancer Controller도 함께 설치했다.&lt;br /&gt;이 컨트롤러가 데이터 조회용 서비스들을 위한 ALB를 생성하고, ALB DNS Name을 발급하여 내부 Pod로 트래픽을 로드밸런싱한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ALB의 DNS Name은 동적으로 변경될 수 있기 때문에, External-DNS가 이를 감지해 Route53 레코드를 자동 업데이트하도록 했다. 이제 외부 사용자는 고정된 도메인 주소를 통해 안정적으로 내부 서비스를 이용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;115&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vRoyH/btsQqrlRyk6/ZCIVg7KWUOMRAEX1KNZGK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vRoyH/btsQqrlRyk6/ZCIVg7KWUOMRAEX1KNZGK0/img.png&quot; data-alt=&quot;External-DNS와 AWS Load Balancer Controller 설치된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vRoyH/btsQqrlRyk6/ZCIVg7KWUOMRAEX1KNZGK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvRoyH%2FbtsQqrlRyk6%2FZCIVg7KWUOMRAEX1KNZGK0%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;538&quot; height=&quot;115&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;115&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;External-DNS와 AWS Load Balancer Controller 설치된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 75 - 모니터링 환경 구성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 목표는 Prometheus + Grafana 기반의 모니터링 환경 구축이었다. 여기에 더해 Prometheus 메트릭 데이터를 장기 저장하기 위해 EBS를 붙이고, EBS 생성을 위한 CSI Driver를 설치하려고 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;260&quot; data-start=&quot;249&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;진행 내용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;585&quot; data-start=&quot;261&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;361&quot; data-start=&quot;261&quot;&gt;&lt;b&gt;EBS 생성 &amp;rarr; 실패&lt;/b&gt;&lt;br /&gt;CSI Driver 설치까지 시도했지만 EBS 생성 단계에서 막혀버렸다. 원인은 아직 명확히 못 잡았고, 다음주에 다시 시도할 예정이다.&lt;/li&gt;
&lt;li data-end=&quot;500&quot; data-start=&quot;363&quot;&gt;&lt;b&gt;Prometheus + Grafana 설치 &amp;rarr; 성공&lt;/b&gt;&lt;br /&gt;Helm 차트 덕분에 repo 추가 후 비교적 간단히 설치할 수 있었다.&lt;br /&gt;다만 마지막 Pod가 Pending 상태로 남아 있어, 이 부분은 추후 확인이 필요하다.&lt;/li&gt;
&lt;li data-end=&quot;585&quot; data-start=&quot;502&quot;&gt;&lt;b&gt;결과&lt;/b&gt;&lt;br /&gt;EBS 추가는 포기했지만, Prometheus와 Grafana만으로도 기본적인 리소스 메트릭이 잘 수집되는 것을 확인했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNjHUV/btsQqE6oii4/BvME2r6zDlF1ljzLKZ8ZtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNjHUV/btsQqE6oii4/BvME2r6zDlF1ljzLKZ8ZtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNjHUV/btsQqE6oii4/BvME2r6zDlF1ljzLKZ8ZtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNjHUV%2FbtsQqE6oii4%2FBvME2r6zDlF1ljzLKZ8ZtK%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;570&quot; height=&quot;165&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1Wtys/btsQpXkSyDs/oKNozphdZZAo095mrKY9ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1Wtys/btsQpXkSyDs/oKNozphdZZAo095mrKY9ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1Wtys/btsQpXkSyDs/oKNozphdZZAo095mrKY9ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1Wtys%2FbtsQpXkSyDs%2FoKNozphdZZAo095mrKY9ik%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;741&quot; height=&quot;256&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DrQOR/btsQroaV2Hz/4FAKE9X24wotDo0ditHLIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DrQOR/btsQroaV2Hz/4FAKE9X24wotDo0ditHLIK/img.png&quot; data-alt=&quot;마지막 Pod가 pending 상태... 이건 다음에 해결하는걸로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DrQOR/btsQroaV2Hz/4FAKE9X24wotDo0ditHLIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDrQOR%2FbtsQroaV2Hz%2F4FAKE9X24wotDo0ditHLIK%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;620&quot; height=&quot;189&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마지막 Pod가 pending 상태... 이건 다음에 해결하는걸로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;928&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GJTlw/btsQrvnA8Qp/Yp5lkNmC32eirIuwko7Qo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GJTlw/btsQrvnA8Qp/Yp5lkNmC32eirIuwko7Qo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GJTlw/btsQrvnA8Qp/Yp5lkNmC32eirIuwko7Qo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGJTlw%2FbtsQrvnA8Qp%2FYp5lkNmC32eirIuwko7Qo1%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;556&quot; height=&quot;619&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;928&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;휴일 추가 진행 사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링 환경을 구성하지 못했다는 점이 너무 아쉬워서 교육 과정일이 아니었음에도 프로젝트를 진행했다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 : Grafana에서 Prometheus 데이터소스 연결 실패&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;prometheus로 시작하는 도메인명으로 연결되지 않고, IP 주소로만 연결이 되는 문제점을 발견했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;External-DNS가 작동하기에 도메인으로 접근이 가능해야 하는데, 도메인 해석이 되지 않았던 것이다.&amp;nbsp;&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;원인&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;293&quot; data-start=&quot;236&quot;&gt;External-DNS 로그 확인 결과: sts.amazonaws.com 접속 실패.&lt;/li&gt;
&lt;li data-end=&quot;349&quot; data-start=&quot;294&quot;&gt;IRSA 인증 과정에서 STS 접근을 통해 임시 토큰을 발급받아야 하는데 이 단계에서 막힘.&lt;/li&gt;
&lt;li data-end=&quot;403&quot; data-start=&quot;350&quot;&gt;즉, Private Subnet에 위치한 노드들이 인터넷에 접근하지 못하는 문제.&lt;/li&gt;
&lt;li data-end=&quot;486&quot; data-start=&quot;404&quot;&gt;NAT Instance를 이용한 인터넷 연결 구조였으나, Pod &amp;harr; NAT Instance 간의 연결이 불안정해 정상적으로 작동하지 않았음.&lt;/li&gt;
&lt;li data-end=&quot;553&quot; data-start=&quot;487&quot;&gt;이전에는 정상 동작했으나 하루아침에 문제가 발생 &amp;rarr; 불안정한 NAT Instance 기반 설계임을 확인.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;563&quot; data-start=&quot;555&quot; data-ke-size=&quot;size20&quot;&gt;해결&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;774&quot; data-start=&quot;564&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;634&quot; data-start=&quot;564&quot;&gt;팀원들이 이미 EIP를 최대치로 사용 중이라 NAT Gateway 대신 NAT Instance를 사용했던 상황.&lt;/li&gt;
&lt;li data-end=&quot;681&quot; data-start=&quot;635&quot;&gt;불필요한 EIP 삭제를 팀원들에게 부탁했고, 팀원들이 협조해주어 삭제 완료.&lt;/li&gt;
&lt;li data-end=&quot;720&quot; data-start=&quot;682&quot;&gt;이를 통해 NAT Gateway 생성 가능 상태 확보.&lt;/li&gt;
&lt;li data-end=&quot;774&quot; data-start=&quot;721&quot;&gt;이후 월요일부터 NAT Gateway를 새로 생성하고 모니터링 환경을 다시 구성할 예정.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉬는 날임에도 팀원들이 메시지를 확인해주어 리소스 삭제를 해주어서 다행이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음주에 있을 자격증 시험 준비로 주말에는 프로젝트를 진행하지 못하겠지만 다음주 월요일부터 바로 NAT Gateway를 생성해 다시 모니터링 환경을 구성해볼 수 있어 다행이었다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✍️ 주간 회고&lt;/h2&gt;
&lt;p data-end=&quot;288&quot; data-start=&quot;64&quot; data-ke-size=&quot;size16&quot;&gt;이번 주는 정말 삽질의 연속이었다. Grafana에서 Prometheus 데이터소스 연결 실패 문제는 상황 파악과 원인 분석이 비교적 명확해서 &quot;곧 해결할 수 있겠다&quot;는 자신감이 들었지만, EBS 추가 문제는 정확히 어디에서 막히는지 원인을 잡지 못해 답답한 마음이 컸다. 다음주 월요일까지만 다시 시도해보고, 그래도 안되면 강사님께 도움을 요청해야 할 것 같다.&lt;/p&gt;
&lt;p data-end=&quot;288&quot; data-start=&quot;64&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;477&quot; data-start=&quot;290&quot; data-ke-size=&quot;size16&quot;&gt;비록 원하는 만큼 결과를 내진 못했지만, 이번 주는 Kubernetes를 한층 더 깊이 이해하게 된 시간이었다. 단순히 이론으로 &quot;아 그렇구나&quot; 하고 넘어가는 게 아니라, 직접 구성해보고 문제를 마주하면서 내부 동작 원리를 더 확실히 알 수 있었다. 문제 상황 속에서 배우는 게 많았고, 이 과정이 결국 내 실력이 될 거라 믿는다.&lt;/p&gt;</description>
      <category>TIL</category>
      <category>aws load balancer controller</category>
      <category>External-DNS</category>
      <category>Ingress</category>
      <category>Monitoring</category>
      <category>service</category>
      <category>TiL</category>
      <category>멀티캠퍼스it부트캠프</category>
      <category>부트캠프후기</category>
      <category>에스넷시스템 부트캠프</category>
      <category>클라우드 활용 네트워크 엔지니어 부트캠프</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/180</guid>
      <comments>https://yulee.tistory.com/180#entry180comment</comments>
      <pubDate>Thu, 4 Sep 2025 22:32:35 +0900</pubDate>
    </item>
    <item>
      <title>[에스넷시스템 부트캠프] TIL Day 67~71 - 프로젝트 5주차</title>
      <link>https://yulee.tistory.com/179</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 67 - CDN 에러 고치기 &amp;amp; Terraform 인프라 문서화&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Route53과 CloudFront 연동 확인&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mbbN4/btsQc7hEm2Q/Q3KL0O79ZWgswleKPIc8rK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mbbN4/btsQc7hEm2Q/Q3KL0O79ZWgswleKPIc8rK/img.png&quot; data-origin-width=&quot;2244&quot; data-origin-height=&quot;1090&quot; data-is-animation=&quot;false&quot; width=&quot;597&quot; height=&quot;290&quot; style=&quot;width: 62.9375%; margin-right: 10px;&quot; data-widthpercent=&quot;63.68&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mbbN4/btsQc7hEm2Q/Q3KL0O79ZWgswleKPIc8rK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmbbN4%2FbtsQc7hEm2Q%2FQ3KL0O79ZWgswleKPIc8rK%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;2244&quot; height=&quot;1090&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biV1PY/btsQdyGtRLY/J7XTjpPC5Us5rVDWZqwNGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biV1PY/btsQdyGtRLY/J7XTjpPC5Us5rVDWZqwNGk/img.png&quot; data-origin-width=&quot;1334&quot; data-origin-height=&quot;1136&quot; data-is-animation=&quot;false&quot; width=&quot;582&quot; height=&quot;496&quot; style=&quot;width: 35.8997%;&quot; data-widthpercent=&quot;36.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biV1PY/btsQdyGtRLY/J7XTjpPC5Us5rVDWZqwNGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiV1PY%2FbtsQdyGtRLY%2FJ7XTjpPC5Us5rVDWZqwNGk%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;1334&quot; height=&quot;1136&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;가비아에서 도메인 구매!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 사용하려던 도메인은 팀원이 내도메인한글 무료 서비스에서 발급받은 것이었다.&lt;br /&gt;처음 계획대로라면 Route53에 Hosted Zone을 만들고 네임서버를 AWS로 변경해야 했는데, 문제는 내도메인한글에서는 네임서버 변경 기능을 제공하지 않는다는 점이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;451&quot; data-start=&quot;287&quot; data-ke-size=&quot;size16&quot;&gt;다행히 빠르게 원인을 파악했고, 오래 고민하지 않고 바로 가비아에서 550원을 결제해 도메인을 구입했다. 이후 Route53에 도메인을 등록하고 네임서버도 AWS로 변경 완료. 중간중간 테스트를 하면서 기다렸는데, 약 4~5시간 정도 뒤에 정상적으로 도메인 접속이 가능해졌다.&lt;/p&gt;
&lt;p data-end=&quot;520&quot; data-start=&quot;453&quot; 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;897&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QFhCp/btsQfl6Rkjv/OJ79L9hyvbCkKU6LKpzGl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QFhCp/btsQfl6Rkjv/OJ79L9hyvbCkKU6LKpzGl1/img.png&quot; data-alt=&quot;도메인 연결 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QFhCp/btsQfl6Rkjv/OJ79L9hyvbCkKU6LKpzGl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQFhCp%2FbtsQfl6Rkjv%2FOJ79L9hyvbCkKU6LKpzGl1%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;767&quot; height=&quot;246&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도메인 연결 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Terraform 인프라 문서화 (Confluence)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5ZvEh/btsQdXZU8qx/F5s85NyWkrlUzYHvV3RSak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5ZvEh/btsQdXZU8qx/F5s85NyWkrlUzYHvV3RSak/img.png&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;1090&quot; data-is-animation=&quot;false&quot; width=&quot;580&quot; height=&quot;428&quot; style=&quot;width: 46.3415%; margin-right: 10px;&quot; data-widthpercent=&quot;46.89&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5ZvEh/btsQdXZU8qx/F5s85NyWkrlUzYHvV3RSak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5ZvEh%2FbtsQdXZU8qx%2FF5s85NyWkrlUzYHvV3RSak%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;1090&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwvRic/btsQeSDT9jO/61Eu4t3kGgWB4Q2Ul6Kesk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwvRic/btsQeSDT9jO/61Eu4t3kGgWB4Q2Ul6Kesk/img.png&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;854&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.4957%;&quot; data-widthpercent=&quot;53.11&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwvRic/btsQeSDT9jO/61Eu4t3kGgWB4Q2Ul6Kesk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwvRic%2FbtsQeSDT9jO%2F61Eu4t3kGgWB4Q2Ul6Kesk%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;1310&quot; height=&quot;854&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Terraform으로 구축한 인프라를 팀원들이 한눈에 볼 수 있도록 Confluence에 문서화했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;781&quot; data-start=&quot;627&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;680&quot; data-start=&quot;627&quot;&gt;코드 레벨에서 정의된 리소스뿐만 아니라, 실제 AWS 상에서 생성된 리소스 이름까지 정리&lt;/li&gt;
&lt;li data-end=&quot;781&quot; data-start=&quot;681&quot;&gt;단순 코드(output.tf 등)로 확인할 수 있는 내용도 있지만, 문서로 풀어내니 프로젝트 보고서 느낌이 나서 팀 공유와 향후 발표 자료로 활용하기 적합하다고 생각&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;911&quot; data-start=&quot;783&quot; data-ke-size=&quot;size16&quot;&gt;다만, 이미 어느 정도 인프라 구성을 마친 상태에서 문서화를 하다 보니 시간이 꽤 걸렸다.&lt;br /&gt;&amp;ldquo;미리 조금씩 해둘걸&amp;hellip;&amp;rdquo; 하는 후회도 있었지만, 그만큼 이번 정리가 앞으로 팀 협업과 프로젝트 관리에서 큰 도움이 될 거라 믿는다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 68 - 백엔드 코드 인프라 환경 반영&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 기존에 만들어둔 백엔드 애플리케이션을 인프라 환경에 맞게 수정하는 작업을 진행했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;251&quot; data-start=&quot;138&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;179&quot; data-start=&quot;138&quot;&gt;환경 변수 세팅: 인프라에서 필요로 하는 환경 변수들을 코드에 반영&lt;/li&gt;
&lt;li data-end=&quot;251&quot; data-start=&quot;180&quot;&gt;불필요한 디버그 출력 정리: 개발 단계에서만 쓰던 디버그용 로그들이 많아 가독성을 해치고 있었는데, 이참에 깔끔하게 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;354&quot; data-start=&quot;253&quot; data-ke-size=&quot;size16&quot;&gt;수정이 끝난 뒤에는 로컬 환경에서 충분히 테스트를 거쳤다. 기능적으로 큰 문제 없이 동작하는 것을 확인한 후, Docker 이미지를 빌드해 DockerHub에 업로드했다.&lt;/p&gt;
&lt;p data-end=&quot;437&quot; data-start=&quot;356&quot; data-ke-size=&quot;size16&quot;&gt;이제 본격적으로 EKS 환경에 이 이미지를 배포하면 된다. 드디어 인프라와 애플리케이션이 맞닿는 지점에 도착한 것 같아 긴장되면서도 기대된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 69 - 멘토링 &amp;amp; 모의면접&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현업자 멘토링&lt;/h3&gt;
&lt;h4 id=&quot;EKS-노드-구성-전략&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;1&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;EKS 노드 구성 전략&lt;/b&gt;&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. &lt;/b&gt;Multi-AZ 2개 노드 vs 단일 AZ + 오토스케일링?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비용 중심: 단일 AZ + 오토스케일링 방식&lt;/li&gt;
&lt;li&gt;실시간성 중요: Multi-AZ 구성으로 즉시 failover&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;121&quot; data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 상황에 맞게 결정&lt;/p&gt;
&lt;h4 id=&quot;오토스케일링-설정&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;135&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;오토스케일링 설정&lt;/b&gt;&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지표 설정: 정답은 없음, 프로젝트별 맞춤 설정 필요&lt;/li&gt;
&lt;li&gt;노드 추가 시간: 일반적으로 5-10분 소요&lt;/li&gt;
&lt;li&gt;개선 방안:
&lt;ul style=&quot;list-style-type: circle;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;여유 노드 미리 배치 (비용 vs 성능 트레이드오프)&lt;/li&gt;
&lt;li&gt;EKS 관련 기능 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;기본 지표: EC2의 CPU, 메모리 사용량 기준&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;Terraform-운영-팁&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;301&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Terraform &lt;/b&gt;운영 팁&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;317&quot; data-ke-size=&quot;size16&quot;&gt;리소스 삭제&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주석 처리 후&lt;b&gt; &lt;/b&gt;apply&lt;b&gt; &lt;/b&gt;실행 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;350&quot; data-ke-size=&quot;size16&quot;&gt;State 파일 관리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GitHub에 업로드 금지&lt;/li&gt;
&lt;li&gt;공동 작업 시 원격 저장소 활용 필수&lt;/li&gt;
&lt;li&gt;Terraform용&lt;b&gt; &lt;/b&gt;.gitignore 인터넷 참고 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;442&quot; data-ke-size=&quot;size16&quot;&gt;공동 작업&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원격 저장소 사용 시 자동 동기화&lt;/li&gt;
&lt;li&gt;별도 pull 과정 불필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;키-페어-관리&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;491&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;키 페어 관리&lt;/b&gt;&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EC2 접근: 필요 시 별도 생성하여 관리&lt;/li&gt;
&lt;li&gt;고려사항: Terraform 코드 vs 수동 관리 범위 결정 필요&lt;/li&gt;
&lt;li&gt;보안: NAT Instance SSH 접근용 최소 관리자 키 페어 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;프로젝트-관리-도구&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;612&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프로젝트 관리 도구&lt;/b&gt;&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;624&quot; data-ke-size=&quot;size16&quot;&gt;Jira vs Notion&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;심플한 환경: Notion 선호 업체 많음&lt;/li&gt;
&lt;li&gt;인프라 관점: 애자일 스프린트가 꼭 필요한지 재검토&lt;/li&gt;
&lt;li&gt;활용 팁: 각 프로젝트 환경에 맞는 맞춤 설정 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;모의면접&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멘토링 이후에는 모의면접 준비와 진행을 했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1336&quot; data-start=&quot;1205&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1236&quot; data-start=&quot;1205&quot;&gt;준비: 자기소개 여러 번 리허설, 예상 질문 정리&lt;/li&gt;
&lt;li data-end=&quot;1281&quot; data-start=&quot;1237&quot;&gt;진행: 약 10~15분, 기술 면접보다는 인성 면접에 가까운 느낌&lt;/li&gt;
&lt;li data-end=&quot;1336&quot; data-start=&quot;1282&quot;&gt;결과: 자기소개에서 긴장해 살짝 꼬였지만, 이후 질문에는 솔직하게 잘 답변했다고 생각한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;1354&quot; data-start=&quot;1338&quot; data-ke-size=&quot;size20&quot;&gt;면접 피드백&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1520&quot; data-start=&quot;1355&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1412&quot; data-start=&quot;1355&quot;&gt;개선할 점: 프로젝트별로 내 역할과 수행 과정을 Notion/블로그에 정리해둘 것&lt;/li&gt;
&lt;li data-end=&quot;1520&quot; data-start=&quot;1413&quot;&gt;자격증: AWS SAA 취득 강력 추천
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1520&quot; data-start=&quot;1445&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1470&quot; data-start=&quot;1445&quot;&gt;이미 강의를 듣고 있었지만 진도가 느림&lt;/li&gt;
&lt;li data-end=&quot;1520&quot; data-start=&quot;1473&quot;&gt;하반기 채용 시즌 대비, 강의보다는 기출 풀이 중심으로 학습 전략 전환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1584&quot; data-start=&quot;1522&quot; data-ke-size=&quot;size16&quot;&gt;면접이 끝난 뒤에는 자격증 로드맵과 채용 공고를 다시 살펴보며 앞으로의 계획을 조금 더 디테일하게 수정했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 70 - Kubernetes 리소스 배포&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 Kubernetes 클러스터에 애플리케이션을 실제로 배포했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uQTXX/btsQfHonP0n/NqWOMjwBBsNghbZokayEAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uQTXX/btsQfHonP0n/NqWOMjwBBsNghbZokayEAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uQTXX/btsQfHonP0n/NqWOMjwBBsNghbZokayEAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuQTXX%2FbtsQfHonP0n%2FNqWOMjwBBsNghbZokayEAk%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;674&quot; height=&quot;333&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;425&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-end=&quot;208&quot; data-start=&quot;192&quot; data-ke-size=&quot;size23&quot;&gt;데이터 수집 서비스&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;375&quot; data-start=&quot;209&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;245&quot; data-start=&quot;209&quot;&gt;Deployment (replicas=1) 로 배포&lt;/li&gt;
&lt;li data-end=&quot;299&quot; data-start=&quot;246&quot;&gt;추가로 CronJob을 설정해 10분마다 뉴스 수집 작업이 실행되도록 구성&lt;/li&gt;
&lt;li data-end=&quot;375&quot; data-start=&quot;300&quot;&gt;  Replicas를 1로 제한한 이유는, 여러 파드가 동시에 실행될 경우 데이터가 중복 수집되는 문제를 방지하기 위함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;393&quot; data-start=&quot;377&quot; data-ke-size=&quot;size23&quot;&gt;데이터 조회 서비스&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;497&quot; data-start=&quot;394&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;430&quot; data-start=&quot;394&quot;&gt;Deployment (replicas=3) 로 배포&lt;/li&gt;
&lt;li data-end=&quot;497&quot; data-start=&quot;431&quot;&gt;조회 요청은 동시에 여러 사용자에게서 들어올 수 있으므로, 가용성과 부하 분산을 위해 3개의 파드로 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 71 - 백엔드 코드 또또수정&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불필요한 API 삭제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바이브 코딩으로 진행하다 보니 애플리케이션에 불필요한 API가 남아있었다. 코드의 복잡성을 줄이고 유지보수성을 높이기 위해 불필요한 API들을 과감히 삭제했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 중복 수집 방지 로직 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 수집 서비스는 Pod 1개만 띄웠는데 생각해보니 API 수행만으로도 데이터 중복이 생길 수 있었다. 최대한 애플리케이션 코드를 수정하고 싶지 않았지만 어쩔 수 없이 애플리케이션 레벨에서 중복 수집 방지를 위한 로직을 추가해야했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DynamoDB에 저장되어 있는 뉴스 아이템 중에서 가장 최신의 pubDate 값보다 수집 API가 수행됐을 때 수집된 뉴스들의 pubDate가 더 최신일 때만 수집하도록 로직을 변경했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권한 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 로직을 수정한 뒤 Docker 이미지로 빌드해서 다시 Kubernetes에 배포했다. 그런데 API 테스트 과정에서 DynamoDB와 S3 권한 에러가 발생했다.&lt;/p&gt;
&lt;p data-end=&quot;362&quot; data-start=&quot;209&quot; data-ke-size=&quot;size16&quot;&gt;원인은 비교적 단순했다. Terraform 코드에서 DynamoDB 정책에 DescribeTable 권한이 빠져 있었고, S3 권한도 일부 부족했던 것이다. 로컬 환경에서는 내 AWS CLI 계정 키를 사용해 권한을 가져오고 있었기 때문에 문제가 드러나지 않았던 것.&lt;/p&gt;
&lt;p data-end=&quot;443&quot; data-start=&quot;364&quot; data-ke-size=&quot;size16&quot;&gt;이왕 정책을 수정하는 김에 서비스별 Role을 새로 만들기로 했다. 멘토링 때 들은 팁대로 기존 Role은 주석 처리 후 삭제했고,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;478&quot; data-start=&quot;445&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;461&quot; data-start=&quot;445&quot;&gt;데이터 수집용 Role&lt;/li&gt;
&lt;li data-end=&quot;478&quot; data-start=&quot;462&quot;&gt;데이터 조회용 Role&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;519&quot; data-start=&quot;480&quot; data-ke-size=&quot;size16&quot;&gt;을 각각 따로 생성한 뒤, 서비스 성격에 맞는 권한만 연결해주었다.&lt;/p&gt;
&lt;p data-end=&quot;660&quot; data-start=&quot;521&quot; data-ke-size=&quot;size16&quot;&gt;결과적으로 권한 문제를 해결했을 뿐 아니라, 최소 권한 원칙(Principle of Least Privilege) 을 지키는 구조로 개선할 수 있었다. 단순한 에러 해결 작업이 아니라, 보안 수준을 한 단계 끌어올린 의미 있는 수정이었다.&lt;/p&gt;
&lt;p data-end=&quot;660&quot; data-start=&quot;521&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;660&quot; data-start=&quot;521&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✍️ 주간 회고&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1265&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LZSoU/btsQdVIjBeF/NDdAZKNuh2qQIFQMTaqEUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LZSoU/btsQdVIjBeF/NDdAZKNuh2qQIFQMTaqEUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LZSoU/btsQdVIjBeF/NDdAZKNuh2qQIFQMTaqEUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLZSoU%2FbtsQdVIjBeF%2FNDdAZKNuh2qQIFQMTaqEUk%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;495&quot; height=&quot;203&quot; data-origin-width=&quot;1265&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주는 공부에 시간을 꽤 많이 썼다. 단순히 AI에게 &amp;ldquo;해줘&amp;rdquo;라고 맡기는 것보다는, 내가 정확한 오더를 내릴 수 있도록 블로그에 정리해둔 글이나 책, 인터넷 자료들을 참고하면서 설계를 진행했다.&lt;/p&gt;
&lt;p data-end=&quot;393&quot; data-start=&quot;259&quot; data-ke-size=&quot;size16&quot;&gt;AI가 생각보다 비효율적인 코드를 짜거나, 내가 요청한 내용을 빠뜨리는 경우가 종종 있었는데, 그럴 때마다 꼼꼼히 점검하는 게 얼마나 중요한지 다시 느꼈다. 솔직히 귀찮을 때도 있었지만, 내가 더 단단해지고 있다는 생각이 들어 뿌듯했다.&lt;/p&gt;
&lt;p data-end=&quot;393&quot; data-start=&quot;259&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;578&quot; data-start=&quot;395&quot; data-ke-size=&quot;size16&quot;&gt;다음 주에는 Pod들이 잘 올라가고 API들이 정상적으로 동작하는지 확인하는 걸 먼저 하고, 이어서 프론트 API 경로 수정, HA 테스트, 모니터링 환경 구축까지 진행할 계획이다. 욕심 같아서는 CI/CD도 이번 주 내에 구축해보고 싶지만, 현실적으로는 시간이 빠듯할 수도 있다. 그래도 최대한 달려봐야겠다.&lt;/p&gt;</description>
      <category>TIL</category>
      <category>Kubernetes</category>
      <category>Terraform</category>
      <category>TiL</category>
      <category>멀티캠퍼스it부트캠프</category>
      <category>부트캠프후기</category>
      <category>에스넷시스템 부트캠프</category>
      <category>클라우드 활용 네트워크 엔지니어 부트캠프</category>
      <category>프로젝트</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/179</guid>
      <comments>https://yulee.tistory.com/179#entry179comment</comments>
      <pubDate>Sat, 30 Aug 2025 16:28:08 +0900</pubDate>
    </item>
    <item>
      <title>[에스넷시스템 부트캠프] TIL Day 62~66 - 프로젝트 4주차</title>
      <link>https://yulee.tistory.com/178</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 62 - EKS 공부&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;787&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uN8FQ/btsP6gYx9Ai/IAaGMYapgdozwScXK1gCRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uN8FQ/btsP6gYx9Ai/IAaGMYapgdozwScXK1gCRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uN8FQ/btsP6gYx9Ai/IAaGMYapgdozwScXK1gCRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuN8FQ%2FbtsP6gYx9Ai%2FIAaGMYapgdozwScXK1gCRK%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;519&quot; height=&quot;433&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;787&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;246&quot; data-start=&quot;68&quot; data-ke-size=&quot;size16&quot;&gt;최근 Kubernetes 환경에 대한 개념은 어느 정도 익숙해졌지만, AWS에서 제공하는 EKS에 대해서도 알아야겠다는 생각이 들었다. 단순히 문서를 읽는 것도 방법이지만, 이해도를 높이기 위해 AWS Korea 공식 유튜브 채널의 강의를 시청했다.&lt;/p&gt;
&lt;p data-end=&quot;246&quot; data-start=&quot;68&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;391&quot; data-start=&quot;248&quot; data-ke-size=&quot;size16&quot;&gt;강의를 통해 Kubernetes의 전체적인 개념을 다시 복습할 수 있었고, EKS가 제공하는 기능과 AWS 환경에서 어떤 방식으로 활용할 수 있는지도 배울 수 있었다. 무엇보다도 AWS의 솔루션 아키텍트가 직접 강의하는 내용이라 신뢰도가 높았다.&lt;/p&gt;
&lt;p data-end=&quot;523&quot; data-start=&quot;393&quot; data-ke-size=&quot;size16&quot;&gt;단순히 영상을 시청하는 것에 그치지 않고, 헷갈릴 수 있는 개념들을 언제든 다시 볼 수 있도록 Notion에 정리했다. 이 정리된 내용은 앞으로 실제로 EKS Cluster를 구성할 때 참고 자료로 활용할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 영상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/E49Q3y9wsUo?si=I-OXGG93Hc24Qg7J&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/E49Q3y9wsUo?si=I-OXGG93Hc24Qg7J&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=E49Q3y9wsUo&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/p9Mn5/hyZDahjPO9/Q5csqBhQcSeiRfDfeyg0hK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/HmCI7/hyZC15LQCx/ORiO0rb9EAxEgg7zuQ3S01/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;600&quot; data-video-height=&quot;338&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Amazon EKS 알아보기 - EKS Overview&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/E49Q3y9wsUo&quot; width=&quot;600&quot; height=&quot;338&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 63 - EKS &amp;amp; Terraform 공부&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;EKS 공부 계속하&lt;/h3&gt;
&lt;p data-end=&quot;218&quot; data-start=&quot;99&quot; data-ke-size=&quot;size16&quot;&gt;어제 이어서 EKS 학습을 진행했다. 이번에는 보안과 네트워크 관련된 개념을 접했는데 다소 어렵게 느껴졌다. 이해가 확실치 않은 부분은 생성형 AI를 활용해 내 이해가 맞는지 검증하면서 공부했다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;220&quot; data-ke-size=&quot;size16&quot;&gt;영상 몇 개만으로 EKS를 완전히 이해했다고는 할 수 없지만, 적어도 환경을 구축하는 데 필요한 수준은 갖출 수 있었다. 또한 정리해둔 내용을 주기적으로 복습하면 전체적인 프로세스와 세부 개념을 함께 잡을 수 있을 것 같다.&lt;/p&gt;
&lt;h3 id=&quot;콘솔-기반-관리의-불편함&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;61&quot; data-ke-size=&quot;size23&quot;&gt;콘솔 기반 관리의 불편함&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS 콘솔을 통해 리소스를 직접 관리하면서 몇 가지 불편함을 크게 느꼈다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스를 하나씩 생성하다 보니 이름 규칙을 잊어버려 다시 확인하느라 시간이 소요됨&lt;/li&gt;
&lt;li&gt;여러 리소스를 확인하느라 브라우저 탭만 늘어남&lt;/li&gt;
&lt;li&gt;설정 변경 시 이전 상태를 추적하기 어려움&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-renderer-start-pos=&quot;184&quot; data-ke-size=&quot;size16&quot;&gt;AWS CLI를 이용해 쉘 스크립트를 작성하는 방식도 있었지만 Terraform의 장점이 더 크다고 느낌&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Terraform-도입-계기&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;245&quot; data-ke-size=&quot;size23&quot;&gt;Terraform 도입 계기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I2176/btsP4Vgvwji/tOS61sz5Pwm8Ol4ZsIYxHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I2176/btsP4Vgvwji/tOS61sz5Pwm8Ol4ZsIYxHk/img.png&quot; data-alt=&quot;Terraform&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I2176/btsP4Vgvwji/tOS61sz5Pwm8Ol4ZsIYxHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI2176%2FbtsP4Vgvwji%2FtOS61sz5Pwm8Ol4ZsIYxHk%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;480&quot; height=&quot;240&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Terraform&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS 사용 경험 중 느낀 불편함을 해결할 수 있을 것 같아 도입&lt;/li&gt;
&lt;li&gt;명령어가 단순하고 공식 문서 튜토리얼만으로도 학습이 가능해 접근성이 높음&lt;/li&gt;
&lt;li&gt;AWS 리소스 자체에 대한 이해가 필요하다는 러닝커브가 있었지만, 이는 콘솔 사용 시에도 동일하게 요구되는 부분이라 큰 문제가 되지 않음 (AI의 도움도 있고)&lt;/li&gt;
&lt;li&gt;결과적으롴 콘솔 대신 Terraform을 통해 인프라를 구성하는 편이 더 효율적이라고 판단&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;IaC의-장점&quot; style=&quot;background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-renderer-start-pos=&quot;496&quot; data-ke-size=&quot;size23&quot;&gt;IaC의 장점&lt;span&gt;&lt;span style=&quot;color: #505258;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #292a2e; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;멱등성&lt;/b&gt;: 여러 번 실행해도 같은 결과가 보장됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버전 관리 용이&lt;/b&gt;: Git을 통한 이력 관리와 롤백이 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 기반 관리&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: circle;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;모듈화와 변수 활용을 통해 재사용성이 높음&lt;/li&gt;
&lt;li&gt;하드코딩 대신 최신 값을 참조하여 유지보수가 용이&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리소스 종속성 관리&lt;/b&gt;: 리소스 간 의존 관계를 코드로 명확히 정의할 수 있어 관리 편의성 증대&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트 및 시뮬레이션 가능&lt;/b&gt; : terraform plan 같은 기능으로 실제 적용 전에 변경 사항을 미리 확인 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Terraform 학습&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;787&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mPhhx/btsP5EL6c91/WEN56iAvYqbXxUUk6xwcwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mPhhx/btsP5EL6c91/WEN56iAvYqbXxUUk6xwcwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mPhhx/btsP5EL6c91/WEN56iAvYqbXxUUk6xwcwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmPhhx%2FbtsP5EL6c91%2FWEN56iAvYqbXxUUk6xwcwK%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;663&quot; height=&quot;553&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;787&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1306&quot; data-start=&quot;1195&quot; data-ke-size=&quot;size16&quot;&gt;Terraform의 기본 개념을 이해하기 위해 HashiCorp 공식 페이지를 참고했다.&lt;br /&gt;기본적인 구조와 문법은 생각보다 어렵지 않았고, 실습 환경 구성과 적용도 금방 끝낼 수 있었다.&lt;/p&gt;
&lt;p data-end=&quot;1348&quot; data-start=&quot;1308&quot; data-ke-size=&quot;size16&quot;&gt;Terraform을 쓰다 보니 Git과 비슷한 경험을 받았다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1428&quot; data-start=&quot;1349&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1382&quot; data-start=&quot;1349&quot;&gt;git init &amp;harr; terraform init&lt;/li&gt;
&lt;li data-end=&quot;1428&quot; data-start=&quot;1383&quot;&gt;git add/commit/push &amp;harr; terraform apply&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1475&quot; data-start=&quot;1430&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;h3 data-ke-size=&quot;size23&quot;&gt;참고 문서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.hashicorp.com/terraform&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.hashicorp.com/terraform&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1756046285223&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;Terraform | HashiCorp Developer&quot; data-og-description=&quot;Explore Terraform product documentation, tutorials, and examples.&quot; data-og-host=&quot;developer.hashicorp.com&quot; data-og-source-url=&quot;https://developer.hashicorp.com/terraform&quot; data-og-url=&quot;https://developer.hashicorp.com/terraform&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cof8kl/hyZDN6YwZF/XvDWugoY6HU5m1C4x7Lz60/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800,https://scrap.kakaocdn.net/dn/vrlRz/hyZDXIwrEO/6dRZmn1l6U0KVMg2HpMKSK/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800&quot;&gt;&lt;a href=&quot;https://developer.hashicorp.com/terraform&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.hashicorp.com/terraform&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cof8kl/hyZDN6YwZF/XvDWugoY6HU5m1C4x7Lz60/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800,https://scrap.kakaocdn.net/dn/vrlRz/hyZDXIwrEO/6dRZmn1l6U0KVMg2HpMKSK/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800');&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;Terraform | HashiCorp Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Explore Terraform product documentation, tutorials, and examples.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.hashicorp.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 64 - Terraform으로 VPC 구성하기&lt;/h2&gt;
&lt;h3 data-end=&quot;93&quot; data-start=&quot;78&quot; data-ke-size=&quot;size23&quot;&gt;VPC 구성 시도&lt;/h3&gt;
&lt;p data-end=&quot;261&quot; data-start=&quot;94&quot; data-ke-size=&quot;size16&quot;&gt;어제 학습한 Terraform을 활용해 AWS 인프라를 직접 구성해보기로 했다. 가장 먼저 VPC를 정의하고, CIDR 블록과 가용 영역, 서브넷을 설정했다. 이어서 백엔드 서버가 외부 API와 통신할 수 있도록 NAT Gateway도 구성했다.&lt;/p&gt;
&lt;p data-end=&quot;348&quot; data-start=&quot;263&quot; data-ke-size=&quot;size16&quot;&gt;코드를 작성한 뒤 terraform plan으로 변경 사항을 시뮬레이션하고, 이어서 긴장되는 마음으로 terraform apply를 실행했다.&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;발생한 문제: Elastic IP 생성 실패&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NAT Gateway를 위해 Elastic IP(EIP)를 할당해줘야 하는데, 이 EIP 생성 부분에서 에러가 났다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756038588396&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;╷
│ Error: creating EC2 EIP: operation error EC2: AllocateAddress, https response error StatusCode: 400, RequestID: 9058c663-1c65-49ef-8652-001832c3459d, api error AddressLimitExceeded: The maximum number of addresses has been reached.       
│
│   with aws_eip.nat[0],
│   on vpc.tf line 53, in resource &quot;aws_eip&quot; &quot;nat&quot;:
│   53: resource &quot;aws_eip&quot; &quot;nat&quot; {
│
╵
╷
│ Error: creating EC2 EIP: operation error EC2: AllocateAddress, https response error StatusCode: 400, RequestID: fe6c6867-311f-4505-a468-4f31e2b7ef74, api error AddressLimitExceeded: The maximum number of addresses has been reached.       
│
│   with aws_eip.nat[1],
│   on vpc.tf line 53, in resource &quot;aws_eip&quot; &quot;nat&quot;:
│   53: resource &quot;aws_eip&quot; &quot;nat&quot; {
│&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Elastic IP Address 생성 및 할당 실패&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;원인&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서는 Elastic IP Address가 리전 당 최대 5개 할당 가능한데, 현재 우리가 사용하고자 하는 리전에서 5개를 할당해놔서 실행에 실패함&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;해결&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NAT Gateway 서비스를 이용하지 않고 EC2를 NAT Gateway 용도로 사용하기 위해 NAT Instance를 생성함&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배운점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 경험을 통해 AWS 리소스에는 서비스별 기본 제한이 존재한다는 사실을 다시금 체감했다. 서비스별 기본 제한을 영어로는 Soft Limit이라고 부른다고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로는 인프라 설계 시, 단순히 구조만 생각하는 것이 아니라 리소스 제한과 비용 요소까지 고려해야 한다는 교훈을 얻었다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Day 65 - Terraform으로 나머지 인프라 구성하기&lt;/h2&gt;
&lt;h3 data-end=&quot;100&quot; data-start=&quot;85&quot; data-ke-size=&quot;size23&quot;&gt;인프라 구성 진행&lt;/h3&gt;
&lt;p data-end=&quot;160&quot; data-start=&quot;101&quot; data-ke-size=&quot;size16&quot;&gt;어제 VPC 구성을 마친 데 이어, 오늘은 Terraform으로 나머지 주요 인프라를 구축했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;304&quot; data-start=&quot;162&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;181&quot; data-start=&quot;162&quot;&gt;EKS Cluster&lt;/li&gt;
&lt;li data-end=&quot;208&quot; data-start=&quot;182&quot;&gt;S3 (정적 페이지 서빙용 버킷)&lt;/li&gt;
&lt;li data-end=&quot;233&quot; data-start=&quot;209&quot;&gt;CloudFront (CDN)&lt;/li&gt;
&lt;li data-end=&quot;259&quot; data-start=&quot;234&quot;&gt;DynamoDB (데이터 저장)&lt;/li&gt;
&lt;li data-end=&quot;284&quot; data-start=&quot;260&quot;&gt;Route53 (도메인 관리)&lt;/li&gt;
&lt;li data-end=&quot;304&quot; data-start=&quot;285&quot;&gt;WAF (웹 방화벽)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;422&quot; data-start=&quot;306&quot; data-ke-size=&quot;size16&quot;&gt;각 리소스를 하나씩 코드로 정의하고 terraform apply로 배포를 진행했다. 또한 인프라 리소스들이 정상적으로 상호 연결될 수 있도록 IAM Role과 Policy 설정도 함께 구성했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LidTz/btsP3uqK7co/OcpP4PEJbg8Kbm1qTUSJF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LidTz/btsP3uqK7co/OcpP4PEJbg8Kbm1qTUSJF0/img.png&quot; data-alt=&quot;terraform 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LidTz/btsP3uqK7co/OcpP4PEJbg8Kbm1qTUSJF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLidTz%2FbtsP3uqK7co%2FOcpP4PEJbg8Kbm1qTUSJF0%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;608&quot; height=&quot;488&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;terraform 코드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRTASy/btsP26coqkx/SRaJIkKC7DTlJc5MXtf2C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRTASy/btsP26coqkx/SRaJIkKC7DTlJc5MXtf2C1/img.png&quot; data-alt=&quot;terraform plan 실행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRTASy/btsP26coqkx/SRaJIkKC7DTlJc5MXtf2C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRTASy%2FbtsP26coqkx%2FSRaJIkKC7DTlJc5MXtf2C1%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;732&quot; height=&quot;376&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;511&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;terraform plan 실행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bd7yHy/btsP4nYUETy/2KuEBYH817mkH50usmN0dK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bd7yHy/btsP4nYUETy/2KuEBYH817mkH50usmN0dK/img.png&quot; data-alt=&quot;정적 페이지를 위한 S3 Bucket&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bd7yHy/btsP4nYUETy/2KuEBYH817mkH50usmN0dK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbd7yHy%2FbtsP4nYUETy%2F2KuEBYH817mkH50usmN0dK%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;719&quot; height=&quot;356&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;460&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정적 페이지를 위한 S3 Bucket&lt;/figcaption&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;h2 data-ke-size=&quot;size26&quot;&gt;Day 66 - S3 Bucket 추가 구성 및 연동 확인&lt;/h2&gt;
&lt;h3 data-end=&quot;867&quot; data-start=&quot;840&quot; data-ke-size=&quot;size23&quot;&gt;코드 버전 관리 (GitHub 업로드)&lt;/h3&gt;
&lt;p data-end=&quot;929&quot; data-start=&quot;868&quot; data-ke-size=&quot;size16&quot;&gt;이번에 만든 Terraform 코드와 백엔드 코드를 각각 GitHub에 올려 버전 관리를 시작했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1056&quot; data-start=&quot;931&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;963&quot; data-start=&quot;931&quot;&gt;인프라 관련 코드는 별도의 리포지토리를 만들어 관리&lt;/li&gt;
&lt;li data-end=&quot;1019&quot; data-start=&quot;964&quot;&gt;애플리케이션 코드와 분리하여, IaC와 애플리케이션 개발 흐름을 독립적으로 관리 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1133&quot; data-start=&quot;1058&quot; data-ke-size=&quot;size16&quot;&gt;버전 관리를 적용하면서, 앞으로는 단순히 로컬에서 실험하는 것에 그치지 않고 팀 단위 협업 및 변경 이력 추적이 가능해졌다.&lt;/p&gt;
&lt;h3 data-end=&quot;104&quot; data-start=&quot;83&quot; data-ke-size=&quot;size23&quot;&gt;S3 Bucket 추가 생성&lt;/h3&gt;
&lt;p data-end=&quot;214&quot; data-start=&quot;105&quot; data-ke-size=&quot;size16&quot;&gt;Terraform으로 인프라 구성을 마무리했다고 생각했지만, 중요한 부분을 하나 놓치고 있었다. 애플리케이션에서 사용하는 이미지 저장용 S3 Bucket을 별도로 만들지 않았던 것.&lt;/p&gt;
&lt;p data-end=&quot;340&quot; data-start=&quot;216&quot; data-ke-size=&quot;size16&quot;&gt;처음 설계도에는 정적 페이지 서빙을 위한 S3 Bucket만 정의해두었기 때문에, 이미지 업로드 기능을 위해 새로운 S3 Bucket을 생성했다. 이후 기존에 만들어둔 CloudFront와도 연결해주었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XfJmn/btsP23mlPXG/NeTGheb0wuvkrAXVLGgaD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XfJmn/btsP23mlPXG/NeTGheb0wuvkrAXVLGgaD1/img.png&quot; data-alt=&quot;cloudfront&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XfJmn/btsP23mlPXG/NeTGheb0wuvkrAXVLGgaD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXfJmn%2FbtsP23mlPXG%2FNeTGheb0wuvkrAXVLGgaD1%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;702&quot; height=&quot;307&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;cloudfront&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-end=&quot;359&quot; data-start=&quot;347&quot; data-ke-size=&quot;size23&quot;&gt;연동 테스트&lt;/h3&gt;
&lt;p data-end=&quot;432&quot; data-start=&quot;360&quot; data-ke-size=&quot;size16&quot;&gt;애플리케이션을 수정하기 전에, S3와 CloudFront, Route53 간에 연동이 잘 되어 있는지 먼저 테스트를 진행했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;495&quot; data-start=&quot;433&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;467&quot; data-start=&quot;433&quot;&gt;팀원이 개발해둔 프론트엔드 코드를 S3에 업로드&lt;/li&gt;
&lt;li data-end=&quot;495&quot; data-start=&quot;468&quot;&gt;CloudFront 도메인으로 접속해 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;634&quot; data-start=&quot;497&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 페이지가 뜨지 않아 당황했지만, 원인은 CloudFront 캐싱이었다.&lt;br /&gt;TTL이 남아 있어 새로운 파일이 반영되지 않은 것이었고, 캐시를 초기화(Invalidation) 해주자 정상적으로 프론트 페이지가 로딩되었다.&lt;/p&gt;
&lt;h3 data-end=&quot;660&quot; data-start=&quot;641&quot; data-ke-size=&quot;size23&quot;&gt;Route53 연동 문제&lt;/h3&gt;
&lt;p data-end=&quot;806&quot; data-start=&quot;661&quot; data-ke-size=&quot;size16&quot;&gt;Route53에 팀원이 등록해둔 도메인에 CloudFront 도메인을 지정해 두었기 때문에, 바로 접속이 가능할 줄 알았다.&lt;br /&gt;하지만 시간이 지나도 연동이 되지 않았고, 아직 해결되지 않은 상태다. 이 부분은 주말이나 다음 주 중에 따로 확인할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✍️ 주간 회고&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjxUNi/btsP43r90gO/WbpXv6KqsN7ioCqKyzhxv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjxUNi/btsP43r90gO/WbpXv6KqsN7ioCqKyzhxv0/img.png&quot; data-alt=&quot;Jira 보드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjxUNi/btsP43r90gO/WbpXv6KqsN7ioCqKyzhxv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjxUNi%2FbtsP43r90gO%2FWbpXv6KqsN7ioCqKyzhxv0%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;332&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Jira 보드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;270&quot; data-start=&quot;60&quot; data-ke-size=&quot;size16&quot;&gt;이번 주는 기획에 없던 Terraform을 새로 도입하느라 예상보다 시간이 조금 더 걸렸다. 사실 초반에는 &amp;ldquo;굳이 지금 해야 할까?&amp;rdquo; 하는 고민도 있었는데, 막상 적용해보니 웹 콘솔에서 리소스를 하나씩 확인하던 번거로움이 사라지고 훨씬 체계적으로 관리할 수 있어 뿌듯했다. 지금은 조금 돌아온 것 같아 보여도, 앞으로 갈수록 이 선택이 좋은 발판이 될 거라는 확신이 든다.&lt;/p&gt;
&lt;p data-end=&quot;270&quot; data-start=&quot;60&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;347&quot; data-start=&quot;272&quot; data-ke-size=&quot;size16&quot;&gt;이번 주에는 Figma 대신 Jira를 보면서 진행 상황을 정리했는데, 한눈에 흐름을 볼 수 있어 나름의 성취감도 느낄 수 있었다.&lt;/p&gt;
&lt;p data-end=&quot;541&quot; data-start=&quot;349&quot; data-ke-size=&quot;size16&quot;&gt;다만 아쉬운 점은, Terraform 세팅에 몰두하느라 EKS 클러스터에 애플리케이션을 배포하는 본격적인 단계에 빨리 들어가지 못했다는 것. 다음 주에는 드디어 핵심 단계에 돌입할 생각을 하니 설레기도 하고, 동시에 잘 마무리할 수 있을지 긴장도 된다. 그래도 이번 주에 다져둔 기반이 든든하니, 조금 더 자신감을 가져도 되지 않을까 싶다.&lt;/p&gt;</description>
      <category>TIL</category>
      <category>amazon</category>
      <category>aws</category>
      <category>Cloudfront</category>
      <category>EKS</category>
      <category>Terraform</category>
      <category>TiL</category>
      <category>멀티캠퍼스it부트캠프</category>
      <category>부트캠프후기</category>
      <category>에스넷시스템 부트캠프</category>
      <category>클라우드 활용 네트워크 엔지니어 부트캠프</category>
      <author>yulee_to</author>
      <guid isPermaLink="true">https://yulee.tistory.com/178</guid>
      <comments>https://yulee.tistory.com/178#entry178comment</comments>
      <pubDate>Sat, 23 Aug 2025 00:26:34 +0900</pubDate>
    </item>
  </channel>
</rss>