<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <author>
    <name>어썸블로그</name>
  </author>
  <id>국내의 좋은 블로그 글들을 매일 배달해줍니다.</id>
  <title>테크회사 어썸블로그</title>
  <updated>2026-06-19T21:40:00+09:00</updated>
  <entry>
    <author>
      <name>rupert.kim</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;AI 에이전트로 카카오톡 추천 지표 분석 자동화하기: Hadoop 기반 도입 사례
안녕하세요. 소셜추천엔진팀에서 숏폼 추천 모델을 개발하고 있는 루퍼트(rupert)입니다.
추천 시스템을 개발하다 보면 코드를 짜는 시간만큼이나 데이터를 들여다보는 시간이 길어집니다. 지표가 조금만 움직여도 “이번 주 CTR이 왜 떨어졌지?”, “실험군 반응은 어땠지?”, “배포 이후 특정 사용자군에서 달라진 점은 없을까?” 같은 질문이 이어집니다.
질문은 한 문장이지만,...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://tech.kakao.com/posts/824</id>
    <link href="https://tech.kakao.com/posts/824"/>
    <summary type="html">AI 에이전트로 카카오톡 추천 지표 분석 자동화하기: Hadoop 기반 도입 사례
안녕하세요. 소셜추천엔진팀에서 숏폼 추천 모델을 개발하고 있는 루퍼트(rupert)입니다.
추천 시스템을 개발하다 보면 코드를 짜는 시간만큼이나 데이터를 들여다보는 시간이 길어집니다. 지표가 조금만 움직여도 “이번 주 CTR이 왜 떨어졌지?”, “실험군 반응은 어땠지?”, “배포 이후 특정 사용자군에서 달라진 점은 없을까?” 같은 질문이 이어집니다.
질문은 한 문장이지만,...</summary>
    <title>AI 에이전트로 카카오톡 추천 지표 분석 자동화하기</title>
    <updated>2026-06-16T00:00:00+09:00</updated>
    <dc:date>2026-06-16T00:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>sue.cream</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;2편을 쓴 뒤 시간이 꽤 지났습니다. 그 사이 AI 도구들은 더 많은 일을 하게 되었고, 저도 이전보다 훨씬 자주 AI 에이전트와 함께 일하게 되었습니다.
처음에는 업무에 실제적으로 도움을 주는 도구를 직접 만드는 일이 신났습니다. 개선하고 싶은 기능을 설명하면 화면이 생기고, 입력값을 넣으면 일정하게 필요한 결과가 나왔습니다. 이렇게 만든 도구들을 실제 업무에 계속쓰다 보니, 관심사가 자연스럽게 다음 단계로 넘어갔습니다.
혼자 쓰던 도구를 다른 사람에...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://tech.kakao.com/posts/823</id>
    <link href="https://tech.kakao.com/posts/823"/>
    <summary type="html">2편을 쓴 뒤 시간이 꽤 지났습니다. 그 사이 AI 도구들은 더 많은 일을 하게 되었고, 저도 이전보다 훨씬 자주 AI 에이전트와 함께 일하게 되었습니다.
처음에는 업무에 실제적으로 도움을 주는 도구를 직접 만드는 일이 신났습니다. 개선하고 싶은 기능을 설명하면 화면이 생기고, 입력값을 넣으면 일정하게 필요한 결과가 나왔습니다. 이렇게 만든 도구들을 실제 업무에 계속쓰다 보니, 관심사가 자연스럽게 다음 단계로 넘어갔습니다.
혼자 쓰던 도구를 다른 사람에...</summary>
    <title>Vibe Coding하는 비개발자는 개발자인가(3)</title>
    <updated>2026-06-16T00:00:00+09:00</updated>
    <dc:date>2026-06-16T00:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>라인</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;안녕하세요. LY Corporation에서 인증·인가 기반 Athenz의 개발·운영을 담당하고 있는 보안 플랫폼 엔지니어 김정우입니다.지난 글 AI 시대에 인증 과제를 해결할 차세...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://techblog.lycorp.co.jp/ko/id-jag-the-hard-way-learning-ai-agent-authz-through-failure</id>
    <link href="https://techblog.lycorp.co.jp/ko/id-jag-the-hard-way-learning-ai-agent-authz-through-failure"/>
    <summary type="html">안녕하세요. LY Corporation에서 인증·인가 기반 Athenz의 개발·운영을 담당하고 있는 보안 플랫폼 엔지니어 김정우입니다.지난 글 AI 시대에 인증 과제를 해결할 차세...</summary>
    <title>ID-JAG The Hard Way: 실패로 배우는 AI 에이전트 보안 핸즈온</title>
    <updated>2026-06-17T12:00:00+09:00</updated>
    <dc:date>2026-06-17T12:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>네이버</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;네이버 사내 기술 교류 행사인 NAVER ENGINEERING DAY 2026(5월)에서 발표되었던 세션을 공개합니다.&lt;br&gt; &lt;/p&gt;

&lt;div style="position: relative; max-width: 100%; padding-bottom: 56.25%; height: 0;"&gt;

&lt;iframe width="800" height="450" src="https://tv.naver.com/embed/101436940?autoPlay=true" frameborder="0" allowfullscreen="" style="position: absolute; position: absolute; top: 0; left: 0; width: 100%; height: 100%;"&gt;&lt;/iframe&gt;  
&lt;/div&gt;  

&lt;p&gt;&lt;br&gt;&lt;/p&gt;

&lt;h4 id=""&gt;발표 내용&lt;/h4&gt;

&lt;p&gt;입력 스펙이 자주 바뀌는 쇼핑 에이전트 답변 모델 개발에서, 변경된 스펙만 입력하면 결함 탐지/프롬프트 최적화/SFT 학습 데이터 생성을 에이전트가 폐쇄 루프로 돌리는 자동화 파이프라인을 설계하며 얻은 구조와 적용 경험을 공유합니다.&lt;/p&gt;

&lt;h4 id=""&gt;발표 대상&lt;/h4&gt;

&lt;p&gt;AI 서비스를 위한 스펙기반 프롬프트 최적화를 적용하고자 하시는 기획/AI엔지니어 분들&lt;/p&gt;

&lt;h4 id=""&gt;목차&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Agent Spec  &lt;/li&gt;
&lt;li&gt;Defect Detection  &lt;/li&gt;
&lt;li&gt;프롬프트 최적화&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;h5 id="naverengineeringdaybr"&gt;
&lt;strong&gt;◎ NAVER Engineering Day란?&lt;/strong&gt;&lt;br&gt;
&lt;/h5&gt;
  
  &lt;p&gt;NAVER에서는 사내 개발 경험과 기술 트렌드를 교류를 할 수 있는 프로그램이 많이 있습니다. 그중 이제는 매회 평균 100개 이상의 발표가 이루어지는 NAVER Engineering Day를 빼놓을 수 없는데요. &lt;br&gt;
  2016년부터 시작된 ENGINEERING DAY는 실무에서의 기술 개발 경험과 새로운 기술과 플랫폼 도입 시 유용하게 활용될 수 있는 팁 등을 공유하며 서로 배우고 성장하는 네이버의 대표적인 사내 개발자 행사입니다.(&lt;a href="https://d2.naver.com/news/0766161"&gt;관련 포스팅 보기&lt;/a&gt;) &lt;br&gt;
  올해 진행된 NAVER Engineering Day의 일부 세션을 공개합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://d2.naver.com/helloworld/2852215</id>
    <link href="https://d2.naver.com/helloworld/2852215"/>
    <title>스펙만 바꾸면 프롬프트가 따라옵니다 - 답변 생성 모델 자동화 파이프라인</title>
    <updated>2026-06-18T19:17:54+09:00</updated>
    <dc:date>2026-06-18T19:17:54+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>네이버</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;네이버 사내 기술 교류 행사인 NAVER ENGINEERING DAY 2026(5월)에서 발표되었던 세션을 공개합니다.&lt;br&gt; &lt;/p&gt;

&lt;div style="position: relative; max-width: 100%; padding-bottom: 56.25%; height: 0;"&gt;

&lt;iframe width="800" height="450" src="https://tv.naver.com/embed/101382306?autoPlay=true" frameborder="0" allowfullscreen="" style="position: absolute; position: absolute; top: 0; left: 0; width: 100%; height: 100%;"&gt;&lt;/iframe&gt;  
&lt;/div&gt;  

&lt;p&gt;&lt;br&gt;&lt;/p&gt;

&lt;h4 id=""&gt;발표 내용&lt;/h4&gt;

&lt;p&gt;매 세션 초기화되는 AI의 한계를 넘어, 경험을 축적하고 스스로 성장하는 에이전트 프레임워크 GNOSIS의 설계 원칙과 구현 사례를 소개합니다.&lt;/p&gt;

&lt;h4 id=""&gt;발표 대상&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;AI Agent 프레임워크 활용에 관심 있는 개발자&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=""&gt;목차&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;PROLOGUE — 당신의 AI는 어제와 똑같다  &lt;/li&gt;
&lt;li&gt;INTRODUCTION — GNOSIS 30초 요약  &lt;/li&gt;
&lt;li&gt;ARCHITECTURE — 3-Loop + Constitution + 5층 기억  &lt;/li&gt;
&lt;li&gt;ALGORITHMS — 13 공리 · 17 메커니즘 · 7 알고리즘  &lt;/li&gt;
&lt;li&gt;THEORY — 수학적 안전 보장  &lt;/li&gt;
&lt;li&gt;EXPERIMENTS — 검증과 외부 근거  &lt;/li&gt;
&lt;li&gt;IMPLEMENTATION — Phase -1 → 3  &lt;/li&gt;
&lt;li&gt;DISCUSSION — 모르는 것은 모른다고 말한다  &lt;/li&gt;
&lt;li&gt;SUMMARY &amp;amp; Q&amp;amp;A — 5분 핵심 요약&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;h5 id="naverengineeringdaybr"&gt;
&lt;strong&gt;◎ NAVER Engineering Day란?&lt;/strong&gt;&lt;br&gt;
&lt;/h5&gt;
  
  &lt;p&gt;NAVER에서는 사내 개발 경험과 기술 트렌드를 교류를 할 수 있는 프로그램이 많이 있습니다. 그중 이제는 매회 평균 100개 이상의 발표가 이루어지는 NAVER Engineering Day를 빼놓을 수 없는데요. &lt;br&gt;
  2016년부터 시작된 ENGINEERING DAY는 실무에서의 기술 개발 경험과 새로운 기술과 플랫폼 도입 시 유용하게 활용될 수 있는 팁 등을 공유하며 서로 배우고 성장하는 네이버의 대표적인 사내 개발자 행사입니다.(&lt;a href="https://d2.naver.com/news/0766161"&gt;관련 포스팅 보기&lt;/a&gt;) &lt;br&gt;
  올해 진행된 NAVER Engineering Day의 일부 세션을 공개합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://d2.naver.com/helloworld/4399330</id>
    <link href="https://d2.naver.com/helloworld/4399330"/>
    <title>도구에서 동료로 — AI 에이전트 자율 성장 프레임워크</title>
    <updated>2026-06-17T20:31:17+09:00</updated>
    <dc:date>2026-06-17T20:31:17+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>네이버</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;네이버 사내 기술 교류 행사인 NAVER ENGINEERING DAY 2026(5월)에서 발표되었던 세션을 공개합니다.&lt;br&gt; &lt;/p&gt;

&lt;div style="position: relative; max-width: 100%; padding-bottom: 56.25%; height: 0;"&gt;

&lt;iframe width="800" height="450" src="https://tv.naver.com/embed/101332026?autoPlay=true" frameborder="0" allowfullscreen="" style="position: absolute; position: absolute; top: 0; left: 0; width: 100%; height: 100%;"&gt;&lt;/iframe&gt;  
&lt;/div&gt;  

&lt;p&gt;&lt;br&gt;&lt;/p&gt;

&lt;h4 id=""&gt;발표 내용&lt;/h4&gt;

&lt;p&gt;서드파티 SDK 환경에서 범용 에러 모니터링 도구 연동 시 발생하는 구조적 한계를 극복하기 위해, AI Agent를 활용해 전용 Javascript 에러 모니터링 시스템을 직접 구축한 경험과 그 가능성을 공유합니다.&lt;/p&gt;

&lt;h4 id=""&gt;발표 대상&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;외부 SaaS 도구의 한계를 경험해본 개발자&lt;/li&gt;
&lt;li&gt;프론트엔드/SDK 에러 모니터링에 관심 있는 개발자&lt;/li&gt;
&lt;li&gt;AI Agent를 활용한 개발 생산성 향상에 관심 있는 개발자&lt;/li&gt;
&lt;li&gt;사내 인프라를 활용한 자체 도구 구축을 고민 중인 팀&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=""&gt;목차&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Sentry와 광고 SDK  &lt;/li&gt;
&lt;li&gt;직접 만들기로 한 이유  &lt;/li&gt;
&lt;li&gt;glog 구축기  &lt;/li&gt;
&lt;li&gt;결과와 교훈&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;h5 id="naverengineeringdaybr"&gt;
&lt;strong&gt;◎ NAVER Engineering Day란?&lt;/strong&gt;&lt;br&gt;
&lt;/h5&gt;
  
  &lt;p&gt;NAVER에서는 사내 개발 경험과 기술 트렌드를 교류를 할 수 있는 프로그램이 많이 있습니다. 그중 이제는 매회 평균 100개 이상의 발표가 이루어지는 NAVER Engineering Day를 빼놓을 수 없는데요. &lt;br&gt;
  2016년부터 시작된 ENGINEERING DAY는 실무에서의 기술 개발 경험과 새로운 기술과 플랫폼 도입 시 유용하게 활용될 수 있는 팁 등을 공유하며 서로 배우고 성장하는 네이버의 대표적인 사내 개발자 행사입니다.(&lt;a href="https://d2.naver.com/news/0766161"&gt;관련 포스팅 보기&lt;/a&gt;) &lt;br&gt;
  올해 진행된 NAVER Engineering Day의 일부 세션을 공개합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://d2.naver.com/helloworld/8319114</id>
    <link href="https://d2.naver.com/helloworld/8319114"/>
    <title>SaaS 대체하기: AI와 함께한 광고SDK 에러 모니터링 시스템 구축기</title>
    <updated>2026-06-16T23:14:39+09:00</updated>
    <dc:date>2026-06-16T23:14:39+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>네이버</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;네이버 사내 기술 교류 행사인 NAVER ENGINEERING DAY 2026(5월)에서 발표되었던 세션을 공개합니다.&lt;br&gt; &lt;/p&gt;

&lt;div style="position: relative; max-width: 100%; padding-bottom: 56.25%; height: 0;"&gt;

&lt;iframe width="800" height="450" src="https://tv.naver.com/embed/101263731?autoPlay=true" frameborder="0" allowfullscreen="" style="position: absolute; position: absolute; top: 0; left: 0; width: 100%; height: 100%;"&gt;&lt;/iframe&gt;  
&lt;/div&gt;  

&lt;p&gt;&lt;br&gt;&lt;/p&gt;

&lt;h4 id=""&gt;발표 내용&lt;/h4&gt;

&lt;p&gt;AI 에이전트가 코드를 짜는 시대, 우리는 그 코드를 어떻게 믿을 수 있을까요? Playwright 기반 E2E 테스트를 구축하고, 에이전트가 직접 테스트 코드를 작성 및 검증하는 워크플로우를 만든 여정을 공유합니다.&lt;/p&gt;

&lt;h4 id=""&gt;발표 대상&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;특히 이런 분들에게 추천 드립니다.
&lt;ul&gt;
&lt;li&gt;"에이전트로 '딸깍'할 수 있는 대규모 코드베이스를 만들고 싶어요"&lt;/li&gt;
&lt;li&gt;"E2E 테스트, 어디서부터 시작해야 할지 모르겠어요"&lt;/li&gt;
&lt;li&gt;"테스트 짜본 적 없는데, 에이전트한테 시키고 싶어요"&lt;/li&gt;
&lt;li&gt;"테스트 깨질 때마다 사람이 고치느라, 오히려 생산성이 줄었어요"&lt;/li&gt;
&lt;li&gt;"테스트가 실패하면 에이전트가 알아서 고치게 하고 싶어요"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=""&gt;목차&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;왜 E2E 테스트가 필요할까요?  &lt;/li&gt;
&lt;li&gt;테스트 어떻게 작성할까요?  &lt;/li&gt;
&lt;li&gt;그럼 사람은 무엇을 할까요?&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;h5 id="naverengineeringdaybr"&gt;
&lt;strong&gt;◎ NAVER Engineering Day란?&lt;/strong&gt;&lt;br&gt;
&lt;/h5&gt;
  
  &lt;p&gt;NAVER에서는 사내 개발 경험과 기술 트렌드를 교류를 할 수 있는 프로그램이 많이 있습니다. 그중 이제는 매회 평균 100개 이상의 발표가 이루어지는 NAVER Engineering Day를 빼놓을 수 없는데요. &lt;br&gt;
  2016년부터 시작된 ENGINEERING DAY는 실무에서의 기술 개발 경험과 새로운 기술과 플랫폼 도입 시 유용하게 활용될 수 있는 팁 등을 공유하며 서로 배우고 성장하는 네이버의 대표적인 사내 개발자 행사입니다.(&lt;a href="https://d2.naver.com/news/0766161"&gt;관련 포스팅 보기&lt;/a&gt;) &lt;br&gt;
  올해 진행된 NAVER Engineering Day의 일부 세션을 공개합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://d2.naver.com/helloworld/6811215</id>
    <link href="https://d2.naver.com/helloworld/6811215"/>
    <title>AI 에이전트를 위한 Playwright E2E 테스트 하네스 구축하기</title>
    <updated>2026-06-15T19:51:03+09:00</updated>
    <dc:date>2026-06-15T19:51:03+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>네이버</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;네이버 사내 기술 교류 행사인 NAVER ENGINEERING DAY 2026(5월)에서 발표되었던 세션을 공개합니다.&lt;br&gt; &lt;/p&gt;

&lt;div style="position: relative; max-width: 100%; padding-bottom: 56.25%; height: 0;"&gt;

&lt;iframe width="800" height="450" src="https://tv.naver.com/embed/101088254?autoPlay=true" frameborder="0" allowfullscreen="" style="position: absolute; position: absolute; top: 0; left: 0; width: 100%; height: 100%;"&gt;&lt;/iframe&gt;  
&lt;/div&gt;  

&lt;p&gt;&lt;br&gt;&lt;/p&gt;

&lt;h4 id=""&gt;발표 내용&lt;/h4&gt;

&lt;p&gt;LLM 추론 성능을 극대화하기 위한 최신 기술들(KV Cache 인지 라우팅, Prefix Cache, 분산 멀티노드 서빙 등)을 Kubernetes 프로덕션 환경에 도입하는 과정에서 기존 인프라 스택(Istio 서비스 메시, 스케줄러, Pod 보호 정책)과 충돌하며 발생한 실전 문제들을 어떻게 진단하고 해결했는지 공유합니다.&lt;/p&gt;

&lt;h4 id=""&gt;발표 대상&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes 위에서 GPU 워크로드를 운영하는 플랫폼 엔지니어&lt;/li&gt;
&lt;li&gt;LLM 서빙 인프라를 직접 구축·운영하는 MLOps / Infra 엔지니어&lt;/li&gt;
&lt;li&gt;Istio 서비스 메시 환경에서 AI 워크로드를 다루는 DevOps 엔지니어&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=""&gt;목차&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;배경 : MLXP와 LLM Serving 최적화 기술  &lt;/li&gt;
&lt;li&gt;MLXP에서 LLM Serving 최적화를 반영한 구조  &lt;/li&gt;
&lt;li&gt;Troubleshooting  &lt;/li&gt;
&lt;li&gt;GroupDisruptionBudget&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;h5 id="naverengineeringdaybr"&gt;
&lt;strong&gt;◎ NAVER Engineering Day란?&lt;/strong&gt;&lt;br&gt;
&lt;/h5&gt;
  
  &lt;p&gt;NAVER에서는 사내 개발 경험과 기술 트렌드를 교류를 할 수 있는 프로그램이 많이 있습니다. 그중 이제는 매회 평균 100개 이상의 발표가 이루어지는 NAVER Engineering Day를 빼놓을 수 없는데요. &lt;br&gt;
  2016년부터 시작된 ENGINEERING DAY는 실무에서의 기술 개발 경험과 새로운 기술과 플랫폼 도입 시 유용하게 활용될 수 있는 팁 등을 공유하며 서로 배우고 성장하는 네이버의 대표적인 사내 개발자 행사입니다.(&lt;a href="https://d2.naver.com/news/0766161"&gt;관련 포스팅 보기&lt;/a&gt;) &lt;br&gt;
  올해 진행된 NAVER Engineering Day의 일부 세션을 공개합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://d2.naver.com/helloworld/1059238</id>
    <link href="https://d2.naver.com/helloworld/1059238"/>
    <title>MLXP : Kubernetes LLM Serving  최적화 기술 도입기</title>
    <updated>2026-06-11T20:16:31+09:00</updated>
    <dc:date>2026-06-11T20:16:31+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>네이버</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;"조직이 잘하고 있는지 어떻게 알 수 있을까?" 이 질문에서 출발해 사내 가이드 문서와 AI를 붙들고 직접 측정 도구를 완성하기까지 9일이 걸렸습니다. 그 과정을 기록으로 남깁니다.&lt;/p&gt;

&lt;h2 id=""&gt;사내 생산성 측정에 관한 고민&lt;/h2&gt;

&lt;p&gt;기술 PM으로 일하면서 조직과 프로젝트의 생산성을 어떻게 측정할지는 늘 풀리지 않는 과제였습니다. 스프린트를 원활하게 진행하는 것 같아도 막상 이를 수치로 보여달라고 하면 난감했습니다. 속도가 빨라지는지, 병목이 어디서 발생하는지, 지난 분기보다 나아지고 있는지 감각적으로는 알 수 있었지만 데이터로 명확히 설명하기는 어려웠습니다.&lt;/p&gt;

&lt;p&gt;사내에는 이미 'DevOps board'라는 시스템이 있어 배포 빈도와 리드타임을 포함한 DORA 지표를 제공하고 있습니다. 소프트웨어 딜리버리 흐름을 측정한다는 점에서 제가 찾던 도구에 가까웠습니다. 다만 저는 분석 지표와 상황에 맞추어 조금 더 세분화된 데이터를 들여다보고 싶었습니다.&lt;/p&gt;

&lt;p&gt;그래서 먼저 Jira 대시보드를 만들어 리치 필터(rich filter)로 데이터를 추출해 보았습니다. 이슈 완료 수, 스프린트 완료율, 컴포넌트별 작업량 등 여러 수치가 모였지만, 수집한 숫자만으로는 조직의 작업 속도를 한눈에 파악하기 어려웠습니다. 작업이 어디서 얼마나 걸리는지도 보이지 않았습니다. Jira는 업무를 관리하는 도구일 뿐 소프트웨어 딜리버리 흐름 전체를 측정하는 도구는 아니기 때문입니다.&lt;/p&gt;

&lt;p&gt;결국 특정 컴포넌트 기준의 분류, 팀 고유의 이슈 타입 정의, 팀 내 업무 흐름을 세밀하게 들여다볼 수 있는 맞춤형 도구가 필요했습니다. 기존 DevOps board를 대체하려는 것이 아니라, 팀의 상황에 맞추어 데이터를 직접 구성해 보고 싶었습니다.&lt;/p&gt;

&lt;p&gt;문제는 제가 이를 직접 구현할 기술적 역량이 부족하다는 점이었습니다. 개발자에게 부탁하기에는 작업 규모가 작았고, 백로그에 등록하더라도 언제 진행될지 기약할 수 없었습니다. 그래서 AI의 도움을 받아 직접 만들어 보기로 했습니다.&lt;/p&gt;

&lt;h2 id="1html"&gt;1단계: HTML 파일 하나로 가설 검증&lt;/h2&gt;

&lt;p&gt;처음에는 배포, 서버, 인증 과정을 모두 생략하고 HTML 파일 하나로 가볍게 시작했습니다. 브라우저에서 Jira 변경 기록(changelog) CSV 파일을 파싱해 바로 시각화하는 구조였습니다.&lt;/p&gt;

&lt;p&gt;AI에게 전달한 첫 프롬프트에는 현재 상황과 맥락을 최대한 자세히 담았습니다.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-text"&gt;Jira 이슈별 changelog CSV에는 'Issue Key', 'Status', 'Created' 칼럼이 있어.

각 이슈가 'In Progress'로 처음 전환된 시각과 'Done'으로 전환된 시각의 차이를 일(day) 단위로 계산하고 싶어. 팀별, 이슈 타입별로 집계해서 주차별 트렌드를 보여주는 웹 대시보드를 만들고 싶은데,

구조는 이해하지만 직접 구현은 못 해.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;이 프롬프트에는 데이터 형식, 원하는 결과물, 그리고 저의 기술적 한계가 모두 들어가 있습니다.&lt;/p&gt;

&lt;p&gt;AI는 곧바로 코드를 작성하는 대신 발생할 수 있는 예외 상황(edge case)을 먼저 짚어 주었습니다.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-text"&gt;이슈가 In Progress → Backlog → In Progress로 다시 이동했다가 Done이 되는 경우, 리드타임 기산점을 첫 번째 In Progress로 할지 마지막으로 할지 정의가 필요해요. Done 이후 재오픈 케이스는요?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;이 질문을 받기 전까지는 저 역시 이러한 예외 상황을 생각하지 못했습니다. 실제로 확인해 보니 데이터에 해당 사례가 적지 않게 포함되어 있었습니다. 결국 AI와 대화하는 과정 자체가 요구사항 정의 세션이 된 셈입니다.&lt;/p&gt;

&lt;p&gt;물론 초기에는 버그도 있었습니다. Jira CSV의 타임스탬프가 UTC 기준이라 KST로 변환해 날짜를 계산해야 했고, 내보내기 설정에 따라 이슈 타입 필드명이 달라지는 문제도 있었습니다. 이럴 때는 문제를 말로 설명하기보다 실제 CSV 헤더와 샘플 데이터 일부를 AI에게 그대로 보여주는 편이 훨씬 효과적이었습니다.&lt;/p&gt;

&lt;p&gt;이렇게 해서 대시보드 화면에 리드타임 수치가 나타났습니다. 하지만 그 숫자를 보면서 새로운 의문이 생겼습니다. &lt;strong&gt;이 수치가 좋은 편인지 나쁜 편인지는 어떻게 알 수 있을까요?&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id="2dora"&gt;2단계: DORA 지표를 통한 기준 마련&lt;/h2&gt;

&lt;p&gt;리드타임을 측정하는 것과 그 수치의 의미를 파악하는 것은 별개의 문제였습니다. 그래서 소프트웨어 딜리버리 성과를 측정하는 프레임워크인 DORA 지표를 참고했습니다. DORA 지표는 수많은 팀과 프로젝트의 데이터를 분석해 도출한 네 가지 핵심 지표로 구성됩니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;배포 빈도&lt;/li&gt;
&lt;li&gt;변경 리드타임&lt;/li&gt;
&lt;li&gt;변경 실패율&lt;/li&gt;
&lt;li&gt;서비스 복구 시간&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;여러 연구를 통해 이 네 가지 지표가 팀의 딜리버리 역량을 가장 잘 설명한다는 사실이 검증되었습니다.&lt;/p&gt;

&lt;p&gt;제가 측정한 Jira 리드타임은 이 중 '변경 리드타임'에 해당했습니다. 작업 시작부터 실제 배포까지 걸리는 시간입니다. 나머지 지표를 확인하려면 추가 데이터가 필요했습니다. 배포 빈도는 배포 이벤트 로그에서, 변경 실패율과 복구 시간은 PR(Pull Request) 및 이슈 데이터에서 얻을 수 있었습니다.&lt;/p&gt;

&lt;p&gt;결국 Jira 데이터만으로는 전체 딜리버리 흐름의 절반만 볼 수 있었습니다. 나머지 절반을 채우려면 사내 GitHub 데이터를 연동해야 했습니다.&lt;/p&gt;

&lt;h2 id="3ai"&gt;3단계: AI를 활용한 서버 구축과 가이드 문서&lt;/h2&gt;

&lt;p&gt;GitHub API를 주기적으로 호출하고 이를 Jira 데이터와 결합하려면 단순한 브라우저용 HTML 환경으로는 부족했습니다. 별도의 서버가 필요해진 것입니다.&lt;/p&gt;

&lt;p&gt;사실 이 시점에서 진행을 포기할까 고민도 했습니다. Dockerfile을 한 번도 작성해 본 적 없는 비개발자가 컨테이너 기반 배포를 직접 해낼 수 있을지 확신이 서지 않았기 때문입니다.&lt;/p&gt;

&lt;p&gt;일단 사내 공통 컨테이너 플랫폼인 'n3r'의 가이드 문서부터 찾아보았습니다. 하지만 낯선 용어가 많아 문서 첫 페이지부터 막막했습니다. 그래서 접근 방식을 바꿨습니다. 가이드 문서를 혼자 끙끙대며 읽는 대신, 그 내용을 AI에게 전달하고 함께 해석해 나가기 시작한 것입니다.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-text"&gt;이 가이드에 이렇게 나와 있는데, 파이썬 FastAPI 앱에 적용하면 Dockerfile을 어떻게 써야 해? [가이드 해당 섹션 붙여넣기]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;가이드 문서에는 사내 환경과 표준 규칙이 담겨 있습니다. AI는 그 내용을 제 상황에 맞게 구체화해 주었습니다.&lt;/strong&gt; 둘 중 어느 한쪽만으로는 해결이 어려웠지만, 가이드 문서와 AI를 교차로 활용함으로써 무사히 서버를 띄울 수 있었습니다.&lt;/p&gt;

&lt;h2 id="4"&gt;4단계: 스케줄러 설정과 데이터 누락 문제 해결&lt;/h2&gt;

&lt;p&gt;서버를 구축했다고 해서 데이터가 저절로 모이는 것은 아닙니다. Jira와 GitHub API를 주기적으로 호출해 줄 스케줄러가 필요했습니다. 다행히 사내에는 이미 Self-Hosted Runner 환경과 관련 설정 가이드 문서가 마련되어 있었습니다.&lt;/p&gt;

&lt;p&gt;돌이켜보면 9일 중 가장 많은 시간을 이 구간에서 소요했습니다. Runner 환경 변수 설정, 인증 토큰 발급, API 페이지네이션(pagination) 처리 등 예상치 못한 문제가 꼬리를 물고 나타났기 때문입니다.&lt;/p&gt;

&lt;p&gt;그중에서도 가장 애를 먹었던 부분은 API 페이지네이션이었습니다. 조회할 이슈가 1,000개를 넘어가면 API 응답이 중간에 잘리는데, 초기에 AI가 작성한 코드에는 이 예외 처리가 누락되어 있었습니다. 오류 메시지조차 없이 데이터만 조용히 누락되고 있었고, 나중에 직접 숫자를 대조하며 검증하다가 우연히 발견했습니다.&lt;/p&gt;

&lt;p&gt;이 과정을 거치며 제가 AI에게 질문하는 방식도 달라졌습니다. 초반에는 "이거 어떻게 해요?"에 가까웠다면, 나중에는 가이드 내용, 현재 설정 파일, 오류 메시지를 함께 붙여 "이 값을 내 상황에 어떻게 적용하면 돼?"라고 물었습니다. &lt;strong&gt;상황과 맥락을 자세히 전달할수록 AI의 답변은 훨씬 정확해졌습니다.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id="5"&gt;5단계: 사내 스토리지 연동과 사람의 역할&lt;/h2&gt;

&lt;p&gt;수집한 데이터를 저장하고 필요할 때 화면에 제공하려면 스토리지가 필요했습니다. 사내에서 제공하는 Redis 기반 스토리지인 nBase-ARC를 활용하기로 하고 관련 가이드 문서를 참고했습니다.&lt;/p&gt;

&lt;p&gt;AI는 보편적인 Redis 사용법은 훌륭하게 알려 주었습니다. 하지만 사내의 특수한 네트워크 정책, 고유한 TTL 설정 방식, 접근 권한 신청 프로세스 같은 내부 정보는 알지 못했습니다. 이런 부분에서는 사내 가이드 문서와 사내 AI 기반 문의 채널 ASK가 도움이 되었습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;널리 공개된 기술 스택을 다룰 때 AI는 탁월한 조력자입니다. 하지만 사내 특화 환경, 내부 정책, 조직 고유의 관행은 AI가 파악할 수 없는 영역입니다. 이 영역은 결국 사람이, 문서가, 동료가 채워야 합니다.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=""&gt;완성된 대시보드의 효과&lt;/h2&gt;

&lt;p&gt;이제 Jira와 GitHub 데이터는 매일 자동으로 수집됩니다. 대시보드에 접속하면 조직과 프로젝트의 전반적인 딜리버리 흐름을 한눈에 확인하고 다음과 같은 것들을 쉽게 파악할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;리드타임이 유독 길어지는 구간&lt;/li&gt;
&lt;li&gt;특정 이슈 타입에서 반복되는 병목 현상&lt;/li&gt;
&lt;li&gt;스프린트 후반부에 배포 이벤트가 몰리는 패턴&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;'요즘 왠지 개발 속도가 느려진 것 같다'는 막연한 느낌을 이제는 데이터를 근거로 설명할 수 있게 되었습니다.&lt;/p&gt;

&lt;p&gt;물론 이 대시보드가 완벽한 측정 도구는 아닙니다. DORA 지표를 온전히 구현한 것도 아닙니다. 하지만 측정 도구가 아예 없었을 때와 비교하면 확실한 차이가 있습니다. &lt;strong&gt;가장 큰 변화는 조직 회고 시간의 논의 수준이 달라졌다는 점입니다. 막연한 감이 아니라 실제 데이터를 보면서 이야기하게 되었습니다.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=""&gt;프로젝트를 진행하며 배운 점&lt;/h2&gt;

&lt;h3 id="ai"&gt;기획의 재발견: AI는 마법사가 아니라 정밀한 조각가다&lt;/h3&gt;

&lt;p&gt;AI는 사용자가 원하는 바를 구현하는 데 탁월한 능력을 보여줍니다. 하지만 그 전제는 사용자 스스로 '무엇을 원하는지'를 명확히 알고 있어야 한다는 것입니다.&lt;/p&gt;

&lt;p&gt;작업을 하면서 특히 효과적이라고 느낀 소통 방식은 다음 세 가지였습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;실제 데이터를 예시로 보여주기&lt;/li&gt;
&lt;li&gt;발생 가능한 예외 상황을 미리 정의하기&lt;/li&gt;
&lt;li&gt;기대한 결과와 실제 결과의 차이를 명확히 짚어 주기&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 세 가지 요건이 충족될 때 AI는 가장 정확한 결과물을 내놓았습니다. 결국 &lt;strong&gt;기획이란 필요한 기능을 나열하는 작업이 아니라, AI가 올바르게 이해하고 작업할 수 있도록 꼼꼼한 설계도를 그리는 과정이었습니다. 얼마나 명확하고 구체적으로 지시하느냐가 최종 결과물의 품질을 결정&lt;/strong&gt;했습니다.&lt;/p&gt;

&lt;h3 id="ai"&gt;인프라의 벽: 가이드와 AI, 둘 다 필요했다&lt;/h3&gt;

