<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩은 마라톤</title>
    <link>https://developer-anxi.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 6 Jul 2026 18:38:27 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>anxi</managingEditor>
    <image>
      <title>코딩은 마라톤</title>
      <url>https://tistory1.daumcdn.net/tistory/6528248/attach/893d53af13b04499865badc7592428f4</url>
      <link>https://developer-anxi.tistory.com</link>
    </image>
    <item>
      <title>[Odyssey-X] 알리콘(로켓펀치) 조민희 대표님의 강연을 듣고 나서..</title>
      <link>https://developer-anxi.tistory.com/96</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;강연 후기 전, 잠깐의 일기 - &quot;Odyssey-X를 하기까지의 여정&quot;&lt;/i&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;2025년 11월 20일, 산업체 근무를 시작하고 모이삼도 운영하다 보니 어느새 2026년 여름이 다가왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초반 3개월은 회사 -&amp;gt; 잠의 굴레에서 지냈다. 3개월이 지나면서 퇴근 후 여유가 생겼지만 여러 이유로 인해 개발과 잠시 멀어졌다. 가장 큰 이유는 AI의 발전이 아니었을까..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 3월, 모이삼 PM 현수가 창업을 하고 싶다 했고, K-pop 라이브 실시간 자막 서비스를 만든다고 했다. 현수 얘기를 듣다가 어디에 홀렸는지 나는 Kaptik을 개발했고 어느새 현수랑 창업에 도전하고 있다. (Kaptik은 아쉽게도 하지 않지만..)&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/kYFQA/dJMcagMjJK7/1fPTE1tNiz0dY0z3K2FQNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kYFQA/dJMcagMjJK7/1fPTE1tNiz0dY0z3K2FQNK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;634&quot; data-origin-height=&quot;854&quot; data-filename=&quot;스크린샷 2026-05-14 오후 10.07.51.png&quot; width=&quot;460&quot; height=&quot;620&quot; style=&quot;width: 50.4474%; margin-right: 10px;&quot; data-widthpercent=&quot;51.04&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kYFQA/dJMcagMjJK7/1fPTE1tNiz0dY0z3K2FQNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkYFQA%2FdJMcagMjJK7%2F1fPTE1tNiz0dY0z3K2FQNK%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;634&quot; height=&quot;854&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/70WxP/dJMcabYwVLr/UjRmPNRIDFa6M4ejg9SG30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/70WxP/dJMcabYwVLr/UjRmPNRIDFa6M4ejg9SG30/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;5704&quot; data-origin-height=&quot;8010&quot; data-filename=&quot;1775105878.png&quot; width=&quot;459&quot; height=&quot;645&quot; style=&quot;width: 48.3898%;&quot; data-widthpercent=&quot;48.96&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/70WxP/dJMcabYwVLr/UjRmPNRIDFa6M4ejg9SG30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F70WxP%2FdJMcabYwVLr%2FUjRmPNRIDFa6M4ejg9SG30%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;5704&quot; height=&quot;8010&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Kaptik &amp;amp; Odyssey-X&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;span style=&quot;color: #000000; text-align: left;&quot;&gt;4월 초, 현수가 서울시립대에서 Odyssey-X 프로그램이 있다고 해서 지원해 보자 해서 우리는 Kaptik으로 지원했고 최종 선발되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 2주차 세션인 5월 9일, 알리콘 조민희 대표님의 강연을 들었다. 앞으로 작성할 내용은 내가 특히 인상 깊게 들었던 부분 위주로 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;(1) 이 시대의 MVP는 무엇인가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님은 강연 서두에 &quot;이 시대의 MVP는 무엇인가?&quot; 질문을 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문을 들었을 때, 내가 생각했던 MVP는 '핵심 기능을 가진 프로덕트', '고객이 써볼 수 있는 최소한의 포로덕트' 였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님은 이 시대의 MVP는 '제품 개발'이 아닌, '&lt;b&gt;사업 검증&lt;/b&gt;'이라 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 생각한 MVP는 검증보다 개발에 집중한 프로덕트였다. 이에 반해, 대표님이 생각하신 MVP는 사업 검증에 집중하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제품을 오랜 시간 만들어서 출시를 해도, 고객이 쓰지 않으면 이는 실패한 아이템이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님은 사업 검증을 강조하며 개발 안된 제품도 이미 만들어있는 것처럼 생각하고, 이에 대해 먼저 고객이 구매할지를 검증해야 한다고 말씀하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 AI 시대에 MVP를 만들기는 매우 쉬워서 MVP는 매우 금방 만들 수 있다. 다만 사업 검증은 AI로 하기에는 한계가 있다. 그래서 사업 검증을 하고 제품을 만들어도 전혀 늦지 않다. (Kaptik도 4시간도 안 돼서 MVP는 만들었으니..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.alicorn-space.ai/2026/01/silicon-valley-end-of-product-development/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://blog.alicorn-space.ai/2026/01/silicon-valley-end-of-product-development/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1778766361054&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;실리콘밸리는 왜 &amp;lsquo;제품 개발의 종말&amp;rsquo;을 말하는가? : 10년 만의 SF 출장기&quot; data-og-description=&quot;일러두기 &amp;mdash; &amp;ldquo;알리콘은 현실 세계의 상업용 공간을 사람대신 운영하는 AI Agent다. 인구 감소 등으로 공간 운영에 어려움을 겪는 전세계 공간 운영 사업자를 돕기 위해, 세계 여러 도시를 방문하&quot; data-og-host=&quot;blog.alicorn-space.ai&quot; data-og-source-url=&quot;https://blog.alicorn-space.ai/2026/01/silicon-valley-end-of-product-development/&quot; data-og-url=&quot;https://blog.alicorn-space.ai/2026/01/silicon-valley-end-of-product-development/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bYUILY/dJMb82MH8Ss/QVI7BhM85UTT7PKRDrG0Sk/img.jpg?width=800&amp;amp;height=1067&amp;amp;face=0_0_800_1067,https://scrap.kakaocdn.net/dn/yTiP5/dJMb8WeEJpl/xGjVya79dVS0iK3S24D4xk/img.jpg?width=800&amp;amp;height=1067&amp;amp;face=0_0_800_1067,https://scrap.kakaocdn.net/dn/bAQT7b/dJMb88e5IE9/r2zhx1cdGdQjL8FEib9FWk/img.jpg?width=800&amp;amp;height=1067&amp;amp;face=0_0_800_1067&quot;&gt;&lt;a href=&quot;https://blog.alicorn-space.ai/2026/01/silicon-valley-end-of-product-development/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.alicorn-space.ai/2026/01/silicon-valley-end-of-product-development/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bYUILY/dJMb82MH8Ss/QVI7BhM85UTT7PKRDrG0Sk/img.jpg?width=800&amp;amp;height=1067&amp;amp;face=0_0_800_1067,https://scrap.kakaocdn.net/dn/yTiP5/dJMb8WeEJpl/xGjVya79dVS0iK3S24D4xk/img.jpg?width=800&amp;amp;height=1067&amp;amp;face=0_0_800_1067,https://scrap.kakaocdn.net/dn/bAQT7b/dJMb88e5IE9/r2zhx1cdGdQjL8FEib9FWk/img.jpg?width=800&amp;amp;height=1067&amp;amp;face=0_0_800_1067');&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;실리콘밸리는 왜 &amp;lsquo;제품 개발의 종말&amp;rsquo;을 말하는가? : 10년 만의 SF 출장기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;일러두기 &amp;mdash; &amp;ldquo;알리콘은 현실 세계의 상업용 공간을 사람대신 운영하는 AI Agent다. 인구 감소 등으로 공간 운영에 어려움을 겪는 전세계 공간 운영 사업자를 돕기 위해, 세계 여러 도시를 방문하&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.alicorn-space.ai&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;(2) 좋은 제품의 기준 = Less Is More&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님은 MVP 얘기를 하시면서 사업 검증 그리고 Less Is More에 대해 말씀하셨다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-14 오후 10.53.26.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;1082&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FYMgO/dJMcagFyowW/JRkR0OkzsDkDVr3oWbGPG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FYMgO/dJMcagFyowW/JRkR0OkzsDkDVr3oWbGPG0/img.png&quot; data-alt=&quot;Less Is More&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FYMgO/dJMcagFyowW/JRkR0OkzsDkDVr3oWbGPG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFYMgO%2FdJMcagFyowW%2FJRkR0OkzsDkDVr3oWbGPG0%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;520&quot; height=&quot;427&quot; data-filename=&quot;스크린샷 2026-05-14 오후 10.53.26.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;1082&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Less Is More&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;&quot;적을수록 더 좋다&quot;는 무슨 의미일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마존을 예를 들어보면, 현재 아마존(Amazon)은 &lt;b&gt;세계 최대 규모의 온라인 쇼핑몰&lt;/b&gt;이지만, 시작은 종이책을 온라인으로 판매 및 배송하는 인터넷 서점이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많고 많은 물건 중, 종이책을 선택한 이유는 무엇일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님이 말씀하시기로는, 종이책은 배송사고가 터지거나, 책을 반품하거나, 수영복이 일부 시즌에 주문량이 급증하는 등 배송에 민감한 상황이 발생하지 않아서 종이책을 선택했을 거라고 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 아마존의 MVP이자 Less Is More 한 핵심 가치는 &quot;가장 팔기 쉬운 책부터 팔겠다.&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하자면, Less Is More 한 기능을 가진 MVP는 웹사이트가 될 수도, 앱이 될 수도 있지만 단지 프로덕트의 퀄리티가 아닐 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVP를 프로덕트에 국한하지 않고, 아마존의 예시처럼 본연의 기능을 어떻게 하면 더 쉽게 검증할 수 있을지에 포커싱 하는 게 아닐까.. 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;(3) 좋은 아이템을 찾기 전에 나 자신을 돌아보자!&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-14 오후 11.15.15.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;1142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qdtnL/dJMb990Ji2l/LHGJKAm1jX12Q0gCI6pBBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qdtnL/dJMb990Ji2l/LHGJKAm1jX12Q0gCI6pBBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qdtnL/dJMb990Ji2l/LHGJKAm1jX12Q0gCI6pBBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqdtnL%2FdJMb990Ji2l%2FLHGJKAm1jX12Q0gCI6pBBk%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;531&quot; height=&quot;460&quot; data-filename=&quot;스크린샷 2026-05-14 오후 11.15.15.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;1142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님은 좋은 사업 아이디어는&amp;nbsp;&lt;b&gt;1. 내가 좋아하는 것&lt;/b&gt; + &lt;b&gt;2. 내가 잘하는 것&lt;/b&gt; &lt;b&gt;3. 세상이 원하는 것&lt;/b&gt;의 교집합을 찾으라고 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님의 말씀을 듣고 나니, 좋은 사업 아이템을 발굴하기 위해선 나 자신을 들여다보는 시간이 필요함을 깨달았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주변에서 아이템 발굴이 능한 사람(현수)을 보면, 본인의 호불호가 명확하고 잘하는 것과 못하는 것에 대한 판단이 빠른 것 같다. 스스로의 확신이 있어야 그 교집합 내에서 다양한 아이템 후보들을 도출해 낼 수 있을 거라 생각했다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, 나는 아직 내가 무엇을 좋아하고 싫어하는지, 어떤 것에 잘하고 못하지를 정의하지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 앞으로는 내가 좋아하고 싫어하는 것을 찾는 시간을 의무적으로 찾으려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사담이지만, 요새는 회사에서 점심을 빠르게 먹고 산책을 하고 있다. 햇빛을 쬐며 푸릇푸릇한 잎을 보고 자그마한 동물들을 보면서 은근히 힐링되는 것 같다. 2026년 5월, 나는 봄과 산책, 자연을 좋아합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLbTo/dJMcaipNRdQ/C3SGq6EwHfUI3hsPES5GWk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLbTo/dJMcaipNRdQ/C3SGq6EwHfUI3hsPES5GWk/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-05-14-23-37-06 001.jpeg&quot; width=&quot;427&quot; height=&quot;569&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/kLbTo/dJMcaipNRdQ/C3SGq6EwHfUI3hsPES5GWk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLbTo%2FdJMcaipNRdQ%2FC3SGq6EwHfUI3hsPES5GWk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9z45n/dJMcagZMHp5/4gSPjtE7pzBlGsEy06fLIk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9z45n/dJMcagZMHp5/4gSPjtE7pzBlGsEy06fLIk/img.jpg&quot; data-origin-width=&quot;4284&quot; data-origin-height=&quot;5712&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-05-14-23-37-07 004.jpeg&quot; width=&quot;409&quot; height=&quot;545&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9z45n/dJMcagZMHp5/4gSPjtE7pzBlGsEy06fLIk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9z45n%2FdJMcagZMHp5%2F4gSPjtE7pzBlGsEy06fLIk%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;4284&quot; height=&quot;5712&quot;/&gt;&lt;/span&gt;&lt;/div&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/biyrGt/dJMcacJU14K/IkdVObKuBnXktpYgk0WIN1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biyrGt/dJMcacJU14K/IkdVObKuBnXktpYgk0WIN1/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-05-14-23-37-06 002.jpeg&quot; width=&quot;406&quot; height=&quot;541&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/biyrGt/dJMcacJU14K/IkdVObKuBnXktpYgk0WIN1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiyrGt%2FdJMcacJU14K%2FIkdVObKuBnXktpYgk0WIN1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UOftI/dJMcaiwx4xT/44hvQiA4thekog53C7ZyAK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UOftI/dJMcaiwx4xT/44hvQiA4thekog53C7ZyAK/img.jpg&quot; data-origin-width=&quot;4284&quot; data-origin-height=&quot;5712&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-05-14-23-37-06 003.jpeg&quot; width=&quot;405&quot; height=&quot;540&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UOftI/dJMcaiwx4xT/44hvQiA4thekog53C7ZyAK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUOftI%2FdJMcaiwx4xT%2F44hvQiA4thekog53C7ZyAK%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;4284&quot; height=&quot;5712&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>대외활동</category>
      <category>Less is more</category>
      <category>MVP</category>
      <category>Odyssey-X</category>
      <category>강연</category>
      <category>로켓펀치</category>
      <category>알리콘</category>
      <category>일기</category>
      <category>조민희</category>
      <category>창업</category>
      <category>후기</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/96</guid>
      <comments>https://developer-anxi.tistory.com/96#entry96comment</comments>
      <pubDate>Thu, 14 May 2026 23:42:23 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] 아침 7시, 멀쩡하던 서버가 죽었다? (ECR Lifecycle Policy 장애 회고 및 Discord 알림 구축기)</title>
      <link>https://developer-anxi.tistory.com/95</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; 발단: 운영 서버 접근 불가&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-20 오후 11.20.09.png&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;605&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0I7sA/dJMcafsLP4W/7MOkfMkKf6RRDNRz6li8QK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0I7sA/dJMcafsLP4W/7MOkfMkKf6RRDNRz6li8QK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0I7sA/dJMcafsLP4W/7MOkfMkKf6RRDNRz6li8QK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0I7sA%2FdJMcafsLP4W%2F7MOkfMkKf6RRDNRz6li8QK%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;1262&quot; height=&quot;605&quot; data-filename=&quot;스크린샷 2026-04-20 오후 11.20.09.png&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;605&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 일하고 있는데 디코 알림이 울렸다. 알림을 보니 모이삼(&lt;a href=&quot;https://moisam.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://moisam.kr/&lt;/a&gt;) 접근이 되지 않는다는 오류였다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 cert-manager, nginx-ingress 충돌 났을 때랑 동일 증상이라 SSL 인증서 문제인가 했지만.. AWS ACM을 사용 중이었어서 이 경우는 아니었다.&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;스크린샷 2026-04-20 오후 11.27.12.png&quot; data-origin-width=&quot;289&quot; data-origin-height=&quot;801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OayVN/dJMcafGktvG/EioACXFU38JhKIlxHnOcG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OayVN/dJMcafGktvG/EioACXFU38JhKIlxHnOcG0/img.png&quot; data-alt=&quot;ECR 이벤트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OayVN/dJMcafGktvG/EioACXFU38JhKIlxHnOcG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOayVN%2FdJMcafGktvG%2FEioACXFU38JhKIlxHnOcG0%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;289&quot; height=&quot;801&quot; data-filename=&quot;스크린샷 2026-04-20 오후 11.27.12.png&quot; data-origin-width=&quot;289&quot; data-origin-height=&quot;801&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;p data-ke-size=&quot;size16&quot;&gt;AWS에서 확인해 보니 이벤트가 금일 쭉 쌓여 있었고, 모든 내용이 다음과 같았다.&lt;/p&gt;