&lt;p&gt;서버를 구축하는 과정에서는 사내 가이드 문서와 AI를 함께 활용해야 했습니다. 가이드 문서는 사내 환경을 정확히 설명해 주었지만 제 프로젝트 상황에 딱 맞는 답을 주지는 못했습니다. 반대로 AI는 기술적 원리를 잘 설명해 주었지만 사내 환경의 특수성은 알지 못했습니다.&lt;/p&gt;

&lt;p&gt;따라서 이 둘을 교차해서 쓰는 것이 가장 효율적이었습니다. 가이드 문서의 내용을 AI에게 알려 주고 그 의미를 함께 해석하는 방식입니다. 가이드 문서가 '무엇을' 해야 하는지 알려주면, AI가 '어떻게' 해야 하는지 구체화했습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;새로운 아이디어의 실현은 도구의 발전에서 비롯되지만, 그것이 지속 가능하게 유지하는 힘은 안정적인 인프라에서 나옵니다. 그리고 비개발자조차 그 인프라에 접근해 활용할 수 있도록 길을 열어 주는 것은 결국 잘 작성된 가이드 문서입니다.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id="ai"&gt;토큰의 무게: AI는 공짜가 아니다&lt;/h3&gt;

&lt;p&gt;AI를 활용하면서 토큰(비용)이 유독 많이 소모되는 구간이 있었습니다. 대체로 다음과 같은 상황이었습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI가 매번 코드 전체를 새로 읽게 했던 초반&lt;/li&gt;
&lt;li&gt;대화 맥락을 정리하지 않고 질문을 무분별하게 이어 갔던 중반&lt;/li&gt;
&lt;li&gt;분석 탭에서 AI API를 3번 순차 호출하던 구조&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;해법은 '역할 분리'였습니다. 데이터 파싱이나 집계 같은 단순 계산은 JavaScript 코드가 직접 처리하도록 하고, AI에게는 최종적으로 요약된 수치만 전달해 의미 해석을 맡기는 구조로 바꿨습니다. 그러자 토큰 사용량이 눈에 띄게 줄었고 응답 속도도 훨씬 빨라졌습니다.&lt;/p&gt;

&lt;p&gt;어떤 기능을 구현하기 전에는 "&lt;strong&gt;이 작업을 반드시 AI가 처리해야 하는가?&lt;/strong&gt;"를 먼저 자문해 볼 필요가 있습니다. 명확한 규칙으로 처리할 수 있는 작업은 코드로 해결하고, AI는 문맥 판단이나 해석이 필요한 영역에만 제한적으로 활용하는 편이 효율적입니다.&lt;/p&gt;

&lt;h3 id="ai"&gt;AI의 한계: 오류가 없다고 올바른 것은 아니다&lt;/h3&gt;

&lt;p&gt;가장 많은 시간을 낭비하게 만든 것은 역설적이게도 AI가 확신에 차서 작성해 준 코드였습니다. 앞서 언급한 API 페이지네이션 코드는 겉보기에는 아무런 오류 없이 매끄럽게 동작했습니다. 하지만 이슈가 1,000개를 넘어가는 순간부터 데이터가 시스템 내부에서 조용히 누락되고 있었습니다. 출력된 수치를 꼼꼼히 검증해 보지 않았다면 끝까지 몰랐을 문제였습니다.&lt;/p&gt;

&lt;p&gt;따라서 &lt;strong&gt;AI가 만들어 준 코드는 오류 없이 실행되는지 확인하는 선에서 그쳐서는 안 됩니다. 도출된 결과가 실제로 정확한지 정합성을 검증하는 단계가 반드시 필요합니다.&lt;/strong&gt; 샘플 데이터로 직접 계산한 값과 AI의 결과물을 대조해 보는 과정은 번거롭지만 생략할 수 없습니다.&lt;/p&gt;

&lt;h3 id=""&gt;생태계의 제언: '데이터 민주주의'를 위한 조건&lt;/h3&gt;

&lt;p&gt;비개발자인 제가 이 프로젝트를 무사히 마칠 수 있었던 것은 AI의 능력 덕분만은 아니었습니다. 든든한 사내 가이드 문서가 뒷받침되었기에 가능한 일이었습니다. 가이드 문서가 없었다면 아무리 훌륭한 AI라도 사내 환경에 맞는 결과물을 만들어내기 어려웠을 것입니다.&lt;/p&gt;

&lt;p&gt;회사에는 방대한 데이터와 훌륭한 인프라가 있습니다. 하지만 권한은 열려 있어도 이를 실제로 활용할 수 있는 사람은 극소수인, 이른바 '접근은 가능하지만 접근할 수 있는 사람은 없는' 상태에 머무는 경우가 많습니다.&lt;/p&gt;

&lt;p&gt;API 사용 가이드를 조금 더 체계적으로 다듬고, 자주 쓰이는 템플릿 코드를 사내에 공유하고, 보안 가이드라인을 명확히 제시해 주는 것만으로도 수많은 사내 맞춤형 도구가 새롭게 만들어질 수 있습니다. &lt;strong&gt;비개발자가 AI와 협업해 가치 있는 무언가를 만들어 내는 진정한 전제 조건은 결국 '친절하고 정확한 가이드 문서'입니다. AI는 사용자가 그 가이드를 조금 더 쉽게 소화하고 자기 상황에 적용할 수 있도록 돕는 훌륭한 조력자일 뿐입니다.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=""&gt;마치며&lt;/h2&gt;

&lt;p&gt;불과 9일 전의 저는 스스로 서버를 구축할 수 있을 거라고는 생각도 못 했습니다. 그런데 결국 Dockerfile을 작성하고, 컨테이너를 빌드해 배포하고, API를 주기적으로 호출하는 스케줄러를 구성했으며, Redis에 데이터를 읽고 쓰는 경험까지 했습니다. 코드는 대부분 AI가 작성해 주었지만, '무엇을 만들 것인지', '어떤 구조로 설계할 것인지', '최종 결과물이 올바른지'를 판단하는 몫은 온전히 제게 있었습니다.&lt;/p&gt;

&lt;p&gt;대시보드의 숫자를 보며 종종 생각합니다. '우리 조직과 프로젝트는 잘 나아가고 있나?' 예전에는 막연했던 그 질문에, 이제는 데이터를 근거로 조금은 명확한 답을 할 수 있게 되었습니다.&lt;/p&gt;

&lt;p&gt;동료에게서 "이거 어떻게 만드셨어요?"라는 질문을 받을 때마다 저는 이렇게 답하곤 합니다.&lt;/p&gt;

&lt;p&gt;"AI한테 말로 시켰어요. 그런데 뭘 시킬지는 제가 알아야 했어요."&lt;/p&gt;

&lt;p&gt;이 글을 통해 전하고 싶은 메시지는 단 하나입니다. &lt;strong&gt;AI를 잘 활용하는 조직은 성능 좋은 AI 도구를 선별하는 데 그치지 않고, AI가 역량을 제대로 발휘할 수 있는 밑바탕 환경을 먼저 탄탄하게 갖춘 조직입니다.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;데이터를 같은 기준으로 관리하려는 조직적 합의&lt;/li&gt;
&lt;li&gt;누구나 안전하게 접근하여 실험할 수 있는 열린 인프라&lt;/li&gt;
&lt;li&gt;비개발자도 천천히 따라갈 수 있도록 작성된 가이드 문서&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 세 가지가 바로 AI 시대에 필요한 인프라입니다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://d2.naver.com/helloworld/2017402</id>
    <link href="https://d2.naver.com/helloworld/2017402"/>
    <title>비개발자의 AI 협업 도전기 — 생산성 측정하려다 서버까지 띄운 9일</title>
    <updated>2026-06-13T01:08:37+09:00</updated>
    <dc:date>2026-06-13T01:08:37+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>miles@infograb.net (Miles)</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;LLM에 정확한 정보와 도구를 제대로 쥐여 주면 더 높은 품질의 n8n 워크플로를 생성할 수 있습니다. 이 글은 LLM의 작업 환경 전체를 설계하는 접근 방식인 '하네스(Harness)'를 만들어 실험한 내용을 다뤘습니다. 같은 모델과 같은 요청을 두고 하네스 수준만 바꿨을 때 모델이 생성한 n8n 워크플로 품질이 어떻게 달라지는지 소개합니다.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://insight.infograb.net/blog/2026/06/17/n8n-harness/</id>
    <link href="https://insight.infograb.net/blog/2026/06/17/n8n-harness/"/>
    <summary type="html">LLM에 정확한 정보와 도구를 제대로 쥐여 주면 더 높은 품질의 n8n 워크플로를 생성할 수 있습니다. 이 글은 LLM의 작업 환경 전체를 설계하는 접근 방식인 '하네스(Harness)'를 만들어 실험한 내용을 다뤘습니다. 같은 모델과 같은 요청을 두고 하네스 수준만 바꿨을 때 모델이 생성한 n8n 워크플로 품질이 어떻게 달라지는지 소개합니다.</summary>
    <title>LLM·하네스로 더 좋은 n8n 워크플로 생성하기</title>
    <updated>2026-06-17T09:00:00+09:00</updated>
    <dc:date>2026-06-17T09:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>여기어때 Brand Design Team</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;h4&gt;여기어때 트립홀릭 그래픽 언어 리뉴얼 프로젝트&lt;/h4&gt;
&lt;p&gt;여기어때에는 우수한 후기를 남겨주시는 상위 0.1% 여행자들의 커뮤니티가 있다는 사실, 알고 계셨나요? 바로 &lt;strong&gt;&amp;lt;트립홀릭&amp;gt;&lt;/strong&gt; 입니다.🚩&lt;/p&gt;
&lt;p&gt;&amp;lt;트립홀릭&amp;gt;이 어떤 브랜드인지 궁금하시다면 지난 글 🔗&lt;a href="https://techblog.gccompany.co.kr/%EB%A6%AC%EB%B7%B0%EB%A5%BC-%EC%93%B0%EB%A9%B4-%ED%95%9C%EC%A0%95%ED%8C%90-%EA%B5%BF%EC%A6%88%EB%A5%BC-%EC%A4%80%EB%8B%A4%EA%B3%A0-6eb83f574a96"&gt;&lt;strong&gt;리뷰를 쓰면 한정판 굿즈를 준다고?&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;에서 자세히 확인하실 수 있습니다.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*phMBVxx5eXPrFOYOaL0_eQ@2x.png"&gt;&lt;/figure&gt;&lt;p&gt;이번 글에서는 트립홀릭의 새로운 얼굴이 된 그래픽 에셋을 소개하고, AI 시대에 일관된 비주얼 브랜딩을 유지하기 위해 고민했던 과정을 공유해보려 합니다. ☺️&lt;/p&gt;
&lt;p&gt;브랜드가 성장할수록 그래픽은 다양한 채널과 작업자들을 통해 확장되며 그 과정에서 단순히 새로운 그래픽을 만드는 것을 넘어, 트립홀릭만의 그래픽 언어를 정의하고 이를 누구나 활용할 수 있는 그래픽 생성 시스템으로 발전시키고자 했습니다.&lt;/p&gt;
&lt;p&gt;이 글은 그래픽 에셋 제작기보다는, 브랜드 그래픽을 어떻게 관리하고 확장할 것인가에 대한 고민의 기록에 더 가까울지도 모르겠습니다.&lt;/p&gt;
&lt;p&gt;그 과정에서 얻은 경험과 나름의 해결 방안을 함께 소개해보겠습니다. 💁🏻‍♂️&lt;/p&gt;
&lt;h4&gt;왜 그래픽이 필요했을까?&lt;/h4&gt;
&lt;p&gt;트립홀릭은 지난 4년간 다양한 프로젝트와 이벤트를 통해 성장해왔습니다.👏&lt;/p&gt;
&lt;p&gt;그 과정에서 웰컴파티, 굿즈, SNS 콘텐츠, 이벤트 등 각 접점의 목적에 맞는 다양한 그래픽이 만들어졌고, 이는 트립홀릭의 활동과 경험을 더욱 풍성하게 만들어 주었습니다. 🎉&lt;/p&gt;
&lt;p&gt;하지만 브랜드가 성장하고 활동 영역이 넓어질수록 새로운 고민이 생겼습니다.&lt;/p&gt;
&lt;p&gt;각 프로젝트마다 완성도 높은 그래픽이 사용되고 있었지만, 트립홀릭을 하나의 브랜드로 연결해 주는 공통된 비주얼은 부족했습니다.&lt;/p&gt;
&lt;p&gt;그래서 자연스럽게 이런 질문에 도달하게 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“트립홀릭을 어떻게 표현해야 하나의 브랜드로 보여줄 수 있을까?” &lt;/strong&gt;🤔&lt;/p&gt;
&lt;h4&gt;말풍선에서 시작된 그래픽&lt;/h4&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PLzoUpdc2r1YU9f3FpADKQ.jpeg"&gt;&lt;figcaption&gt;그래픽 모티프&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;BXD1팀은 트립홀릭의 일관된 비주얼 브랜딩을 위해 가장 먼저 브랜드의 본질을 다시 살펴봤습니다.&lt;/p&gt;
&lt;p&gt;트립홀릭은 단순히 여행지를 소개하는 서비스가 아닙니다.&lt;/p&gt;
&lt;p&gt;여행 경험을 공유하고, 좋은 여행 정보를 나누며, 사람들과 소통하는 커뮤니티입니다. 🧳 🤝&lt;/p&gt;
&lt;p&gt;우리는 이 과정에서 반복적으로 등장하는 세 가지 키워드를 발견했습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;리뷰, 소통, 커뮤니티&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그리고 이 세 가지를 가장 직관적으로 표현할 수 있는 형태로 말풍선을 선택했습니다. 💬&lt;/p&gt;
&lt;p&gt;말풍선은 여행 경험을 공유하는 행동을 상징하는 동시에, 사람과 사람을 연결하는 트립홀릭의 정체성을 담고 있었습니다.&lt;/p&gt;
&lt;p&gt;이후 우리는 말풍선을 하나의 그래픽 모티프로 확장해 트립홀릭만의 그래픽 언어를 만들어 나가기 시작했습니다. 🛠️&lt;/p&gt;
&lt;h4&gt;하나의 브랜드 하나의 그래픽언어&lt;/h4&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*khw4TPBB1MKYFhoriICt4A.png"&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sI3GG0ZBPMYCR8M6mWEClg.jpeg"&gt;&lt;figcaption&gt;트립홀릭 그래픽 에셋 중 일부&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;트립홀릭은 다양한 외부 협력사와 함께 운영되는 브랜드로, SNS 콘텐츠부터 이벤트 제작물까지 다양한 작업이 동시에 진행됩니다.&lt;/p&gt;
&lt;p&gt;그래픽 에셋이 있더라도 프로젝트에 맞춰 새로운 그래픽은 계속 필요하게 됩니다.&lt;/p&gt;
&lt;p&gt;자연스럽게 이런 고민이 생겼습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“새롭게 만들어지는 작업물들도 트립홀릭처럼 보일 수 있을까?”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;또한 기존 방식에서는 새로운 그래픽이 필요할 때마다&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;그래픽 요청 → 디자인 → 커뮤니케이션 → 검수 → 배포&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;과정을 반복했으며 기존 에셋을 활용해 작업하더라도 지속적인 확인과 피드백이 필요했습니다. 😅&lt;/p&gt;
&lt;p&gt;디자인 파일 형태의 에셋이 많아질수록 관리와 공유의 범위가 넓어지고, 작업자마다 그래픽을 해석하는 방식 역시 달라질 수 있기 때문에 결국 브랜드의 일관성을 유지하기 위해 많은 커뮤니케이션과 제작 리소스가 발생하고 있었습니다. 🫠&lt;/p&gt;
&lt;p&gt;그래서 우리는 브랜드 일관성과 작업 효율성을 동시에 해결할 수 있는 방법을 찾기 시작했습니다.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FIfbEwdR7netfgpmkBSD7w.png"&gt;&lt;/figure&gt;&lt;p&gt;그래픽 에셋을 처음부터 구축하는 과정이었기에 오히려 새로운 접근이 가능했습니다.&lt;/p&gt;
&lt;p&gt;마침 생성형 AI가 빠르게 발전하면서, 많은 사람들이 동일한 프롬프트를 활용해 특정 스타일의 이미지를 생성하는 사례들이 등장하고 있었습니다. 🤖&lt;/p&gt;
&lt;p&gt;이를 보며 하나의 아이디어가 떠올랐습니다. 기존처럼 그래픽 에셋과 디자인 가이드를 공유하는 것이 아니라,&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“누구나 트립홀릭 그래픽을 생성할 수 있는 규칙 자체를 공유하면 어떨까?”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;그래픽 결과물을 전달하는 대신, 그래픽을 만들어내는 언어를 전달하는 것입니다. 그렇게 우리는 트립홀릭 그래픽 에셋을 프롬프트로 정의하고,&lt;/p&gt;
&lt;p&gt;이를 기반으로 누구나 동일한 그래픽 언어를 사용할 수 있는&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;트립홀릭 그래픽 생성 시스템&amp;gt; &lt;/strong&gt;구축을 시작했습니다. 👩‍💻&lt;/p&gt;
&lt;h4&gt;AI 시대의 그래픽 에셋&lt;/h4&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*82GAKP1Nr_K52tiDhxXLPA.png"&gt;&lt;/figure&gt;&lt;p&gt;먼저 기존에 제작되어 있던 트립홀릭 그래픽들을 ChatGPT와 Gemini에 학습시키며, 그래픽이 공통적으로 가지고 있는 특징들을 분석했습니다. 🧐&lt;/p&gt;
&lt;p&gt;분석 과정에서 그래픽의 특성을 크게&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;형태(Shape), 스타일(Style), 표현 방식(Rendering)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;세 가지 요소로 구분했습니다.&lt;/p&gt;
&lt;p&gt;이후 각 요소를 프롬프트 언어로 변환하고, 반복적인 생성 테스트를 통해 하나의 구조화된 프롬프트로 정리해 나갔습니다.&lt;/p&gt;
&lt;p&gt;생성 결과를 검증하며 형태가 달라지는 경우, 불필요한 디테일이 추가되는 경우 등 다양한 예외 상황을 보완했고, 그 결과 최종적으로는 트립홀릭 그래픽의 특징과 톤앤매너를 안정적으로 재현할 수 있는 생성 규칙을 구축할 수 있었습니다.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/500/1*Pflx_FU7L1zJ5Xb7nSOxDA.gif"&gt;&lt;figcaption&gt;Chat GPT를 활용한 실제 생성 사례&lt;/figcaption&gt;&lt;/figure&gt;&lt;h4&gt;에셋을 넘어 비주얼 시스템으로&lt;/h4&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zyQwCXusGegX6atALEFLzA.png"&gt;&lt;figcaption&gt;트립홀릭 비주얼 시스템 가이드 중 일부&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;그래픽 생성 시스템을 구축한 이후에는 이를 실제 브랜드 운영에 적용하기 위한 비주얼 가이드 정리가 이어졌습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BXD1팀의 라이카&lt;/strong&gt;와 함께 로고, 컬러, 폰트, 그래픽 에셋은 물론 그래픽 생성 시스템까지 하나의 체계로 정리하며 트립홀릭 비주얼 가이드를 구축했습니다. 🤝&lt;/p&gt;
&lt;p&gt;이를 통해 트립홀릭은 단순한 그래픽 에셋 모음을 넘어, 누구나 동일한 브랜드 경험을 만들 수 있는 비주얼 시스템을 갖추게 되었습니다. 🎨 ⚙️&lt;/p&gt;
&lt;h4&gt;에셋을 넘어 비주얼 시스템으로&lt;/h4&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Tbu7HAvpNtqz5ARA8DyLRQ.png"&gt;&lt;/figure&gt;&lt;p&gt;이번 프로젝트는 단순히 그래픽 에셋을 제작하고 비주얼 가이드를 만드는 것을 넘어, 트립홀릭을 표현하는 일관된 시각 언어를 구축하고 이를 누구나 활용할 수 있도록 시스템화하는 과정이었습니다. 🧑‍🔧&lt;/p&gt;
&lt;p&gt;과거에는 그래픽 파일과 에셋을 공유했다면, 이제는 AI를 활용해 동일한 그래픽을 만들어낼 수 있는 규칙과 언어를 공유하는 시대가 되었습니다.&lt;/p&gt;
&lt;p&gt;트립홀릭 그래픽 리뉴얼 역시 이러한 변화에 맞춰 브랜드 에셋을 관리하고 확장하는 새로운 방식을 실험한 프로젝트였습니다.&lt;/p&gt;
&lt;p&gt;물론 아직 완성된 답을 찾았다고 생각하지는 않습니다. 브랜드가 성장하고 새로운 경험이 만들어질수록 그래픽 시스템 역시 함께 발전해야 하기 때문입니다. 🏃‍➡️&lt;/p&gt;
&lt;p&gt;무엇보다 시스템은 가이드북 안에서 완성되지 않습니다. 실제 브랜드 경험 속에서 사용되고 확장될 때 비로소 의미를 갖게 됩니다.&lt;/p&gt;
&lt;p&gt;트립홀릭 그래픽 시스템 또한 그래픽 에셋과 프롬프트를 정리하는 것에서 끝나지 않고, 다양한 접점에서 하나의 브랜드 경험으로 연결되는 것을 목표로 하고 있습니다. 🧗‍♂️&lt;/p&gt;
&lt;p&gt;다음 글에서는 이번에 구축한 트립홀릭 그래픽 시스템이 6기 웰컴파티에 어떻게 적용되었는지, 하나의 그래픽 언어가 공간, 콘텐츠, 굿즈 전반으로 확장되며 실제 브랜드 경험으로 구현된 과정을 소개해 드리겠습니다.&lt;/p&gt;
&lt;p&gt;여행의 경험을 공유하는 트립홀릭처럼, 이번 프로젝트를 통해 얻은 경험 역시 여러분과 함께 나누며 글을 마치겠습니다. 🫰✈️&lt;/p&gt;
&lt;p&gt;Written by Bigo&lt;/p&gt;
&lt;img src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=2d993720b3ce" width="1" height="1" alt=""&gt;&lt;hr&gt;
&lt;p&gt;&lt;a href="https://techblog.gccompany.co.kr/ai-%EC%8B%9C%EB%8C%80%EC%9D%98-%EB%B8%8C%EB%9E%9C%EB%93%9C-%EA%B7%B8%EB%9E%98%ED%94%BD-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95%EA%B8%B0-2d993720b3ce"&gt;AI 시대의 브랜드 그래픽 시스템 구축기&lt;/a&gt; was originally published in &lt;a href="https://techblog.gccompany.co.kr"&gt;여기어때 기술블로그&lt;/a&gt; on Medium, where people are continuing the conversation by highlighting and responding to this story.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://techblog.gccompany.co.kr/ai-%EC%8B%9C%EB%8C%80%EC%9D%98-%EB%B8%8C%EB%9E%9C%EB%93%9C-%EA%B7%B8%EB%9E%98%ED%94%BD-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95%EA%B8%B0-2d993720b3ce?source=rss----18356045d353---4</id>
    <link href="https://techblog.gccompany.co.kr/ai-%EC%8B%9C%EB%8C%80%EC%9D%98-%EB%B8%8C%EB%9E%9C%EB%93%9C-%EA%B7%B8%EB%9E%98%ED%94%BD-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95%EA%B8%B0-2d993720b3ce?source=rss----18356045d353---4"/>
    <title>AI 시대의 브랜드 그래픽 시스템 구축기</title>
    <updated>2026-06-19T14:56:11+09:00</updated>
    <dc:date>2026-06-19T14:56:11+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>주디Judy(송민경) / 인사팀</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;h4&gt;여기어때 컬처 라운지 ep. 19&lt;/h4&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-1EajsXaN4_kjErx3013Yg.png"&gt;&lt;/figure&gt;&lt;p&gt;안녕하세요! 여기어때의 조직문화와 사람 이야기를 전하는 &amp;lt;컬처 라운지&amp;gt;입니다. 😊&lt;/p&gt;
&lt;p&gt;지난 3편에 걸쳐 서류 지원부터 대망의 입사 첫날 ‘웰컴 세션’까지의 여정을 함께 살펴보았는데요. 혹시 글을 읽으시면서 이런 걱정이 들진 않으셨나요?&lt;/p&gt;
&lt;blockquote&gt;&lt;em&gt;‘첫날 오후 3시, 온보딩 교육이 모두 끝나고 나면… 이제 진짜 나 혼자 남겨지는 걸까?’&lt;/em&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;em&gt;‘팀원들 모두 바빠보이는데, 이런 질문 자꾸 해도 되는걸까?’&lt;/em&gt;&lt;/blockquote&gt;
&lt;p&gt;새로운 환경에 홀로 던져진 것 같은 막막함과 두근거림, 누구나 한 번쯤 느껴보셨을 텐데요. 여기어때에서는 그런 걱정을 하실 필요가 전혀 없답니다. 문을 열고 나서는 순간, 여러분의 손을 따뜻하게 잡아줄 ‘짝꿍’이 기다리고 있으니까요!&lt;/p&gt;
&lt;p&gt;오늘은 신규 입사자들이 입을 모아 “가장 만족스러웠던 온보딩 프로그램”으로 꼽는 여기어때만의 특별한 문화, &lt;strong&gt;🧩&lt;/strong&gt;‘짝꿍 제도’를 소개해 드릴게요.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;🤝 ‘짝꿍’이라는 든든한 존재&lt;/strong&gt;&lt;/h3&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P7wJAG5gOxtuEaCGXoyvtw.jpeg"&gt;&lt;/figure&gt;&lt;p&gt;많은 IT 기업에서 신규 입사자의 적응을 돕는 ‘버디(Buddy)’나 ‘사수’ 제도를 운영하고 있어요. 여기어때는 정겨운 ‘짝꿍’이라는 단어를 사용하고 있는데요! 단순히 업무만 가르쳐주는 관계를 넘어, 새로운 환경에 첫발을 디딘 동료에게 단짝 친구처럼 친근하고 편안한 조력자가 되기를 바라는 마음이 담겨있답니다.&lt;/p&gt;
&lt;p&gt;실제로 신규 입사자분들께 “여기어때에 적응하며 가장 좋았던 점이 무엇인가요?”라고 여쭤보면, 단연 이 ‘짝꿍 제도’를 꼽는 분들이 많아요.&lt;/p&gt;
&lt;blockquote&gt;&lt;em&gt;“새로 입사하면 이것저것 물어볼 게 정말 많잖아요. 그런데 다들 바빠 보일 때면 선뜻 말을 걸기가 망설여지곤 하거든요. 그때 ‘짝꿍’이라는 지정된 소통 창구가 있으니 미안해할 필요 없이 언제든 편하게 질문할 수 있어서 정말 든든했어요. 짝꿍분도 강한 책임감을 가지고 친절하게 알려주셔서 회사 생활에 빠르게 적응할 수 있었어요.”&lt;/em&gt;&lt;/blockquote&gt;
&lt;p&gt;이처럼 짝꿍은 신규 구성원이 여기어때라는 새로운 여행지에 무사히 도착해 안전하고 부드럽게 체크인(Soft Landing)할 수 있도록, 입사 후 90일 동안 가장 가까이서 길잡이가 되어주고 있어요. 👼&lt;/p&gt;
&lt;h3&gt;📋 꼼꼼한 ‘짝꿍 가이드북’&lt;/h3&gt;
&lt;p&gt;여기어때의 짝꿍 제도는 단순히 “새로 오신 분 잘 챙겨주세요~”라는 말 한마디로 끝나지 않아요. 신규 구성원이 방치되거나 헤매지 않도록 꼼꼼하게 설계되어 있답니다.&lt;/p&gt;
&lt;p&gt;인사팀에서는 짝꿍이 된 선배 젊은이에게 90일 동안 시기별로 해야 할 미션들이 담긴 [짝꿍 가이드]북을 전달하는데요. 짝꿍은 가이드의 타임라인을 따라 크게 &lt;strong&gt;5가지 핵심 역할&lt;/strong&gt;을 수행하며 새로운 동료의 안착을 돕습니다.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DRCuipR2Slr4tiIntMXjLA.png"&gt;&lt;/figure&gt;&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;❤ ️팀에 대한 이해 돕기:&lt;/strong&gt; 입사 첫날, 교육장 앞으로 직접 마중을 나가 팀원들과의 첫인사를 주선하고 첫 점심 식사를 함께해요. 이후 팀의 고유한 문화와 일하는 방식을 자연스럽게 익힐 수 있도록 도와줘요.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;️❤ 전사 공통 시스템 &amp;amp; 협업 툴 사용 돕기:&lt;/strong&gt; 매일 사용하는 메신저와 업무 협업 툴 세팅, 필수 권한 신청 등 보안 가이드까지 꼼꼼하게 챙겨주어 초반의 막막함을 덜어줘요.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;❤ 업무 적응 돕기:&lt;/strong&gt; 직무 관련 히스토리와 참고 자료들을 적극적으로 공유하고, 실제 업무 피드백을 주며 담당 업무에 연착륙할 수 있도록 실무적으로 지원해요.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;❤ 회사 내 소셜 네트워킹 돕기: &lt;/strong&gt;타 팀 동료들과의 캐주얼한 소통을 도와 회사 내 인맥을 넓혀주고 네트워킹을 도와요.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;❤ 심리적 안정감 :&lt;/strong&gt; 정기적인 티타임 시간을 가지며 새로운 조직에 적응하며 겪는 정서적 부담을 낮춰줘요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;입사 첫날 픽업부터 팀원들과 다 같이 참여하는 ‘소통 맥주’ 까지, 가이드에 적힌 미션들을 타임라인에 맞춰 하나씩 지워가다 보면 신규 구성원도 자연스럽게 조직에 녹아들게 된답니다.&lt;/p&gt;
&lt;h3&gt;💡 실제 짝꿍들은 어떤 도움을 주고 있을까요?&lt;/h3&gt;
&lt;p&gt;여기어때는 프로덕트, 개발, 리서치, 촬영, 마케팅 다양한 직무가 모여서 서비스를 만드는 만큼, 짝꿍들의 케어 방식도 직무마다 조금씩 달라요.&lt;/p&gt;
&lt;p&gt;실제로 90일 동안 짝꿍들은 구체적으로 어떤 순간에 함께하며 새로운 구성원의 안착을 돕고 있을까요?&lt;/p&gt;
&lt;p&gt;짝꿍이 제출한 미션 카드의 내용을 슬쩍 보여드릴게요! 🔎&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F6KUOJ1S97DyJMsZfbimkg.png"&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;💻 개발 직군 #아키텍처_설계공유 #과거히스토리_브리핑&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;대규모 프로젝트 구조를 빠르게 파악할 수 있도록 주요 프레임워크들의 역할과 모듈화 구조, 아키텍처 설계 의도를 일대일로 세심하게 공유했어요. 또한, 눈앞의 소스 코드만 봐서는 알기 어려운 과거의 변경 히스토리와 API 리프레시 정책, 앱 전반의 날짜 변경 동기화 정책까지 상세히 브리핑하며 첫 피쳐 개발을 성공적으로 도왔습니다.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;🤝 영업 직군 #제휴점_동반미팅 #정산데이터_피벗테이블&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;주요 제휴점과 만나는 미팅 자리에 동반하여 세일즈 담당자분들을 소개해드리고, 수수료 인상도 함께 협의하며 소통 물꼬를 터드렸어요. 또한, 까다로운 양도양수 계약 과정과 실적 데이터를 쉽게 추출하는 엑셀 피벗 테이블 노하우도 전수해드렸습니다!&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;📊 리서치 직군 #전사유관팀_런치챗 #리서치실사_밀착참여&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;리서치 직군 특성상 유관 팀과의 협업/소통이 많으므로, 신규 구성원이 어색해하지 않도록 프로덕트센터 내 모든 팀과 릴레이 점심 티타임을 주선했어요. 또한, 복잡한 리서치 단계를 쉽게 이해할 수 있도록 말로만 설명하지 않고 실제 리서치 과정 중에 보조 역할로 밀착 참여해 든든하게 서포트했습니다.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;📸 콘텐츠 직군 #드론_시뮬레이터 #포트폴리오_공유&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;인테리어 촬영이 처음이라 구도에 어려움을 겪는 신규 구성원에게 유명 건축 사진가들의 작례와 전문 잡지를 공유하며 구도 감각을 다질 수 있게 도왔어요. 더불어, 드론 시뮬레이터를 이용해 언제든지 드론 조작을 연습할 수 있는 환경을 지원해드렸습니다!&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;이처럼 각 직무의 언어와 환경에 맞춰 깊이 고민해 주는 짝꿍이 있기에, 신규 구성원들은 실무의 막막함을 빠르게 지워낼 수 있습니다. 이 친절한 가이드북 미션 중에서도 유독 ‘더 가벼운 마음’으로 대화를 건넬 수 있는 장치가 있습니다.&lt;/p&gt;
&lt;h3&gt;☕ 어색함이 사르르, ‘짝꿍 티타임 쿠폰’&lt;/h3&gt;
&lt;p&gt;바로 짝꿍과 쓸 수 있는 티타임 쿠폰인데요!&lt;/p&gt;
&lt;p&gt;지하 1층 사내 라운지 카페에서 사용할 수 있는 이 쿠폰은 짝꿍에게 자연스럽게 다가가 티타임을 요청할 수 있는 아주 유용한 ‘명분’이 되어줍니다.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QSNT37QqdCexFWl2EPj-eg.jpeg"&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pW1NuQ0hoiLrDmuetQdETg.jpeg"&gt;&lt;/figure&gt;&lt;ul&gt;&lt;li&gt;
&lt;strong&gt;D+30 / D+60 / D+90 루틴:&lt;/strong&gt; 한 달에 한 번씩, 총 3개월 동안 짝꿍과 함께 카페로 내려가 편안하게 커피 브레이크를 가질 수 있는 무료 음료 쿠폰입니다. (쿠폰 1장당 음료 2잔 이용 가능!)&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;평소 바빠 보이는 팀원들에게 차마 물어보기 힘들었던 소소한 질문들이나, 적응하면서 겪었던 작은 고민들을 이 시간을 통해 편안하게 풀어낼 수 있도록 배려한 세심한 장치랍니다.&lt;/p&gt;
&lt;p&gt;누군가의 짝꿍이 되어 90일 동안 세심하게 마음을 쓴다는 건 분명 멋지지만, 그만큼의 에너지와 정성이 들어가는 일이죠.&lt;/p&gt;
&lt;p&gt;여기어때는 선배 구성원들의 이러한 따뜻한 노력을 당연하게 여기지 않죠!&lt;/p&gt;
&lt;p&gt;90일간 짝꿍과의 여정을 마무리하면, 고생한 짝꿍을 위해 소소하지만 선물도 드린답니다.🎁&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/800/1*bSGiJhw0AE_U37O6b6LZPQ.png"&gt;&lt;/figure&gt;&lt;p&gt;낯선 환경에서 먼저 다정하게 손을 내밀어 주는 동료들이 있는 곳.&lt;/p&gt;
&lt;p&gt;든든한 짝꿍과 함께 여기어때에서 여러분의 새로운 커리어를 시작해 보는 건 어때요?&lt;/p&gt;
&lt;p&gt;여러분의 든든한 짝꿍이 되어줄 멋진 동료들이 오피스 라운지에서 여러분을 기다리고 있습니다. 😊&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gccompany.career.greetinghr.com/ko/apply"&gt;&lt;strong&gt;👉 [지금 진행 중인 여기어때 채용 공고 확인하고 내 짝꿍 만나러 가기]&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;img src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=7ace186c2671" width="1" height="1" alt=""&gt;&lt;hr&gt;
&lt;p&gt;&lt;a href="https://techblog.gccompany.co.kr/90%EC%9D%BC-%EB%8F%99%EC%95%88-%EB%82%B4-%ED%8E%B8%EC%9D%B4-%EC%83%9D%EA%B2%BC%EB%8B%A4-%EC%A7%9D%EA%BF%8D-%EC%A0%9C%EB%8F%84-7ace186c2671"&gt;90일 동안 내 편이 생겼다! 짝꿍 제도&lt;/a&gt; was originally published in &lt;a href="https://techblog.gccompany.co.kr"&gt;여기어때 기술블로그&lt;/a&gt; on Medium, where people are continuing the conversation by highlighting and responding to this story.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://techblog.gccompany.co.kr/90%EC%9D%BC-%EB%8F%99%EC%95%88-%EB%82%B4-%ED%8E%B8%EC%9D%B4-%EC%83%9D%EA%B2%BC%EB%8B%A4-%EC%A7%9D%EA%BF%8D-%EC%A0%9C%EB%8F%84-7ace186c2671?source=rss----18356045d353---4</id>
    <link href="https://techblog.gccompany.co.kr/90%EC%9D%BC-%EB%8F%99%EC%95%88-%EB%82%B4-%ED%8E%B8%EC%9D%B4-%EC%83%9D%EA%B2%BC%EB%8B%A4-%EC%A7%9D%EA%BF%8D-%EC%A0%9C%EB%8F%84-7ace186c2671?source=rss----18356045d353---4"/>
    <title>90일 동안 내 편이 생겼다! 짝꿍 제도</title>
    <updated>2026-06-16T10:46:24+09:00</updated>
    <dc:date>2026-06-16T10:46:24+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Google for Developers</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;style&gt;