&lt;pre id=&quot;code_1776695282490&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;service &amp;lt;SERVICE_NAME&amp;gt; was unable to place a task.
Reason: CannotPullContainerError: pull image manifest has been retried 7 time(s):
failed to resolve ref &amp;lt;AWS_ACCOUNT_ID&amp;gt;.dkr.ecr.ap-northeast-2.amazonaws.com/&amp;lt;REPO_NAME&amp;gt;:&amp;lt;TAG&amp;gt;@sha256:&amp;lt;DIGEST&amp;gt;: not found.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 태스크를 사용할 수 없는 문제였고 이는 ECR에서 이미지를 pull 하지 못해 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  뭐가 문제였을까? 'ECR 수명 주기 정책'&lt;/b&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;b&gt;ECR 수명 주기 정책&lt;/b&gt;'이 문제였다. 기존 정책은 최근 10개 이미지만 남기고 모두 제거하는 것이었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 하나의 ECR 레포지토리에 운영과 개발 이미지를 태그로만 구분해서 계속 푸시하고 있었다. 운영 배포보다 개발 서버 배포가 훨씬 잦다 보니, 개발 이미지가 계속 쌓이면서 운영 이미지가 '최근 10개' 목록에서 밀려나 기계적으로 삭제되어 버린 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 운영 이미지가 최근 10개 이미지에서 벗어나면서.. ECS 재가동 과정에서 PULL 할 이미지가 없어 장애가 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비용 절감을 위해 무심코 만든 정책이 04.20 07시 ~ 04.20 15시 총 8시간 동안 서버가 꺼졌으며.. 8시간 동안 장애가 발생한 사실을 알지 못했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  해결 1. ECR 수명 주기 정책 수정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1개의 ECR에서 운영, 개발 이미지를 태그로 분리하고 있어서 최근 10개 이미지만 남기는 건 위험할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 규칙 우선순위에 따라 3개로 나눠 정책을 추가했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1순위: latest 태그 이미지는 9999개 보관 (절대 삭제 안 함)&lt;/li&gt;
&lt;li&gt;2순위: 그 외의 태그 이미지는 30개 유지&lt;/li&gt;
&lt;li&gt;3순위: untagged 이미지는 7일 뒤 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776695973379&quot; class=&quot;json&quot; data-ke-language=&quot;json&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;rules&quot;: [
    {
      &quot;rulePriority&quot;: 1,
      &quot;description&quot;: &quot;latest 태그는 삭제하지 않음&quot;,
      &quot;selection&quot;: {
        &quot;tagStatus&quot;: &quot;tagged&quot;,
        &quot;tagPrefixList&quot;: [
          &quot;latest&quot;
        ],
        &quot;countType&quot;: &quot;imageCountMoreThan&quot;,
        &quot;countNumber&quot;: 9999
      },
      &quot;action&quot;: {
        &quot;type&quot;: &quot;expire&quot;
      }
    },
    {
      &quot;rulePriority&quot;: 2,
      &quot;description&quot;: &quot;나머지 모든 태그 이미지 최근 30개 유지&quot;,
      &quot;selection&quot;: {
        &quot;tagStatus&quot;: &quot;tagged&quot;,
        &quot;tagPatternList&quot;: [
          &quot;*&quot;
        ],
        &quot;countType&quot;: &quot;imageCountMoreThan&quot;,
        &quot;countNumber&quot;: 30
      },
      &quot;action&quot;: {
        &quot;type&quot;: &quot;expire&quot;
      }
    },
    {
      &quot;rulePriority&quot;: 3,
      &quot;description&quot;: &quot;태그 없는 이미지 7일 후 삭제&quot;,
      &quot;selection&quot;: {
        &quot;tagStatus&quot;: &quot;untagged&quot;,
        &quot;countType&quot;: &quot;sinceImagePushed&quot;,
        &quot;countUnit&quot;: &quot;days&quot;,
        &quot;countNumber&quot;: 7
      },
      &quot;action&quot;: {
        &quot;type&quot;: &quot;expire&quot;
      }
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최신 배포된 운영 이미지는 &lt;b&gt;latest&lt;/b&gt; 태그를 붙이고 latest 태그가 붙어 있으면 절대 삭제하지 않도록 했다. 또한 개발 이미지도 같이 올림으로 모든 태그의 이미지는 30개까지만 남기고 나머지는 제거하도록 했다. 추가로 태그 없는 이미지는 7일 후 삭제하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1776696339914&quot; class=&quot;yml yaml&quot; data-ke-language=&quot;yml&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;      - name: Build and push image
        id: build-image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./deploy/Dockerfile
          platforms: linux/amd64
          push: true
          tags: |
            ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
            // 추가
            ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max
          build-args: |
            JAR_FILE=build/libs/*.jar&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 배포 스크립트에도 latest 태그를 추가해뒀다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  해결 2. AWS Lambda, SNS, CloudWatch를 사용해 Discord 서버 다운/복구 모니터링&lt;/b&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모니터링을 할 수 있는 방법을 찾아보던 중, 서버 다운/복구 시에만 알림 보내면 되기 때문에 AWS Lambda를 사용해서 구축할 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스코드 서버 다운/복구 알림은 다음과 같이 파이프라인을 구축했다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;ALB (HealthyHostCount) ➡️ CloudWatch Alarm ➡️ AWS SNS ➡️ AWS Lambda ➡️ Discord Webhook&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;(참고로 Lambda 월 100만 건, SNS 월 100만 건, CloudWatch 알람 10개까지&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;AWS 12개월 프리티어가 끝나도 평생(Always Free) 0원이다!)&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이프라인은 아래와 같이 동작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ALB에서 서버가 닫혀있음을 확인 -&amp;gt; 커스텀한 Cloud Watch Alarm 발생 -&amp;gt; SNS가 구독한 CloudWatch Alarm을 받아서 Lambda로 내용 전달 -&amp;gt; Lambda에서 Discord Webhook으로 알림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.1. Lambda 디스코드 알리미 생성&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-20 오후 11.55.29.png&quot; data-origin-width=&quot;1784&quot; data-origin-height=&quot;841&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eE8BVM/dJMcagFfRii/hqohfbJ2L1eZmkOVDKP3A0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eE8BVM/dJMcagFfRii/hqohfbJ2L1eZmkOVDKP3A0/img.png&quot; data-alt=&quot;디스코드 알리미 함수 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eE8BVM/dJMcagFfRii/hqohfbJ2L1eZmkOVDKP3A0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeE8BVM%2FdJMcagFfRii%2FhqohfbJ2L1eZmkOVDKP3A0%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;1784&quot; height=&quot;841&quot; data-filename=&quot;스크린샷 2026-04-20 오후 11.55.29.png&quot; data-origin-width=&quot;1784&quot; data-origin-height=&quot;841&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디스코드 알리미 함수 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1776698238077&quot; class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import json
import os
import urllib.request
from datetime import datetime, timezone, timedelta

KST = timezone(timedelta(hours=9))


def lambda_handler(event, context):
    webhook_url = os.environ[&quot;DISCORD_WEBHOOK_URL&quot;]

    for record in event.get(&quot;Records&quot;, []):
        message = json.loads(record[&quot;Sns&quot;][&quot;Message&quot;])
        payload = build_payload(message)
        send_discord(webhook_url, payload)


def build_payload(message):
    alarm_name = message.get(&quot;AlarmName&quot;, &quot;Unknown&quot;)
    state = message.get(&quot;NewStateValue&quot;, &quot;Unknown&quot;)
    reason = message.get(&quot;NewStateReason&quot;, &quot;&quot;)
    state_change_time = message.get(&quot;StateChangeTime&quot;, &quot;&quot;)

    is_alarm = state == &quot;ALARM&quot;
    title = f&quot;  서버 다운: {alarm_name}&quot; if is_alarm else f&quot;✅ 서버 복구: {alarm_name}&quot;
    color = 0xFF0000 if is_alarm else 0x00FF00

    timestamp = parse_kst(state_change_time)

    return {
        &quot;embeds&quot;: [{
            &quot;title&quot;: title,
            &quot;color&quot;: color,
            &quot;fields&quot;: [
                {&quot;name&quot;: &quot;상태&quot;, &quot;value&quot;: state, &quot;inline&quot;: True},
                {&quot;name&quot;: &quot;발생 시각 (KST)&quot;, &quot;value&quot;: timestamp, &quot;inline&quot;: True},
                {&quot;name&quot;: &quot;원인&quot;, &quot;value&quot;: reason or &quot;-&quot;, &quot;inline&quot;: False},
            ],
        }]
    }


def parse_kst(iso_string):
    try:
        dt = datetime.fromisoformat(iso_string.replace(&quot;Z&quot;, &quot;+00:00&quot;))
        return dt.astimezone(KST).strftime(&quot;%Y-%m-%d %H:%M:%S&quot;)
    except Exception:
        return iso_string


def send_discord(webhook_url, payload):
    data = json.dumps(payload).encode(&quot;utf-8&quot;)
    req = urllib.request.Request(
        webhook_url,
        data=data,
        headers={
            &quot;Content-Type&quot;: &quot;application/json&quot;,
            &quot;User-Agent&quot;: &quot;AWS-Lambda-Moism/1.0&quot;
        },
    )
    with urllib.request.urlopen(req, timeout=5) as resp:
        return resp.status&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-20 오후 11.56.09.png&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nRIeA/dJMcacQl6S5/ghHRuR4jnfG50cnw8lUR81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nRIeA/dJMcacQl6S5/ghHRuR4jnfG50cnw8lUR81/img.png&quot; data-alt=&quot;람다 함수 작성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nRIeA/dJMcacQl6S5/ghHRuR4jnfG50cnw8lUR81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnRIeA%2FdJMcacQl6S5%2FghHRuR4jnfG50cnw8lUR81%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;1764&quot; height=&quot;824&quot; data-filename=&quot;스크린샷 2026-04-20 오후 11.56.09.png&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;824&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;p data-ke-size=&quot;size16&quot;&gt;AWS Lambda에 함수를 생성한 뒤, 위 코드를 작성한다. Deploy를 해서 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 위 코드에 DISCORD_WEBHOOK_URL은 Lambda 환경변수에 추가하거나, 문자열로 작성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1776698333625&quot; class=&quot;json&quot; data-ke-language=&quot;json&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;Records&quot;: [
    {
      &quot;Sns&quot;: {
        &quot;Message&quot;: &quot;{\&quot;AlarmName\&quot;: \&quot;moisam-server-down\&quot;, \&quot;NewStateValue\&quot;: \&quot;OK\&quot;, \&quot;NewStateReason\&quot;: \&quot;테스트: Task가 다시 1개 이상으로 복구되었습니다.\&quot;, \&quot;StateChangeTime\&quot;: \&quot;2026-04-20T22:45:00.000+0000\&quot;}&quot;
      }
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.20.15.png&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RMbrf/dJMcafzy98e/VibMFlceEk7Zlq8CSYcumk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RMbrf/dJMcafzy98e/VibMFlceEk7Zlq8CSYcumk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RMbrf/dJMcafzy98e/VibMFlceEk7Zlq8CSYcumk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRMbrf%2FdJMcafzy98e%2FVibMFlceEk7Zlq8CSYcumk%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;611&quot; height=&quot;646&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.20.15.png&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;테스트는 Test 버튼을 누른 뒤,&lt;span&gt; 위 JSON을 &lt;/span&gt;&lt;/span&gt;복사하여 Event JSON에 붙여 넣은 뒤 Invoke 하면 디스코드로 알림이 온다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.04.31.png&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bI0Duk/dJMcahREuHN/V16KEug06EnowXW0c1Bqs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bI0Duk/dJMcahREuHN/V16KEug06EnowXW0c1Bqs0/img.png&quot; data-alt=&quot;모이삼 배포봇&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bI0Duk/dJMcahREuHN/V16KEug06EnowXW0c1Bqs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbI0Duk%2FdJMcahREuHN%2FV16KEug06EnowXW0c1Bqs0%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;337&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.04.31.png&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;337&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.2. SNS 주제 생성&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.23.36.png&quot; data-origin-width=&quot;1754&quot; data-origin-height=&quot;561&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UVOQ0/dJMcadVZLMb/jdQpVFTYQC9kxc0kxhMJY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UVOQ0/dJMcadVZLMb/jdQpVFTYQC9kxc0kxhMJY1/img.png&quot; data-alt=&quot;SNS 주제 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UVOQ0/dJMcadVZLMb/jdQpVFTYQC9kxc0kxhMJY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUVOQ0%2FdJMcadVZLMb%2FjdQpVFTYQC9kxc0kxhMJY1%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;1754&quot; height=&quot;561&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.23.36.png&quot; data-origin-width=&quot;1754&quot; data-origin-height=&quot;561&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SNS 주제 생성&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;SNS 주제는 '&lt;b&gt;표준&lt;/b&gt;' 유형으로 생성한다. (표준 유형만 무료)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.26.39.png&quot; data-origin-width=&quot;1765&quot; data-origin-height=&quot;757&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RKFRL/dJMcabjD8de/Ius4sA8KJP83G92cO13V61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RKFRL/dJMcabjD8de/Ius4sA8KJP83G92cO13V61/img.png&quot; data-alt=&quot;주제 &amp;amp;gt; 구독 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RKFRL/dJMcabjD8de/Ius4sA8KJP83G92cO13V61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRKFRL%2FdJMcabjD8de%2FIus4sA8KJP83G92cO13V61%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;1765&quot; height=&quot;757&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.26.39.png&quot; data-origin-width=&quot;1765&quot; data-origin-height=&quot;757&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;주제 &amp;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;p data-ke-size=&quot;size16&quot;&gt;생성한 주제에서 구독을 생성한다. 이때 프로토콜은 '&lt;b&gt;AWS Lambda&lt;/b&gt;', 엔드포인트는 2.1에서 만든 Lambda 함수를 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.3. CloudWatch Alarm (경보) 생성&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.06.53.png&quot; data-origin-width=&quot;1904&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmoGst/dJMcagyq199/DQ6RUdpLVP75Y39I4hTVXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmoGst/dJMcagyq199/DQ6RUdpLVP75Y39I4hTVXk/img.png&quot; data-alt=&quot;CloudWatch 경보 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmoGst/dJMcagyq199/DQ6RUdpLVP75Y39I4hTVXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmoGst%2FdJMcagyq199%2FDQ6RUdpLVP75Y39I4hTVXk%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;1904&quot; height=&quot;349&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.06.53.png&quot; data-origin-width=&quot;1904&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CloudWatch 경보 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1777&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5AjYQ/dJMcaiJLBbQ/IXcW5aao8ujbp4Cm9ZewgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5AjYQ/dJMcaiJLBbQ/IXcW5aao8ujbp4Cm9ZewgK/img.png&quot; data-alt=&quot;지표 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5AjYQ/dJMcaiJLBbQ/IXcW5aao8ujbp4Cm9ZewgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5AjYQ%2FdJMcaiJLBbQ%2FIXcW5aao8ujbp4Cm9ZewgK%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;1777&quot; height=&quot;834&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1777&quot; data-origin-height=&quot;834&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;스크린샷 2026-04-21 오전 12.13.14.png&quot; data-origin-width=&quot;1597&quot; data-origin-height=&quot;541&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/piyaT/dJMcajaQhFY/0aWONI0Prt2csDa2eZLkM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/piyaT/dJMcajaQhFY/0aWONI0Prt2csDa2eZLkM0/img.png&quot; data-alt=&quot;조건&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/piyaT/dJMcajaQhFY/0aWONI0Prt2csDa2eZLkM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpiyaT%2FdJMcajaQhFY%2F0aWONI0Prt2csDa2eZLkM0%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;1597&quot; height=&quot;541&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.13.14.png&quot; data-origin-width=&quot;1597&quot; data-origin-height=&quot;541&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;조건&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지표 선택은 다양하게 선택할 수 있지만, 모이삼은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;ALB &amp;gt; 대상 그룹(TG) 별 지표 &amp;gt; HealthyHostCount로&lt;/b&gt; 선택했다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;HealthyHostCount는 ALB에서 헬스체크 시 결과 기반이라 1 미만이면 서버가 정상적으로 뜨지 않았음을 의미한다. 그래서 조건에 1 미만으로 설정한 뒤, 다음으로 넘어간다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; 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;스크린샷 2026-04-21 오전 12.14.51.png&quot; data-origin-width=&quot;1890&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LFl3X/dJMcajokXLf/eJ586hknAm6GLxIq3UVaG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LFl3X/dJMcajokXLf/eJ586hknAm6GLxIq3UVaG0/img.png&quot; data-alt=&quot;트리거 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LFl3X/dJMcajokXLf/eJ586hknAm6GLxIq3UVaG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLFl3X%2FdJMcajokXLf%2FeJ586hknAm6GLxIq3UVaG0%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;1890&quot; height=&quot;828&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.14.51.png&quot; data-origin-width=&quot;1890&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;트리거 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;알림은 총 2개로 설정했다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 경보 상태는 HealthyHostCount가 1 미만인 오류 상황인 경우, 두 번째 경보 상태는 정상인 상황의 트리거이다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 다음으로 알림 전송... 에서는 앞서 (2.2)에서 만들어둔 SNS 주제(Topic)를 선택해 주고 경보를 생성하면 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; &amp;nbsp;결과&amp;nbsp;및&amp;nbsp;회고&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.28.42.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmGZqH/dJMb99TCURZ/i8SquqElqZyrCUsqKL3KRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmGZqH/dJMb99TCURZ/i8SquqElqZyrCUsqKL3KRK/img.png&quot; data-alt=&quot;실제 알림 내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmGZqH/dJMb99TCURZ/i8SquqElqZyrCUsqKL3KRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmGZqH%2FdJMb99TCURZ%2Fi8SquqElqZyrCUsqKL3KRK%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;613&quot; height=&quot;208&quot; data-filename=&quot;스크린샷 2026-04-21 오전 12.28.42.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;208&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;p data-ke-size=&quot;size16&quot;&gt;컨테이너 개수가 1개가 되어서 더 이상 임계값(1.0) 미만이 아니므로 정상 상태 값의 디스코드 알림이 왔다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 빨간 알림이 오지 않는 것을 바라지만.. 이전과는 달리 알림으로 받을 수 있어 빠른 처리가 가능할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번을 계기로 서버가 닫힌 경우에도 모니터링이 필요함을 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 애플리케이션 오류, Slow API 등의 로그를 위와 같이 설정해서 비용 0원으로 AWS 모니터링 시스템을 구축해 봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Backend/CI CD</category>
      <category>AWS</category>
      <category>cloudwatch</category>
      <category>DISCORD</category>
      <category>ECR</category>
      <category>ecs</category>
      <category>Lambda</category>
      <category>SNS</category>
      <category>webhook</category>
      <category>모니터링</category>
      <category>트러블슈팅</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/95</guid>
      <comments>https://developer-anxi.tistory.com/95#entry95comment</comments>
      <pubDate>Tue, 21 Apr 2026 00:44:15 +0900</pubDate>
    </item>
    <item>
      <title>[K3s] cert-manager 인증서 갱신 실패(ERR_CERT_DATE_INVALID) 해결해보자</title>
      <link>https://developer-anxi.tistory.com/94</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  문제 발생&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난주 금요일 (3/20), 친구들과 모임 이후 모이삼 어드민 페이지에서 모임 통계를 확인하려 했다.&amp;nbsp;&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;710&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yivUU/dJMcac3vQDO/ZUiPjhKk4v4HCXIpj7CKj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yivUU/dJMcac3vQDO/ZUiPjhKk4v4HCXIpj7CKj0/img.png&quot; data-alt=&quot;ERR_CERT_DATE_INVALID&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yivUU/dJMcac3vQDO/ZUiPjhKk4v4HCXIpj7CKj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyivUU%2FdJMcac3vQDO%2FZUiPjhKk4v4HCXIpj7CKj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;710&quot; height=&quot;475&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ERR_CERT_DATE_INVALID&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;잘 작동하던 어드민 사이트 (백엔드 API, Thymeleaf로 구현된 SSR)가 갑자기 인증서 만료가 뜨며 먹통이 되었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트(`&lt;a href=&quot;https://moisam.kr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;moisam.kr&lt;/a&gt;`)는 Vercel로 돌리고 있어 인증서 문제는 없었지만, 클라이언트 단에서 백엔드 API를 호출할 때 SSL 프로토콜 오류가 발생하여 비정상적인 리다이렉트 라우팅이 발생하고 있었다. (`moisam.kr` 로 접속 시, `moisam.kr/history` 로 이동)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/history는 가입 유저만 사용할 수 있는 기능이었고 인증서 만료 이전에 로그인 한 유저는 사용 가능했지만, 비로그인 유저는 접근조차 불가능했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; ️&amp;zwj;♂️&amp;nbsp;원인&amp;nbsp;파악&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Let's Encrypt 인증서 확인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모이삼은 K3s의 &lt;b&gt;cert-manager&lt;/b&gt;를 사용하여 SS&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;L/TLS 인증서를 자동으로 프로비저닝하고 관리하고 있다. cert-manager는 만료 30일 전부터 자체적으로 갱신을 시도한다. 작년 9월부터 초기 설정 이후, 인증서에 대한 문제는 없었는데 갑자기&lt;/span&gt; 장애가 났다는 것은 지난 30일 동안 cert-manager의 백그라운드 자동 갱신이 무언가에 막혀 계속 실패하고 있었음을 시사한다.&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;b&gt;2. 쿠버네티스 상태 확인&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8aGJT/dJMcabctf1p/sco9wbNptDdq0YZ7JYJky1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8aGJT/dJMcabctf1p/sco9wbNptDdq0YZ7JYJky1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8aGJT/dJMcabctf1p/sco9wbNptDdq0YZ7JYJky1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8aGJT%2FdJMcabctf1p%2Fsco9wbNptDdq0YZ7JYJky1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;188&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1774281014307&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kubectl get certificate -n prod
NAME       READY   SECRET     AGE
prod-tls   False   prod-tls   247d&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경의 인증서를 확인해보니 `READY=False` 상태였다. cert-manager에서 자동 갱신이 되지 않고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증서 발급에 문제가 있음을 확인하여 Challenge 상태를 확인해 보았다.&lt;/p&gt;
&lt;pre id=&quot;code_1774281320835&quot; class=&quot;routeros&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kubectl describe challenge -n prod
...
Warning  PresentError  Error presenting challenge: Internal error occurred: 
failed calling webhook &quot;validate.nginx.ingress.kubernetes.io&quot;: failed to call webhook: 
Post &quot;https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s&quot;: 
service &quot;ingress-nginx-controller-admission&quot; not found&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubectl describe challenge -n prod 명령어를 통해 상세 내역(Events)을 확인해 보니 에러 로그가 존재했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  원인: ingress-nginx 불완전 삭제로 인한 잔여 데이터 존재&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;??? &lt;/b&gt;ingress-nginx ???&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모이삼은 K3s에서 기본으로 제공하는 Traefik을 Ingress Controller로 사용하고 있었다. 하지만 이전에 ClientIP 로깅 과정에 `ingress-nginx`를 테스트 목적으로 설치한 적이 있었는데, 이때 설치된 `ingress-nginx`가 불완전 삭제되어 잔여 리소스가 남아있던 것이 문제였다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; ️ 해결 과정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결&amp;nbsp;방법은&amp;nbsp;K3s에&amp;nbsp;남아있는&amp;nbsp;불필요한&amp;nbsp;&lt;b&gt;ValidatingWebhookConfiguration를&lt;/b&gt; 지워주면 된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. ValidatingWebhookConfiguration&amp;nbsp;관련 잔여 데이터 조회&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cghiin/dJMcahDKZUf/rSQuECSnzzsIS14R0xPxfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cghiin/dJMcahDKZUf/rSQuECSnzzsIS14R0xPxfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cghiin/dJMcahDKZUf/rSQuECSnzzsIS14R0xPxfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcghiin%2FdJMcahDKZUf%2FrSQuECSnzzsIS14R0xPxfK%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;742&quot; height=&quot;230&quot; data-origin-width=&quot;742&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1774282223657&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kubectl get validatingwebhookconfigurations&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 통해 Nginx와 관련된 잔여 데이터(&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;`ingress-nginx-admission`&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;를 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 잔여 데이터 삭제&lt;/b&gt;&lt;/h4&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ kubectl delete validatingwebhookconfiguration ingress-nginx-admission&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;b&gt;3. 결과&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b04PlX/dJMcadafxER/FRBD8jsI1nb6E0axhqVv50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b04PlX/dJMcadafxER/FRBD8jsI1nb6E0axhqVv50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b04PlX/dJMcadafxER/FRBD8jsI1nb6E0axhqVv50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb04PlX%2FdJMcadafxER%2FFRBD8jsI1nb6E0axhqVv50%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;644&quot; height=&quot;182&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;182&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;잔여 데이터를 삭제하자마자 cert-manager는 즉각 인증서를 새롭게 발급했고, 사이트도 정상적으로 접속 가능했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  결론&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿠버네티스에서 어떠한 도구를 사용하든 &lt;b&gt;제거는 확실&lt;/b&gt;하게 해야 한다. (쿠버네티스에 국한된 얘기는 아닌 듯..)&lt;/li&gt;
&lt;li&gt;cert-manager의 인증서 갱신은 뒷단에서 조용히 실패하기 때문에, 자동으로 관리해 준다 하더라도 READY 상태나 만료일에 대한 &lt;b&gt;모니터링이 필수&lt;/b&gt;임을 깨달았다. (참고로 4월부터 AWS ACM을 사용해서 인증서를 발급받을 예정..)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Projects/MOISAM</category>
      <category>cert-manager</category>
      <category>https</category>
      <category>Ingress</category>
      <category>K3S</category>
      <category>kubernetes</category>
      <category>letsencrypt</category>
      <category>SSL</category>
      <category>traefik</category>
      <category>Troubleshooting</category>
      <category>모이삼</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/94</guid>
      <comments>https://developer-anxi.tistory.com/94#entry94comment</comments>
      <pubDate>Tue, 24 Mar 2026 01:29:36 +0900</pubDate>
    </item>
    <item>
      <title>Jar를 다이어트 시켜보자 (Layered Jar)</title>
      <link>https://developer-anxi.tistory.com/93</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요새 AWS로 마이그레이션을 진행하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마이그레이션을 진행하기 앞서, 배포 과정에서의 문제점을 살펴보고 개선할 수 있는 부분은 개선하고자 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1165&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2WXHw/dJMcacI5S68/vBdgVAU0kgQmnupiuor5M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2WXHw/dJMcacI5S68/vBdgVAU0kgQmnupiuor5M0/img.png&quot; data-alt=&quot;40초나 걸린다고?!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2WXHw/dJMcacI5S68/vBdgVAU0kgQmnupiuor5M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2WXHw%2FdJMcacI5S68%2FvBdgVAU0kgQmnupiuor5M0%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;1165&quot; height=&quot;394&quot; data-origin-width=&quot;1165&quot; data-origin-height=&quot;394&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;40초나 걸린다고?!&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;서버 로그를 살피고 있던 도중, 어느샌가 스프링 애플리케이션 초기 실행 시간이 40초에 근접했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 나는 Github Actions가 돌아가는 것이 배포의 시작이자 끝이라 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 애플리케이션 초기 실행 시간, 그리고 배포된 Docker Image를 Pull 하는 과정에 대해선 간과하고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초기 실행 시간을 줄일 순 없을까?&lt;/li&gt;
&lt;li&gt;배포 과정에서 도커 이미지를 만들고 push, pull 과정에서 개선할 수 없을까?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 나는 위 두 가지의 고민을 해결하고자 찾던 도중 &quot;&lt;b&gt;Layered Jar&lt;/b&gt;&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;&lt;b&gt;Layered Jar&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔히 `./gradlew bulid`를 통해 만들어진 Jar은 &quot;&lt;b&gt;Fat Jar&lt;/b&gt;&quot; 라고 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-03-10 오후 9.41.58.png&quot; data-origin-width=&quot;301&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwCeCc/dJMcabKb45r/6Qwbi3zbTT3xQ2gqnKGhO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwCeCc/dJMcabKb45r/6Qwbi3zbTT3xQ2gqnKGhO0/img.png&quot; data-alt=&quot;Fat Jar&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwCeCc/dJMcabKb45r/6Qwbi3zbTT3xQ2gqnKGhO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwCeCc%2FdJMcabKb45r%2F6Qwbi3zbTT3xQ2gqnKGhO0%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;301&quot; height=&quot;173&quot; data-filename=&quot;스크린샷 2026-03-10 오후 9.41.58.png&quot; data-origin-width=&quot;301&quot; data-origin-height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fat Jar&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;사진에서 보이는 server-0.0.1-SNAPSHOT.jar 내부에는 사용된 모든 라이브러리와 내가 짠 코드가 몽땅 들어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 보통은 배포할 때 `java -jar app.jar` 명령 한 줄로 어디서든 실행할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 소스 코드 한 줄만 수정해도 100MB가 넘는 Jar 파일이 새롭게 만들어진다.&lt;/p&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;&quot;Layered Jar&quot;&lt;/b&gt; 은 도커 이미지 생성 개선을 위해 Spring Boot 2.3.0에 도입된 것으로, Jar 내부에 'layers.idx'라는 인덱스 파일이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'layers.idx'는 의미 그대로 Jar 내부 파일이 어떤 레이어에 속하는지를 정의하는 지도 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot 는 다음 4가지 레이어를 기본으로 제공한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;559881850-c098b9d7-2c19-4d7f-8392-ec73cb4e8249.png&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhoNqb/dJMcadVtas3/WmTWdd9BfezLjXm09aXp41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhoNqb/dJMcadVtas3/WmTWdd9BfezLjXm09aXp41/img.png&quot; data-alt=&quot;Layered Jar&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhoNqb/dJMcadVtas3/WmTWdd9BfezLjXm09aXp41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhoNqb%2FdJMcadVtas3%2FWmTWdd9BfezLjXm09aXp41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;429&quot; data-filename=&quot;559881850-c098b9d7-2c19-4d7f-8392-ec73cb4e8249.png&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Layered Jar&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,0,0&quot;&gt;dependencies&lt;/b&gt;: 버전에 SNAPSHOT이 포함되지 않은 일반 외부 라이브러리. (가장 안 변함)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,1,0&quot;&gt;spring-boot-loader&lt;/b&gt;: Jar를 실행하기 위한 로더 클래스들.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,2,0&quot;&gt;snapshot-dependencies&lt;/b&gt;: 버전에 SNAPSHOT이 포함된, 자주 바뀔 수 있는 내부 라이브러리.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,3,0&quot;&gt;application&lt;/b&gt;: 우리가 작성한 소스 코드(. class)와 리소스 파일들. (가장 자주 변함)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fat Jar, Layered Jar를 비교하는 것만으론 Layered Jar의 장점을 이해하기 어렵다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜냐하면 Layered Jar는 Dockerfile로&amp;nbsp;빌드할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;최적화된&amp;nbsp;Docker&amp;nbsp;이미지를&amp;nbsp;더&amp;nbsp;쉽게&amp;nbsp;생성하기 위해 나온 것이기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  Docker 의 이미지 구축 방식&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;399&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnTIEZ/dJMcaf6Q8yT/kvMkqwMq1G5fh9kHi23axK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnTIEZ/dJMcaf6Q8yT/kvMkqwMq1G5fh9kHi23axK/img.png&quot; data-alt=&quot;Docker Image Layer&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnTIEZ/dJMcaf6Q8yT/kvMkqwMq1G5fh9kHi23axK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnTIEZ%2FdJMcaf6Q8yT%2FkvMkqwMq1G5fh9kHi23axK%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;1280&quot; height=&quot;399&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;399&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Docker Image Layer&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;p data-ke-size=&quot;size16&quot;&gt;도커 이미지는 여러 개의 레이어를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사진처럼 DockerFile에 작성된 명령어마다 레이어를 가지며 순서대로 차곡차곡 쌓인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 새로운 이미지가 만들어졌을 때의 레이어의 변경점이 없다면, 새 이미지의 레이어를 덮어 씌우는 것이 아닌 레이어 캐시를 사용해 레이어를 재사용한다. 레이어의 재사용은 빌드 속도를 향상할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Layered Jar의 4가지 레이어를 도커 레이어에 각각 배치한다. 변경될 가능성이 거의 없는 레이어(dependencies, spring-boot-loader ..)들은 도커 캐시를 통해 재사용하고, 매번 수정되는 application 레이어만 교체하는 식으로 개선할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 Fat Jar 방식처럼 큰 덩어리를 전부 바꿔치기 하는 대신, 코드가 변경된 일부만 쏙 골라 배포할 수 있게 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Layered Jar를 사용해서 개선해보자&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1773148484538&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM eclipse-temurin:21-jre-alpine AS builder
WORKDIR /app
ARG JAR_FILE=./*.jar
COPY ${JAR_FILE} app.jar
RUN java -Djarmode=layertools -jar app.jar extract

FROM eclipse-temurin:21-jre-alpine
WORKDIR /app

COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./

ENTRYPOINT [&quot;java&quot;, &quot;org.springframework.boot.loader.launch.JarLauncher&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티 스테이지로 DockerFile을 구성하여 builder 스테이지에서 추출한 레이어를 runner 스테이지에서 COPY 하여 사용하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;builder 스테이지&lt;/b&gt;: `&lt;b&gt;java -Djarmode=layertools -jar&lt;/b&gt;` 명령어로 JAR에서 레이어를 &lt;b&gt;추출(extract)&lt;/b&gt;하는 과정.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;runner 스테이지&lt;/b&gt;: 추출된 4개의 레이어를 &lt;b data-index-in-node=&quot;26&quot; data-path-to-node=&quot;9,0,1,1,0&quot;&gt;순서대로&lt;/b&gt;&amp;nbsp;COPY 하는 과정.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;❗️COPY 과정이 매우 중요❗️&lt;/b&gt;&lt;br /&gt;도커 레이어는 특정 레이어에서 변경 사항이 생길 경우, 이후 &lt;b&gt;모든 레이어를 전부 무효화한다.&lt;/b&gt;&lt;br /&gt;따라서 COPY 시, &lt;b&gt;변경 사항이 가장 낮은 dependencies 순&lt;/b&gt;으로 진행해야 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;❗️Spring Boot 3.2 이상 사용 중이라면?❗️&lt;/b&gt;&lt;br /&gt;RUN java -Djarmode=layertools -jar app.jar extract 이&amp;nbsp;&lt;b&gt;Deprecated&lt;/b&gt;&amp;nbsp;되었다고 한다.&lt;br /&gt;따라서 다음과 같이 변경한다.&lt;br /&gt;&lt;b&gt;RUN java -Djarmode=tools -jar app.jar extract --layers --launcher&lt;/b&gt;&lt;br /&gt;(바꾸지 않아도 동작하지만,, 혹시 모르니 변경하기를 바란다.)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 구성한 뒤, 두 번째 배포부터 레이어의 캐싱을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-03-10 오후 10.30.17.png&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dP2648/dJMcacoLMfQ/QHaBHAebbIRjPUTTqLhuyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dP2648/dJMcacoLMfQ/QHaBHAebbIRjPUTTqLhuyK/img.png&quot; data-alt=&quot;dependencies, spring-boot-loader 가 캐싱 됨을 확인할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dP2648/dJMcacoLMfQ/QHaBHAebbIRjPUTTqLhuyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdP2648%2FdJMcacoLMfQ%2FQHaBHAebbIRjPUTTqLhuyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;887&quot; height=&quot;818&quot; data-filename=&quot;스크린샷 2026-03-10 오후 10.30.17.png&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;dependencies, spring-boot-loader 가 캐싱 됨을 확인할 수 있다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckUHw4/dJMcagYZF3I/wNkpH26mGpIZFoH2hKF7I0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckUHw4/dJMcagYZF3I/wNkpH26mGpIZFoH2hKF7I0/img.png&quot; data-alt=&quot;기존 Jar 방식의 Docker Image Layer&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckUHw4/dJMcagYZF3I/wNkpH26mGpIZFoH2hKF7I0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckUHw4%2FdJMcagYZF3I%2FwNkpH26mGpIZFoH2hKF7I0%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;1141&quot; height=&quot;304&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기존 Jar 방식의 Docker Image Layer&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C4ogN/dJMcabXHw2O/QWVi9ZMSQ0vqRbN5t3FMzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C4ogN/dJMcabXHw2O/QWVi9ZMSQ0vqRbN5t3FMzk/img.png&quot; data-alt=&quot;Layered Jar의 Docker Image Layer&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C4ogN/dJMcabXHw2O/QWVi9ZMSQ0vqRbN5t3FMzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC4ogN%2FdJMcabXHw2O%2FQWVi9ZMSQ0vqRbN5t3FMzk%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;1144&quot; height=&quot;329&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Layered Jar의 Docker Image Layer&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;개선 결과&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_o34txbo34txbo34t.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ntBJe/dJMcaadqVLs/1hA9juXOkXClRDt02PABj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ntBJe/dJMcaadqVLs/1hA9juXOkXClRDt02PABj0/img.png&quot; data-alt=&quot;Gemini야 고마워&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ntBJe/dJMcaadqVLs/1hA9juXOkXClRDt02PABj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FntBJe%2FdJMcaadqVLs%2F1hA9juXOkXClRDt02PABj0%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_o34txbo34txbo34t.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Gemini야 고마워&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;좌측 그래프: 이미지 Pull 성능 비교 (PULL 할 경우)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,1,0,0&quot;&gt;내용:&lt;/b&gt; 쿠버네티스 노드가 이미지를 다운로드하는 데 걸린 시간&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,1,1,0&quot;&gt;해석:&lt;/b&gt; 기존 Jar 방식은 전체를 다운로드해야 해서 &lt;b data-index-in-node=&quot;36&quot; data-path-to-node=&quot;5,0,1,1,0&quot;&gt;4초&lt;/b&gt;가 걸렸지만, Layered Jar 방식은 변경된 소스(application) 레이어만 다운로드하므로&lt;b data-index-in-node=&quot;82&quot; data-path-to-node=&quot;5,0,1,1,0&quot;&gt;&amp;nbsp;1초&lt;/b&gt; 만에 완료되었다. 현재는 도커 이미지가 크지 않아 엄청 크게 와닿지는 않지만, 도커 이미지가 커진다면 75%의 시간 단축은 꽤나 유의미한 개선일 것 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;우측 그래프: 초기 실행 성능 비교 (초기 실행 시간)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,1,0,0&quot;&gt;내용:&lt;/b&gt; 스프링 애플리케이션이 시작되어 서비스 준비가 되기까지 걸린 시간&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,1,1,0&quot;&gt;해석:&lt;/b&gt; 기존 Jar 방식의 &lt;b data-index-in-node=&quot;16&quot; data-path-to-node=&quot;5,1,1,1,0&quot;&gt;40초&lt;/b&gt;에 비해, Layered Jar 방식은 &lt;b data-index-in-node=&quot;41&quot; data-path-to-node=&quot;5,1,1,1,0&quot;&gt;20초&lt;/b&gt;로 단축되었다. 기존 Jar 방식은 압축이 되어 있어 압축 해제하고 클래스 로딩하는데 시간이 소요되지만, Layered Jar 방식은 DockerFile에서 extract로 압축을 풀었기 때문에 곧장 클래스 로딩을 하여 시간이 단축된 것으로 확인된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Layered Jar 적용 후, Github Actions 빌드가 끝난 시점부터 실제 서비스가 가동되기까지의 소요 시간을 &lt;b data-index-in-node=&quot;69&quot; data-path-to-node=&quot;5,0&quot;&gt;44초에서 21초&lt;/b&gt;로 &lt;b data-index-in-node=&quot;69&quot; data-path-to-node=&quot;5,0&quot;&gt;약 52% 단축&lt;/b&gt;했다. 무중단 배포가 되어 있지 않을 경우, Layered Jar을 적용하면 다운타임을 줄일 수 있으므로 용이할 것 같다. 다음에는 &lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;애플리케이션 클래스 데이터 공유(Application Class-Data Sharing)를 활용해서 시간을 더 낮출 수 있을지도 확인해 봐야겠다. Spring AOT라는 것도 있던데.. 이것도 되면 확인해 봐야겠다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;출처&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://spring.io/blog/2020/01/27/creating-docker-images-with-spring-boot-2-3-0-m1&quot;&gt;https://spring.io/blog/2020/01/27/creating-docker-images-with-spring-boot-2-3-0-m1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://spring.io/blog/2020/08/14/creating-efficient-docker-images-with-spring-boot-2-3&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://spring.io/blog/2020/08/14/creating-efficient-docker-images-with-spring-boot-2-3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/devops/what-is-docker-image-layer/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.geeksforgeeks.org/devops/what-is-docker-image-layer/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://netmarble.engineering/class-data-sharing-cds-and-layered-jar/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://netmarble.engineering/class-data-sharing-cds-and-layered-jar/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Backend/CI CD</category>
      <category>cicd</category>
      <category>devops</category>
      <category>docker</category>
      <category>Docker cache</category>
      <category>Docker Layer</category>
      <category>DockerOptimization</category>
      <category>FatJar</category>
      <category>jar</category>
      <category>LayeredJar</category>
      <category>springboot</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/93</guid>
      <comments>https://developer-anxi.tistory.com/93#entry93comment</comments>
      <pubDate>Tue, 10 Mar 2026 23:21:24 +0900</pubDate>
    </item>
    <item>
      <title>[모이삼] AWS 1000달러 크레딧을 받았다. (AWS Startups)</title>
      <link>https://developer-anxi.tistory.com/92</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  모이삼의 서버 비용은 어떻게 처리해?&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;open graph.png&quot; data-origin-width=&quot;4800&quot; data-origin-height=&quot;2520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nvktn/dJMcahDqnFH/YKyIwJjWOzwaCkVIyiWqi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nvktn/dJMcahDqnFH/YKyIwJjWOzwaCkVIyiWqi1/img.png&quot; data-alt=&quot;모이삼 : https://moisam.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nvktn/dJMcahDqnFH/YKyIwJjWOzwaCkVIyiWqi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnvktn%2FdJMcahDqnFH%2FYKyIwJjWOzwaCkVIyiWqi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;651&quot; height=&quot;342&quot; data-filename=&quot;open graph.png&quot; data-origin-width=&quot;4800&quot; data-origin-height=&quot;2520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모이삼 : https://moisam.kr&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;나는 작년 9월부터 &lt;b&gt;&quot;&lt;a href=&quot;https://moisam.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;모이삼&lt;/a&gt;&quot;&lt;/b&gt;이라는 웹 서비스를 운영하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;큐시즘(한국대학생IT경영학회)&lt;/b&gt;에서 시작된 모이삼은 감사하게도 &lt;b&gt;네이버 클라우드&lt;/b&gt;에서 서버 비용을 지원해 주셨다. 그 결과 서버비에 구애받지 않고 넉넉히 사용할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 6.54.40.png&quot; data-origin-width=&quot;2282&quot; data-origin-height=&quot;858&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H4tAQ/dJMcahXKn8D/MIII9oVfkRivXj0FYNu67k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H4tAQ/dJMcahXKn8D/MIII9oVfkRivXj0FYNu67k/img.png&quot; data-alt=&quot;네이버 클라우드에서 받은 크레딧&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H4tAQ/dJMcahXKn8D/MIII9oVfkRivXj0FYNu67k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH4tAQ%2FdJMcahXKn8D%2FMIII9oVfkRivXj0FYNu67k%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;2282&quot; height=&quot;858&quot; data-filename=&quot;스크린샷 2026-02-22 오후 6.54.40.png&quot; data-origin-width=&quot;2282&quot; data-origin-height=&quot;858&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;p data-ke-size=&quot;size16&quot;&gt;다만 달에 10만원 가까이 나가는 서버비는 올해 3월이면 고갈되었고, 서버비를 충당하기 위해 방법을 찾던 도중 &lt;b&gt;&quot;AWS Startups 크레딧 지원&quot;&lt;/b&gt;을 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.07.00.png&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;1002&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qHQm6/dJMb996ucJJ/Ltfv6GSswEXpgUClU5wEPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qHQm6/dJMb996ucJJ/Ltfv6GSswEXpgUClU5wEPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qHQm6/dJMb996ucJJ/Ltfv6GSswEXpgUClU5wEPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqHQm6%2FdJMb996ucJJ%2FLtfv6GSswEXpgUClU5wEPk%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;2250&quot; height=&quot;1002&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.07.00.png&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;1002&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;결론부터 말하면, 우리는 AWS Startup 창업자(Founders) 티어를 신청하였고 승인되어 &lt;b&gt;1,000 달러&lt;/b&gt;를 받았다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서 큰 금액을 지원하는 만큼, 쉽게 승인되는 것은 아니라서 신청부터 반려된 경험과 승인까지 이뤄낸 과정을 후술 하고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AWS Startup Credit을 알려준 상호형에게 다시 한번 감사 인사 드리며, &lt;a href=&quot;https://velog.io/@hsh111366/5%EB%B6%84-%EB%A7%8C%EC%97%90-AWS-140%EB%A7%8C%EC%9B%90-%EB%B2%8C%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;상호형의 블로그 글&lt;/a&gt;로 많은 도움을 받았습니다!!)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  AWS Activate 프로그램이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Activate 프로그램은 AWS에서 스타트업을 위해 지원하는 프로그램이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Activate 멤버가 되면 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;클라우드 크레딧, 기술 지원 및 비즈니스 멘토십을 제공받을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.15.05.png&quot; data-origin-width=&quot;2124&quot; data-origin-height=&quot;1272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9vRXJ/dJMcachQifX/OwxbDzTtkkkkgEGCvue3wK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9vRXJ/dJMcachQifX/OwxbDzTtkkkkgEGCvue3wK/img.png&quot; data-alt=&quot;AWS Activate 크레딧&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9vRXJ/dJMcachQifX/OwxbDzTtkkkkgEGCvue3wK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9vRXJ%2FdJMcachQifX%2FOwxbDzTtkkkkgEGCvue3wK%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;2124&quot; height=&quot;1272&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.15.05.png&quot; data-origin-width=&quot;2124&quot; data-origin-height=&quot;1272&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS Activate 크레딧&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;AWS Activate 크레딧은 &quot;&lt;b&gt;Activate Founders&lt;/b&gt;&quot;와 &quot;&lt;b&gt;Activate Portfolio&lt;/b&gt;&quot;가 있다. Portfolio는 최대 10만 달러까지 받을 수 있으나, Activate 제공업체가 있어야 한다. 모이삼은 Activate 제공업체가 없기 때문에 &lt;b&gt;Activate Founders&lt;/b&gt;를 신청했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS Activate 크레딧의 자격 요건&lt;/b&gt;은 다음과 같다. (출처: &lt;span&gt;Ask AWS Startups)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,0,0&quot;&gt;기업 단계:&lt;/b&gt; 부트스트랩(자체 자금 조달), 자기 자본 조달, 그리고 &lt;b data-index-in-node=&quot;38&quot; data-path-to-node=&quot;3,0,0&quot;&gt;시리즈 A 단계 이하&lt;/b&gt;의 투자를 유치한 스타트업까지 신청 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;설립 연도:&lt;/b&gt; 기업 설립일로부터 &lt;b data-index-in-node=&quot;17&quot; data-path-to-node=&quot;3,1,0&quot;&gt;10년 이내&lt;/b&gt;인 스타트업이어야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,2,0&quot;&gt;온라인 존재 여부:&lt;/b&gt; 스타트업의 &lt;b data-index-in-node=&quot;17&quot; data-path-to-node=&quot;3,2,0&quot;&gt;활성화된 웹사이트&lt;/b&gt; 또는 공식적인 퍼블릭 프로필(링크드인 등)이 반드시 있어야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,3,0&quot;&gt;이메일 계정:&lt;/b&gt; AWS Activate 프로필과 크레딧 신청 시, 스타트업의 &lt;b data-index-in-node=&quot;42&quot; data-path-to-node=&quot;3,3,0&quot;&gt;자체 도메인과 일치하는 비즈니스 이메일 주소&lt;/b&gt;를 사용해야 합니다. (예: name@yourstartup.com)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,4,0&quot;&gt;지역 제한:&lt;/b&gt; &lt;b data-index-in-node=&quot;7&quot; data-path-to-node=&quot;3,4,0&quot;&gt;AWS 중국 리전&lt;/b&gt;에서 서비스를 구축 중인 스타트업은 일반 AWS Activate 프로그램 대상에서 제외됩니다. (중국 리전은 별도의 전용 프로그램이 운영됩니다.)&lt;/li&gt;
&lt;/ul&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;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  신청 절차&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS Activate Credit 신청 절차&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;Ask AWS Startups)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,0,0&quot;&gt;AWS Builder ID 생성:&lt;/b&gt; 먼저 AWS 서비스 통합 관리를 위한 &lt;b data-index-in-node=&quot;40&quot; data-path-to-node=&quot;3,0,0&quot;&gt;AWS Builder ID&lt;/b&gt;를 만드세요.&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;3,2,0&quot; data-index-in-node=&quot;0&quot;&gt;패키지 선택:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;스타트업의 상황에 맞춰 다음 두 가지 중 하나를 선택하세요.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot; data-path-to-node=&quot;3,2,1&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;3,2,1,0,0&quot; data-index-in-node=&quot;0&quot;&gt;Founders Package(창업자 패키지):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;외부 투자 없이 자력으로 운영 중인(Self-funded) 스타트업용&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;3,2,1,1,0&quot; data-index-in-node=&quot;0&quot;&gt;Portfolio Package(포트폴리오 패키지):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;엑셀러레이터나 VC 등 파트너사로부터 투자 및 지원을 받는(Provider-backed) 스타트업용&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;AWS Activate 프로필 작성:&lt;/b&gt; 가입 후 본인의 &lt;b data-index-in-node=&quot;30&quot; data-path-to-node=&quot;3,1,0&quot;&gt;AWS Activate 프로필&lt;/b&gt; 정보를 모두 입력하여 완료하세요.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,3,0&quot;&gt;상세 정보 제공:&lt;/b&gt; 비즈니스 세부 정보, 제품 설명, 현재 펀딩 상태(투자 단계) 등 스타트업에 관한 &lt;b data-index-in-node=&quot;56&quot; data-path-to-node=&quot;3,3,0&quot;&gt;정확한 정보&lt;/b&gt;를 입력하세요.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;b data-path-to-node=&quot;3,0,0&quot; data-index-in-node=&quot;0&quot;&gt;AWS Builder ID 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/startups&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://aws.amazon.com/startups&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사이트에 접속하여 회원가입한다. 이 계정은 AWS 계정과는 다른 Builder 계정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2️⃣ 크레딧 &lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,2,0&quot;&gt;패키지 선택&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2390&quot; data-origin-height=&quot;1392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l3Ljo/dJMcagR5bEq/hjRebiTFGeVtojO1m9pWx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l3Ljo/dJMcagR5bEq/hjRebiTFGeVtojO1m9pWx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l3Ljo/dJMcagR5bEq/hjRebiTFGeVtojO1m9pWx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl3Ljo%2FdJMcagR5bEq%2FhjRebiTFGeVtojO1m9pWx0%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;2390&quot; height=&quot;1392&quot; data-origin-width=&quot;2390&quot; data-origin-height=&quot;1392&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;로그인 후, AWS 크레딧 탭에 진입 &amp;gt; &quot;지금 신청&quot; 클릭한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.42.13.png&quot; data-origin-width=&quot;2412&quot; data-origin-height=&quot;1436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4aLUq/dJMcajnFhyi/6rCnTowSfzjk7cws9TsTK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4aLUq/dJMcajnFhyi/6rCnTowSfzjk7cws9TsTK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4aLUq/dJMcajnFhyi/6rCnTowSfzjk7cws9TsTK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4aLUq%2FdJMcajnFhyi%2F6rCnTowSfzjk7cws9TsTK0%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;2412&quot; height=&quot;1436&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.42.13.png&quot; data-origin-width=&quot;2412&quot; data-origin-height=&quot;1436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀에 맞는 크레딧 패키지를 선택한다. 모이삼은 &lt;b&gt;창립자 티어 (Founder)&lt;/b&gt;를 선택했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;b data-path-to-node=&quot;3,1,0&quot; data-index-in-node=&quot;0&quot;&gt;프로필 작성&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.50.11.png&quot; data-origin-width=&quot;2410&quot; data-origin-height=&quot;1492&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xytae/dJMcaiI5cPq/V8S95NokCvezrXF6O7nq0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xytae/dJMcaiI5cPq/V8S95NokCvezrXF6O7nq0k/img.png&quot; data-alt=&quot;내 프로필&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xytae/dJMcaiI5cPq/V8S95NokCvezrXF6O7nq0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXytae%2FdJMcaiI5cPq%2FV8S95NokCvezrXF6O7nq0k%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;2410&quot; height=&quot;1492&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.50.11.png&quot; data-origin-width=&quot;2410&quot; data-origin-height=&quot;1492&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;p data-ke-size=&quot;size16&quot;&gt;신청자의 프로필을 작성한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 모이삼의 CTO를 맡고 있다   나를 최대한 PR 하기 위해 LinkedIn 프로필도 넣어줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외 항목은 본인이 원하는 대로 기입하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.53.46.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qw4xQ/dJMcahwG7Pn/9R6f6JVJPoYoxUkBikhfuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qw4xQ/dJMcahwG7Pn/9R6f6JVJPoYoxUkBikhfuk/img.png&quot; data-alt=&quot;팀 프로필&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qw4xQ/dJMcahwG7Pn/9R6f6JVJPoYoxUkBikhfuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqw4xQ%2FdJMcahwG7Pn%2F9R6f6JVJPoYoxUkBikhfuk%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;2378&quot; height=&quot;1316&quot; data-filename=&quot;스크린샷 2026-02-22 오후 7.53.46.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1316&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;p data-ke-size=&quot;size16&quot;&gt;아래로 스크롤하면 스타트업 프로필을 작성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹사이트 URL을 입력했고, 공개 프로필로는 PM 현수가 Product Hunt에 모이삼을 올렸어서 이를 넣어줬다. 서비스를 PR 하기 위해 공개 프로필은 꼭 넣어주는 게 좋을 것 같다. (디스콰이엇, 링크드인 등등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;4️⃣ 제품 및 자금 조달 설명 작성&lt;/b&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2396&quot; data-origin-height=&quot;1380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eE458U/dJMb99ZJWSU/v0ViH5hUCJZfdfyqz38AwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eE458U/dJMb99ZJWSU/v0ViH5hUCJZfdfyqz38AwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eE458U/dJMb99ZJWSU/v0ViH5hUCJZfdfyqz38AwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeE458U%2FdJMb99ZJWSU%2Fv0ViH5hUCJZfdfyqz38AwK%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;2396&quot; height=&quot;1380&quot; data-origin-width=&quot;2396&quot; data-origin-height=&quot;1380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.03.19.png&quot; data-origin-width=&quot;2396&quot; data-origin-height=&quot;986&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z1mBG/dJMcafySE6h/Jk9KpVv4RkbKcRAKULWSdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z1mBG/dJMcafySE6h/Jk9KpVv4RkbKcRAKULWSdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z1mBG/dJMcafySE6h/Jk9KpVv4RkbKcRAKULWSdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ1mBG%2FdJMcafySE6h%2FJk9KpVv4RkbKcRAKULWSdK%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;2396&quot; height=&quot;986&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.03.19.png&quot; data-origin-width=&quot;2396&quot; data-origin-height=&quot;986&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제품 설명은 서비스에 맞게 작성하면 된다. 여기서 가장 중요한 부분은 &lt;b&gt;서비스 소개글&lt;/b&gt;이다. 250자까지만 작성 가능하여 최대한 옹골지게 작성해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모이삼은 &quot;&lt;b&gt;서비스 소개 + MAU 성장률 + 발전 가능성&lt;/b&gt;&quot; 에 대해 작성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 자금 조달 설명을 작성해야 하는데 모이삼은 투자를 받지 않아 &quot;&lt;b&gt;자금 조달 없음&lt;/b&gt;&quot;으로 선택하고 넘겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-path-to-node=&quot;3,1,0&quot; data-index-in-node=&quot;0&quot;&gt;5️⃣ AWS 계정 연결 + 신청서 제출&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.10.06.png&quot; data-origin-width=&quot;2226&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRwGBP/dJMcaibiIPK/AsURWpsKaPjE8U193RXo1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRwGBP/dJMcaibiIPK/AsURWpsKaPjE8U193RXo1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRwGBP/dJMcaibiIPK/AsURWpsKaPjE8U193RXo1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRwGBP%2FdJMcaibiIPK%2FAsURWpsKaPjE8U193RXo1K%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;2226&quot; height=&quot;598&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.10.06.png&quot; data-origin-width=&quot;2226&quot; data-origin-height=&quot;598&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;AWS 계정은 크레딧 받을 계정으로 연결하면 된다. 연결 후 &lt;b&gt;신청서 제출 &lt;/b&gt;버튼을 클릭하여 신청서를 제출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6️⃣ 신청 완료&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.13.29.png&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRymQj/dJMcahDqqig/AJAkKlmKMnxbfD8X63YR9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRymQj/dJMcahDqqig/AJAkKlmKMnxbfD8X63YR9K/img.png&quot; data-alt=&quot;신청 메일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRymQj/dJMcahDqqig/AJAkKlmKMnxbfD8X63YR9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRymQj%2FdJMcahDqqig%2FAJAkKlmKMnxbfD8X63YR9K%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;2208&quot; height=&quot;1132&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.13.29.png&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1132&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.15.37.png&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biP2A8/dJMcahcmFzo/RkKHZW82xhybkzmfH3cAp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biP2A8/dJMcahcmFzo/RkKHZW82xhybkzmfH3cAp1/img.png&quot; data-alt=&quot;AWS Startups&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biP2A8/dJMcahcmFzo/RkKHZW82xhybkzmfH3cAp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiP2A8%2FdJMcahcmFzo%2FRkKHZW82xhybkzmfH3cAp1%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;2386&quot; height=&quot;1112&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.15.37.png&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1112&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS Startups&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;신청이 완료되면 회사 이메일로 확인 메일이 발송되며, AWS Startups 홈페이지에서도 상태를 확인할 수 있다. (페이지 내 &lt;b data-index-in-node=&quot;86&quot; data-path-to-node=&quot;6,0&quot;&gt;'신청서 제출' 항목에 체크 표시&lt;/b&gt;가 되어 있다.)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;❌ 첫 번째 신청: 반려 (AWS 이메일과 도메인 불일치)&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.19.01.png&quot; data-origin-width=&quot;2348&quot; data-origin-height=&quot;966&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce8Vef/dJMcaadgi7H/dlZSKKaVTduiMYrXkvvABK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce8Vef/dJMcaadgi7H/dlZSKKaVTduiMYrXkvvABK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce8Vef/dJMcaadgi7H/dlZSKKaVTduiMYrXkvvABK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce8Vef%2FdJMcaadgi7H%2FdlZSKKaVTduiMYrXkvvABK%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;2348&quot; height=&quot;966&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.19.01.png&quot; data-origin-width=&quot;2348&quot; data-origin-height=&quot;966&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하루 만에 결과가 나왔다. 반려되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 &lt;b&gt;AWS 계정과 서비스 도메인이 일치하지 않기&lt;/b&gt; 때문이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모이삼 AWS 계정은 구글 메일(&lt;b&gt;@gmail.com&lt;/b&gt;)이어서 이를 도메인(&lt;b&gt;@moisam.kr&lt;/b&gt;)으로 바꿔야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인으로 메일을 만들기 위해서는 Google Workspace나 Naver Works 등을 사용하여 비즈니스 메일을 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 Naver Works로 비즈니스 메일을 만들었고, AWS 계정을 비즈니스 메일로 변경하여 재신청하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AWS 계정 변경 방법은 &lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/accounts/latest/reference/manage-acct-update-root-user-email.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;해당 문서&lt;/a&gt;를 참고했다.)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;❌ 두 번째 신청: 반려 (서비스 문제)&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.31.40.png&quot; data-origin-width=&quot;1130&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/euAotr/dJMcad13QqT/ZkMPhFWb65M7uKveFHUkjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/euAotr/dJMcad13QqT/ZkMPhFWb65M7uKveFHUkjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/euAotr/dJMcad13QqT/ZkMPhFWb65M7uKveFHUkjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeuAotr%2FdJMcad13QqT%2FZkMPhFWb65M7uKveFHUkjK%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;1130&quot; height=&quot;258&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.31.40.png&quot; data-origin-width=&quot;1130&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비즈니스 메일로 바꾸고도 반려되었다. 이미 위 사항들은 수정하고 나서 신청했었는데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 나는 &lt;a href=&quot;https://aws.amazon.com/startups/contact-us/contact-support&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AWS Startups 문의&lt;/a&gt;를 통해 우리의 상황이 자격 요건을 충족함을 나타냈고, 어떤 이유로 반려되었는지를 문의했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문의를 기다리던 도중, 메일이 도착했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.35.45.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;1010&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9RaIx/dJMcadOwlAB/klPL73o3I8NIowsHkKKckk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9RaIx/dJMcadOwlAB/klPL73o3I8NIowsHkKKckk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9RaIx/dJMcadOwlAB/klPL73o3I8NIowsHkKKckk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9RaIx%2FdJMcadOwlAB%2FklPL73o3I8NIowsHkKKckk%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;642&quot; height=&quot;612&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.35.45.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;1010&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이널 리뷰 진행 중이며, 상태가 바뀌면 이메일로 연락을 준다는 것이다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때부터 될 거 같은 느낌이 솔솔 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;✅ 두 번째 신청: 반려 (서비스 문제) -&amp;gt; 승인&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.39.15.png&quot; data-origin-width=&quot;2372&quot; data-origin-height=&quot;984&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JE1bR/dJMcafr5kqx/ePse2E4b5YtbBzpFMHqy50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JE1bR/dJMcafr5kqx/ePse2E4b5YtbBzpFMHqy50/img.png&quot; data-alt=&quot; &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JE1bR/dJMcafr5kqx/ePse2E4b5YtbBzpFMHqy50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJE1bR%2FdJMcafr5kqx%2FePse2E4b5YtbBzpFMHqy50%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;2372&quot; height=&quot;984&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.39.15.png&quot; data-origin-width=&quot;2372&quot; data-origin-height=&quot;984&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;스크린샷 2026-02-22 오후 8.38.40.png&quot; data-origin-width=&quot;2192&quot; data-origin-height=&quot;1092&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SQAnW/dJMcafMqaKM/z6Ila8xiY1GCXpEgvjppzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SQAnW/dJMcafMqaKM/z6Ila8xiY1GCXpEgvjppzk/img.png&quot; data-alt=&quot; &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SQAnW/dJMcafMqaKM/z6Ila8xiY1GCXpEgvjppzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSQAnW%2FdJMcafMqaKM%2Fz6Ila8xiY1GCXpEgvjppzk%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;2192&quot; height=&quot;1092&quot; data-filename=&quot;스크린샷 2026-02-22 오후 8.38.40.png&quot; data-origin-width=&quot;2192&quot; data-origin-height=&quot;1092&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;p data-ke-size=&quot;size16&quot;&gt;파이널 리뷰 진행 중이라는 메일을 받은 후, 다음 날에 승인 결과를 받았다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버비에 대한 부담이 있었는데 메일을 받고 근심 걱정 다 날아갔다  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; &amp;zwj;↕️ 마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 모이삼도 AWS 크레딧(1,000달러)을 사용할 수 있게 되었다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 클라우드를 떠나 AWS로 마이그레이션하면서 아키텍처도 개편할 계획인데 ECS나 ALB 등을 사용하여 개편할 생각에 설렌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 큰 힘이 되어준 네이버 클라우드, 그리고 기회를 주신 AWS 모두 감사합니다 ☺️&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Projects/MOISAM</category>
      <category>AWS</category>
      <category>AWS Activate</category>
      <category>AWS Credits</category>
      <category>Founders Package</category>
      <category>MOISAM</category>
      <category>Naver Cloud Platform</category>
      <category>모이삼</category>
      <category>중간장소 찾기</category>
      <category>중간지점 찾기</category>
      <category>크레딧</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/92</guid>
      <comments>https://developer-anxi.tistory.com/92#entry92comment</comments>
      <pubDate>Sun, 22 Feb 2026 20:55:40 +0900</pubDate>
    </item>
    <item>
      <title>[모이삼] 한 달 만에 MAU 300% 성장 (feat. 회고)</title>
      <link>https://developer-anxi.tistory.com/91</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-28 오후 12.19.30.png&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ccu1m/dJMcagD9D72/hfrhaTk2z0iWG1mKKtMv30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ccu1m/dJMcagD9D72/hfrhaTk2z0iWG1mKKtMv30/img.png&quot; data-alt=&quot;2025.12.28 기준&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ccu1m/dJMcagD9D72/hfrhaTk2z0iWG1mKKtMv30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCcu1m%2FdJMcagD9D72%2FhfrhaTk2z0iWG1mKKtMv30%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;775&quot; height=&quot;394&quot; data-filename=&quot;스크린샷 2025-12-28 오후 12.19.30.png&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;394&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2025.12.28 기준&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;b&gt;Thanks to. 현수, 현비   최고의 팀원들과 같이 할 수 있어 영광이었습니다  &amp;zwj;↕️&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;최고의 사람들이 만든 서비스를 사용하고 싶다면? 아래 링크를 통해 마음껏 사용해 보세요!&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;  모이삼 바로가기:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://moisam.kr&quot;&gt;https://moisam.kr&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;  피드백 남기기:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://forms.gle/3GDyQcZezyMf6fi2A&quot;&gt;https://forms.gle/3GDyQcZezyMf6fi2A&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;발단 : 모이삼 이대로 괜찮은가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐시즘이 끝나고도 모이삼은 꾸준히 발전했다. SPOT에서 MOISAM으로 서비스 명 변경, UIUX 개선, 서버 장애 대응 등 각 파트에서 무던히 노력해 왔다. 다만, 다들 취업 시기가 다가왔고 취업 준비를 하면서 모이삼에 쓸 수 있는 리소스가 부족했다. 또한 리소스가 있어도 큐시즘이라는 동기부여가 사라진 이상, 팀의 활력을 불어줄 무언가 필요했다.&lt;/p&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월 중순, PM 현수와 1시간 넘게 이야기를 나눴다. 모이삼의 활력을 줄 수 있는 건 결국 &quot;&lt;b&gt;사용자&lt;/b&gt;&quot;였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모이삼은 &quot;&lt;b&gt;중간지점 찾기&lt;/b&gt;&quot;의 니즈가 명확해서 사용자에게 홍보만 된다면 충분히 많이 쓸 서비스라 생각했다. 그래서 우리는 2025년 남은 기간 '&lt;b&gt;마케팅에 집중하자&lt;/b&gt;'는 목표를 잡고 나아가기 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-28 오후 12.35.41.png&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HF86z/dJMcaajCuPL/h7Nmp0bKq3h0eKzeyygHD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HF86z/dJMcaajCuPL/h7Nmp0bKq3h0eKzeyygHD0/img.png&quot; data-alt=&quot;10월 MAU&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HF86z/dJMcaajCuPL/h7Nmp0bKq3h0eKzeyygHD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHF86z%2FdJMcaajCuPL%2Fh7Nmp0bKq3h0eKzeyygHD0%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;769&quot; height=&quot;382&quot; data-filename=&quot;스크린샷 2025-12-28 오후 12.35.41.png&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;382&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;10월 MAU&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;전개 1 : GA (Google Analytics) 공부&lt;/b&gt;&lt;/h2&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/dVaOta/dJMcadHnljY/Jv6iXlMMFHgUmNxKbKcrP1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVaOta/dJMcadHnljY/Jv6iXlMMFHgUmNxKbKcrP1/img.jpg&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;1200&quot; data-filename=&quot;XL.jpeg&quot; width=&quot;308&quot; height=&quot;399&quot; style=&quot;width: 28.5668%; margin-right: 10px;&quot; data-widthpercent=&quot;28.9&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVaOta/dJMcadHnljY/Jv6iXlMMFHgUmNxKbKcrP1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVaOta%2FdJMcadHnljY%2FJv6iXlMMFHgUmNxKbKcrP1%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;926&quot; height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8230w/dJMcafSLHHW/IozzP9JXIGzt5r8woJP6S0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8230w/dJMcafSLHHW/IozzP9JXIGzt5r8woJP6S0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1678&quot; data-origin-height=&quot;884&quot; data-filename=&quot;스크린샷 2025-12-28 오후 12.44.33.png&quot; style=&quot;width: 70.2704%;&quot; data-widthpercent=&quot;71.1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8230w/dJMcafSLHHW/IozzP9JXIGzt5r8woJP6S0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8230w%2FdJMcafSLHHW%2FIozzP9JXIGzt5r8woJP6S0%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;1678&quot; height=&quot;884&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;고객을 끌어오는 구글 애널리틱스 4&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;본격적인 마케팅을 시작하기 전에, 우리는 GA 공부를 먼저 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현수랑 나는 매주 하나의 챕터씩 읽고 본 회의 때 서로 가르쳐주고, 모이삼 데이터를 토대로 이야기를 나눴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;획득, 참여도, 이벤트 등 생소한 개념도 알 수 있게 되었고, 특히 모이삼의 데이터에 적용하면서 추후 마케팅을 어떻게 해야 할지를 정할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면, &lt;b&gt;GA를 통해서 우리는 인스타그램 마케팅을 잠시 멈췄다.&lt;/b&gt; 블로그와 인스타그램에서 유입된 사용자 수가 비슷해도, 블로그에서 유입된 사용자는 대략 1분 정도 서비스에 참여했지만 인스타그램에서 유입된 사용자는 3초 이내로 이탈이 빨랐다. 그래서 우리는 인스타그램 게시물 작성 대신, 블로그 작성에 힘을 실었다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;전개 2 : 커뮤니티(에브리타임, OKKY..) 홍보&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_AF802DE36F70-1.jpeg&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;1638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brovJF/dJMcacV15b3/XmSr85brdFitKHxbsyAxe1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brovJF/dJMcacV15b3/XmSr85brdFitKHxbsyAxe1/img.jpg&quot; data-alt=&quot;에브리타임&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brovJF/dJMcacV15b3/XmSr85brdFitKHxbsyAxe1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrovJF%2FdJMcacV15b3%2FXmSr85brdFitKHxbsyAxe1%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;528&quot; height=&quot;1045&quot; data-filename=&quot;IMG_AF802DE36F70-1.jpeg&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;1638&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;p data-ke-size=&quot;size16&quot;&gt;모이삼은 중간지점 찾기 서비스인 만큼, 동네 친구들 보단 거리의 편차가 큰 사용자들이 사용하기 적합하다. 그래서 대학생이 타겟층인데 에브리타임에 홍보를 한 적이 없었다. 그래서 12월 연말인 만큼, 모임이 많을 거라 판단하여 에브리타임에 글을 올렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 여기서 현수가 게시글 제목에 업로드할 대학교를 넣어 작성하자고 했다. 많은 홍보 게시글 속에서 사소한 터치가 개인적으로 참 좋았다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sBNqI/dJMcadHnnWC/plDXCY6kgWXIK2XsjrRYTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sBNqI/dJMcadHnnWC/plDXCY6kgWXIK2XsjrRYTk/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;263&quot; data-filename=&quot;image (1).png&quot; style=&quot;width: 45.5704%; margin-right: 10px;&quot; data-widthpercent=&quot;46.11&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sBNqI/dJMcadHnnWC/plDXCY6kgWXIK2XsjrRYTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsBNqI%2FdJMcadHnnWC%2FplDXCY6kgWXIK2XsjrRYTk%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;466&quot; height=&quot;263&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d93j86/dJMcag5dzDS/zzM6KG8tnCluDAkVi8XXn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d93j86/dJMcag5dzDS/zzM6KG8tnCluDAkVi8XXn1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;225&quot; data-filename=&quot;image.png&quot; data-widthpercent=&quot;53.89&quot; style=&quot;width: 53.2668%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d93j86/dJMcag5dzDS/zzM6KG8tnCluDAkVi8XXn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd93j86%2FdJMcag5dzDS%2FzzM6KG8tnCluDAkVi8XXn1%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;466&quot; height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;현수의 Okky 홍보&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;현수는 일회성인 에브리타임 말고도 다양한 채널을 통해 장기적으로 홍보하기를 원했다. 현수는 여러 플랫폼(OKKY, 독취사 등)에서 적극적으로 홍보를 진행했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/plVdd/dJMcaacQHtj/yxU73UG7kKzwuzESkyEoi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/plVdd/dJMcaacQHtj/yxU73UG7kKzwuzESkyEoi0/img.png&quot; data-alt=&quot;디시인사이드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/plVdd/dJMcaacQHtj/yxU73UG7kKzwuzESkyEoi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FplVdd%2FdJMcaacQHtj%2FyxU73UG7kKzwuzESkyEoi0%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;1096&quot; height=&quot;148&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;148&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;여담이지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;나는 디시인사이드 커뮤니티에 올렸고 게시글과 댓글 수위가 세서 금방 접었다  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;전개 3 : 디스콰이엇, 유아이볼에 서비스 공유&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-28 오후 1.12.23.png&quot; data-origin-width=&quot;1909&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkO7oR/dJMcabv32G4/x5coLfNTEzGkVmImY3ePJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkO7oR/dJMcabv32G4/x5coLfNTEzGkVmImY3ePJk/img.png&quot; data-alt=&quot;디스콰이엇&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkO7oR/dJMcabv32G4/x5coLfNTEzGkVmImY3ePJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkO7oR%2FdJMcabv32G4%2Fx5coLfNTEzGkVmImY3ePJk%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;1909&quot; height=&quot;923&quot; data-filename=&quot;스크린샷 2025-12-28 오후 1.12.23.png&quot; data-origin-width=&quot;1909&quot; data-origin-height=&quot;923&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;스크린샷 2025-12-28 오후 1.13.26.png&quot; data-origin-width=&quot;1909&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OrQ5b/dJMcabiw60I/HnSr5AIzDGc6w3p168gHU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OrQ5b/dJMcabiw60I/HnSr5AIzDGc6w3p168gHU0/img.png&quot; data-alt=&quot;유아이볼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OrQ5b/dJMcabiw60I/HnSr5AIzDGc6w3p168gHU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOrQ5b%2FdJMcabiw60I%2FHnSr5AIzDGc6w3p168gHU0%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;1909&quot; height=&quot;923&quot; data-filename=&quot;스크린샷 2025-12-28 오후 1.13.26.png&quot; data-origin-width=&quot;1909&quot; data-origin-height=&quot;923&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;p data-ke-size=&quot;size16&quot;&gt;디스콰이엇에 우리의 서비스를 투고했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스콰이엇은 투고 이후, &lt;b&gt;이 주의 프로덕트&lt;/b&gt;에 2 연속 선정됐다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;기회가 된다면 업보트 한 번씩 부탁드립니다&lt;/span&gt;   &lt;a href=&quot;https://disquiet.io/product/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://disquiet.io/product/%EB%AA%A8%EC%9D%B4%EC%82%BC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766904258692&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;모이삼 | Disquiet*&quot; data-og-description=&quot;최고의 중간지점 찾기 서비스&quot; data-og-host=&quot;disquiet.io&quot; data-og-source-url=&quot;https://disquiet.io/product/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot; data-og-url=&quot;https://disquiet.io/product/모이삼&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bgFFQF/hyZQsomu2t/yzZbcPF2inAXATmt2K6bYk/img.jpg?width=664&amp;amp;height=664&amp;amp;face=0_0_664_664,https://scrap.kakaocdn.net/dn/c4HMzO/hyZPPj9Zni/wp8fMGYRMqLy6Vnlmg4lk0/img.jpg?width=664&amp;amp;height=664&amp;amp;face=0_0_664_664&quot;&gt;&lt;a href=&quot;https://disquiet.io/product/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://disquiet.io/product/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bgFFQF/hyZQsomu2t/yzZbcPF2inAXATmt2K6bYk/img.jpg?width=664&amp;amp;height=664&amp;amp;face=0_0_664_664,https://scrap.kakaocdn.net/dn/c4HMzO/hyZPPj9Zni/wp8fMGYRMqLy6Vnlmg4lk0/img.jpg?width=664&amp;amp;height=664&amp;amp;face=0_0_664_664');&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;모이삼 | Disquiet*&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;최고의 중간지점 찾기 서비스&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;disquiet.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유아이볼에서는 모이삼 서비스를 좋게 봐주셔서 자체 플랫폼, 인스타그램, 브런치 게시글을 통해 모이삼 사용 후기를 남겨주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 부분뿐만 아니라, 아쉬운 부분도 함께 제시해 주셔서 참 감사했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유아이볼 : &lt;a href=&quot;https://uibowl.io/website/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://uibowl.io/website/%EB%AA%A8%EC%9D%B4%EC%82%BC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766895749862&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;https://uibowl.io/&quot; data-og-description=&quot;국내 UI/UX 패턴을 담은 공간, 유아이볼&quot; data-og-host=&quot;uibowl.io&quot; data-og-source-url=&quot;https://uibowl.io/website/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot; data-og-url=&quot;https://uibowl.io/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dSNc28/hyZQx4iKaU/NVb7XuaTMlKR8KPVBjFaOk/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://uibowl.io/website/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://uibowl.io/website/%EB%AA%A8%EC%9D%B4%EC%82%BC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dSNc28/hyZQx4iKaU/NVb7XuaTMlKR8KPVBjFaOk/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&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;https://uibowl.io/&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;국내 UI/UX 패턴을 담은 공간, 유아이볼&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;uibowl.io&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;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;전&lt;/b&gt;&lt;b&gt;개 4 : 디자인 Threads 운영&lt;/b&gt;&lt;/h2&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/bVBaDO/dJMcadUTzk8/ZYwoiRt2px9oRjsjgbkBck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVBaDO/dJMcadUTzk8/ZYwoiRt2px9oRjsjgbkBck/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;912&quot; data-filename=&quot;스크린샷 2025-12-28 오후 1.34.52.png&quot; style=&quot;width: 39.3705%; margin-right: 10px;&quot; data-widthpercent=&quot;39.83&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVBaDO/dJMcadUTzk8/ZYwoiRt2px9oRjsjgbkBck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVBaDO%2FdJMcadUTzk8%2FZYwoiRt2px9oRjsjgbkBck%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;647&quot; height=&quot;912&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K9jqr/dJMcag5dzVV/33JkPILeDek5crVL8SQfV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K9jqr/dJMcag5dzVV/33JkPILeDek5crVL8SQfV0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;587&quot; data-filename=&quot;스크린샷 2025-12-28 오후 1.39.33.png&quot; style=&quot;width: 59.4667%;&quot; data-widthpercent=&quot;60.17&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K9jqr/dJMcag5dzVV/33JkPILeDek5crVL8SQfV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK9jqr%2FdJMcag5dzVV%2F33JkPILeDek5crVL8SQfV0%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;629&quot; height=&quot;587&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;@yogurtzzang&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팔로우 부탁드려요   &lt;/b&gt;&lt;a href=&quot;https://www.threads.com/@yogurtzzang&quot;&gt;https://www.threads.com/@yogurtzzang&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12월 초중순부터 모이삼 디자이너인 현비가 마케팅에 참여했다. 현비는 개인 스레드에서 디자인, IT 계열 사람들에게 모이삼을 홍보하고 있다. 스레드에서는 현비의 디자인 이야기나 모이삼 홍보글 등이 주기적으로 업로드될 예정이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;위기 : 마케팅의 성과를 확인하고 싶어!&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 과정을 토대로 사용자의 유입은 꾸준히 성장했다. 현수, 현비는 GA를, 나는 DB로 생성된 모임과 참여자 수 등을 확인했다. 그러나 GA에서 UTM으로 가져온 데이터를 확인하는 건 꽤 복잡했다. 그래서 나는 어드민 페이지를 만들어 현수, 현비도 모임 정보를 쉽게 확인할 수 있도록 했다.&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;1909&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RqP8n/dJMcagc4HVd/zytgzcJ3EOS85p5nhvSgO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RqP8n/dJMcagc4HVd/zytgzcJ3EOS85p5nhvSgO0/img.png&quot; data-alt=&quot;모이삼 어드민 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RqP8n/dJMcagc4HVd/zytgzcJ3EOS85p5nhvSgO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRqP8n%2FdJMcagc4HVd%2FzytgzcJ3EOS85p5nhvSgO0%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;1909&quot; height=&quot;923&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1909&quot; data-origin-height=&quot;923&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;p data-ke-size=&quot;size16&quot;&gt;어드민 페이지를 만들면서 어디서나 확인할 수 있다는 점이 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 모이삼의 상세 경로를 가져올 때, 외부 API를 사용하다 보니 경로를 못 가져오는 경우도 더러 있었는데, 이때 어드민 페이지에서 확인 후 빠르게 대처할 수 있게 되었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;절정 : MAU 300% 증가  &lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-28 오후 2.27.33.png&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9fvAI/dJMcaaqnUpz/fz9V8MZ4vuyeWG32yBBsIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9fvAI/dJMcaaqnUpz/fz9V8MZ4vuyeWG32yBBsIk/img.png&quot; data-alt=&quot;첫 사용자(신규 방문자)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9fvAI/dJMcaaqnUpz/fz9V8MZ4vuyeWG32yBBsIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9fvAI%2FdJMcaaqnUpz%2Ffz9V8MZ4vuyeWG32yBBsIk%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;1460&quot; height=&quot;386&quot; data-filename=&quot;스크린샷 2025-12-28 오후 2.27.33.png&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;386&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;스크린샷 2025-12-28 오후 2.47.27.png&quot; data-origin-width=&quot;1464&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhm1YM/dJMcaajCCiS/yMC6HP1pzjtGeuT0YGSyQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhm1YM/dJMcaajCCiS/yMC6HP1pzjtGeuT0YGSyQK/img.png&quot; data-alt=&quot;세션 수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhm1YM/dJMcaajCCiS/yMC6HP1pzjtGeuT0YGSyQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhm1YM%2FdJMcaajCCiS%2FyMC6HP1pzjtGeuT0YGSyQK%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;1464&quot; height=&quot;387&quot; data-filename=&quot;스크린샷 2025-12-28 오후 2.47.27.png&quot; data-origin-width=&quot;1464&quot; data-origin-height=&quot;387&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;신규 방문자와 세션 수는 &lt;b&gt;에브리타임 &amp;gt; okky &amp;gt; 네이버 블로그 &amp;gt; 디스콰이엇 &amp;gt; 구글 검색&lt;/b&gt;&amp;nbsp;순이다.&lt;/li&gt;
&lt;li&gt;google / organic 이 꾸준히 늘어나고 있는데,&amp;nbsp; 이는 &lt;b&gt;'중간지점 찾기', '모이삼' 을 검색해서 들어온 사람이 증가&lt;/b&gt;했다는 점이고, 마케팅을 통해 &lt;b&gt;SEO 활성화&lt;/b&gt;된 것이 가장 긍정적인 부분이라 생각한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은&amp;nbsp;&lt;b&gt;세션 수와 첫 사용자(신규 방문자)&lt;/b&gt;를 비교한 &lt;b&gt;서비스 참여 정도&lt;/b&gt;의 표와 해석이다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; background-color: #ffffff; color: #333333; border: 1px solid #dddddd;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;th style=&quot;padding: 12px; text-align: left; border: 1px solid #dddddd;&quot;&gt;유입 채널&lt;/th&gt;
&lt;th style=&quot;padding: 12px; text-align: left; border: 1px solid #dddddd;&quot;&gt;첫 사용자 수 (A)&lt;/th&gt;
&lt;th style=&quot;padding: 12px; text-align: left; border: 1px solid #dddddd;&quot;&gt;참여 세션 수 (B)&lt;/th&gt;
&lt;th style=&quot;padding: 12px; text-align: left; border: 1px solid #dddddd;&quot;&gt;유입당 참여율 (B/A)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;&lt;b&gt;everytime.kr&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;123명&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;92건&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;0.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;&lt;b&gt;okky.kr&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;70명&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;57건&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;0.81&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;&lt;b&gt;m.blog.naver.com&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;67명&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;69건&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;&lt;b&gt;1.03&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;&lt;b&gt;disquiet.io&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;40명&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;35건&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;0.88&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;&lt;b&gt;google&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;24명&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;26건&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #dddddd;&quot;&gt;&lt;b&gt;1.08&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;&lt;b data-path-to-node=&quot;7,0,0&quot; data-index-in-node=&quot;0&quot;&gt;구글, &lt;/b&gt;네이버 블로그의 참여율이 높다:&lt;/b&gt; 유입된 사람 수(67명, 24명) 보다 참여 세션 수(69건, 26건)가 더 많다. 이는 신규 사용자가 이탈하지 않고 &lt;b data-index-in-node=&quot;84&quot; data-path-to-node=&quot;7,0,0&quot;&gt;재방문&lt;/b&gt;했음을 알 수 있다. 특히 네이버 블로그의 GA 참여율은 &lt;b&gt;95.83%&lt;/b&gt;로 가장 높음을 알 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;에브리타임의 유입량이 높다:&lt;/b&gt; 가장 많은 123명의 신규 사용자를 데려왔지만, 참여율(0.75)은 타 채널 대비 낮다. 이는 호기심에 들어온 유저는 많으나, &lt;b&gt;실제 서비스 사용까지 전환이 이뤄지지는 않음&lt;/b&gt;을 시사한다. &lt;b&gt;개강 시즌에 단기적인 유입&lt;/b&gt;을 늘리는데 도움이 될 수 있을 것으로 보인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-28 오후 2.58.28.png&quot; data-origin-width=&quot;1909&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UiuGy/dJMcabW8s22/38g6MVKavCSy89YW020pN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UiuGy/dJMcabW8s22/38g6MVKavCSy89YW020pN1/img.png&quot; data-alt=&quot;네이버에도 최상단에 노출&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UiuGy/dJMcabW8s22/38g6MVKavCSy89YW020pN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUiuGy%2FdJMcabW8s22%2F38g6MVKavCSy89YW020pN1%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;1909&quot; height=&quot;923&quot; data-filename=&quot;스크린샷 2025-12-28 오후 2.58.28.png&quot; data-origin-width=&quot;1909&quot; data-origin-height=&quot;923&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;p data-ke-size=&quot;size16&quot;&gt;또한 마케팅 이전에는 네이버에 모이삼 검색 시, 우리 서비스가 노출되지 않았다. 하지만 마케팅 이후, 네이버 검색 시 최상단에 노출됨으로써 네이버에서 유입을 기대할 수 있다. 다만 아쉬운 점은 '중간지점 찾기'를 통한 노출은 이뤄지지 않아 좀 더 SEO를 신경 써야 할 것 같다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결말 : 모이삼은 잘 된다. 그리고 잘 될 것이다.&lt;/b&gt;&lt;/h2&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;더 개선하고 나중에...&quot;라는 생각은 마케팅 시기를 늦출 뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 99개의 단점이 있더라도, 자신에게 필요한 단 1개의 장점만 있더라도 기꺼이 사용할 것이라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 마케팅을 하는 입장에서 단점에 매몰되어 소극적인 홍보가 아닌, 장점을 부각하여 적극적인 홍보가 마케팅의 시작이라는 걸 깨달았다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;MVP를 만들었다면, 일단 뛰어드는 게 어떨까?!&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;같이 읽으면 좋은 글&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.naver.com/nanhyunsoo00/224123738686&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://blog.naver.com/nanhyunsoo00/224123738686&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766904366627&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[모이삼 마케팅 - 1] 광고 없이 한달 만에 사이드프로젝트 MAU 300% 성장&quot; data-og-description=&quot;서비스 MAU 300% 성장 다시 한 번 최고의 중간지점 찾기 서비스 - 모이삼 관련 글로 찾아오게 되었다. ...&quot; data-og-host=&quot;blog.naver.com&quot; data-og-source-url=&quot;https://blog.naver.com/nanhyunsoo00/224123738686&quot; data-og-url=&quot;https://blog.naver.com/nanhyunsoo00/224123738686&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lMyhl/hyZPKQIr3h/KKKLb6qxhAqwW0Hi5WPpak/img.png?width=743&amp;amp;height=280&amp;amp;face=0_0_743_280&quot;&gt;&lt;a href=&quot;https://blog.naver.com/nanhyunsoo00/224123738686&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.naver.com/nanhyunsoo00/224123738686&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lMyhl/hyZPKQIr3h/KKKLb6qxhAqwW0Hi5WPpak/img.png?width=743&amp;amp;height=280&amp;amp;face=0_0_743_280');&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;[모이삼 마케팅 - 1] 광고 없이 한달 만에 사이드프로젝트 MAU 300% 성장&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;서비스 MAU 300% 성장 다시 한 번 최고의 중간지점 찾기 서비스 - 모이삼 관련 글로 찾아오게 되었다. ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.naver.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.naver.com/nanhyunsoo00/224123904644&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://blog.naver.com/nanhyunsoo00/224123904644&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766904372361&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[모이삼 마케팅 - 2] 마케팅 예산 0원. 우리가 선택한 유입 채널 4가지&quot; data-og-description=&quot;이번 편에는 지난 편의 인트로에 이어 실제로 어떤 마케팅 채널을 선택했고, 어떤 효과를 보았는 지 소개하...&quot; data-og-host=&quot;blog.naver.com&quot; data-og-source-url=&quot;https://blog.naver.com/nanhyunsoo00/224123904644&quot; data-og-url=&quot;https://blog.naver.com/nanhyunsoo00/224123904644&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fV4Rl/hyZQu0M9jf/fx1bejL8rf1wiGMEZubhG0/img.png?width=743&amp;amp;height=215&amp;amp;face=0_0_743_215&quot;&gt;&lt;a href=&quot;https://blog.naver.com/nanhyunsoo00/224123904644&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.naver.com/nanhyunsoo00/224123904644&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fV4Rl/hyZQu0M9jf/fx1bejL8rf1wiGMEZubhG0/img.png?width=743&amp;amp;height=215&amp;amp;face=0_0_743_215');&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;[모이삼 마케팅 - 2] 마케팅 예산 0원. 우리가 선택한 유입 채널 4가지&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 편에는 지난 편의 인트로에 이어 실제로 어떤 마케팅 채널을 선택했고, 어떤 효과를 보았는 지 소개하...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.naver.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Projects/MOISAM</category>
      <category>Google Analytics</category>
      <category>마케팅</category>
      <category>모이삼</category>
      <category>약속 장소 찾기</category>
      <category>약속 장소 추천</category>
      <category>중간 장소 찾기</category>
      <category>중간 장소 추천</category>
      <category>중간 지점 찾기</category>
      <category>중간 지점 추천</category>
      <category>회고</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/91</guid>
      <comments>https://developer-anxi.tistory.com/91#entry91comment</comments>
      <pubDate>Sun, 28 Dec 2025 15:55:23 +0900</pubDate>
    </item>
    <item>
      <title>[Network] Loopback 루프백 (127.0.0.1, localhost)</title>
      <link>https://developer-anxi.tistory.com/90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Loopback 루프백이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프백은 Loop + Back, 단어 그대로 되돌려 보내는 행위를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 네트워크에 적용해 보면, 데이터를 자기 자신에게 다시 전송하는 메커니즘을 뜻한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;For-loop-diagram.png&quot; data-origin-width=&quot;250&quot; data-origin-height=&quot;543&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWG7Ut/dJMcajgpQtw/Q3zbyD9RBp9eqiYOsfBGDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWG7Ut/dJMcajgpQtw/Q3zbyD9RBp9eqiYOsfBGDK/img.png&quot; data-alt=&quot;forloop의 loop와 동일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWG7Ut/dJMcajgpQtw/Q3zbyD9RBp9eqiYOsfBGDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWG7Ut%2FdJMcajgpQtw%2FQ3zbyD9RBp9eqiYOsfBGDK%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;163&quot; height=&quot;354&quot; data-filename=&quot;For-loop-diagram.png&quot; data-origin-width=&quot;250&quot; data-origin-height=&quot;543&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;forloop의 loop와 동일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;루프백 주소란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;127.0.0.0에서 시작하여 127.255.255.255로 끝나는 예약된 IP 주소 범위를 말한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;IPv4&amp;nbsp;루프백&amp;nbsp;주소&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;IPv4&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;범위: &lt;b&gt;127.0.0.0/8&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;브로드캐스트 주소&lt;b&gt;:&lt;/b&gt; 127.255.255.255&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;일반적으로 사용되는 루프백 주소: &lt;b&gt;127.0.0.1 &lt;/b&gt;(로컬호스트, localhost로 알려져 있다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;IPv6&amp;nbsp;루프백&amp;nbsp;주소&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IPv6 범위: &lt;b&gt;&lt;span&gt;::1&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;활용 예시: localhost:8080 + 동작 방식&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SpringBoot를 통해 로컬에서 웹 서버를 띄우고 테스트하기 위해서 항상 접속하는 주소가 있다.&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;1717&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGkv1E/dJMcahiEnsx/rm5fdcDJ8Cft746AslG5wK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGkv1E/dJMcahiEnsx/rm5fdcDJ8Cft746AslG5wK/img.png&quot; data-alt=&quot;Swagger를 사용할 때도 localhost로 접속한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGkv1E/dJMcahiEnsx/rm5fdcDJ8Cft746AslG5wK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGkv1E%2FdJMcahiEnsx%2Frm5fdcDJ8Cft746AslG5wK%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;1717&quot; height=&quot;418&quot; data-origin-width=&quot;1717&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Swagger를 사용할 때도 localhost로 접속한다.&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;b&gt;'localhost:8080'&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;Nestjs, Spring Boot와 같은 프레임워크를 통해 로컬에서 웹 서버를 띄워 Swagger로 API 테스트할 때 우리는 항상 localhost:8080에 접속한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;루프백 주소를 사용해 외부 네트워크와 연결 없이 로컬 컴퓨터가 스스로에게 요청하고 응답을 받기 위해 루프백 메커니즘을 이용한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;루프백이 localhost:8080에서 작동하는 방식 (OSI 7 Layer)&lt;/b&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 157px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 20px;&quot;&gt;&lt;b&gt;Layer&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 20px;&quot;&gt;&lt;b&gt;계층&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 20px;&quot;&gt;&lt;b&gt;루프백 통신 과정&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 20px;&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 20px;&quot;&gt;응용 (Application)&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 20px;&quot;&gt;웹 브라우저(클라이언트)가 HTTP 요청 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 20px;&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 20px;&quot;&gt;표현 (Presentation)&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 20px;&quot;&gt;데이터가 필요한 형식으로 인코딩&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 19px;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 19px;&quot;&gt;세션 (Session)&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 19px;&quot;&gt;&lt;span data-path-to-node=&quot;5,3,3,0&quot;&gt;통신 세션 시작&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 20px;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 20px;&quot;&gt;전송 (Transport)&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 20px;&quot;&gt;브라우저 프로세스가 목적지 포트(8080)를 지정, 데이터는 TCP 세그먼트로 캡슐화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 20px;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 20px;&quot;&gt;네트워크 (Network)&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 20px;&quot;&gt;IP 계층이 목적지 IP 주소 &lt;b&gt;127.0.0.1&lt;/b&gt;을 확인 후 &lt;b&gt;루프백 주소&lt;/b&gt;임을 인지하여 &lt;b&gt;라우팅 테이블의 루프백 인터페이스&lt;/b&gt;로 경로 지정&lt;br /&gt;&lt;br /&gt; &lt;b&gt;루프백 인터페이스&lt;/b&gt;: 루프백 통신을 가능하게 하는 운영체제 내의&amp;nbsp;&lt;b&gt;가상 네트워크 인터페이스&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 20px;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 20px;&quot;&gt;데이터 링크 (Data Link)&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 20px;&quot;&gt;패킷이 외부 LAN 카드로 전달되지 않음으로 사용되지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 7.51937%; height: 18px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 19.3799%; height: 18px;&quot;&gt;물리 (Physical)&lt;/td&gt;
&lt;td style=&quot;width: 73.1007%; height: 18px;&quot;&gt;물리적인 케이블을 통해 외부로 전달하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/computer-networks/what-is-a-loopback-address/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.geeksforgeeks.org/computer-networks/what-is-a-loopback-address/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/네트워크</category>
      <category>127.0.0.0/8</category>
      <category>127.0.0.1</category>
      <category>Computer Science</category>
      <category>CS</category>
      <category>localhost</category>
      <category>localhost:8080</category>
      <category>Loopback</category>
      <category>Network</category>
      <category>로컬호스트</category>
      <category>루프백</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/90</guid>
      <comments>https://developer-anxi.tistory.com/90#entry90comment</comments>
      <pubDate>Sat, 13 Dec 2025 20:00:48 +0900</pubDate>
    </item>
    <item>
      <title>[Security] 샌드박스(Sandbox)</title>
      <link>https://developer-anxi.tistory.com/89</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-27 오후 7.23.05.png&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;699&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pZB5R/dJMcagxbkGT/gkv1Hdn1RkgpqXoOFzgzWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pZB5R/dJMcagxbkGT/gkv1Hdn1RkgpqXoOFzgzWk/img.png&quot; data-alt=&quot;내가 알고 있는 샌드박스..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pZB5R/dJMcagxbkGT/gkv1Hdn1RkgpqXoOFzgzWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpZB5R%2FdJMcagxbkGT%2Fgkv1Hdn1RkgpqXoOFzgzWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1422&quot; height=&quot;699&quot; data-filename=&quot;스크린샷 2025-11-27 오후 7.23.05.png&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;699&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;스크린샷 2025-11-27 오후 7.26.38.png&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;908&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bI1OCk/dJMcab3IrHg/QGipMzFKtM3n390cA90811/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bI1OCk/dJMcab3IrHg/QGipMzFKtM3n390cA90811/img.png&quot; data-alt=&quot;나만 몰랐던 샌드박스...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bI1OCk/dJMcab3IrHg/QGipMzFKtM3n390cA90811/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbI1OCk%2FdJMcab3IrHg%2FQGipMzFKtM3n390cA90811%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;1308&quot; height=&quot;908&quot; data-filename=&quot;스크린샷 2025-11-27 오후 7.26.38.png&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;908&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;p data-ke-size=&quot;size16&quot;&gt;최근에 샌드박스(Sandbox)라는 단어를 듣게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 아는 샌드박스는 도티가 운영한다는 MCN 회사인데.. 알고 보니 보안에서도 샌드박스라는 게 쓰인다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샌드박스를 알아보니 꽤 재밌어서 글을 작성하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;샌드박스 (Sandbox)&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드.jpeg&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csfag6/dJMcaaDJlNy/6Bkm8Vh5zX67ul83nbwnb0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csfag6/dJMcaaDJlNy/6Bkm8Vh5zX67ul83nbwnb0/img.jpg&quot; data-alt=&quot;놀이터&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csfag6/dJMcaaDJlNy/6Bkm8Vh5zX67ul83nbwnb0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsfag6%2FdJMcaaDJlNy%2F6Bkm8Vh5zX67ul83nbwnb0%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;291&quot; height=&quot;173&quot; data-filename=&quot;다운로드.jpeg&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;173&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;p data-ke-size=&quot;size16&quot;&gt;샌드박스는 단어 그대로, 모래 상자, 모래로 가득 채워진 공간을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모래로 가득 채워진 공간을 상상해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나 혼자 그 공간에 있다면, 땅을 온종일 파서 지하수를 구하거나, 개미집과 같이 나만의 공간을 만드는 등,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남 눈치 안 보고 상상 조차 하지 못한 일을 할 거 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안에서의 샌드박스도 마찬가지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모래뿐인 공간에서 개발자가 상상력을 펼치며 놀 수 있는 곳.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모래뿐인 공간에서 보안에서의 공간으로 확장되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용을 토대로 샌드박스가 무엇인지 어느 정도 파악할 수 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안에서의 샌드박스란&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;다른 프로그램에 영향을 끼치지 않고 (외부 자원 접근 X) 프로그램을 안전하게 실행할 수 있는 격리된 환경&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예시 : iOS APP&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔히 접할 수 있는 샌드박스의 예시가 바로 &lt;b&gt;iOS APP&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 아이폰의 장점을 이야기할 때, 가장 많이 나오는 게 보안에 관한 내용이다. 아이폰은 해킹하기 어렵다는 말들이 많았고, 샌드박스를 알기 전에는 그 이유에 대해 알지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;compressed_Screen-Shot-2021-05-17-at-12.18.44-PM.png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMnheK/dJMb99SmPtY/qvaERk6QX9xKz4uj8fqaVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMnheK/dJMb99SmPtY/qvaERk6QX9xKz4uj8fqaVk/img.png&quot; data-alt=&quot;iphone Sandbox&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMnheK/dJMb99SmPtY/qvaERk6QX9xKz4uj8fqaVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMnheK%2FdJMb99SmPtY%2FqvaERk6QX9xKz4uj8fqaVk%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;750&quot; height=&quot;678&quot; data-filename=&quot;compressed_Screen-Shot-2021-05-17-at-12.18.44-PM.png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;iphone Sandbox&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;b&gt;각자의 샌드박스&lt;/b&gt;를 갖는다. (App Sandbox)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샌드박스 내부에 앱에 대한 파일, 하드웨어(카메라, 마이크), 네트워크 등 여러 리소스를 격리하여 저장한다. 따라서 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;샌드박스의&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;외부의 데이터를&lt;span&gt;&amp;nbsp;접근할 수 없게 된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;만약 하나의 앱에서 문제가 발생하더라도, 샌드박스 외부에선 시스템 리소스와 사용자 데이터에 접근할 수 없어 보호할 수 있게 된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 밖에도, 알고리즘 문제 풀 수 있는 사이트로 유명한 백준도 샌드박스에서 채점을 했다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.slideshare.net/slideshow/ss-51001155/51001155&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.slideshare.net/slideshow/ss-51001155/51001155&lt;/a&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;b&gt;샌드박스 vs 가상 머신 (VM)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샌드박스를 알게 되면서 유사하다고 느낀 건 바로 가상머신이다. 가상머신도 호스트와 격리된 환경을 제공하는데 과연 무슨 차이가 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ORYtk/dJMcacn1ivU/W6N3Gg3sz3nSHKyOPvCLL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ORYtk/dJMcacn1ivU/W6N3Gg3sz3nSHKyOPvCLL1/img.png&quot; data-alt=&quot;Hypervisor&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ORYtk/dJMcacn1ivU/W6N3Gg3sz3nSHKyOPvCLL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FORYtk%2FdJMcacn1ivU%2FW6N3Gg3sz3nSHKyOPvCLL1%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;750&quot; height=&quot;434&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;434&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Hypervisor&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;b&gt;하이퍼바이저(Hypervisor)&lt;/b&gt;가 필요하다. 사진에서 보면 Type1의 경우, &lt;b&gt;하이퍼바이저가 하드웨어 위에서 동작&lt;/b&gt;함을 볼 수 있다. 하드웨어를 하이퍼바이저를 이용해 가상화함으로써 하드웨어 수준에서 격리를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 샌드박스는 &lt;b&gt;호스트 OS의 커널을 이용해 호스트 위에서 격리 환경&lt;/b&gt;이 구성되기 때문에, 빠르게 환경을 구성하고 있고, OS 또한 따로 설치할 필요가 없다.&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;Windows에서는 샌드박스(WSB)와 가상 머신(Hyper-V) 둘 다 제공하고 있다. MS에서 말하는 차이는 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-27 오후 8.42.51.png&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;621&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ezMjEl/dJMcadf6L2d/XRwU2C35dEUx1TGO5KGRe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ezMjEl/dJMcadf6L2d/XRwU2C35dEUx1TGO5KGRe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ezMjEl/dJMcadf6L2d/XRwU2C35dEUx1TGO5KGRe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FezMjEl%2FdJMcadf6L2d%2FXRwU2C35dEUx1TGO5KGRe0%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;883&quot; height=&quot;621&quot; data-filename=&quot;스크린샷 2025-11-27 오후 8.42.51.png&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;621&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용을 표로 정리해 봤다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;&lt;b&gt;구분&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 46.3953%;&quot;&gt;&lt;b&gt;Windows Sandbox (WSB)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 43.0233%;&quot;&gt;&lt;b&gt;Hyper-V 가상 머신 (VM)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;목적/특징&lt;/td&gt;
&lt;td style=&quot;width: 46.3953%;&quot;&gt;경량 및 일시적(Lightweight &amp;amp; Temporary)&lt;/td&gt;
&lt;td style=&quot;width: 43.0233%;&quot;&gt;무겁고 영구적인 환경(Heavyweight &amp;amp; Persistent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;설정 시간&lt;/td&gt;
&lt;td style=&quot;width: 46.3953%;&quot;&gt;빠른 실행 가능 (Quickly launch)&lt;/td&gt;
&lt;td style=&quot;width: 43.0233%;&quot;&gt;설정에 더 많은 시간 소요 (Longer to set up)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;자원 효율성&lt;/td&gt;
&lt;td style=&quot;width: 46.3953%;&quot;&gt;고효율적 (More resource efficient), 요구에 따라 메모리 조정, 호스트의 읽기 전용 OS 파일 재사용&lt;/td&gt;
&lt;td style=&quot;width: 43.0233%;&quot;&gt;고정 자원 할당 (Fixed resource allocations), 시스템 성능에 영향 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;격리 및 보안&lt;/td&gt;
&lt;td style=&quot;width: 46.3953%;&quot;&gt;보안 격리 제공. 닫으면 모든 변경 사항이 폐기됨 (Disposable)&lt;/td&gt;
&lt;td style=&quot;width: 43.0233%;&quot;&gt;격리 제공. 수동으로 복원하지 않는 한 변경 사항이 영구적으로 저장됨 (Persistent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;사용 편의성&lt;/td&gt;
&lt;td style=&quot;width: 46.3953%;&quot;&gt;사용이 간단 (Simple to use), 복잡한 설정 불필요&lt;/td&gt;
&lt;td style=&quot;width: 43.0233%;&quot;&gt;더 많은 구성 필요 (More configuration), 가상 스위치, 네트워크 어댑터, 스냅샷 관리 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;기술적 배경&lt;/td&gt;
&lt;td style=&quot;width: 46.3953%;&quot;&gt;호스트 OS 커널 활용 (경량 격리 환경)&lt;/td&gt;
&lt;td style=&quot;width: 43.0233%;&quot;&gt;하이퍼바이저를 통한 하드웨어 가상화 (완벽한 시스템 격리)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.quora.com/What-does-sandbox-mean-in-a-programmers-context&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.quora.com/What-does-sandbox-mean-in-a-programmers-context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/documentation/security/app-sandbox/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/documentation/security/app-sandbox/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-faq&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-faq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nice-engineer.tistory.com/entry/%ED%95%98%EC%9D%B4%ED%8D%BC%EB%B0%94%EC%9D%B4%EC%A0%80Hypervisor-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EC%A2%85%EB%A5%98&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://nice-engineer.tistory.com/entry/%ED%95%98%EC%9D%B4%ED%8D%BC%EB%B0%94%EC%9D%B4%EC%A0%80Hypervisor-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EC%A2%85%EB%A5%98&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/운영체제</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/89</guid>
      <comments>https://developer-anxi.tistory.com/89#entry89comment</comments>
      <pubDate>Thu, 27 Nov 2025 20:51:29 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] Spring Filter로 특정 API 응답 데이터 gzip 압축 적용하기</title>
      <link>https://developer-anxi.tistory.com/88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;중간지점 찾기 서비스인 모이삼에서는 중간지점 산출 및 출발지에서 중간지점까지의 상세 경로를 알려준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;모이삼&quot; href=&quot;https://www.moisam.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.moisam.kr/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1762766752277&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;모이삼&quot; data-og-description=&quot;최적의 중간장소 찾기, 약속장소 추천&quot; data-og-host=&quot;www.moisam.kr&quot; data-og-source-url=&quot;https://www.moisam.kr/&quot; data-og-url=&quot;https://www.moisam.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bro1xU/hyZNgIaUOi/Ko5RLBM5R86a4pKODeKELK/img.jpg?width=4800&amp;amp;height=2520&amp;amp;face=0_0_4800_2520&quot;&gt;&lt;a href=&quot;https://www.moisam.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.moisam.kr/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bro1xU/hyZNgIaUOi/Ko5RLBM5R86a4pKODeKELK/img.jpg?width=4800&amp;amp;height=2520&amp;amp;face=0_0_4800_2520');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;모이삼&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;최적의 중간장소 찾기, 약속장소 추천&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.moisam.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간지점은 최대 3개까지 산출되며, 출발지마다 경로를 보여주는 만큼, 응답 데이터의 크기는 중간지점 수와 출발지 수에 비례한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모이삼은 응답 시간을 줄이기 위해 응답 데이터 캐싱과 멀티 스레드를 사용해 외부 API에서 경로를 가져오는 등 여러 처리를 진행했다. 위 과정을 통해 비약적으로 속도 개선을 이뤘지만, 응답 데이터의 크기는 줄이지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;줄일 수 있는 방법을 찾아보던 와중, 응답 데이터를 압축할 수 있는 포맷인 &lt;b&gt;gzip&lt;/b&gt;을 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  gzip이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gzip은 파일 압축 및 압축 해제에 사용되는 &lt;b&gt;파일 형식(file format)&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Deflate 알고리즘&lt;/b&gt;을 기반으로, 파일 크기를 줄여 &lt;b&gt;네트워크 전송 속도를 향상&lt;/b&gt;시킬 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gzip은 &lt;b&gt;웹 서버 및 최신 브라우저에서 지원돼서,&lt;/b&gt; 서버는 응답을 전송 이전에 gzip으로 압축할 수 있고, 브라우저는 응답을 자동으로 압축해제 할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  적용 근거&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최범균 님의 &quot;주니어 백엔드 개발자가 반드시 알아야 할 실무 지식&quot;에서는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응답 시간에는 &lt;b&gt;데이터 전송 시간&lt;/b&gt;이 포함되고, 데이터 전송 시간에는 '네트워크 속도', '전송 데이터 크기' 2가지 요인에 영향을 받는다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 2가지 요인 중에 서버가 핸들링할 수 있는 것은 '전송 데이터 크기' 뿐이다. '네트워크 속도'는 공유기나 통신사 등 여러 요인에 따라 영향받을 수 있지만, 전송 데이터 크기는 서버에서 압축할 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 나는 '전송 데이터 크기'를 gzip으로 압축하여 서버에서 데이터 크기를 줄여 해결하고자 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 브라우저 범용성이 높다.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-10 오후 6.50.59.png&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/toxln/dJMcaiBEDwr/zXcOuDisim6LF5voEF2lvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/toxln/dJMcaiBEDwr/zXcOuDisim6LF5voEF2lvK/img.png&quot; data-alt=&quot;Browser Compatibility&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/toxln/dJMcaiBEDwr/zXcOuDisim6LF5voEF2lvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftoxln%2FdJMcaiBEDwr%2FzXcOuDisim6LF5voEF2lvK%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;612&quot; height=&quot;516&quot; data-filename=&quot;스크린샷 2025-11-10 오후 6.50.59.png&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Browser Compatibility&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;p data-ke-size=&quot;size16&quot;&gt;위 사진은 gzip뿐만 아닌 여러 압축 포맷에서의 브라우저 수용 가능성을 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Brotli 알고리즘을 사용한 br 포맷도 Opera Android를 제외하고 대부분의 브라우저에서 사용 가능하기 때문에, 더 오래된 gzip은 더 범용성 있을 거라 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 압축률이 좋다.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-10 오후 6.54.34.png&quot; data-origin-width=&quot;1360&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGrLr2/dJMcabvLnK0/KSd6Zrj1prH6sBPb0y1tQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGrLr2/dJMcabvLnK0/KSd6Zrj1prH6sBPb0y1tQK/img.png&quot; data-alt=&quot;https://tools.paulcalvano.com/compression.php&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGrLr2/dJMcabvLnK0/KSd6Zrj1prH6sBPb0y1tQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGrLr2%2FdJMcabvLnK0%2FKSd6Zrj1prH6sBPb0y1tQK%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;1360&quot; height=&quot;844&quot; data-filename=&quot;스크린샷 2025-11-10 오후 6.54.34.png&quot; data-origin-width=&quot;1360&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://tools.paulcalvano.com/compression.php&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;위 사진은 gzip과 brotli, 그리고 압축 전의 응답 크기를 비교한 결과다. (중간지점 2개, 출발지 8개 기준)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;level을 1로 계산했을 경우에 아래와 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;gzip: 1614&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Brotli: 1691&lt;/li&gt;
&lt;li&gt;비압축(Uncompressed):&amp;nbsp; 2788&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gzip을 사용할 경우, 원본 크기의 57% 압축을 이뤄낼 수 있다. level을 높게 설정할 경우 압축률은 더 늘릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 적용하기 쉽다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTP request&lt;/b&gt;의 'Accept-Encoding' 헤더를 통해 서버에 처리할 수 있는 압축 알고리즘을 알려준다.&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;스크린샷 2025-11-10 오후 7.02.24.png&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;45&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFYhfm/dJMcaap5pfm/hBXY9KZWLkHJ2RRAy4UGb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFYhfm/dJMcaap5pfm/hBXY9KZWLkHJ2RRAy4UGb0/img.png&quot; data-alt=&quot;HTTP request&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFYhfm/dJMcaap5pfm/hBXY9KZWLkHJ2RRAy4UGb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFYhfm%2FdJMcaap5pfm%2FhBXY9KZWLkHJ2RRAy4UGb0%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;315&quot; height=&quot;45&quot; data-filename=&quot;스크린샷 2025-11-10 오후 7.02.24.png&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;45&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HTTP request&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;b&gt;HTTP response&lt;/b&gt;에서는 클라이언트에서 명시된 알고리즘 중에서 지원한 방식의 알고리즘을 'Content-Encoding' 헤더에 명시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에서만 gzip으로 압축하고 'Content-Encoding'을 명시해 주면 끝이다. (br, deflate, zstd로 압축을 해도 상관없다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx나 Traefik와 같은 웹 서버는 압축 기능을 제공하고 있어 백엔드 코드를 건드리지 않고도 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 특정 경로에서의 처리는 불가능하기 때문에 나는 스프링 필터를 사용해 특정 경로에서만 gzip 압축을 하도록 구현했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  Spring Filter를 사용하여 특정 API 응답 압축 구현기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;java.util.zip&lt;/b&gt;에서 &lt;b&gt;GZIPOutputStream&lt;/b&gt;을 제공하기 때문에 ServletOutputStream을 GZIPOutputStream으로 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&amp;nbsp;&lt;b&gt;HttpServletResponseWrapper&lt;/b&gt;를 GZIPOutputStream을 사용하도록 수정하고 Filter에서 압축할 API의 엔드포인트를 검증하여 분기처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1️⃣ GzipHttpServletResponseWrapper&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1762772881074&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** GZIP 압축 적용 응답 Wrapper */
public class GzipHttpServletResponseWrapper extends HttpServletResponseWrapper {

    public static final String GZIP = &quot;gzip&quot;;

    private GzipServletOutputStream gzipServletOutputStream;

    public GzipHttpServletResponseWrapper(HttpServletResponse response) {
        super(response);
        // HTTP response에 Content-Encoding을 GZIP으로 설정
        response.addHeader(HttpHeaders.CONTENT_ENCODING, GZIP);
        
        // Vary: Accept-Encoding 헤더 설정
        response.addHeader(HttpHeaders.VARY, HttpHeaders.ACCEPT_ENCODING);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (gzipServletOutputStream == null) {
            gzipServletOutputStream = new GzipServletOutputStream(getResponse().getOutputStream());
        }
        return gzipServletOutputStream;
    }

    /** GZIP 출력 스트림 종료 */
    public void finish() throws IOException {
        if (gzipServletOutputStream != null) {
            gzipServletOutputStream.flush();
            gzipServletOutputStream.close();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1017&quot; data-start=&quot;943&quot;&gt;&lt;b&gt;HttpServletResponseWrapper&lt;/b&gt;를 상속받아 &lt;b&gt;응답 스트림을 GZIPOutputStream으로 감싼다.&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1076&quot; data-start=&quot;1018&quot;&gt;&quot;Content-Encoding: gzip&quot;과 &quot;Vary: Accept-Encoding&quot; 헤더를 추가한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1076&quot; data-start=&quot;1018&quot;&gt;&quot;Vary: Accept-Encoding&quot;는 캐시 시스템(CDN, Proxy, Cache)에게 클라이언트의 &quot;Accept-Encoding&quot; 헤더 값에 따라 응답이 달라질 수 있음을 알려준다. 만약 Vary를 적용하지 않는다면, gzip으로 압축한 응답이 캐시 했다가 gzip을 지원하지 않는 클라이언트에게 그대로 전달할 수 있는 문제가 발생한다. 따라서 &quot;Vary: Accept-Encoding&quot;도 추가하는 게 안전하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1141&quot; data-start=&quot;1077&quot;&gt;&lt;b&gt;getOutputStream()&lt;/b&gt;에서 gzip 압축 스트림(GzipServletOutputStream)을 생성한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;즉, 이 클래스는 기존 &lt;b&gt;HttpServletResponse&lt;/b&gt;를 gzip 응답용으로 감싸는 역할을 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1268&quot; data-start=&quot;1231&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2️⃣ GzipServletOutputStream&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1762774439385&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** GZIP 출력 스트림 */
public class GzipServletOutputStream extends ServletOutputStream {

    private final GZIPOutputStream gzipOutputStream;

    public GzipServletOutputStream(OutputStream outputStream) throws IOException {
        this.gzipOutputStream = new GZIPOutputStream(outputStream);
    }

    @Override
    public boolean isReady() {
        return true;
    }

    @Override
    public void setWriteListener(WriteListener writeListener) {
    }

    @Override
    public void write(int b) throws IOException {
        gzipOutputStream.write(b);
    }

    @Override
    public void flush() throws IOException {
        gzipOutputStream.flush();
    }

    @Override
    public void close() throws IOException {
        gzipOutputStream.close();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;1368&quot; data-end=&quot;1517&quot;&gt;
&lt;li data-start=&quot;1368&quot; data-end=&quot;1426&quot;&gt;&lt;b&gt;ServletOutputStream&lt;/b&gt;을 상속받아 내부적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;GZIPOutputStream&lt;/b&gt;을 사용한다.&lt;/li&gt;
&lt;li data-start=&quot;1427&quot; data-end=&quot;1476&quot;&gt;write(), flush(), close() 모두 &lt;b&gt;java.util.zip&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;GZIPOutputStream&lt;/b&gt;을 적용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;즉, 이 클래스는 실제 gzip 압축을 수행하는 역할을 한다.&lt;b&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-end=&quot;1582&quot; data-start=&quot;1554&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1582&quot; data-start=&quot;1554&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3️⃣ CompressFilter&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1762774412891&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** 응답 데이터 압축 필터 */
@Component
public class CompressFilter extends OncePerRequestFilter {

    /** GZIP 압축이 허용된 API 엔드포인트의 정규식 패턴 목록 */
    private static final List&amp;lt;Pattern&amp;gt; ALLOWED_COMPRESS_ENDPOINT_PATTERNS = List.of(
            Pattern.compile(&quot;^/events/[^/]+$&quot;)
    );

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        /** 압축 허용된 API가 아닐 경우 미압축 응답을 반환 */
        if (!shouldCompress(request)) {
            filterChain.doFilter(request, response);
            return;
        }

        /** Gzip 압축 응답 생성 Wrapper를 사용하여 필터 체인 실행 */
        GzipHttpServletResponseWrapper gzipResponse = new GzipHttpServletResponseWrapper(response);
        try {
            filterChain.doFilter(request, gzipResponse);
        } finally {
            gzipResponse.finish();
        }
    }

    /** 주어진 요청이 GZIP 압축 대상인지 검증 */
    private boolean shouldCompress(HttpServletRequest request) {
        String acceptEncoding = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
        String uri = request.getRequestURI();
        String method = request.getMethod();

        boolean isGet = HttpMethod.GET.name().equalsIgnoreCase(method);

        return acceptEncoding != null
                &amp;amp;&amp;amp; acceptEncoding.contains(GZIP)
                &amp;amp;&amp;amp; isGet
                &amp;amp;&amp;amp; matchesAllowedUri(uri);
    }

    /** 요청 URI가 허용된 압축 엔드포인트 패턴과 일치하는지 검사 */
    private boolean matchesAllowedUri(String uri) {
        return ALLOWED_COMPRESS_ENDPOINT_PATTERNS.stream()
                .anyMatch(pattern -&amp;gt; pattern.matcher(uri).matches());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1811&quot; data-start=&quot;1685&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1714&quot; data-start=&quot;1685&quot;&gt;&lt;b&gt;특정 API 요청만&lt;/b&gt; gzip으로 압축하도록 필터링한다.&lt;/li&gt;
&lt;li data-end=&quot;1714&quot; data-start=&quot;1685&quot;&gt;정규식으로 URI를 매칭하여 일치할 경우에만 압축한다.&lt;/li&gt;
&lt;li data-end=&quot;1811&quot; data-start=&quot;1766&quot;&gt;request의 &quot;Accept-Encoding&quot; 헤더에 gzip이 포함된 경우에만 처리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;즉, 이 클래스는 클라이언트의 요청을 확인하고 gzip으로 반환 가능한지 검증 후 Wrapper를 사용해 응답을 압축하는 역할을 한다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  적용 결과&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-10 오후 8.43.53.png&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;30&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mIOm4/dJMcajURNZf/umTb2OVJHbBgMr8LTaxZi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mIOm4/dJMcajURNZf/umTb2OVJHbBgMr8LTaxZi0/img.png&quot; data-alt=&quot;gzip 압축 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mIOm4/dJMcajURNZf/umTb2OVJHbBgMr8LTaxZi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmIOm4%2FdJMcajURNZf%2FumTb2OVJHbBgMr8LTaxZi0%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;295&quot; height=&quot;30&quot; data-filename=&quot;스크린샷 2025-11-10 오후 8.43.53.png&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;30&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gzip 압축 전&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-10 오후 8.43.40.png&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;34&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckFOQ1/dJMcacamUdz/oOgkPOPdJnsQEClvIfoJk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckFOQ1/dJMcacamUdz/oOgkPOPdJnsQEClvIfoJk1/img.png&quot; data-alt=&quot;gzip 압축 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckFOQ1/dJMcacamUdz/oOgkPOPdJnsQEClvIfoJk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckFOQ1%2FdJMcacamUdz%2FoOgkPOPdJnsQEClvIfoJk1%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;258&quot; height=&quot;34&quot; data-filename=&quot;스크린샷 2025-11-10 오후 8.43.40.png&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;34&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gzip 압축 후&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;b&gt;중간지점 1개, 출발지 8개 기준&lt;/b&gt;으로 압축 전후의 결과이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;167&quot; data-start=&quot;120&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;143&quot; data-start=&quot;120&quot;&gt;응답 시간: 약 &lt;b&gt;27% 단축&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;167&quot; data-start=&quot;144&quot;&gt;응답 크기: 약 &lt;b&gt;83% 감소&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;233&quot; data-start=&quot;169&quot; data-ke-size=&quot;size16&quot;&gt;앞서 언급한 적용 근거처럼, &lt;b&gt;네트워크 속도가 느릴수록&lt;/b&gt; 압축 전후의 응답 시간 차이는 더 크게 나타날 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;233&quot; data-start=&quot;169&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;최범균 - &quot;주니어 백엔드 개발자가 반드시 알아야 할 실무 지식&quot;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/gzip_compression&quot;&gt;https://developer.mozilla.org/en-US/docs/Glossary/gzip_compression&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Encoding&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Encoding&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://tools.paulcalvano.com/compression.php&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tools.paulcalvano.com/compression.php&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://bepoz-study-diary.tistory.com/434&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://bepoz-study-diary.tistory.com/434&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Backend/Spring Boot</category>
      <category>gzip</category>
      <category>http</category>
      <category>java</category>
      <category>Spring Boot</category>
      <category>spring filter</category>
      <category>모이삼</category>
      <category>중간 장소 찾기</category>
      <category>중간 장소 추천</category>
      <category>중간 지점 찾기</category>
      <category>중간 지점 추천</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/88</guid>
      <comments>https://developer-anxi.tistory.com/88#entry88comment</comments>
      <pubDate>Mon, 10 Nov 2025 21:19:53 +0900</pubDate>
    </item>
    <item>
      <title>[PostgreSQL] FATAL: remaining connection slots are reserved for roles with privileges of the &amp;quot;rds_reserved&amp;quot; role 해결하기</title>
      <link>https://developer-anxi.tistory.com/87</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; &amp;zwj;♂️ 문제 : 외부에서 DB 접속이 되지 않음&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-10-21 오전 12.32.16.png&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czOj2V/dJMb89dIUnu/3PZAzANMN2v7bu5lV19MIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czOj2V/dJMb89dIUnu/3PZAzANMN2v7bu5lV19MIK/img.png&quot; data-alt=&quot;DB 연결 시, 발생한 문제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czOj2V/dJMb89dIUnu/3PZAzANMN2v7bu5lV19MIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczOj2V%2FdJMb89dIUnu%2F3PZAzANMN2v7bu5lV19MIK%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;682&quot; height=&quot;144&quot; data-filename=&quot;스크린샷 2025-10-21 오전 12.32.16.png&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DB 연결 시, 발생한 문제&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;최근 모이삼 프로젝트 git이 꼬여 제거하고 다시 clone 하여 로컬 환경 설정을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IDE에서 DB를 연결하는 도중, 위와 같은 에러가 발생했다.&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;1608&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ToPf6/dJMb9XdgTOa/xKxMCy5pOpX5Tx7ofha9Jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ToPf6/dJMb9XdgTOa/xKxMCy5pOpX5Tx7ofha9Jk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ToPf6/dJMb9XdgTOa/xKxMCy5pOpX5Tx7ofha9Jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FToPf6%2FdJMb9XdgTOa%2FxKxMCy5pOpX5Tx7ofha9Jk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1608&quot; height=&quot;586&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;586&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;RDS를 사용하고 있어 확인해 보니 &quot;&lt;b&gt;현재 활동&quot;&lt;/b&gt;의 연결 수가 72개였다. &lt;b&gt;현재 활동&lt;/b&gt;이란 Connection 연결 수를 의미한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-10-21 오후 6.36.56.png&quot; data-origin-width=&quot;931&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAxjM6/dJMb9VNiahC/K5TRnUX1LSSxeKD7HXajE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAxjM6/dJMb9VNiahC/K5TRnUX1LSSxeKD7HXajE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAxjM6/dJMb9VNiahC/K5TRnUX1LSSxeKD7HXajE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAxjM6%2FdJMb9VNiahC%2FK5TRnUX1LSSxeKD7HXajE0%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;931&quot; height=&quot;270&quot; data-filename=&quot;스크린샷 2025-10-21 오후 6.36.56.png&quot; data-origin-width=&quot;931&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그를 확인해 보니 위 에러가 반복적으로 발생했음을 알 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DB가 허용하는 최대 연결 수(Max Connections)가 완전히 꽉 찼으며, 일반 사용자를 위한 연결 슬롯은 0개입니다. 이제 남은 연결 자리는 AWS가 DB 관리를 위해 확보해 둔 비상용 슬롯뿐입니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, AWS가 아닌 우리(사용자)는 DB 연결을 할 수 없음을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이런 문제가 발생했을까?&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; &amp;nbsp; Client와&amp;nbsp; RDS를 중개하는 EC2 서버가 존재&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blGpLA/dJMb9WSYaIg/RbW49vI9leK5PtPXPuBEcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blGpLA/dJMb9WSYaIg/RbW49vI9leK5PtPXPuBEcK/img.png&quot; data-alt=&quot;모이삼 시스템 아키텍처&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blGpLA/dJMb9WSYaIg/RbW49vI9leK5PtPXPuBEcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblGpLA%2FdJMb9WSYaIg%2FRbW49vI9leK5PtPXPuBEcK%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;1280&quot; height=&quot;820&quot; data-filename=&quot;다운로드.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;820&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;p data-ke-size=&quot;size16&quot;&gt;메인 서버는 &lt;b&gt;Naver Cloud Server&lt;/b&gt;를 사용하고 있다. 그리고 DB는 &lt;b&gt;AWS의 RDS&lt;/b&gt;를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 서버에서 DB의 연결은 &lt;b&gt;AWS의 EC2&lt;/b&gt;로 &lt;b&gt;중개&lt;/b&gt;하여 구축했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 구축한 이유는 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS 프리티어의 이점을 살리기 위함.&lt;/li&gt;
&lt;li&gt;Naver Cloud의 DB 인스턴스 비용이 비쌈.&lt;/li&gt;
&lt;li&gt;Naver Cloud와 AWS 멀티 클라우드 환경에서의 연결이 가능하지만 비용 발생.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구축 이유를 요약하자면, 비용을 들이지 않고 구축하기를 바랐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 에러 원인을 찾기 위해 중개 서버인 EC2를 확인했고, 그 결과..&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;1291&quot; data-origin-height=&quot;667&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ERLrU/dJMb9LDZeIO/8xO55NV3yzwOc4taakidu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ERLrU/dJMb9LDZeIO/8xO55NV3yzwOc4taakidu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ERLrU/dJMb9LDZeIO/8xO55NV3yzwOc4taakidu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FERLrU%2FdJMb9LDZeIO%2F8xO55NV3yzwOc4taakidu0%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;1291&quot; height=&quot;667&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1291&quot; data-origin-height=&quot;667&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;수많은 socat 프로세스가 존재했고, 이는 RDS에서 보았던 &lt;b&gt;현재 활동&lt;/b&gt;의 수와 일치함을 확인했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  기존 EC2, RDS 연결 방식 : socat을 이용하여 포트포워딩&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 서버에서 RDS를 접속하기 위해서 EC2가 포트포워딩을 해줘야 했다. EC2를 포트포워딩 하기 위해 나는 &lt;b&gt;socat&lt;/b&gt;을 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;socat은 소켓(Socket) 생성 및 소켓 간 데이터 전송 등의 데이터 송신 등의 기능을 제공하는 프로그램이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1761042210952&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# EC2
$ nohup socat TCP-LISTEN:{EC2_PORT},fork TCP:{RDS_ADDRESS}:{RDS_PORT} &amp;amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2의 특정 포트로 들어온 연결을 RDS의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;특정&lt;span&gt;&amp;nbsp;포트&lt;/span&gt;&lt;/span&gt;로 연결하여, 메인 서버에서 EC2 IP를 사용해 RDS에 접근하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 nohup은 터미널 세션이 끝나도 동작하도록, 뒤에 ampersand(&amp;amp;)는 백그라운드에서 실행 가능하기 위해 설정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 fork 옵션에서 문제가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fork 옵션은 자식 프로세스를 생성하기 때문에 다수의 connection을 만들기 위해 필수적인 옵션이다. 그러나 프로세스가 계속 누적되고, 누적된 프로세스를 청소하질 않아 위의 문제가 발생했다.&lt;/p&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;killall socat을&lt;/b&gt; 사용하여 socat의 모든 프로세스를 제거했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  해결 방법 : PgBouncer를 이용&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1시간마다 프로세스를 클린업 하도록 자동화 스크립트를 작성하면 socat을 사용하더라도 괜찮을 수 있다. 다만 단순히 프로세스를 클린업 하는 건 좋지 않다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면, 정각에 클린업 이후 다수의 db connection이 발생했을 경우에 초기 연결 비용이 발생할 수 있다. 또한 현재 사용하고 있는 프로세스가 db 트랜잭션 연결 중인지, idle 상태인지 구분하기 어렵다고 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 PostgreSQL 프로세스 연결을 도와주는 도구인 PgBouncer를 알게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-10-21 오후 7.40.23.png&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/64fRV/dJMb9VGwH1c/0mk7TUR62NZg6Muu14kkOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/64fRV/dJMb9VGwH1c/0mk7TUR62NZg6Muu14kkOk/img.png&quot; data-alt=&quot;https://postgresql.kr/blog/pgbouncer.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/64fRV/dJMb9VGwH1c/0mk7TUR62NZg6Muu14kkOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F64fRV%2FdJMb9VGwH1c%2F0mk7TUR62NZg6Muu14kkOk%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;847&quot; height=&quot;148&quot; data-filename=&quot;스크린샷 2025-10-21 오후 7.40.23.png&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://postgresql.kr/blog/pgbouncer.html&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;그리고 PgBouncer 관련 글을 읽던 와중, 세 번째 방식인 전용 호스트를 두는 방법이 중개 서버 EC2와 유사하다고 느껴 적용하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  적용 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용 방식은 &lt;a href=&quot;https://postgresql.kr/blog/pgbouncer.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://postgresql.kr/blog/pgbouncer.html을&lt;/a&gt; 참고했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. PgBouncer 설치하기&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1761043442749&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo apt update
$ sudo apt install pgbouncer&lt;/code&gt;&lt;/pre&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;b&gt;2. /etc/pgbouncer/pgbouncer.ini 설정하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;/etc/pgbouncer &lt;/b&gt;하위에 &lt;b&gt;pgbouncer.ini&lt;/b&gt;와 &lt;b&gt;userlist.txt&lt;/b&gt;가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;pgbouncer.ini&lt;/b&gt;는 응용 프로그램 설정 파일, &lt;b&gt;userlist.txt&lt;/b&gt;는 사용자 인증 파일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값 설정은 위 링크를 참고하여 서비스에 맞게 설정하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모이삼은 다음과 같이 설정했다.&lt;/p&gt;
&lt;pre id=&quot;code_1761044265908&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo vi pgbouncer.ini

[databases] # PgBouncer가 RDS 인스턴스에 접속할 때 사용할 정보
&amp;lt;RDS 별칭&amp;gt; = host=&amp;lt;RDS 엔드포인트&amp;gt; port=5432 dbname=&amp;lt;RDS 이름&amp;gt; user=&amp;lt;RDS 사용자 이름&amp;gt;
ex) mydb = host=mydb.xxxx.rds.amazonaws.com port=5432 dbname=app user=admin

[pgbouncer]
listen_addr = * # 모든 IP 허용
listen_port = 5432

;; any, trust, plain, md5, cert, hba, pam
auth_type = md5 # 암호 방식
auth_file = /etc/pgbouncer/userlist.txt # 사용자 인증 파일 위치 

;; When server connection is released back to pool:
;;   session      - after client disconnects (default)
;;   transaction  - after transaction finishes
;;   statement    - after statement finishes
;; 트랜잭션이 끝날 때마다 풀에 반납하도록 함
pool_mode = transaction

;; Comma-separated list of parameters to ignore when given in startup packet.
;; 최신 JDBC 드라이버가 PgBouncer가 지원하지 않는 시작 파라미터를 보낼 때 연결이 거부되는 오류를 방지
ignore_startup_parameters = extra_float_digits 

;; PgBouncer가 RDS로 유지하는 connection 수
default_pool_size = 40

;; 풀에 들어있는 최소 connection 수
min_pool_size = 10

;; RDS connection 슬롯 부족을 방지하기 위해 default_pool_size와 동일하게 설정
max_db_connections = 40

;; PgBouncer와 RDS 간의 연결을 1시간마다 주기적으로 재생성
;; 장기 연결로 인한 DB 서버의 메모리 누수 방지
server_lifetime = 3600

;; 사용되지 않고 풀에 남아 있는 RDS 연결을 10분 후 자동으로 정리
;; 불필요한 DB 연결 슬롯 낭비 방지
server_idle_timeout = 600

;; PgBouncer에 연결한 클라이언트가 1분 동안 아무 활동이 없으면 연결을 강제로 끊음.
client_idle_timeout = 60&lt;/code&gt;&lt;/pre&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;b&gt;3. /etc/pgbouncer/userlist.txt 설정하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #585858; text-align: start;&quot;&gt;&quot;사용자이름&quot; &quot;비밀번호&quot;로 작성하면 되고, 비밀번호는 DB 암호를 사용하면 된다. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;(AWS RDS PostgreSQL 17 기준)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1761045009463&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo vi userlist.txt

# &quot;사용자 이름&quot; &quot;비밀번호&quot;
&quot;admin&quot; &quot;1234&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;  비밀번호를 scram-sha-256 방식으로 바꿔서 넣어야 한다고 하는데, pgbouncer가 동작하지 않았다.&lt;br /&gt;만약 AWS RDS PostgreSQL 17 버전을 사용한다면, 비밀번호를 평문으로 넣어서 실행하면 될 것이다.&lt;/blockquote&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;b&gt;4. PgBouncer 재시작하기&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1761045316579&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo systemctl restart pgbouncer&lt;/code&gt;&lt;/pre&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;b&gt;5. AWS EC2 IP를 사용해 RDS 접속하기&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1761045459667&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# application.yml
spring:
  datasource:
    # EC2 인스턴스의 IP 주소 사용
    url: jdbc:postgresql://&amp;lt;EC2 IP 주소&amp;gt;/&amp;lt;Database&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot는 위와 같이 변경하면 되고, Data Grip을 사용할 경우에도 EC2 IP 주소를 통해 접속 가능하다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  마무리&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;FATAL:&amp;nbsp;remaining&amp;nbsp;connection&amp;nbsp;slots&amp;nbsp;are&amp;nbsp;reserved&amp;nbsp;for&amp;nbsp;roles&amp;nbsp;with&amp;nbsp;privileges&amp;nbsp;of&amp;nbsp;the&amp;nbsp;&quot;rds_reserved&quot;&amp;nbsp;role&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS RDS 연결 과정에서 마주한 에러를 PgBouncer를 사용해 해결했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에는 socat을 사용했고, 이번에는 PgBouncer를 사용하는 방식으로 변경했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;돈을 내지 않기 위해 이런저런 방법을 사용해 봤는데, 나름대로 괜찮은 방법인 거 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RDS의 Public Access를 키더라도, 비용 발생할 뿐만 아니라 보안적으로도 좋지 않고,, Naver Cloud의 DB를 사용하기엔 비용이 너무 비싸다. 메인 서버 내부의 파드로 띄울 수도 있긴 하지만, RDS에서 제공하는 기능을 사용할 수 있음&amp;nbsp;좋으니까..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;➕ &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Unable to commit against JDBC Connection 발생  &lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-09 오후 8.05.04.png&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;847&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckC2FM/dJMcajtNecK/M0kghtuFZk7AJ5WpDrIRS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckC2FM/dJMcajtNecK/M0kghtuFZk7AJ5WpDrIRS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckC2FM/dJMcajtNecK/M0kghtuFZk7AJ5WpDrIRS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckC2FM%2FdJMcajtNecK%2FM0kghtuFZk7AJ5WpDrIRS1%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;712&quot; height=&quot;735&quot; data-filename=&quot;스크린샷 2025-11-09 오후 8.05.04.png&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;847&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;PgBoucer를 적용한 뒤, 종종 위 에러를 확인할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전엔 발견하지 못했던 에러라서 PgBouncer 적용 과정에서 발생한 문제가 확실했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 에러는 지도 조회 페이지에서 오랜 시간 있었을 경우 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 생각에는 &lt;b&gt;pool_mode&lt;/b&gt;를 &lt;b&gt;transaction&lt;/b&gt;으로 설정했기 때문에 트랜잭션이 끝나면 PgBouncer가 커넥션풀에 커넥션을 반환한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 커넥션을 반환한 후에 다시 사용할 수 없어 위 에러가 발생했다고 판단한 뒤, pool_mode를 &lt;b&gt;session&lt;/b&gt;으로 설정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;session 모드는 커넥션이 세션 단위로 유지되기 때문에 웹 페이지에서 오랜 시간 있더라도 문제가 발생하지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;만약 &lt;b&gt;Unable to commit against JDBC Connection&lt;/b&gt;이 발생한다면,&amp;nbsp;&lt;br /&gt;&lt;b&gt;pool_mode&lt;/b&gt;를 &lt;b&gt;session&lt;/b&gt;으로 변경해보자!&lt;/span&gt;&lt;/blockquote&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://postgresql.kr/blog/pgbouncer.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://postgresql.kr/blog/pgbouncer.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sawaca96.tistory.com/16&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://sawaca96.tistory.com/16&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/데이터베이스</category>
      <category>AWS</category>
      <category>ConnectionPool</category>
      <category>db</category>
      <category>Infra</category>
      <category>PgBouncer</category>
      <category>PostgreSQL</category>
      <category>RDS</category>
      <category>socat</category>
      <category>Trouble Shooting</category>
      <category>트러블슈팅</category>
      <author>anxi</author>
      <guid isPermaLink="true">https://developer-anxi.tistory.com/87</guid>
      <comments>https://developer-anxi.tistory.com/87#entry87comment</comments>
      <pubDate>Tue, 21 Oct 2025 20:40:07 +0900</pubDate>
    </item>
  </channel>
</rss>