.post-body span {
white-space: normal !important; }
&lt;/style&gt;

&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;         &lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ5jGOkZf1r1k0dc4YmXDxP0M8JioqNqlhJb8NuVCVBw556o5wlXNpOZimVOOSyBvRRNFZPktWwYIM4BcKOJLa7X_lttEqMoHHaiBDTL5mjxlvNzRkxwjltznLwcx5pd4XxYC2vEzMgRvvlYsSTop9hJgPg_f24dVSUZoIVCuS8UdQX4vh66yQrhxPLw/s3334/Google%20Dev_Header_final.png" style="font-family: inherit; margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" data-original-height="835" data-original-width="3334" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ5jGOkZf1r1k0dc4YmXDxP0M8JioqNqlhJb8NuVCVBw556o5wlXNpOZimVOOSyBvRRNFZPktWwYIM4BcKOJLa7X_lttEqMoHHaiBDTL5mjxlvNzRkxwjltznLwcx5pd4XxYC2vEzMgRvvlYsSTop9hJgPg_f24dVSUZoIVCuS8UdQX4vh66yQrhxPLw/w640-h160/Google%20Dev_Header_final.png" width="640"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="color: black; font-family: inherit; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;개발자 여러분, 안녕하세요!&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="color: black; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;6월 셋째 주 블로그에 발표된 Google의 주요 개발자 제품별 최신 소식을 살펴보세요.&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span id="docs-internal-guid-02d963c5-7fff-b97c-f79a-9177957eea84"&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="color: black; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;"&gt;[주요 개발자 블로그 업데이트]&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="background-color: #ffe599; color: black; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: inherit;"&gt;AI &amp;amp; Machine Learning&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;에이전틱 리소스 디스커버리 규격 발표 (&lt;/span&gt;&lt;a href="https://developers.googleblog.com/announcing-the-agentic-resource-discovery-specification/" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Announcing the Agentic Resource Discovery specification&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit; font-variant: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;의료 AI 'AMIE'가 건강 관리에 기여할 수 있음을 증명한 새로운 연구 결과 (&lt;/span&gt;&lt;a href="https://blog.google/innovation-and-ai/models-and-research/google-research/amie-for-disease-management-in-nature/" style="font-family: inherit; text-decoration: none;" target="_blank"&gt;&lt;span style="color: #1155cc; font-variant: normal; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;New research shows how AMIE, our medical AI, could help manage health conditions&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: inherit; font-variant: normal; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;A2UI와 MCP 앱의 만남: 선언형 UI와 맞춤형 에이전틱 UI의 장점 결합하기 (&lt;/span&gt;&lt;a href="https://developers.googleblog.com/a2ui-and-mcp-apps/" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;A2UI + MCP Apps: Combining the best of declarative and custom agentic UIs&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;보안 및 신뢰성 강화: Google 계정 로그인에 새로운 세션 메타데이터 추가 (&lt;/span&gt;&lt;a href="https://developers.googleblog.com/enhance-security-and-trust-new-session-metadata-in-sign-in-with-google/" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Enhance Security and Trust: New Session Metadata in Sign in with Google&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;b id="docs-internal-guid-dee7812f-7fff-2a3b-eb7f-21914a4210a6" style="font-weight: normal;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="background-color: #ffe599; color: black; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: inherit;"&gt;Android&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Android 17 정식 출시 (&lt;/span&gt;&lt;a href="https://android-developers.googleblog.com/2026/06/Android-17.html" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Android 17 is here&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Android 개발자 신원 확인: 함께 만들어가는 더 안전한 생태계 (&lt;/span&gt;&lt;a href="https://android-developers.googleblog.com/2026/06/android-developer-verification.html" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Android developer verification: Building a safer ecosystem together&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Android XR, Geospatial API, Gemini를 활용한 혼합현실(MR) 투어 가이드 앱 빌드하기 (&lt;/span&gt;&lt;a href="https://android-developers.googleblog.com/2026/06/android-xr-geospatial-api-gemini.html" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Building a Mixed-Reality Tour Guide with Android XR, the Geospatial API, and Gemini&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Android XR 신규 기능 살펴보기: 개발 도구, 엔진 지원, 생태계 업데이트 (&lt;/span&gt;&lt;a href="https://android-developers.googleblog.com/2026/06/what-is-new-android-xr.html" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;What’s New in Android XR: Tooling, Engine Support, and Ecosystem Updates&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;b style="font-weight: normal;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="background-color: #ffe599; color: black; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: inherit;"&gt;Flutter&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;/p&gt;
&lt;ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"&gt;&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Flutter 2분기 개발자 설문조사 참여하기 (&lt;/span&gt;&lt;a href="https://blog.flutter.dev/flutter-q2-survey-475913d622ec" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Flutter Q2 survey&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span id="docs-internal-guid-f353c7e6-7fff-4ce8-9cb9-434260c17814" style="font-family: inherit;"&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span id="docs-internal-guid-d373cb86-7fff-d08b-193a-8a9cd353ad34"&gt;&lt;p style="line-height: 1.68; margin-bottom: 12pt; margin-top: 12pt;"&gt;&lt;span style="font-family: inherit; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;&lt;span style="font-family: inherit;"&gt;* &lt;/span&gt;국문 번역본으로 보시려면 Chrome 창에서 각 영문 링크로 이동한 후 마우스 우측 버튼을 눌러 ‘한국어로 번역'을 선택하시면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span face='"Google Sans", sans-serif' style="font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;* 최신 개발자 문서에 대한 알림을 받아보려면, &lt;/span&gt;&lt;a href="http://developer.google.com/profile/u/me?hl=ko" style="text-decoration-line: none;" target="_blank"&gt;&lt;span face='"Google Sans", sans-serif' style="color: #1155cc; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space-collapse: preserve;"&gt;여기&lt;/span&gt;&lt;/a&gt;&lt;span face='"Google Sans", sans-serif' style="font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;에서 Google 개발자 프로필을 생성하여 손쉽게 살펴보세요. 다양한 개발자 학습 과정과 커뮤니티 이벤트에 참여하면 여러분의 프로필에 표시할 수 있는 온라인 인증 배지도 함께 드립니다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;"&gt;Google for Developers&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>http://developers-kr.googleblog.com/2026/06/weeklyupdate-week3.html</id>
    <link href="http://developers-kr.googleblog.com/2026/06/weeklyupdate-week3.html"/>
    <title>에이전틱 리소스 디스커버리 규격 발표 등 6월 셋째 주 Google for Developers 위클리 업데이트를 지금 확인하세요! </title>
    <updated>2026-06-19T18:09:27.367+09:00</updated>
    <dc:date>2026-06-19T18:09:27.367+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Google for Developers</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;        &lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ5jGOkZf1r1k0dc4YmXDxP0M8JioqNqlhJb8NuVCVBw556o5wlXNpOZimVOOSyBvRRNFZPktWwYIM4BcKOJLa7X_lttEqMoHHaiBDTL5mjxlvNzRkxwjltznLwcx5pd4XxYC2vEzMgRvvlYsSTop9hJgPg_f24dVSUZoIVCuS8UdQX4vh66yQrhxPLw/s3334/Google%20Dev_Header_final.png" style="font-family: inherit; margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" data-original-height="835" data-original-width="3334" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ5jGOkZf1r1k0dc4YmXDxP0M8JioqNqlhJb8NuVCVBw556o5wlXNpOZimVOOSyBvRRNFZPktWwYIM4BcKOJLa7X_lttEqMoHHaiBDTL5mjxlvNzRkxwjltznLwcx5pd4XxYC2vEzMgRvvlYsSTop9hJgPg_f24dVSUZoIVCuS8UdQX4vh66yQrhxPLw/w640-h160/Google%20Dev_Header_final.png" width="640"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="color: black; font-family: inherit; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;개발자 여러분, 안녕하세요!&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="color: black; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;6월 둘째 주 블로그에 발표된 Google의 주요 개발자 제품별 최신 소식을 살펴보세요.&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span id="docs-internal-guid-02d963c5-7fff-b97c-f79a-9177957eea84"&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="color: black; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;"&gt;[주요 개발자 블로그 업데이트]&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="background-color: #ffe599; color: black; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: inherit;"&gt;AI &amp;amp; Machine Learning&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style="margin-bottom: 0; margin-top: 0; padding-inline-start: 48px;"&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;‘Gemini 3.5 라이브 번역’을 통한 매끄럽고 자연스러운 음성 번역 (&lt;/span&gt;&lt;a href="https://blog.google/intl/ko-kr/company-news/technology/gemini-live-3-5-translate-kr/" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;국문&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;개발자를 위한 DiffusionGemma 핵심 가이드 (&lt;/span&gt;&lt;a href="https://developers.googleblog.com/diffusiongemma-the-developer-guide" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;DiffusionGemma: The Developer Guide&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;2026년 5월에 발표된 최신 AI 소식 총정리 (&lt;/span&gt;&lt;a href="https://blog.google/innovation-and-ai/technology/ai/google-ai-updates-may-2026/" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;The latest AI news we announced in May 2026&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Google Colab CLI 출시 소식 살펴보기 (&lt;/span&gt;&lt;a href="https://developers.googleblog.com/introducing-the-google-colab-cli" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Introducing the Google Colab CLI&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;b id="docs-internal-guid-82a6a1a0-7fff-89fd-3f50-cb5b6ecf9d67" style="font-weight: normal;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="background-color: #ffe599; color: black; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: inherit;"&gt;Android&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style="margin-bottom: 0; margin-top: 0; padding-inline-start: 48px;"&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Android 개발자 생산성 향상을 위한 주요 업데이트 3가지 (&lt;/span&gt;&lt;a href="https://android-developers.googleblog.com/2026/06/android-developer-productivity-updates.html" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Top 3 updates for Android developer productivity&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Datadog이 ProfilingManager를 통해 깊이 있는 성능 데이터를 제공하는 방법 (&lt;/span&gt;&lt;a href="https://android-developers.googleblog.com/2026/06/datadog-profilingmanager-performance-insights.html" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Datadog delivers millions of in-depth performance insights with ProfilingManager&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;b style="font-weight: normal;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="background-color: #ffe599; color: black; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: inherit;"&gt;Firebase&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;/p&gt;
&lt;ul style="margin-bottom: 0; margin-top: 0; padding-inline-start: 48px;"&gt;&lt;li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"&gt;&lt;p dir="ltr" role="presentation" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Apple의 Foundation Models 프레임워크에 탑재된 Gemini 살펴보기 (&lt;/span&gt;&lt;a href="https://firebase.blog/posts/2026/06/apple-foundation-models-gemini" style="text-decoration: none;" target="_blank"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Gemini in Apple's Foundation Models framework&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span id="docs-internal-guid-f353c7e6-7fff-4ce8-9cb9-434260c17814" style="font-family: inherit;"&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span id="docs-internal-guid-d373cb86-7fff-d08b-193a-8a9cd353ad34"&gt;&lt;p style="line-height: 1.68; margin-bottom: 12pt; margin-top: 12pt;"&gt;&lt;span style="font-family: inherit; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;&lt;span style="font-family: inherit;"&gt;* &lt;/span&gt;국문 번역본으로 보시려면 Chrome 창에서 각 영문 링크로 이동한 후 마우스 우측 버튼을 눌러 ‘한국어로 번역'을 선택하시면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span face='"Google Sans", sans-serif' style="font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;* 최신 개발자 문서에 대한 알림을 받아보려면, &lt;/span&gt;&lt;a href="http://developer.google.com/profile/u/me?hl=ko" style="text-decoration-line: none;" target="_blank"&gt;&lt;span face='"Google Sans", sans-serif' style="color: #1155cc; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space-collapse: preserve;"&gt;여기&lt;/span&gt;&lt;/a&gt;&lt;span face='"Google Sans", sans-serif' style="font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;"&gt;에서 Google 개발자 프로필을 생성하여 손쉽게 살펴보세요. 다양한 개발자 학습 과정과 커뮤니티 이벤트에 참여하면 여러분의 프로필에 표시할 수 있는 온라인 인증 배지도 함께 드립니다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;p dir="ltr" style="line-height: 1.68; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span style="font-family: inherit; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;"&gt;Google for Developers&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>http://developers-kr.googleblog.com/2026/06/weeklyupdate-week2.html</id>
    <link href="http://developers-kr.googleblog.com/2026/06/weeklyupdate-week2.html"/>
    <title>Gemini 3.5 라이브 번역 출시 등 6월 둘째 주 Google for Developers 위클리 업데이트를 지금 확인하세요! </title>
    <updated>2026-06-12T10:58:54.443+09:00</updated>
    <dc:date>2026-06-12T10:58:54.443+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Dreamhack</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;보안 업계 취업을 준비한다면 직종부터 알아야죠. 보안관제, 모의해킹, 포렌식, 컨설턴트 등 6개 직종이 실제로 무슨 일을 하는지 확인해 보세요.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://theori.io/ko/blog/cybersecurity-job-types</id>
    <link href="https://theori.io/ko/blog/cybersecurity-job-types"/>
    <summary type="html">보안 업계 취업을 준비한다면 직종부터 알아야죠. 보안관제, 모의해킹, 포렌식, 컨설턴트 등 6개 직종이 실제로 무슨 일을 하는지 확인해 보세요.</summary>
    <title>화이트햇 해커 취업, 어떤 직종이 있을까? - 사이버 보안 6개 직종 정리</title>
    <updated>2026-06-17T14:37:31+09:00</updated>
    <dc:date>2026-06-17T14:37:31+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/15bd515f-7007-43b7-857e-8807d4d356f4/image-2026-06-19T213239.828-ezgif.com-compress-png.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/f0cdd0e0-4997-4a3d-a4ce-58300f18fd60/Frame_1707482502.png"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="384a360d-33e3-80de-895f-da7798d7900b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;지난 3월, 토스 디자인 챕터는 AI Contest를 열었어요. 규칙은 단 하나였어요. AI로 뭐든 만들어보기.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8044-a860-d0acbf7175ac" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;형식도 결과물도 자유예요. 업무와 관련 없어도 괜찮았고, 단순 재미로 만들어도 되고, 완성도가 높지 않아도 됐어요. &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;중요한 건 AI를 직접 만져보고, 자신의 문제를 스스로 해결해 보는 경험이었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-80a0-a641-e1750ea5493b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그렇게 한 달 동안 122개의 작업이 모였어요. 흥미로운 점은, 디자이너들이 AI를 활용하는 방식이 몇 가지 공통된 방향으로 나뉘었다는 거예요. 그중 인상적이었던 네 가지 사례를 소개할게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8076-8e63-ca31b3cd302c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8082-aef9-e974712c4c22" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="384a360d-33e3-804e-b26a-e4ab24696c8f" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;반복되는 일을 AI에 넘기다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="384a360d-33e3-80e3-b8d5-ef0f220c628d" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/15bd515f-7007-43b7-857e-8807d4d356f4/image-2026-06-19T213239.828-ezgif.com-compress-png.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="384a360d-33e3-8063-8704-e9c72a68b0c1" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;컬러 추출 자동화 로직&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-803d-86d2-d951d84fd4e9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이미지를 넣으면 UI에 쓸 색을 자동으로 추출·보정해 주는 로직이에요. 색 추출은 사진마다 결과가 제각각이라, 토스에서 몇 년째 진전이 없던 과제였어요. AI와 함께 보정 로직 초안을 코드로 만든 뒤, 샘플 이미지를 잔뜩 넣어 만들고, 확인하고, 고치는 사이클을 빠르게 반복했어요. 그렇게 깎아낸 로직이 지금 토스 쇼핑 상품 카드의 색상에 실제로 적용되고 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-80df-969f-d470e06ff235" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8086-9c2c-f0de454d4c56" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="384a360d-33e3-8017-98b0-f5d2ab012835" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;나를 복제해 협업 비용을 줄이다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="384a360d-33e3-80ab-8a5f-d7935fb410ae" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/f0cdd0e0-4997-4a3d-a4ce-58300f18fd60/Frame_1707482502.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="384a360d-33e3-80d1-8cc4-c9317ffacd88" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;나의 지식과 커뮤니케이션을 통째로 학습시킨 슬랙(메신저) 봇이에요. 디자인·요건 질문이 하루에도 수십 번 들어왔는데 답변하는 데 시간이 너무 많이 들었어요. 이 문제를 해결하려고 봇을 만들었죠. 이제 팀원이 질문을 던지면, 봇이 과거 논의 메시지와 정리해 둔 참고 자료를 근거로 답변 초안을 만들어줘요. 사람은 그 초안을 보고 바로 보낼지 수정할지 결정하면 돼요. 게다가 초안을 고쳐 보내면 봇이 그 수정 방향까지 학습해, 다음 비슷한 질문엔 더 정확하게 답해요. "내가 1.5명으로 늘어난 느낌"이라 했을 만큼 효과가 또렷했고, 토스의 다른 디자이너들도 각자 봇을 만들기 시작했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-80af-91ed-cc55253e768a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8049-92df-c94242bf6938" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8052-8c0c-fff42ddc786e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="384a360d-33e3-80aa-b234-e78913b5ba61" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;말 대신 동작하는 걸로 설득하다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="384a360d-33e3-80d4-b958-ed3aaf5738cf" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/5b6ebf45-41b0-4ec0-bb10-4fee0d5cab55/KakaoTalk_Video_2026-06-19-12-10-20.mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;/figure&gt;&lt;p id="384a360d-33e3-80a3-a6ca-c3b8cd59abf9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;주식을 사고파는 증권 PC 화면을, 그림이 아니라 '진짜로 움직이는' 화면으로 만든 프로토타입이에요. 보통 디자이너는 멈춰 있는 시안을 그리고, 화면이 어떻게 움직이는지는 말이나 영상으로 설명해 넘기잖아요. 그러면 그 의도가 개발 단계에서 흐려지기도 하고요. 그래서 실제 제품 코드를 직접 만져서, 패널을 끌어다 자리를 바꾸거나 창 크기를 줄이면 화면이 알아서 반응하는 것까지 동작하게 만들었어요. 멈춘 시안이었다면 말로 설명했을 인터랙션을 직접 움직여 보여주며, 개발자와 눈높이를 맞추고 PO까지 설득했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8079-8f62-d6f378702809" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-80aa-a990-fa6392a7a0a6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="384a360d-33e3-80ba-ab78-c868219baf5f" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;짧은 시간에 퀄리티를 끝까지 밀어붙이다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="384a360d-33e3-800a-a524-fbf6e34f04f9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="384a360d-33e3-8099-a27e-ec0cf1503d8b" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/07ddf3ae-5d59-4a5b-905f-91ddea87b33c/2026-06-1610.28.14-ezgif.com-gif-maker.mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;/figure&gt;&lt;p id="384a360d-33e3-806d-b2e0-d0357d8dc9b4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스뱅크 공채 웹페이지의 키비주얼에 들어간, AI로 만든 직군별 모션그래픽이에요. 직군마다 모션을 다 만들어야 하는데 일정이 아주 촉박했어요. 모션의 뼈대 이미지는 직접 만들고, AI(kling)로는 원하는 결과가 나올 때까지 프롬프트를 집요하게 수정했죠. 시작과 끝 프레임은 사람 손을 거쳤지만, 직군별 모션을 단 하루 만에 완성했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-802d-8b43-c584033895ff" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="384a360d-33e3-802c-bc4b-e9f3b40743ef" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;적용해 보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="384a360d-33e3-805e-95ce-fa463fce1f48" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;디자이너들은 AI로 완전히 새로운 일을 하기보다, 이미 하고 있는 일을 더 빠르게, 더 설득력 있게, 더 높은 완성도로 만드는 데 AI를 활용하고 있었어요. AI를 써보고 싶은데 어디서 시작해야 할지 모르겠다면, 아래 네 가지 방향 중 하나를 생각해보세요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="384a360d-33e3-804b-961f-ec7b2e7ec6a0" class="css-nv7vyi"&gt;&lt;h4 class="css-123co55"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;1️⃣ 효율&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; : 매일 반복하는 일 중 가장 거슬리는 동작 하나를 AI에 넘겨보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="384a360d-33e3-8047-8920-eaf7f3904b67" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;2️⃣ 분신&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; : 내가 반복해서 답하는 질문을 대신 답해줄 봇 만들어보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8058-afca-fadfe28aa917" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;3️⃣ 설득&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; : 말로 설명하던 디자인을 동작하는 프로토타입으로 보여주기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-80cc-a346-cc594043f6d1" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;4️⃣ 퀄리티&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; : 제한된 시간 안에 더 높은 완성도에 도달해보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;&lt;p id="384a360d-33e3-807c-92f9-d307cfddc418" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-80c9-9854-db340901ac23" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="384a360d-33e3-8056-b3e1-e67e66531be7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Editor 유아란&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/ai_contest</id>
    <link href="https://toss.tech/article/ai_contest"/>
    <summary type="html">토스 디자인챕터에서 AI Contest를 열었어요. 그중 인상적이었던 네 가지 사례를 소개합니다.</summary>
    <title>디자이너에게 AI로 뭐든 만들어보라고 한다면</title>
    <updated>2026-06-19T21:40:00+09:00</updated>
    <dc:date>2026-06-19T21:40:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/93d1a2d3-1a71-475c-9a53-214e62881ff0/n1a-client-mode.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/8356a8d3-1147-4948-870b-9688d880c995/n1b-cluster-mode.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/ac5183c9-7b89-4f56-8590-d91210998b0c/n2c-connect-only.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/b5021eae-ad96-4c83-bfbb-dd5750e96973/n3-sparkcontext-share.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/67d7dce0-82c6-4308-a542-56d9518044da/n5-fifo-slots.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/a92da84e-464a-4bb8-b089-1d9ace6a9905/n6-fault-tolerance.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/8042b085-f441-4c04-b45e-92206fbb6519/n7-replication.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/a45f2475-64fa-4a9e-acd6-67d50cfdfbd3/n8-consistent-hash-limit.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/5786899b-c9d9-4e95-8673-bf1c06c090a2/n9-gateway-two-rules.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/fa3dc6fb-5997-47ff-95ea-d735f87c9ea3/n11-gateway-no-k8s.png"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="eb23e08e-53e2-4ab0-8e87-afb644834681" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;안녕하세요. 토스증권 Data Infra팀 박지원입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="ccd4cbdd-a51f-4ac9-8635-59d9a552d215" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스증권은 분석가와 엔지니어가 복잡한 설정 없이 Spark를 쓸 수 있도록, Spark Connect를 Kubernetes에서 서비스로 운영하고 있습니다. 사내 여러 팀의 분석과 데이터 파이프라인이 이 위에서 돌아가는 만큼, 안정성을 확보하는 것을 가장 중요한 목표로 두고 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="9cba68b5-42b3-4419-b405-c8798185e92d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 시리즈에서는 Spark Connect를 Production 수준의 서비스로 만들어온 과정을 풀어보려고 합니다. 첫 주제는 견고한 Spark Connect 만들기 — 여러 사용자가 함께 써도 각자의 작업을 서로 지키며, 안정적으로 운영하는 방법입니다. Spark Connect가 처음인 분도 부담 없이 따라올 수 있게, 개념부터 차근차근 짚어 보겠습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b2-b5d2-c1c2e57ff06c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="386ce606-dbe0-4e9b-8a43-548bf7d2e2f6" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;Spark는 원래 어떻게 동작하나요&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="0aa9de57-5b9d-4de9-bd29-17b684a2e897" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Spark Connect가 무엇인지 이해하려면, 먼저 Spark가 원래 어떻게 동작하는지부터 봐야 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="ce96a112-dbcc-4ec7-9125-f6d251f11a79" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Spark에는 두 종류의 프로세스가 있습니다. 작업을 계획하고 지휘하는 Driver, 그리고 실제 연산을 나눠 수행하는 Executor입니다. Driver가 코드를 받아 실행 계획을 세우고, Executor들에게 Task를 나눠주고, 결과를 모읍니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="af0ef073-7a9f-4301-9b73-38453ba3fb5c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Classic Spark에는 이 Driver를 어디서 실행하느냐에 따라 두 가지 배포 모드가 있습니다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div class="css-1lyd0tt"&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="380a360d-33e3-8033-ac2c-e0181182065b" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/93d1a2d3-1a71-475c-9a53-214e62881ff0/n1a-client-mode.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="380a360d-33e3-80ca-914f-f039e75ac611" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/8356a8d3-1147-4948-870b-9688d880c995/n1b-cluster-mode.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p id="fa1e917a-d156-49d9-9340-e8f995e8fa82" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;① Client mode는 Driver가 클라이언트 프로세스 안에 있습니다. 클라이언트가 곧 Driver죠. ② Cluster mode는 Driver가 클러스터 노드에서 실행돼, 작업을 제출할 때마다 떴다가 끝나면 사라집니다. 대신 클라이언트가 죽어도 앱은 계속 돌아가고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="81410123-3bef-42c9-bd98-a303137497d7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;중요한 건 두 모드의 공통점입니다. 둘 다 App마다 Driver가 새로 뜨고, 그 Driver는 App의 수명과 함께 살고 죽습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="e21db4f8-e3d1-46db-98d6-a334c7882bb2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그리고 작업을 제출하려면 클라이언트 쪽에도 Spark 라이브러리와 설정이 갖춰져 있어야 하죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="37da360d-33e3-80c2-a838-ced3bc8b8db2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Spark Connect가 바로 이 지점을 개선했습니다. 2022년 &lt;/span&gt;&lt;a target="_blank" rel="noreferrer noopener" class="css-iynyr0" href="https://issues.apache.org/jira/browse/SPARK-39375"&gt;SPIP&lt;/a&gt;&lt;span class="css-1kxrhf3"&gt;로 출발해 Spark 3.4에 처음 들어왔어요. 초기에는 클라이언트에서 쓸 수 없는 API가 적지 않았지만 버전을 거듭하며 공백이 메워졌고, 4.0에서는 기존 Dataset/DataFrame API와 동등한 수준에 올라섰습니다. 4.1에서도 사용성과 성능 개선이 이어지고 있고요. 저희는 4.1 버전을 운영하고, 글의 코드·설정도 4.1 기준이에요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-800f-989d-cc87473f8522" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="3958fafb-0f36-4c3c-998f-7050e8298c75" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;Spark Connect는 무엇이 다른가요&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="dc908d9a-698b-4f06-8a0c-34bf72da039c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Spark Connect는 Driver를 애플리케이션마다 뜨는 것에서, 미리 떠있는 서버로 만들었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="381a360d-33e3-8011-831b-f74ed28a88fc" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/ac5183c9-7b89-4f56-8590-d91210998b0c/n2c-connect-only.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="6c71c411-0677-4617-b359-3b00d13f0574" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;클라이언트는 더 이상 Driver를 갖고 있지 않습니다. DataFrame이나 SQL 연산을 Unresolved Logical Plan으로 바꿔 Protocol Buffer로 인코딩하고, 이걸 gRPC로 서버에 보냅니다. 이미 떠 있는 서버가 분석·최적화·스케줄링·실행을 맡고, 결과는 Arrow로 다시 스트리밍됩니다. 마치 JDBC Client로 데이터베이스에 질의하는 모델과 유사합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8036-a8d0-f3e6fbf07991" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="fdd936db-0e8b-423d-85fb-caeba013359b" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 좋은 점&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="b92dcb8a-f238-4cbb-9769-967f14d587fd" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Driver를 서버로 분리해 미리 띄워두면, 이런 이점이 생깁니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="381a360d-33e3-80d9-ae8c-eea24032d074" class="css-nv7vyi"&gt;&lt;div class="css-1vn47db"&gt;&lt;ul class="css-uswsmm"&gt;
&lt;li id="d4fc1caa-809e-404a-80d1-e8935143c38a" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;가벼운 클라이언트&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; — 클라이언트는 gRPC로 명세만 주고받는 Thin Client입니다. 무거운 Spark 의존성과 JVM 없이도 접속할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="a4855756-5d7e-4d3f-b2ac-c6f2870bd86c" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;언어·플랫폼 독립&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; — 서버가 연산을 맡으니 클라이언트 쪽은 어떤 언어든, 노트북이든 BI 도구든 SQL 클라이언트든 상관없습니다. 같은 서버에 여러 종류의 클라이언트가 붙습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="a925aab8-b22e-4b6f-ba9a-2603005f2952" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;즉시 세션 생성&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; — 서버가 이미 떠 있는 상태로 대기하니, 접속하면 곧바로 세션이 열립니다. 매번 Driver를 띄우고 리소스를 협상하며 기다릴 필요가 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="14ba511b-a442-4809-86c3-16aede8cbce7" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;클라이언트 장애에 강함&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; — 연산 주체가 서버라서, 클라이언트가 끊기거나 노트북을 닫아도 서버 쪽 작업은 보호됩니다. 세션만 정리하면 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/aside&gt;&lt;p id="24eabfcb-3d92-4ffb-b9e1-0bc5f0dfffa2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;여기까지만 보면 이상적입니다. 그런데 미리 띄워둔 long-running 서버 하나에 여러 클라이언트가 붙는다는 모델은, 동시에 새로운 문제들을 만들었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803c-9ff5-de7d348e8d46" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="1ee45951-22e3-41be-9059-5888947e0eb5" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;Spark Connect 서버가 만드는 문제들&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="acc9d939-8aa5-441c-bcc5-89268f51f4ab" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;미리 말해두면, 이 문제들의 근본적인 원인은 하나입니다. Spark의 기본 설계 곳곳이 ‘앱 하나 = 워크로드 하나’를 전제하는데, 우리는 그 앱을 여러 사용자가 공유하는 long-running 서버로 쓰고 있다는 것. 아래 문제들은 전부 이 전제가 깨지는 지점에서 나옵니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="58f534c3-cb24-49d9-85f0-2ca3f35b0e23" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문제 ①, Driver = 단일 장애점&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="454ff4aa-8f4c-4e16-9eb6-a31d9c2e884b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Spark Connect 서버 하나에 여러 세션이 붙으면, 그 세션들은 하나의 SparkContext를 공유합니다. Driver JVM이 하나라는 뜻입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="e7c2a349-f32e-4f02-a4b6-2f8089a802ad" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;세션이 아무리 늘어도 Driver는 하나입니다. 그래서 Driver 프로세스에 문제가 생겨 내려가는 순간, 영향은 한 세션에 그치지 않고 그 서버에 붙은 모든 세션으로 번집니다. 진행 중이던 job과 캐시도 함께 사라지죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="380a360d-33e3-8053-b454-c7c312f5c819" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/b5021eae-ad96-4c83-bfbb-dd5750e96973/n3-sparkcontext-share.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="2da7f086-5407-4c9c-9535-f4e5803aee2c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;실제로 한 사용자의 쿼리 하나가 서버 전체를 내릴 수 있습니다. Spark는 executor 실패가 임계값(&lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.executor.maxNumFailures&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;, 기본값 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;max(3, 2 × executor 수)&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;)을 넘으면 앱을 종료하는데, 이 로직이 바로 ‘앱 하나 = 워크로드 하나’ 전제로 설계돼 있거든요. Kubernetes 환경의 실제 코드를 보면:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="2a8bb6f3-1e13-47c5-ba53-173d651f4843" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;stopApplication&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;이 하는 일이 곧 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;sys.exit(11)&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;입니다. gRPC 서버도, SparkContext도, 모든 세션도 이 한 줄에 함께 내려갑니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="4779ed5a-4f6f-4f72-b382-9e71999638a4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 카운터의 두 가지 성질이 멀티세션 서버에서 위험을 키웁니다. 첫째, Executor 단위 글로벌 카운터라 개별 쿼리의 Task 수준 fault tolerance(&lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.task.maxFailures&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;)와 무관하게 쌓이고, 시간이 지나도 사라지지 않습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="3f88c8c3-4d10-4ddb-ba36-e13ca720e0de" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;둘째, 모든 세션의 실패를 합산합니다. 그래서 OOM을 일으키는 쿼리가 반복되거나 여러 사용자의 executor 실패가 누적되면, 그 합이 임계값을 넘는 순간 서버 전체가 종료되고 원인을 만든 세션과 함께 아무 잘못 없는 다른 세션까지 함께 사라집니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="7516764c-bb07-4245-98f5-b5b0bd96bbf8" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문제 ②, 리소스 경합과 Task Scheduling 한계&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="3b540b37-03bd-426c-965a-aef1d6e36dfb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;서버가 세션마다 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;newSession()&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;을 만들긴 하지만, 이건 세션 로컬 상태(SQL 네임스페이스)만 격리할 뿐입니다. CPU·메모리·Executor 같은 실행 리소스는 모두가 나눠 씁니다. 그래서 한 사용자가 Job을 대량으로 제출하면 다른 사용자의 응답이 느려집니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="86421c1a-882a-482e-a499-75ebd8fcf27f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이건 Driver의 Task Scheduling 구조 때문입니다. 한 Driver의 스케줄러는 모든 세션의 Task를 함께 놓고, Executor의 Task 슬롯이 빌 때마다 하나씩 나눠줍니다. 기본 정책이 FIFO라 경합이 생기면 먼저 제출된 작업이 우선이고, 선점(Preemption)이 없어서 이미 슬롯을 차지한 Task를 중단시키지도 못합니다. 무거운 작업이 슬롯을 전부 채우면 뒤에 온 가벼운 쿼리는 그 Task들이 끝나 슬롯이 반환되기만 기다려야 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="380a360d-33e3-80e7-a457-cb47a2c285f2" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/67d7dce0-82c6-4308-a542-56d9518044da/n5-fifo-slots.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="1ad2a786-529c-401b-a6ac-0dc52f0b4264" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Scheduler가 다루는 건 어디까지나 Task 슬롯의 순서뿐이라, 사용자별로 CPU·메모리를 보장하거나 우선순위를 세밀하게 나누는 데는 구조적 한계가 있습니다. Spark에는 작업을 풀(Pool)로 나눠 가중치를 주는 Fair Scheduler도 있지만, 이 역시 빈 슬롯을 누구에게 먼저 줄지 순서를 바꿀 뿐 CPU·메모리를 격리해주지는 못합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="32e91304-f023-4c95-b7d4-c87d88d20570" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;사실 Spark Connect에서는 이 Fair Scheduler의 Pool 분리조차 동작하지 않습니다. &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.scheduler.pool&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;은 Job을 제출하는 실행 스레드에 thread-local로 얹혀 있어야 스케줄러가 인식하는데요. Classic Spark에서는 클라이언트가 곧 Driver라 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;setLocalProperty()&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; 한 줄이면 그 스레드에 바로 적용되었지만, Spark Connect는 클라이언트와 Driver가 떨어져 있어 서버가 요청을 실행하는 스레드에 이 값을 대신 넣어줘야 합니다. 그런데 서버는 다른 값은 전파하면서 정작 Scheduler Pool만 빠뜨려요. 그래서 모든 쿼리가 Default Pool 하나에 들어갑니다. 커뮤니티에도 알려진 공백인데, 저희는 요청을 실행하는 서버 스레드에 사용자별 Pool을 직접 넣어주는 방식으로 메웠어요. 다만 Pool을 '사용자별'로 가르려면 먼저 그 요청이 누구 것인지 알아야 하죠. 이 사용자 식별이 인증·인가의 몫이라 자세한 건 3편에서 다룰게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="38b3249b-f9d9-4d7f-813d-79b8ae957a81" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;어쨌거나 Pool이 다루는 건 어디까지나 Task 슬롯의 순서입니다. CPU·메모리 격리는 스케줄러로는 불가능하고, 결국 Spark 바깥에서 풀어야 했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="240d519d-f976-43dc-be90-283e3efa8828" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문제 ③, 고정된 스케일&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="3b012389-7b61-496f-887d-df774f8f40ee" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;마지막은 이번 편에서는 다루지 않는 문제입니다. 서버는 미리 정해진 스펙(이미지, Driver·Executor 리소스, Spark 설정)으로 뜹니다. Dynamic Resource Allocation으로 Executor 수는 부하에 따라 늘었다 줄었다 할 수 있지만, 서버 자체의 스펙은 실행 시점에 고정됩니다. 서버를 그때그때 만들고 교체할 수 있어야 풀리니, 이건 다음 편 몫이에요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80aa-89ee-daa2c0a10caf" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="8b17dc85-d104-47d9-97ce-778d9bce5907" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;그래서, 어떻게 풀었나&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="05936ee3-9009-4be5-bde5-aee144412457" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 문제들을 한 번에 없애는 단일 해법은 없었습니다. 단일 장애점(①)과 리소스 경합(②)은 이번 편에서, 고정된 스케일(③)과 팀 단위 격리는 다음 편에서 다룰게요. 단일 장애점부터 보겠습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="bf5126e2-71cc-4948-b254-6c0990353c15" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;공유 Driver의 SPOF를 어떻게 극복했나&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="2f7a5936-ceba-4650-a81c-c068d019ad05" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;단일 장애점은 두 단계로 풀었습니다. 먼저 서버가 죽는 일 자체를 줄이고, 그걸로도 못 막는 장애는 여러 Replica로 다중화해 받아냈어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="c8677353-24ff-4642-b8f3-043a92364d80" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;먼저, 죽는 일 자체부터 줄이기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="15a79291-483e-4c52-98dd-75726e73b68b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Replica를 늘리기 전에, 앞에서 본 ‘실패가 누적돼 서버를 죽이는’ 경로부터 끊었습니다. 글로벌 Executor 실패 카운터를 사실상 비활성화하고, 문제 쿼리의 정리는 Task·Stage·Job 단위의 Fault Tolerance에 맡긴 거예요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="1b59f78e-b565-432d-bedd-c8d77b462c19" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;핵심은 첫 줄, 글로벌 카운터를 끄는 것입니다. &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;failuresValidityInterval&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;은 흔히 오래된 실패를 잊는 설정으로 소개되지만 카운터를 꺼둔 저희에게는 long-running 서버에 실패 기록이 끝없이 쌓이지 않게 주기적으로 비워주는 쪽에 가깝습니다. 나머지 두 값은 Bad query가 Executor를 붙잡는 시간을 줄이기 위한 저희 환경의 선택이라, 워크로드에 따라 달라질 수 있어요. 다만 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;task.maxFailures&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;를 기본값보다 공격적으로 낮추면, 문제 쿼리를 빨리 끊는 대신 일시적인 장애에도 멀쩡한 쿼리까지 실패할 수 있어서 조금 여유를 두는 편이 안전해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="bcf52bb9-8cf4-45b2-a6e8-a0beaf879c2a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;task.maxFailures&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;와 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;stage.maxConsecutiveAttempts&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;는 같은 일을 단계만 달리해 막는 게 아니라, 서로 다른 실패를 맡습니다. 앞은 같은 Task가 거듭 실패하는 경우(OOM·예외)를, 뒤는 Shuffle Fetch 실패로 Stage가 통째로 다시 도는 경우를 끊어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="72eeca55-f6fd-4f4c-b15d-d2a7e3041ab0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이제 Executor가 반복해서 죽어도 서버는 살아남고, 문제를 일으킨 쿼리만 실패합니다. 에러도 달라졌어요. 전에는 서버가 죽어 모두가 ‘SparkContext에 접근할 수 없음’을 받았다면, 지금은 해당 쿼리를 보낸 사용자만 어떤 Executor가 어떤 Exit code로 죽었는지 담긴 Stage failure 에러를 받습니다. 원인 추적이 가능한 실패가 된 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="380a360d-33e3-806d-871a-d81596d07d92" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/a92da84e-464a-4bb8-b089-1d9ace6a9905/n6-fault-tolerance.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="fe9faa47-bff3-454a-bdf2-43cdff8c7929" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Executor 실패만이 아니라, 쿼리 결과 그 자체도 서버를 위협합니다. Spark Connect에서는 모든 세션의 쿼리 결과가 Driver를 거쳐 클라이언트로 스트리밍되니까, 누군가 거대한 테이블을 Collect하면 그 데이터가 전부 Driver 메모리로 향하거든요. 여기는 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.driver.maxResultSize&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;가 막아줍니다. 한 액션의 Task 결과 누적 크기가 한도를 넘으면 job을 abort하는데, 눈여겨볼 건 차단 시점이에요. executor에 쌓인 큰 결과는 Driver가 가져오기 전에 크기부터 검사하고, 한도를 넘으면 Fetch 자체를 포기합니다. 위험한 데이터가 Driver 메모리에 발을 들이기 전에 끊는 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="59c49fc2-469b-4b0d-95d5-6c99f8ce2c8d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;다만 기본값 1g은 이것도 ‘앱 하나 = 워크로드 하나’ 시절의 숫자입니다. 한도가 쿼리 단위라서, 여러 세션이 동시에 큰 결과를 받아 가면 각자 한도까지 통과합니다. 멀티세션 서버에서는 동시 쿼리 수를 감안해 이 값을 보수적으로 잡아야 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="e01bf553-803a-4eaf-9924-fbe19e0c0121" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래도 서버는 죽을 수 있습니다. Driver 자체가 OOM으로 내려가거나 노드가 통째로 사라지는 것까지 설정으로 막을 수는 없으니까요. 그래서 다음 단계가 필요했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80e9-8b52-ebc5a2b186cd" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="3f6db1fd-ac86-4653-80d0-8a903dfddccf" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;하나의 Spark Connect 서버를 여러 replica로&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="c566675c-6770-412d-8b1b-c3f56320eedd" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;가장 확실한 격리는 SparkContext 자체를 나누는 것입니다. 그래서 Spark Connect를 서버 한 대가 아니라, 같은 스펙의 서버 여러 대(Replica)로 구성할 수 있게 했어요. 각 Replica는 자기만의 SparkContext·Driver·Executor를 가지므로, 한 대가 장애로 내려가도 같은 Spark Connect의 다른 replica가 세션을 받습니다. 단일 장애점의 영향 범위가 Spark Connect 전체에서 replica 한 대로 줄어든 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="382a360d-33e3-8015-b432-fdcac954e62d" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/8042b085-f441-4c04-b45e-92206fbb6519/n7-replication.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="2f75396a-5640-4905-aaee-aa14af266a2d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Replica 수와 Executor 정책은 워크로드에 따라 조합합니다. 부하 변동이 크고 가용성이 중요한 워크로드라면 여러 replica(HA)에 Dynamic Resource Allocation을 얹어 한가한 replica는 Driver만 두고 Task가 쌓일 때만 Executor를 띄워요. 반대로 부하가 일정하거나 한 대로 충분하면 단일 replica에 Executor를 고정해 둡니다. DRA를 쓰는 쪽에선 부하가 replica들로 나뉘니, Executor 총량은 replica 수가 아니라 실제 작업량에 비례하고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80ad-a533-d7c2f65fc173" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="dc6e3519-0e4c-4a2a-9859-0eb08e165c01" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;요청을 어느 서버로 보낼까&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="5adf839c-d1e3-4dc7-bcaf-e38bc314bd2e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;하나의 Spark Connect가 여러 replica로 늘었으니, 이제 들어온 요청을 그중 어느 서버로 보낼지 정해야 합니다. 여기가 까다로웠어요. 새 세션은 한가한 서버에 놓여야 하고, 기존 세션은 늘 같은 서버로 가야 하거든요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="380a360d-33e3-80b2-b87d-fcd06c68ff29" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;처음엔 Istio로 풀어봤어요. Spark Connect의 replica들을 하나의 Aggregate Service로 묶고, consistent hash로 세션을 고정했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul class="css-uswsmm"&gt;
&lt;li id="b6e24957-f520-4cda-85f7-db368d6710b0" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;session affinity — Spark Connect 세션은 특정 Driver의 JVM 메모리에만 존재하니, 같은 세션의 요청은 늘 같은 replica로 가야 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="56df3cb9-c000-4780-8c3a-301a07b952a8" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;consistent hash — DestinationRule이 Client에서 따로 주입해준 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;x-spark-session-id&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; 헤더를 해시해서 같은 세션을 같은 pod에 고정합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="841d9231-3a73-496d-843d-60590844978a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;session affinity는 이걸로 잡혔습니다. 여기에도 명확한 한계가 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="be8638d5-79f5-4fcb-9a84-cf4256eab0f8" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Istio는 Spark를 모른다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="a0ea16f4-6148-4058-bf63-960fa35f3c61" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;consistent hash는 우리가 원한 session affinity를 정확히 만들어줬습니다. 같은 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;x-spark-session-id&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;는 늘 같은 pod로 갔으니까요. 문제는 affinity가 아니라 새 세션을 어디에 둘지였습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="62ca59c6-02b0-4bdf-825d-4803a54adbda" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;consistent hash는 오직 해시값으로만 pod를 정합니다. 그 서버가 지금 메모리를 얼마나 쓰는지, 무거운 쿼리가 몇 개 돌고 있는지는 전혀 보지 않습니다. 그래서 이미 바쁜 Spark Connect 서버에도 해시가 그쪽을 가리키면 새 세션을 계속 얹습니다. 한 서버는 터질 듯한데 옆 서버는 놀고 있어도, Istio 입장에선 그냥 균일한 백엔드 주소일 뿐 이 Spark 서버가 얼마나 바쁜지 알 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="380a360d-33e3-80e7-8511-de929de00345" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/a45f2475-64fa-4a9e-acd6-67d50cfdfbd3/n8-consistent-hash-limit.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="60aad9a6-e69e-491d-a5d8-c80328b3f1d9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;우리가 원한 건 두 가지였어요. 기존 세션은 원래 서버에 묶어두는 것, 새 세션은 서버 부하를 보고 할당하는 것. 범용 프록시의 로드밸런싱 정책은 이 둘을 동시에 만족하지 못합니다. consistent hash는 앞의 것만, Least request 같은 부하 기반 정책은 뒤의 것만 해주거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="9094fd8b-84d0-4e2b-bf69-e010e2b7d9ec" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;부하를 분산하려면, 단순한 주소가 아니라 Spark 서버의 상태를 아는 router가 필요했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803e-ac61-c4c71be5521c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="d8e35d6a-c62e-4f5b-bf80-bebd5b45a7a3" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 Gateway를 개발했어요&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="8f21858a-b497-4710-a32d-21a3c1378da8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;만들기 전에 기존 프로젝트부터 살펴봤어요. Kyuubi는 멀티테넌트 게이트웨이라는 방향이 같고 성숙한 프로젝트지만, 제공하는 인터페이스가 Thrift/JDBC(HiveServer2 프로토콜) — SQL Only입니다. 우리는 분석가와 파이프라인이 쓰는 DataFrame API를 그대로 서비스해야 한다는 요구사항이 확실했고, 그걸 표준 프로토콜로 제공하는 건 Spark Connect뿐이었어요. Kyuubi의 Spark Connect 프로토콜 지원은 아직 커뮤니티에서 논의가 진행 중이고요. 그래서 우리 요구에 맞는 대안이 없었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="81275711-fc19-433e-a815-dd579ecc8a39" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;결국 Spark Connect 서버의 부하를 이해하는 Gateway를 직접 만들었습니다.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 이 Gateway, 그리고 다음 편에서 다룰 테넌트의 생성·교체·삭제를 맡는 Controller — 이 둘을 묶어 우리는 Spark Connect Hub라고 부릅니다. 이번 편은 그중 트래픽을 받아 나누는 Data Plane, 즉 Gateway 이야기예요. 핵심은 새 세션을 가장 한가한 서버에 배치하는 것입니다. 그러려면 먼저 이 서버가 지금 얼마나 바쁜지 관측할 수 있어야 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="3a7645ac-e92e-452d-9d90-6b354132da1c" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;서버 부하를 어떻게 점수로 만드나&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="3676e285-7fe7-40ff-81b9-8c91437f4c69" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;Spark는 Driver마다 모니터링용 REST API를 열어둡니다. Gateway는 이걸 폴링해 세 가지 숫자를 읽어요. 지금 executor에서 돌고 있는 Task 수(active), 슬롯을 못 잡고 줄 서 있는 Task 수(pending), 그리고 이 서버가 동시에 굴릴 수 있는 Task 슬롯의 총량(maxTasks)입니다. maxTasks는 executor마다의 슬롯(≈ 코어 수)을 전부 더한 값, 곧 그 서버의 동시 처리 용량이에요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="a7f8b653-537b-4804-bb13-c913bd0a6cae" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;보는 건 메모리 사용량이 아니라 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;이 슬롯이 얼마나 꽉 찼고 얼마나 밀려 있나&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;입니다. 그래서 부하를 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;(active + pending) / maxTasks&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;로 잡아요 — 처리 중이거나 대기 중인 Task를 전체 슬롯으로 나눈 거죠. 슬롯이 다 차고 대기까지 쌓인 서버는 1을 넘고, 노는 서버는 0에 가까우니, 무거운 쿼리가 도는 서버를 집어내는 신호가 됩니다. 다만 폴링 스냅샷이라 측정할 때마다 출렁여서, 지수가중이동평균(EWMA)으로 다듬어 순간 스파이크가 아니라 그 서버의 평소 바쁨이 점수에 남게 했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="b27f2924-e188-44d7-8be6-367dc8e4c3b9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;여기에 보조 신호로 활성 세션 수를 더합니다. REST 폴링은 갱신에 지연이 있어, 짧은 시간에 새 세션이 몰리면 측정값이 갱신되기 전까지 전부 같은 한가한 서버로 쏠리거든요. 세션 수는 저장소에서 즉시 읽히니 배치하는 순간 바로 반영돼, 그 폴링 공백을 메워 줍니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="37c3d483-6cfc-46f8-a310-2ba761e6316c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;utilization을 지배적으로(0.9) 두고 세션 수는 보조로(0.1) 얹습니다. 점수가 같은 서버가 여럿이면 한쪽으로 쏠리지 않게 무작위로 고르고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="17a31547-f259-4967-b15c-c578cf9ec80d" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;세션은 한 번 정한 서버를 끝까지&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="9377ee68-1ba5-4a2e-a136-da549e14a9ee" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;새 세션은 위 점수로 배치하지만, 이미 자리를 잡은 세션은 부하와 무관하게 원래 서버로 보냅니다. 세션 상태가 그 Driver의 메모리에만 있으니 다른 데로 보내면 안 되거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="380a360d-33e3-806a-a655-dd9cd6fda673" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/5786899b-c9d9-4e95-8673-bf1c06c090a2/n9-gateway-two-rules.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="2f38c4fe-5e85-4c64-a4e1-eb424627d3ae" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;요청이 올 때마다 idle 타이머를 리셋하는 방식이라, 활발히 쓰는 세션은 계속 유지되고 한참 안 쓴 세션만 만료됩니다. 부하 인지 배치(새 세션)와 고정 affinity(기존 세션), 이 두 규칙으로 consistent hash가 못 하던 문제를 풀면서도 세션은 안전하게 지킵니다. 하나였던 Driver를 여러 대로 나눠 세션들이 한 SparkContext를 공유하지 않게 되었고, 새 세션은 그중 가장 한가한 서버로 갑니다. 이렇게 리소스 경합을 풀었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80c4-9c02-e3504b7df57e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="eb3824c7-70ce-4b86-a000-b31b0f1d779a" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;라우팅 상태는 어디에 있을까 — ServerPool·SessionStore&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="dcc63dfa-0805-4def-9654-542aadb2fc2e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;새 세션은 한가한 서버로, 기존 세션은 원래 서버로 — 이런 결정을 내리려면 Gateway는 두 가지 상태를 들고 있어야 합니다. 어떤 서버가 있나(ServerPool), 이 세션은 어디 붙었나(SessionStore). 둘 다 ‘풀’이지만, &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;누가 Redis에 쓰고, Gateway가 그걸 어떻게 들고 있는지&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;가 서로 다릅니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="381a360d-33e3-80cd-b69e-fa4da1e69e38" class="css-nv7vyi"&gt;&lt;div class="css-1vn47db"&gt;&lt;ul class="css-uswsmm"&gt;
&lt;li id="a2fa8dff-1255-406e-9207-cfddb30aea53" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;ServerPool — 어떤 서버가 살아있나.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 서버 목록을 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;healthy&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;/&lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;draining&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;/&lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;generation&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;과 함께 들고, 앞서 본 부하 인지 라우팅이 여기에서 일어납니다. 후보는 healthy하고 draining이 아닌 서버, 그중 가장 최신 세대로 좁힙니다. (세대로 좁히는 게 무중단 교체의 핵심인데, 다음 편에서 다뤄요.) 다만 이 풀의 원본을 Gateway가 직접 만드는 게 아닙니다. Controller가 Redis에 올려둔 서버 상태를 각 Gateway가 폴링해 자기 메모리에 캐싱해 둔 거예요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="46e1ca35-3d6d-4016-b2f4-42e3a2e5299b" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;SessionStore — 이 세션은 어느 서버에 붙었나.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 새 세션을 배치하는 순간 매핑을 기록하고, 이후 같은 세션은 이 기록을 따라 같은 서버로 갑니다. 이건 Gateway가 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;Redis&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;에 직접 씁니다. Gateway도 여러 대라, 앞단 로드밸런서가 요청을 아무 replica로 보내도 모두 같은 Redis를 보고 같은 서버로 보내야 하거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/aside&gt;&lt;p id="98b78eaf-f432-467f-af64-7c7cf59569ef" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;정리하면, 세션 매핑은 Gateway가 Redis에 직접 써서 모든 Gateway가 공유하고, 서버 목록은 Controller가 Redis로 흘려준 걸 각 Gateway가 메모리에 캐싱해 들고 있습니다. 그런데 ServerPool은 채우는 주체가 Gateway가 아니라고 했죠. 그 이야기를 할 차례입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8069-9c06-d6f08c31e0a2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="76f4ee58-6595-4c66-84b0-9c731cfcf9e1" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;Gateway는 Kubernetes를 몰라도 돼요&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="cba5fa1b-8af3-4db5-a3c9-05a2dce9726e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;살아있는 서버 목록(ServerPool)을 채우려면, 보통은 각 Gateway가 Kubernetes API를 직접 watch하게 만듭니다. 하지만 그러면 Gateway를 늘릴 때마다 watch가 replica 수만큼 API 서버에 붙고, Data Plane인 Gateway가 K8S 접근 권한과 informer까지 떠안아야 합니다. 무엇보다 트래픽을 받는 Data Plane이 Control Plane에 묶이는 게 안정성 면에서 좋지 않습니다 — Controller나 K8S API가 흔들리면 라우팅까지 같이 흔들리니까요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="380a360d-33e3-8046-abc7-d8b3cec14512" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/fa3dc6fb-5997-47ff-95ea-d735f87c9ea3/n11-gateway-no-k8s.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="5e11b84f-d486-41d5-bd7b-897f048cbed6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 K8S를 보는 일은 Controller 하나에 몰아줬습니다. Controller는 Kubernetes Operator로 구현했어요. 단일 Spark Connect 서버의 라이프사이클은 이미 Spark Operator가 다루는 영역이라, 우리는 그 위에 한 계층을 더 올렸습니다. Controller는 서버를 직접 만들지 않고, 이 operator들이 관리하는 서버 리소스를 여러 대 묶음으로 선언·조율하죠 — 즉 우리가 푼 문제는 ‘서버 한 대를 어떻게 띄우나’가 아니라 ‘여러 대를 한 묶음으로, 무중단으로 어떻게 굴리나’입니다. 복제본 수 유지, 스펙 변경 시 Blue-Green 교체, 스케일 인/아웃 시 drain이 여기 들어갑니다(Controller의 자세한 동작은 다음 편에서 다룹니다). 이렇게 Controller가 파악한 서버 상태를 Redis instance store에 Publish하면, Gateway는 K8S API를 전혀 보지 않고 이 Redis만 짧은 주기로 폴링해 ServerPool을 맞춥니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="06a75cac-6932-40ea-b88d-74aac27c0c76" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;폴링할 때마다 Instance store와 ServerPool을 비교해, 새 서버는 더하고 사라진 서버는 빼면서 그 서버에 묶인 세션 매핑까지 정리합니다. 살아있는 서버는 Controller가 주기적으로 갱신하고, 사라진 서버는 TTL이 지나 저절로 빠집니다. 그래서 서버가 생기든 없어지든 Gateway는 다음 폴링이면 따라잡습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="ce40cb20-0267-47bc-ba7d-3d1f69782ab5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;덕분에 Gateway를 아무리 늘려도 K8S API 부하는 그대로고, Controller가 잠시 죽어도 Gateway는 마지막 ServerPool로 계속 라우팅합니다. Data Plane은 Redis만 보면 되니 책임이 깔끔하게 나뉩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80f7-b5d1-c8458f41d1ee" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="f5ec89a7-c59c-48e8-ac72-2ba84dcf6d0a" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;마치며&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="b0e483e4-8f34-48ad-a290-daacb0f92c14" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;정리하면, Spark Connect는 Driver를 미리 띄운 서버로 옮겨 가벼운 클라이언트와 즉시 세션을 얻는 대신, 서버 하나에 세션이 몰려 단일 장애점(①)과 리소스 경합(②)을 안게 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="1442f155-fffc-4776-b0cd-092f9f2846b7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;먼저 서버가 죽는 일을 줄이려고, 멀티세션에서 깨지는 Spark 기본값을 다시 잡았습니다. 앞에서 짚은 값들에, Driver heap을 함께 나눠 쓰며 위험을 키우는 몇 가지를 더해 아래에 모았어요. 기존 Spark 운영에선 건드릴 일 없던 값들이라, Spark Connect를 운영한다면 여기부터 점검해 보면 좋습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div data-table-wrapper="true" class="css-1m7s5mg"&gt;&lt;div role="table" class="css-uznrcw"&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;설정&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;기본값&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;가이드&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.driver.maxResultSize&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;1g&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;쿼리 단위로 한도가 적용되므로, 동시 쿼리 수를 감안해 보수적으로 설정&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.driver.memory&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;1g&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;모든 세션이 하나의 Driver heap을 공유하므로, 동시 세션 수를 고려해 여유 있게 설정&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.driver.memoryOverhead&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;max(384m, 0.1×driver)&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;off-heap·네이티브 메모리가 한도를 넘으면 driver pod가 OOMKill되므로, heap과 함께 여유 있게 설정&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.executor.failuresValidityInterval&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;(none)&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;장기 실행 서버에 실패 기록이 끝없이 쌓이지 않도록 주기적으로 비움&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.executor.maxNumFailures&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;max(3, 2×executor)&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;executor 실패가 전 세션에 걸쳐 합산돼 서버를 종료시키므로, 사실상 무한대로 두어 비활성화&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.sql.autoBroadcastJoinThreshold&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;10m&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;broadcast 해시 테이블이 공유 Driver heap에 빌드되고 동시 broadcast가 합산되므로, 키울 때는 압축 해제 후 실제 크기와 동시 쿼리 수를 함께 고려&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.stage.maxConsecutiveAttempts&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;4&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;
&lt;span class="css-1mjnzsq"&gt;shuffle fetch 실패로 stage가 통째로 재시도되는 것을 끊는 한도라, &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;task.maxFailures&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1mjnzsq"&gt;와 짝으로 워크로드에 맞춰 조정&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.task.maxFailures&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;4&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;문제 쿼리가 executor를 오래 붙잡지 않도록 워크로드에 맞춰 조정&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;spark.ui.store.path&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;(none)&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;Job·Stage·Task·SQL 실행 UI 상태가 모두 Driver heap의 in-memory store에 쌓이므로, 디스크(RocksDB)로 분리&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p id="daff3b4c-1258-470e-bca9-f4a45618069f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래도 막지 못하는 장애는 여러 Replica로 받고, 그 앞에 Spark Connect Hub의 Gateway를 둔 뒤 새 세션은 한가한 서버로·기존 세션은 원래 서버로 보냈습니다. 덕분에 장애 범위는 replica 한 대로 줄고(①), 경합도 풀었죠(②). &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="1f3aac53-f90f-4a50-88f6-6580bdd686f7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;다음 편에서는 고정된 스케일(③)과 테넌트 격리를 맡는 Control Plane·무중단 Blue-Green 교체를, 3편에서는 인증·인가로 사용자를 식별해 각자 허용된 범위 안에서만 데이터에 접근하도록 만드는 이야기를 다룹니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="37aa360d-33e3-8026-be35-e81d764971f2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/spark-connect-on-kubernetes-1</id>
    <link href="https://toss.tech/article/spark-connect-on-kubernetes-1"/>
    <summary type="html">Spark Connect 서버에 세션이 몰리면, 무거운 작업이 다른 사용자까지 느리게 만들고 그 서버가 죽는 순간 모두가 실패합니다. 이 문제들을 어떻게 풀었는지 공유합니다.</summary>
    <title>Spark Connect on Kubernetes #1: 견고한 Spark Connect 만들기</title>
    <updated>2026-06-19T16:35:00+09:00</updated>
    <dc:date>2026-06-19T16:35:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/32f69388-1094-4f0d-8945-93c5f66b8826/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/81e23b26-a80e-4ba8-9f88-f9ecdeef1906/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/70ac1ab0-9bbb-4c84-a077-dc0f6b341292/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/8cdf6de5-7322-4837-9443-673a41ce2ab0/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/efe1bdfe-213f-40a8-a66e-5df29a46b3f2/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/3a2701db-68dc-434b-893d-20a9acddde1e/image.png"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;h2 id="383a360d-33e3-80b2-afb3-dbaca640bc06" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;TW가 제품 오너로 일한다는 것&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="383a360d-33e3-80b5-9309-e4c55eb1740d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;앞서 토스의 Technical Writer(이하 TW)가 하는 일을 네 가지로 나눠 소개했어요. 그중 첫 번째가 '제품을 만든다'였죠. TW가 제품을 만든다는 게 어떤 의미인지, 제 이야기부터 풀어볼게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80dd-9cab-d087c6adaab4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;저는 지금 Knowledge System Team이라는 제품 팀의 리더로 일하고 있어요. 개발자·디자이너·TW와 함께 제품의 방향을 잡고, 로드맵과 우선순위를 정합니다. 사용자를 직접 인터뷰해 인사이트를 팀에 가져오고, 기능을 기획하고, AI 도구로 직접 만들기도 하고요. 단순히 문서와 관련된 요구사항을 전달하는 사람이 아니라, 제품에 대한 판단을 내리고 실제로 만드는 메이커로 일하고 있는 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-809e-a615-c9ef29a8352e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;TW가 왜 제품을 만들고 있을까요? 이 제품의 핵심이 문서와 지식을 다룬다는 점 때문인데요. TW들은 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;왜 어떤 문서는 읽기가 어려운지, 무엇이 좋은 문서인지, 어떤 구조여야 AI가 잘 활용할 수 있는지&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 같은 질문들을 가장 오랫동안 고민하며 기준을 세워왔어요. 그래서 이를 녹인 제품을 만드는데 가장 중요한 인사이트를 제공할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="384a360d-33e3-806c-962a-e2597dbe33e1" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/32f69388-1094-4f0d-8945-93c5f66b8826/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-8011-bb1c-edfb2289f2ac" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;저희가 만들고 싶은 끝그림은 TW의 전문성이 하나의 제품으로 확장되어 문서와 실제 업무 워크플로우가 연결되고, 일만 하면 지식이 자동으로 쌓이고, 누구나 쉽게 그 지식에 접근하고 활용하는 모습이에요. 그 목표를 위해 만들고 있는 제품을 소개드릴게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="383a360d-33e3-807f-8d78-df2e9f108cde" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;TW의 고민이 담긴 제품, ‘토독(todoc)’&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="383a360d-33e3-8062-963e-c9b36baf752e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문서화 도구가 오랫동안 지속적으로 작동하고, 다른 조직으로도 스케일업을 하려면 어떻게 해야 할까요? 오랜 고민 끝에 작년 10월, 사내 문서 플랫폼 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;토독&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;(todoc)을 런칭했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80a1-b580-e5d3c94bca5d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;작년 10월 베타 오픈 공지를 올리자마자 "지금 바로 써보고 싶어요", "드디어 원하던 문서 플랫폼이 나왔어요" 같은 긍정적인 반응이 많아 놀랐는데요. 이미 문서화를 하고 있는 조직에서도, 아직 문서가 잘 정리되지 않은 조직에서도 AI로 쉽게 연결할 수 있고, 팀의 지식을 쉽게 쌓을 수 있는 플랫폼이 절실했던 것으로 이해했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8013-83b0-e27a315d56a8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;반년이 지난 지금 토독에는 약 500개 이상의 문서, 40,000개 이상의 유효한 페이지가 쌓였고, 매달 1000명 이상이 사용하고 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-8042-85ff-d14728984111" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/81e23b26-a80e-4ba8-9f88-f9ecdeef1906/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-80df-a162-e5e798be3edb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;GitHub이나 문서 툴을 사용하면 되는데 왜 새로운 제품을 만들었을까요? 기존의 내부 문서들은 몇 가지 문제가 있었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-806a-89b0-e7b124200c22" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;먼저 기존에 정적 사이트 생성기(SSG, Static Site Generator)로 만들어져 있는 문서는 비개발자가 사용하기는 어려웠어요. 문서 하나를 고치려면 저장소를 클론해, 마크다운을 작성한 뒤, PR을 올려 리뷰를 받는 등의 과정이 필요한데요. 개발자에게는 익숙해도, 디자이너나 PM에게는 문서를 쓰기도 전에 포기하게 만드는 허들이었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80b6-b98c-e17ba32c148c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그리고 기존 문서 툴에는 너무 많은 메모와 '쓰레기 지식'들이 누적되어 있었어요. 누가 언제 왜 썼는지 알 수 없는 내용들, 이미 바뀐 정책을 가리키는 낡은 문서들, 쓰다 만 메모들 등등… 다들 경험해 보신 적 있을 거예요. 이런 상태에서는 기존 문서 툴 자체가 문서 부채라서 양질의 지식을 판별하고 관리하는 것이 거의 불가능해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8094-9912-e3bab4799501" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;마지막으로 이렇게 지식들이 각자 혹은 팀별로 선택한 도구에 파편화되어 있었어요. SSG로 만든 문서에, 각종 문서 툴에, 코드에, 협업 메신저 속 논의에, 누군가의 머릿속에 흩어져 있었죠. 이렇게 흩어진 소스를 한곳에 모으지 않으면 조직의 지식이 잘 쌓일 수도, 활용할 수도 없을 거라고 판단했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80ef-bb98-d6e39d8b37dc" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 토독은 네 가지를 핵심 가치로 잡았어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8089-9760-d995d1c341d1" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;1. 누구나 문서를 쉽게 쓸 수 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80d9-a648-ea5a82fe78d4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문서화의 모든 장벽을 없앴어요. 토독에서 누구나 곧바로 문서를 만들고 고칠 수 있고, GitHub, 문서 툴, 사내 메신저 등 어떤 소스로 시작하든 토독으로 연결할 수 있어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80c5-97a1-ee6b0c258ee4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;2. 토독에 있는 지식은 AI로 쉽게 활용할 수 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80f3-bda7-f47a5e7c8957" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;잘 모으고 관리한 지식은 결국 AI가 쓰기 위한 것이기도 해요. 토독에 문서를 쓰면 AI 활용이 무척 쉬워요. 팀 별로 사용하는 봇과 연결해서 쓸 수 있고, API/CLI/MCP 모두 자유롭게 사용할 수 있죠. 그래서 각 팀에서 요청 봇이나 제품 스펙을 정리하기 위한 용도 등으로 다양하게 활용하고 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-80c5-9cd4-c40c5c917921" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/70ac1ab0-9bbb-4c84-a077-dc0f6b341292/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;figure id="383a360d-33e3-80d6-a037-cecc8fed7c04" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/8cdf6de5-7322-4837-9443-673a41ce2ab0/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;figure id="383a360d-33e3-8045-9279-f62511d1303b" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/efe1bdfe-213f-40a8-a66e-5df29a46b3f2/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-80ec-9eec-dc917098ca51" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;3. 모든 사내 지식을 한 곳에 모아 단일 진실 공급원(SSoT, Single Source of Truth) 역할을 해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8033-ae72-f970212b7ec0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토독은 흩어진 소스들을 한곳으로 연결해서 완결된 문서를 만들고, "이건 어디서 찾지?"를 고민할 필요가 없게 만들어요. 무엇이 지금도 유효한 최신 지식인지 한곳에서 판별할 수 있으니, 토독이 조직의 단일 진실 공급원 역할을 하는 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80e7-8859-df444f25b779" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;4. 확장 가능한 구조가 된다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80d7-89be-dd466782e69c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;어떤 조직이 문서화를 하고 싶을 때 툴을 선택하거나 새로 구축하는 게 아니라, 이미 돌아가는 토독 위에서 시작하면 돼요. 하나의 플랫폼 위에서 각자의 문서 공간을 가질 수 있죠. 지금까지는 문서를 쓰려면 팀마다, 챕터마다 따로 도구를 정해야 하고 인프라를 세팅하거나 관리해야 하는 공수가 들었어요. 토독이 생겼기 때문에 이제 팀원들은 문서를 쓰는데만 집중하면 돼요. 이런 구조를 이제 계열사로도 확장하고 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="383a360d-33e3-80a0-9048-c8ccc964b13d" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;남은 과제들&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="383a360d-33e3-800a-adb7-f27f958b6dab" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문서의 진입 장벽을 낮추면 많은 사람들이 문서를 쉽게 쓸 수 있지만 동시에 문서의 질은 유지하기가 힘들다는 문제도 생깁니다. 그래서 "어떻게 문서의 질까지 유지할까"도 TW들이 자주 하는 고민인데요. 이전에는 이 고민을 TW가 직접 문서를 리뷰하고, 낡은 문서가 없는지 확인하면서 해결했습니다. 토독에서는 이런 TW의 일을 TW가 판단해온 "좋은 문서의 기준"을 바탕으로 자동화해서 AI 교정 기능이나 문서 봇을 통한 초안 자동화를 제공하기도 했습니다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80e6-9ca1-cd5b9f48eb4d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그치만 이런 기능들은 여전히 사람들이 직접 문서를 쓴다는 것을 전제로 합니다. 그리고 사용자들을 봤을 때 저는 이것으로는 충분하지 않다고 느꼈어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80b0-b560-fcc811287d95" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;'문서를 쓰겠다'고 따로 마음먹고 완성하기까지는 많은 노력과 시간이 들어요. 그래서 일을 하다 보면 자연스럽게 문서가 생기게끔 하고 있어요. 토독은 사내 메신저에서 오가는 의사결정, 코드, 논의를 자동으로 문서로 만들어줘요. 코드 변경, 의사결정 이후 논의 모니터링을 통해 누군가의 의지에 기대지 않아도 문서가 갱신되는 구조도 만들고 있고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-8084-aa9b-c6a18ac06318" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/3a2701db-68dc-434b-893d-20a9acddde1e/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-8000-864a-f19b1272179b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;단순한 정보 수집과 문서 생성을 넘어, 무엇이 지금도 유효한 지식인지를 가려내는 것이 문서의 핵심이라고 생각해요. 정책과 실제 반영된 코드가 어긋나지 않는지, 이 지식이 실제로 쓰이고 있는지, 얼마나 최신인지 까지 토독 시스템 위에서 풀어 나가고 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="383a360d-33e3-802a-a191-d2e7e3d772bd" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;전문성의 확장과 이동&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="383a360d-33e3-8002-8959-ce59629b28e6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;예전에 TW에게 중요한 역량이 좋은 문서를 직접 잘 쓰는 능력에 가까웠다면, 이제는 좋은 문서가 반복해서 나오도록 시스템을 설계하는 능력을 중심으로 일해야 한다고 생각해요. TW가 쌓아온 전문성은 사라지지 않고 다음과 같이 시스템 속에 녹아있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul class="css-uswsmm"&gt;
&lt;li id="383a360d-33e3-80ff-9a8e-eef728beca50" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"왜 문서가 안 읽히는가"를 고민하던 경험은 → &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;누구나 쉽게 쓰고, AI가 잘 읽는 문서의 기준&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이 됐어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="383a360d-33e3-80bd-a133-c9ba1e7a3926" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"좋은 문서란 무엇인가"에 대한 판단은 → &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;AI 교정과 자동 리뷰의 기준&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;으로 옮겨갔고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="383a360d-33e3-8042-af4b-c66d7399d7cd" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문서가 낡았는지 확인하고, 유효한 지식을 판단하는 역량은 → &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;무엇이 지금도 유효한 지식인지 판별하는 시스템&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이 됐습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="383a360d-33e3-80b9-869a-c79967472b0f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 변화 속에서 저희가 하는 일은 명확해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol class="css-hokoge"&gt;
&lt;li id="383a360d-33e3-8018-a7c2-e4fce772e510" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;흩어진 지식이 모일 곳을 만든다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="383a360d-33e3-8093-801b-caf13c83d90e" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;좋은 문서의 기준을 정의한다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="383a360d-33e3-800d-bf58-cef03955a678" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그 기준을 사람의 판단이 아니라 시스템으로 옮긴다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="383a360d-33e3-8017-a4b1-f6d3f04eb8a3" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;일하는 과정 속에서 문서가 자연스럽게 만들어진다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="383a360d-33e3-8094-8344-d522667f45ef" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그 위에서 지식이 스스로 갱신되게 한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr class="css-1ifza5r"&gt;
&lt;p id="383a360d-33e3-8008-aee5-fbfcadabebbe" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토독이 모든 과제를 마친 뒤, 제품 팀 리더이자 TW로써 저의 하루는 이런 모습입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote id="384a360d-33e3-8079-9eca-e8637a193361" class="css-2sk6rv"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;1달 넘은 문서 확인해 달라는 공지를 할 필요가 없어졌다. &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;토독이 낡은 문서를 감지해서 담당자에게 직접 알림을 보내고 개선점을 제안하고 있었다. &lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;누가 챙기지 않아도 문서는 신뢰할 수 있는 상태였다.

더 이상 프로젝트 관리 도구를 직접 업데이트하지 않았다. 팀이 일하면서 남긴 흔적들이 이미 정리되어 있었다. &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;주연님은 다음 방향을 고민하는 데만 시간을 썼다.

&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;릴리즈마다 썼던 공지, 문의마다 반복했던 설명들이 남아있어서 새로 온 팀원도, 처음 연동하는 팀원도 같은 질문을 다시 하지 않았다. 이렇게 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;한 번 일하면 흔적이 남아 모두의 업무 실행 시간이 줄었다.

&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;어느 날 주연님은 노트북을 열었다가 조용히 닫았다. 할 일이 없었다. 토독이 너무 잘 돌아가고 있었다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p id="383a360d-33e3-80c2-8df0-d239dbc9ab40" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이렇게 토스의 Technical Writing Chapter는 TW의 전문성, 기준 자체가 시스템화 되는 것에 집중하고, 나아가 지식 관리 거버넌스를 만들어서 조직마다 문서화를 잘 할 수 있게 만들어 두고 다음 일을 하러 갈 예정입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8061-ac32-d427be29610e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/technical-writing-2</id>
    <link href="https://toss.tech/article/technical-writing-2"/>
    <summary type="html">Technical Writer의 고민과 전문성을 '토독'이라는 제품으로 만들면서, 기존의 전문성을 더 확장하는 과정을 담았습니다.</summary>
    <title>2. 전문성 밖으로 나아가기</title>
    <updated>2026-06-19T11:01:00+09:00</updated>
    <dc:date>2026-06-19T11:01:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/270b98b2-b315-4c45-be6e-c3b911eb99cd/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/1ab8dff9-dd40-4d21-acb5-a0a259471e87/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/e7fb7b6f-64d9-413b-b9e1-666cfdf06da7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4.23.01.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/2a9728bd-6bda-4ccf-bd36-b1f7c3e5a94d/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/d96ae646-ca67-4a12-b33f-87d938db261b/image.png"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="383a360d-33e3-8038-a450-cc8f2aa06b99" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;안녕하세요, 토스 Technical Writing Chapter Lead 한주연입니다. 이번 시리즈에서는 토스의 Technical Writer(이하 TW)들이 어떻게 '문서를 쓰는 사람'에서 '조직의 지식 시스템을 설계하는 사람'으로 일을 넓혀왔는지 이야기해보려고 해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-801a-9d7f-d6f62725e0c5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr class="css-1ifza5r"&gt;
&lt;p id="383a360d-33e3-805b-a6a5-e916748a81b9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"이거 왜 이렇게 되어 있나요?" 회사에서 일하다 보면 하루에도 몇 번씩 듣고, 또 묻는 질문이에요. 코드를 짠 사람의 기억을 함께 더듬거나, 1년 전 업무 메신저 스레드까지 뒤져가며 맥락을 찾으신 적 많으실 거예요. 심지어 이미 사람이 자리를 비우거나 회사를 떠나서 답을 얻을 수 없는 경우도 있죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8094-80c7-c2f7aafc1759" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;특히 요즘은 AI에게 일을 맡기다 보면 이 문제를 더 자주 느끼실 거예요. AI는 일반적인 지식은 잘 알고 있지만, 우리 조직만의 맥락과 히스토리는 모르기 때문에 매번 맥락과 정보를 넣어줘야 해요. 흔히 코드가 SSoT(Single Source of Truth)라고들 해요. 그런데 코드에는 '결과'만 남아요. 무엇을 하는지는 적혀 있어도, 왜 이렇게 짰는지, 어떤 결정을 거쳐 여기까지 왔는지는 빠져 있죠. 주석 하나 없는 코드 앞에서 한참 헤매본 경험, 다들 있으실 거예요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80eb-9b1b-e750abd50fc9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;저는 그래서 문서화가 여전히 중요하다고 생각해요. &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;진짜 SSoT는 코드와, 그 코드를 둘러싼 맥락이 함께 있어야 비로소 완성됩니다.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 코드가 왜 그런지는 결국 우리가 알려줘야 하죠. AI에게 일을 시키려면, 우리가 아는 걸 먼저 어딘가에 남겨야 합니다. 그래서 Technical Writing Chapter는 이 부분을 채우기 위한 일을 하고 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80be-95ba-eb7cedf58667" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그런데 단순히 이 맥락을 채우기 위한 문서를 쓰는 것이 저희의 일은 아닙니다. 제가 처음 토스 커뮤니티에 합류했던 5년 전과 지금을 비교해 보면, TW가 하는 일은 많이 달라졌습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-8015-89b2-d3adb9d39f75" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/270b98b2-b315-4c45-be6e-c3b911eb99cd/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-802b-aacd-fb0dc7d1c5dd" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;또, 일의 목표도 달라졌습니다. 올해 목표는 사람이 문서를 직접 쓰지 않아도 지식이 쌓이게 만드는 것입니다. 그리고, &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;Technical Writing Chapter의 궁극적인 목표는 사라지는 것입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80c8-b30e-ca0eddb5ae78" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;TW를 떠올렸을 때 어떤 일을 할 거라고 생각하셨나요? 사실 저는 TW가 AI에게 가장 먼저 대체될 거라고 생각했었는데요. 제 예상과는 반대로 할 일이 더 넓어지고 많아진다고 느낍니다. 기술 문서를 쓰는 역할을 하던 TW가 어떻게 위와 같은 일을 하고, 이런 목표를 가지게 됐을까요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="383a360d-33e3-8035-9bbd-d1e005cecb94" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;문서를 쓰는 일에서, 직접 찾아가는 방향으로&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="383a360d-33e3-8054-84a2-dcb90e9dd10a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;제가 사내 문서화를 처음 시작했을 때 가장 먼저 했던 일은 프론트엔드 챕터의 온보딩 문서 만들기였어요. 그런데 내부 문서를 만들면서 계속 마음에 걸리는 게 있었어요. 저는 Technical Writing의 목표가 글을 잘 쓰는 게 아니라 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;독자가 문제를 해결하고 목표를 이루도록 돕는 것&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이라고 생각하거든요. 그런데 문서가 아무리 좋아도, 사람들은 필요한 것만 찾지 처음부터 끝까지 읽진 않습니다. 사실 저조차도 그렇고요. 그래서 문서를 쓴 뒤 링크를 던지는 것 말고, 어떻게 하면 사람들이 이 내용을 실제로 활용하게 할지를 고민하게 됐어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80bd-970f-c537b68ae60b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;고민하다 만든 게 ‘&lt;/span&gt;&lt;a target="_blank" rel="noreferrer noopener" class="css-iynyr0" href="https://toss.tech/article/toss-frontend-ai-docs"&gt;박씨’라는 챗봇&lt;/a&gt;&lt;span class="css-1kxrhf3"&gt;이었어요. (*참고: &lt;/span&gt;&lt;a target="_blank" rel="noreferrer noopener" class="css-iynyr0" href="https://www.youtube.com/watch?v=zlXsomDPQ_U"&gt;TMC25 - 100번 실패하고 살려 낸 문서 시스템&lt;/a&gt;&lt;span class="css-1kxrhf3"&gt;) 사람들이 매일 쓰는 메신저와 IDE 안에서, 대화하듯 물어보면 기존 문서를 근거로 출처까지 달아 답해주는 챗봇이에요. 지금은 많은 곳에서 익숙해진 것처럼 문서를 찾아오게 하는 대신, 문서가 사람들이 일하는 자리로 찾아가게 만든 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-80bc-80f7-ebded3aaf1f5" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/1ab8dff9-dd40-4d21-acb5-a0a259471e87/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-8055-ab45-e9df75b4209b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;흥미로운 건 그다음이었어요. 문서를 쓰는 것도 읽는 것도 관심이 없었던 팀원들이 찾아오기 시작했어요. "우리 챕터도, 우리 조직도 이런 걸 만들고 싶다"고 하면서요. 조직의 크기가 커지면서 다들 반복되는 질문에 답하는 데 지쳤고, 암묵지를 사람이 아니라 시스템에서 얻고 싶어 했어요. 마침 AI가 빠르게 발전하면서 "AI에게 일을 시키려면 문서가 필요하다"는 흐름까지 더해졌죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80f0-a52d-cefaf2ff2c46" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;오랫동안 귀찮은 일 취급받던 문서가 갑자기 모두가 원하는 것이 된 게 신기하기도 했습니다. 이런 흐름 속에서 저는 팀원 모두가 쓸 수 있는 지식 시스템 제품을 만들기 시작했습니다. 이 제품은&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 다음 글&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;에서 자세히 소개할게요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-8048-9f7c-ef80a511d940" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/e7fb7b6f-64d9-413b-b9e1-666cfdf06da7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4.23.01.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;h3 id="383a360d-33e3-802f-9842-dcebcae1ecc1" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;문서에서 지식 시스템으로&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="383a360d-33e3-8028-9c5e-de47ad5316a2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그때부터 TW들은 직무에 갇히지 않고 일을 넓혔어요. TW는 이제 문서를 쓰는 사람이 아니라, 위와 같이 각 조직에 맞는 지식 시스템을 설계하는 사람이 되어야 한다고 판단했어요. AI가 점점 더 많은 일을 하는 지금, 조직에 흩어진 지식과 암묵지가 문서화되는 게 정말 중요하다는 생각도 들었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80be-a724-e60cec8b5f2b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;잘 만든 지식 시스템은 두 가지 가치를 가집니다. 위로는 조직 전체의 생산성을 끌어올리고, 아래로는 모든 팀원이 쉽고 빠르게 적응할 수 있도록 하방을 막아줍니다. 조직이 커질수록 질문이 늘고 커뮤니케이션 비용이 급증하기 때문에 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;잘 설계된 지식 시스템은 우리가 일하는 속도와 품질을 지켜주는 중요한 인프라&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="383a360d-33e3-80fb-ba27-e2751faa1591" class="css-nv7vyi"&gt;&lt;h4 class="css-123co55"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;지식&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이란 특정한 맥락에서 개인이나 조직이 문제·상황을 이해하고 더 나은 결정을 내려 행동하게 하는 검증된 정보예요. 맥락에 맞게 검증되어 있어야 지식이에요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="383a360d-33e3-8075-8c3e-f9bafcd14675" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;지식 시스템&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;은 이 지식을 한곳에 모아, 필요한 사람과 AI에게 제때 가닿게 하는 구조예요. 코드·대화·배포처럼 곳곳에 흩어진 지식을 단일한 원천(Single Source of Truth)으로 모으고, 사람이 읽을 수 있을 뿐 아니라 AI가 이해할 수 있도록 구조화해서, 질문과 자동화로 바로 활용되게 만드는 것이죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-80df-908d-cb10c84a86ee" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/2a9728bd-6bda-4ccf-bd36-b1f7c3e5a94d/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;
&lt;/div&gt;&lt;/aside&gt;&lt;p id="383a360d-33e3-8028-b3c7-ece32118d26e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;지금 토스의 Technical Writing Chapter가 하는 일은 크게 네 파트로 나뉩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80de-85c9-db7b049b7e05" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;첫 번째, &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;제품을 만들어요.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 사내 지식을 관리하는 플랫폼 '토독'을 직접 만들고 운영하는 팀을 이끌고 있어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8085-80ee-d15e778264a5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;두 번째, &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;각 조직에 들어가&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;문서화를 주도해요.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 각 조직에 맞는 방식으로 흩어진 지식을 모으고, 활용도를 극대화합니다. 조직마다 필요한 지식 시스템의 성격이 달라서 접근 방식도 달라져요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8093-81a8-cebe6225410c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;세 번째, 이 과정에서 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;사람이 하는 Technical Writing을 없앱니다.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; AI 워크플로와 자동화로 모두가 비슷한 품질로 문서를 쓰고 리뷰 받을 수 있게 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-8075-a934-fa084a8244c0" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/de7f0294-9359-499e-9c11-ff2ccf6bfaa4/%E1%84%92%E1%85%AA%E1%84%86%E1%85%A7%E1%86%AB_%E1%84%80%E1%85%B5%E1%84%85%E1%85%A9%E1%86%A8_2026-02-04_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11.36.39_(1)_(1).mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-80fd-b6a7-d8b96e7e4341" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="383a360d-33e3-8041-9a3d-e6ebde4111bb" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/d96ae646-ca67-4a12-b33f-87d938db261b/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="383a360d-33e3-8061-bc7a-d7854b8ea716" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;마지막으로, &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;토스의 문서화&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;문화를 만듭니다.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 전 커뮤니티 대상으로 AI가 잘 읽을 수 있는 문서를 쓰는 방법 같은 주제로 세션을 열어요. 또 조직별로 문서화 길드와 지식 커미티를 운영하며 토스 곳곳에서 지식을 다루는 방식 자체를 바꿔 나가고 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="383a360d-33e3-80ac-b888-eff2647c0ea7" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;이 시리즈에서 다룰 이야기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="383a360d-33e3-8055-b903-c97a5c183347" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 시리즈에서는 앞으로 이런 이야기를 들려드릴게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="381a360d-33e3-80da-9c78-ddf6fed60534" class="css-nv7vyi"&gt;&lt;div class="css-1vn47db"&gt;&lt;ul class="css-uswsmm"&gt;
&lt;li id="381a360d-33e3-8056-96de-da326cb15d88" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;a target="_blank" rel="noreferrer noopener" class="css-wi4a2c" href="https://toss.tech/article/50655"&gt;전문성 밖으로 나아가기&lt;/a&gt;&lt;span class="css-q3ktjb"&gt;: &lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;테크니컬 라이팅의 전문성이 어떻게 '토독'이라는 제품으로 녹아들었는지 이야기해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-80a0-99bc-c25e98d0b52f" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;우리 팀의 문서화는 왜 실패할까? / 같은 문제 다른 해법 (&lt;/span&gt;&lt;span class="css-q3ktjb"&gt;coming soon&lt;/span&gt;&lt;span class="css-q3ktjb"&gt;): &lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;거의 모든 회사가 겪는 "지식이 안 쌓인다"는 문제에 어떻게 접근했고 무엇을 배웠는지 두 편의 인터뷰로 공유해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-8029-ae76-c5b809b6c67f" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;Technical Writer, 사라질 결심 (coming soon): &lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;테크니컬 라이터의 일을 어디까지 자동화할 수 있는지, 저희가 만든 것들을 공유해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-80db-9651-fd9f1de45f9b" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;Knowledge 전문가로 거듭나기 (coming soon): &lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;챕터 없이도 조직이 스스로 지식을 생산·관리하게 만드는, 마지막 목표로 가는 고민을 나눠요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/aside&gt;&lt;p id="383a360d-33e3-80ee-b3e6-fb530144a7e6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;저희 직무의 이름은 여전히 ‘Technical Writer’지만, 실제로 하는 일은 조직의 지식 인프라를 설계하는 것에 가까워요. 정해진 직무를 수행한 게 아니라, 풀어야 할 문제를 따라가다 직무를 새로 그린 거죠. 그러다 어느새 업계 어디에도 없는 모습이 됐습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-808c-bbcd-e85cb4f3fcd4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그리고 이건 Technical Writing만의 이야기가 아니라고 생각해요. AI가 모든 직군의 일을 다시 정의하는 지금, 자기 직무의 외연을 스스로 넓히는 일은 누구에게나 열려 있는 선택지니까요. 한 명이었던 챕터가 셋이 되고 더 많은 동료를 찾고 있는 지금, 저희 이야기를 하나씩 풀어볼게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8081-a0d4-fb06b264080a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-8033-a187-e5e9d4a32816" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80fd-bd46-c4d13d4eea68" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-80c3-aec9-d8ff3d720c5c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="383a360d-33e3-803e-80fc-e111a1779231" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/technical-writing-1</id>
    <link href="https://toss.tech/article/technical-writing-1"/>
    <summary type="html">토스의 Technical Writer들이 어떻게 '문서를 쓰는 사람'에서 '조직의 지식 시스템을 설계하는 사람'으로 일을 넓혀왔는지 소개해요.</summary>
    <title>1. 세상에 없던 직무를 만들어가기</title>
    <updated>2026-06-19T11:00:00+09:00</updated>
    <dc:date>2026-06-19T11:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/a978e687-4115-4a7a-81d7-d0d980e46888/Frame_85.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/475d9a52-450d-4889-a94b-6616cd26e33a/Frame_85_(1).png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/b395d690-9f50-4199-92fb-e31f55463a15/Frame_85_(5).png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/4d0c6a9e-204b-4768-8195-108776d9b739/Frame_85_from_Toss.png"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="382a360d-33e3-8095-924c-d0549db285fb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;안녕하세요. 토스뱅크에서 주택담보대출을 디자인하고 있는 Product Designer 김혜미입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-802b-85c8-fe108bed8b81" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이번 글에서는 프로덕트가 아니라, 제가 일하는 방식을 디자인했던 이야기를 해보려고 해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80a7-88a4-e50a23b4e8dd" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="382a360d-33e3-80f3-969d-f393a98d0ea3" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;매일 할 일을 손으로 옮겨 적었다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="382a360d-33e3-80b9-a367-eb4c30b863bc" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/a978e687-4115-4a7a-81d7-d0d980e46888/Frame_85.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="382a360d-33e3-80d8-8979-cc17d8debbff" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스에 입사한 첫 주부터 저는 할 일을 매일 손으로 정리했어요. 처음엔 노션이었고, 나중에는 슬랙이었죠. 제 일의 대부분은 슬랙에서 시작되는데, 피드백이나 요청 스레드, 논의 링크를 다시 노션으로 옮기는 일이 번거로웠거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8076-bdf1-e2f3e006ea04" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;하지만 채널이 바뀌었을 뿐 본질은 같았어요. 매일 아침 할 일을 정리하고, 끝난 일은 체크하고, 새 업무를 추가하고, 참고 링크를 붙였죠. 이렇게 2년 반을 했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8056-b460-eec96c94638d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이게 이상하다고 생각해본 적은 없었어요. 할 일을 정리하고, 흩어진 맥락을 모으는 일은 원래 업무의 일부라고 생각했거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80d5-9035-e62b77940cdb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 한 번도 이런 의문을 가진 적이 없었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8078-92d0-fa695855fd47" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;"이걸 꼭 내가, 손으로, 매일 해야 하나?"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80d4-96a8-ee80d355d7a5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80ba-a449-ca14c10919e9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-803b-8eae-c975f28c6075" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-802d-a854-c6e051d0544a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="382a360d-33e3-80c3-97a9-f52d1ea0c63b" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;참을 문제가 아니라, 디자인할 문제&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="382a360d-33e3-80ac-9ae2-cf88504b9f4a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그러다가 할 일을 도저히 제가 관리할 수 없는 시기가 왔어요. 올해 초, 세 팀을 동시에 맡게 되면서 업무량이 크게 늘었거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80ad-9cd0-c030aa7f7fdb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;처음 슬랙에 할 일을 정리하던 시절엔 하루 10개 안팎이었는데, 어느 순간 20개가 넘었어요. 이제 더 이상 수기로는 할 수 없는 수준이 됐다고 생각했죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80a0-a273-d84a5f6b9596" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;보통 여기서 더 좋은 할 일 앱을 찾거나, 더 열심히 관리하는 쪽으로 가잖아요. 저는 세 번째 길을 골랐어요. 이 불편을 제가 매일 쓰는 프로덕트라고 생각하고 디자인하기로 한 거예요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80f6-b2d0-df2392c1ed4f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;프로덕트를 디자인할 때 늘 하던 방식을 그대로 적용했어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul class="css-uswsmm"&gt;
&lt;li id="382a360d-33e3-80e0-b6cc-def7cfe89cad" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;사용자는 누구인가?&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; → 나&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-80a4-87de-f06588e19c14" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;진짜 하려는 일은 무엇인가?&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; → 할 일을 정리하는 게 아니라, 지금 가장 중요한 일을 놓치지 않고 처리하는 것&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-8001-90fb-cd7bdc03b757" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;어디에서 마찰이 발생하는가?&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; → 할 일을 옮겨 적고, 정리하고, 출처를 찾아가는 반복 작업&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-80b7-8032-da69de3ab7b5" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;무엇이 잘된 상태인가?&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; → 해야 할 일이 자동으로 모이고, 우선순위만 판단하면 되는 상태&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="382a360d-33e3-80de-9010-fddf0e935630" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이렇게 문제를 정의하고 나니 만들어야 할 것도 자연스럽게 따라왔어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul class="css-uswsmm"&gt;
&lt;li id="382a360d-33e3-8038-9426-fb1a739627a1" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;할 일은 슬랙에서 생기는데, 그걸 옮겨 적는 게 일이다 → &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;AI가 알아서 등록하게 하자&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-8072-8231-cb379624bf95" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;옮겨 적다 보면 왜 하는지 잊는다 → &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;출처 스레드와 문서 링크를 함께 남기자&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-8030-81ac-fb3e4f432cdc" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;뭐부터 해야 할지 모르겠고, 안 보이면 잊는다 → &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;우선순위를 붙이고 항상 보이는 위젯으로 두자&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="382a360d-33e3-808d-8039-e323b727f281" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;할 일 앱은 넘쳐나지만, 세상 어떤 앱도 제가 어떤 채널을 보는지, 무엇을 중요하게 생각하는지, 왜 이 일을 하는지까지는 모르잖아요. 그 맥락을 아는 사람은 저뿐이었어요. 그래서 직접 만드는 게 답이었죠. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-800a-bf43-dd7f883809d2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8066-97e3-dcdbb698a08f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80f7-9db3-c9a13696dacc" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80b6-a392-da3ef0c776de" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="382a360d-33e3-803b-b5be-fe405060e325" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;AI에게 내 일을 이해시키기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="382a360d-33e3-805c-ad24-e214050cbb1d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;위젯 동작 자체는 단순해요. 슬랙에서 특정 이모지를 달면 메시지가 한 채널에 모이고, Claude Code가 그 내용을 읽어 할 일로 등록해요. 출처 스레드 링크도 함께요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8023-b173-de0264a93405" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;말로는 간단해보이지만 실제로는 전혀 그렇지 않았어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="382a360d-33e3-8086-9148-c0753bbd9701" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/475d9a52-450d-4889-a94b-6616cd26e33a/Frame_85_(1).png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="382a360d-33e3-8054-a242-ca0d344e7446" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;가장 어려웠던 건 긴 맥락의 메시지를 한 줄의 할 일로 바꾸는 것이었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80b1-bd02-fc7a19010143" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;슬랙 메시지는 길고 맥락이 잔뜩 붙어 있잖아요. 이걸 한눈에 알아볼 수 있는 한 줄의 할 일로 바꾸고, 알맞은 팀까지 연결해야 했어요. 군더더기를 걷어내고, 진짜 해야 할 일만 남기는 일이었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8000-9896-fcdc8bd68b56" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;예를 들어 "대출에서 연장 신청할 때 이런 에러가 떠요. 봐주실 수 있을까요?"라는 메시지가 오면, 위젯에는 "대출 연장 에러 케이스 확인"이라는 한 줄의 할 일로, 해당 팀 태그와 함께 들어와야 했죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80ea-8c74-d4a38646471b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;처음부터 잘 되지는 않았어요. 요약이 너무 길어지기도 하고, 핵심을 놓치기도 하고, 엉뚱한 팀에 들어가기도 했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8043-8e71-c8ede38bfe61" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 UX 라이팅 가이드를 만들듯 접근했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80bb-9d37-f047f9b5a577" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;좋은 할 일은 어떤 형태인지, 어떤 기준으로 팀을 나눌지, 어떤 표현을 사용할지를 예시와 규칙으로 하나씩 정의했죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8032-a496-f0376925cd08" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그리고 결과가 "내가 직접 적었을 법한 문장"이 될 때까지 계속 다듬었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80a0-9540-eed79e671871" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;돌이켜보면 이 과정이 가장 디자인에 가까웠어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8000-b7fd-c793c9f2c918" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;코드를 짠 게 아니라, 무엇이 진짜 할 일인지, 그걸 어떤 언어로 표현해야 하는지에 대한 제 판단을 AI가 따라 할 수 있게 만드는 일이었거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8057-bbe3-f0fb938f91f7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;위젯을 실제로 쓰고 싶을 만큼 자연스럽게 만드는 것도 힘들었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8063-8bd9-eaf624e9fe13" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;작게 접힌 상태에서 펼쳐지는 동작 하나를 다듬다가 코드를 전부 갈아엎고 다시 만든 적도 있었고, 드래그 기능은 일주일 가까이 붙잡고 있었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-809f-b6ac-cfa1c2e9564a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;두 경우 모두 결국 중요한 건 AI에게 어떻게 설명하느냐였어요. 머릿속에서는 너무 당연한 것도 한 줄 한 줄 풀어서 설명해야 했어요. AI에게 내 일을 이해시키는 일은, 결국 제 요구를 더 또렷한 언어로 정의하는 과정이었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80ae-bfb3-d04f242b2ef2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-804b-881c-e35a4d8c9e4f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80af-8934-c4e420fb04a5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8026-99fd-c97db396daec" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="382a360d-33e3-80cd-ba73-e108248547f8" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;놓칠 걱정 대신 우선순위 고민하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="382a360d-33e3-80b4-8b61-c4f224a82f02" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/b395d690-9f50-4199-92fb-e31f55463a15/Frame_85_(5).png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="382a360d-33e3-8060-b4bb-d9305767cf8b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이제 할 일을 보기 위해 슬랙이나 노션을 열지 않아요. 위젯이 늘 화면 위에 떠 있으니까요. 별것 아닌 것 같지만, 저는 하루에도 수십 번 "할 일이 뭐였더라?" 하며 다른 창을 열고 있었더라고요. 불편한 줄도 모르던 불편이 사라진 거예요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80eb-ac97-c0892c013eeb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;진짜 달라진 건 제 머릿속이에요. 예전에는 할 일을 모으고 정리하는 데 계속 에너지를 썼어요. 지금은 그 일을 AI가 대신 해주니까, 저는 무엇부터 해야 하는지만 고민하면 돼요. 무언가 놓칠 것 같은 불안감이 없으니, 우선순위를 판단하는 데 더 많은 시간을 쓰게 됐죠. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8002-a9d6-cf5e1357100b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8096-b81f-fbdfa93d1a72" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-806f-9f75-c535f30a86ed" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="382a360d-33e3-805a-a965-c0a903344dc2" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;사실은 모두의 문제였다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="382a360d-33e3-80be-a086-f8fd815e09be" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/4d0c6a9e-204b-4768-8195-108776d9b739/Frame_85_from_Toss.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="382a360d-33e3-8043-9206-e0f860eee154" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;저 혼자 쓰려고 만든 도구였지만, 지금은 팀의 많은 분들이 사용하고 있어요. 돈 주고서라도 쓰고 싶은 서비스라고 말씀해 주신 분도 계시고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80d6-9a2b-da0a97093c60" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;특히 개발자분들의 반응이 의외였어요. 저는 개발자분들은 이미 더 좋은 도구를 쓰고 있거나, 필요하면 직접 만들어서 해결할 거라고 생각했거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8025-ac1f-e723926de9e5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그런데 오히려 먼저 찾아와 버그를 제보하고 기능을 제안해주시더라고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8096-8cb5-c3ebc3d83519" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;평소에는 디자이너인 제가 개발자분들께 "이것 좀 고쳐주세요"라고 요청하는 입장이었는데, 이번에는 반대의 그림이 펼쳐진 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8017-a0d7-c1f3e0951daa" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;개발자분이 버그를 알려주고, 제가 수정해서 다시 배포하는 모습이요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80c6-9aa1-dc090fc125f7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그 역할이 뒤바뀐 것도 신기했지만, 그보다 더 흥미로웠던 건 제가 개인적인 문제라고 생각했던 불편이 사실은 여러 사람이 함께 겪고 있는 문제였다는 점이었어요. 할 일을 정리하고, 우선순위를 관리하고, 흩어진 맥락을 모으는 일은 직무와 상관없이 많은 사람들이 비슷하게 겪고 있었던 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80f5-84d3-c4fd1eaac423" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 위젯이 퍼진 이유도 획기적인 아이디어여서가 아니라, 많은 사람들이 이미 겪고 있던 불편을 해결했기 때문인 것 같아요. 회사에서 제품을 디자인할 때도 마찬가지잖아요. 새로운 문제를 찾는 것보다, 이미 겪고 있는 문제를 해결하는 게 더 중요하니까요.

&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="382a360d-33e3-80ea-a902-c383e0e60537" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;적용해보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;aside id="382a360d-33e3-806b-a938-d992e7c97b83" class="css-nv7vyi"&gt;&lt;h4 class="css-123co55"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;1️⃣ 이번 주 가장 자주 반복한 '진짜 일이 아닌 일'은 무엇인가요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="382a360d-33e3-80af-8b1e-f202f00ebd3f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;옮겨 적기, 찾기, 정리하기처럼 결과물은 남지 않지만 시간을 계속 쓰는 일&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8036-ab46-f95259ade652" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;2️⃣ 그 불편을 도구로 해결할 수 있는 문제라고 생각해보면 어떨까요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="css-1vn47db"&gt;&lt;ul class="css-uswsmm"&gt;
&lt;li id="382a360d-33e3-803a-8459-f82b1f515230" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;사용자는 누구인가요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-805b-b5ab-d748c2066f41" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;진짜 하려는 일은 무엇인가요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-802a-af1a-fbb1a61847db" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;어디에서 가장 큰 마찰이 생기나요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="382a360d-33e3-80e3-98d0-c5118c040dff" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;무엇이 '잘된 상태'인가요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80e7-930c-fe633c13a441" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;3️⃣ 그 문제를 시중 도구가 해결하지 못하는 이유는 무엇인가요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80bb-b84d-e3c1c49a6027" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;4️⃣ 내일 바로 써볼 수 있을 만큼 작게 만든다면 무엇부터 시작할 수 있을까요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;&lt;p id="382a360d-33e3-800b-b030-df836f566349" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/todolist</id>
    <link href="https://toss.tech/article/todolist"/>
    <summary type="html">반복되는 업무를 프로덕트처럼 정의하고, AI와 함께 해결했어요.
</summary>
    <title>매일 하던 업무를 디자인하기</title>
    <updated>2026-06-17T14:06:00+09:00</updated>
    <dc:date>2026-06-17T14:06:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/97631620-aad3-44f6-9695-992202ae7dfb/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/35e73e6d-91c7-4b60-9299-334c0908623c/image.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/d8b4d38a-a698-47bf-9cf6-66002d5d5ad2/22.gif"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="381a360d-33e3-80ec-b1b4-c4e301824794" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80e9-ab29-ded22f38b54a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;안녕하세요. 토스에서 고객센터 챗봇 설계를 담당하고 있는 Product Designer 김유라입니다. 이번 글에서는 토스 고객센터 AI 챗봇을 만들면서 시도했던 새로운 설계 방식을 이야기해 보려고 해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-80fc-9c76-c647f4ff358c" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;배경&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-8002-ad7a-edcfcd7a979f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;고객센터 방문자는 한 달에 약 60만 명이고, 그 중 약 17만 명이 채팅 상담을 시도해요. 그런데 챗봇에 들어온 사용자의 약 60%가 중간에 이탈했어요. 가장 큰 문제는 챗봇의 구조였죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="381a360d-33e3-8045-b588-ea52954b75d3" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/97631620-aad3-44f6-9695-992202ae7dfb/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;figure id="381a360d-33e3-80db-9e41-cbab31192ad0" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/35e73e6d-91c7-4b60-9299-334c0908623c/image.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="381a360d-33e3-8079-83b2-dfa95cf3312c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1qimhyf"&gt;통신3사와 관련된 문의를 하려면 거쳐야 하는 과정&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80cd-b97b-e2b2b6233543" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80e1-9370-c7d3f4063002" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;원하는 답을 찾으려면 메뉴를 하나씩 눌러가며 탐색해야 했어요. 문제는 사용자는 자신의 문제는 알아도, 서비스가 그걸 어떤 카테고리로 분류했는지는 모른다는 거예요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-807b-a5dc-c3f1ab2e1164" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"결제가 안 돼요."&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8089-9160-e6e11df70de9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"프리미엄 멤버십을 해지하고 싶어요."&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8052-ae09-e6b6ae0cd640" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"송금을 잘못 보냈어요."&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8088-997c-fec9944c2e34" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;사용자가 아는 건 이게 전부예요. 그래서 카테고리를 찾아야 하는 구조 자체를 없애고, 자연어로 말하면 AI가 의도를 파악해서 필요한 행동으로 바로 연결해 주는 경험으로 바꾸기로 했죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80fe-a456-eed69fd0be18" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8002-870f-f31cb9a98a3e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8077-9857-fc2dd0c427b5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-80c6-8645-ebdc7536de4c" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;설계 방식을 뒤집다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-801d-a122-e0f3ee004978" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;챗봇은 보통 이런 순서로 만들어져요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8075-b697-ec37fecd1847" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;고객 문의 분석 → 유형 정리 → 시나리오 작성 → 리뷰 및 수정 → 프로토타입 제작 → 개발&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8031-b016-fe370e41b5e8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시나리오란 특정 문의가 들어왔을 때 챗봇이 어떤 순서로 무슨 말을 할지 미리 짜놓은 대화 흐름인데요. 가장 설계하기 복잡한 부분이에요. 예를 들어 "프리미엄 멤버십을 해지하고 싶어요"라는 하나의 문의에도 전혀 다른 여러 상황이 숨어 있거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul class="css-uswsmm"&gt;
&lt;li id="381a360d-33e3-8017-afae-fbbc85f66640" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이번 달 이용료를 이미 결제한 고객&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-80dd-9816-e892f59234b9" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;아직 결제하지 않은 고객&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-80ce-a88c-f74b74ebc2bb" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;혜택을 이미 사용한 고객&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-80c9-8d91-feec6298e8aa" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;혜택을 한 번도 사용하지 않은 고객&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-809c-84f8-f3fbb423b9eb" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;해지 예약이 이미 되어 있는 고객&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="381a360d-33e3-8055-9752-d7bb070238f0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;사용자는 모두 같은 말로 시작하지만, 확인해야 할 정보도 안내할 내용도 달라요. 하나의 문의처럼 보여도 뒤에서는 수십 개의 분기가 생기죠. 보통은 모든 시나리오를 완성한 뒤 프로토타입을 만들어요. 그런데 이번에는 순서를 조금 바꿔보기로 했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8049-a797-c184a820622a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시나리오를 먼저 완성하는 대신, AI로 시나리오 초안을 만들고 곧바로 프로토타입에서 검증하기 시작한 거예요. 시나리오와 프로토타입을 함께 발전시키는 방식으로요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80bb-b582-ef198b605dcf" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-804a-8a4c-d14df0b1eac8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-8042-bab5-ff48564b3e83" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;1단계) 실제 상담 데이터로 시나리오 초안 만들기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-8037-bcc8-fc4527e42efb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;고객센터에서 가장 많이 발생하는 상담 유형 20개를 뽑아서 AI가 시나리오 초안을 만들도록 했어요. 학습에 활용한 데이터는 개인정보를 제거하고 가명·익명 처리한 뒤 활용했죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8067-a332-ea1971914792" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;우리가 만들고 싶었던 건 정책을 잘 설명하는 챗봇이 아니었어요. 고객의 문제를 이해하고, 필요한 정보를 확인하고, 해결 방법까지 자연스럽게 안내하는 ‘사람 같은 챗봇’이었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80d9-bf47-e41aa68d138b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 시나리오를 만들 때 AI가 어떤 정보를 참고하게 할지 고민했어요. 상담 가이드에는 정책과 기능이 잘 정리되어 있었지만, 실제 상담이 어떻게 진행되는지는 담겨 있지 않았어요. 반면 상담 데이터에는 고객이 어떤 표현으로 질문하는지, 상담사가 어떤 순서로 문제를 해결하는지 생생한 정보가 그대로 담겨 있었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-809d-9805-e19abd920eca" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;고객은 "결제가 왜 안 되죠?"처럼 넓은 문제를 이야기하지만, 상담사는 필요한 정보를 확인하고 원인을 하나씩 좁혀가며 문제를 해결하잖아요. 복잡한 정책과 기능도 고객이 이해할 수 있는 언어로 풀어서 설명하고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80d7-9a94-e38513d9752f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 AI에게 정책을 학습시키기보다 상담 경험을 학습시키는 게 더 효과적이라고 판단했어요. 결과적으로 AI는 단순히 정보를 나열하는 대신, 실제 상담사가 고객을 응대하는 방식에 더 가까운 시나리오를 만들 수 있었어요.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-802f-87d8-efbf2132f1ba" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-806d-9738-f6a3eecccd4d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-80d5-abcd-d74b10c683f5" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;2단계 ) 수십 개의 상황을 빠르게 검증하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-8028-a4ac-cd65de9ed796" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시나리오 초안을 만들고 바로 프로토타입을 만들었어요. 답변이 어색한지, 질문 순서가 이상한지 실제로 대화를 해봐야 알 수 있으니까요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80f3-8add-ee87a5d4e3b0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그런데 위에서 말했듯, 하나의 문의에도 수십 개의 상황 조합이 존재했어요. 매번 조건을 바꿔가며 테스트하는 건 너무 비효율적이었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8003-95ae-d7492b9b1057" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 다양한 상황을 빠르게 검증할 수 있는 시나리오 허브를 만들었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="382a360d-33e3-80f3-ad00-d33dfb3502e9" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/d8b4d38a-a698-47bf-9cf6-66002d5d5ad2/22.gif" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="382a360d-33e3-8000-b421-e7dddce0ee28" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8025-a93a-ec47f265829d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;같은 '프리미엄 멤버십 해지' 문의라도 '이미 이번 달 결제를 완료한 고객', '혜택을 사용한 고객'처럼 여러 상황이 있을 수 있잖아요. 이런 조합을 미리 저장해두고 원하는 시나리오를 선택할 수 있도록 했어요. 상황을 선택하면 오른쪽에서 해당 조건이 적용된 상태로 챗봇 대화가 바로 시작됐고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80a1-a6a9-fada7077131c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;덕분에 시나리오를 수정한 뒤에도 해당 상황으로 바로 들어가서 답변이 의도대로 나오는지 빠르게 확인할 수 있었어요. 새로운 분기가 추가되거나 규칙이 변경될 때도 같은 방식으로 반복 검증할 수 있었고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8077-9e89-e1c0e521b520" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;무엇보다 좋았던 건 진짜 같은 결과물을 바로 만들어볼 수 있었다는 점이었어요. 시나리오만 봤을 때는 괜찮아 보였던 흐름도 실제로 대화를 해보면 어색한 경우가 많았거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-801d-a07b-f74ae74a9424" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;실제 데이터를 적용한 상태로 프로토타입을 만들 수 있으니 고객이 겪게 될 경험을 훨씬 현실적으로 볼 수 있었어요. 덕분에 '이럴 것 같다'가 아니라 '실제로 이렇다'를 기준으로 판단할 수 있었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80d7-bae7-d6ef79a86274" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;결과적으로 이 프로토타입은 단순한 목업이 아니라, AI가 생성한 시나리오를 테스트하고 개선하기 위한 실험 환경이 되었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8022-b842-e380e7e4cc97" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803a-a462-c089ff34309f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-80df-99a0-c82a13099be4" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;3단계) 시나리오를 고치기보다 규칙을 만들기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-801e-9bea-fde10fbe0112" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시나리오 허브를 만들고 실제로 대화를 검증해 보니 예상하지 못한 문제들이 계속 발견됐어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80ce-8457-daaa869c1417" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이미 알고 있는 정보를 다시 물어보기도 하고, 같은 설명을 반복하기도 하고, 틀린 정보를 추측해서 답변하기도 했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80d3-8623-ff98e6637229" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;처음에는 문제를 발견할 때마다 시나리오를 하나씩 수정했어요. 그런데 검증할수록 비슷한 문제가 반복해서 나타났어요. 그래서 개별 시나리오를 수정하는 대신, 이런 문제를 방지하기 위한 규칙을 만들기 시작했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8073-8a37-e702947eec9a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;예를 들면 이런 원칙들이요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul class="css-uswsmm"&gt;
&lt;li id="381a360d-33e3-8031-b604-fa6ce6386e4b" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;해결이 먼저, 설명은 나중에&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-8033-9a44-d8d51f59297f" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;추측하지 말고 모르면 모른다고 하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-805d-88cb-da225e5cf833" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;상담사 연결은 특정 조건에서 진행하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-8069-b073-f7b2827c0577" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;AI의 권한 경계 확실히 하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="381a360d-33e3-80d3-9c53-d299f89b22bc" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시나리오를 검증할 때마다 규칙이 하나씩 늘어났고, 그 규칙을 다시 AI에게 반영했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8024-80f8-e9873349478a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시나리오를 수정하면 하나만 좋아지는데, 규칙 하나를 수정하면 모든 시나리오가 같이 좋아지기 때문에 규칙을 만들수록 검증 속도가 빨라졌죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803e-b3e3-c0d7880692d1" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80a6-8d54-fb92817cae0c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-8005-8823-c1d3b601a189" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;경험을 먼저 만들고, 나머지는 나중에 정의하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-80b0-9c9d-db3cf1cf4d5a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이번 프로젝트에서 가장 재밌었던 점은 이상적인 사용자 경험을 먼저 그려보고, 그 경험을 구현하는 데 필요한 것들을 하나씩 역산해 나갔다는 거예요. 보통은 데이터 구조를 정의하고, 운영 도구를 만들고, 시스템을 설계한 뒤 그 위에 사용자 경험을 고민하죠. 그런데 이번에는 반대로 진행했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803f-a25a-eb1bd08d0e83" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그러다 보니 오히려 그다음에 필요한 것들이 선명하게 보이기 시작했어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b5-bc10-df501b7481af" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"이 경험을 구현하려면 어떤 데이터가 필요하지?"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8065-a744-e7fa8289b711" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"어떤 API가 필요하지?"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8059-9c8f-e183477c9039" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"어떤 운영 도구가 필요하지?"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b4-90d1-f1d97e30cab6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이렇게 하니까 처음부터 모든 걸 설계하는 대신, 정말 필요한 것만 빠르게 정의할 수 있었어요. 팀에 합류하고 약 3주 만에 현황 분석부터 경험 설계, 시나리오 생성, 프로토타입 제작, 검증, 고도화까지 진행할 수 있었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8094-b814-d3fe63d56ae0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803b-b6fc-ddf06ab2e3eb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;AI가 바꾼 것은 단순한 생산성이 아니라 제품을 설계하는 순서였어요. 구현을 전제로 경험을 설계하는 것이 아니라, 경험을 먼저 그려보고 검증한 뒤 필요한 것들을 정의하는 방식으로요. 그래서 AI는 일을 대신 해주는 도구라기보다, 좋은 경험을 훨씬 빠르게 검증할 수 있게 해주는 도구에 가까웠어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8091-aa58-e533b7ef8137" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;디자이너가 시간을 쓰는 지점도 달라졌어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80af-b1a7-e0d413090610" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;예전에는 화면을 그리고 시나리오를 작성하는 데 많은 시간을 썼어요. 좋은 아이디어가 있어도 구현 비용이 크다 보니 실제로 검증해 보기 전에 포기하는 경우도 많았고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-806f-927d-dc12386ac18f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그런데 이번 프로젝트에서는 상황이 조금 달랐어요. AI 덕분에 시나리오를 만들고, 프로토타입을 구현하고, 검증하는 비용이 크게 줄어들었거든요. 덕분에 화면을 그리거나 시나리오를 작성하는 시간보다, 어떤 경험이 더 좋은 경험인지, 어떤 규칙이 더 좋은 규칙인지, 무엇을 검증해야 하는지를 판단하는 시간이 더 중요해졌어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8026-af63-d3457ffc79f4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;AI가 대신 만들어준 게 아니라, 더 많은 선택지를 빠르게 검증할 수 있게 된 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8014-bc57-e0034b2ca5ed" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이런 방식은 챗봇을 만드는 과정뿐 아니라, 새로운 제품이나 기능을 설계할 때도 충분히 적용될 수 있을 것 같아요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-802e-a578-fca1fbb45e37" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-807d-acd4-cc7f5dd8dbdd" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-801f-bc3c-ff8ffe62ca09" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;적용해 보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;aside id="382a360d-33e3-80ed-9730-fc888b7c2ff6" class="css-nv7vyi"&gt;&lt;h4 class="css-123co55"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;1️⃣ 완벽하게 설계하려고 하지 말고 먼저 만들어보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="382a360d-33e3-80a8-8e6a-cc98c657e2d7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;구현이 어렵거나 비용이 많이 들 것 같아서 미뤄두고 있는 아이디어가 있나요? AI를 활용하면 생각보다 빠르게 프로토타입을 만들 수 있어요. 완벽한 설계가 끝날 때까지 기다리기보다 먼저 만들어보고 검증해 보세요. 어떤 문제가 있는지, 어떤 방향이 맞는지 훨씬 빨리 알 수 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8006-800f-e8b814479800" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8012-86d5-eb7456f7c3ae" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;2️⃣ 가이드보다 실제 데이터를 먼저 살펴보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-801b-b570-cf93f746e0a3" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;실제 사용자 데이터에는 문서에 없는 맥락이 숨어 있는 경우가 많아요. 사용자가 어떤 표현을 쓰는지, 어디에서 막히는지, 실제로 어떻게 문제를 해결하는지 먼저 살펴보세요. 생각보다 많은 답이 이미 사용자 행동 안에 들어있을 수 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-800d-9ece-d09aea41e696" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-80f0-9b4b-c549ce18b728" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;3️⃣ 같은 문제를 반복해서 고치고 있다면 규칙을 찾아보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="382a360d-33e3-8034-8ceb-d15d520fe82a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;비슷한 문제가 여러 번 반복된다면 개별 수정보다 공통 원칙을 만드는 편이 더 효과적일 수 있어요. 규칙 하나가 수십 개의 케이스를 동시에 개선하기도 하니까요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/chatbot</id>
    <link href="https://toss.tech/article/chatbot"/>
    <summary type="html">고객센터 챗봇을 만들면서, 좋은 사용자 경험을 먼저 만들고 필요한 것들을 역산해나간 과정을 소개할게요.</summary>
    <title>AI로 바꾼 제품 설계의 순서</title>
    <updated>2026-06-17T13:56:00+09:00</updated>
    <dc:date>2026-06-17T13:56:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/eb5dfb51-c880-4463-8ca1-d7b953c850a9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-11_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9.19.38.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/bc8ea359-7621-4b2c-94b4-ea3f146a57c7/Simulator_Screenshot_-_iPhone_17_-_2026-06-11_at_20.26.13.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/ec16bb8f-1137-4eb1-9275-fba9dd154b1a/Simulator_Screenshot_-_iPhone_17_-_2026-06-11_at_21.27.41.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/e11d10a0-67ae-4673-a56d-7e18f00e4aab/Frame_74_1.png"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="381a360d-33e3-80fc-a4ec-cd9fa998bf39" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;디자인 과정에서 AI를 쓰며 달라진 것 중 하나는, 디자이너가 직접 동작하는 시안을 만들 수 있게 되었다는 점이에요. 예전에는 디자인을 만들고, 문서로 설명하고, 개발자가 다시 구현하는 과정이 필요했어요. 그런데 AI와 함께 코드를 다루기 시작하면서 디자인과 개발 사이의 번역 과정이 크게 줄어들기 시작했죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80cf-bb3b-fc73ed4bcea7" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이번 글에서는 토스의 underlay 컴포넌트를 만들며 경험했던 변화를 이야기해 보려고 해요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8017-aa6a-fdfc5456ce82" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-80f7-9861-cca9f57c3588" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;경험이 끝난 뒤를 설계하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-80bb-b16d-c2a30002cc6b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스 앱에는 경험이 끝나는 화면들이 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8064-83dd-cefa83eb7b89" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;송금을 마치고 나오는 송금 완료 화면, 결제가 끝난 뒤의 결제 완료 화면처럼 사용자가 할 일을 모두 마친 화면들이죠. 대부분은 거기서 앱을 닫고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80d9-835c-cd83843c02d9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이런 화면들을 '데드엔드'라고 불렀어요. 데드엔드를 더 이상 경험의 끝이 아니라, 다음 경험의 시작점으로 만들고 싶었죠. 그렇게 데드엔드 프로젝트가 시작됐어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80d4-a7e9-f5dc48ea926e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;목표는 특정 화면 하나를 개선하는 것이 아니었어요. 앱 안 어디에서든 다음 경험으로 자연스럽게 이어질 수 있도록 돕는 공통된 장치가 필요했죠. 그래서 먼저 컴포넌트를 만드는 것부터 시작하기로 했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803c-8dbc-c5448f26e948" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b9-b619-e152b9c24f5e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8003-be7e-d7cf6364f07b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-80ad-8951-ded0630662f7" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;택배 송장이 준 힌트&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-8049-8896-ce1328ee950d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;컴포넌트를 만들기로 하고 가장 먼저 조건을 정리했어요. 기능으로 인지되어야 하고, 기존 사용자 경험을 해치면 안 되고, 앱 안 어디서든 재사용할 수 있어야 했죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80ea-b849-e63e0e22a7b2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;여러 가지 방향을 시도해 봤어요. 전화가 오는 것처럼 등장하는 방식, 화면 한쪽에 나타나는 방식, 채팅창처럼 올라오는 방식… 그런데 전부 사용자의 동작을 방해할 수밖에 없는 구조였어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-807b-92c7-f1d96550a4ab" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;바텀시트, 토스트, 푸시처럼 우리가 익숙하게 사용하는 UI는 대부분 화면 위에 올라오는 구조예요. 사용자의 시선을 끌 수는 있지만, 동시에 사용자가 보고 있던 화면이나 하려던 행동을 방해할 수도 있죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8013-8d3e-f511b2fdfa81" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 기존의 알림성 UI와는 다른 방식이 필요했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8075-b571-e1685f5a4e50" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;실마리는 예상치 못한 곳에서 왔어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8063-a8f7-d72eca955eba" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이사를 하던 중 택배 상자에 붙어 있던 송장을 떼어냈는데, 그 밑에 가려져 있던 책의 문구가 드러난 거예요. 새로운 것이 나타난 게 아니라 원래 거기 있던 것이 모습을 드러낸 거였죠. 그 순간 관점을 바꿔보게 됐어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-805b-b275-ca3884a8b491" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;“위에 띄우는 것이 아니라 아래에 존재하던 것이 드러난다면 어떨까?”&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b3-8160-dde80dd9651d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="381a360d-33e3-809e-a5c3-f2e6b5f5b165" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/933098fc-c1f3-4d3f-8648-9b47c6601712/v1_framed_3600x2400_from4s.mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;/figure&gt;&lt;p id="381a360d-33e3-80cb-9bad-d230697c7857" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그렇게 화면 위(overlay)가 아니라 아래에 깔린 컴포넌트, underlay를 만들기로 했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80c3-ab40-c914e329cf68" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b1-8837-c66dd5ccbf9b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80ae-bde3-dcad63bb2038" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80c1-9f05-feb2147966cd" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-807f-bb50-df555d93a693" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-8039-8030-d8b9ed5dbf01" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;인터랙션 툴 대신 코드로 디자인하다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-8072-b65b-d382fdb08f9a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;디자인을 시작하면서 곧바로 다른 문제가 생겼어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8028-ba96-c7371580ce0d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;처음에는 피그마로 시안을 만들었어요. 이 컴포넌트는 실제 손안의 화면에서 경험하게 되는 인터랙션이잖아요. 그래서 시안을 폰에 띄워두고 밥을 먹을 때도, 이동할 때도 계속 들고 다니면서 봤어요. "이 느낌이 맞나?" 계속 확인하면서요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80a4-bc1d-f2e7b713e88f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;피그마 시안을 통해 깨달았어요. underlay는 어떻게 생겼는가보다 어떻게 움직이는가가 더 중요한 컴포넌트였거든요. 인터랙션 자체가 디자인이었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b4-8654-de1863c9960a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;문제는 제가 인터랙션 툴을 제대로 다뤄본 적이 없다는 거였어요. 프로토파이 경험도 없고, 프레이머 경험도 없었어요. 대신 다른 방법을 선택했어요. 인터랙션이 중요한 작업이라 웹 개발 대신 SwiftUI 기반으로 Xcode에서 iOS 앱을 직접 만들었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="381a360d-33e3-801f-b9a8-ff48cc53f352" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/eb5dfb51-c880-4463-8ca1-d7b953c850a9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-11_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9.19.38.png" alt="" class="css-1pgssrp"&gt;&lt;figcaption class="css-wgpbp3"&gt;&lt;span class="css-jfs1hr"&gt;작업 환경&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p id="381a360d-33e3-8063-a0f8-e6e0f05cfeb9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80a8-8cdd-f69fb0396166" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8079-a2c3-d5f45bd91f07" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80f0-9adb-e302263969d6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80bf-b1d3-e7a51037fffc" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;물론 저는 SwiftUI를 다뤄본 적이 없었어요. 하지만 AI가 있었죠. Xcode를 열고, 만들려는 걸 AI에게 시켰어요. 문법은 AI가 알고 있었고, 원하는 결과물은 이미 제 머릿속에 있었어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80be-81a6-e3a670113fff" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;제 역할은 세 가지였어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul class="css-uswsmm"&gt;
&lt;li id="381a360d-33e3-8019-8165-d80bc7571a26" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;어떤 경험을 만들고 싶은지 설명하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-80a6-9096-f863fbd79265" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;AI가 제안한 방향 중 더 좋은 것을 선택하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="381a360d-33e3-80b9-9e9d-f36d7daba8ad" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;실제 기기에서 결과물을 보고 판단하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="381a360d-33e3-8063-ab32-ce07b639818b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;AI와 함께 디자인하는 과정은 결국 설계하고, 선택하고, 판단하는 일의 연속이었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8018-9433-f88c9ece8210" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-8005-8b81-f0a5fef6ba2c" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;작업 순서&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-80b6-b1d1-c5ae1df7244d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;1. 기본 환경 세팅하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8006-9bfa-d3ad816d88f5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;먼저 이것저것 그려보고 지울 수 있는 저만의 플레이그라운드를 만들었어요. 피그마에서 새 파일을 파는 것처럼요. 컴포넌트가 들어갈 화면 구조를 만들고, 기본 디자인을 올렸어요. 이때 피그마로 작업한 시안을 AI에게 예시로 주기도 했고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div class="css-1lyd0tt"&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="381a360d-33e3-80e4-83fe-c072c1e509db" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/bc8ea359-7621-4b2c-94b4-ea3f146a57c7/Simulator_Screenshot_-_iPhone_17_-_2026-06-11_at_20.26.13.png" alt="" class="css-1pgssrp"&gt;&lt;figcaption class="css-wgpbp3"&gt;&lt;span class="css-jfs1hr"&gt;디자인 시안 갤러리&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="381a360d-33e3-80a5-8865-cf3f2e2df81d" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/ec16bb8f-1137-4eb1-9275-fba9dd154b1a/Simulator_Screenshot_-_iPhone_17_-_2026-06-11_at_21.27.41.png" alt="" class="css-1pgssrp"&gt;&lt;figcaption class="css-wgpbp3"&gt;&lt;span class="css-jfs1hr"&gt;인터랙션 효과 구현을 위한 테스트 그라운드&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p id="381a360d-33e3-80f7-997d-d4500efbc6f8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-805b-9ff0-e31b8bb52f81" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;2. 실제로 움직여보며 디자인하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80f5-aba1-d21eafa0078d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그다음 버튼, 텍스트, 레이아웃 같은 디테일을 하나씩 다듬었어요. 중요한 건 정지 화면으로 보지 않았다는 점이에요. underlay는 인터랙션 자체가 디자인인 컴포넌트였기 때문에, 수정할 때마다 실제 기기에서 직접 움직여봤어요. 상상한 것과 실제로 구현돼서 움직이는 건 생각보다 느낌이 많이 달랐거든요. 그래서 진짜 몇백 번씩 수정했어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8092-b68d-e065764fd20f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-801f-a0b5-ebde654f3a8b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;3. 원하는 질감이 나올 때까지 다듬기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80c8-803e-eb5b34469ba2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 컴포넌트는 화면을 읽고 그 맥락에 맞는 정보를 제공하는 역할을 해요. 그래서 "AI가 화면을 읽고 알맞은 정보를 찾아준다"라는 심상을 만들어보고 싶었어요. 여러 표현을 고민하다가, 빛이 화면을 훑고 지나가는 스캔 인터랙션을 만들기로 했어요. 스캔 효과는 Metal 셰이더로 구현했어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80d5-a7ae-dce75d88e3c6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;셰이더는 화면의 픽셀 하나하나를 어떻게 그릴지 직접 계산하는 그래픽 코드인데, 빛이 번지고 퍼지는 질감은 일반적인 UI 코드로는 표현하기 어렵거든요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b6-968a-e231d4be0b64" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;처음에는 AI가 작성한 코드를 사용했지만, 계속 수정하다 보니 어느 순간부터는 직접 값을 조정하고 있더라고요. 빛의 번짐, 틴트, 폭, 지나가는 속도, 배경이 어두워지는 정도 같은 요소들을 바꿔가며 원하는 질감을 찾았어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="381a360d-33e3-8060-821e-f439491bdcf2" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/e11d10a0-67ae-4673-a56d-7e18f00e4aab/Frame_74_1.png" alt="" class="css-1pgssrp"&gt;&lt;figcaption class="css-wgpbp3"&gt;&lt;span class="css-jfs1hr"&gt;실제 작업한 메탈 코드&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;div class="css-1lyd0tt"&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="381a360d-33e3-80fc-bc01-d2fae044a544" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/43905190-3c4f-48f1-8762-fbf72e503c9d/scannoise_from4s.mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;figcaption class="css-5ovf3r"&gt;&lt;span class="css-jfs1hr"&gt;스캔 효과 1차 안&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="381a360d-33e3-8092-be7a-e4188f3aaeef" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/3280775d-637c-47b9-b8d2-98eeaafc556e/s1t1_wobble_OFF_from4s.mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;figcaption class="css-5ovf3r"&gt;&lt;span class="css-jfs1hr"&gt;스캔 효과 최종안&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p id="381a360d-33e3-80e5-ae9a-f30811786926" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;스캔이 지나갈 때나 컴포넌트가 등장할 때 미세하게 출렁거리는 디테일도 같은 방식으로 다듬었고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div class="css-1lyd0tt"&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="381a360d-33e3-80d5-805d-ce105ed8ce1b" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/0a5bb7d4-a0ee-4024-a403-9c427028885d/%E1%84%87%E1%85%B3%E1%84%85%E1%85%B5%E1%86%BA%E1%84%8C%E1%85%B5_%E1%84%83%E1%85%B3%E1%86%BC%E1%84%8C%E1%85%A1%E1%86%BC_wobble.mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;figcaption class="css-5ovf3r"&gt;&lt;span class="css-jfs1hr"&gt;등장 시 디테일 다듬기&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class="css-31l7gp"&gt;&lt;figure id="381a360d-33e3-8016-a922-e2717d12866e" class="css-of5acw"&gt;&lt;video muted="" loop="" autoplay="" playsinline="" class="css-8atqhb"&gt;&lt;source src="https://static.toss.im/ipd-tcs/toss_core/live/8e4ad735-75df-4381-aa35-a2605c6b2007/v3_bridge_to_scan_ON.mp4"&gt;&lt;/source&gt;&lt;/video&gt;&lt;figcaption class="css-5ovf3r"&gt;&lt;span class="css-jfs1hr"&gt;스캔 시 디테일 다듬기&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p id="381a360d-33e3-804b-bc43-fd4554a8facb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;인터랙션 툴을 한 번도 써본 적 없는 사람이 어느새 셰이더 코드의 숫자를 만지고 있었던 거예요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80bd-ad46-fd17af2850a6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-804c-b425-ed8339e8dd9b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-8043-b09d-c2dc9fe44bf1" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-q3ktjb"&gt;디자인 가이드 대신 레포를 전달하다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-8038-815b-ce44f59b44b2" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시안이 완성되고 개발을 시작했어요. 이 미세한 인터랙션을 개발자에게 어떻게 전달해야 할지 고민이 됐죠. 보통이라면 등장 타이밍, 이징 커브, 딜레이 값을 정리한 인터랙션 가이드 문서를 만들었을 거예요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-800a-8e19-e8302ff4cdc4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그런데 이번에는 방식을 조금 바꿔봤어요. 인터랙션에 대한 자세한 가이드 없이 간략한 플로우만 정리하고, 제가 디자인하며 만든 레포를 그대로 전달했죠. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80cb-9ade-d5d3a39effde" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;솔직히 괜찮을까 싶었어요. 그런데 개발자분들이 레포를 보더니 "일단 이 정도면 될 것 같다"라고 하시더라고요. 그리고 실제로 첫 개발 버전부터 시안의 기본 구조를 거의 그대로 구현해 주셨어요. 제가 예상했던 것보다 디자인 완성도가 훨씬 높았죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80b6-bce8-e52d8d827411" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;완성도를 끌어올리는 파인튜닝 단계에서는 더 재미있는 일이 생겼어요. UI 디테일을 조정할 때마다 개발자분들이 저한테 노트북을 주시더라고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-803d-a444-d39402ae2a40" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;opacity 같은 값은 "0.4로 해주세요 → 빌드 → 음, 0.5로요 → 빌드"를 반복하는 것보다, 직접 보면서 수정하는 편이 훨씬 빠르니까요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-800f-926c-c164d1f0224b" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그러다 등장 인터랙션 차례가 왔을 때는 개발자분 노트북에서 제가 AI에게 직접 명령을 내리기 시작했어요. 머릿속의 모션을 설명하고, 결과를 보고, 다시 수정하고 명령을 내렸죠. 그랬더니 인터랙션 퀄리티가 확 높아졌어요. 옆에서 보던 개발자분이 그러시더라고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote id="381a360d-33e3-809b-baa7-debb5c0e2a44" class="css-2sk6rv"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;"얘가 민지 님 말을 더 잘 듣네요…"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p id="381a360d-33e3-8098-98c2-c28220caef20" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 과정이 수월했던 이유 중 하나는 동작하는 레퍼런스가 있었기 때문이에요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8089-adf1-f2aa9fcf9939" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시안 단계에서 직접 만들었던 코드가 있었기 때문에, "느낌이 이상해요" 같은 추상적인 표현 대신 어떤 동작을 원하는지 구체적으로 설명할 수 있었어요. AI와도, 개발자분들과도 같은 결과물을 보며 이야기할 수 있었죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8007-8243-efa57d6f0cb4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이런 과정을 거쳐 underlay는 실제 서비스에 적용됐어요. 아직 실험이 진행 중이기는 하지만, 예상했던 것보다 좋은 결과가 나오고 있고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8017-a5fb-facf2abd3804" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80a2-90db-d7805a7848fe" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-8093-a923-cc3f0f423104" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;보이는 것을 넘어, 구조까지 디자인하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p id="381a360d-33e3-8049-a2e2-f493921f9af8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-808c-8364-d1e865dc9478" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이번 프로젝트에서 가장 신기했던 건 실제 개발된 버전의 코드 구조가 제가 디자인했던 레포와 거의 동일했다는 점이었어요(iOS 기준).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80e9-80f3-fa4cf7612c51" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;처음부터 개발을 염두에 둔 건 아니었어요. UT를 하면서 여러 버전을 빠르게 바꿔보고 싶었고, 제가 테스트하기 편한 구조를 만들다 보니 자연스럽게 그렇게 된 거였죠. 그런데 나중에 보니 그 구조가 실제 개발에도 그대로 활용할 수 있는 형태였어요. 그래서 파인튜닝 과정에서도 수정 사항을 말로 설명하기보다 코드로 전달할 수 있었고요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80c1-b71d-dc9242f72938" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이게 이 프로젝트에서 가장 크게 배운 점이었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8093-8884-c4ea5e89261f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;좋은 시안은 단순히 보기 좋은 화면만을 의미하지는 않는다는 점이요. "보이는 것"만이 아니라 "만들어진 방식"까지 괜찮아야 하죠. 화면은 같아 보여도 일회용 코드 덩어리였다면 개발자분들은 결국 처음부터 다시 만들었을 거예요. 하지만 개발할 수 있는 구조로 만들어진 시안은 그대로 스펙이 될 수 있었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8052-a5c8-eee01614d1ca" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이제 디자이너가 코드로 디자인하는 일 자체는 점점 특별한 일이 아니게 될 것 같아요. 오히려 차이를 만드는 건 그다음이에요. "어떻게 만들지"는 AI가 알고 있으니, 디자이너에게 남는 질문은 "뭘 만들까"거든요. 툴의 제약 때문에 포기했던 것들이 사라진 자리에서, 뭘 상상하고 뭘 만들기로 결정하느냐. 그게 디자인의 전부가 되는 것 같아요.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80c8-82a8-cac36b3ac269" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-8004-acb1-fec0b13d84e1" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="381a360d-33e3-80ab-a9fe-eddd46f525af" class="css-1c1qox8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-p4abj2"&gt;&lt;span class="css-1kxrhf3"&gt;적용해 보기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;aside id="381a360d-33e3-8050-85f3-de633f48dc19" class="css-nv7vyi"&gt;&lt;h4 class="css-123co55"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;underlay의 이야기는 여기까지지만, 이 방식은 어떤 프로젝트에서든 시도해볼 수 있어요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="381a360d-33e3-8003-8f56-c3402a50e4a0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;1️⃣ 툴의 제약 없이 가장 좋은 디자인부터 생각하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="css-1vn47db"&gt;&lt;p id="381a360d-33e3-808f-b94f-f2da3ffcd59a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;디자인하고 싶은 게 있다면 더 이상 툴의 제약은 없어요. "만들 수 있는 디자인"이 아니라 "가장 좋은 디자인"부터 그려보세요. 어떻게 만들지는 AI와 풀면 되니까요&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-804b-8a28-d52bc905ba0f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;2️⃣ 그림이 아니라 실물 만들기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="css-1vn47db"&gt;&lt;p id="381a360d-33e3-80da-abf3-dae7fce94675" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;시안을 그림으로 두지 말고, AI와 코드로 실제로 동작하는 걸 만들어보세요. 실물에서만 보이는 디테일이 있고, 툴로는 표현하지 못하던 질감까지 만들 수 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="381a360d-33e3-80cc-8c31-edbcf1894980" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;3️⃣ 가이드 문서 대신 동작하는 코드 전달하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="css-1vn47db"&gt;&lt;p id="381a360d-33e3-80f1-b7f4-d29e835ba4db" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;개발자에게 인터랙션을 넘길 때, 말로 설명한 문서보다 직접 만든 레포 하나가 더 정확하게 전달돼요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;&lt;p id="381a360d-33e3-80ec-94ba-ddb00e170a76" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/deadend</id>
    <link href="https://toss.tech/article/deadend"/>
    <summary type="html">툴의 제약을 넘어, 머릿속에 있던 디자인을 AI로 그대로 구현해본 이야기를 들려드립니다.</summary>
    <title>디자이너가 시안 대신 앱을 만든 이유</title>
    <updated>2026-06-16T10:06:00+09:00</updated>
    <dc:date>2026-06-16T10:06:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>토스</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/f1ac07e6-1126-4260-bd9a-1c23d814a8a9/tues_1_13x.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/861f0e36-ff54-4254-be99-883d168eff53/tues_23x.png"&gt;
&lt;link rel="preload" as="image" href="https://static.toss.im/ipd-tcs/toss_core/live/81a54d2b-8159-4a2c-b9b4-948fbf3d10b1/tues_v2_structure.png"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="2e4b468d-4704-4d9e-ba82-3332b3b7cb5e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;안녕하세요, 토스 Director of Data Analytics 우찬희입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-80dc-8321-c320f83133b6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;저는 Data Intelligence and Analytics Team을 이끌며 전사적으로 주요한 의사결정을 잘 내릴 수 있도록 데이터를 분석하고, 새로운 프레임워크를 만들고 데이터 분석 거버넌스를 만드는 업무를 하고 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="71560a6a-fe83-4c4b-ba06-eeaee4a6fad5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;오늘은 토스의 2,800만 MAU를 분석할 때 활발히 활용하고 있는 유저 세그먼트, &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;TUES(Toss User Engagement Segment)&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 를 소개해 드릴게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="364a360d-33e3-80db-8550-cb1e51934fb4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="6b1d1849-8692-4f66-b67c-99d4cac0b011" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;TUES가 무엇인가요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="36ca360d-33e3-8081-b17d-d922a081c78d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스와 같은 플랫폼 앱에서 유저 분석을 하다보면 이런 고민이 자연스레 들게 돼요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote id="36ca360d-33e3-8020-9bce-cc6f4962f189" class="css-2sk6rv"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1odxvuk"&gt;“유저들은 왜, 무엇을 위해 우리 앱을 이용하는 걸까?”
“앱 이용의 주 목적이 A 서비스인 유저는 얼마나 될까?”
“A 서비스는 우리 앱 MAU와 다른 지표에 얼마나 영향을 끼치는 걸까? B 서비스랑 비교하면 어떨까?”
“각 유저의 이용 패턴을 안다면 각 패턴마다 더 적절한 전략을 취할 수 있지 않을까?”&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p id="36ca360d-33e3-80f8-ba7f-c832b57d0a5c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스에서도 비슷한 고민이 계속 있었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-8006-95dd-c358eeeaf78d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;각 서비스 내에서 ‘A 서비스를 이용한 유저’, ‘B 서비스를 이용한 유저’와 같은 방식으로 정의해서 진행하긴 했지만, 이건 MECE(Mutually Exclusive, Collectively Exhaustive) 하지 않죠. 유저는 둘 다 이용할 수 있으니까요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-8070-90a7-e94858cab695" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;즉, 플랫폼 관점의 유저 세그먼테이션이 필요했습니다. 이를 위해 만들어진 것이 바로 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;TUES&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;입니다. &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;각 유저의 서비스 이용 패턴을 기준으로 비슷한 유저들끼리 묶어둔 세그먼트&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;라고 봐주시면 돼요. (참고로 ‘튜스’라고 읽습니다.)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-8017-89cc-e0198774fc3a" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;결과적으로 TUES는 각 유저가 어떤 유저인지, 우리 앱의 어떤 서비스를 좋아하고 주로 이용하는지를 바로 파악할 수 있는 도구의 역할을 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-8039-ad6a-c125c5ab42b9" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 TUES는 진화를 거듭해 현재 V2가 적용되어 있습니다. 그 여정을 하나씩 소개해 드릴게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="9ea6565b-7bb1-4679-91b3-9fec03cd89be" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="45b75478-a5fb-4045-a40d-f09560808852" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;TUES V1은 어떻게 만들어졌나요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="36ca360d-33e3-8023-8d89-e90d29cba253" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;TUES V1을 정의하는 핵심 개념을 간단히 설명해 드릴게요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="23589a03-358a-40de-97f7-175266c74b65" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스가 제공하고 있는 서비스는 매우 많고, 유저는 각자가 원하는 서비스를 선택적으로 써요. 이걸 하나하나 조합을 만들어 파악하는 건 불가능했어요. 그래서 인사이트를 얻기 위해 머신러닝(ML) 알고리즘을 이용하기로 했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="364a360d-33e3-8024-82f5-d24a938b4c3d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;먼저 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;각 유저가 1회 앱오픈 시 각 서비스를 이용할 확률&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;을 계산했어요. 예를 들어 한 달간 60번 앱을 켠 유저가 그 중 20번 토스페이를 썼다면, 이 유저의 토스페이 이용률은 33%가 되는 식이에요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-8080-aaa7-da462dab08d1" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그러면 유저마다 각 서비스의 이용률 분포를 갖게 됩니다. 그리고 &lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 이용률 분포가 비슷한 유저들끼리 묶었어요. 묶는 도구로는 K-Means Clustering을 썼습니다. 다만 이 결과를 그대로 쓰지 않고 왜 이런 결과가 나왔는지를 분석해, 주요 키 서비스와 포인트를 찾은 뒤 전략·제품 관점에서 더 직관적으로 이해하고 활용할 수 있도록 각색하는 과정을 거쳤어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="7754247a-1768-4fde-a296-1276569e89b3" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그렇게 만들어진 TUES V1의 세그먼트는 이렇게 구성됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="372a360d-33e3-80b3-8d46-d7881016ea7a" class="css-nv7vyi"&gt;&lt;h4 class="css-123co55"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1kxrhf3"&gt;고관여&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; : 여러 서비스를 두루두루 잘 이용하는 유저군 (이용률이 높은 서비스가 여러 개)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div class="css-1vn47db"&gt;
&lt;p id="d2d6b4a1-6d7d-447c-8bf3-5b3f9fe00b5e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;토스뱅크 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; / &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;토스증권 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; / &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;조회서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; / &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;혜택서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; / &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;송금서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; / &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;기타서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; : 주로 이용하는 서비스가 분명한 유저군&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="2d495ea9-c2a8-4adb-8f76-3bdf1b31cb64" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;단순 방문&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; : 서비스를 사실상 이용하지 않는 유저군&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;&lt;figure id="36ca360d-33e3-8092-b997-d5c157d1c24b" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/f1ac07e6-1126-4260-bd9a-1c23d814a8a9/tues_1_13x.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="36ca360d-33e3-808c-8866-dd790d1bd747" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="37a00861-5188-470c-a386-c3d975e43bb8" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;TUES로 무엇을 할 수 있나요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="3470a43d-a868-4b82-a240-4b75b1f3b1b5" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;TUES 같은 세그먼테이션은 그 자체보다 활용에 더 가치가 있습니다. TUES는 아래와 같이 활용하고 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="82c75d3f-2dad-47ed-8784-b4daa025d669" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;1️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;세그먼트별 Transition 전략 수립의 기준이 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="0e7937cc-5050-4a88-8333-7b1fa414c9e6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;각 세그먼트별로 특징이 꽤 명확해요. 이 특징을 활용해 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;세그먼트별 Retention Rate 제고, 타 서비스로의 Cross Activation, UX 개선&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 등의 전략을 세울 수 있습니다. 특히 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;고관여&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; 유저의 MoM Retention이 매우 높은 반면, &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;단순 방문&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; 유저는 낮아요. 중간에 있는 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;각 서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; 세그먼트는 그 사이에 있고요. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-80fd-9a05-e599656d06d6" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;그래서 &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote id="36ca360d-33e3-800c-a639-c32aceddcc9a" class="css-2sk6rv"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1odxvuk"&gt;“어떻게 하면 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1qi1uub"&gt;단순 방문&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1odxvuk"&gt; 유저들을 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1qi1uub"&gt;각 서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1odxvuk"&gt; 세그먼트로, 이들을 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1qi1uub"&gt;고관여&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1odxvuk"&gt;로 보낼 수 있을까?”&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p id="36ca360d-33e3-8088-9bb6-eb18d052e685" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;라는 질문에 대한 대답을 큰 관점에서 찾을 수 있었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id="36ca360d-33e3-804e-9af8-f83777db4b83" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/861f0e36-ff54-4254-be99-883d168eff53/tues_23x.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;p id="75d90aed-453c-48f8-a293-ad310e4c5a44" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;2️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;각 제품의 Growth 전략에 쓰입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="30b2594b-5c9f-44f6-95bb-bfb5d02746e0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;각 제품 입장에서는 &lt;/span&gt;&lt;span class="css-1odxvuk"&gt;“우리 제품을 어떤 유저가 많이 쓰고 있나”&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 를 TUES로 빠르게 파악할 수 있어요. 이 힌트를 바탕으로 1번에서 구한 대답과 결합하여 제품 Growth 전략을 세울 수 있었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-80e5-9ce0-e0c52b829a97" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;3️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;유저의 행동을 더 다각화하여 볼 수 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-8033-a8bc-cc373deb4316" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;TUES를 통해 그동안 보기 힘들었던 유저의 행동 패턴들이 보이기 시작했어요. 세그먼트는 언제 무엇에 의해 바뀌는지, 언제 이탈하기 시작하는지, 부활하는 유저는 어떤 모습인지 등 유저의 행동을 플랫폼 관점에서 더 잘 이해할 수 있었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="aba2c8ae-152f-4f0f-b0e7-06d353c9b792" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;4️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;탑라인 지표 분석의 기본 도구가 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="97b27b11-0741-4f15-a027-4e30ce29bd9e" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;전사 MAU 같은 탑라인 지표가 흔들렸을 때 어떤 세그먼트가 움직였는지 보면, 어떤 서비스가 영향을 줬는지 쉽게 파악할 수 있어요. 탑라인 지표를 유저단위로 MECE 하게 증감 사유를 분석할 수 있게 된 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-804c-9445-ec9ba4288457" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;5️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;푸시 같은 타겟마케팅에 매우 강력한 소스가 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-806e-8358-db2faeb408a8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;마케팅하려는 서비스 상황에 알맞은 세그먼트를 찾아 마케팅을 했을 때 그 효율이 크게 높아진 사례가 자주 나오고 있어요. 타겟 마케팅에서 어떤 조건보다도 활용도가 높아, TUES를 자주 쓰는 직군 중 하나가 마케터분들이라고 할 수 있을 정도입니다. 사내 마케팅 툴인 TUBA에도 기본 제공 세그먼트로 등록되어 있어 누구나 손쉽게 쓸 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="b3263e00-c1b0-428c-9619-c69891a48bed" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="804c317a-3ca9-44ba-b626-c72a68d7b51c" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;TUES V2 — 문제점 보완&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="d1ba113c-36d2-4999-bb69-771697e24e56" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;V1을 2년 정도 쓰면서 &lt;/span&gt;&lt;span class="css-1odxvuk"&gt;“이걸 더 잘 할 수는 없을까”&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 라는 갈증이 점점 커졌어요. TUES가 풀고자 하는 문제는 그대로지만, 그 문제를 푸는 방법을 손볼 필요가 생긴 거죠.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="b9ccefff-1d6d-4c37-9ca9-7f4d87117e83" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;V1이 아쉬웠던 점들은 이랬어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="372a360d-33e3-80bc-81d1-c0773d1733dc" class="css-nv7vyi"&gt;&lt;div class="css-1vn47db"&gt;&lt;ul class="css-uswsmm"&gt;
&lt;li id="eed464ea-641c-4435-8877-522b306da854" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;‘횟수’, 즉 ‘깊이’ 개념이 없었어요.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;
V1은 ‘앱오픈 시 이용 확률’만 봤기 때문에, 한 번의 앱오픈에서 혜택서비스를 1번 이용한 유저와 10번 이용한 유저가 같이 취급됐어요. 깊이가 담기지 않았습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="a31bfb14-26a0-48c3-be9a-f4c379f1c6d0" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;각 세그먼트 유저의 다른 카테고리 Engagement가 안 보였어요.
&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;같은 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;조회서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt; 유저라도 어떤 사람은 혜택서비스도 조금씩 같이 쓰고 어떤 사람은 조회서비스만 써요. 그런데 V1은 이 차이를 보여주지 못했어요. 서비스별 관여도 정보가 없었기 때문입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="9019a2bd-a88c-4c88-b3af-1ef5901972ea" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;한 유저는 한 세그먼트에만 속했어요.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 
V1의 근간이 되는 K-Means Clustering은 Hard Clustering 알고리즘이에요. 실제 유저는 여러 서비스를 동시에 쓰는데, V1 로직 안에서는 그 복합성을 담을 수 없었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="313a97c0-7625-4c9d-8766-0567aebc96c8" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;새로 생긴 핵심 서비스가 누락돼 있었어요.&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 
2년 사이 토스쇼핑·앱인토스·토스페이 등 중요한 서비스가 늘었는데 V1 로직 안에서는 모두 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1mjnzsq"&gt;ETC&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1kxrhf3"&gt;로 처리됐어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/aside&gt;&lt;p id="36ca360d-33e3-80d7-a7b9-cb51eec85fda" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="da388f5c-3a57-4628-b419-fe1ccabf760c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;결과적으로 V2는 세 가지 변화로 이 한계들을 풀었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="aa01f4ec-3749-4c81-9294-93e3d00f0a53" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;1️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;측정 방식이 횟수 기반으로 바뀌었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="6ab0411c-c293-4db1-925e-7219a8d68bbb" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;‘앱오픈 시 이용 확률’ 대신 ‘서비스별 이용 횟수’를 그대로 다루기 시작했어요. 즉 앱오픈 1회당 이용 횟수를 Feature로 넣음으로써 V1에서는 부재했던 ‘깊이’를 반영했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-804e-97d6-dcd086232f37" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;2️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;Soft Clustering 알고리즘 적용&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="36ca360d-33e3-80a3-a634-d7d194d37020" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;기존 Hard Clustering 알고리즘에서 Soft Clustering 알고리즘으로 바꾸면서, 한 유저가 하나의 세그먼트에만 속하는 게 아니라 각 세그먼트에 속할 확률&lt;/span&gt;&lt;span class="css-1odxvuk"&gt;(정확히 확률 개념은 아니지만)&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;을 구하고 그것을 선별적으로 가져가는 구조로 바꿨어요. 이를 통해 V1에서는 담을 수 없었던 ‘복합성’까지 담을 수 있었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="3f4fc2c4-8d82-452f-a4bd-f047b7057f4d" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;3️⃣ &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;세그먼트 구조가 세 층으로 바뀌었어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="f183376d-7eca-4c77-9838-36a5416fa581" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;한 유저를 ‘전체 앱 관여도’와 ‘주 이용 서비스’, ‘서비스별 관여도’ 세 가지로 동시에 표현할 수 있게 됐어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote id="36ca360d-33e3-8067-8a33-d503fd43d615" class="css-2sk6rv"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;서비스별 관여도 정의 → 앱 전체 관여도 정의 → 주 이용 서비스 정의&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p id="49cebbaa-9062-4caa-a737-cd66e436836c" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;이 세 개의 층을 단계적으로 쌓아 세그먼트를 만들기 때문에, 유저가 그 세그먼트에 배치된 이유를 더 자세히 알 수 있을 뿐만 아니라 Next Action도 더 효율적으로 수립할 수 있게 되었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div data-table-wrapper="true" class="css-1m7s5mg"&gt;&lt;div role="table" class="css-uznrcw"&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;TUES V1&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;TUES V2&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;Feature 기준&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;앱오픈 1회당 이용률&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;앱오픈 1회당 이용 횟수&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;결과물&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;전사 세그먼트&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;서비스별 관여도 세그먼트
앱 전체 관여도 세그먼트
주 이용 서비스 세그먼트&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;기반 모델&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;K-means (Hard) → Rule 생성&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;NMF (Soft) → Rule 생성&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;이용 서비스&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;6개&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;10개&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div role="row" class="css-1obf64m"&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;Engagement 구분&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;3개&lt;/span&gt;&lt;/div&gt;
&lt;div role="cell" class="css-8vl804"&gt;&lt;span class="css-1mjnzsq"&gt;6개&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;figure id="379a360d-33e3-80e9-8bff-d21240f24f89" class="css-of5acw"&gt;&lt;img src="https://static.toss.im/ipd-tcs/toss_core/live/81a54d2b-8159-4a2c-b9b4-948fbf3d10b1/tues_v2_structure.png" alt="" class="css-1pgssrp"&gt;&lt;/figure&gt;&lt;h3 id="0d2586b6-5e44-4266-84ca-81e73133d51e" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;V2로 어떤 것을 더 할 수 있나요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="041e3db0-91d3-4de5-a23f-0f88c1693f92" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;크게 보면 V2는 V1에서 &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;‘서비스별 관여도’라는 차원&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이 더해진 거예요. 그래서 이런 일들이 가능해졌습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="372a360d-33e3-80ef-b3b2-c88f9156a9f4" class="css-nv7vyi"&gt;&lt;div class="css-1vn47db"&gt;&lt;ul class="css-uswsmm"&gt;
&lt;li id="cef977af-631d-45d1-9421-210c0278c23b" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1odxvuk"&gt;“&lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1qi1uub"&gt;준고관여 - 혜택서비스 지향&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1odxvuk"&gt; 유저들이 &lt;/span&gt;&lt;code style='font-family:Consolas, Menlo, Monaco, source-code-pro, "Courier New", monospace;font-size:0.9em;background-color:var(--adaptiveOpacity100);border:1px solid var(--adaptiveOpacity200);border-radius:3px'&gt;&lt;span class="css-1qi1uub"&gt;고관여&lt;/span&gt;&lt;/code&gt;&lt;span class="css-1odxvuk"&gt;로 가려면 어떤 카테고리의 관여도를 먼저 올려야 할까?”&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt; 같은 질문에 서비스별 관여도를 보면서 답할 수 있어요. &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;Cross Activation 전략의 출발점&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이 서비스별 관여도로 분명해졌습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="f3115b58-7cfb-47d5-b14c-9de2f0b6b7ff" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;각 Silo는 ‘&lt;/span&gt;&lt;span class="css-1odxvuk"&gt;내 서비스의 관여도를 끌어올리는 액션이 전사 세그먼트와 전사 성과에 어떤 영향을 줬는가’&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;를 정량적으로 추적할 수 있어요. &lt;/span&gt;&lt;span class="css-q3ktjb"&gt;‘Silo Action → 전사 성과’의 연결&lt;/span&gt;&lt;span class="css-1kxrhf3"&gt;이 더 명확해졌습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="cab88651-d561-4fb5-8bf8-4e1d804650b7" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;각 서비스의 이용/미이용 유저가 어떤 관여도를 갖고 있는지가 직관적으로 보여, 제품 Growth 전략의 방향이 더 명확해졌습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/aside&gt;&lt;p id="372a360d-33e3-80fc-a778-dbd2bafc05d4" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;실제로 Silo에서 서비스 관련 전략 분석을 할 때 어떤 세그먼트를 공략해야 할지를 빠르고 간편하게, 더 자세하게 볼 수 있는 환경이 마련되었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="ee59e3cb-4dc5-4182-9eee-27156dc1a107" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="e12e0e91-37f3-4399-8ff9-ed087fcb739a" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;다음 단계&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="7737e1f0-41bc-4eb9-9f65-e18d450d35d0" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;TUES는 앞으로 더욱 진화할 예정입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;aside id="a18fd6a2-5b1f-4ad3-a0ec-a7c604038534" class="css-nv7vyi"&gt;&lt;div class="css-1vn47db"&gt;&lt;ul class="css-uswsmm"&gt;
&lt;li id="3ca539f8-0dd1-4289-a4ef-29c5a5eb4440" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;세그먼트의 Transition 전략을 더 빠르고 자세하게 세울 수 있는 분석 프레임워크 생성 (서비스 유사도 등)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="36ca360d-33e3-800a-aa27-e5486171a6f1" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;유저 프로파일링과 결합하여 유저 x 서비스 이용 패턴 기반의 전략적 유저 맵 생성, 전략적 시사점 도출&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li id="1e1ba547-6ca5-4d3f-99a1-d6df7b49fb3d" class="css-1hwiibq"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;MTVi 등 다른 분석 프레임워크와의 결합을 통한 ‘세그먼트별 가치’ 정량화&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/aside&gt;&lt;p id="6c22bd2a-9f0f-4d19-b2ef-4cc1a5f16707" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;활용 방안에 대해서 더 발전시킬 여지가 많아요. 앞으로 다양한 팀과 더 고도화해 나갈 예정입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="4d2aca7b-f948-4712-a285-af936e5da86f" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="07b107bf-1118-467d-b807-1b312e4106d8" class="css-1feg9au"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-q3ktjb"&gt;마무리하며&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id="fddaef1b-d635-4feb-81fe-c4198e908171" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스의 MAU는 계속해서 성장하고 있습니다. TUES는 이 MAU를 더 잘 이해하고 어떤 유저를 타겟해 어떤 액션을 해야 하는지, 그리고 그 액션이 전사적으로 어떻게 작동하는지를 해석할 수 있는 플랫폼 관점의 세그먼트입니다.
이 세그먼트 덕분에 MAU가 계속 늘어나더라도 유저들을 빠르고 직관적으로 그룹화하여 더 빠르고 정교한 분석과 전략을 짤 수 있어요.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="379a360d-33e3-8014-a1c7-e7de8c318667" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;span class="css-1kxrhf3"&gt;토스의 Data Analyst 분들은 서비스를 효율적으로 성장시키기 위해 데이터 분석에 기반한 전략을 수립하는 업무와 더불어, 이런 분석이 더 빠르고 잘 진행될 수 있도록 TUES, MTVi 같은 분석 프레임워크를 만드는 업무도 함께 하고 있어요.
방대한 데이터로 유저의 행동을 분석하는 방법을 만들고, 그 방법으로 분석하고, 그 분석이 의사결정과 서비스의 성장으로 이어지게 만드는 일에 관심 있으신 분들은 토스 Data Analyst에 많은 관심 부탁드립니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="f42ec5b9-94ce-42c5-98c8-dffe20be97ec" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="d505a119-c54b-443f-843c-b5b46d8142d8" class="css-14on8x8"&gt;&lt;span class="css-1r3ko7u"&gt;&lt;span class="css-1iisb9p"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id="tds-mobile-portal-container"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</content>
    <id>https://toss.tech/article/tues</id>
    <link href="https://toss.tech/article/tues"/>
    <summary type="html">토스가 자체 개발한 이용서비스 기반 유저 세그먼트 TUES(Toss User Engagement Segment)를 활용해 2,800만 MAU를 어떻게 분석하고 의사결정에 녹이는지 소개합니다.</summary>
    <title>2,800만 MAU를 이해하는 유저 Segmentation, TUES</title>
    <updated>2026-06-16T10:00:00+09:00</updated>
    <dc:date>2026-06-16T10:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>인프랩</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;안녕하세요. 인프랩 백엔드 개발자 후니입니다.&lt;/p&gt;
&lt;p&gt;최근 공급망 공격(Supply-Chain-Attack)에 대한 보안 사고가 연이어 발생하고 있습니다. 올해 초 가장 논란이 되었던 &lt;a href="https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack" target="_blank" rel="nofollow noopener noreferrer"&gt;LiteLLM 공급망 공격 사건&lt;/a&gt;,
자바스크립트 생태계에서 가장 널리 사용되는 HTTP 클라이언트 라이브러리인 Axios 패키지 배포망 오염까지 정말 많은 보안 사고가 발생했습니다.
이 글에서는 공급망 공격이 어떻게 일어나는지 살펴보고, 인프랩에서 어떤 방어 대책을 세우고 있는지 공유하고자 합니다.&lt;/p&gt;
&lt;h2 id="소프트웨어-공급망-공격software-supply-chain-attack" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B3%B5%EA%B8%89%EB%A7%9D-%EA%B3%B5%EA%B2%A9software-supply-chain-attack" aria-label="소프트웨어 공급망 공격software supply chain attack permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;소프트웨어 공급망 공격(Software Supply-Chain-Attack)&lt;/h2&gt;
&lt;p&gt;소프트웨어 공급망 공격(Software Supply-Chain-Attack)은 최종 공격 대상이 되는 서비스나 기업의 인프라를 직접 타격하지 않고,
대상이 개발 과정에서 신뢰하고 끌어다 쓰는 외부 자산(오픈소스 패키지, 빌드 환경, 서드파티 서비스 등)을 먼저 침해한 뒤 이를 징검다리 삼아 최종 내부 망으로 침투하는 고도의 우회 공격 기법입니다.
신뢰할 수 있는 개발 공급망의 일부가 오염되면 해당 공급망에 의존하고 있는 인프랩 시스템 역시 연쇄적으로 오염될 수밖에 없는 구조를 가지고 있습니다.&lt;/p&gt;
&lt;h3 id="axios-패키지의-사례" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#axios-%ED%8C%A8%ED%82%A4%EC%A7%80%EC%9D%98-%EC%82%AC%EB%A1%80" aria-label="axios 패키지의 사례 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Axios 패키지의 사례&lt;/h3&gt;
&lt;p&gt;올해 3월경 발생한 Axios 사례를 간단히 설명하겠습니다. 이 사고는 개발자가 직접 작성한 코드나 명시적으로 선언한 직접 의존성이 아니라, 그 하위에 숨겨진 간접 의존성(transitive dependency) 트리를 오염시키는 방식으로 진행되었습니다.
해당 사례는 저희 사내 슬랙에서도 긴급히 공지되었는데요.&lt;/p&gt;
&lt;p&gt;&lt;span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; "&gt;
      &lt;span class="gatsby-resp-image-background-image" style="padding-bottom: 56.111111111111114%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABfklEQVQoz41SXY+bMBDM32iTEOxACAb8BQTnyFXXezypD/3/P2aqWcqJq9rqHkZrVmZ2Zta7nz/e8P3hEENA0wV0NqA2FnVjUZsOSpc4ns74esjxZX+Sup63YG9/VNgdMg0XRwz3Z4zzC+L0QJ8eiOmB2/yC9PyKMCSYxqFzvdSrsWjtIqDpPKzvRQBJd8dMo3ATcjdB+wmK1d2gfIJqAlTVYp9pcDCVHjbnj9ALIWVa14vVzka4MMCHAc4PKC8G+lyJldXq/7BYPiq0NmKcZhQX89ec1sufwY6XSRiHBF1cpbnayPJCsC7lMxDLPt4kYIZN2xzAb4btwijgEkzrJXxWgvc6F2HaZWF0KIRV3QmuZqnqXImykyrkrIsKuSrfFW9x+t1n5bKEkNOZ4S3NSHw+0xP68S49qqNqTmckZdXIshjDNu8PlimXBMzxPn8T4n5I6MckP+f6IkpZ13z/uZRDpkRFHCZYP4htZnm5touayuBc1u+gre0z+fMF/ALOeT2oJyxcMQAAAABJRU5ErkJggg=='); background-size: cover; display: block;"&gt;&lt;/span&gt;
  &lt;img class="gatsby-resp-image-image" alt="img.png" title="img.png" src="https://tech.inflab.com/static/b7fd45e5c96a2d2393e448a420f6462e/37523/axios-slack.png" srcset="/static/b7fd45e5c96a2d2393e448a420f6462e/e9ff0/axios-slack.png 180w,
/static/b7fd45e5c96a2d2393e448a420f6462e/f21e7/axios-slack.png 360w,
/static/b7fd45e5c96a2d2393e448a420f6462e/37523/axios-slack.png 720w,
/static/b7fd45e5c96a2d2393e448a420f6462e/302a4/axios-slack.png 1080w,
/static/b7fd45e5c96a2d2393e448a420f6462e/fe8a7/axios-slack.png 1223w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이 공격 사례를 간단히 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;악성 공격자가 &lt;code class="language-text"&gt;axios&lt;/code&gt; 리드 메인테이너의 npm 계정 탈취&lt;/li&gt;
&lt;li&gt;공격자가 &lt;code class="language-text"&gt;axios&lt;/code&gt; 의존성 트리에 악성 코드인 &lt;code class="language-text"&gt;plain-crypto-js@4.2.1&lt;/code&gt; 강제 주입&lt;/li&gt;
&lt;li&gt;탈취한 계정 토큰으로 npm CLI로 직접 수동 배포&lt;/li&gt;
&lt;li&gt;이 사실을 몰랐던 사용자 환경에서 &lt;code class="language-text"&gt;npm install&lt;/code&gt; 실행&lt;/li&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;postinstall&lt;/code&gt; 스크립트를 통해 백그라운드에서 악성 코드(드로퍼) &lt;code class="language-text"&gt;setup.js&lt;/code&gt; 를 실행&lt;/li&gt;
&lt;li&gt;드로퍼가 &lt;strong&gt;임의 명령실행이 가능한 RAT를 설치하였고&lt;/strong&gt;, 그 공격자가 RAT을 통해 &lt;strong&gt;자격증명을 포함한 시스템 정보가 탈취될 수 있는 상태가 됨&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;해당 &lt;a href="https://socket.dev/blog/axios-npm-package-compromised" target="_blank" rel="nofollow noopener noreferrer"&gt;링크&lt;/a&gt;에서 Axios 공격 사례를 자세히 볼 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이처럼 악성 코드가 사용자도 모르게 자동으로 실행될 수 있었던 것은 공격자가 npm lifecycle scripts를 악용했기 때문입니다.&lt;/p&gt;
&lt;h2 id="lifecycle-scripts의-실행-순서" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#lifecycle-scripts%EC%9D%98-%EC%8B%A4%ED%96%89-%EC%88%9C%EC%84%9C" aria-label="lifecycle scripts의 실행 순서 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;lifecycle scripts의 실행 순서&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://docs.npmjs.com/cli/v8/using-npm/scripts#life-cycle-operation-order" target="_blank" rel="nofollow noopener noreferrer"&gt;lifecycle scripts&lt;/a&gt;는 패키지 설치나 배포 등
특정 상황이나 이벤트가 발생할 때, 그 전후에 자동으로 맞물려 실행되도록 미리 약속된 특별한 스크립트 단계입니다.&lt;/p&gt;
&lt;p&gt;&lt;code class="language-text"&gt;npm install&lt;/code&gt; 및 &lt;code class="language-text"&gt;npm ci&lt;/code&gt; 명령어를 실행하면 아래 이미지와 같은 순서로 스크립트가 실행됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="gatsby-resp-image-figure" style=""&gt;
    &lt;span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 223px; "&gt;
      &lt;span class="gatsby-resp-image-background-image" style="padding-bottom: 237.77777777777777%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAwCAYAAAARtFotAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEa0lEQVRIx51XaXfaOhDN//9J7YeX5TQhfSltSiB9EBIgeJFtvGBjFku6PTPGhHgJztNh0GJ5PKO5s+gMALTWKFoxpp6GVdKHHtAov3/2nkF5g/6AcMT47f0zpVSFIa2Fiwy+JxEsJKJAI/QVQl8jCoCFkyEO5WFv8S6Nz8oiF3NhSTgOYJo7zGYrzOdrTKcJZrMErktMJUtaerVBZaXgCgXhSNx+f8T5RRfX1w/4+rWD+98TBCSlm+0ZvqdGlYWZQdgKjlDwXMARGq4DJttS8N1cwpMqF+PtWmGT5rReSQg7yMepxDpV2G0V6lqjhEcnyv9xsjyMC0vT9oqETbDJN2goqbHb7jAajg5z6st7D2fYpDKp5FgSnqPge8D0JUa4ABxbwrUzVMzbqDL/FDZrCdfREEKiPzDRHxjo9w04bg4prXQ9DutEL4xCDB1Hodsd4/b2Eb3eK2OQpGxUufogP3RS2bVzlUPCnQeEPsFGscqNDJusTGOZETwkkyM87rOdYirvPYnDcsthg4qLVoxSBxv60m6jsCVaS6TJFg+9Rz4GmtP5FsA+eYbUyMK2Idn16OwWLmCZknvPycfkmmVmFRwWGpAE5L/CyXBz08fV1T0HiaurX7i7G8LzcuMU0HkXYI+NovYb1isKDBq2kBgMbIxGC4yfQwyHHl5eIg5rzh6LrVyPrBhwcFWII2AZAq7YHsYUeENf1qvcBGwUc6X4y77vH+a6SDBomwJ0Odpo+OTQKOeaUzjcdxRRkqVkWsWUR3b4/WuI9QpIlmq/LmuSWgMON6mEZUjYlmaIUIQmIxmvW5hGxusEK/rwh65XWJkYEv6E2OHisovz8zv8c/4vvny5RqfThx+AfbzMsKLyMQ5tU7F0r7MNZtMUxnzH0h0kNHMJP8Rh8YCCQhLTOSmmNNFw7GU+TzTi6O0MW6eAspWXBMDS2qdSwLHZtZawLOPdWlOrN8pacrlBnkKlB/WDhzl7Cc3JU4hkRlK1UHmVSJiGgmVJjMcRxuMQs1mK5+clnscRhNBsNApvZbVrGaaJ5GgznUa4vu4xbC4uf+Ly8iduOn24bp5vcoYtcEgWNGYZA9oVlJQAYWnuac6QmmccZCsq11dfFHH0nvK84rkBz4lJ8ay169VZOo6X7WDTWIrsyw4C+XZDpcgTlFQ8J/p0KULeYBkZ/AWYppOE87Ln5m5HFdixuza6XpHoo4ByMTCZRLi/n3LVQGSaGwibkKDaliJHDB3gv6GDHz/GuLkZoNt9rjBsnQKSiFJpxpVXsMjTZ8i95vU3lVveAoq5lJKNsfAW3L+PMP+7FNGIohBtWmMapbq6oDjaoHf/h2vsNMkO6ydTQFEJLEMJe1+G0BUi8PNbAJV1PkHHA8x5AZ2TKUAzQ3pxNHK5/Pj2rYfv3//g4qKLTmcAw0jZr8uGaYyHkZ9DZjKJ8fgoMOhbeHry8fBgYjTyuUw253QsNRLWhq9VfrGhYErlR1GCJPue7n0UgPOS7tMpoP4m2mTlvxdMpxPGU84JAAAAAElFTkSuQmCC'); background-size: cover; display: block;"&gt;&lt;/span&gt;
  &lt;img class="gatsby-resp-image-image" alt="life-cycle-operation-order.png" title="이 스크립트들은 node_modules에 실제 모듈이 설치된 직후에 실행됩니다" src="https://tech.inflab.com/static/f4ed58563a09b21a8e7e1b7c5f113172/e92b6/life-cycle-operation-order.png" srcset="/static/f4ed58563a09b21a8e7e1b7c5f113172/e9ff0/life-cycle-operation-order.png 180w,
/static/f4ed58563a09b21a8e7e1b7c5f113172/e92b6/life-cycle-operation-order.png 223w" sizes="(max-width: 223px) 100vw, 223px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"&gt;
    &lt;/span&gt;
    &lt;figcaption class="gatsby-resp-image-figcaption"&gt;&lt;p&gt;이 스크립트들은 node_modules에 실제 모듈이 설치된 직후에 실행됩니다&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;예를 들어 아래와 같이 &lt;code class="language-text"&gt;package.json&lt;/code&gt;이 작성된 패키지를 &lt;code class="language-text"&gt;npm install&lt;/code&gt; 하면, 각 단계의 스크립트가 정해진 순서대로 실행되어 터미널에 출력되는 결과를 쉽게 예상할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="gatsby-resp-image-figure" style=""&gt;
    &lt;span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 588px; "&gt;
      &lt;span class="gatsby-resp-image-background-image" style="padding-bottom: 41.11111111111111%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABHUlEQVQoz21R7W6DMAzkOSZITJzvAO1oYXv/F7vKpmJq1x8nx458Pp87YxnWMjxnMEUYYowcYEeP0QeQO6LkZnAw5hXDML7EjsijHwgtLNjbL0qaEJeKtDSEqSoZ56xDpOkd78SdNXwSbu0Ht7Ih+wmckxJpTAkuRPiS4Ws54XxE/0UvKjtyAYMZkbhiqzvWekeNs9ogJCSrc4CL8cifb1EucDGpHadCl6TAIOtxzSvudVdCURBaUVXpcqwfnzaky6SQXP7F54+Et7qpj0v+RixVm4U4rzPSdULdLhqlLjUd0Mrp70EYIox1GClgSVdVGeTiJetq4l+cqzbGuaky8VVqouz94h1RUL+YE/qe9ED/rtkfkP+hp7/ah4s/APhg41+bhyLZAAAAAElFTkSuQmCC'); background-size: cover; display: block;"&gt;&lt;/span&gt;
  &lt;img class="gatsby-resp-image-image" alt="life-cycle-hook-scripts-example.png" title="lifecycle scripts 사용 예시" src="https://tech.inflab.com/static/6c6f91634595cc1d3a7bde4bab06b743/9bbaf/life-cycle-hook-scripts-example.png" srcset="/static/6c6f91634595cc1d3a7bde4bab06b743/e9ff0/life-cycle-hook-scripts-example.png 180w,
/static/6c6f91634595cc1d3a7bde4bab06b743/f21e7/life-cycle-hook-scripts-example.png 360w,
/static/6c6f91634595cc1d3a7bde4bab06b743/9bbaf/life-cycle-hook-scripts-example.png 588w" sizes="(max-width: 588px) 100vw, 588px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"&gt;
    &lt;/span&gt;
    &lt;figcaption class="gatsby-resp-image-figcaption"&gt;&lt;p&gt;lifecycle scripts 사용 예시&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;여기까지가 lifecycle scripts의 기본 동작입니다. 그렇다면 이 메커니즘을 악용한 악성 버전의 Axios는 &lt;code class="language-text"&gt;node_modules&lt;/code&gt;를 어떤 구조로 만들어 두었을까요?&lt;/p&gt;
&lt;div class="gatsby-highlight" data-language="text"&gt;&lt;pre class="language-text"&gt;&lt;code class="language-text"&gt;node_modules/
├── axios/                    &amp;lt;- 1.14.1 (악성 게시 버전)
│   ├── dist/
│   ├── lib/
│   ├── index.js
│   ├── package.json          ⚠️ dependencies에 plain-crypto-js 추가됨
│   ├── LICENSE
│   └── README.md
├── plain-crypto-js/          ⚠️ 4.2.1 (악성 의존성 crypto-js 타이포스쿼팅)
│   ├── setup.js              ⚠️ 드로퍼 (약 4209 bytes) postinstall로 자동 실행
│   ├── package.json          ⚠️ "postinstall": "node setup.js" 포함
│   ├── package.md            ⚠️ 깨끗한 4.2.0용 package.json 사본 (위장 대기)
│   ├── index.js                  (crypto-js 원본 그대로 복사)
│   ├── core.js
│   ├── aes.js
│   └── ... (나머지 crypto-js 파일들)
├── follow-redirects/         ✅ 정상 axios 의존성
├── form-data/                ✅ 정상 axios 의존성
└── proxy-from-env/           ✅ 정상 axios 의존성&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 구조에서 주목할 점은, 공격자가 &lt;code class="language-text"&gt;plain-crypto-js@4.2.1&lt;/code&gt;을 코드 어디에서도 &lt;code class="language-text"&gt;import&lt;/code&gt;하지 않았다는 것입니다.
오로지 &lt;code class="language-text"&gt;postinstall&lt;/code&gt;로 자동 실행되는 것만을 노리고, 악성 게시 버전의 의존성에 몰래 추가해 두었습니다.
그리고 그 &lt;code class="language-text"&gt;postinstall&lt;/code&gt; 단계에서 실제 공격을 수행한 것이 바로 &lt;code class="language-text"&gt;setup.js&lt;/code&gt; 드로퍼입니다.&lt;/p&gt;
&lt;h3 id="setupjs-드로퍼는-무슨-일을-했나" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#setupjs-%EB%93%9C%EB%A1%9C%ED%8D%BC%EB%8A%94-%EB%AC%B4%EC%8A%A8-%EC%9D%BC%EC%9D%84-%ED%96%88%EB%82%98" aria-label="setupjs 드로퍼는 무슨 일을 했나 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;strong&gt;setup.js 드로퍼는 무슨 일을 했나&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;setup.js(약 4.2KB)는 postinstall 단계에서 자동 실행되며, 대략 다음과 같은 순서로 동작하는 전형적인 &lt;strong&gt;자격증명 탈취형 드로퍼(credential-stealing dropper)&lt;/strong&gt; 였습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;실행 환경 판별 - 운영체제, CI 환경 여부, 분석 샌드박스로 의심되는 흔적 등을 확인합니다. 분석 환경으로 판단되면 아무 일도 하지 않고 조용히 종료해 탐지를 회피합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;민감 정보 수집 - 작업 디렉터리의 &lt;code class="language-text"&gt;.env&lt;/code&gt; 파일, &lt;code class="language-text"&gt;~/.aws/credentials&lt;/code&gt;, &lt;code class="language-text"&gt;~/.ssh&lt;/code&gt; 등 자격증명이 위치하는 알려진 경로를 훑어 토큰, 키, 시크릿을 긁어모읍니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;외부 전송(Exfiltration) - 수집한 데이터를 인코딩해 공격자가 통제하는 C2 서버로 전송합니다. 보통 한 번의 단발성 요청으로 끝나 흔적을 최소화합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;흔적 은폐 - 함께 들어있던 &lt;code class="language-text"&gt;package.md&lt;/code&gt;(깨끗한 4.2.0용 &lt;code class="language-text"&gt;package.json&lt;/code&gt; 사본)로 자신의 &lt;code class="language-text"&gt;package.json&lt;/code&gt;을 덮어써, 사후 점검 시 정상 패키지처럼 보이도록 위장합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;여기서 무서운 점은, 이 모든 과정이 개발자가 코드를 단 한 줄도 실행하기 전에, 그저 &lt;code class="language-text"&gt;npm install&lt;/code&gt; 한 번으로 백그라운드에서 모든 공격을 끝냈다는 점입니다.&lt;/p&gt;
&lt;h2 id="그래서-인프랩은-어떻게-대비하였나요" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#%EA%B7%B8%EB%9E%98%EC%84%9C-%EC%9D%B8%ED%94%84%EB%9E%A9%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8C%80%EB%B9%84%ED%95%98%EC%98%80%EB%82%98%EC%9A%94" aria-label="그래서 인프랩은 어떻게 대비하였나요 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;그래서 인프랩은 어떻게 대비하였나요?&lt;/h2&gt;
&lt;p&gt;앞서 사례로 언급드린 Axios의 경우, Axios에 주입된 악성 간접 의존성 &lt;code class="language-text"&gt;plain-crypto-js@4.2.1&lt;/code&gt;은 게시 &lt;strong&gt;6분 만에&lt;/strong&gt; 자동 분석 시스템에 탐지 되었습니다.
또한 &lt;a href="https://news.hada.io/topic?id=24537" target="_blank" rel="nofollow noopener noreferrer"&gt;주요 공급망 공격 10건을 분석한 결과&lt;/a&gt;, 이중 8건의 사례가 악성 버전이 배포된 뒤 발견되어 제거되기까지 1주일채 걸리지 않았다고 보고되었습니다.&lt;/p&gt;
&lt;p&gt;결국 저희가 세운 방어 전략은 다음 두 가지로 모아집니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cool-Down 적용&lt;/strong&gt; - 갓 게시된 버전이 곧바로 설치되지 않도록 지연시켜, 그 사이에 보안 커뮤니티의 탐지 및 신고가 이루어지도록 합니다.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;설치 시점 임의 코드 실행 차단&lt;/strong&gt; - Cool-Down 기간이 지나 악성 버전이 설치되더라도, &lt;code class="language-text"&gt;postinstall&lt;/code&gt; 같은 lifecycle scripts가 자동 실행되지 못하게 막습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 두 전략은 pnpm 10부터 공식 설정으로 지원되기 시작했습니다. 저희 팀에서도 Axios 사건 직후 Cool-Down 도입에 대한 논의가 빠르게 이루어졌습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="gatsby-resp-image-figure" style=""&gt;
    &lt;span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 571px; "&gt;
      &lt;span class="gatsby-resp-image-background-image" style="padding-bottom: 64.44444444444444%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAACRklEQVQ4y1VTWW7bQAzVFQoUTuVF+27Jo2WkkWRtdlI0Kdq/AjlZj9AL9IKvIGW7yAfBEcl58x5JaSIvsMw9StmgO8/ohhnteYJUZ1hOAMsNYd783nTxtDXYNvoBX3bm43t7sNm09/df+PvnN97eXvH19Qe+ff+JYbpimK8oKoWq7iDKBmXdIhMVwuTElooKXpAgOgrEaQ59b/EjWhClGIYRSXpClkvklYIoalRNj0K2UN2IphsgVc/Mu2HBebxgurygkIpj/LhUDK4R7U+fdSRZwUVNNzKwFx5ZphskcPyYLYgzjvtRyt+UJ6MzxW0vgnbXThdJEtEP4nTtne1z/wzbh2F7N+9zzviQW88Hy1sBiWUqSpZJ8tbBzCjrjntYNR33k2RTjupUP7LcWp3Zj8sz4lT8BySGdXuGvBXX7bAOIpccIxDqL8WzvOJHqNf0ANWpfuKWPACpB9Q/ai6xKWX7GAyxoDWiB2lIBELA65Bm5FXDiujeAzCMs0cBXSJAKiA2UXICbUOS5SyLPLE5FRJhsg5KlDX7D5JJXngUOJ5KHo7txzDdEJutiaediQ0ZLTUvs8l7R3G6f1/0FXBvwbA8uGkJsxpg5S17p+zh1iPc7gqnnuD3L/CaCZ5a4LcXeO0FhlDQaVMMF/rBuTO0eEUCIbnIVzPc9oJAzQjUgqB/htvMCPtnhGpG2F0QtgtCyqkFXtXDkwPsYwmNfhkC1XcmjODILPxmQtRfEakZcX+FX4/YmS52ho2d4ax2uJ1Nl//xNe/gHy3IjKpFbFOsAAAAAElFTkSuQmCC'); background-size: cover; display: block;"&gt;&lt;/span&gt;
  &lt;img class="gatsby-resp-image-image" alt="yakpoong-slack.png" title="동료의 쿨다운 제안." src="https://tech.inflab.com/static/87247b38f762c43861d0f680adb6c301/17d73/yakpoong-slack.png" srcset="/static/87247b38f762c43861d0f680adb6c301/e9ff0/yakpoong-slack.png 180w,
/static/87247b38f762c43861d0f680adb6c301/f21e7/yakpoong-slack.png 360w,
/static/87247b38f762c43861d0f680adb6c301/17d73/yakpoong-slack.png 571w" sizes="(max-width: 571px) 100vw, 571px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"&gt;
    &lt;/span&gt;
    &lt;figcaption class="gatsby-resp-image-figcaption"&gt;&lt;p&gt;동료의 쿨다운 제안.&lt;/p&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="패키지-매니저-통합-pnpm으로의-마이그레이션" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%A7%A4%EB%8B%88%EC%A0%80-%ED%86%B5%ED%95%A9-pnpm%EC%9C%BC%EB%A1%9C%EC%9D%98-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98" aria-label="패키지 매니저 통합 pnpm으로의 마이그레이션 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;패키지 매니저 통합: pnpm으로의 마이그레이션&lt;/h3&gt;
&lt;p&gt;당시 인프랩 Node.js 백엔드 저장소들은 어떤 곳은 pnpm을, 어떤 곳은 yarn을 사용하는 식으로 패키지 매니저가 통일된 상태는 아니었습니다.
패키지 매니저마다 보안 설정 방식이 다르기 때문에, 이런 상태에서는 앞서 이야기한 전략을 모든 저장소에 똑같이 적용하기 어려웠습니다.
그래서 보안 설정을 일관되게 적용하려면 패키지 매니저부터 하나로 맞출 필요가 있었고, 저희는 이번 기회에 &lt;strong&gt;모든 저장소를 pnpm으로 통합&lt;/strong&gt;하기로 결정하였습니다.
위 사유와 더불어 아래와 같은 배경들 덕분에 패키지 매니저 통합 결정을 빠르게 할 수 있었습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;레거시 코드가 존재하는 일부 저장소를 제외하면, 대부분의 저장소가 이미 pnpm을 사용 중이었습니다.&lt;/li&gt;
&lt;li&gt;논의를 진행하는 동안 pnpm 11 버전이 릴리스되었고, 이 버전에서는 10 버전에서 도입된 보안 설정들이 &lt;strong&gt;기본값으로 더욱 엄격하게&lt;/strong&gt; 적용되었습니다.&lt;/li&gt;
&lt;li&gt;pnpm 11은 Node.js 22 버전부터 지원하는데, 이미 일부 서비스에서 Node.js 22를 운영 환경에 적용하여 안정성이 어느 정도 검증된 상태였습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pnpm-11의-보안-강화-기능" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#pnpm-11%EC%9D%98-%EB%B3%B4%EC%95%88-%EA%B0%95%ED%99%94-%EA%B8%B0%EB%8A%A5" aria-label="pnpm 11의 보안 강화 기능 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;pnpm 11의 보안 강화 기능&lt;/h2&gt;
&lt;p&gt;pnpm 11에서는 공급망 공격에 대비할 수 있는 보안 설정들이 기본으로 활성화됩니다. 커뮤니티에서 추천하는 설정과 각 옵션의 역할을 소개합니다.&lt;/p&gt;
&lt;div class="gatsby-highlight" data-language="yaml"&gt;&lt;pre class="language-yaml"&gt;&lt;code class="language-yaml"&gt;&lt;span class="token comment"&gt;# pnpm-workspace.yaml&lt;/span&gt;
&lt;span class="token key atrule"&gt;minimumReleaseAge&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;1440&lt;/span&gt;
&lt;span class="token key atrule"&gt;minimumReleaseAgeStrict&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token boolean important"&gt;true&lt;/span&gt;
&lt;span class="token key atrule"&gt;blockExoticSubdeps&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token boolean important"&gt;true&lt;/span&gt;
&lt;span class="token key atrule"&gt;strictDepBuilds&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token boolean important"&gt;true&lt;/span&gt;
&lt;span class="token key atrule"&gt;dangerouslyAllowAllBuilds&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token boolean important"&gt;false&lt;/span&gt;
&lt;span class="token key atrule"&gt;trustPolicy&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; no&lt;span class="token punctuation"&gt;-&lt;/span&gt;downgrade

&lt;span class="token comment"&gt;# CI에서는 install이 암묵적으로 돌기보다 실패하게 하고 싶다면:&lt;/span&gt;
&lt;span class="token key atrule"&gt;verifyDepsBeforeRun&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; error&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="minimumreleaseage" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#minimumreleaseage" aria-label="minimumreleaseage permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;minimumReleaseAge&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;1440&lt;/code&gt; (pnpm 11부터, 이전 버전은 &lt;code class="language-text"&gt;0&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;분 단위 숫자&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;레지스트리에 게시된 지 지정된 시간(분)이 지나지 않은 버전은 설치 대상에서 제외합니다. &lt;code class="language-text"&gt;1440&lt;/code&gt;은 24시간을 의미합니다.
&lt;code class="language-text"&gt;^1.14.0&lt;/code&gt; 같은 캐럿 범위로 선언된 의존성이라 하더라도, 게시된 지 24시간이 지나지 않은 버전은 설치되지 않습니다.
Axios 사례처럼 악성 버전이 게시 후 6분 만에 탐지된다면, 24시간의 Cool-Down은 탐지와 대응에 넉넉한 시간을 확보해 줍니다.&lt;/p&gt;
&lt;h3 id="minimumreleaseagestrict" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#minimumreleaseagestrict" aria-label="minimumreleaseagestrict permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;minimumReleaseAgeStrict&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt; (minimumReleaseAge를 명시적으로 설정한 경우), &lt;code class="language-text"&gt;false&lt;/code&gt; (그 외)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt; / &lt;code class="language-text"&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Cool-Down 조건을 만족하는 버전이 하나도 없을 때의 동작을 결정합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt;: 설치를 &lt;strong&gt;실패&lt;/strong&gt; 시킵니다. 안전하지 않은 버전이 조용히 설치되는 것보다 설치가 실패하는 편이 안전하므로, &lt;code class="language-text"&gt;true&lt;/code&gt;로 두는 것이 권장됩니다.&lt;/li&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;false&lt;/code&gt;: 경고를 출력하되, 조건을 만족하지 않는 버전으로 &lt;strong&gt;폴백&lt;/strong&gt;하여 설치를 진행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="strictdepbuilds" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#strictdepbuilds" aria-label="strictdepbuilds permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;strictDepBuilds&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt; (pnpm 11부터)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt; / &lt;code class="language-text"&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;의존성 패키지에 빌드 스크립트(&lt;code class="language-text"&gt;preinstall&lt;/code&gt;, &lt;code class="language-text"&gt;install&lt;/code&gt;, &lt;code class="language-text"&gt;postinstall&lt;/code&gt;)가 포함되어 있는데 아직 허용 목록에 등록되지 않은 경우, 설치를 &lt;strong&gt;비정상 종료(non-zero exit)&lt;/strong&gt; 시킵니다.
Axios 사례에서 &lt;code class="language-text"&gt;plain-crypto-js&lt;/code&gt;가 &lt;code class="language-text"&gt;postinstall&lt;/code&gt;로 악성 코드를 실행했던 것과 같은 공격을 원천 차단할 수 있습니다.&lt;/p&gt;
&lt;h3 id="allowbuilds" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#allowbuilds" aria-label="allowbuilds permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;allowBuilds&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;빈 목록 (아무 패키지도 빌드 스크립트를 실행하지 못함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;패키지명: true&lt;/code&gt; 형태의 목록&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class="language-text"&gt;strictDepBuilds&lt;/code&gt;가 모든 빌드 스크립트를 막아버리기 때문에, 빌드 스크립트가 &lt;strong&gt;정상적인 동작에 꼭 필요한 패키지&lt;/strong&gt;까지 함께 차단되는 문제가 생깁니다.
예를 들어 &lt;code class="language-text"&gt;esbuild&lt;/code&gt;, &lt;code class="language-text"&gt;sharp&lt;/code&gt;처럼 네이티브 바이너리를 직접 컴파일하는 패키지는 &lt;code class="language-text"&gt;postinstall&lt;/code&gt;로 바이너리를 받거나 빌드해야 정상 동작합니다.
이런 패키지를 &lt;code class="language-text"&gt;allowBuilds&lt;/code&gt;에 등록하면, 해당 패키지에 한해 빌드 스크립트 실행을 &lt;strong&gt;명시적으로 허용&lt;/strong&gt;할 수 있습니다.&lt;/p&gt;
&lt;div class="gatsby-highlight" data-language="yaml"&gt;&lt;pre class="language-yaml"&gt;&lt;code class="language-yaml"&gt;&lt;span class="token comment"&gt;# pnpm-workspace.yaml&lt;/span&gt;
&lt;span class="token key atrule"&gt;allowBuilds&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt;
  &lt;span class="token key atrule"&gt;esbuild&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token boolean important"&gt;true&lt;/span&gt;
  &lt;span class="token key atrule"&gt;sharp&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token boolean important"&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;즉, &lt;code class="language-text"&gt;strictDepBuilds&lt;/code&gt;가 기본적으로 모든 문을 잠그는 설정이라면, &lt;code class="language-text"&gt;allowBuilds&lt;/code&gt;는 신뢰할 수 있는 패키지에만 열쇠를 내어주는 &lt;strong&gt;화이트리스트&lt;/strong&gt; 역할을 합니다.&lt;/p&gt;
&lt;p&gt;다만 주의할 점이 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;패키지를 등록한다는 것은 곧 &lt;strong&gt;그 패키지의 빌드 스크립트가 임의 코드를 실행하도록 허용&lt;/strong&gt;한다는 의미입니다. 등록 전에 정말 빌드 스크립트가 필요한 패키지인지, &lt;strong&gt;신뢰할 수 있는 출처인지 반드시 확인해야 합니다.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;설치가 실패한다고 해서 습관적으로 목록에 추가하지 말고, 목록은 &lt;strong&gt;최소한으로&lt;/strong&gt; 유지하는 것이 좋습니다. 허용 항목이 늘어날수록 그만큼 공격 표면도 함께 넓어집니다.&lt;/li&gt;
&lt;li&gt;번거롭다는 이유로 뒤에 설명할 &lt;code class="language-text"&gt;dangerouslyAllowAllBuilds: true&lt;/code&gt;로 한 번에 열어버리면 &lt;code class="language-text"&gt;strictDepBuilds&lt;/code&gt;의 의미가 사라지므로, 반드시 &lt;code class="language-text"&gt;allowBuilds&lt;/code&gt;로 패키지를 하나씩 허용하는 방식을 권장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="dangerouslyallowallbuilds" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#dangerouslyallowallbuilds" aria-label="dangerouslyallowallbuilds permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;dangerouslyAllowAllBuilds&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class="language-text"&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt; / &lt;code class="language-text"&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이름에 &lt;code class="language-text"&gt;dangerously&lt;/code&gt;가 붙어 있는 것에서 알 수 있듯이, 이 옵션을 &lt;code class="language-text"&gt;true&lt;/code&gt;로 설정하면 &lt;strong&gt;모든 의존성의 빌드 스크립트를 무조건 허용&lt;/strong&gt;합니다. &lt;code class="language-text"&gt;strictDepBuilds&lt;/code&gt;를 무력화하므로, 반드시 &lt;code class="language-text"&gt;false&lt;/code&gt;로 유지해야 합니다.&lt;/p&gt;
&lt;h3 id="blockexoticsubdeps" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#blockexoticsubdeps" aria-label="blockexoticsubdeps permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;blockExoticSubdeps&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt; (pnpm 11부터)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;true&lt;/code&gt; / &lt;code class="language-text"&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;간접 의존성(transitive dependency)이 npm 레지스트리가 아닌 &lt;strong&gt;이질적인(exotic) 소스&lt;/strong&gt;(Git URL, HTTP tarball 등)에서 설치되는 것을 차단합니다.
직접 의존성은 개발자가 의도적으로 선언한 것이므로 허용하되, 하위 의존성 트리에서 예상치 못한 외부 소스로 우회하는 공격을 방지합니다.&lt;/p&gt;
&lt;h3 id="trustpolicy" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#trustpolicy" aria-label="trustpolicy permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;trustPolicy&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;미설정 (비활성)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;no-downgrade&lt;/code&gt; / &lt;code class="language-text"&gt;off&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class="language-text"&gt;no-downgrade&lt;/code&gt;로 설정하면, 이전 버전 대비 패키지의 &lt;strong&gt;신뢰 수준이 하락&lt;/strong&gt;한 경우 설치를 실패시킵니다.&lt;/p&gt;
&lt;p&gt;npm 패키지의 신뢰 수준은 게시 방식에 따라 크게 세 단계로 나뉩니다. 위에서 아래로 갈수록 신뢰 수준이 낮아집니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;신뢰 수준&lt;/th&gt;
&lt;th&gt;게시 방식&lt;/th&gt;
&lt;th&gt;검증 범위&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trusted Publisher&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitHub Actions 등 CI/CD에서 자동 게시&lt;/td&gt;
&lt;td&gt;게시자 신원과 빌드 출처를 모두 검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Provenance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;서명·attestation은 있으나 Trusted Publisher는 아님&lt;/td&gt;
&lt;td&gt;빌드 출처는 검증되나 게시자 신원은 미검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;None&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;npm CLI로 수동 게시&lt;/td&gt;
&lt;td&gt;아무런 증명 없음, 누가 어디서 빌드했는지 알 수 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class="language-text"&gt;trustPolicy: no-downgrade&lt;/code&gt;는 신뢰 수준이 유지되거나 높아지는 변경은 허용하고, &lt;strong&gt;낮아지는 방향의 변경&lt;/strong&gt;만 차단합니다.
예를 들어 &lt;code class="language-text"&gt;axios@1.14.0&lt;/code&gt;에서 &lt;code class="language-text"&gt;axios@1.14.1&lt;/code&gt;로 올라갈 때, 신뢰 수준 변화에 따라 다음과 같이 동작합니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;변경 전 → 변경 후&lt;/th&gt;
&lt;th&gt;신뢰 수준&lt;/th&gt;
&lt;th&gt;설치&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trusted Publisher → Trusted Publisher&lt;/td&gt;
&lt;td&gt;유지&lt;/td&gt;
&lt;td&gt;허용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provenance → Trusted Publisher&lt;/td&gt;
&lt;td&gt;상승&lt;/td&gt;
&lt;td&gt;허용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;None → Provenance&lt;/td&gt;
&lt;td&gt;상승&lt;/td&gt;
&lt;td&gt;허용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trusted Publisher → Provenance&lt;/td&gt;
&lt;td&gt;하락&lt;/td&gt;
&lt;td&gt;차단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trusted Publisher → None&lt;/td&gt;
&lt;td&gt;하락 (Axios 공격 사례)&lt;/td&gt;
&lt;td&gt;차단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provenance → None&lt;/td&gt;
&lt;td&gt;하락&lt;/td&gt;
&lt;td&gt;차단&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Axios 공격 사례에서 공격자는 탈취한 계정 토큰으로 &lt;code class="language-text"&gt;npm CLI&lt;/code&gt;를 통해 수동 배포했습니다.
기존 Axios는 Trusted Publisher로 게시되고 있었으므로, 신뢰 수준이 &lt;code class="language-text"&gt;Trusted Publisher → None&lt;/code&gt;으로 급락하게 됩니다.
&lt;code class="language-text"&gt;trustPolicy: no-downgrade&lt;/code&gt;가 설정되어 있었다면, 이 시점에서 설치가 차단되어 공격을 사전에 막을 수 있었습니다.&lt;/p&gt;
&lt;h3 id="verifydepsbeforerun" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#verifydepsbeforerun" aria-label="verifydepsbeforerun permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;verifyDepsBeforeRun&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;기본값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class="language-text"&gt;install&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정값&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code class="language-text"&gt;install&lt;/code&gt; / &lt;code class="language-text"&gt;warn&lt;/code&gt; / &lt;code class="language-text"&gt;error&lt;/code&gt; / &lt;code class="language-text"&gt;prompt&lt;/code&gt; / &lt;code class="language-text"&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code class="language-text"&gt;pnpm run&lt;/code&gt;이나 &lt;code class="language-text"&gt;pnpm exec&lt;/code&gt;를 실행하기 전에 의존성 상태를 검증합니다. CI 환경에서 의존성이 불완전한 상태로 스크립트가 실행되는 것을 막으려면 &lt;code class="language-text"&gt;error&lt;/code&gt;로 두는 것이 권장됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;install&lt;/code&gt;: 의존성이 불완전하면 자동으로 &lt;code class="language-text"&gt;pnpm install&lt;/code&gt;을 실행합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;warn&lt;/code&gt;: 경고만 출력하고 계속 진행합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;error&lt;/code&gt;: 의존성이 불완전하면 &lt;strong&gt;실행을 중단&lt;/strong&gt;합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;prompt&lt;/code&gt;: 사용자에게 설치 여부를 대화형으로 묻습니다.&lt;/li&gt;
&lt;li&gt;
&lt;code class="language-text"&gt;false&lt;/code&gt;: 검증을 하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;이처럼 pnpm 11은 대부분의 보안 설정이 기본값만으로도 강력하게 보호를 할 수 있습니다.
악성 버전의 게시 자체를 막을 수는 없지만, 라이브러리를 소비하는 입장에서 즉시 자동 전파되는 구조를 &lt;strong&gt;“지연”으로 전환&lt;/strong&gt;하여, 그 사이에 보안 커뮤니티의 탐지와 신고가 이루어지도록 시간을 벌 수 있습니다.&lt;/p&gt;
&lt;h2 id="패키지-매니저-마이그레이션-팁" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%A7%A4%EB%8B%88%EC%A0%80-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98-%ED%8C%81" aria-label="패키지 매니저 마이그레이션 팁 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;패키지 매니저 마이그레이션 팁&lt;/h2&gt;
&lt;h3 id="이미-pnpm을-쓰고-있다면-버전-업데이트" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#%EC%9D%B4%EB%AF%B8-pnpm%EC%9D%84-%EC%93%B0%EA%B3%A0-%EC%9E%88%EB%8B%A4%EB%A9%B4-%EB%B2%84%EC%A0%84-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8" aria-label="이미 pnpm을 쓰고 있다면 버전 업데이트 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;이미 pnpm을 쓰고 있다면 (버전 업데이트)&lt;/h3&gt;
&lt;p&gt;앞서 소개한 보안 설정들은 pnpm 11 기준입니다. 그렇다면 이미 구버전 pnpm을 사용하고 있는 저장소는 어떻게 11까지 올려야 할까요?&lt;/p&gt;
&lt;p&gt;여기서 한 가지 유의할 점이 있습니다. pnpm의 마이그레이션 가이드는 &lt;strong&gt;메이저 버전을 한 단계씩 올릴 때를 기준으로 제공&lt;/strong&gt;됩니다.
예를 들어 8 → 9, 9 → 10, 10 → 11처럼 각 단계별로 변경된 동작과 마이그레이션 방법이 문서화되어 있습니다.&lt;/p&gt;
&lt;p&gt;따라서 pnpm 8에서 11로 곧장 점프하기보다는, &lt;strong&gt;한 메이저 버전씩 차근차근 올리는 방식을 권장&lt;/strong&gt;합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 단계마다 어떤 동작이 바뀌었는지 공식 마이그레이션 가이드로 확인할 수 있습니다.&lt;/li&gt;
&lt;li&gt;한 번에 여러 버전을 건너뛰면, 어느 단계에서 문제가 생겼는지 원인을 추적하기 어렵습니다.&lt;/li&gt;
&lt;li&gt;단계별로 올리면 &lt;code class="language-text"&gt;pnpm install&lt;/code&gt;과 테스트를 거치며 변경 사항을 점진적으로 검증할 수 있어, 잠금 파일(&lt;code class="language-text"&gt;pnpm-lock.yaml&lt;/code&gt;)이나 의존성 해석 방식의 차이로 인한 문제를 조기에 발견할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;저희도 혼용하던 패키지 매니저를 pnpm으로 통합하고 11까지 올리는 과정에서, 단계별 업데이트가 디버깅 부담을 크게 줄여준다는 것을 체감할 수 있었습니다.&lt;/p&gt;
&lt;h3 id="다른-패키지-매니저npm-yarn를-쓰고-있다면" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#%EB%8B%A4%EB%A5%B8-%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%A7%A4%EB%8B%88%EC%A0%80npm-yarn%EB%A5%BC-%EC%93%B0%EA%B3%A0-%EC%9E%88%EB%8B%A4%EB%A9%B4" aria-label="다른 패키지 매니저npm yarn를 쓰고 있다면 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;다른 패키지 매니저(npm, yarn)를 쓰고 있다면&lt;/h3&gt;
&lt;p&gt;한편 아직 yarn이나 npm을 쓰고 있어 pnpm으로 처음 넘어와야 하는 저장소라면, &lt;a href="https://pnpm.io/cli/import" target="_blank" rel="nofollow noopener noreferrer"&gt;pnpm import&lt;/a&gt; 명령으로 기존 &lt;code class="language-text"&gt;yarn.lock&lt;/code&gt;이나 &lt;code class="language-text"&gt;package-lock.json&lt;/code&gt;을 기반으로 &lt;code class="language-text"&gt;pnpm-lock.yaml&lt;/code&gt;을 생성할 수 있습니다.
의존성 버전을 처음부터 다시 해석하지 않고 기존 잠금 상태를 그대로 가져올 수 있어, 마이그레이션 초기의 버전 변동을 줄이는 데 도움이 됩니다.&lt;/p&gt;
&lt;h2 id="마무리" style="position:relative;"&gt;
&lt;a href="https://tech.inflab.com/20260601-supply-chain-attack/#%EB%A7%88%EB%AC%B4%EB%A6%AC" aria-label="마무리 permalink" class="anchor before"&gt;&lt;svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"&gt;&lt;path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h2&gt;
&lt;p&gt;이번 글에서 다룬 공격 경로는 &lt;code class="language-text"&gt;postinstall&lt;/code&gt; 스크립트를 악용한 &lt;strong&gt;설치 시점 공격&lt;/strong&gt;이었습니다.
하지만 이 경로만 차단한다고 해서 공급망 공격을 완벽하게 막을 수 있는 것은 아닙니다.
설치 스크립트에 대한 방어가 강화될수록, 공격자들은 다음 공격 지점으로 옮겨갈 가능성이 큽니다.&lt;/p&gt;
&lt;p&gt;일종의 두더지 잡기와 같습니다. 설치 스크립트 차단과 Cool-Down은 가장 흔한 설치 시점 공격을 효과적으로 줄여주지만, &lt;code class="language-text"&gt;import&lt;/code&gt; 시점이나 런타임에서 실행되는 악성 코드에는 무력합니다.
예를 들어 패키지의 정상적인 모듈 코드 내부에 난독화된 악성 로직을 삽입하는 방식은 설치 스크립트 차단만으로는 탐지할 수 없습니다.&lt;/p&gt;
&lt;p&gt;따라서 설치 시점 방어는 개발자들이 지켜내야할 &lt;strong&gt;최소한의 기본 방어선&lt;/strong&gt;이며, 앞으로는 더 다양한 방어 체계를 고려해야 합니다.&lt;/p&gt;
&lt;p&gt;긴 글 읽어주셔서 감사합니다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://tech.inflab.com/20260601-supply-chain-attack/</id>
    <link href="https://tech.inflab.com/20260601-supply-chain-attack/"/>
    <summary type="html">안녕하세요. 인프랩 백엔드 개발자 후니입니다. 최근 공급망 공격(Supply-Chain-Attack)에 대한 보안 사고가 연이어 발생하고 있습니다. 올해 초 가장 논란이 되었던 LiteLLM…</summary>
    <title>소프트웨어 공급망 공격, pnpm으로 1차 방어선 구축하기</title>
    <updated>2026-06-19T00:00:00+09:00</updated>
    <dc:date>2026-06-19T00:00:00+09:00</dc:date>
  </entry>
  <dc:date>2026-06-19T21:40:00+09:00</dc:date>
</feed>
