<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel xmlns:content="http://purl.org/rss/1.0/modules/content/"><title>요즘IT » 개발 » 피드</title><link>https://yozm.wishket.com/magazine/list/develop</link><description>쉽고 재미있는 IT 이야기를 다룹니다. 업계 전문가들이 전하는 IT 트렌드, 기획, 디자인, 개발, 인사이트 소식들이 가득합니다.</description><atom:link href="https://yozm.wishket.com/magazine/list/develop/feed/" rel="self"/><language>ko-kr</language><lastBuildDate>Fri, 21 Aug 2026 14:35:29 +0000</lastBuildDate><item><title>채용 공고 1만 건에서 뽑아낸 ‘AI 엔지니어링 스킬 맵’</title><link>https://yozm.wishket.com/magazine/detail/3909</link><description>남들이 미리 밟아본 길을 따라 걸으면 어딘가에 도착하던 시대는 끝난 것 같습니다. 그렇다면 지금 필요한 건 정해진 목적지로 가는 지도보다 멈춰서지는 않게 해주는 이정표일 텐데, 스탠퍼드 교수이자 AI 대가인 앤드류 응(Andrew Ng)이 채용 공고 1만 건과 수십 건의 인터뷰를 분석해 그 이정표를 내놓았습니다. AI 애플리케이션 구축, 소프트웨어 엔지니어링 기본기, 코딩 에이전트 활용, 무엇을 만들지 형태 잡기. 이 네 가지 스킬이 왜 중요한지, 그리고 그 밑에 깔린 마인드셋까지 정리했습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3909</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;“이 로드맵대로 공부하면 취업할 수 있다”는 글을 요즘도 종종 봅니다. 그런데 이상하게 예전만큼 그런 말에 눈이 가지 않더라고요. 로드맵이 가리키는 목적지가 반년 뒤에도 그대로 있을 거라는 확신이 없어서 그렇습니다. 남들이 미리 밟아본 길을 따라 걸으면 어딘가에 도착하던 시대는 끝난 것 같습니다. 지금 필요한 건 정해진 목적지로 가는 지도보다 이 혼란기에 적어도 멈춰서지는 않게 해주는 이정표가 아닐까 싶습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마침 그런 이정표로 삼을 만한 글이 하나 올라왔습니다. 스탠퍼드 교수이자 세계적인 AI 대가 앤드류 응&lt;span style="color:#999999;"&gt;(Andrew Ng)&lt;/span&gt;이 지난 8월 14일 공개한 아티클 “&lt;a href="https://x.com/AndrewYNg/status/2088302050706686198"&gt;The AI Engineering Skills Map&lt;/a&gt;”입니다. 그는 주요 AI 이론을 정립한 연구자이자, 코세라&lt;span style="color:#999999;"&gt;(Coursera)&lt;/span&gt;와 딥러닝.AI&lt;span style="color:#999999;"&gt;(DeepLearning.AI)&lt;/span&gt;처럼 유명한 교육 플랫폼을 창립한 교육자이기도 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그러한 AI 업계의 멘토가 제시한 지도를 따라가며, 이 시대의 생존을 위해 필요한 스킬이 무엇인지, 그 능력을 얻기 위해 실제로 무엇을 할 줄 알아야 할지 정리해 봤습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3909/img-01.png" alt="Andrew Ng이 X에 올린 AI 엔지니어링 스킬 맵 — AI 앱 구축·배포, SW 기본기, 코딩 에이전트 활용, 빌드 형태 잡기 네 갈래로 나뉜 다이어그램"&gt;&lt;figcaption&gt;&amp;lt;출처: &lt;a href="https://x.com/AndrewYNg/status/2088302050706686198"&gt;Andrew Ng X&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#757575;"&gt;- Andrew Ng, 〈&lt;/span&gt;&lt;a href="https://x.com/AndrewYNg/status/2088302050706686198"&gt;The AI Engineering Skills Map&lt;/a&gt;&lt;span style="color:#757575;"&gt;〉&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;글에서 이탈릭 체로 처리한 모든 대화체는 아티클에서 인용한 글입니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;지금 가장 중요한 AI 엔지니어링 스킬 4가지&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이런 종류의 글은 대개 유명한 분들의 직관에서 나오는 것을 많이 봤습니다. 그런데 이번 스킬 맵의 출처는 데이터라고 합니다. AI 덕분에 전과는 전혀 다른 방식으로 소프트웨어를 만들 수 있게 됐고 기회도 많아졌는데, 정작 AI를 둘러싼 정보 환경은 &lt;i&gt;“시끄럽고 과장으로 가득”&lt;/i&gt;합니다. 그래서 지금 배울 가치가 가장 큰 스킬이 무엇인지를 데이터로 추려 보기로 했다는 겁니다. 개발자에게는 무엇을 먼저 배울지 우선순위를, 고용주에게는 숙련된 개발자를 알아보는 기준을 주겠다는 목적으로요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;응 교수의 팀은 1만 건이 넘는 채용 공고를 분석했습니다. AI 전문가와 채용 관리자, 리크루터를 상대로 수십 건의 구조화된 인터뷰를 진행하고 설문과 온라인 데이터까지 종합했고요. 그렇게 뽑아낸 가장 중요한 AI 엔지니어링 스킬이 네 가지입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;AI 애플리케이션을 만들고 배포하기&lt;/li&gt;&lt;li&gt;소프트웨어 엔지니어링 기본기&lt;/li&gt;&lt;li&gt;코딩 에이전트 사용하기&lt;/li&gt;&lt;li&gt;그리고 무엇을 만들지 형태를 잡기&lt;span style="color:#999999;"&gt;(Shaping the build)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;목록에는 새로운 프레임워크 이름도, 뜨는 도구 이름도 없습니다. 이는 다분히 의도된 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;응 교수는 이번 스킬 맵이 ‘AI 엔지니어’라는 직무 대신 ‘AI 엔지니어링’이란 영역을 다룬다고 단언합니다. &lt;i&gt;“나는 ‘AI 엔지니어’라는 직무&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;(AI 시스템을 만드는 것이 일인 사람)&lt;/i&gt;&lt;/span&gt;&lt;i&gt;가 아니라 ‘AI 엔지니어링 스킬’을 이야기한다. 후자가 훨씬 넓기 때문”&lt;/i&gt;이라고요. 오늘날 모든 개발자는 클라우드를 다룰 줄 알아야 하지만 ‘클라우드 엔지니어’라는 직함을 가진 사람은 그보다 훨씬 적은 것처럼, 풀스택이든 데이터든 데브옵스든 머신러닝이든 모든 개발자가 AI 엔지니어링 스킬을 필요로 하게 될 거라는 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 관점이 기존 스킬 로드맵과의 가장 큰 차이라고 생각합니다. 특정 직무로 갈아타기 위한 목록이 아니라, 지금 자기 직무를 그대로 가진 채, 새로 더해야 하는 스킬의 목록이라는 거죠. 그럼 하나씩 보겠습니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;1. AI 애플리케이션을 만들고 배포하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;첫 번째 스킬은 AI 애플리케이션을 만들고 배포하는 것입니다. 응 교수는 AI 애플리케이션과 그렇지 않은 애플리케이션의 핵심 차이를 한 문장으로 정리합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;“AI 애플리케이션과 AI가 아닌 애플리케이션의 핵심 차이는, 전자는 출력을 예측할 수 없다는 점이다.”&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;우리는 LLM에 프롬프트를 넣을 때 무엇이 돌아올지 알 수 없습니다. 또, 딥러닝 알고리즘을 학습시킬 때 새 예시에 어떤 예측을 내놓을지 알 수 없습니다. 반면 전통적인 소프트웨어는 훨씬 예측 가능하게 동작하죠. 같은 입력에는 같은 출력이 나오도록 짜는 게 지금까지의 개발이었으니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇다면 이 스킬에 능숙하다는 건 무엇을 할 줄 안다는 걸까요. 응 교수에 따르면 LLM, 컨텍스트 엔지니어링, RAG, 에이전틱 워크플로, 머신러닝과 딥러닝 같은 AI의 구성 요소를 이해하는 것이 바탕이 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 그가 &lt;i&gt;“무엇보다”&lt;/i&gt;라며 강조하는 건 따로 있습니다. 통계적 기법으로 AI 시스템을 측정하고 방향을 잡고 통제해, 더 예측 가능하게 행동하도록 만들 줄 아는 것. 그리고 그 핵심은 규율 있는 평가&lt;span style="color:#999999;"&gt;(eval)&lt;/span&gt;와 오류 분석 루프를 굴릴 줄 아는 기술에 있다고 합니다. 예측할 수 없다는 특성을 없앨 수는 없으니, 측정하고 좁혀가는 루프를 사람이 돌릴 줄 알아야 한다는 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3909/img-02.png" alt="여러 겹의 투명 유리 패널을 파란 실선이 관통하며 통과하는 3D 렌더링 — AI 모델 내부에서 데이터가 층층이 처리되는 과정을 은유적으로 표현"&gt;&lt;figcaption&gt;&amp;lt;출처: Google DeepMind&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;2. 소프트웨어 엔지니어링 기본기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;두 번째는 소프트웨어 엔지니어링 기본기입니다. AI가 코드를 다 짜주는 시대에 기본기라니, 목록에서 가장 의아한 항목일 수 있는데요. 응 교수의 논리는 이렇습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;소프트웨어를 엔지니어링한다는 건 비용, 확장성, 신뢰성, 속도 사이에서 트레이드오프를 하는 일이고, 보안과 프라이버시가 여기에 복잡성을 더합니다. 기본기를 이해하면 애초에 어떤 트레이드오프가 존재하는지를 알아볼 수 있습니다. 그 결과 소프트웨어 스택 선택, 시스템 아키텍처 설계, 데이터 저장소 설계, 테스트 같은 결정이 더 나아집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;대비되는 인물은 누굴까요? 코딩 에이전트가 어떤 트레이드오프를 하고 있는지도 모른 채 바이브 코딩으로 해법을 만들어내는 미숙한 개발자입니다. 응 교수는 이들의 결과가 나쁜 이유를 &lt;i&gt;“코딩 에이전트에 어떤 컨텍스트를 줘야 하는지 모르기 때문”&lt;/i&gt;이라고 짚습니다. 반대로 기본기를 이해하면 &lt;i&gt;“소프트웨어 엔지니어링의 정확한 언어로 코딩 에이전트를 조종해 좋은 트레이드오프를 할 수 있다”&lt;/i&gt;고 하고요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그러니까 기본기를 익혀야 하는 ‘필요’가 바뀐 겁니다. 예전에는 내 손으로 좋은 코드를 짜기 위해 기본기가 필요했다면, 이제는 에이전트에 무엇을 시킬지 정확한 언어로 말하기 위해 필요합니다. 즉, “이 API는 캐시를 두되 무효화 조건을 이렇게 걸어라”라고 말할 수 있는 사람과 “빠르게 만들어줘”라고밖에 못 하는 사람의 차이는, 타이핑 실력이 아니라 트레이드오프를 알아채는 지식에서 갈립니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3909/img-03.png" alt="블러 처리된 모니터 화면 속 파이썬 코드 — 지진 이벤트 데이터를 JSON으로 불러와 반복문으로 파싱하는 코드가 담겨 있다"&gt;&lt;figcaption&gt;&amp;lt;출처: Pexels&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;3. 코딩 에이전트 사용하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;세 번째는 코딩 에이전트 사용하기입니다. 응 교수는 에이전틱 코딩을 효과적으로 쓰는 것이 이제 모든 개발자의 핵심 스킬이라고 말합니다. 그렇다면 ‘숙련된 기술’을 가진 개발자의 모습은 무엇일까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 스킬을 갖춘 사람은 에이전트가 어떻게 동작하는지에 대한 좋은 ‘멘탈 모델’을 가지고 있습니다. 글에 따르면 &lt;i&gt;“에이전트의 한계와 그 한계를 우회하는 방법을 이해하고, 빠르게 방향을 잡아줄 수 있다 — 얼마나 개입하고 얼마나 내버려둘지를 알고 — 그래서 시간과 토큰을 지나치게 낭비하지 않으면서 견고한 소프트웨어”&lt;/i&gt;를 만들 수 있다는 뜻입니다. 어느 도구의 어느 기능을 쓸 줄 아느냐가 아니라, 언제 손을 대고 언제 손을 뗄지 판단하는 능력이 진짜 스킬이라는 얘기입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;구체적으로 할 줄 알아야 하는 것들 목록도 있습니다. 1) 코딩 에이전트의 컨텍스트를 관리할 줄 알아야 하고, 2) 계획과 실행 사이의 트레이드오프를 할 줄 알아야 합니다. 3) 검증기&lt;span style="color:#999999;"&gt;(verifier)&lt;/span&gt;나 평가를 제공해 에이전트가 스스로 루프를 닫도록 도울 줄도 알아야 하죠. 4) 명확한 스펙을 가지고 일하는 법과 굳이 그럴 필요가 없는 때가 언제인지 아는 것, 5) 여러 에이전트를 함께 동작하도록 오케스트레이션하는 법, 6) 에이전트가 프로덕션 데이터베이스를 망가뜨리는 것 같은 함정을 피하는 법도요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하나하나가 도구 매뉴얼보다는 판단 기준에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;무엇보다 에이전틱 코딩은 빠르게 진화하고 있습니다. 그래서 코딩 에이전트를 능숙하게 쓴다는 건 최신 실천법을 아는 것뿐 아니라 새로운 도구를 계속 시도해 보고 모범 사례가 바뀔 때마다 자기 워크플로를 진화시키는 루틴을 갖추는 것을 뜻합니다. 오늘 익힌 도구 활용법은 몇 달 지나면 낡은 것으로 바뀝니다. 그래서 이 스킬의 핵심은 빠르게 루틴을 갱신할 힘에 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3909/img-04.png" alt="코딩 에이전트 화면 — ‘다크모드 토글 추가’ 요청에 ThemeProvider.tsx를 수정하고, 우측 미리보기엔 Appearance 설정에 Light/Dark 버튼이 반영됐다"&gt;&lt;figcaption&gt;&amp;lt;출처: Anthropic&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;4. 무엇을 만들지 형태를 잡기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;네 번째 스킬의 이름이 ‘무엇을 만들지 형태를 잡기’입니다. 명확한 스펙을 줄수록 코딩 에이전트가 그것을 구현해 내는 능력은 빠르게 좋아지고 있습니다. 그러니 엔지니어의 일은 스펙에 무엇이 들어가야 하는지를 결정하는 쪽으로 옮겨 가고 있습니다. 응 교수는 꽤 단호하게 말합니다. &lt;i&gt;“엔지니어는 더 이상 픽셀 단위까지 완성된 디자인을 받아서 구현만 하도록 요구받는 존재로 스스로를 기대해서는 안 된다.”&lt;/i&gt;고요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;대신 요구되는 건 제품, 그리고 비즈니스 맥락과 고객의 목표에 대한 이해입니다. 그래야 무엇을 만들지 형태를 잡고 추진하는 데 참여할 수 있으니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;응 교수는 &lt;i&gt;“AI가 전보다 더 큰 주인의식과 주도권을 가질 기회를 준다”&lt;/i&gt;고도 덧붙입니다. 흥미로운 문제와 기회를 스스로 발견하고 책임 있게 실행에 옮길 수 있게 됐다는 겁니다. 이 기회를 잡으려면 프로젝트를 앞으로 밀고 나가는 법을 알아야 합니다. 언제 빠르게 MVP를 만들어 사용자에게 가져가 테스트할지, 언제 속도를 늦추고 시간을 더 들여 신중하게 만들지를 아는 것.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;만드는 속도 자체는 더 이상 병목이 아니니, 어떤 속도로 만들지 정하는 게 스킬이 된 겁니다. 구현 능력을 갈고닦아 온 사람에게는 불편한 변화일 수 있지만, 방향은 분명해 보입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3909/img-05.png" alt="하얀 로봇 손이 키보드 자판들을 그릇에 담아내는 흑백 사진 — Ctrl 키 등 낱개 키캡이 담겨 있다"&gt;&lt;figcaption&gt;&amp;lt;출처: Pexels&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;스킬보다 더 중요한 ‘마인드셋’ 하나&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;마지막으로, 이 모든 스킬 밑에 깔려 있는 것은 ‘꾸준히 학습을 멈추지 않겠다’는 마인드셋입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;“AI는 계속 빠르게 변하기 때문에, 우리 모두 계속 배우고 스킬을 진화시켜 새롭게 떠오르는 모범 사례를 받아들여야”&lt;/i&gt;합니다. 그리고 이 모든 것이 저 4가지 역량을 키우는 토대가 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이렇게 보니 네 가지 스킬의 공통점이 보입니다. 전부 외워두면 끝나는 지식이 아니라 계속 굴려야 하는 루프라는 거죠. 코딩 에이전트 워크플로는 모범 사례가 바뀔 때마다 다시 짜야 하고, 무엇을 만들지 정하는 힘도 시장과 모델이 바뀌는 것을 따라가야 합니다. 이제 AI는 스스로 다루는 걸 멈추는 순간 무뎌지다 못해 손에서 사라져 버리는 칼로 변했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 저는 요즘 자주 쓰이는 ‘언런&lt;span style="color:#999999;"&gt;(unlearn)&lt;/span&gt;’이라는 말을 떠올렸습니다. 언제나 새로 배우려는 마음가짐. 대신, 가진 것을 모조리 버리라는 말로 이해하지는 않고 있습니다. 기본기 항목에서 봤듯 옛 지식은 버려지는 게 아니라 쓰는 방식이 바뀌는 것뿐이라고 생각하니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;변화의 속도에 압도돼 아무것도 손에 안 잡히는 상태야말로 피해야 할 것이겠죠. 혼란과 두려움에 갇혀 있는 대신, 지금 다룰 수 있는 것을 다뤄 보면서 스스로를 갱신해 나가는 것. 응 교수의 표현으로는 지속 학습 마인드셋, 이것이야말로 진짜 역량이 아닐까 합니다.&lt;/p&gt;&lt;hr&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;여러분은 에이전트에 정확한 언어로 트레이드오프를 말할 수 있나요? 개입할 때와 내버려 둘 때를 제대로 구분하고 있나요? 스펙을 받기만 하는지, 아니면 스스로 스펙을 정하고 있나요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;응 교수의 지도는 목적지를 약속하지 않습니다. 이 네 가지를 익히면 어떤 직함과 어느 정도 연봉에 도달한다는 식의 보장은 어디에도 없습니다. 대신 지금 무엇을 공부하고 익혀야 하는지는 비교적 잘 보여준다고 느낍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그리고 지금 같은 혼란기에는, 어쩌면 그게 바랄 수 있는 전부이자 가장 필요한 것일지도 모르겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>클로드 코드 제대로 써먹는 프롬프트 작성 팁 6가지</title><link>https://yozm.wishket.com/magazine/detail/3907</link><description>같은 에이전트를 만들더라도 요청 방식에 따라 결과물의 완성도는 크게 달라집니다. 배경과 목적, 제약을 먼저 설명해야 클로드 코드가 상황에 맞는 결과물을 설계할 수 있고, 이메일·PDF·JSON 등 매체에 맞는 출력 형식과 예외 처리까지 미리 말해 두면 결과의 신뢰도가 달라집니다. 복잡한 작업은 단계별로 나눠 요청하고, 결과가 마음에 들지 않을 때는 무엇이·왜·어떻게 문제인지 짚어야 원하는 방향에 닿습니다. 배경 설명부터 수정 요청, 그대로 쓰는 프롬프트 템플릿까지, 클로드 코드를 제대로 써먹는 프롬프트 작성 팁 6가지를 정리했습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3907</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p&gt;바이브 코딩에서 좋은 결과물을 얻기 위해서는 프롬프트의 품질이 중요합니다. 같은 에이전트를 만들더라도 요청 방식에 따라 결과물의 완성도가 크게 달라질 수 있습니다. 이 글에서는 효과적인 프롬프트 작성법을 실제 예시와 함께 상세히 설명해보겠습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;프롬프트 원칙 1: 배경·목적·제약을 먼저 설명하라&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;가장 흔한 실수는 결과물만 요청하는 것입니다. “~ 만들어 줘.”라는 모호한 요청보다 배경과 목적을 설명해야 클로드 코드가 최적의 설계 과정을 거쳐 사용자의 상황에 맞는 가장 정확한 결과물을 만들어낼 수 있습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;나쁜 프롬프트 예시&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;뉴스 수집 에이전트 만들어 줘&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;&amp;nbsp;&lt;/h4&gt;&lt;h4&gt;&lt;strong&gt;좋은 프롬프트 예시&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;나는 IT 스타트업에서 사업 개발을 담당하고 있어. 
매일 아침 출근 전에 AI, 클라우드, 핀테크 분야 주요 뉴스를 
5분 안에 파악하고 싶어.

이를 위해 다음 기능을 하는 에이전트를 만들어 줘:
- 매일 오전 7시 자동 실행
- 키워드: AI 기술, 클라우드 서비스, 핀테크 규제
- 각 키워드당 최신 뉴스 3건 수집
- 각 뉴스의 비즈니스 영향도를 높음/보통/낮음으로 분류
- 영향도 높음 뉴스만 모아서 Gmail로 발송
- 메일 제목: ‘[일일 뉴스 브리핑] YYYY-MM-DD’&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;차이가 보이나요? 좋은 프롬프트는 ‘내가 누구인지’, ‘무엇을 달성하고 싶은지’, ‘구체적인 요구사항이 무엇인지’를 명확하게 담고 있습니다. 이 세 가지 정보가 있어야 클로드 코드가 내 상황에 맞는 최적의 에이전트를 설계할 수 있습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;목표(뉴스 수집)가 동일하지만 배경이 다른 프롬프트 예시&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;예시1 마케팅 담당자&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;경쟁사 마케팅 캠페인 동향을 매일 5건씩 모아서 분석하고 마케팅 팀 슬랙 채널에 공유하고 싶어.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;→ 웹 검색 + 분석 + 슬랙 연동 에이전트)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;예시2 주식 투자자&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;기술주 관련 뉴스와 실시간 주가 변동을 함께 보여 주고, 매도/매수 신호가 나타나면 즉시 알림을 받고 싶어.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;→ 웹 검색 + 금융 데이터 API + 푸시 알림 에이전트)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;예시3 대학 신문 편집자&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;캠퍼스 관련 뉴스를 자동으로 수집하고, 기사 가치도별로 분류한 후 구글 문서로 편집 대기 목록을 만들어 줘.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;→ 웹 검색 + 분류 + 구글 문서 에이전트)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;​&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;프롬프트 원칙 2: 출력 형식을 구체적으로 명시하라&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;에이전트 요청 시 출력 형식을 구체적으로 명시해야 의도에 맞는 완성도 높은 결과물을 얻을 수 있습니다. 이메일 본문에는 마크다운, PDF 보고서에는 표와 그래프, JSON 데이터 연동일 때는 구조화된 형식 등과 같이 매체나 용도에 맞춰 원하는 구조를 명확히 제시하는 것이 중요합니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;나쁜 프롬프트 예시&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;분석 결과를 메일로 보내 줘.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;좋은 프롬프트 예시&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;분석 결과를 메일로 보내 줘. 메일 형식은 다음과 같아: 

제목: [뉴스 브리핑] {날짜} 

오늘의 핵심 뉴스 ({영향도 높음 건수}건) 

1. {뉴스 제목} 
요약: {2-3줄 요약} 
영향도: 높음 
링크: {URL} 

---
전체 수집: {총 건수}건 | 높음: {건수} | 보통: {건수} | 낮음: {건수}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;일반적인 출력 형식 선택 기준&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;HTML 이메일:&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; 구조적이면서도 가독성이 높아, 깃허브(GitHub)나 슬랙(Slack)처럼 마크다운을 지원하는 플랫폼에 정보를 보낼 때 최적입니다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;PDF 첨부:&lt;/strong&gt; 보고서나 공식 문서처럼 고정된 레이아웃이 필요하거나, 파일을 다운로드하여 오프라인에서 읽어야 하는 경우에 적합합니다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;JSON 데이터:&lt;/strong&gt;사람이 읽기보다는 다른 시스템이나 프로그램과 연동하여 데이터를 자동으로 파싱하고 처리해야 할 때 가장 효율적입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;​&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;프롬프트 원칙 3: 예외 케이스와 오류 처리를 미리 말하라&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;예외 처리 없이 만든 에이전트는 예상 밖의 상황이 오면 그냥 중단되거나 이상한 결과를 만들지만, 예외 처리를 미리 정의하면 어떤 상황이 와도 에이전트가 적절히 처리하고 사용자에게 알려주므로 에이전트의 신뢰도가 달라집니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;일반적인 예외 케이스&lt;/strong&gt;&lt;/h4&gt;&lt;ul&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;li&gt;&lt;strong&gt;API 한도 초과 시:&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;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;좋은 프롬프트 예시&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;예외 처리 예시:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;웹 검색 결과가 없는 키워드는 건너뛰고 나머지는 진행해 줘.&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;Gmail 발송 실패 시 3번까지 재시도하고, 그래도 실패하면 텔레그램으로 알림 보내 줘.&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;네트워크 오류 발생 시 최대 5초 대기 후 1회 재시도&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;모든 오류는 ./logs/error.log 파일에 타임스탬프와 함께 저장&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;5개 이상의 오류가 쌓이면 알림 메일 발송&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;프롬프트 원칙 4: 단계별로 나누어 요청하라&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;복잡한 에이전트를 만들 때는 한 번에 처리하기보다 단계별로 나누어 요청하는 것이 훨씬 안정적입니다. 이는 ① 컨텍스트 창(Context Window)의 한계로 인한 중요 정보 누락을 방지하고, ② 문제 발생 시 오류 원인을 쉽게 격리(Error Isolation)하여 수정할 수 있도록 도와줍니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;뉴스 수집 에이전트를 단계별로 만든다면 다음과 같습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;1단계: 뉴스 수집 에이전트 생성 및 테스트&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;요청 내용&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;뉴스 수집 에이전트 하나만 만들고 테스트해 줘.&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;확인 포인트: 실제로 뉴스가 수집되는지, 데이터 구조가 올바른지 확인&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;2단계: 영향도 분류 기능 추가&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;요청 내용&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;수집된 뉴스에 영향도 분류 기능 추가해 줘.&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;확인 포인트: 분류 기준이 적절한지, 결과가 기대에 맞는지 확인&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;3단계: 메일 발송 기능 추가&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;요청 내용&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;분류 완료된 결과를 메일로 보내는 기능 추가해 줘.&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;확인 포인트: 메일 형식 및 실제 수신 여부 확인&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;4단계: 자동 실행 스케줄 등록&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;요청 내용&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;이 전체를 매일 오전 7시에 자동 실행하도록 스케줄 등록해 줘.&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;확인 포인트: 스케줄러의 정상 동작 여부 확인&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;프롬프트 원칙 5: 수정 요청은 구체적으로&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;결과가 마음에 들지 않을 때는 ‘무엇이 문제인지’, ‘왜 문제인지’, ‘어떻게 바뀌어야 하는지’ 세 가지를 함께 담아 수정을 요청해야 가장 효과적으로 원하는 방향에 도달할 수 있습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;막연한 수정 요청&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;결과가 별로야. 다시 만들어 줘.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;구체적인 수정 요청&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;두 가지를 수정해 줘: 

1. 현재 메일에 뉴스가 제목만 있는데, 
각 뉴스 아래에 2-3문장 요약을 추가해 줘. 

2. 영향도 '높음'으로 분류된 기준이 너무 느슨한 것 같아.
현재 10건 중 8건이 높음으로 나오는데,
실제로 즉각적인 비즈니스 행동이 필요한 뉴스만 높음으로

분류되도록 기준을 강화해 줘.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;‘나쁜 요청’에는 클로드 코드가 스스로 채워야 할 질문들이 숨어 있는데, 아래 예시에서는 그 숨은 질문들을 괄호로 나타내 보았습니다. ‘좋은 요청’은 이미 요청 안에 그 질문들의 답이 들어 있는 요청입니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;나쁜 수정 요청&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;메일이 너무 길어&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;→&amp;nbsp;(어느 부분이? 몇 줄까지가 적당한지?)&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;뉴스 분류가 잘못 되었어 &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;→&amp;nbsp;(어떤 뉴스? 왜 잘못된 것인지?)&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;성능이 안 좋아 &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;→&amp;nbsp;(어디가 느린지? 목표는?)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;좋은 수정 요청&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;메일이 현재 3000자인데 500자 이내로 줄여 줘. 각 뉴스의 요약 문장을 1-2줄로 단축하고 링크는 제거해 줘.&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;AI 관련 뉴스 3개를 실행해 본 결과 2개는 '높음'으로 분류되었는데, 둘 다 장기 기술 뉴스라서 낮음이 맞아. 높음 기준을 '3개월 내 즉시 행동이 필요한 경우'로 더 엄격하게 조정해 줘.&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;지난 3회 실행에서 평균 45초가 걸렸는데, 30초 이내로 줄이고 싶어. 어디가 병목일까? 병목을 제거하는 방식을 제안해 줄 수 있어?&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;프롬프트 원칙 6: 유형별 프롬프트 템플릿&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;유형별 프롬프트 템플릿입니다. 그대로 사용하거나 원하는 내용으로 채워서 사용하세요.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;새 에이전트 생성&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;나는 [직업/역할]이야. 
[문제 상황]을 자동화하고 싶어. 

다음 기능을 하는 에이전트를 만들어 줘:
- 트리거: [언제 실행되는가? 매일 몇 시? 특정 이벤트?]
- 입력: [어떤 데이터를 사용하는가?]
- 처리: [어떤 작업을 수행하는가?]
- 출력: [결과를 어떻게 전달하는가?]

예외 처리:
- [예외 상황 1]: [처리 방법]
- [예외 상황 2]: [처리 방법]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;기존 에이전트 기능 추가&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;기존 [에이전트 이름]에 [새 기능]을 추가해 줘.


추가 기능 상세:
- [기능 설명]
- 기존 [특정 부분] 다음에 실행되어야 해.
- 이미 있는 [기존 기능]은 유지해야 해.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;오류 수정 요청&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;아래 오류가 발생했어. 원인 분석하고 수정해 줘.

[오류 메시지 전체 붙여 넣기]

이 오류는 [어떤 상황에서] 발생했어.
기대했던 동작은 [기대 동작]이야.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;결과 형식 수정&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;[현재 출력 형식의 문제점]이 마음에 안 들어.
​
다음과 같은 형식으로 변경해 줘:
[원하는 출력 형식 예시를 직접 작성]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;프롬프트 작성에서 가장 중요한 것은 ‘내가 원하는 것’을 구체적으로 아는 것입니다. 에이전트를 만들기 전에 잠깐 시간을 들여 정확히 무엇을 자동화하고 싶은가를 정리하면 훨씬 좋은 결과가 나옵니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3907/img-01.png" alt="저자 서지영 소개: 마이크로소프트 Data &amp;amp; AI 스페셜리스트, 정보관리기술사·컴퓨터시스템응용기술사, 랭체인·챗GPT 등 AI 저서 다수 집필"&gt;&lt;/figure&gt;&lt;ul&gt;&lt;li&gt;이 글은 길벗에서 출간된 책 &lt;a href="https://gilbut.co/c/26070157IB"&gt;&amp;lt;클로드 코드 &amp;amp; 오픈클로&amp;gt;&lt;/a&gt;&amp;nbsp;에서 발췌·편집한 글입니다. 원문은 [&lt;a href="https://blog.naver.com/gilbutzigy/224371229233"&gt;여기&lt;/a&gt;]에서 볼 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>23년 된 동네슈퍼를 데이터로 분석하기: 무엇이 팔렸나?</title><link>https://yozm.wishket.com/magazine/detail/3900</link><description>23년째 이어온 동네슈퍼 POS 데이터를 상품 단위까지 내려가 분석한 두 번째 이야기입니다. 얼마나 많이 팔렸는가와 실제로 얼마가 남았는가는 전혀 다른 질문이었죠. Supabase에 쌓은 영수증 60만 건, 상품 100만 줄을 SQL로 계산하고 LLM은 그 결과를 문장으로 옮기는 역할만 맡겼습니다. 동반구매·날씨·시간대 리듬까지 연결해 점주가 놓친 패턴을 찾아내는 과정, 그리고 바이브 코딩의 기억을 지키기 위해 만든 SSOT 문서까지 함께 담았습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3900</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;지난 글 ‘&lt;a href="https://yozm.wishket.com/magazine/detail/3883/"&gt;23년 동안 살아남은 동네슈퍼를 데이터로 분석해봤습니다&lt;/a&gt;’에서 제가 한 일은 단순했습니다. 기존 나들가게 POS에서 월별 매출, 거래 건수, 객단가, 현금매출과 카드매출 데이터를 크롤링하고, 이를 Supabase에 저장해 별도의 대시보드에서 볼 수 있도록 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존 POS에서도 데이터를 조회할 수는 있었습니다. 그러나 과거 데이터를 조회할 때마다 직접 하나씩 하나하나 조회해야 했고, 여러 메뉴에 정보가 흩어져 있어 전체 흐름을 한눈에 파악하기 어려웠습니다. 그래서 한 번 수집한 과거 데이터는 데이터베이스에 저장하고, 이후부터는 복잡한 POS 사이트에 다시 접속하지 않고 바로 불러오는 구조로 변경했습니다. 그 결과, POS가 처음 도입된 &lt;strong&gt;2011년의 매출과 2026년의 매출을 같은 화면에서 비교할 수 있는 기반&lt;/strong&gt;이 만들어졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 단계까지만 해도 나름대로 의미가 있었습니다. 오래된 시스템 안에 갇혀 있던 데이터를 외부로 꺼냈고, 과거의 기록을 빠르게 탐색할 수 있게 되었기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 여전히 알 수 있는 것은 다음 정도였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&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;li&gt;현금과 카드의 비중이 어떻게 변했는지&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;매출이 왜 달라졌는지 알려면 결국 &lt;strong&gt;무엇이 팔렸는지&lt;/strong&gt;까지 내려가야 했습니다. 이번 편에서는 프로젝트가 어디까지 확장되었는지, 그리고 데이터를 많이 모으는 것만으로는 왜 점주의 의사결정을 도울 수 없었는지를 정리해 보려고 합니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;이번에는 ‘얼마나 팔렸는가’에서 ‘무엇이 팔렸는가’로 내려갔다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번에 가장 먼저 추가한 것은 상품 상세 데이터였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존에는 하루 총매출과 거래 건수만 가져왔다면, 이제는 POS의 다른 메뉴에 들어가 다음 정보까지 수집하도록 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&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;li&gt;거래가 발생한 시간&lt;/li&gt;&lt;li&gt;같은 영수증에 포함된 다른 상품&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-01.png" alt="동네슈퍼 대시보드 첫 화면, 매출 기여 TOP5는 국산담배류 28%·아이스크림류 12%·소주 7% 순이고 아래엔 오늘 매출 베스트 상품 목록이 나열됨"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 데이터는 월매출 달력보다 수집하기 더 어려웠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;상품별 이익은 ‘일일 분류별 상품 판매 현황’에 있었고, 몇 시에 어떤 상품이 팔렸는지는 별도의 ‘상품 판매내역 조회’ 화면에 있었습니다. 결국 두 화면을 각각 크롤링한 뒤, 날짜와 상품을 기준으로 다시 연결해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;특히 거래 내역 화면은 하루치 영수증을 하나씩 열어 상품을 확인해야 했습니다. 어떤 날은 하루 데이터를 가져오는 데만 몇 분이 걸렸습니다. 그래서 최근 데이터만 가져오는 것으로 끝내지 않고, 과거 날짜를 하루씩 거슬러 올라가며 자동으로 수집하는 &lt;strong&gt;백필 과정&lt;/strong&gt;을 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;월별 매출 데이터는 2011년까지 수집을 마쳤지만, 상품과 영수증 단위의 상세 데이터는 양이 훨씬 많아 아직도 수집 중입니다. 현재는 대략 2014년의 데이터까지 내려가며 차근차근 데이터베이스에 쌓고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그리고 이 과정을 대시보드에서 직접 확인할 수 있도록 별도의 ‘수집 현황’ 페이지도 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-02.png" alt="수집 현황 페이지, 수집 대상일 5,529일 중 상품 데이터 담긴 날 65%·거래 상세 완전 68%이며 연도별 수집 커버리지 바는 2021년부터 100%"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;처음에는 단순히 오래 걸리는 작업이라고만 생각했습니다. 하지만 수집 기간이 길어질수록 어느 연도까지 정상적으로 들어왔는지, 누락된 날짜는 없는지, 달력 매출과 세부 상품 매출의 합계가 일치하는지를 확인하는 기능도 중요해졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;데이터가 많아지면 수집 자체보다 &lt;strong&gt;제대로 수집되었는지를 검증하는 일&lt;/strong&gt;이 더 어려워진다는 사실도 알게 되었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;데이터가 쌓이자 결국 무료 요금제를 벗어나게 됐다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;처음에는 개인 프로젝트이기 때문에 Supabase 무료 요금제로도 충분할 것이라고 생각했습니다. 하지만 영수증 거래 데이터만 60만 건을 넘어섰고, 영수증에 포함된 개별 상품 행은 100만 줄 이상 쌓였습니다. 일별 상품 집계 데이터까지 더해지면서 데이터베이스 용량은 빠르게 증가했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 Supabase 무료 요금제에서 제공하는 500MB 한도를 넘겼습니다. 오래된 데이터를 삭제하거나, 최근 2년 정도만 보관하는 방법도 생각해 볼 수 있었습니다. 하지만 이 프로젝트를 시작한 중요한 이유 중 하나가 &lt;strong&gt;2011년부터 이어진 가게의 데이터를 한곳에 모으는 것&lt;/strong&gt;이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;과거 데이터를 삭제하면 비용은 줄어들겠지만, 이 프로젝트가 가진 가장 중요한 자산도 함께 사라지게 됩니다. 결국 Supabase Pro 요금제로 업그레이드했고, 현재 매달 약 3만 8천 원 정도를 지불하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개인 사이드 프로젝트에 매달 비용을 내는 것이 부담스럽지만, 10년이 넘는 실제 가게의 원장을 보존하고 분석하는 비용이라고 생각하고 유지하기로 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;데이터가 늘어나면서 대시보드의 구조도 다시 나눴다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;상품과 시간대 정보가 추가되자 기존 한 화면에 모든 내용을 담기 어려워졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&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;li&gt;날씨&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;처음 화면을 열면 ‘오늘’ 탭이 나타납니다. 점주가 가게에서 가장 먼저 궁금해할 정보는 과거의 장기 추세보다 &lt;strong&gt;오늘 장사가 어떻게 되고 있는지&lt;/strong&gt;이기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;‘오늘’ 탭에서는 현재까지의 매출, 거래 건수, 객단가, 예상 이익과 함께 오늘 판매된 주요 상품군과 세부 상품을 보여줍니다. 반면, ‘월별’ 탭에서는 한 달 동안 누적된 데이터를 기준으로 다음 내용을 확인할 수 있도록 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&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;li&gt;세부 상품별 매출·이익·판매량 순위&lt;/li&gt;&lt;li&gt;현금과 카드 결제 비중&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-03.png" alt="나들 매출 대시보드의 월별 탭 ‘7월엔 뭐가 팔렸나’, 이익률 19.1%·피크 18시 391건과 시간대별 판매 추이, 7월 매출 베스트 상품 목록"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-04.png" alt="7월 판매 상품 분류별 패널, 국산담배류 마진9%·구성비23%, 아이스크림류 마진28%, 소주 마진20% 등 카테고리별 이익률과 구성비 목록"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-05.png" alt="오늘 판매 상품 시간대별 상세 화면, 10시부터 시각별 거래 건수와 던힐1미리·콩나물 등 개별 판매 품목이 분 단위로 나열됨"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 데이터를 확인해 보니 담배, 소주, 맥주가 전체 매출에서 매우 큰 비중을 차지하고 있었습니다. 세 상품군을 합치면 매출의 절반에 가까운 기간도 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 여기서 재미있는 점이 하나 있었습니다. 매출이 높은 날이 반드시 돈을 많이 남긴 날은 아니었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;어떤 날은 음식물 쓰레기 종량제 스티커가 많이 판매되면서 매출액 자체는 높게 나타났습니다. 하지만 이 상품은 가게에 남는 이익이 거의 없기 때문에 매출 순위만 보면 좋은 날처럼 보이지만, 실제 이익 측면에서는 그렇지 않았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-06.png" alt="매출 기여 TOP5 바 차트, 쓰레기봉투가 17%로 1위지만 마진 2%에 그치고 국산담배류·외산담배류·맥주·소주가 뒤를 이음"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 경험을 통해 단순한 매출 순위가 점주에게 잘못된 인상을 줄 수 있다는 사실을 확인했습니다. &lt;strong&gt;얼마나 많이 팔렸는가와 실제로 얼마가 남았는가는 전혀 다른 질문&lt;/strong&gt;이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;보기 좋은 대시보드만 만들고 싶었던 것은 아니었다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;사실 제가 처음부터 만들고 싶었던 것은 POS를 현대적으로 다시 디자인한 화면이 아니었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존보다 정보를 보기 쉽게 만들고, 토스처럼 중요한 숫자가 먼저 들어오도록 UI를 구성하는 것도 필요했습니다. 하지만 그것만으로는 기존 POS를 조금 예쁘게 다시 만든 것에 불과합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 정말 만들고 싶었던 것은 다음 구조였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;Raw Data
무엇이 언제 얼마에 팔렸는가
↓  
Calculation
요일·시간·상품·이익의 관계를 코드와 공식으로 계산
↓
Decision
그래서 점주가 무엇을 확인하거나 바꿔볼 것인가&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 중요한 점은 계산을 LLM에 맡기지 않는 것입니다. 매출 변화율, 판매지수, 동반구매율, 상품별 마진과 같은 숫자는 SQL과 코드로 계산합니다. LLM은 이미 계산된 결과를 점주가 이해할 수 있는 문장으로 바꾸는 역할만 맡도록 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;LLM이 원본 데이터를 보고 자유롭게 판단하게 하면 그럴듯하지만 근거가 불분명한 설명을 만들 가능성이 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;그런데 첫 번째 ‘인사이트’는 별로 유의미하지 않았다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;처음에는 이런 판단 카드를 만들었습니다. 13시 방문을 이익으로 전환할 기회가 있어요. 13시는 거래 건수가 많지만 객단가가 낮으므로 계산대 근처에 고마진 상품을 배치해 보라는 내용이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&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;li&gt;단골 한두 명의 반복 구매로 만들어진 패턴은 아닌지&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;어느 것도 충분히 설명하지 못했습니다. 결국 ‘데이터를 분석한 문장’처럼 보일 뿐, 실제 행동을 바꿀 만큼 구체적인 판단은 아니었습니다. 그래서 이 카드를 제거하고, 계산 계층을 다시 설계했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;반복되는 패턴만 판단 후보로 올리기 시작했다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이후에는 하루의 숫자 하나를 보고 인사이트를 만들지 않도록 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어, 특정 상품이 금요일에 많이 팔렸다고 판단하려면 다음 조건을 함께 계산합니다.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;최근 8주 동안 비교 가능한 금요일이 충분히 존재하는지&lt;/li&gt;&lt;li&gt;8주 중 몇 주에서 같은 패턴이 반복됐는지&lt;/li&gt;&lt;li&gt;다른 요일보다 얼마나 많이 팔렸는지&lt;/li&gt;&lt;li&gt;최근 4주 동안 증가하거나 감소하고 있는지&lt;/li&gt;&lt;li&gt;결과를 만들 수 있는 데이터가 충분히 수집되었는지&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이를 바탕으로 다음과 같은 결과를 만들고자 했습니다. 최근 8주 금요일 중 7주에서 12~14시 아이스크림 판매량이 다른 시간대보다 높았습니다. 단순히 “금요일에 아이스크림이 많이 팔립니다”라고 말하는 것보다, 표본과 반복성을 함께 보여주는 방식입니다. ‘더 준비하세요’라는 표현도 조심했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;현재 데이터에는 실제 재고 수량이나 발주 단위가 없기 때문에 정확히 몇 개를 주문해야 하는지는 알 수 없습니다. 그래서 시스템에서는 ‘발주량’이 아니라, 과거 판매량의 중앙값과 최근 추세를 기준으로 &lt;strong&gt;목표 준비량&lt;/strong&gt;을 보여주도록 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;가게의 시간을 하나의 리듬처럼 보기 시작했다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;데이터가 충분히 쌓이면서 각각의 표를 나열하는 것보다, 가게의 운영 구조를 한 번에 보고 싶다는 생각이 들었습니다. 그래서 ‘판단’ 탭을 일종의 &lt;strong&gt;가게 디지털 트윈&lt;/strong&gt;처럼 다시 구성했습니다. 물론 공장의 설비나 물류 흐름을 실시간으로 복제하는 거창한 디지털 트윈은 아닙니다. 이 가게에서 반복되는 시간과 상품의 구조를 데이터로 옮겨놓았다는 의미에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 화면은 네 가지 관점으로 구성했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 시간대 리듬&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;요일과 시간을 히트맵으로 연결해, 언제 가게의 거래가 집중되는지 보여줍니다. 실제로 데이터를 확인해 보니, 요일에 관계없이 대체로 &lt;strong&gt;오후 5시에서 8시 사이&lt;/strong&gt;가 가장 중요한 시간대로 나타났습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;단순히 피크 시간만 보여주는 것이 아니라, 오전 8~12시, 12~16시, 16~20시, 20~24시로 나누어 각 시간대에 어떤 상품과 상품 조합이 주로 판매되는지도 연결했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-07.png" alt="시간대 리듬 히트맵, 요일×시간대 거래 밀도를 색으로 표시하고 저녁 16~20시엔 진로이즈백·생탁·음식물쓰레기봉투가 많이 팔림"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 계절 달력&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;월별로 어떤 카테고리의 비중이 달라지는지 여러 해의 평균으로 계산했습니다. 아이스크림처럼 계절성이 명확한 상품뿐 아니라, 같은 계절에도 매년 반복적으로 증가하거나 감소하는 상품군을 확인할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-08.png" alt="계절 달력 선그래프, 국산담배류 23%를 축으로 외산담배류·소주·맥주가 뒤를 잇고 아이스크림류는 7월 5.9%에서 11월 1.9%로 떨어짐"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 명목 매출과 실질 성장&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;2011년보다 지금의 매출이 높다고 해서 가게가 실제로 더 많은 상품을 판매한다고 볼 수는 없습니다. 그동안 상품 가격 자체가 올랐기 때문입니다. 그래서 공식 소비자물가지수와는 별개로, 우리 가게에서 여러 해 동안 공통으로 판매된 상품들의 단가 변화를 이어 붙인 &lt;strong&gt;자체 단가 지수&lt;/strong&gt;를 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이를 통해 매출이 가격 상승 때문에 오른 것인지, 실제 거래와 상품 판매가 늘어 오른 것인지를 구분해보려 했습니다. 이 지수는 공식 물가지표가 아니라, 어디까지나 &lt;strong&gt;우리 가게의 판매가격을 기준으로 계산한 지표&lt;/strong&gt;라는 점도 화면에 함께 표시했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-09.png" alt="연도 구조 변화 그래프, 2015년을 100으로 놓고 명목매출·실질매출·가격지수·거래건수·객단가 흐름을 겹쳐 그려 2025년 실질 성장 -3.6%를 보여줌"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;4) 상품의 세대교체&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;같은 카테고리 안에서도 시간이 지나면서 대표 상품이 바뀝니다. 과거에 많이 팔렸던 상품의 점유율이 줄어들고 새로운 상품이 이를 추월하는 시점을 찾아, 어떤 제품이 어떤 제품으로 대체됐는지 시각화했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;데이터에서는 박카스 중심이던 에너지음료 수요가 몬스터 같은 새로운 상품으로 이동하는 모습도 확인할 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-10.png" alt="상품 세대교체 막대그래프, 동아제약 박카스F 액이 2018년 26%로 정점을 찍은 뒤 줄고 해태음료 몬스터 에너지가 2022년부터 새로 자리잡음"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;과거에 무엇이 팔렸는지를 단순히 보여주는 것은 “그때는 그랬구나”에서 끝날 가능성이 큽니다. 제가 찾고 싶었던 것은 과거의 기록 자체가 아니라, &lt;strong&gt;현재 상품 운영에 영향을 줄 만큼 반복되거나 구조적으로 변한 패턴&lt;/strong&gt;이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;함께 사가는 상품도 데이터로 꺼내보았다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;영수증 단위의 상품 데이터가 생기면서 어떤 상품을 함께 구매하는지도 계산할 수 있게 되었습니다. 다만 판매 건수가 많은 상품끼리는 우연히 함께 잡힐 가능성도 높습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 단순 동반 구매 횟수뿐 아니라, 두 상품이 각각 팔릴 확률과 비교해 실제로 함께 구매될 가능성이 몇 배 높은지를 나타내는 lift도 함께 계산했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그 결과 POS에 기록된 상품명을 그대로 기준으로 다음과 같은 조합을 발견했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;[시원] 360ml 보조 상표&lt;span style="color:#999999;"&gt;(통합)&lt;/span&gt; + 카스1000L&lt;/li&gt;&lt;li&gt;98회 함께 판매, 일반적인 경우보다 20.5배 높은 조합&lt;/li&gt;&lt;li&gt;[시원] 360ml 보조 상표&lt;span style="color:#999999;"&gt;(통합)&lt;/span&gt; + 팔리아멘트 아쿠아5&lt;/li&gt;&lt;li&gt;53회 함께 판매, 일반적인 경우보다 22.8배 높은 조합&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-11.png" alt="함께 사가는 조합 리스트, [시원]360ml 보조상표와 카스1000L을 같이 사는 경우가 우연 대비 20.5배로 나타나는 등 동시구매 배수를 정리함"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;부모님은 오랫동안 가게를 운영했기 때문에 어떤 상품이 함께 팔리는지 어느 정도 이미 알고 계셨을 수 있습니다. 다만 그동안은 경험과 감각으로 알고 있던 사실을 데이터상에서 정확한 횟수와 수치로 꺼낼 수 있게 되었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇다고 이 결과만 보고 곧바로 두 상품을 묶어 팔거나 진열을 바꾸는 것은 아닙니다. 두 상품을 함께 산 사람이 실제로 여러 명인지, 한 명의 단골이 반복해서 구매한 것인지 현재 POS 데이터만으로는 알 수 없기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 동반 구매 분석도 정답이라기보다, &lt;strong&gt;점주가 현장을 다시 살펴볼 질문의 출발점&lt;/strong&gt;에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;2011년부터의 날씨도 가게 데이터와 연결했다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번에는 POS 밖의 데이터도 처음으로 연결했습니다. 기상청 데이터를 활용해 2011년부터 현재까지 부산의 기온, 습도, 강수량, 운량 등의 날씨 정보를 수집했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;현재는 약 5,690일의 일별 날씨와 13만 건이 넘는 시간대별 관측 데이터가 쌓여 있습니다. 처음에는 같은 달과 같은 요일 안에서 날씨가 더운 날과 그렇지 않은 날을 비교했습니다. 하지만 15년 가까운 데이터가 생기자 같은 달에만 한정할 필요가 없다는 생각이 들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;작년 8월과 올해 7월이라도 기온과 습도, 강수 조건이 비슷하다면 가게의 입장에서는 충분히 비교할 수 있는 날이기 때문입니다. 그래서 현재는 강수 여부를 먼저 나누고, 기온·습도·운량이 오늘과 가장 비슷했던 과거 날짜를 전 기간에서 찾는 방식으로 변경했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그 뒤 비슷한 날들에 평소보다 더 팔렸던 상품과 덜 팔렸던 상품을 보여줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-12.png" alt="날씨 연동 화면, 오늘 최고 36.3℃ 폭염 표시와 함께 닮은 날엔 월드콘·탱크보이·메로나가 더 팔리고 쓰레기봉투10L은 덜 팔린다는 예측을 보여줌"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어, 단순히 “더운 날에는 아이스크림이 잘 팔립니다”라고 보여주는 것은 큰 의미가 없습니다. 대신 다음과 같이 보여주는 것이 목표입니다. 오늘과 비슷한 날씨였던 과거 20일에서 비비빅은 하루 평균 9개, 메로나는 3.2개 더 판매됐습니다. 판매량이 0.02개에서 0.4개로 올랐다면 수치상으로는 20배지만, 실제로는 하루 0.38개 차이에 불과합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 배수보다 &lt;strong&gt;하루에 실제로 몇 개 더 팔렸는지&lt;/strong&gt;를 기준으로 순위를 정했습니다. 다만 이것 역시 인과관계라고 단정할 수는 없습니다. 기온이 비슷한 날에 특정 상품이 함께 많이 팔렸다는 사실을 보여줄 뿐, 날씨 때문에 해당 상품이 팔렸다고 확정하는 것은 아닙니다. 계절, 요일, 상품의 출시 시점과 단종 여부 같은 다른 요인도 함께 영향을 줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;따라서 날씨 탭도 현재는 정답을 알려주는 기능이라기보다, &lt;strong&gt;내일 무엇을 조금 더 준비해 볼지 판단할 근거를 제공하는 단계&lt;/strong&gt;에 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;LLM은 계산하지 않고, 계산된 결과만 설명하게 했다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;분석 결과를 점주가 읽기 쉬운 문장으로 바꾸기 위해 LLM API도 연결했습니다. 하지만 LLM이 매출 원장을 직접 보고 계산하거나, 자유롭게 상품 운영 방법을 추천하도록 하지는 않았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;역할을 다음과 같이 분리했습니다.&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;SQL과 코드
판매량·마진·반복성·동반구매·날씨 효과를 계산

LLM
계산된 수치와 한계를 사람이 이해하기 쉬운 문장으로 정리&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;LLM이 실패하거나 API를 사용할 수 없는 경우에도 판단 기능이 멈추지 않도록, 같은 내용을 정해진 문장으로 출력하는 템플릿도 함께 만들었습니다. 결국 이 시스템에서 LLM은 판단을 만들어내는 두뇌라기보다, &lt;strong&gt;이미 계산된 결과를 점주의 언어로 번역하는 인터페이스&lt;/strong&gt;에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;기능을 추가할수록 서비스는 느려졌다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 프로젝트를 하면서 개발자분들이 새삼 대단하다고 느낀 순간도 많았습니다. 이 서비스는 사실상 한 사람, 많아야 가족 몇 명이 사용하는 개인용 서비스입니다. 대규모 트래픽이 발생하지도 않고, 수많은 사용자가 동시에 요청을 보내지도 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데도 상품 데이터, 판단 탭, 날씨 데이터처럼 기능을 하나씩 추가할 때마다 탭 이동이 느려지고 로딩 시간이 길어졌습니다. 과거 데이터를 매번 다시 계산하면 화면을 열 때 오래 기다려야 했고, 백필 작업이 브라우저를 사용하고 있으면 오늘 데이터를 수집하는 작업이 밀리기도 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&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;li&gt;사용자가 새로고침하면 과거 백필 작업이 브라우저를 양보&lt;/li&gt;&lt;li&gt;한 번 계산한 값은 캐시에 저장&lt;/li&gt;&lt;li&gt;누락되거나 합계가 맞지 않는 날짜는 별도로 탐지해 재수집&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;혼자 사용하는 서비스에서도 이 정도의 고민이 생겼습니다. 그렇다면 토스처럼 수많은 사용자가 동시에 접속하고, 계속 새로운 기능이 추가되는 서비스에서 백엔드 개발자분들은 얼마나 많은 통신 방식과 캐싱, 동시성, 데이터 정합성 문제를 고민하고 있을까 하는 생각이 들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;화면에서는 버튼을 한 번 누르면 바로 다음 정보가 나오지만, 그 자연스러운 경험 뒤에 얼마나 많은 최적화가 숨어 있는지 조금이나마 체감할 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;바이브 코딩에도 기억을 보존하는 장치가 필요했다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;기능이 많아지면서 또 다른 문제가 발생했습니다. Claude나 Codex를 이용해 바이브 코딩을 하다 보면, 새로운 터미널과 새로운 대화창에서 작업을 시작하게 됩니다. 그러면 이전 대화에서 왜 특정 구조를 선택했는지, 어떤 오류 때문에 방어 로직을 추가했는지가 사라집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;새로운 AI는 현재 코드만 보고 다음과 같이 판단할 수 있습니다. 이 부분은 복잡해 보이니 제거해도 되겠습니다. 하지만 실제로는 과거에 발생했던 데이터 오염이나 삭제를 막기 위해 일부러 복잡하게 만들어둔 코드일 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 프로젝트에서는 같은 날 같은 이름을 가진 다른 상품이 한 번에 들어오면서 저장 배치 전체가 실패한 적도 있었습니다. 그 문제로 1,000일이 넘는 상품 데이터가 정상적으로 저장되지 않았고, 백필 작업도 과거로 내려가지 못한 채 같은 구간을 반복하고 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또 수집이 2014년에서 멈춘 이유를 처음에는 데이터베이스 용량이나 POS 보관기간 때문이라고 의심했지만, 실제로는 앞선 저장 오류로 미완료 날짜가 쌓여 과거 날짜까지 내려가지 못한 것이 원인이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이런 맥락을 모르는 AI가 코드를 단순화하면 이미 해결한 문제가 다시 발생할 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 SSOT.md라는 문서를 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3900/img-13.png" alt="SSOT.md 문서 캡처, ‘선점 가능하게 최적화하지 마라’·‘probe 자체를 제거하지 마라’ 등 바이브 코딩에서 지켜야 할 로직 원칙이 불릿으로 정리됨"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;SSOT는 Single Source of Truth, 즉 하나의 기준이 되는 문서라는 의미입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&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;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 style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI에 새로운 작업을 맡길 때도 먼저 이 문서를 읽도록 했고, 중요한 구조를 변경하면 코드와 함께 SSOT도 갱신하도록 했습니다. 바이브 코딩은 코드를 빠르게 만드는 데에는 매우 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 프로젝트가 길어질수록 중요한 것은 코드를 빨리 생성하는 능력보다, &lt;strong&gt;왜 이런 코드가 존재하는지를 잊지 않는 능력&lt;/strong&gt;이라는 사실도 알게 되었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;동네 슈퍼 데이터는 편의점 데이터와 다르다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이 프로젝트에서 계속 경계하고 있는 부분도 있습니다. 우리 가게는 불특정 다수가 끊임없이 방문하는 대형 매장이나 프랜차이즈 편의점이 아닙니다. 주변에 거주하는 단골손님과 매일 담배나 술을 사러 오는 고객의 비중이 높습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;따라서 특정 상품 조합이 많이 나타났다고 해서 많은 고객이 공통으로 선호한다고 단정할 수 없습니다. 한 명의 단골이 같은 조합을 반복해서 구매했기 때문에 만들어진 결과일 수도 있습니다. 고객 ID가 없는 POS 데이터만으로는 이를 완전히 구분하기 어렵습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어, 데이터를 분석하니 월요일에는 캔커피가 평소보다 약 2.3배 많이 팔리는 패턴이 나타났습니다. 하지만 이 수치만 보고 월요일마다 캔커피를 두 배로 발주하는 것은 위험합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&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;li&gt;실제로 진열 위치를 바꾸면 추가 판매로 이어질 수 있는가?&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 시스템이 해야 할 일은 “월요일에는 캔커피를 더 주문하세요”라고 정답을 말하는 것이 아닐 수 있습니다. 오히려 부모님이 오랜 경험 속에서 놓치고 있던 패턴을 꺼내 다음과 같은 질문을 던지는 것이 더 중요할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;월요일에 캔커피가 반복적으로 더 팔리는 이유가 무엇일까?&lt;/li&gt;&lt;li&gt;이 패턴을 이용해 함께 판매할 상품이나 준비 방식을 바꿔볼 수 있을까?&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;필요한 데이터는 거의 모았지만 진짜 어려운 문제가 남았다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;처음에는 POS 데이터를 가져오는 것 자체가 가장 어려운 문제라고 생각했습니다. 엑셀 다운로드도 제대로 지원하지 않는 오래된 사이트에서 데이터를 크롤링하고, 2011년부터의 기록을 데이터베이스에 저장하는 일이 가장 큰 과제처럼 보였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 지금은 생각이 달라졌습니다. 데이터를 모으는 것은 어렵지만, 언젠가는 끝납니다. 진짜 어려운 문제는 그다음입니다. 수집한 데이터를 어떤 기준으로 연결하고, 어떤 차이를 의미 있는 변화로 판단하며, 어떤 결과만 점주에게 보여줄 것인가.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;수많은 숫자를 보여주는 것은 쉽습니다. 그러나 그중 실제로 부모님의 다음 행동을 바꿀 만한 신호를 찾아내는 것은 전혀 다른 문제입니다. 현재 시스템은 과거와 비슷한 날, 특정 요일과 시간대의 평균, 함께 팔린 상품, 날씨 조건에 따른 판매 차이를 보여줄 수 있는 단계까지 왔습니다. 하지만 아직은 대부분 관찰과 비교에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앞으로는 여기서 한 단계 더 나아가고 싶습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&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;li&gt;부모님의 현장 경험과 데이터가 서로 충돌할 때 무엇을 다시 확인할지&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 제가 만들고 싶은 것은 가게 운영의 정답을 대신 내려주는 AI가 아닙니다. &lt;strong&gt;점주가 그냥 지나쳤을 수 있는 변화를 발견하고, 무엇을 확인하고 시험해 볼지 더 정확한 출발점을 제시하는 시스템&lt;/strong&gt;입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;23년 동안 가게를 운영해 온 부모님의 경험을 데이터로 대체하는 것이 아니라, 그 경험이 새로운 질문을 만날 수 있도록 돕는 것. 그것이 이 프로젝트가 다음 단계에서 풀고 싶은 문제입니다.&lt;/p&gt;&lt;hr&gt;&lt;p style="text-align:justify;"&gt;&amp;lt;원문&amp;gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;a href="https://velog.io/@minority_report/23%EB%85%84-%EB%8F%99%EC%95%88-%EC%82%B4%EC%95%84%EB%82%A8%EC%9D%80-%EB%8F%99%EB%84%A4%EC%8A%88%ED%8D%BC%EB%A5%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A1%9C-%EB%B6%84%EC%84%9D%ED%95%B4%EB%B3%B4%EB%A0%A4-%ED%95%A9%EB%8B%88%EB%8B%A4.-3%ED%8E%B8"&gt;23년 동안 살아남은 동네슈퍼를 데이터로 분석해보려 합니다. &lt;span style="color:#999999;"&gt;(3편)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>MCP 새로운 스펙 총정리: 무엇을 결정하고 바꿔야 할까?</title><link>https://yozm.wishket.com/magazine/detail/3893</link><description>지난 7월 28일, MCP(Model Context Protocol) 스펙의 새 버전 2026-07-28이 확정되며 공개 이후 가장 큰 개정이 이뤄졌습니다. 스테이트리스 전환이라는 헤드라인 하나만 보고 넘어가면 놓치기 쉬운 내용이 많아, 이번 개정의 변화 전체를 6가지로 나누어 무엇을 알아두고 무엇을 결정해야 하는지 정리했습니다. 결국 대다수가 쓰지 않던 기능을 걷어내고 웹에서 검증된 스테이트리스 요청 모델로 돌아온 것이 핵심이며, MCP가 실험적 프로토콜에서 운영 가능한 인프라로 넘어가는 단계라고 볼 수 있습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3893</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;지난 7월 28일, MCP&lt;span style="color:#999999;"&gt;(Model Context Protocol)&lt;/span&gt; 스펙의 새 버전 &lt;code&gt;2026-07-28&lt;/code&gt;이 &lt;a href="https://blog.modelcontextprotocol.io/posts/2026-07-28/"&gt;확정됐습니다&lt;/a&gt;. MCP 공개 이후 가장 큰 개정으로, &lt;a href="https://modelcontextprotocol.io/specification/2026-07-28/changelog"&gt;변경 이력&lt;span style="color:#999999;"&gt;(changelog)&lt;/span&gt;&lt;/a&gt;에 굵직한 변경만 9건이 올라와 있습니다. 클로드 코드&lt;span style="color:#999999;"&gt;(Claude Code)&lt;/span&gt;나 커서&lt;span style="color:#999999;"&gt;(Cursor)&lt;/span&gt; 같은 코딩 에이전트에 MCP 서버를 붙여 쓰는 환경에 직접 해당하는 내용들입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다행히 오늘 당장 MCP 설정을 바꾸지 않는다고 해서 기존 동작에 문제가 생기는 건 아닙니다. &lt;a href="https://blog.modelcontextprotocol.io/posts/sdk-betas-2026-07-28/"&gt;공식 발표&lt;/a&gt;도 “기존 클라이언트와 서버는 오늘도, 7월 28일에도 문제없이 동작한다&lt;span style="color:#999999;"&gt;(nothing breaks today, and nothing breaks on July 28 either)&lt;/span&gt;”라고 분명하게 밝혔습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만, 변경의 폭이 넓어 스테이트리스&lt;span style="color:#999999;"&gt;(stateless)&lt;/span&gt; 전환이라는 헤드라인 하나만 보고 넘어가면 중요한 내용들을 놓치기 쉽습니다. 그런 만큼 이 글에서는 이번 개정의 변화 전체를 6개로 나누어 하나씩 설명하고, 지금 MCP를 쓰고 있는 사용자라면 무엇을 알아두고 무엇을 결정해야 하는지 정리해 보겠습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;MCP 개편 항목 한눈에 보기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;우선 공식 변경 이력의 항목들을 성격에 따라 다음 6가지로 구분하여 표로 정리해 볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3893/img-02.png" alt="스테이트리스 코어를 중심으로 통신 방식·인프라·인증·확장 프레임워크·기능 정리 6개 카드로 나눈 MCP 개정 요약 카드형 다이어그램"&gt;&lt;figcaption&gt;&lt;i&gt;2026-07-28 개정의 변화 전체: 6가지 분류 &amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;참고로 MCP는 앤트로픽&lt;span style="color:#999999;"&gt;(Anthropic)&lt;/span&gt;이 만들었고 2025년 12월부터 리눅스 재단 산하 AAIF&lt;span style="color:#999999;"&gt;(Agentic AI Foundation, 에이전틱 AI 재단)&lt;/span&gt;에 기부되어 중립 재단 아래에서 관리되고 있습니다. 이번 릴리스는 그 체제에서 나온 첫 대규모 개정이며 릴리스 후보&lt;span style="color:#999999;"&gt;(RC, Release Candidate)&lt;/span&gt;가 5월 21일에 나와 10주의 검증 기간을 거쳐 확정됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그러면 6가지 주요 변화를 하나씩 함께 보겠습니다.&lt;/p&gt;&lt;hr&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;1. 스테이트리스 코어: 세션이 사라진 이유와 방식&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;가장 큰 변화로, 이로 인해 나머지 변화들이 생겼다고 볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;기존 핸드셰이크 구조의 문제&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;기존 MCP에서 클라이언트(코딩 에이전트)와 서버(도구 제공자)는 요청을 주고받기 전에 확인 절차부터 거쳤습니다. 즉, 클라이언트가 &lt;code&gt;initialize&lt;/code&gt; 요청으로 “나는 이런 기능을 지원한다”라고 알리면 서버가 세션&lt;span style="color:#999999;"&gt;(session)&lt;/span&gt; ID를 발급해 돌려주는 핸드셰이크&lt;span style="color:#999999;"&gt;(handshake)&lt;/span&gt; 구조였습니다. 이후 모든 요청에는 &lt;code&gt;Mcp-Session-Id&lt;/code&gt; 헤더로 발급받은 세션 ID를 함께 보내야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 이 구조를 쓴다 해도 로컬에서 서버를 1개 띄웠을 경우에는 문제가 되지 않습니다. 하지만 원격에 여러 대로 늘려 운영하는 순간, 문제가 생깁니다. 세션이 특정 서버에 묶여 있다 보니 요청 분배와 장애 복구에서 문제가 일어날 수 있습니다. 특히, 같은 클라이언트의 요청은 세션을 기억하는 서버 인스턴스로만 보내야 하므로 일반 로드밸런서&lt;span style="color:#999999;"&gt;(load balancer)&lt;/span&gt;의 라운드로빈 분배 대신 스티키 세션&lt;span style="color:#999999;"&gt;(sticky session)&lt;/span&gt; 같은 장치가 필요했습니다. 결국 그 인스턴스가 죽으면 세션도 함께 사라졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기에 세션을 만들고 관리하고 나중에 정리하는 코드까지 서버 개발자가 직접 구현해야 하다 보니 버그와 메모리 누수로 이어지는 경우도 많았습니다. 스펙 개선 제안 문서인 &lt;a href="https://modelcontextprotocol.io/seps/2575-stateless-mcp"&gt;SEP-2575&lt;/a&gt;&lt;span style="color:#999999;"&gt;(Specification Enhancement Proposal)&lt;/span&gt;를 보면, 이러한 문제들이 많이 등장합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;MCP 코어 메인테이너인 MS 개발자 케이티 맥카프리&lt;span style="color:#999999;"&gt;(Caitie McCaffrey)&lt;/span&gt;의 릴리스 직후 &lt;a href="https://www.arcade.dev/blog/mcp-maintainers-interview"&gt;인터뷰&lt;/a&gt;에 따르면, 호스트마다 세션 기능의 구현 방식이 제각각이거나 아예 올바르지 않아 상태 유지가 프로토콜에서 제대로 작동한 적이 없었다고 합니다. 실제 사용 사례의 약 90%는 그 기능을 쓰지도 않았다고 합니다. 그래서 이번 2026-07-28 개정이 이 문제들을 해결했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;새로운 스펙이 문제를 해결한 방법&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;그렇다면 새로운 스펙은 이 문제를 어떻게 풀었을까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;답은 “처리에 필요한 정보를 요청 하나에 전부 담는다&lt;span style="color:#999999;"&gt;(self-contained)&lt;/span&gt;”입니다. 매 요청의 &lt;code&gt;_meta&lt;/code&gt; 필드에 프로토콜 버전과 클라이언트 기능 목록이 필수로 실립니다. 어떤 서버 인스턴스가 받아도 그 요청 하나만 보고 독립적으로 처리하도록 했습니다. 서버 정보가 궁금하면 &lt;code&gt;server/discover&lt;/code&gt;라는 요청으로 지원 버전과 기능을 물어볼 수 있고, 이 요청은 모든 서버가 반드시 지원하게 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3893/img-03.png" alt="좌측은 클라이언트가 initialize로 세션ID를 받아 서버 1에만 요청을 보내는 구조, 우측은 매 요청에 _meta를 담아 로드밸런서가 서버 1·2·3에 독립 처리하는 구조를 도식화"&gt;&lt;figcaption&gt;&lt;i&gt;세션 기반(구 스펙) 요청 흐름과 스테이트리스(신 스펙) 요청 흐름 비교 &amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;변경에 따른 두 가지 오해&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;두 가지 오해를 짚고 넘어가는 게 좋겠습니다. 첫째, 세션이 없어졌다고 해서 상태 자체가 금지된 것은 아닙니다. 장바구니처럼 여러 호출에 걸친 상태가 필요한 서버는, 생성 도구가 &lt;code&gt;basket_id&lt;/code&gt; 같은 명시적 핸들&lt;span style="color:#999999;"&gt;(handle)&lt;/span&gt;을 돌려주고 이후 호출마다 그 식별자를 인자로 받는 방식으로 바뀌게 됩니다. 기존에는 이러한 상태가 전송 계층에서 세션으로 관리되어 모델이 그 존재를 보기 어려웠습니다. 그러나 이제는 핸들 방식으로 변경되면서 도구의 인자와 반환값처럼 모델이 직접 볼 수 있는 데이터 형태로 오갑니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;둘째, 끊긴 스트림을 이어받는 재개&lt;span style="color:#999999;"&gt;(resumability)&lt;/span&gt; 기능도 함께 사라졌습니다. 스트림을 이어받으려면 서버가 직전까지 보낸 내용을 기억하고 있어야 하는데, 상태를 남기지 않는다는 새 원칙과 맞지 않기 때문입니다. 응답 스트림이 끊기면 클라이언트는 새 요청으로 다시 시도해야 하고, 오래 걸리는 작업은 뒤에서 설명할 Tasks 확장이 담당하게 됐습니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p style="text-align:justify;"&gt;왜 기존 방식과 호환되는 방식을 선택하지 않고 전면적인 개정으로 진행하게 되었을까요? 두 상호작용 모델을 병행하면 프로토콜과 모든 구현체가 두 벌의 로직을 만들고 유지해야 해서 복잡도와 버그 여지가 커집니다. 그래서 메인테이너들은 한 번에 정리하는 쪽이 생태계 전체에 낫다고 판단했습니다. &lt;span style="color:#999999;"&gt;(보다 상세한 내용은&lt;/span&gt; &lt;a href="https://modelcontextprotocol.io/seps/2575-stateless-mcp"&gt;SEP-2575 문서&lt;/a&gt;&lt;span style="color:#999999;"&gt;에 기록되어 있으니 참고하시기 바랍니다.)&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;2. 통신 방식 변경: 서버가 더 이상 클라이언트를 호출하지 않음&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;세션이 사라지면서 서버가 클라이언트와 연결을 계속 유지한다는 전제도 사라졌기 때문에, 통신 방식도 함께 달라졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존에는 서버가 역으로 클라이언트에 요청을 보낼 수 있었습니다. 도구 실행 중에 사용자 입력을 요청하는 엘리시테이션&lt;span style="color:#999999;"&gt;(elicitation)&lt;/span&gt;이 대표적입니다. 신 스펙에서 서버는 JSON-RPC 요청을 시작할 수 없도록 했고 이런 상호작용은 MRTR&lt;span style="color:#999999;"&gt;(Multi Round-Trip Requests, 다중 왕복 요청)&lt;/span&gt;이라는 패턴으로 바뀌었습니다. 서버가 클라이언트를 직접 호출하는 대신 “추가 입력이 필요하다”는 중간 결과를 돌려주면 클라이언트가 입력을 채워 원래 요청을 다시 보내는 방식입니다. 이때 서버는 진행 상태를 &lt;code&gt;requestState&lt;/code&gt;라는 문자열로 내보내고 클라이언트가 그대로 돌려줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 이 값은 클라이언트를 거쳐 돌아오기 때문에, 서버가 보낸 그대로라는 보장이 없습니다. 그래서 &lt;a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr"&gt;스펙&lt;/a&gt;은 이 값을 믿지 말고 외부에서 온 입력처럼 검증하도록 명시합니다. 인가나 비즈니스 로직에 영향을 준다면 HMAC&lt;span style="color:#999999;"&gt;(Hash-based Message Authentication Code, 해시 기반 메시지 인증 코드)&lt;/span&gt; 같은 무결성 보호가 필수입니다. SDK가 이를 위한 도구를 제공합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;[노트] 엘리시테이션(elicitation)이 무엇인가요?

서버가 도구를 실행하다가 사용자에게 추가 입력이나 확인을 요청하는 기능입니다.
예를 들어 배포 도구가 실행 도중에 “어느 환경에 배포할까요?”라고 물어보고 답을 받아 이어가는 상호작용이 여기에 해당합니다.&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;서버에서 클라이언트로 가는 통신에는 응답을 요구하는 요청 말고도 일방적으로 알려주기만 하는 알림이 있는데, 이 알림 채널도 하나로 합쳐졌습니다. 기존에는 알림을 받는 통로가 2개여서, 서버가 보내는 일반 알림은 클라이언트가 HTTP GET으로 열어 둔 상시 연결로 받고 리소스 변경 알림은 별도의 구독 요청으로 신청했습니다. 게다가 서버가 아무 때나 일방적으로 알림을 보낼 수 있어서 클라이언트는 쓰지도 않을 알림까지 받아서 처리해야 했습니다. 서버도 어느 클라이언트가 듣고 있는지를 세션 상태로 관리해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;신 스펙은 이 둘을 &lt;code&gt;subscriptions/listen&lt;/code&gt;이라는 단일 스트림으로 통합하고 받고 싶은 알림 종류(도구 목록 변경 등)를 클라이언트가 명시적으로 신청하는 옵트인 방식으로 정리했습니다. 이제 클라이언트는 신청한 알림만 받고, 서버는 신청받은 알림만 처리해서 보냅니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;3. 인프라 친화적 개선: HTTP 헤더와 캐시 표준화로 운영 부담을 줄임&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;운영하는 쪽에 이득이 집중된 변화입니다. 이제 Streamable HTTP 요청에는 어떤 메서드인지(&lt;code&gt;Mcp-Method&lt;/code&gt;), 어떤 도구를 호출하는지(&lt;code&gt;Mcp-Name&lt;/code&gt;)가 HTTP 헤더로 필수로 실리도록 했습니다. 게이트웨이나 로드밸런서가 요청 본문&lt;span style="color:#999999;"&gt;(JSON)&lt;/span&gt;을 뜯어보지 않고도 특정 도구 호출만 골라서 다른 경로로 보내거나 차단하거나 기록하는 일을 할 수 있게 된 것입니다. 실제로 깃허브&lt;span style="color:#999999;"&gt;(GitHub)&lt;/span&gt;는 자사 MCP 서버를 신 스펙으로 옮기면서 본문 검사&lt;span style="color:#999999;"&gt;(deep packet inspection)&lt;/span&gt; 없이 헤더 기반 라우팅으로 바꿨다고 &lt;a href="https://github.blog/changelog/2026-07-23-github-mcp-server-supports-the-next-mcp-specification/"&gt;밝혔습니다&lt;/a&gt;.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;캐시 규칙도 표준화됐습니다. 도구 목록(&lt;code&gt;tools/list&lt;/code&gt;) 같은 조회 결과에는 캐시 유효 시간 힌트인 &lt;code&gt;ttlMs&lt;/code&gt;와 공유 캐시 허용 여부인 &lt;code&gt;cacheScope&lt;/code&gt;가 필수로 붙게 됐습니다. 목록이 연결마다 달라지는 것도 금지되어 같은 서버라면 누가 물어도 같은 목록이 나오는 캐시 가능한 구조를 전제로 삼았습니다. 여기에 요청이 여러 구성 요소를 거칠 때 하나의 흐름으로 이어서 추적하는 분산 추적도 오픈텔레메트리&lt;span style="color:#999999;"&gt;(OpenTelemetry)&lt;/span&gt; 기준으로 연동 방법이 문서화됐습니다. 이제 MCP 트래픽을 일반 웹 트래픽처럼 관리 도구로 다룰 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;4. 인증과 보안 강화: OAuth 실전 배포에 맞게 다듬음&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;원격 MCP 서버의 인증 계층도 여러 곳이 수정되었습니다. 고친 항목 하나하나는 작은 기술적 수정이지만 기업의 실제 OAuth·OIDC&lt;span style="color:#999999;"&gt;(OpenID Connect)&lt;/span&gt; 배포 환경에서 통용되게 만든다는 점에서는 모두 동일한 방향성을 가지고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;특히, 인가 응답에 발급자&lt;span style="color:#999999;"&gt;(issuer)&lt;/span&gt; 정보를 실어, 응답을 보낸 인가 서버가 클라이언트 자신이 요청했던 서버와 같은지 확인하게 하는 요건이 더해졌습니다. 공격자가 서로 다른 인가 서버의 응답을 뒤섞어 인가 코드를 가로채는 경로를 막기 위한 것입니다. 또한 클라이언트 자격 증명은 발급한 서버에만 쓸 수 있게 묶어 다른 서버에 재사용하지 못하게 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;사실 가장 눈에 띄는 변화는 클라이언트 등록 방식입니다. 그동안 쓰이던 동적 클라이언트 등록&lt;span style="color:#999999;"&gt;(DCR, Dynamic Client Registration)&lt;/span&gt;은 더 이상 사용을 권고하지 않는 상태&lt;span style="color:#999999;"&gt;(deprecated)&lt;/span&gt;로 변경되었습니다. 당장 지원이 끊기는 것은 아니고 기존 환경과의 호환을 위해 당분간 유지되지만 새로 만드는 구현에서는 쓰지 말라는 뜻입니다. 그 대신 HTTPS URL 자체가 클라이언트 ID가 되는 CIMD&lt;span style="color:#999999;"&gt;(Client ID Metadata Documents, 클라이언트 ID 메타데이터 문서)&lt;/span&gt;가 권장 방식으로 지정됐습니다. 클라이언트가 자기 메타데이터를 URL로 게시하면 어떤 인가 서버에서든 재등록 없이 통하는 방식입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개인이 로컬에서 stdio 방식으로 서버를 쓰는 경우에는 이 인가 스펙이 적용되지 않으니, 원격 HTTP 서버를 만들거나 운영하는 쪽에서 대응해야 하는 내용이라고 보면 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;5. 확장 프레임워크: 코어는 작게, 나머지는 확장으로&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 개정의 설계 방침이 잘 드러나는 변화입니다. 코어 프로토콜에는 &lt;code&gt;extensions&lt;/code&gt; 필드가 추가되어 클라이언트와 서버가 각자 지원하는 확장을 이 필드로 알립니다. 코어에 지금 담지 않기로 한 기능들은 공식 확장으로 분리하고 버전을 따로 매겨 관리하는 형태가 되었습니다. 쿠버네티스가 코어 API 밖에서 Gateway API 같은 프로젝트를 별도 버전으로 발전시켜 온 것과 비슷한 관리 방식이라고 볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Tasks&lt;/strong&gt;: 오래 걸리는 작업 처리가 코어의 실험 기능에서 공식 확장(&lt;code&gt;io.modelcontextprotocol/tasks&lt;/code&gt;)으로 이동했습니다. 서버가 작업 핸들을 돌려주면 클라이언트가 폴링&lt;span style="color:#999999;"&gt;(polling, 주기적으로 상태를 물어보는 방식)&lt;/span&gt;으로 진행 상황을 확인하고 접속이 끊겼다 돌아와도 결과를 받아갈 수 있습니다. 스트림 재개가 사라진 부분을 대신하는 기능이기도 합니다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;MCP Apps&lt;/strong&gt;: 서버가 채팅 화면 안에 렌더링되는 대화형 UI를 제공할 수 있게 하는 확장입니다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;EMA&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(Enterprise-Managed Authorization, 기업 관리형 인가)&lt;/span&gt;: 이번 개정과 묶여 자주 언급되는 기업용 인증 확장인데, 실제로는 이번 코어 스펙의 일부가 아니라 &lt;a href="https://modelcontextprotocol.io/extensions/auth/enterprise-managed-authorization"&gt;별도 확장&lt;/a&gt;으로 이미 6월에 안정화됐습니다. 이 구분이 매우 중요한 이유는, 스펙을 따라가는 일과 EMA를 도입하는 일이 서로 별개의 결정이기 때문입니다. 이를테면 직원이 회사의 IdP&lt;span style="color:#999999;"&gt;(Identity Provider, Okta 같은 신원 제공 서비스)&lt;/span&gt;에 한 번 로그인하면 서버마다 개별 동의 화면을 거치지 않고 회사가 승인한 MCP 서버들이 연결되는 방식입니다. IdP·클라이언트·서버 삼자가 모두 지원해야 동작하는 옵트인 기능이기에, 개인 사용자와는 무관합니다. 사내 MCP 접근 통제를 고민하는 조직이 지켜볼 영역입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;확장은 전부 선택 사항이고 기본으로 꺼져 있습니다. 코어를 가볍게 유지하면서 필요한 조직만 필요한 확장을 켜는 구조입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;6. 기능 정리와 수명주기: 세 기능이 제거 수순에 들어감&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;마지막은 기능을 덜어내는 변화입니다. Roots, Sampling, Logging 세 기능이 &lt;a href="https://modelcontextprotocol.io/specification/2026-07-28/deprecated"&gt;더 이상 사용을 권고하지 않는&lt;/a&gt; 상태가 됐습니다. 지금은 동작하지만 신규 구현에는 넣지 말라는 의미입니다. 각 기능이 하던 일과 스펙이 제시한 대안을 정리하면 다음과 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3893/img-04.png" alt="제거 예정 기능 3종 비교표: Roots(작업 디렉터리 공유→도구 파라미터·설정으로 경로 전달), Sampling(서버가 클라이언트 LLM 호출 대리→LLM 제공자 API 직접 호출), Logging(프로토콜 차원 로그 전달→표준 에러 출력 또는 오픈텔레메트리)"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번에는 이렇게 기능을 정리하는 절차 자체도 정해진 규칙을 따르게 되었습니다. 기능이 이 상태로 지정되면 최소 12개월은 유지된 뒤에야 제거될 수 있다는 &lt;a href="https://modelcontextprotocol.io/community/feature-lifecycle"&gt;수명주기 정책&lt;/a&gt;이 정식 문서로 만들어진 것입니다. 따라서 위 세 기능은 적어도 2027년 7월 28일까지는 그대로 유지되며 실제 제거는 그 이후에 나오는 첫 리비전에서야 가능합니다. 그 시점이 되어도 자동으로 제거되는 것은 아니고 메인테이너가 릴리스를 준비하며 결정하는 것이라 더 늦어질 수도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그에 반해 2024년 말의 초기 전송 방식인 HTTP+SSE&lt;span style="color:#999999;"&gt;(Server-Sent Events)&lt;/span&gt;는 정리 절차가 훨씬 앞서 있습니다. 아직 이 방식을 쓰고 있다면 가장 시급한 이전 대상입니다. 그러면 구 스펙(2025-11-25) 자체는 언제까지 지원될까요? 아쉽게도, 종료일은 명시되어 있지 않습니다. 수명주기 정책이 리비전이 아니라 기능 단위로 적용되기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;그래서 지금, 사용자 유형별로 해야 할 일&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;그럼 이제부터 각자의 자리에서 무엇을 하면 되는지 정리해 보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;MCP 서버를 붙여 쓰는 사용자&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;원칙적으로 할 일이 없습니다.&lt;/strong&gt; 버전 협상, 그리고 신 스펙이 통하지 않는 상대를 만나면 기존 방식으로 자동 전환해 다시 시도하는 폴백&lt;span style="color:#999999;"&gt;(fallback)&lt;/span&gt;은 클라이언트와 SDK가 처리합니다. 깃허브도 자사 MCP 서버를 전환하면서 “사용자는 아무것도 할 필요가 없다”라고 &lt;a href="https://github.blog/changelog/2026-07-23-github-mcp-server-supports-the-next-mcp-specification/"&gt;얘기했습니다&lt;/a&gt;.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 예외가 두 가지 있을 수 있습니다. 하나는 설정에 SSE 전송을 명시적으로 고정해 둔 경우로, 클라우드플레어&lt;span style="color:#999999;"&gt;(Cloudflare)&lt;/span&gt;는 자동 감지나 Streamable HTTP로 바꾸라고 &lt;a href="https://developers.cloudflare.com/changelog/post/2026-07-28-cloudflare-mcp-servers-mcp-2026-07-28/"&gt;안내됩니다&lt;/a&gt;. 다른 하나는 회사 내부 MCP 서버가 세션에 상태를 묶어 두는 경우입니다. 접속 시점 헤더로 받은 테넌트&lt;span style="color:#999999;"&gt;(tenant)&lt;/span&gt; 정보를 세션에 저장해 쓰는 유형의 서버라면 신 스펙 환경에서 동작이 어긋날 수 있습니다. 실제로 전환 시점 전후 이런 유형으로 추정되는 &lt;a href="https://github.com/anthropics/claude-code/issues/81965"&gt;동작 이상 보고&lt;/a&gt;도 올라왔습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;추가로 이 글을 작성하는 시점(8월 5일) 기준으로도 클라이언트 쪽은 공개된 정보가 부족하다는 점을 알아두면 좋겠습니다. 서버와 플랫폼에 대한 지원과 관련된 내용은 많이 나왔지만 앤트로픽은 “클로드 제품군에 순차 적용 중”이라고만 &lt;a href="https://claude.com/blog/bringing-mcp-2026-07-28-to-claude"&gt;밝혔고&lt;/a&gt; 커서의 &lt;a href="https://cursor.com/changelog"&gt;변경 이력&lt;/a&gt;에는 관련 언급이 아직 없습니다. 오픈AI 코덱스&lt;span style="color:#999999;"&gt;(Codex)&lt;/span&gt; CLI는 기능 플래그 등록에 이어 &lt;a href="https://github.com/openai/codex/pull/35724"&gt;일부 기반 코드를 넣는&lt;/a&gt; 단계라, 어느 클라이언트가 어느 버전부터 신 스펙을 지원하는지 정리된 표는 아직 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;서버를 만드는 개발자&lt;/strong&gt;&lt;/h4&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;마이그레이션을 실제로 계획해야 하는 시점입니다.&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;우선 스펙 확정과 같은 시기에 주요 SDK 안정 버전이 나왔습니다. 파이썬은 &lt;code&gt;mcp&lt;/code&gt; 2.0.0이 릴리스 당일 나왔습니다&lt;span style="color:#999999;"&gt;(이제&lt;/span&gt; &lt;code&gt;pip install m&lt;/code&gt;&lt;span style="color:#999999;"&gt;&lt;code&gt;cp&lt;/code&gt;가 2.x를 설치하므로, 준비가 안 된 프로젝트는&lt;/span&gt; &lt;code&gt;mcp&amp;gt;=1.28,&amp;lt;&lt;/code&gt;&lt;span style="color:#999999;"&gt;&lt;code&gt;2&lt;/code&gt;처럼 상한을 거는 것이&lt;/span&gt; &lt;a href="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.0.0"&gt;공식 권고&lt;/a&gt;&lt;span style="color:#999999;"&gt;입니다)&lt;/span&gt;. 타입스크립트는 기존 &lt;code&gt;@modelcontextprotocol/sdk&lt;/code&gt;가 1.x에서 멈추고 &lt;code&gt;@modelcontextprotocol/server&lt;/code&gt; 등 새 패키지의 2.0.0으로 나뉘었습니다. 그래서 새로 만드는 MCP 서버라면 처음부터 신 스펙&lt;span style="color:#999999;"&gt;(SDK 2.x)&lt;/span&gt;으로 시작하면 되고 구 스펙으로 새로 만들 이유는 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다행히 세션 관리 코드는 모두 지워집니다. 실제로 깃허브 MCP 서버를 옮긴 메인테이너 샘 모로우&lt;span style="color:#999999;"&gt;(Sam Morrow)&lt;/span&gt;도 얻은 것밖에 없다고 &lt;a href="https://www.arcade.dev/blog/mcp-maintainers-interview"&gt;말할 정도입니다&lt;/a&gt;.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;대신 손이 가는 곳은 세션에 두던 상태를 핸들이나 외부 저장소로 넘기는 일, 엘리시테이션을 MRTR 패턴으로 다시 작성하는 일, 그리고 오래 걸리는 작업을 Tasks 확장으로 옮기는 일입니다. 또, 파이썬 SDK 2.0.0에는 Tasks 확장이 아직 구현되지 않았으므로 장기 작업 의존 서버는 조금 기다려야 합니다. 마지막으로 신/구 클라이언트를 모두 받는 양쪽 지원&lt;span style="color:#999999;"&gt;(dual-era)&lt;/span&gt; 운영이 SDK 기본값이므로, 아직 사용자 중에 기존 버전을 사용하는 경우가 있을 수 있으니 그대로 두는 게 더 안전합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;배포/운영하는 팀&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;이번 변경으로 운영 구성이 실제로 단순해집니다.&lt;/strong&gt; 스티키 세션과 세션 공유 저장소가 필요 없어지고 쿠버네티스&lt;span style="color:#999999;"&gt;(Kubernetes)&lt;/span&gt; 서비스 뒤에 평범한 라운드로빈으로 레플리카를 늘리는 구성이 프로토콜 차원에서 성립합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;전환 전략으로는 게이트웨이를 앞에 두는 방법이 제시되어 있습니다. 오픈소스 MCP 게이트웨이인 에이전트게이트웨이&lt;span style="color:#999999;"&gt;(agentgateway)&lt;/span&gt;는 &lt;a href="https://github.com/agentgateway/agentgateway/releases/tag/v1.4.0"&gt;1.4.0 버전&lt;/a&gt;부터 신 스펙을 정식으로 지원합니다. 클라이언트를 일괄 업그레이드하지 않고 게이트웨이 뒤에서 서버만 먼저 올린 뒤 트래픽을 조금씩 옮기는 카나리&lt;span style="color:#999999;"&gt;(canary)&lt;/span&gt; 방식이 가능합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마지막으로, 적용 여부를 어떻게 판단하면 될까요? &lt;a href="https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning"&gt;호환되지 않는 조합&lt;/a&gt;은 정해져 있습니다. 신 스펙 전용 클라이언트가 구 스펙 전용 서버를 만나거나 그 반대인 경우만 실패하고 한쪽이라도 양쪽을 지원하면 동작합니다. 따라서 당분간은 양쪽을 다 지원하는 구성이 안전합니다. 강제 전환 시점이 없고 유예도 넉넉하니, 이를 상황별로 정리하면 다음과 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3893/img-05.png" alt="MCP 서버 사용자·서버 개발자·배포 운영팀 3열로 나눠 할 일·주의사항·전환 전략을 정리하고, 하단에 구형 HTTP+SSE 전송 사용자에게 최우선 전환을 안내하는 카드형 표"&gt;&lt;figcaption&gt;&lt;i&gt;사용자 유형과 상황별 권고 정리 &amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;결국, 이번 개정은 대다수가 쓰지 않던 기능을 걷어내고 웹에서 오래 검증된 스테이트리스 요청 모델로 돌아온 것이 가장 핵심 변화라고 볼 수 있습니다. 이는 즉, MCP가 실험적 프로토콜에서 운영 가능한 인프라로 넘어가는 단계가 된 것이라고 생각합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;깃허브와 클라우드플레어는 확정일 전후로 전환을 마쳤고 &lt;a href="https://aws.amazon.com/blogs/machine-learning/how-agentcore-gateway-supports-the-mcp-2026-07-28-spec/"&gt;AWS&lt;/a&gt;와 &lt;a href="https://techcommunity.microsoft.com/blog/appsonazureblog/mcp-just-went-stateless-%E2%80%94-what-the-2026-spec-changes-about-scaling-on-app-servic/4530222"&gt;마이크로소프트&lt;/a&gt;도 대응 방안을 내놨으니, 방향은 이미 정해진 셈입니다. 물론 이 글은 스펙과 공식 발표, 릴리스 직후 며칠간의 생태계 반응을 기준으로 쓴 것이라, 클라이언트 지원 현황 같은 부분은 앞으로 몇 주 사이에 빠르게 갱신될 수 있습니다. 영향을 크게 받는 분들이라면 꾸준히 커뮤니티를 주목하는 것이 좋겠습니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#757575;"&gt;참고로, 저는 이 중에서도 1번 항목인 스테이트리스 전환이 실제 운영 환경에서 어떤 차이를 만드는지가 궁금해졌습니다. 따라서 구 스펙 서버와 신 스펙 서버를 같은 쿠버네티스 클러스터에서 돌려 스케일아웃과 파드 교체 상황을 실측하는 실험을 준비하고 있습니다. “스티키 세션이 필요 없어졌다”는 말이 수치로는 어떻게 나타나는지, 괜찮은 측정 결과가 나온다면 또 소개해 보겠습니다.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;참고 자료&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;MCP 2026-07-28 공식 발표: &lt;a href="https://blog.modelcontextprotocol.io/posts/2026-07-28/"&gt;https://blog.modelcontextprotocol.io/posts/2026-07-28/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;스펙 변경 이력&lt;span style="color:#999999;"&gt;(changelog)&lt;/span&gt;: &lt;a href="https://modelcontextprotocol.io/specification/2026-07-28/changelog"&gt;https://modelcontextprotocol.io/specification/2026-07-28/changelog&lt;/a&gt;&lt;/li&gt;&lt;li&gt;SEP-2575 &lt;span style="color:#999999;"&gt;(Make MCP Stateless)&lt;/span&gt;: &lt;a href="https://modelcontextprotocol.io/seps/2575-stateless-mcp"&gt;https://modelcontextprotocol.io/seps/2575-stateless-mcp&lt;/a&gt;&lt;/li&gt;&lt;li&gt;SDK 베타 발표(호환성 정책 포함): &lt;a href="https://blog.modelcontextprotocol.io/posts/sdk-betas-2026-07-28/"&gt;https://blog.modelcontextprotocol.io/posts/sdk-betas-2026-07-28/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Arcade.dev 메인테이너 인터뷰: &lt;a href="https://www.arcade.dev/blog/mcp-maintainers-interview"&gt;https://www.arcade.dev/blog/mcp-maintainers-interview&lt;/a&gt;&lt;/li&gt;&lt;li&gt;GitHub MCP 서버 전환 안내: &lt;a href="https://github.blog/changelog/2026-07-23-github-mcp-server-supports-the-next-mcp-specification/"&gt;https://github.blog/changelog/2026-07-23-github-mcp-server-supports-the-next-mcp-specification/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;작가&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;조훈 (CNCF&amp;amp;AAIF 앰버서더)&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;쿠버네티스 및 AI 네이티브 기술 전문가로, CNCF와 에이전틱 AI 재단&lt;span style="color:rgb(153,153,153);"&gt;(AAIF)&lt;/span&gt; 글로벌 앰버서더이자 Kubestronaut이다. 쿠버네티스랩을 운영하며 인프라 자동화 기술을 연구하고 공유한다. ‘IT 인프라 엔지니어 그룹’ 운영진이자 오픈소스 컨트리뷰터로 활동 중이며, 맞춤형 인프라 교육, 쿠버네티스 비용 최적화, 멀티 LLM 및 AI 에이전트 비교 검증 등 다양한 실무 PoC를 수행하고 있다. 최근 출간한 『AI 시대에 개발자가 알아야 할 인프라 구성 배포 with 클로드 코드』를 포함해 총 5권의 IT 서적을 집필했으며, 인프런 강의 및 요즘IT 기고 등 지식 공유 활동을 이어가고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;심근우&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;LG유플러스 CTO부문에서 대고객 비즈니스 시스템의 DevOps를 담당하는 UcubeDAX팀의 팀장으로 일하고 있다. 퍼블릭 클라우드와 프라이빗 클라우드에 걸친 쿠버네티스 클러스터를 안정적으로 운영하기 위해 노력하고 있으며, 특히 주니어 DevOps 엔지니어들의 육성에 큰 관심을 가지고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;문성주&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;체커(CHEQUER) 사의 DevOps Engineer로서 쿠버네티스의 멀티 클러스터 관리 방법론과 쿠버네티스 구현체(CAPI, OCI)에 대한 명세와 컨테이너 리소스 격리 방법에 대한 연구를 병행하고 있다. 이런 연구 활동을 기반으로 쿠버네티스 볼륨 테스트 파트에 컨트리뷰션했다. 본업은 쿠버네티스 오퍼레이터와 같은 CRD(커스텀 리소스)를 개발해 현업에서 쿠버네티스를 좀 더 편리하게 사용할 수 있도록 돕는 일이다. 또한, 페이스북 그룹 ‘코딩이랑 무관합니다만'과 ‘IT 인프라 엔지니어 그룹'의 운영진을 맡고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;이성민&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;미국 넷플릭스(Netflix) 사의 Data Platform Infrastructure 팀에서 사내 플랫폼 팀들과 데이터 사용자들을 어우르기 위한 가상화 및 도구들을 개발하는 일들을 하고 있다. 과거 컨테이너와 쿠버네티스에 큰 관심을 두고 ingress-nginx를 비롯한 오픈 소스에 참여했으며, 현재는 데이터 분야에 일하게 되면서 stateful 한 서비스들이 컨테이너화에서 겪는 어려움을 보다 근본적으로 해결하기 위한 많은 노력을 하고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>23년 동안 살아남은 동네슈퍼를 데이터로 분석해봤습니다</title><link>https://yozm.wishket.com/magazine/detail/3883</link><description>부모님 가게의 15년 치 매출 데이터를 디지털로 복원했습니다. API가 없는 낡은 POS라 웹 크롤러를 직접 만들어 데이터를 추출하고 구조화했죠. 단순히 AI를 도입하는 게 아니라, 현장의 맥락을 파악하고 정보를 빠르게 이해할 수 있는 대시보드를 만드는 것부터 시작했습니다. 숨어있던 데이터를 실질적인 의사결정 도구로 바꾸는 과정, 이것이 제가 고민하는 진짜 AX(AI 전환)의 첫걸음입니다.</description><guid>https://yozm.wishket.com/magazine/detail/3883</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;저희 부모님은 23년째 동네 슈퍼마켓을 운영하고 계십니다. 그 덕에 저는 어릴 때부터 아버지를 따라 세무서, 회계사무소, 구청, 물류도매센터를 다니며, 유통과 장사의 뒷면을 지켜볼 수 있었습니다. 제조사·대리점·영업사원 사이에 얽힌 인센티브 구조, 같은 규정도 담당자에 따라 다르게 해석되던 행정 처리, 작은 창고 하나에서 시작해 공장까지 세운 납품업체의 성장 과정까지, 그 모든 장면이 결국 하나의 시스템이었다는 걸 시간이 지나 깨닫게 됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이런 경험은 중학생 때 직접 사업자등록을 내고 작은 온라인 판매를 해본 것으로 이어졌는데요. 지금은 해군 복무 중 LLM, RAG, 온톨로지를 공부하며 "이 기술을 어디에 써야 할까"라는 질문에 도달했습니다. 그리고 그 답을 가장 가까운 현장, 부모님 가게에서 찾아보기로 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 부모님이 운영하고 계신 나들가게 POS 데이터를 실제로 들여다보는 과정을 정리했습니다. 거창한 AI 대시보드가 아니라, 데이터를 정리하고 기본 지표(일별·시간대별 매출, 상품별 판매량, 객단가)를 뽑아보는 것부터 시작했는데요. 최근 화제가 된 클로드(Claude)의 페이블 5를 사용해보게 됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;페이블 5는 앤트로픽이 장시간 이어지는 복잡한 코딩과 에이전트 작업을 위해 내놓은 상위 모델입니다. 한동안 접근이 제한됐다가 한시적으로 다시 사용할 수 있게 됐습니다(2026년 7월 12일까지). 일상적인 개발에서는 다시 오푸스(Opus)를 주로 쓰게 될 가능성이 커서, 사용할 수 있을 때 제대로 한번 써보고 싶었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;써본 소감은 아주 단순했습니다. &lt;strong&gt;확실히 프런티어 모델은 알잘딱깔센을 잘했습니다.&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 모든 버튼과 간격, 상태 처리 방식을 하나하나 지시하지 않아도 됐습니다. 모델이 기존 코드와 화면을 확인하고, 원하는 방향을 어느 정도 추론한 뒤 결과물을 만들어냈습니다. 물론 모델이 제품의 방향까지 대신 결정해준 것은 아닙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;어떤 데이터를 남길 것인지, 과거 데이터와 현재 데이터를 어떻게 구분할 것인지, 무엇을 가장 먼저 보여줄 것인지, 이 서비스가 결국 어떤 의사결정을 도와야 하는지는 여전히 제가 판단해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;부모님은 23년 동안 동네 슈퍼마켓을 운영하셨고, 저는 가게에 쌓인 데이터를 꺼내 단순한 매출표가 아니라, 실제 운영자가 더 나은 결정을 내릴 수 있는 시스템을 만들어보고 싶었습니다. POS 데이터와 상품, 시간대, 거래처, 결제수단, 재고, 날씨, 상권을 연결하고, 나중에는 온톨로지와 LLM을 활용해 숫자 너머의 맥락까지 보고 싶었죠. 그런데 프로젝트를 실제로 시작하면서 가장 먼저 알게 된 것이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;AI를 붙이는 것보다 먼저 해야 할 일이 있었습니다. 바로 ‘데이터’부터 꺼내야 했습니다.&lt;/i&gt;&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3&gt;&lt;strong&gt;엑셀도 API도 없다면, 브라우저가 대신 읽게 하자&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;처음에는 간단하게 생각했습니다. POS 사이트에서 조회한 자료를 엑셀로 내려받고, 파이썬(Python)이나 판다스(Pandas)로 정리하면 되지 않을까?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 실제로 확인해보니 엑셀 추출이 되지 않았습니다. 화면에서는 월매출, 일별 거래건수, 객단가, 현금매출과 카드매출 같은 데이터를 볼 수 있었습니다. 다만 그 데이터를 분석 가능한 파일로 내려받는 기능은 사실상 쓸 수 없었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;API 문서도 찾을 수 없었습니다. 결국 선택지는 하나였습니다. 사람이 화면에서 읽을 수 있다면, 브라우저가 대신 읽게 해보자.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;나들가게 POS는 생각보다 오래된 시스템이었습니다.&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;정확한 최초 개발일을 공개 문서만으로 확정하기는 어려웠습니다. 다만 실제 관리 화면 하단에는 Copyright © 2009가 표시되어 있었고, 2010년에는 이미 점주들을 대상으로 나들가게 POS 교육이 진행되고 있었습니다. 적어도 현재 화면의 계보가 2000년대 말에서 2010년대 초반에 만들어진 시스템이라는 것은 확인할 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;공식 안내를 보면 나들가게 POS는 판매와 반품뿐 아니라 상품관리, 재고관리, 영업관리, 정산과 마감까지 다루는 시스템입니다. 별도의 경영분석시스템도 POS 판매기록을 바탕으로 매출과 이익, 방문객 수, 일·월 영업실적 등을 보여주도록 설계되어 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;데이터가 없었던 것은 아니었습니다. 오히려 필요한 데이터는 이미 상당 부분 존재했습니다. 문제는 그 데이터가 오래된 웹 화면 안에 흩어져 있고, 외부에서 쉽게 사용할 수 있는 형태로 열려 있지 않았다는 점이었습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존 화면은 오래된 GWT(Google Web Toolkit) 기반 웹 애플리케이션 형태였고, 메뉴와 프레임, 조회 결과가 여러 단계로 나뉘어 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image2_9UC6TKs.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 나들가게 POS, 작가 캡처&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 클로드(Claude)와 코덱스(Codex)를 활용해 HTML 구조와 프레임을 하나씩 확인하고, 로그인부터 메뉴 이동, 조회, 테이블 파싱까지 브라우저가 자동으로 수행하게 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;아이디와 비밀번호 입력 → 로그인 → 영업분석 메뉴 이동 → 월매출 캘린더 조회 → 셀 데이터 수집&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;첫 번째 목표는 이것뿐이었습니다. 그리고 결국 월매출 캘린더의 데이터를 가져오는 데 성공했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image5.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 나들가게 POS, 작가 캡처&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;처음 데이터를 가져오는 데 약 40초가 걸렸습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;40초를 5초로 줄이기까지&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;처음에는 성공했다는 사실만으로도 만족했습니다. 그런데 새로고침을 한 번 할 때마다 40초 가까이 기다려야 했습니다. 테스트 한 번은 괜찮았지만, 실제 서비스라면 쓸 수 없는 속도였습니다. 로그를 나눠서 확인해보니 사이트가 원래 느린 것 외에도, AI가 만든 크롤러 안에 불필요한 낭비가 꽤 많았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image4.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;가장 큰 문제는 이중 로그인이었습니다. 한 번 로그인한 뒤 바로 메뉴를 클릭하면 되는데, 캘린더 주소로 직접 접근하면서 로그인 페이지로 되돌아가고 있었습니다. 그 결과 로그인과 GWT 초기화가 두 번씩 발생했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;셀을 읽는 방식도 비효율적이었습니다. 화면에 있는 약 400개의 셀을 하나씩 파이썬으로 가져오면서 브라우저와 수백 번 통신하고 있었습니다. 이를 frame.evaluate 한 번으로 모든 셀의 텍스트를 묶어서 가져오는 방식으로 바꿨습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;스크린샷과 HTML 저장도 실패했을 때나 디버깅이 필요할 때만 실행하도록 바꿨습니다. 브라우저와 로그인 세션은 계속 살려뒀습니다. 새로고침을 누르면 다시 로그인하는 대신 이미 열린 세션에서 조회 버튼만 누르고 데이터를 읽도록 했습니다. 세션이 만료된 경우에만 자동으로 초기화하고 한 번 다시 시도하게 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마지막으로 배경 예열을 추가했습니다. 서비스가 시작되면 데이터를 미리 가져오고, 기본 10분마다 다시 갱신해 캐시를 채우도록 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그 결과 속도는 다음과 같이 줄었습니다.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;캐시된 일반 접속: 거의 즉시&lt;/li&gt;&lt;li&gt;수동 새로고침: 약 5초&lt;/li&gt;&lt;li&gt;최초 배포 후 콜드 스타트: 약 15초&lt;/li&gt;&lt;li&gt;기존 방식: 약 40초&lt;/li&gt;&lt;li&gt;그런데 속도를 줄이고 나니 또 다른 문제가 보였습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;바뀌지 않는 데이터를 왜 매번 다시 조회해야 할까?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;2012년 1월 매출을 조회한다고 가정해보겠습니다. 처음 조회할 때 오래 걸리는 것은 어느 정도 이해할 수 있습니다. 하지만 같은 달의 데이터를 며칠 뒤 다시 보고 싶을 때도, 또 오래된 POS에 로그인하고 또 같은 화면을 불러오고 또 같은 데이터를 크롤링해야 했습니다. 이상했습니다. 2012년 1월 매출은 더 이상 바뀌지 않습니다. 지난달 데이터도 마감이 끝났다면 바뀔 가능성이 거의 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 왜 볼 때마다 원본 POS를 다시 조회해야 할까? 그래서 데이터 구조를 바꾸기로 했습니다. 과거 데이터는 한 번 가져오면 데이터베이스에 저장하고, 현재 진행 중인 달만 다시 조회하는 방식입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Supabase에 monthly_sales, daily_sales 등의 테이블을 만들었습니다. 월별 총매출, 거래건수, 객단가, 일평균 매출, 반품 건수와 금액, 수집 시각, 월 마감 여부를 저장했습니다. 현재 달은 계속 변하므로 새로고침할 때 POS에서 다시 가져옵니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반면, 이미 끝난 달은 Supabase에서 즉시 읽습니다.&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;나들가게 POS
    ↓
브라우저 자동화·크롤링
    ↓
데이터 정규화
    ↓
Supabase 저장
    ↓
새로운 조회·분석 UI
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존 POS는 여전히 원천 시스템입니다. 제가 만든 서비스는 운영 데이터를 수정하지 않고, 그것을 가져와 조회와 분석에 적합한 형태로 저장하는 새로운 읽기 계층입니다. 그리고 2011년 7월, 부모님 가게에 POS가 처음 도입된 시점부터 월별 데이터를 순차적으로 가져와 저장했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;가게 자체의 역사는 23년이지만, 디지털로 남은 매출의 역사는 약 15년입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image6.png"&gt;&lt;figcaption&gt;&amp;lt;출처: Supabase, 작가 캡처&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이제 2012년 1월을 보든, 2018년 6월을 보든 매번 오래된 POS를 다시 기다릴 필요가 없습니다. 한 번 가져온 과거 데이터는 데이터베이스에서 바로 불러옵니다. 이 결정 하나로 서비스의 성격이 바뀌었습니다. 이전에는 오래된 POS 화면을 대신 열어주는 크롤러였다면, 이제는 매장의 역사를 자체적으로 보관하고 조회하는 서비스가 됐습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;조회할 수 있는 화면에서 이해할 수 있는 화면으로&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;데이터를 가져온 뒤에는 화면도 다시 만들었습니다. 기존 POS에도 필요한 숫자는 있었습니다. 문제는 정보가 너무 많은 표와 메뉴 안에 흩어져 있다는 점이었습니다. 월매출을 보려면 월매출 캘린더를 열어야 하고, 날짜를 누르면 오른쪽에 세부 결제수단이 나옵니다. 지난달과 비교하려면 다른 화면을 열어야 하고, 월별 흐름을 보려면 숫자를 직접 기억하거나 옮겨 적어야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존 화면이 틀렸다는 의미는 아닙니다. 당시의 업무 환경에서는 많은 기능을 한 화면에 제공하는 것이 중요했을 것입니다. 하지만 제가 만들고 싶은 서비스의 목적은 달랐습니다. “조회할 수 있는 화면”보다 “빠르게 이해할 수 있는 화면”이 필요했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 토스증권의 정보 구조를 참고했습니다. 토스증권은 모든 숫자를 한꺼번에 보여주기보다, 사용자가 현재 가장 궁금해할 정보부터 위계를 만들어 보여줍니다. 제가 만든 화면도 같은 원칙으로 다시 구성했습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;상단에는 이번 달 총매출을 가장 크게 배치했습니다. 바로 아래에는 전월 대비 변화, 거래건수, 객단가, 일평균 매출, 최고 매출일을 두었습니다. 그다음에는 일별 매출 그래프와 최근 6개월·12개월 흐름을 배치했습니다. 아래에는 현금매출, 카드매출, 포인트매출 등 결제수단의 구성을 정리했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;현재 진행 중인 달은 완료된 달과 구분해 진행 중 상태로 표시했습니다. 아직 끝나지 않은 달을 전월과 단순 비교하면, 큰 폭으로 하락한 것처럼 오해할 수 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image8.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;단순히 색상을 바꾸고 카드 형태로 만든 것은 아닙니다. 사용자가 숫자를 이해하는 순서를 다시 설계했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;지금 매출이 얼마인가?&lt;/li&gt;&lt;li style="text-align:justify;"&gt;지난달보다 올랐는가?&lt;/li&gt;&lt;li style="text-align:justify;"&gt;거래건수와 객단가 중 무엇이 변했는가?&lt;/li&gt;&lt;li style="text-align:justify;"&gt;어느 날 매출이 높았는가?&lt;/li&gt;&lt;li style="text-align:justify;"&gt;최근 흐름은 상승인가 하락인가?&lt;/li&gt;&lt;li style="text-align:justify;"&gt;어떤 결제수단으로 매출이 발생했는가?&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존 POS의 메뉴와 표를 그대로 복사하지 않고, 사용자의 질문을 기준으로 정보를 다시 배열했습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;동네슈퍼에서 해본 아주 작은 차세대 프로젝트&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;만들고 보니 아주 작은 ‘차세대 프로젝트’ 같았습니다. IT 업계에서 차세대 프로젝트라는 말을 자주 사용합니다. 오래된 ERP나 업무 시스템을 새로운 데이터 구조와 화면, 인프라로 다시 만드는 프로젝트를 의미합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 한 일이 기업 단위의 거대한 차세대 프로젝트와 같다고 말할 수는 없습니다. 하지만 구조는 꽤 닮아 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&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;li&gt;현대적인 사용자 경험으로 재구성했습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;작은 동네 슈퍼마켓을 대상으로 한 아주 작은 레거시 현대화 프로젝트였던 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;코드를 쓰는 비용이 낮아지면 무엇이 남을까?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이 작업을 하면서 기존에 ERP, MES(제조실행시스템), 관리자 대시보드를 구축해온 업체들의 해자가 예전보다 많이 낮아질 수 있겠다는 생각도 들었습니다. 과거에는 오래된 시스템을 분석하고, 별도의 데이터베이스와 화면을 만들고, 자동화 코드를 작성하려면 상당한 개발 인력과 비용이 필요했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지금은 클로드 코드(Claude Code)나 코덱스 같은 도구를 쓸 수 있습니다. 기존 HTML을 분석하고, 크롤러를 만들고, 데이터베이스 스키마를 설계하고, 프런트엔드를 구현하는 데 드는 비용과 시간이 크게 줄었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 모든 해자가 사라지는 것은 아닙니다. 실제 현장을 이해하고, 데이터의 의미를 정의하고, 기존 시스템과 안정적으로 연결하고, 장애와 예외를 관리하는 역량은 여전히 중요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;오히려 코드를 작성하는 비용이 낮아질수록 이런 판단 역량이 더 중요해질 것 같습니다. “어떻게 개발할 것인가”보다, &lt;strong&gt;“무엇을 왜 만들어야 하는가”&lt;/strong&gt;가 더 큰 차이가 되는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;15년치 데이터가 보여준 변화&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;2011년의 데이터를 열어보니, 매출표가 아니라 시간의 기록처럼 보였습니다.&lt;/strong&gt;처음에는 월별 숫자를 저장하는 것만 생각했습니다. 그런데 2011년과 2012년 데이터를 실제로 조회해보니 예상보다 훨씬 많은 질문이 생겼습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;2012년 1월의 객단가는 5,566원이었습니다. 최근에는 대체로 9,000원 안팎까지 올라와 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:80%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image7.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;2012년에는 현금매출이 압도적으로 많았고, 카드매출의 비중은 훨씬 작았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:80%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image10.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지금은 반대입니다. 카드와 각종 전자결제가 매출의 대부분을 차지합니다. 한 가게의 데이터 안에 한국 사회의 결제 방식 변화가 그대로 남아 있었습니다. 객단가가 5,000원대에서 9,000원대로 오른 것도 흥미로웠습니다. 물론 이것을 단순히 “물가가 올랐기 때문”이라고 단정할 수는 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;상품 가격의 상승도 영향을 줬겠지만, 상품 구성과 고객층, 한 번에 구매하는 물품 수, 주변 경쟁점, 소비 습관도 함께 바뀌었을 수 있습니다. 그렇기 때문에 오히려 다른 데이터를 연결할 필요가 생깁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&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;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 style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;2020년, 재난지원금이 지급된 뒤 매출이 눈에 띄게 올랐던 시기가 있었습니다. 주변에 편의점이 생긴 뒤 매출이 크게 떨어졌던 기억도 있습니다. 지금까지는 부모님의 기억으로만 남아 있던 사건입니다. 하지만 15년치 월별·일별 데이터를 확보하면 실제 변화가 발생한 날짜를 찾을 수 있습니다. 지원금 지급 전후로 거래건수와 객단가가 어떻게 변했는지, 편의점 개점 이후 어떤 품목과 시간대의 매출이 먼저 떨어졌는지 확인할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이때부터 데이터는 단순한 매출표가 아니라, 현장의 사건과 연결되는 기록이 됩니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;숫자만으로는 보이지 않는 현장의 구조&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;숫자만 많다고 현장을 이해하는 것은 아닙니다. 기존의 회귀분석이나 머신러닝으로도 매출과 날씨, 요일, 가격 사이의 상관관계를 찾을 수 있습니다. 하지만 숫자만 놓고 보면 그 사이에 숨어 있는 현장의 구조를 놓치기 쉽습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어, 편의점이 생긴 뒤 매출이 떨어졌다고 해도, 모든 상품이 똑같이 영향을 받은 것은 아닐 것입니다. 편의점이 강한 담배, 음료, 간편식이 먼저 영향을 받았을 수 있습니다. 반대로 대용량 생필품이나 동네 단골이 외상으로 구매하던 상품은 영향을 덜 받았을 수도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;정책지원금이 풀린 뒤 매출이 올랐다고 해도, 단순히 손님이 많아진 것인지, 기존 고객의 객단가가 올라간 것인지, 특정 상품군에만 소비가 집중된 것인지 나눠봐야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;숫자만 보면 매출 상승입니다. 현장의 구조를 연결하면 다음처럼 바뀝니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;정책지원금 지급&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 특정 결제수단 사용 증가&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 기존 고객의 객단가 상승&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 생필품과 고단가 상품 판매 증가&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 월매출 증가&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또는 다음과 같을 수도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;인근 편의점 개점&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 야간·출근시간 고객 이동&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 담배·음료 거래건수 감소&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 전체 고객수 감소&lt;/p&gt;&lt;p style="text-align:justify;"&gt;→ 월매출 하락&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;온톨로지로 담고 싶은 세 계층&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;제가 온톨로지에 관심을 갖는 이유도 여기에 있습니다. 온톨로지는 단순히 그래프를 멋지게 그리는 기술이 아닙니다. 상품과 카테고리, 거래처, 결제수단, 시간, 날씨, 정책, 경쟁점, 매장의 의사결정을 서로 연결해 현장의 구조를 표현하는 방법입니다. 저는 앞으로 이 구조를 세 계층으로 만들고 싶습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;첫 번째는 매장의 기본 개체입니다.&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;상품, 카테고리, 거래처, 결제수단, 날짜, 시간대, 고객군&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;두 번째는 실제 발생한 사건입니다.&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;판매, 반품, 가격 변경, 지원금 지급, 경쟁점 개점, 비와 폭염&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;세 번째는 가게의 의사결정입니다.&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;무엇을 더 발주할지, 가격을 바꿀지, 어디에 진열할지, 어떤 상품을 묶어 팔지&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 세 계층이 연결돼야 단순히 “무슨 일이 있었는가”를 넘어서 “왜 그랬고, 다음에는 무엇을 바꿀 것인가”에 답할 수 있다고 생각합니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;조직에 맞는 AX는 무엇부터 구조화해야 할까?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이 프로젝트를 하면서 AX에 대해서도 다시 생각하게 됐습니다. 최근 많은 기업과 조직이 AX를 이야기합니다. 문서를 요약하고, 사내 자료를 검색하고, 회의록을 정리하는 AI를 도입합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이런 기능도 분명히 유용합니다. 하지만 단건의 문서 요약이나 검색만으로 조직이 AI 네이티브로 바뀌었다고 보기는 어렵습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;진짜 조직에 맞는 AX를 하려면, 그 조직이 실제로 어떻게 판단하고 움직이는지를 먼저 구조화해야 한다고 생각합니다.&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;li&gt;문서에는 없지만 구성원들이 당연하게 여기는 가정은 무엇인가&lt;/li&gt;&lt;li&gt;의사결정 결과가 다음 단계에 어떤 영향을 미치는가&lt;/li&gt;&lt;li&gt;이런 암묵지와 의사결정 구조가 워크플로에 담겨 있어야 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;LLM은 학습 과정에서 역전파를 통해 방대한 언어 패턴을 익히고, 실제 생성 과정에서는 주어진 문맥을 바탕으로 다음 토큰의 확률 분포를 계산해 결과를 만듭니다. 이 방식은 매우 강력하지만, 조직 고유의 맥락이 없으면 자연스럽게 일반적이고 평균적인 답변으로 흐를 수 있습니다. 다음 토큰 예측은 현대 언어모델의 핵심 학습·생성 구조지만, 그것만으로 특정 조직의 규칙과 예외, 책임 구조가 자동으로 생기는 것은 아닙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3883/image9.png"&gt;&lt;figcaption&gt;&amp;lt;출처: X, @akshay_pachaar&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 AI에 문서만 많이 넣는다고 우리 조직에 맞는 AI가 만들어지는 것은 아닙니다. 우리 조직의 개체와 관계, 이벤트, 규칙, 예외, 의사결정 단계를 먼저 정리해야 합니다. 그 위에서 AI가 워크플로를 따라 움직여야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;조직이 AI의 방식에 맞추는 것이 아니라, AI가 조직의 실제 구조를 이해하고 따라가게 만들어야 합니다. 동네 슈퍼마켓 프로젝트는 아주 작은 사례지만 본질은 비슷합니다. 단순히 POS 매출표를 LLM에 넣고 “인사이트를 알려줘”라고 하면 그럴듯한 말은 만들 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 왜 특정 상품을 계속 취급했는지, 거래처와 어떤 조건으로 거래했는지, 편의점이 언제 들어왔는지, 특정 정책이 어떤 고객에게 영향을 줬는지는 알기 어렵습니다. 이런 맥락을 모르면 현장에 맞는 판단을 내릴 수 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 AI보다 먼저 필요한 것은 조직과 현장의 구조입니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;아직 이 프로젝트에 AI가 없다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;아직 이 프로젝트에는 AI가 거의 없습니다. 현재까지 가져온 데이터는 나들가게 POS의 월매출 캘린더 정보가 중심입니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지금 볼 수 있는 것은 다음 정도입니다.&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;월별 총매출&lt;/li&gt;&lt;li style="text-align:justify;"&gt;월별 거래건수&lt;/li&gt;&lt;li style="text-align:justify;"&gt;객단가&lt;/li&gt;&lt;li style="text-align:justify;"&gt;일평균 매출&lt;/li&gt;&lt;li style="text-align:justify;"&gt;일별 매출&lt;/li&gt;&lt;li style="text-align:justify;"&gt;현금매출&lt;/li&gt;&lt;li style="text-align:justify;"&gt;카드매출&lt;/li&gt;&lt;li style="text-align:justify;"&gt;포인트매출&lt;/li&gt;&lt;li style="text-align:justify;"&gt;최근 6개월과 12개월 흐름&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;아직 상품별 판매 데이터도 충분히 가져오지 못했습니다. 카드사별 매출, 카테고리별 매출과 이익, 거래처별 상품, 재고와 발주 데이터도 추가해야 합니다. 그래프 데이터베이스도 없습니다. 온톨로지도 아직 만들지 않았습니다. LLM에 자연어로 질문하는 기능도 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇지만 저는 지금 단계가 중요하다고 생각합니다. AI를 붙이기 위한 가장 기본적인 토대를 만들었기 때문입니다. 데이터가 어디에 있는지 확인했고, 사람이 화면을 열지 않아도 자동으로 가져올 수 있게 만들었습니다. 변하지 않는 과거 데이터를 데이터베이스에 쌓았고, 사용자가 빠르게 이해할 수 있는 화면으로 다시 구성했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앞으로는 여기에 하나씩 데이터를 붙여갈 생각입니다. 먼저 상품별 매출과 이익, 카테고리와 거래처 데이터를 가져옵니다. 그다음 날씨와 공휴일, 물가, 상권, 정책 데이터를 연결합니다. 이후 상품, 거래처, 시간, 외부 사건, 운영 의사결정을 그래프와 온톨로지로 구조화합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마지막에 LLM을 붙이려고 합니다. LLM이 숫자를 직접 계산하고 근거 없이 판단하게 하려는 것은 아닙니다. 구조화된 데이터와 규칙, 과거 실험 결과를 바탕으로 설명하고 다음 행동을 제안하게 만들고 싶습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI는 마지막입니다. 먼저 현장을 담아야 합니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 단계에서 제가 한 일은, 어쩌면 데이터를 구출한 것에 가깝습니다. 가게에는 이미 15년치 디지털 기록이 있었습니다. 하지만 그 데이터는 오래된 POS 화면을 한 달씩 넘겨보지 않으면 볼 수 없었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한 번 본 과거 데이터를 다시 보기 위해 또 로그인하고, 또 기다리고, 또 조회해야 했습니다. 저는 그 데이터를 꺼내 데이터베이스에 쌓고, 다시 빠르게 볼 수 있는 화면을 만들었습니다. 아직 이 시스템은 제가 최종적으로 만들고 싶은 의사결정 도구가 아닙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지금은 토대에 가깝습니다. 하지만 이제 최소한 2011년의 가게와 2026년의 가게를 같은 화면에서 비교할 수 있습니다. 현금 중심의 매장이 카드 중심의 매장으로 바뀐 과정도 볼 수 있습니다. 객단가가 5,000원대에서 9,000원대로 이동한 과정도, 부모님의 기억 속에 있던 사건을 실제 날짜와 숫자로 다시 확인하는 일도 가능합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;1편에서는 이런 질문을 했습니다. 부모님 가게는 어떻게 23년 동안 망하지 않고 살아남았을까? 아직 답을 찾지는 못했습니다. 다만 이제 그 질문에 답할 수 있는 데이터를 처음으로 한곳에 모으기 시작했습니다. 그리고 다음 단계에서는 단순히 매출이 오르고 내린 것을 보는 것을 넘어, 어떤 상품과 거래처, 어떤 시간대와 외부 사건이 그 변화에 영향을 줬는지 연결해보려고 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;데이터가 없었던 것이 아니었습니다. 오래된 화면 안에 갇혀 있었을 뿐입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번에는 그 데이터를 꺼냈습니다. 이제부터는 그 데이터에 현장의 맥락을 연결해 보려고 합니다.&lt;/p&gt;&lt;hr&gt;&lt;p style="text-align:justify;"&gt;&amp;lt;원문&amp;gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;a href="https://velog.io/@minority_report/23%EB%85%84-%EB%8F%99%EC%95%88-%EC%82%B4%EC%95%84%EB%82%A8%EC%9D%80-%EB%8F%99%EB%84%A4%EC%8A%88%ED%8D%BC%EB%A5%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A1%9C-%EB%B6%84%EC%84%9D%ED%95%B4%EB%B3%B4%EB%A0%A4-%ED%95%A9%EB%8B%88%EB%8B%A4.-2%ED%8E%B8"&gt;&lt;u&gt;23년 동안 살아남은 동네슈퍼를 데이터로 분석해보려 합니다. (2편)&lt;/u&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>AI 시대의 엔지니어링: 이 일, 정말 AI에 시켜야 하는가?</title><link>https://yozm.wishket.com/magazine/detail/3882</link><description>훌륭한 엔지니어링은 언제나 ‘목적에 맞는 가장 단순한 도구’를 선택하는 데서 출발합니다. 그 원칙을 프론트엔드 API 연동 코드에 그대로 적용해, 같은 OpenAPI 스펙으로 코드젠 Orval과 AI가 각각 코드를 생성하게 하고 결과를 직접 비교했습니다. Orval은 1초 만에 비용 없이 스펙 그대로를 옮겼지만, AI는 2~4분에 매번 비용을 치르고도 실행마다 다른 코드를 내놓았습니다. 결정론적인 일은 자동화에 맡기고 맥락을 읽고 판단해야 하는 일에만 AI를 투입해야 하는 이유를, Orval과 Hey API 비교 예시로 짚었습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3882</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;결정론적인 일은 자동화에, 추론이 필요한 일은 AI에&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;바야흐로 AI의 시대입니다. 코드 리뷰도, 리팩토링도, 테스트 작성도 AI에 맡기는 것이 자연스러운 풍경이 됐습니다. 그런데 역설적이게도, AI가 만능처럼 보이는 지금이야말로 필요한 질문이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;“이 일, 정말 AI에게 시켜야 하는 일인가?”&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;훌륭한 엔지니어링은 언제나 ‘목적에 맞는 가장 단순한 도구’를 선택하는 것에서 출발합니다. CSS로 가능한 것은 JavaScript가 아닌 CSS로 처리해야 합니다. 브라우저가 기본으로 제공하는 기능을 사용하는 것이 훨씬 빠르고, 안전하며, 가볍기 때문입니다. 더 강력한 도구가 항상 더 나은 선택은 아니라는 것. 이 원칙은 AI 시대에도 그대로 적용됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;따라서 AI를 맹목적으로 더 많이 사용하는 것보다, 기술의 성격에 따라 명확한 경계를 나눌 때 더 효율적이고 빠른 워크플로우를 만들 수 있습니다. 따라서 이 글에서는 &lt;strong&gt;‘결정론적인 일은 자동화, 추론은 AI’&lt;/strong&gt;라는&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;기준을 바탕으로, 프론트엔드 API 연동 코드를 만들 때 AI 워크플로우를 더 효율적으로 만드는 방법과 이를 뒷받침할 구체적인 방법론을 소개해 보려고 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;패러다임의 분리: 결정론적 자동화 vs 확률적 AI&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3882/img-01.png" alt="결정론적 자동화(타입 생성·API 보일러플레이트·스키마 동기화)와 확률적 AI(비즈니스 로직·UI 프로토타입·아키텍처 제안)로 나눈 두 엔지니어링 영역 비교 인포그래픽"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&lt;span style="color:#999999;"&gt;(Gemini로 생성)&lt;/span&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;효율적인 엔지니어링 워크플로우를 구축하기 위해서는 기술적 접근법을 크게 두 가지 영역으로 분리할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;결정론적 영역&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(Deterministic)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;입력이 같으면 출력도 항상 동일해야 하는 영역입니다. 타입 생성, API 통신 보일러플레이트, 데이터 스키마 동기화, 코드 스타일 통일이 여기에 속합니다. 규칙과 규격이 명확하기 때문에 고도의 추론이 아닌, 오차 없는 ‘기계적 번역’이 핵심입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;확률적 영역&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(Probabilistic)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;주어진 맥락과 컨텍스트에 따라 최선의 답이 달라지며, 복잡한 추론과 트레이드오프&lt;span style="color:#999999;"&gt;(Trade-off)&lt;/span&gt; 판단이 요구되는 영역입니다. 비즈니스 로직 설계, 레거시 코드의 의도 파악, UI 프로토타입 작성, 아키텍처 리팩토링 제안 등이 대표적입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그럼 AI는 어떤 일에 더 적합할까요? 이 도구는 추론에 강점을 지니고, 그러니 확률적 영역에 투입하는 것이 더 큰 변화를 만들어냅니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데, 현실에서는 결정론적 영역에까지 AI를 투입하는 경우가 적지 않습니다. 대표적인 예가 swagger.json을 통째로 복사해 프롬프트 창에 붙여넣고 “이거 보고 API 훅이랑 타입 좀 만들어줘”라고 던지는 방식입니다. 언뜻 잘 작동하는 것처럼 보이지만, 여기에는 눈에 잘 띄지 않는 몇 가지 비용이 숨어 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;비결정성&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(Non-determinism)&lt;/span&gt;&lt;strong&gt;:&lt;/strong&gt;&amp;nbsp;AI는 동일한 입력값을 주더라도 매번 미묘하게 다른 코드를 생성합니다. 어제 생성한 훅과 오늘 생성한 훅의 네이밍 규칙이나 에러 핸들링 방식이 달라질 수 있으며, 이러한 편차가 누적되면 결국 전체 코드베이스의 일관성이 무너질 수 있습니다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;속도와 비용&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(Speed &amp;amp; Cost)&lt;/span&gt;&lt;strong&gt;:&lt;/strong&gt;&amp;nbsp;전용 코드 생성기&lt;span style="color:#999999;"&gt;(Generator)&lt;/span&gt;는 수백 개의 엔드포인트를 단 몇 초 만에, 리소스 비용 없이 완벽하게 처리합니다. 반면 AI는 불필요하게 토큰을 소모하며 처리 속도 또한 상대적으로 느립니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;동일한 스펙에서 언제나 100% 일치하는 결과물을 보장하는 전용 도구가 이미 존재하는데도, 조금씩 다른 답을 내놓을 수 있는 AI를 고집할 이유는 없습니다. 적어도 결정론적 영역에서만큼은 &lt;strong&gt;전통적인 자동화가 AI보다 훨씬 정확하고, 빠르며, 비용 효율적&lt;/strong&gt;입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;케이스 스터디: API 연동 코드와 ‘코드젠&lt;/strong&gt;&lt;span style="color:#999999;"&gt;&lt;strong&gt;(Codegen)&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;’&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3882/img-02.png" alt="OpenAPI(Swagger) 스펙 하나에서 TypeScript 타입, API 호출 함수·훅, 검증 스키마 세 갈래가 뻗어나가는 구조도"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&lt;span style="color:#999999;"&gt;(NotebookLM으로 생성)&lt;/span&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 원칙이 가장 극적인 효과를 내는 영역이 바로 &lt;strong&gt;프론트엔드의 API 연동 코드 작성&lt;/strong&gt;입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;백엔드와 프론트엔드 간의 API 통신은 철저하게 ‘약속&lt;span style="color:#999999;"&gt;(Specification)&lt;/span&gt;’에 기반한 결정론적 영역입니다. 게다가 OpenAPI 스펙은 시스템 전체를 관통하는 &lt;strong&gt;단일 진실 원천&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(Single Source of Truth)&lt;/span&gt;입니다. 타입도, 함수도, 훅도, 검증 스키마도 전부 이 한 파일에서 끌어낼 수 있습니다. 그러니 이 일에 AI를 쓸 이유가 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;코드젠 vs AI 실험 설계&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이 격차가 실제로 어느 정도인지 숫자로 확인하기 위해, 프로젝트의 실제 OpenAPI 스펙(&lt;strong&gt;53개 엔드포인트 · 90개 스키마&lt;/strong&gt;)을 두 방식으로 직접 생성해 측정했습니다. 정답 스펙이 이미 존재하는 결정론적 영역에서 코드젠과 AI의 산출물을 직접 대조하고자, 동일한 OpenAPI 스펙을 양쪽에 그대로 맡겨 진행했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3882/img-03.png" alt="코드젠 vs AI 비교표: Orval과 AI(claude-fable-5)의 생성 시간(0.55~1.10초 vs 2분13초~3분54초), 비용($0 vs 회당 $1.40~1.43), 결정성(diff 0줄 vs 447~520줄 상이), 타입 에러(0개 vs 1회차 4개·2회차 0개)"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI에게는 “이 스펙으로 API 연동 코드를 생성하라”, “Orval로 코드젠을 실행하고 생성 시간·비용·결정성·타입 에러를 측정하라, 결정성 확인을 위해 2회 실행하라”와 같이 지시했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;측정값 자체는 실행 로그, 산출물 diff, &lt;code&gt;tsc --noEmit&lt;/code&gt;&amp;nbsp;결과처럼 기계적으로 검증 가능한 항목이라 측정 주체와 무관하게 동일하게 재현됩니다. 반복 횟수를 2회로 둔 이유도 있습니다. 코드젠은 정의상 몇 번을 돌려도 byte 단위로 동일해 반복 측정 자체가 무의미하고, AI 역시 “매번 다른 결과가 나온다”는 질적 대비를 보이는 데는 2회로 충분했기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 여기서 확인하려는 명제는 “AI가 평균 몇 % 흔들리는가”가 아니라 “결정론적 도구는 항상 같고 AI는 매번 다르다”는 대비였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;코드젠&amp;nbsp;vs AI 결과&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Orval은 엔드포인트를 약 &lt;strong&gt;1초 만&lt;/strong&gt;에 생성했습니다. 비용은 $0이고, 스펙의 모든 필드를 정확히 옮겼으며, 타입 에러도 없었습니다. 몇 번을 다시 돌려도 byte 단위로 똑같은 코드가 나옵니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반면 AI는 같은 일을 하는 데 2~4분이 걸렸고, 실행할 때마다 약 $1.4(약 2,000원)씩 들었습니다. 두 번의 실행 결과가 서로 달랐고, 한 번은 타입 에러 4개를 남겼습니다. 더 느리고, 더 비싸고, 매번 조금씩 다른 코드를 내놓았습니다. 스펙이라는 정답지가 이미 있는 영역에서 코드젠이 속도, 비용, 정확성, 일관성 전 항목에서 압도적이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3882/img-04.png" alt="코드젠은 106KB JSON을 AST 파싱해 순간적으로 5,400줄 TypeScript를 생성하고, AI는 40k 토큰을 프리필한 뒤 토큰을 하나씩 확률적으로 추측하며 느리게 흘려보내는 대비 삽화"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&lt;span style="color:#999999;"&gt;(NotebookLM으로 생성)&lt;/span&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;이런 차이가 나는 구조적인 이유&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;코드젠은 ‘번역기’입니다.&lt;/strong&gt;&amp;nbsp;Orval은 스펙 JSON을 파싱해 각 스키마와 엔드포인트를 추상 구문 트리&lt;span style="color:#999999;"&gt;(AST)&lt;/span&gt;에 가까운 중간 표현으로 올립니다. 그다음 미리 정해진 변환 규칙(템플릿)에 따라 TypeScript 코드를 그대로 방출합니다. 또, 스키마 하나에서 어떤 코드가 나올지는 실행 전에 이미 규칙으로 결정되어 있습니다. 남은 일은 106KB의 JSON을 5,400여 줄의 TS로 ‘기계적으로 옮겨 적는’ 순수 CPU 문자열 변환뿐입니다. 추론도, 탐색도, GPU도, 네트워크 왕복도 없습니다. 그래서 5,400여 줄을 통째로 만들어내는 데 1초가 걸리지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;AI는 ‘생각하면서 타이핑하는 기계’입니다.&lt;/strong&gt;&amp;nbsp;LLM은 자기회귀&lt;span style="color:#999999;"&gt;(autoregressive)&lt;/span&gt; 방식으로 동작합니다. 출력 코드를 토큰(대략 몇 글자) 단위로 하나씩, 앞선 토큰을 전부 본 뒤에야 다음 토큰을 생성합니다. 8,000토큰짜리 코드를 출력하려면 8,000번의 순차 연산이 필요하고, 이 순차성 때문에 아무리 좋은 GPU를 붙여도 초당 수십~수백 토큰이 물리적 상한입니다. 여기에 매 요청마다 40k 토큰짜리 스펙을 처음부터 다시 읽어들이는&lt;span style="color:#999999;"&gt;(prefill)&lt;/span&gt; 비용이 더해집니다. 즉 AI는 답이 이미 규칙으로 정해져 있는 코드조차 &lt;strong&gt;‘한 글자씩 타이핑’&lt;/strong&gt;해서 내놓아야 하며, 그 타이핑의 매 순간이 확률적 선택입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;API 코드젠이 가져다주는 세 가지 구조적 이점&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;코드젠의 또 다른 가치는 개발 경험이 구조적으로 달라지는 지점에 있습니다. 백엔드와 프론트엔드가 어긋날 틈을 컴파일 타임에 막는 &lt;strong&gt;런타임 안전성&lt;/strong&gt;, 관리할 코드 자체를 레포지토리에서 걷어내는 &lt;strong&gt;유지보수 부담의 소멸&lt;/strong&gt;, 그리고 스펙이 요동치는 프로젝트일수록 오히려 커지는 &lt;strong&gt;변화 대응력&lt;/strong&gt;입니다. 그리고 이는 어쩌면 전통적인 자동화가 AI에 비해 가지는 가치를 그대로 보여줄 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 시스템 동기화가 만드는 ‘런타임 안전성’&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3882/img-05.png" alt="백엔드 스펙 변경(userName→name)이 AI·수동 워크플로에서는 런타임 버그로 터지고, 코드젠 파이프라인에서는 CI/CD 컴파일 에러로 미리 걸러지는 체인 리액션 흐름도"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&lt;span style="color:#999999;"&gt;(NotebookLM으로 생성)&lt;/span&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;백엔드 응답 필드 이름이 userName에서 name으로 바뀌었는데 프론트엔드가 이를 모르면 사용자 화면에서 버그가 터집니다. 문제는 손으로 짠 타입이나 AI가 과거 스펙으로 만든 타입은 이를 잡아내지 못한다는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반면 코드 생성기를 사용하면 스펙이 바뀌는 즉시 타입이 자동 업데이트되며, 바뀐 필드를 쓰던 코드는 컴파일 에러(빨간 줄)로 즉시 드러납니다. 출력이 결정론적이기 때문에 GitHub Actions 같은 CI/CD 파이프라인에 주기적 스크립트를 걸어둘 수도 있습니다. 사람이 개입하지 않아도 변경 사항이 생기면 자동으로 PR이 올라옵니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 유지보수 대상에서 빠지는 코드&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;코드 생성기를 도입하면 API 통신을 위한 Fetch/Axios 함수 정의, Request/Response 타입 선언, Query Key 팩토리 설계, useQuery 커스텀 훅 정의가 모두 자동 생성 영역으로 넘어갑니다. 코드 자체는 여전히 프로젝트 어딘가에 생성되지만, 개발자가 직접 수정하거나 관여할 필요가 없어집니다. 그저 생성된 훅을 import해서 쓰기만 하면 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI가 만든 훅은 결국 레포지토리에 남아 ‘내가 유지보수하고 관리해야 할 코드’가 됩니다. 반면 코드 생성기의 산출물은 언제든 명령어로 다시 만들어낼 수 있는 ‘파생물’이므로 코드는 존재하되 개발자의 ‘유지보수 대상’에서는 제외됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 바쁠수록 빛나는 변화 대응력&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;일정이 빡빡하고 스펙이 매주 바뀌는 프로젝트일수록 자동화의 가치는 극대화됩니다. 스펙이 바뀔 때마다 타입과 API 클라이언트를 고치다 보면 어딘가 누락이 생길 수 있는데, 코드젠은 명령어 한 줄로 스펙과 코드를 항상 일치시켜 이 리스크 자체를 없애줍니다. 변경이 잦을수록 이 한 줄이 아껴주는 시간과 사고 비용은 커집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;multipart/form-data나 바이너리 업로드처럼 번거로운 요청도 스펙만 잘 정의되어 있다면 생성기가 알아서 코드를 짜줍니다. 단순하고 기계적인 배선 작업을 자동화가 가져가 주기 때문에, 개발자는 청크 분할이나 재시도 로직 같은 고차원적인 커스텀 비즈니스 로직에 집중할 여력이 생깁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실전 솔루션: Orval vs Hey API&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;방법론을 소개하는 김에 이를 실제로 구현해 줄 도구도 함께 소개하려고 합니다. 현재 웹 프론트엔드 생태계에서 백엔드의 OpenAPI 스펙을 TypeScript 코드로 변환해 주는 두 가지 도구를 비교해 보겠습니다. 하나는 완제품 훅을 통째로 뽑아주는 검증된 원조 Orval이고, 다른 하나는 유연한 옵션 객체로 최신 생태계의 방향을 이끄는 Hey API입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 올인원 훅 제너레이터의 원조, Orval&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;오랫동안 프론트엔드 개발자들의 사랑을 받아온 도구입니다. 스펙을 읽어 단순한 API 호출 함수뿐만 아니라 컴포넌트에서 바로 사용할 수 있는 완제품 형태의 훅 자체를 통째로 생성해 줍니다. 특히 MSW&lt;span style="color:#999999;"&gt;(Mock Service Worker)&lt;/span&gt;와 Faker.js 연동 기능이 내장되어 있어서, 백엔드 개발이 완전히 끝나지 않았어도 목&lt;span style="color:#999999;"&gt;(Mock)&lt;/span&gt; 데이터 통신 코드를 자동으로 만들어 즉시 프론트엔드 개발에 착수할 수 있도록 돕습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 가볍고 모던한 플러그인 기반, Hey API&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;최신 생태계의 패러다임 변화를 잘 보여주는 도구입니다. TanStack Query v5에 도입된 queryOptions() 아키텍처 이후, 프레임워크에 종속적인 훅을 통째로 만드는 것보다 유연한 옵션 객체를 생성하는 것이 대세가 되었습니다. Hey API는 처음부터 이 철학으로 설계되었습니다. Vercel의 CEO 기예르모 라우치&lt;span style="color:#999999;"&gt;(Guillermo Rauch)&lt;/span&gt;는 Hey API를 두고 &lt;strong&gt;“그냥 작동하는 OpenAPI 코드젠&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(OpenAPI codegen that just works)&lt;/span&gt;&lt;strong&gt;”&lt;/strong&gt;이라고 평하기도 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;무거운 커스텀 훅 대신 깔끔한 옵션 객체 형태로 코드를 뽑아주기 때문에, 하나의 생성물로 SSR Prefetch, 캐시 제어, 다양한 프레임워크&lt;span style="color:#999999;"&gt;(React, Vue, Svelte 등)&lt;/span&gt; 대응까지 유연하게 커버할 수 있습니다. Vercel, PayPal, AWS 등 글로벌 기업들이 프로덕션에 채택하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3882/img-06.png" alt="Orval과 Hey API 비교표: 출력 형태(완제품 커스텀 훅 vs queryOptions 객체), 목 생성(MSW·Faker 내장 vs 별도 플러그인), HTTP 클라이언트(Axios·Fetch vs Fetch·Axios·Ky·Next/Nuxt 전용), 추천 대상(강력한 모킹·완제품 훅 필요 시 vs 가볍고 최신 v5 아키텍처 선호 시)"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;개인적으로, 장기적인 아키텍처 관점에서는 생태계의 방향성과 일치하는 Hey API를 추천합니다. 다만 아직 빠르게 발전 중인 도구이므로 공식 문서에서도 정확한 버전 고정&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;(pin)&lt;/i&gt;&lt;/span&gt;&lt;i&gt;을 권장한다는 점은 알아두는 것이 좋습니다.&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3882/img-07.png" alt="npm trends 캡처, @hey-api/openapi-ts가 orval을 앞질러 최근 1년간 다운로드 수가 약 45만에서 350만 건까지 가파르게 증가"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;경계를 나누면 AI가 더 강력해진다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;결정론적인 일에서 AI를 제외해야 하는 이유는, AI를 정말 필요한 곳에 훨씬 더 안전하고 강력하게 투입하기 위해서입니다. 튼튼한 자동화 뼈대를 세우고, 그 위에 가변적인 AI를 얹는 식으로 역할을 분담하는 것입니다. 이렇게 역할을 나누면, 자동화와 AI가 하나의 파이프라인으로 연결되는 다음과 같은 자동화 시나리오가 가능해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;시나리오 A: 비즈니스 로직 자동 수정&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;백엔드 필드명이 바뀌면 코드 생성기가 돌면서 타입이 갱신되고, 바뀐 필드를 쓰던 곳에서 컴파일 에러가 발생합니다. 이때 &lt;strong&gt;CI 파이프라인의 AI 에이전트가 타입 에러 목록을 감지&lt;/strong&gt;해, 컴포넌트 내부의 데이터 매핑 코드까지 자동으로 수정(패치)합니다. 즉 스펙 변경 → 코드 재생성 → 비즈니스 로직 수정까지 사람 손을 거치지 않고 이어지는 것입니다. AI가 막연히 추측하는 것이 아니라 자동화 도구가 &lt;strong&gt;‘어디가 고장 났는지’를 결정론적으로 짚어줬기 때문에&lt;/strong&gt;, AI의 수정 성공률도 &lt;strong&gt;비약적으로 상승&lt;/strong&gt;합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;시나리오 B: UI 페이지 자동 생성&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;새로운 API 엔드포인트가 추가되면 코드 생성기가 타입과 API 연동 코드를 작성합니다. 여기서 멈추지 않고, CI 파이프라인에 “새 엔드포인트의 연동 코드가 생성되면 이 데이터 규격에 맞는 UI를 만들어달라”는 프롬프트를 미리 정의해두면, 코드 생성을 트리거로 CI 상에서 AI가 자동으로 실행되어 화면 초안까지 만들어냅니다. 개발자가 그때그때 프롬프트를 입력하는 것이 아니라, &lt;strong&gt;엔드포인트 추가 → 연동 코드 생성 → UI 초안 생성까지 사람의 개입 없이 하나의 파이프라인으로 이어지는 완전 자동화&lt;/strong&gt;입니다. 이때 AI에 주입되는 데이터의 형태&lt;span style="color:#999999;"&gt;(Schema)&lt;/span&gt;는 코드 생성기가 이미 100% 확정해둔 상태이므로, AI가 그려내는 UI가 실제 응답과 어긋날 확률도 줄어듭니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이처럼 자동화가 결정론적인 토대와 명확한 제약 조건(타입)을 깔아주면, AI는 그 제약 안에서 판단이 필요한 일만 수행합니다. AI의 최대 약점인 ‘비결정성(불확실성)’이 자동화의 ‘결정성(확실성)’으로 상쇄되는 시너지가 일어나는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 앤트로픽&lt;span style="color:#999999;"&gt;(Anthropic)&lt;/span&gt;도&amp;nbsp;에이전트 설계 가이드 ‘Building Effective Agents’에서 같은 원칙을 권장합니다. 가능한 일은 미리 정의된 코드 경로&lt;span style="color:#999999;"&gt;(predefined code paths)&lt;/span&gt;로 실행하고, 여기에 프로그래밍 방식의 검증을 결합하라는 것입니다. &lt;strong&gt;결정론적 토대 위에 AI를 얹는 이 역할 분담은, 에이전트 시대 전반이 수렴하고 있는 설계 원칙인 셈&lt;/strong&gt;입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며: 기계적인 자동화는 시스템에, 고차원 추론은 AI에&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이 글에서는 AI 워크플로우를 만들어나가는 여러 관점 중 하나로, 규칙 기반 자동화의 영역과 AI 본연의 역량이 필요한 영역을 구분 짓고 그 위에 워크플로우를 설계하는 접근을 제시해보았습니다. “얼마나 많은 일을 AI에 위임하느냐”보다, 그 경계를 명확히 이해하고 확정하는 것이 더 나은 출발점이 될 수 있다는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;정형화된 원천 데이터가 존재하고, 도출되어야 할 결과물이 이미 결정되어 있으며, 기계적인 검증이 가능한 작업이라면 규칙 기반&lt;span style="color:#999999;"&gt;(Rule-based)&lt;/span&gt;의 자동화 시스템에 맡기세요. 그리고 맥락을 읽고 판단해야 하는 고차원적인 일에 AI를 투입하세요. &lt;strong&gt;누구나 같은 모델을 빌려 쓸 수 있는 시대에, 엔지니어링의 진짜 경쟁력은 모델 자체가 아니라 이를 안전하게 감싸는 ‘결정론적 통제 계층’을 얼마나 촘촘히 구축하느냐에 달려 있습니다.&lt;/strong&gt;&amp;nbsp;이 경계가 분명할수록 파이프라인은 견고해지며, AI 역시 자신의 영역 안에서 더 효율적으로 일할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;습관적으로 AI 프롬프트 창에 복사-붙여넣기 하던 작업이 있나요? ‘결정론적 영역’에 속하는 업무는 없는지 한번 점검해보세요. 만약 있다면 전용 자동화 파이프라인 구축을 고려해볼 만합니다. 이 작은 경계의 구분이 여러분의 AI 워크플로우를 한층 더 효율적이고 강력하게 발전시켜 줄 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>개발자의 “할 수 있다”는 말은 어디까지일까요?</title><link>https://yozm.wishket.com/magazine/detail/3880</link><description>같은 “사용 가능”이라는 표현 안에도 서로 다른 경험이 들어 있습니다. 책을 읽고 예제를 따라 해본 사람도, 실제 서비스의 오류를 수정하고 운영해 본 사람도, 이력서에는 똑같이 'Java 가능'이라고 적을 수 있죠. 학교에서 웹 애플리케이션을 만든 경험, 혼자 서버를 구성한 자신감, 한국과 일본에서 다르게 받은 채용 질문까지 되짚으며, 필자는 지금도 Java를 '중'이라고 적는 이유를 설명합니다. '사용 가능'이나 '상·중·하' 뒤에 한 줄을 더 붙인다면, 그 수준을 선택하게 만든 구체적인 경험이어야 한다는 이야기입니다.</description><guid>https://yozm.wishket.com/magazine/detail/3880</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3880/img-01.png" alt="노트북 앞의 개발자, 말풍선에 '문법을 알아요' '실무에서 사용했어요' '개인 프로젝트 해봤어요' '서비스에 적용했어요'가 떠 있음"&gt;&lt;figcaption&gt;같은 “사용 가능”이라는 표현 안에도 서로 다른 경험이 들어 있습니다. &lt;i&gt;&amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이력서를 작성하다 보면 사용 기술 옆에 ‘상·중·하’를 표시하거나, ‘사용 가능’이라는 표현을 적을 때가 있습니다. 저 역시 그 칸 앞에서 여러 번 멈췄습니다. 저는 컴퓨터공학과에서 자바&lt;span style="color:#999999;"&gt;(Java)&lt;/span&gt;를 배웠습니다. 학교에서 웹 애플리케이션을 만들어봤고, 졸업 후 한국 회사에서도 Java를 사용했습니다. 일본 취업을 준비할 때도 Java 경력을 적었으며, 현재 업무에서도 계속 사용하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 누군가 “Java를 할 수 있나요?”라고 물으면 지금도 바로 답하기 어렵습니다. 학교에서 문법을 배웠다면 가능한 것일까요? 개인 프로젝트를 끝냈다면 충분할까요? 회사에서 일부 기능을 개발했다면 경력자라고 말할 수 있을까요? 같은 ‘사용 가능’이라는 표현 안에는 서로 다른 경험이 들어갑니다. 책을 읽고 예제를 따라 해본 사람도, 실제 서비스의 오류를 수정하고 운영해 본 사람도, 이력서에는 똑같이 ‘Java 가능’이라고 적을 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 글에서는 누가 초급이고 누가 고급인지 판정하려는 것이 아닙니다. 저 역시 제 수준을 하나의 등급으로 정확하게 설명하기 어렵거든요. 대신 학교와 한국·일본의 개발 현장에서 겪은 일을 돌아보며, 기술 수준을 어떤 근거로 설명해야 신뢰를 얻을 수 있을지 이야기해 보려고 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;학교에서 웹 애플리케이션을 만들면 Java를 할 수 있을까요?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;저는 컴퓨터공학과 재학 중 Java를 처음 배웠습니다. 변수와 조건문, 반복문을 익혔고 객체지향 개념도 공부했습니다. 수업에서는 웹 애플리케이션을 직접 만들어보기도 했습니다. 당시에는 프로그램이 정상적으로 실행되고 과제를 완성하면 해당 언어를 사용할 수 있다고 생각했습니다. 직접 코드를 작성해 결과물을 만들었으니, 졸업 이력서에 Java를 적는 것도 자연스럽게 느껴졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 졸업 당시의 저에게 실제 회사의 Java 업무를 맡겼다면 어땠을까요? 이미 운영 중인 코드를 읽고 수정하거나, 팀의 규칙에 맞춰 기능을 구현하거나, 오류가 발생했을 때 원인을 추적하는 일까지 바로 해낼 수 있었을지는 자신 있게 답하기 어렵습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;학교에서 웹 애플리케이션을 만들어본 경험은 분명한 출발점이었습니다. 다만 문법을 배웠다는 사실과 실제 업무를 수행할 수 있다는 것은 다른 문제였습니다. 혼자 결과물을 완성하는 것과 여러 개발자가 함께 관리하는 서비스를 만드는 일도 달랐습니다. 지금 돌아보면 당시의 저는 Java를 ‘배운 사람’에 가까웠습니다. 그런데 그때는 ‘배웠다’와 ‘할 수 있다’ 사이에 얼마나 많은 단계가 있는지 잘 보이지 않았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3880/img-02.png" alt="'문법 학습→개인 구현→실무 개발→운영 경험→설계·협업' 5단계로 나눈 기술 경험 단계 도식"&gt;&lt;figcaption&gt;기술 경험은 문법 학습부터 운영과 설계·협업까지 여러 단계로 나눌 수 있습니다. &lt;i&gt;&amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;버리는 컴퓨터로 서버를 만들며 생긴 자신감&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;한국에서 전산실 업무를 담당하던 시절, 전사적 자원관리&lt;span style="color:#999999;"&gt;(Enterprise Resource Planning, ERP)&lt;/span&gt; 시스템의 출하 정보를 확인할 수 있는 사내 웹페이지를 혼자 만든 적이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;별도의 프레임워크&lt;span style="color:#999999;"&gt;(Framework)&lt;/span&gt;는 사용하지 않았습니다. 화면은 HTML로 만들고, 웹 서버는 IIS&lt;span style="color:#999999;"&gt;(Internet Information Services, 인터넷 정보 서비스)&lt;/span&gt;를 사용했습니다. 동적 처리는 ASP&lt;span style="color:#999999;"&gt;(Active Server Pages, 액티브 서버 페이지)&lt;/span&gt;로 구현했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;서버 장비를 새로 구매한 것도 아니었습니다. 회사에서 사용하지 않던 컴퓨터를 가져와 사내 서버로 구성했습니다. 외부 클라우드가 아니라 회사 내부에서 직접 운영하는 온프레미스&lt;span style="color:#999999;"&gt;(On-premises)&lt;/span&gt; 방식이었습니다. 화려한 시스템은 아니었지만, 현장에서 필요한 출하 정보를 웹으로 확인할 수 있게 됐습니다. 요구를 듣고, 화면을 만들고, 서버를 구성해 실제 사용 가능한 결과물까지 혼자 완성했습니다. 이 경험은 저에게 꽤 큰 자신감을 줬죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;프레임워크도 쓰지 않고 필요한 기능을 만들었으니 당시에는 “개발이 생각보다 별것 아닐 수도 있겠다”는 생각도 했습니다. 하지만 혼자 개발하는 환경에는 당시 제가 알아차리지 못한 편리함이 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;설계 방식과 코드 작성 규칙을 제가 정했고, 문제가 생기면 제 판단대로 고칠 수 있었습니다. 다른 개발자가 제 코드를 읽어야 하는 상황도 많지 않았습니다. 코드 리뷰, 공동 작업 규칙, 버전 충돌처럼 협업에서 생기는 복잡성도 거의 경험하지 않았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 경험이 가치 없었다는 뜻은 아닙니다. 제한된 자원으로 실제 업무에 쓰이는 시스템을 완성한 일은 지금도 제 강점입니다. 다만 혼자 프로그램을 완성할 수 있다는 것과 팀 안에서 오래 관리할 수 있는 소프트웨어를 만드는 것은 서로 다른 능력이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;협업을 시작하자 ‘잘한다’의 기준이 달라졌습니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;실제 협업 환경에 들어간 뒤에는 개발을 바라보는 기준이 완전히 달라졌습니다. 혼자 만들 때는 코드가 정상적으로 동작하는지가 가장 중요했지만, 팀에서는 동작 여부만으로 끝나지 않았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;팀의 코드 규칙과 명명 규칙을 따라야 했고, 기존 프로젝트의 구조에 맞춰 기능을 추가해야 했습니다. 코드 리뷰에서는 실행 결과와 직접 관련이 없어 보이는 부분도 수정해야 했습니다. 여러 사람이 같은 저장소에서 작업하니 깃&lt;span style="color:#999999;"&gt;(Git)&lt;/span&gt; 충돌과 브랜치 관리도 피할 수 없었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;프레임워크와 라이브러리를 쓰는 일도 생각보다 단순하지 않았습니다. 사용법을 따라 하는 것만으로는 부족했습니다. 왜 이런 구조를 사용하는지, 기존 코드가 어떤 규칙으로 연결돼 있는지, 버전이 바뀌면 어느 부분에 영향이 생기는지를 이해해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;도메인 지식도 큰 벽이었습니다. 급여, 결제, 예약처럼 업무 규칙이 복잡한 프로젝트에서는 문법을 알아도 업무 흐름을 이해하지 못하면 올바른 기능을 만들 수 없었습니다. 기술적으로 실행되는 코드가 실제 업무 규칙과 맞지 않아 다시 수정되는 일도 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;혼자 개발할 때는 제가 이해할 수 있는 코드면 충분했습니다. 협업에서는 다른 개발자가 읽고 수정할 수 있어야 했습니다. 일정과 품질을 지켜야 했고, 테스트와 문서도 남겨야 했습니다. 담당자가 바뀌어도 이어서 개발할 수 있는 상태를 만들어야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개발을 잘 몰랐을 때 오히려 제 실력을 높게 평가했습니다. 더 많은 도구와 규칙을 접하고 나서야 제가 모르는 범위가 얼마나 넓은지 알게 됐습니다. 자신감이 줄었다기보다, 개발이라는 일의 실제 크기를 조금 더 정확하게 보기 시작한 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3880/img-03.png" alt="'혼자 개발할 때'는 '동작하면 끝', '협업을 시작한 뒤'는 코드 규칙·도구·라이브러리·도메인 지식·문서화·운영 품질을 나열한 비교 도식"&gt;&lt;figcaption&gt;혼자 개발할 때와 협업할 때는 완성의 기준부터 달라집니다. &lt;i&gt;&amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;‘대형 프로젝트 참여’의 대형은 무엇일까요?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이력서에서 자주 보이는 표현 가운데 하나가 ‘대형 프로젝트 참여’입니다. 저 역시 약 3,000명의 사용자가 이용하는 공공기관 시스템 프로젝트에 참여한 경험이 있습니다. 그렇다면 사용자 3,000명이면 대형 시스템일까요? 대기업이나 공공기관이 발주하면 대형일까요? 참여 인원이 많아야 할까요? 데이터가 많아야 할까요? 개발 기간이나 예산이 크면 대형이라고 부를 수 있을까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저는 이 기준도 ‘Java 사용 가능’이라는 표현만큼 애매하다고 느꼈습니다. 사용자가 적어도 다루는 데이터가 민감할 수 있고, 사용자 수가 많아도 기능은 비교적 단순할 수 있습니다. 팀 규모가 커도 한 개발자가 맡는 범위는 작은 기능 하나일 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;프로젝트 전체의 크기와 개인이 경험한 범위도 구분해야 합니다. 대부분의 개발자는 큰 시스템에 참여하더라도 전체를 혼자 설계하거나 구현하지 않습니다. 각자 일부 화면이나 기능, 업무 영역 또는 개발 공정을 맡습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;따라서 “대형 프로젝트에 참여했습니다”라는 문장만으로는 개인의 역량을 알기 어렵습니다. 약 3,000명이 사용하는 공공기관 시스템이라는 배경은 프로젝트를 설명해주지만, 제 실력을 보여주려면 그 안에서 무엇을 맡았는지를 더 말해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;프로젝트 기간은 얼마였는지, 어떤 기능을 담당했는지, 기본설계부터 참여했는지, 구현과 테스트 중 어디까지 책임졌는지, 운영 이후의 수정에도 참여했는지를 함께 적어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대로 프로젝트 자체는 작더라도 요구사항 정리부터 설계, 구현, 배포와 운영까지 맡았다면 개인에게는 더 넓은 경험이 될 수 있습니다. 프로젝트 이름보다 내가 책임졌던 범위를 설명하는 편이 더 정직하고 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3880/img-04.png" alt="12개 기능 모듈 중 '정산'과 '배치'만 표시해 담당 범위를 나타내고, 옆에 경험 확인 질문 5가지를 나열한 도식"&gt;&lt;figcaption&gt;프로젝트 전체의 규모와 개인이 실제로 담당한 범위는 구분해서 설명해야 합니다. &lt;i&gt;&amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;같은 경력도 한국과 일본에서 질문받는 방식이 달랐습니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;한국과 일본에서 취업을 준비하며 채용 과정의 초점이 다르다고 느낀 적도 있습니다. 다만 회사와 직무, 면접관에 따라 차이가 크기 때문에 아래 내용은 제가 직접 지원하고 면접을 본 범위에 한정된 경험입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 경험한 한국 채용에서는 학력, 전공, 자격증, 이전 회사와 경력이 비교적 자주 언급됐습니다. 어느 회사에서 어떤 업무를 했는지, 어떤 도메인을 경험했는지가 지원자의 배경을 판단하는 기준처럼 느껴졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반면 일본 면접에서는 실무에 바로 참여할 수 있는지를 확인하려는 기술 질문을 더 자주 받았습니다. 어떤 기술을 사용했는지뿐 아니라, 그 기술로 어떤 기능을 직접 구현했는지, 문제가 생겼을 때 어떻게 대응했는지, 프로젝트의 어느 단계에 참여했는지를 구체적으로 설명해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;같은 Java 경력이라도 단순히 사용 기간만 말하는 것으로 끝나지 않았습니다. 새 기능을 개발해 봤는지, 기존 코드를 수정해 봤는지, 오류를 분석해 봤는지, 팀의 규칙에 맞춰 협업해 봤는지에 따라, 답변의 내용이 달라졌습니다. 두 나라에서 질문받는 방식은 달랐지만, 공통점도 있었습니다. 결국 상대가 알고 싶은 것은 기술 이름 자체가 아니라, “실제로 무엇을 해봤고, 지금 어떤 일을 맡길 수 있는가”였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;자기 객관화가 부족하면 답변이 양극단으로 흐르기 쉽습니다. 분명히 해본 일도 “잘 모릅니다”라고 줄여 말하거나, 한두 번 써본 기술을 능숙하다고 표현할 수 있습니다. 가장 설득력 있었던 답변은 경험의 범위를 있는 그대로 설명하는 답변이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3880/img-05.png" alt="한국 면접 질문은 학력·전공·자격증·경력·업무 도메인, 일본은 사용 기술·담당 기능·문제 해결·즉시 활용 중심임을 비교한 도식"&gt;&lt;figcaption&gt;채용 환경은 달라도 실제로 해본 일을 구체적으로 설명해야 한다는 점은 같았습니다. &lt;i&gt;&amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;저는 지금도 Java를 ‘중’이라고 적습니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;학교에서 Java를 배운 뒤 한국과 일본의 업무에서도 계속 사용했지만, 기술 수준을 표시해야 한다면 저는 지금도 Java를 ‘중’이라고 적는 편입니다. Java로 기능을 개발하고 수정했으며, 오류 대응과 협업도 경험했습니다. 그렇다고 언어의 내부 구조나 성능 최적화, 복잡한 시스템의 전체 설계까지 자유롭게 담당할 수 있다고 말하기는 어렵습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;현재 제가 개인적으로 생각하는 ‘사용 가능’의 기준은 일정 기간 실제 업무에서 사용해 본 경험입니다. 대략 1년 정도 기능 개발과 수정, 오류 대응, 협업을 경험해야 비로소 업무에서 사용할 수 있다고 말할 수 있지 않을까 생각합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 이 기준도 절대적이지 않습니다. 같은 1년이라도 단순한 수정 업무를 반복한 사람과 요구사항 분석부터 설계, 구현, 운영까지 경험한 사람의 깊이는 다릅니다. 프로젝트 환경과 담당 범위에 따라 경험의 밀도가 달라집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개인 프로젝트 역시 하나의 기준만으로 평가하기 어렵습니다. 강의를 따라 간단한 예제를 만든 경험과 실제 사용자를 고려해 여러 기능을 설계하고, 배포한 경험은 다릅니다. 그래서 ‘상·중·하’나 ‘사용 가능’이라는 표시를 없애야 한다고 생각하지는 않습니다. 빠르게 기술 수준을 전달하는 표시는 필요합니다. 다만 그 뒤에는 판단의 근거가 따라야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3880/img-06.png" alt="'Java 중'이라는 기술 수준 표시 옆에 학습·개인 구현·실무·서비스·운영·설계협업 여부를 묻는 질문 6가지를 나열한 도식"&gt;&lt;figcaption&gt;‘상·중·하’라는 등급보다 그 판단을 뒷받침하는 경험이 중요합니다. &lt;i&gt;&amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&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;li&gt;기본설계나 상세설계에 참여했는가&lt;/li&gt;&lt;li&gt;팀의 코드 규칙과 리뷰 과정에 맞춰 협업했는가&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;기술 이름 대신 경험을 적어 보면 달라집니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이력서에서 기술 이름을 완전히 빼기는 어렵습니다. 채용 담당자가 지원자의 경험을 빠르게 파악하려면 기술 목록과 등급도 필요합니다. 문제는 그 한 단어만으로 실력을 모두 설명하려 할 때 생깁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어, “Java 중”이라고만 적는 대신 “Java 기반 업무 시스템에서 기능 개발과 수정, 오류 대응을 경험했으며, 팀의 코드 규칙에 맞춰 협업했습니다”라고 쓰면 판단 근거가 생깁니다. 공개할 수 있다면, 사용 기간과 담당 기능도 함께 적는 편이 좋습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 과거에 만든 출하 정보 웹페이지도 단순히 ‘ASP 사용 가능’이라고만 적으면, 경험의 특징이 잘 드러나지 않습니다. ERP 출하 정보를 확인하는 사내 웹페이지를 혼자 만들었고, HTML과 IIS, ASP를 사용했으며, 사용하지 않던 컴퓨터를 온프레미스 서버로 구성했다고 설명해야 실제로 한 일이 보입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;공공기관 시스템 프로젝트도 ‘대형 프로젝트 참여’라고만 적으면 제가 한 일이 보이지 않습니다. 약 3,000명의 사용자가 이용하는 시스템이라는 배경과 함께, 프로젝트 기간과 담당 기능, 참여한 개발 단계와 책임 범위를 설명해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;성과를 수치로 적을 때도 같은 원칙이 필요합니다. 응답 속도를 개선했거나 오류 건수를 줄인 결과가 실제 측정값이라면 좋은 근거가 됩니다. 확인할 수 없는 숫자를 억지로 만들기보다, 변경 전의 문제와 자신이 한 행동, 변경 후 달라진 점을 구체적으로 적는 편이 낫습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;자기 객관화는 경험을 축소해서 말하는 일이 아닙니다. 자신이 한 일을 상대방이 오해하지 않도록 구체적인 언어로 바꾸는 과정입니다. 작은 프로젝트라도 해결한 문제가 분명하면 강점이 되고, 큰 프로젝트라도 담당 범위를 설명하지 못하면 프로젝트 이름만 남습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며: ‘할 수 있다’ 뒤에 경험을 붙여봅시다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;지금도 저는 “Java를 할 수 있나요?”라는 질문에 단순히 “네”라고 답하기 어렵습니다. 학교에서 배웠고, 웹 애플리케이션을 만들었으며, 한국과 일본의 업무에서도 계속 사용했습니다. 기능 개발과 수정, 오류 대응과 협업도 경험했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 아직 경험하지 못한 영역도 많습니다. 그래서 저는 Java 수준을 표시해야 한다면 ‘중’이라고 적습니다. 이 선택이 모든 개발자에게 맞는 기준이라고 생각하지는 않습니다. 같은 기술을 사용했어도, 프로젝트와 담당 업무에 따라 경험의 깊이가 다르기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;대신 기술 옆에 적은 등급을 설명할 수 있어야 한다고 생각합니다. 얼마나 사용했는지, 무엇을 만들었는지, 실제 서비스에 적용했는지, 어떤 문제를 해결했는지, 어느 단계까지 책임졌는지를 함께 말할 수 있어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;자기 객관화는 자신을 낮추는 일이 아닙니다. “이 부분은 직접 해봤습니다. 여기까지는 책임질 수 있습니다. 이 영역은 더 경험해야 합니다”라고 구분해 말할 수 있는 상태에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다음에 이력서에서 ‘사용 가능’이나 ‘상·중·하’를 선택하게 된다면, 그 뒤에 한 줄을 더 붙여보면 어떨까요? 그 수준을 선택하게 만든 구체적인 경험입니다. 막연했던 기술 목록이 개발자로서 걸어온 과정으로 바뀌고, 그 과정이 화려한 표현보다 오래 신뢰를 남길 수 있을 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;이 글은 AI의 도움을 받아 작성했습니다. 필자가 직접 작성한 초안을 바탕으로 AI를 활용해 구조와 문장을 보정했으며, 모든 경험과 판단은 필자가 직접 검수했습니다.&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>미토스 쇼크 이후, 보안은 어떻게 바뀌어야 할까?</title><link>https://yozm.wishket.com/magazine/detail/3877</link><description>앤트로픽의 미토스(Mythos)가 실제 소프트웨어 취약점을 발견하고 공격 가능성까지 분석해내면서 보안 업계에 적지 않은 충격을 주고 있습니다. 하지만 미토스 쇼크의 본질은 AI가 똑똑해졌다는 사실이 아니라, 공격자의 속도는 빨라지는데 방어자의 운영 체계는 그대로라는 데 있습니다. 이제 AI 시대의 보안 경쟁은 누가 더 많은 솔루션을 갖췄는지가 아니라, 누가 더 빠르게 탐지하고 판단하며 대응할 수 있는가로 결정될 겁니다.</description><guid>https://yozm.wishket.com/magazine/detail/3877</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;최근 몇 달 동안 보안 업계에서 가장 많이 언급되는 키워드를 하나 꼽으라면, 단연 앤트로픽의 미토스&lt;span style="color:#999999;"&gt;(Mythos)&lt;/span&gt;일 것입니다. 보안 콘퍼런스와 기술 커뮤니티, 주요 언론 기사까지 모두 미토스 이야기를 다루고 있을 정도죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지금까지 생성형 AI가 문서 작성이나 코드 생성, 고객 응대 자동화와 같은 생산성 혁신의 도구로 주목받았다면, 미토스는 한 단계 더 나아가, 실제 소프트웨어 취약점을 발견하고 공격 가능성을 분석할 수 있는 수준의 능력을 보여주며, 보안 업계에 적지 않은 충격을 주고 있습니다. 이번 글에서는 미토스 쇼크 이후, 보안에서 무엇이 중요할지 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;같은 모델, 다른 이름: 미토스 5와 페이블 5&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;미토스는 앤트로픽이 만든 최상위 AI 모델 등급으로, 기존 최고 모델이던 Opus보다 한 단계 위에 새로 만들어진 티어입니다. 다만 등장 과정이 일반적인 AI 모델 출시와는 달랐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;첫 모델인 클로드 미토스 프리뷰&lt;span style="color:#999999;"&gt;(Claude Mythos Preview)&lt;/span&gt;는 2026년 4월에 나왔는데, 처음부터 일반 공개가 아니었습니다. 미국 정부와 협력하는 사이버 보안 프로그램인 프로젝트 글래스윙을 통해 초기 50여 개 조직에 제한적으로 배포됐고, 6월에는 150여 개 조직으로 확대됐습니다. 이 프리뷰 버전이 완전히 패치된 소프트웨어에서도 보안 취약점을 대량으로 찾아내면서 이른바 ‘미토스 쇼크’가 시작됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이후 2026년 6월, 프리뷰의 업그레이드 버전인 클로드 미토스 5&lt;span style="color:#999999;"&gt;(Claude Mythos 5)&lt;/span&gt;와 클로드 페이블 5&lt;span style="color:#999999;"&gt;(Claude Fable 5)&lt;/span&gt;가 정식 출시됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="/media/news/3877/img-01.png"&gt;&lt;figcaption&gt;&amp;lt;출처: &lt;a href="https://platform.claude.com/docs/ko/about-claude/models/overview"&gt;앤트로픽&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;두 모델은 동일한 모델이며, 차이는 안전장치에 있습니다. 페이블 5는 누구나 쓸 수 있는 일반 공개판으로, 사이버 보안이나 생물학 등 민감한 영역의 질문은 차단하거나 이전 모델&lt;span style="color:#999999;"&gt;(Opus 4.8)&lt;/span&gt;로 우회시킵니다. 미토스 5는 이 제한을 일부 해제한 버전으로, 여전히 검증된 파트너에게만 제공됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;현장에서 들은 불편한 질문&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;얼마 전 참석했던 한 AI 보안 관련 공청회에서도 미토스는 가장 뜨거운 화두였습니다. 그런데 정작 인상 깊었던 것은 발표 자체가 아니라 행사장 밖에서 현업 보안 담당자들과 나눈 대화였습니다. 한 보안 팀장은 발표를 들은 뒤 “기술은 놀랍지만 한편으로는 불편한 마음도 든다”라고 말했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;보안 담당자 입장에서 분명 중요한 기술 변화이고 대비가 필요하다는 데는 동의하지만, 미토스가 새로운 보안 위협의 상징처럼 소비되면서 결과적으로 보안 업체들의 마케팅 도구가 되고 있는 것 같다는 이야기였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그는 이런 질문도 함께 던졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;“만약 미토스가 보안의 미래라면 왜 일부 대기업과 정부 기관만 접근할 수 있는 걸까요?&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;모두가 앞으로 AI 기반 공격에 노출될 수 있다면 차라리 공개해서 모두가 준비할 수 있게 하는 것이 맞지 않을까요?&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;공개가 어렵다면 정부는 미토스를 사용할 수 없는 기업을 위해 과연 무엇을 해줄 수 있을까요?”&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;상당히 현실적인 질문입니다. 앞서 정리했듯 미토스는 누구나 사용할 수 있는 공개 모델이 아닙니다. 우리 정부는 최근 프로젝트 글래스윙에 참여하며 미토스 접근권을 확보했고, 삼성전자와 SK하이닉스, SK텔레콤 등 일부 기업도 관련 프로그램에 참여하고 있습니다. 하지만 대부분의 국내 기업, 특히 중소기업과 스타트업 입장에서는 여전히 먼 이야기입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;미토스 쇼크의 본질은 AI가 아니라 ‘시간’이다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;많은 언론은 미토스가 취약점을 발견했다는 사실 자체에 집중합니다. 물론 인상적인 기술적 성과입니다. 하지만 실제 기업 보안팀 입장에서 더 중요한 것은 취약점 탐지 능력 자체가 아니라 그로 인해 발생하는 속도의 변화입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;과거에도 뛰어난 보안 연구자들은 새로운 취약점을 발견할 수 있었습니다. 다만 그 과정에는 상당한 시간이 필요했습니다. 공개된 코드를 분석하고, 실행 흐름을 추적하며, 취약점 발생 조건을 재현하고, 실제 공격 가능성을 검증하는 데 수주에서 수개월이 걸리는 경우도 흔했습니다. 그 덕분에 방어자 역시 일정 수준의 대응 시간을 확보할 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 AI는 이 균형을 빠르게 무너뜨리고 있습니다. 미토스와 GPT-5.5-Cyber가 보여준 가장 중요한 변화는 분석과 재현 과정이 극적으로 짧아졌다는 것입니다. 공개된 CVE 정보와 패치 내역만으로도 AI는 취약점의 동작 원리를 추론할 수 있고, 경우에 따라서는 취약점 악용 코드까지 생성할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="/media/news/3877/img-02.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 진짜 문제는 공격자의 속도보다 방어자의 속도에 있습니다. 공격자는 AI를 활용해 몇 시간 안에 취약점을 분석할 수 있지만, 대부분의 기업은 여전히 취약점 분석, 영향도 검토, 보고, 승인, 변경 관리, 운영 일정 조정이라는 절차를 거칩니다. 안정적인 운영을 위해 반드시 필요한 과정이지만, AI가 등장한 이후 공격과 방어의 속도 차이가 급격히 벌어지고 있다는 점이 문제입니다. 결국 미토스 쇼크의 본질은 AI가 똑똑해졌다는 사실이 아니라, 공격자의 속도는 빨라지는데 방어자의 운영 체계는 그대로라는 데 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;기존의 보안 패치 SLA는 이제 유효하지 않다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;많은 언론은 글래스윙을 미토스에 대한 대응 프로젝트 정도로 설명합니다. 하지만 실제로는 그보다 훨씬 큰 의미를 가지고 있습니다. 이것의 핵심은 AI를 활용해 공격자보다 먼저 취약점을 발견하는 건데요. OpenAI 역시 같은 방향으로 움직이고 있습니다. 그들의 데이브레이크&lt;span style="color:#999999;"&gt;(Daybreak)&lt;/span&gt; 플랫폼의 핵심은 취약점 분석부터 코드 리뷰, 수정안 생성, 패치 검증까지, 보안 운영 프로세스를 AI 중심으로 자동화하는 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;흥미로운 점은 두 프로젝트가 모두 같은 문제를 해결하려 한다는 것입니다. 바로 사람보다 빠르게 움직이는 공격자에 대응하기 위해 사람보다 빠르게 움직이는 방어 체계를 만드는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;즉, 이 프로젝트들은 단순한 AI 보안 제품이 아니라 미래의 보안 운영 체제를 보여주는 초기 사례에 가깝습니다.&amp;nbsp;많은 기업은 취약점 대응 정책을 가지고 있습니다. 일반적으로 심각도에 따라 수일 이내 패치를 적용하도록 내부 기준을 정해두고 있습니다. 문제는 이러한 기준이 대부분 인간이 분석하고 인간이 공격을 준비하던 시대에 만들어졌다는 점입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;과거에는 새로운 취약점이 공개되더라도, 실제 공격 코드가 등장하기까지 일정 시간이 존재했습니다. 기업은 그 사이에 영향도를 분석하고 테스트 환경에서 검증한 뒤 운영 환경에 적용할 수 있었습니다. 그러나 AI가 공개된 취약점을 빠르게 분석할 수 있는 환경에서는 상황이 달라질 수 있습니다. 앞으로는 단순히 CVSS&lt;span style="color:#999999;"&gt;(Common Vulnerability Scoring System)&lt;/span&gt; 점수만으로 패치 우선순위를 정하는 것이 아니라, AI가 얼마나 쉽게 해당 취약점을 분석하고 재현할 수 있는지까지 고려해야 할 가능성이 높습니다. 즉 취약점의 위험도를 평가하는 기준에 ‘AI 재현 가능성’이라는 새로운 요소가 추가될 수 있다는 의미입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;미토스가 던진 진짜 질문, AI 주권&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;최근 미토스를 둘러싼 또 다른 논쟁은 기술 자체보다 접근 권한에 관한 문제입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="/media/news/3877/img-03.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;미토스 5와 페이블 5가 정식 출시된 지 사흘 만인 2026년 6월 12일, 미국 상무부는 국가 안보를 이유로 모든 외국인의 두 모델 접근을 중단하라는 수출 통제 지침을 앤트로픽에 발령했습니다. 미국 밖은 물론 미국 내에서 일하는 외국 국적 직원까지 포함하는 조치였기 때문에, 앤트로픽은 지침을 준수하기 위해 전 세계 모든 고객을 대상으로 두 모델의 서비스를 전면 중단해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앤트로픽은 지침을 따르면서도 좁은 범위의 잠재적 탈옥&lt;span style="color:#999999;"&gt;(jailbreak)&lt;/span&gt; 발견이 이미 상용 배포된 모델을 회수할 사유는 아니라고 공개적으로 반박했습니다. 이후 정부 검토와 협의를 거쳐 6월 26일 일부 신뢰 파트너의 미토스 5 접근이 승인됐고, 6월 30일 상무부가 통제를 완전히 해제하면서 7월 1일부터 서비스가 재개됐습니다. 해제 조건에는 앤트로픽이 모델 관련 보안 위험을 선제적으로 탐지하고 향후 모델 기준에 대해 정부와 협력한다는 내용이 포함된 것으로 알려졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 사례는 최첨단 AI 모델이 단순한 상용 소프트웨어를 넘어 국가 안보와 직결되는 전략 기술로 인식되고 있음을 보여줍니다. 반도체, 원자력, 우주 기술에 이어 AI 역시 국가 차원의 수출 통제와 정책적 관리 대상이 되는 시대가 본격적으로 시작된 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그러나 동시에 현실적인 질문도 남습니다. 미래의 보안 경쟁력이 특정 국가와 특정 기업이 보유한 AI 모델 접근 여부에 의해 결정된다면, 중소기업과 스타트업은 어떤 방식으로 보호받을 수 있을까요? 그리고 국가 차원에서는 특정 해외 AI 모델에 의존하는 것이 장기적으로 바람직한 방향일까요? 결국 미토스가 우리에게 던지는 질문은 기술의 우수성보다 AI 주권&lt;span style="color:#999999;"&gt;(AI Sovereignty)&lt;/span&gt;에 대한 질문에 더 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="/media/news/3877/img-04.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;AI 시대의 보안팀은 무엇을 해야 할까?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;많은 사람들이 AI가 보안 전문가를 대체할 것이라고 이야기합니다. 하지만 실제로는 역할이 달라질 가능성이 더 높습니다. 현재 보안팀은 로그 분석, 취약점 분류, 코드 리뷰, 경보 검토와 같은 반복 업무에 상당한 시간을 사용하고 있습니다. 이러한 영역은 AI가 가장 큰 효과를 발휘할 수 있는 분야입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반면 실제 비즈니스 영향도 판단이나 서비스 중단 위험 평가, 예외 정책 승인과 같은 업무는 여전히 사람이 수행해야 합니다. 따라서 앞으로의 보안 조직은 AI와 경쟁하는 조직이 아니라, AI와 협업하는 조직으로 변화할 가능성이 높습니다. SOC 분석가는 AI가 수집하고 정리한 결과를 검토하는 역할로 변화할 수 있으며, 보안 아키텍트는 AI가 제안한 대응 방안의 우선순위를 결정하는 역할을 수행하게 될 것입니다. 결국 보안팀은 운영 조직을 넘어 AI 기반 의사결정을 수행하는 조직으로 진화하게 될 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI 시대에는 취약점 공개에 대한 관점 역시 달라질 수 있습니다. 지금까지 많은 기업은 취약점이 발견되더라도 이를 외부에 적극적으로 공개하거나 제보받는 체계를 운영하지 않았습니다. 하지만 AI가 취약점을 빠르게 분석할 수 있는 환경에서는 오히려 기업 스스로 취약점을 먼저 발견할 수 있는 체계를 갖추는 것이 중요해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 기업이 다시 주목하는 것이 버그 바운티와 취약점 공개 프로그램, 그리고 PSIRT&lt;span style="color:#999999;"&gt;(Product Security Incident Response Team)&lt;/span&gt;입니다. 많은 국내 기업은 아직도 보안 연락처가 없거나 취약점 제보 프로세스가 명확하지 않은 경우가 적지 않습니다. 하지만 AI 시대에는 공격자보다 먼저 취약점을 발견하는 것이 가장 중요한 경쟁력이 될 수 있습니다. 보안팀은 이제 취약점을 숨기는 조직이 아니라 더 빨리 발견하고 더 빨리 수정하는 조직이 되어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;이제 보안 경쟁은 기술보다 운영의 경쟁이다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;미토스는 분명 인상적인 기술입니다. 하지만 미토스가 던진 진짜 메시지는 AI가 얼마나 똑똑한가에 있지 않습니다. 오히려 “우리 조직은 AI가 발견한 취약점보다 빠르게 대응할 수 있는가”라는 질문에 더 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;독자분들이 이 글을 읽고 한 번쯤 점검해 보면 좋을 질문들을 남기며 글을 마치고자 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;첫째, 우리 조직은 인터넷에 노출된 모든 자산을 정확히 파악하고 있는가?&lt;/li&gt;&lt;li&gt;둘째, 취약점이 발견되었을 때 누가 최종 의사결정을 내리는지 명확한가?&lt;/li&gt;&lt;li&gt;셋째, 치명적인 취약점에 대한 패치 SLA는 실제로 운영되고 있는가?&lt;/li&gt;&lt;li&gt;넷째, 코드 리뷰와 취약점 분석 과정에 AI를 활용할 계획이 있는가?&lt;/li&gt;&lt;li&gt;다섯째, 침해 이후 확산을 제한하기 위한 제로 트러스트와 마이크로 세그먼테이션 전략이 준비되어 있는가?&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;만약 이 질문들에 쉽게 답하기 어렵다면, 미토스보다 먼저 점검해야 할 과제가 이미 조직 내부에 있을 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI 시대의 보안 경쟁은 더 이상 누가 더 많은 보안 솔루션을 갖고 있는지가 아니라, 누가 더 빠르게 탐지하고, 판단하며 대응할 수 있는가?라는 관점에서 결정될 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>우리 팀의 CLAUDE.md, AGENTS.md로 바꿔도 될까</title><link>https://yozm.wishket.com/magazine/detail/3874</link><description>CLAUDE.md는 AI 코딩 에이전트에 프로젝트 규칙을 알려주는 컨텍스트 파일로, 한국에서는 사실상 표준처럼 쓰입니다. 그런데 실제 글로벌 표준 형식은 CLAUDE.md가 아니라 AGENTS.md죠. 표준인 걸 알겠는데, 옮기면 느려지거나 비용이 더 들지는 않을까요? 그래서 Haiku부터 Fable 5까지 5개 모델로 총 210회 실측을 돌렸습니다. 결론부터 말하면, 어떤 모델에서도 성능이 떨어지거나 비용이 늘지 않았습니다. AGENTS.md가 표준이 된 흐름부터 측정 방법, 그리고 한 시간이면 끝나는 마이그레이션 5단계까지 순서대로 정리했습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3874</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;CLAUDE.md&lt;/strong&gt;는 AI 코딩 에이전트에 프로젝트 규칙을 알려주는 컨텍스트 파일로, 한국에서는 사실상 표준처럼 쓰입니다. 그런데 실제 글로벌 표준 형식은 CLAUDE.md가 아니라 &lt;strong&gt;AGENTS.md&lt;/strong&gt;입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;오늘은&amp;nbsp;AGENTS.md가 무엇인지, 지금 쓰는 CLAUDE.md와는 어떻게 다른지 간단히 정리하는 데서 시작하려고 합니다. 그런다 해도 불분명한 것도 있습니다. 표준인 걸 알겠는데, 옮기면 무슨 이득이 있고, 그 과정에서 느려지거나 비용이 더 들지는 않을지 우려가 생길 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 정말 차이가 생기는지는 직접 확인해 보고자 실측을 돌렸습니다. Anthropic의 Haiku부터 최상위 Fable 5까지 5개 모델, 총 210회입니다. 결론이 궁금한 분들을 위해 먼저 말씀드리면, 어떤 모델에서도 성능이 떨어지거나 비용이 늘지 않았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;순서대로 컨텍스트 파일을 표준 규격으로 쓸&amp;nbsp;때 어떤 이점이 있는지부터 짚고, 측정을 어떻게 했는지, 그리고 마이그레이션 과정에 필요한 것까지 순서대로 정리하겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;도구마다 하나씩 늘어나는 컨텍스트 파일&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI 코딩 에이전트를 팀에 도입해 보면 곧 한 가지를 깨닫게 됩니다. 에이전트는 프로젝트의 사정을 전혀 모르는 상태에서 작업을 시작한다는 점입니다. 빌드는 어떤 명령으로 하는지, 테스트는 어떻게 돌리는지, 절대 건드리면 안 되는 디렉토리는 어디인지 같은 정보를 알 수 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇다고 이런 내용을 매번 대화창에 붙여 넣을 수는 없으니, 저장소 루트에 파일 하나를 두고 에이전트가 시작할 때 자동으로 읽게 합니다. 이것이 &lt;strong&gt;컨텍스트 파일&lt;/strong&gt;입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;문제는 이 파일이 도구마다 다르다는 데 있습니다. 실제로 저장소를 열어 보면 다음과 같이 여러 파일이 흩어져 있는 경우가 많습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;$ ls -a.cursor/rules.github/copilot-instructions.mdCLAUDE.mdGEMINI.mdREADME.mdsrc&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Claude Code는 CLAUDE.md를, Cursor는 .cursor/rules를, Gemini CLI는 GEMINI.md를, GitHub Copilot은 .github/copilot-instructions.md를 읽습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이름도 위치도 제각각이지만, 정작 담긴 내용은 거의 같습니다. 그래서 도구가 하나 늘 때마다 같은 내용을 복제하게 되고, 한 파일을 수정한 다음&amp;nbsp;나머지를 고치는 것을 잊어버리기도 쉽습니다. 규칙이 파일마다 조금씩 어긋나기 시작하면, 결국 에이전트마다 다른 규칙을 따라 움직이게 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한국은 개발과 운영 현장 모두 Claude 사용률이 특히 높은 편이라, 컨텍스트 파일이라고 하면 자연스럽게 CLAUDE.md를 먼저 떠올립니다. 모두가 그렇게 쓰다 보니 당연하게 느껴지지만, 앞서 말했듯 이 파일의 표준 형식은 따로 정해져 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3874/img-01.png"&gt;&lt;figcaption&gt;&lt;i&gt;도구마다 따로 쓰던 컨텍스트 파일이 AGENTS.md 하나로 모이는 흐름 &amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;AGENTS.md:&amp;nbsp;표준으로 자리 잡는 컨텍스트 파일&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&lt;a href="https://agents.md/"&gt;AGENTS.md&lt;/a&gt;는 코딩 에이전트용 컨텍스트 파일의 개방형 표준입니다. “에이전트를 위한 README”라고 보면 정확합니다. 2025년 8월 OpenAI가 자사 코딩 에이전트 Codex의 컨텍스트 파일로 처음 내놓았고, Cursor, Jules, Amp, Factory 등이 각자의 포맷을 접고 이 형식을 따르면서 사실상의 표준이 됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그리고 같은 해 12월, OpenAI가 이 파일을 Linux Foundation 산하에 새로 설립된 AAIF&lt;span style="color:#999999;"&gt;(Agentic AI Foundation)&lt;/span&gt;에 기부하면서 특정 회사가 아닌 중립 재단이 관리하는 공식 표준이 됐습니다. &lt;span style="color:#999999;"&gt;(이때 Anthropic의 MCP와 Block의 goose도 함께 기부되어 AAIF의 창립 프로젝트 세 개가 나란히 출발했습니다.)&lt;/span&gt; 2026년 중반 기준으로 6만 개가 넘는 저장소가 이 파일을 갖고 있고, 30개가 넘는 도구가 AGENTS.md를 네이티브로 지원합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 같은 “지원”이라도 그 수준은 도구마다 다릅니다. 세 부류로 나뉩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3874/img-02.png"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이처럼 &lt;a href="http://agents.md"&gt;AGENTS.md&lt;/a&gt;를 표준으로 채택하는&amp;nbsp;흐름을 보여주는 최근 사례가 하나 있습니다. Google은&amp;nbsp;2026년 6월 Gemini CLI 지원을 종료하고 후속인 Antigravity CLI로 전환했는데, 새 도구는 GEMINI.md와 함께 AGENTS.md를 수정 없이 그대로 읽습니다. 벤더 전용 파일&lt;span style="color:#999999;"&gt;(GEMINI.md)&lt;/span&gt;은 도구가 사라지면 함께 수명을 다하지만, 표준 파일은 도구가 바뀌어도 그대로 남는다는 것을 보여준 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만,&amp;nbsp;&lt;strong&gt;정작 실무에서 가장 많이 쓰는 Claude Code만 아직 표준에 합류하지 않아, AGENTS.md를 바로 읽지 못합니다.&lt;/strong&gt;&amp;nbsp;이를 연결하는 방법은&amp;nbsp;두 가지 있습니다. CLAUDE.md 안에 &lt;code&gt;@AGENTS.md&lt;/code&gt;&amp;nbsp;한 줄을 적어 불러오게 하거나&lt;span style="color:#999999;"&gt;(import)&lt;/span&gt;, CLAUDE.md 자체를 AGENTS.md로 가는 심볼릭 링크로 바꾸는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;그런데, 옮겨도 괜찮을까?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;컨텍스트 파일은 에이전트 세션을 시작할 때마다 로드됩니다. 이렇게 한 단계를 거쳐 읽는 과정에서 비용이 조금이라도 붙는다면, 그 비용은 팀 전체가 세션을 돌릴 때마다 쌓입니다. 그러니 이런 우회 경로를 활용해 옮길 때 비용이 더 들지 않느냐는 의문이 생깁니다. 그 문제를 짚어 보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이런 우려를 다룬 연구나 테스트가 이미 있는지부터 찾아봤습니다&lt;span style="color:#999999;"&gt;(저만 같은 궁금증을 품진 않았을 테니까요)&lt;/span&gt;. Princeton의 &lt;a href="https://arxiv.org/abs/2601.20404"&gt;측정 연구&lt;/a&gt;가 있긴 한데, 여기서는 AGENTS.md를 네이티브로 읽는 Codex만 다뤘습니다. import나 심볼릭 링크처럼 한 번 거쳐서 읽는 경로를 직접 잰 데이터는 없었습니다. 원리상으로는 차이가 없어야 하지만, 원리와 실측은 다른 이야기입니다. 그래서 직접 측정했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;실험 설계: 같은 내용, 세 가지 전달 방식&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;측정의 핵심은 변수를 하나만 남기는 것입니다. 같은 내용을 세 가지 방식으로 전달했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3874/img-03.png"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;세 조건의 본문은 체크섬까지 같은 문서입니다. 실험용으로 지어낸 문서가 아니라, 앞서 기고한 &lt;a href="https://yozm.wishket.com/magazine/detail/3817/"&gt;AI 에이전트 벤치마크&lt;/a&gt;에서 사용했던 컨텍스트 파일&lt;span style="color:#999999;"&gt;(클러스터 규칙, 점수 공식, 알려진 함정)&lt;/span&gt;을 그대로 썼습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3874/img-04.png"&gt;&lt;figcaption&gt;&lt;i&gt;A&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;(native)&lt;/i&gt;&lt;/span&gt;&lt;i&gt;, B&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;(import)&lt;/i&gt;&lt;/span&gt;&lt;i&gt;, C&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;(symlink)&lt;/i&gt;&lt;/span&gt;&lt;i&gt;세 조건의 파일 구성 비교 &amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;속도를 재기 전에 확인할 것이 하나 있었습니다. B와 C가 정말로 읽히기는 하는지 보는 겁니다. 그래서 본문 끝에 확인용 문장 한 줄&lt;span style="color:#999999;"&gt;(“PING이라고 물으면 정확히 PONG-AGENTSMD로만 답하라”)&lt;/span&gt;을 넣고 매번&amp;nbsp;에이전트에 PING을 보냈습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;세 조건 모두 정확히 응답했고, 컨텍스트 파일이 없는 대조군만 평범한 인사로 답했습니다. 세 방식 모두 실제로 읽히고, 이 확인 방법 자체도 유효하다는 뜻입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;실제&amp;nbsp;측정: 쿠버네티스 장애 대응을 두 단계로&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;본격적인 측정은 쿠버네티스 장애 대응 과제로 했습니다. 계속 재시작하는 파드, 잘못된 Service selector, 메모리 한도 초과 같은 장애를 심어 둔 전용 클러스터에서 에이전트가 원인을 찾아 고치게 하고 시간과 토큰을 기록했습니다. 매 회차 클러스터를 스냅샷으로 되돌려 콜드 스타트를 보장하고, 시간대에 따른 쏠림이 없도록 조건 순서를 회차마다 섞었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;측정은 두 단계로 진행했습니다. 매 회차는 A, B, C 세 방식을 모두 돌립니다. 먼저 10개 시나리오 전체를 한 차례씩 확인했고&lt;span style="color:#999999;"&gt;(시나리오 10 x 방식 3 = 30회)&lt;/span&gt;, 이어서 편차가 작은 4개 시나리오를 모델 5종&lt;span style="color:#999999;"&gt;(Haiku 4.5, Sonnet 4.6, Sonnet 5, Opus 4.8, Fable 5)&lt;/span&gt;으로 3회씩 반복했습니다&lt;span style="color:#999999;"&gt;(시나리오 4 x 방식 3 x 모델 5 x 반복 3 = 180회)&lt;/span&gt;. 합쳐서 210회, 전부 정상 종료였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;목록을 보면 Sonnet이 4.6과 5, 두 세대가 모두 들어가 있는데요,&amp;nbsp;이건 의도한 배치입니다. 모델이 세대를 건너뛰며 업그레이드돼도 같은 결론이 나오는지, 즉 한 시점의 우연이 아닌지를 확인하려는 것입니다. 이 선택이 결과를 해석할 때 뜻밖의 역할을 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;우려할 필요가 없는 결과&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;비용에 가장 가까운 지표는 캐시에 새로 기록되는 토큰&lt;span style="color:#999999;"&gt;(cache write)&lt;/span&gt;입니다. 여기서 심볼릭 링크&lt;span style="color:#999999;"&gt;(C)&lt;/span&gt;의 역할이 하나 더 있습니다. C는 OS가 링크만 풀어 줄 뿐 native와 달라질 수 없는 구성이라, 실험에 내장된 대조군이 됩니다. 거쳐 읽는 방식이 로드되는 내용을 부풀렸다면 B가 이 대조군보다 커야 합니다. 다만, 그런 일은 없었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3874/img-05.png"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3874/img-06.png"&gt;&lt;figcaption&gt;&lt;i&gt;모델 5종에서 조건별 cache write 토큰 비교. Sonnet은 4.6과 5 두 세대를 함께 넣어 세대 변화에도 결론이 유지되는지 확인했다. 어느 모델에서도 import&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;(B)&lt;/i&gt;&lt;/span&gt;&lt;i&gt;가 대조군&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;(C)&lt;/i&gt;&lt;/span&gt;&lt;i&gt;보다 일관되게 높지 않다. &amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;어느 모델에서도 B가 대조군&lt;span style="color:#999999;"&gt;(C)&lt;/span&gt;보다 일관되게 높지 않았습니다. 4개 모델에서는 import가 3~4% 낮았는데, 여기까지만 봤다면 “import가 조금 이득”이라고 결론 냈을 겁니다. 그런데 새로운 Sonnet 5에서는 같은 import가 +6%로 방향이 뒤집혔고, 결정적으로 같은 회차에서 대조군도 똑같이 +6%였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앞서 Sonnet을 두 세대 넣은 이유가 여기에 있습니다. 한 세대만 봤다면 3~4%를 실제 이득으로 오해했을 텐데, 세대를 바꾸자 그 방향이 유지되지 않았습니다. 대조군과 함께 움직이는 편차는 전달 방식의 비용이 아니라, 에이전트가 매번 조금씩 다르게 풀어서 생기는 실행 편차입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실행 시간&lt;span style="color:#999999;"&gt;(wall time)&lt;/span&gt;은 차이가 커 보이는 회차도 있었지만 일관된 경향이 없었습니다. 어떤 모델에서는 B가 빠르고 어떤 모델에서는 느렸으며, 시간 차이가 가장 큰 경우에도 토큰 차이는 거의 없었습니다. 전달 방식에서 온 오버헤드라면 결과가 한쪽으로 치우쳐야 하는데 그렇지 않았습니다. 이 변동은 에이전트가 문제를 푸는 과정이 매번 조금씩 달라서 생긴 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;왜 이런 결과가 나오는지는 메커니즘을 보면 이해가 됩니다. 심볼릭 링크는 Claude Code가 CLAUDE.md라는 경로를 여는 순간 OS가 링크를 해석해 AGENTS.md의 내용을 돌려줍니다. Claude Code 입장에서는 native 파일을 읽을 때와 완전히 같고, 링크 처리는 파일시스템의 몫입니다. 그래서 C의 편차는 곧 측정 노이즈의 크기이고, import&lt;span style="color:#999999;"&gt;(B)&lt;/span&gt;는 그 노이즈 범위를 벗어난 적이 없습니다. 어느 쪽이든 전달 방식의 손해가 아니라는 점이 중요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실제로 AGENTS.md로 마이그레이션하는 법&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;측정으로 옮겨도 문제없다는 것을 확인했으니, 남은 것은 실제로 옮기는 절차입니다. 팀 기준으로 따져도&amp;nbsp;한 시간이 안 걸립니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1. 기존 파일의 이름을 AGENTS.md로 바꿉니다.&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;git mv CLAUDE.md AGENTS.md&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;새 파일을 만들어 내용을 복사하는 것이 아니라 이름을 바꾸는 것입니다. git 이력이 그대로 이어지고, agents.md 공식 안내도 “기존 파일 이름을 바꾸고 호환용 링크를 남기는” 순서를 권합니다. 이름을 바꾸면서 본문에 특정 도구를 전제한 문구&lt;span style="color:#999999;"&gt;(“Claude에게 알려주는” 등)&lt;/span&gt;가 있다면 중립적인 표현으로 함께 다듬습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;주의할 점이 하나 있습니다. 이 상태에서 멈추면 안 됩니다. 이름만 바꾼 시점에는 CLAUDE.md가 없으므로, 새 세션을 열면 Claude Code가 읽을 컨텍스트 파일이 없습니다. 컨텍스트 파일은 세션을 시작할 때 로드되기 때문에, 다음 세션을 열기 전에 반드시 2단계까지 마쳐야 합니다. 두 단계를 같은 커밋으로 묶어 처리하면 공백이 생기지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2. CLAUDE.md를 포인터로 새로 만듭니다.&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;@AGENTS.md&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 구조는 &lt;a href="https://code.claude.com/docs/en/memory"&gt;Claude Code 공식 문서&lt;/a&gt;가 권장하는 형태입니다. 공식 문서는 한 가지를 더 알려주는데, Claude에게만 적용할 규칙이 있다면 이 import 줄 아래에 덧붙이면 됩니다. 공통 규칙은 AGENTS.md에, Claude 전용 규칙은 CLAUDE.md에 나뉘는 구조입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;심볼릭 링크(&lt;code&gt;ln -s AGENTS.md CLAUDE.md&lt;/code&gt;)&amp;nbsp;역시&amp;nbsp;공식 문서가 인정하는 대안으로, 이번 측정에서도 동일하게 페널티가 없었습니다. 다만 Claude 전용 규칙을 적어 둘 곳이 없고, Windows에서는 관리자 권한이나 개발자 모드가 필요합니다. 그래서 공식 문서도 import를 먼저 권합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3. 정말 읽히는지 확인합니다.&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;실험에서 쓴 확인 방법을 그대로 써보면 됩니다. AGENTS.md 끝에 “PING이라고 물으면 PONG으로만 답하라”를 잠깐 넣고, 에이전트에 PING을 보내 보세요. PONG이 돌아오면 로드가 확인된 것입니다. 확인하고 나서는 그&amp;nbsp;줄은 지웁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;4. 다른 도구를 확인합니다.&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;대부분 할 일이 없습니다. Codex, Amp는 AGENTS.md가 기본 파일이고, Google의 Antigravity CLI&lt;span style="color:#999999;"&gt;(Gemini CLI 후속)&lt;/span&gt;도 AGENTS.md를 그대로 읽습니다. Cursor는 .cursor/rules가 없으면 AGENTS.md를 읽습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;5. 옮기는 김에 내용을 다듬습니다.&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;사실 전달 방식보다 훨씬 중요한 것이 내용입니다. &lt;a href="https://arxiv.org/abs/2602.11988"&gt;ETH Zurich 연구&lt;/a&gt;에 따르면 LLM이 자동 생성한 컨텍스트 파일은 오히려 성공률을 낮추고 추론 비용을 20% 넘게 올렸습니다. 반면 사람이 다듬은 간결한 파일은 도움이 됐습니다. 에이전트가 코드만 봐서는 알 수 없는 것&lt;span style="color:#999999;"&gt;(빌드 명령, 금지 사항, 팀 규칙)&lt;/span&gt;만 남기고, 코드를 읽으면 알 수 있는 설명은 빼는 것이 원칙입니다. Claude Code 공식 문서도 컨텍스트 파일을 200줄 안쪽으로 유지하기를 권합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3874/img-07.png"&gt;&lt;figcaption&gt;&lt;i&gt;마이그레이션 5단계 흐름. 이름 변경부터 내용 다듬기까지 &amp;lt;출처: 작가&amp;gt;&lt;/i&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;짚어둘 두 가지&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;첫째, 이번에 측정한 범위는 속도와 토큰 비용까지입니다. 답변의 정확성이나 안전&lt;span style="color:#999999;"&gt;(위험한 명령이 늘거나 줄었는지)&lt;/span&gt;은 별도 채점이 필요해서 이번 범위에 넣지 않았습니다. 원리상 세 조건 모두 모델에는 완전히 같은 내용이 전달되므로 정확성이 달라질 이유는 없지만, 측정하지 않은 이상 단정하지는 않겠습니다. 필요해지면 따로 진행하겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;둘째, 측정 환경은 Claude Code 2.1.198~2.1.199 기준입니다. Claude Code가 AGENTS.md를 네이티브로 지원하면 이런 연결 자체가 필요 없어집니다. 다만 이를 요청하는 &lt;a href="https://github.com/anthropics/claude-code/issues/6235"&gt;공식 저장소의 이슈&lt;/a&gt;가 2025년 8월에 처음 열렸는데, 수천 개의 공감이 달린 지금까지도 공식 응답이 없습니다. 오래 열려 있는 이슈가 대개 그렇듯 당분간은 이 구조가 유지된다고 보는 편이 현실적이고, 그때까지 import로 연결해 써도 손해가 없다는 것을 실측으로 확인해 둔 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며: 도구, 에이전트, 그리고 지시하는 방법&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;2025년에는 &lt;a href="https://yozm.wishket.com/magazine/detail/3559/"&gt;Gateway API 구현체 7개를 비교&lt;/a&gt;했고, 올해는 &lt;a href="https://yozm.wishket.com/magazine/detail/3817/"&gt;그 인프라를 다루는 AI 에이전트 9종을 비교&lt;/a&gt;했습니다. 그 벤치마크는 CLAUDE.md 기반으로 설계했는데, 다음 측정으로 넘어가기 전에 AGENTS.md로 옮겨도 되는지부터 확인한 것이 이번 글입니다. 답은 “&lt;strong&gt;된다&lt;/strong&gt;”였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;필요한 것들이 하나씩 앞단으로 옮겨 온 셈입니다. 어떤 도구를 고를 것인가에서, 그 도구를 다룰 에이전트를 고르는 문제로, 이제는 그 에이전트에 지시하는 방법을 표준화하는 문제로 왔습니다. 도구는 계속 바뀌고 에이전트도 계속 바뀌지만, 팀의 규칙을 한 곳에 적어 두고 어떤 에이전트든 같은 규칙을 읽게 하는 구조는 오래 남을 것입니다. AGENTS.md가 그 자리를 차지해 가고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 옮기는 일이 그냥 되는 것은 아닙니다. 팀 기준 한 시간 남짓의 작업이 들고, 옮긴 뒤에도 신경 쓸 일이 생깁니다. 모두가 CLAUDE.md를 쓰는 환경에서 AGENTS.md를 중심에 두고 import로 연결하는 구조가 낯설고 부담스러운 것도 사실입니다. 이번 측정이 보여준 것&amp;nbsp;역시&amp;nbsp;속도와 토큰에서 손해가 없다는 점이지, 아무 노력도 들지 않는다는 뜻은 아닙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래도 여러 에이전트를 함께 쓰는 팀이라면, 조직 방침이나 고객 요구로 특정 도구에 묶이지 않는 구성이 필요하다면 옮길 이유는 충분합니다. 지금은 Claude가 앞서 있지만, 경쟁이 치열해져 주력 도구는 언제든 바뀔 수 있습니다. 그 가능성까지 생각하면 규칙을 표준 파일 하나에 모아 두는 쪽이 결국 좋은 선택일 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#757575;"&gt;이번 AGENTS.md 측정 하네스와 재현 방법은&lt;/span&gt; &lt;a href="https://github.com/sysnet4admin/Research/tree/main/agents-md-migration"&gt;GitHub 저장소&lt;/a&gt;&lt;span style="color:#757575;"&gt;에, 측정 설계와 해석은&lt;/span&gt; &lt;a href="https://kuberneteslab.dev/ko/blog/agents-md-migration/"&gt;블로그&lt;/a&gt;&lt;span style="color:#757575;"&gt;에 정리해 두었습니다.&lt;/span&gt;&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="background-color:transparent;color:#999999;"&gt;끝으로 개인적인 소식을 하나 나누자면, 제가 이 AGENTS.md를 관리하는 &lt;strong&gt;AAIF의 앰배서더로 선정되었습니다&lt;/strong&gt;. CNCF 앰배서더로 활동해 온 데 이어 두 번째 앰배서더 자리라 무척 기쁜 소식입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="background-color:transparent;color:#999999;"&gt;AAIF는 에이전트 생태계의 개방형 표준을 중립적으로 관리하는 재단으로, MCP를 비롯해 goose, AGENTS.md, agentgateway까지 네 가지 프로젝트를 책임지고 있습니다. 지난 28일 발표된 MCP의 대형 업데이트도 조만간 자세히 소개해 보겠습니다. AAIF 앰버서더 전체 명단과 프로그램 소개는&lt;/span&gt;&lt;a href="aaif.io/ambassadors"&gt;&lt;span style="background-color:transparent;"&gt;aaif.io/ambassadors&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color:transparent;color:#999999;"&gt;에서 보실 수 있습니다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="background-color:transparent;color:#999999;"&gt;앞으로도 CNCF &amp;amp; AAIF 앰배서더로서, 어디에도 치우치지 않고 사용자에게 직접 도움이 되는 연구 활동을 공유하겠습니다.&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;작가&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;조훈 (CNCF&amp;amp;AAIF 앰버서더)&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;쿠버네티스 및 AI 네이티브 기술 전문가로, CNCF와 에이전틱 AI 재단&lt;span style="color:rgb(153,153,153);"&gt;(AAIF)&lt;/span&gt; 글로벌 앰버서더이자 Kubestronaut이다. 쿠버네티스랩을 운영하며 인프라 자동화 기술을 연구하고 공유한다. ‘IT 인프라 엔지니어 그룹’ 운영진이자 오픈소스 컨트리뷰터로 활동 중이며, 맞춤형 인프라 교육, 쿠버네티스 비용 최적화, 멀티 LLM 및 AI 에이전트 비교 검증 등 다양한 실무 PoC를 수행하고 있다. 최근 출간한 『AI 시대에 개발자가 알아야 할 인프라 구성 배포 with 클로드 코드』를 포함해 총 5권의 IT 서적을 집필했으며, 인프런 강의 및 요즘IT 기고 등 지식 공유 활동을 이어가고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;심근우&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;LG유플러스 CTO부문에서 대고객 비즈니스 시스템의 DevOps를 담당하는 UcubeDAX팀의 팀장으로 일하고 있다. 퍼블릭 클라우드와 프라이빗 클라우드에 걸친 쿠버네티스 클러스터를 안정적으로 운영하기 위해 노력하고 있으며, 특히 주니어 DevOps 엔지니어들의 육성에 큰 관심을 가지고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;문성주&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;체커(CHEQUER) 사의 DevOps Engineer로서 쿠버네티스의 멀티 클러스터 관리 방법론과 쿠버네티스 구현체(CAPI, OCI)에 대한 명세와 컨테이너 리소스 격리 방법에 대한 연구를 병행하고 있다. 이런 연구 활동을 기반으로 쿠버네티스 볼륨 테스트 파트에 컨트리뷰션했다. 본업은 쿠버네티스 오퍼레이터와 같은 CRD(커스텀 리소스)를 개발해 현업에서 쿠버네티스를 좀 더 편리하게 사용할 수 있도록 돕는 일이다. 또한, 페이스북 그룹 ‘코딩이랑 무관합니다만'과 ‘IT 인프라 엔지니어 그룹'의 운영진을 맡고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;이성민&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;미국 넷플릭스(Netflix) 사의 Data Platform Infrastructure 팀에서 사내 플랫폼 팀들과 데이터 사용자들을 어우르기 위한 가상화 및 도구들을 개발하는 일들을 하고 있다. 과거 컨테이너와 쿠버네티스에 큰 관심을 두고 ingress-nginx를 비롯한 오픈 소스에 참여했으며, 현재는 데이터 분야에 일하게 되면서 stateful 한 서비스들이 컨테이너화에서 겪는 어려움을 보다 근본적으로 해결하기 위한 많은 노력을 하고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;함께 보면 좋은 글&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://yozm.wishket.com/magazine/detail/3453/"&gt;AI는 주니어 개발자다: 클로드 코드와 함께한 6주 체험기&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://yozm.wishket.com/magazine/detail/3801/"&gt;클로드 코드를 떠나 오픈소스로 돌아간 이유&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://yozm.wishket.com/magazine/detail/3816/"&gt;제가 정말 루프 엔지니어링까지 알아야 할까요?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://yozm.wishket.com/magazine/detail/3620/"&gt;3개월간 AI에 2,348만 원 쓰고도 10배 더 늘리려는 이유&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>비개발자가 400페이지 서명 검사를 자동화하며 고민한 것</title><link>https://yozm.wishket.com/magazine/detail/3872</link><description>매달 마감이면 400페이지가 넘는 스캔 점검철을 한 장씩 넘기며, 표지마다 서명 두 칸이 채워졌는지 눈으로 대조했다. 처음엔 '요즘 AI가 좋다는데, PDF를 던져주고 서명 없는 칸 찾아줘 하면 끝나는 거 아닌가' 싶었지만, 결론부터 말하면 그렇게 하지 않았다. 글자 검색 불가, 프로그램 설치 불가, 외부 전송 불가라는 상자 안에서 코딩이 본업이 아닌 사업관리 담당자가 클로드 코드와 대화하며 도구를 만들었다. 완성품 자랑보다, 다섯 번 넘어진 이야기와 '어디까지 도구에 맡기고 어디부터 사람이 봐야 하는가'를 정하게 된 두 번의 방향 전환이 이 글의 진짜 내용이다.</description><guid>https://yozm.wishket.com/magazine/detail/3872</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;매달 마감이 되면 내 책상에는 두툼한 점검철 한 권이 올라온다. 어느 공공 사업의 월 유지관리 점검 기록을 묶은 것인데, 수백 페이지짜리 스캔본이다. 시스템마다 앞에 표지가 한 장씩 있고, 그 표지 맨 아래 오른쪽에 점검자와 확인자가 서명과 날인을 한다. 마감을 담당하는 내 일은 여기서 딱 하나다. 모든 표지에 두 사람의 서명이 빠짐없이 들어갔는지 확인하는 것이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;말로 쓰면 한 줄이지만, 실제로는 400페이지가 넘는 스캔본을 한 장씩 넘기며 표지를 골라내고, 서명란 두 칸을 눈으로 대조하는 일이다. 한장이라도 놓치면 마감이 틀어진다. 매달 30분에서 한 시간씩, 나는 이 단순 반복에 시간을 썼다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 자동화를 마음먹었을 때, 솔직히 처음 떠오른 건 이거였다. “요즘 AI가 좋다는데, PDF 파일을 던져주고 ‘서명 없는 칸 찾아줘’ 하면 끝나는 거 아닌가?” 결론부터 말하면, 그렇게 하지 않았다. 아니, 그렇게 할 수가 없었고, 몇 번 부딪히고 나서는 일부러 그렇게 하지 않기로 했다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 글은 도구를 만든 자랑이 아니다. 코딩이 본업이 아닌 사업관리 담당자가, 반복 업무 하나를 자동화하면서 “어디까지 도구에 맡기고 어디부터는 내가 봐야 하는가”를 정하게 된 기록이다. 완성품보다 그 사이에서 다섯 번 넘어진 이야기와, 두 번의 방향 전환이 이 글의 진짜 내용이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3872/img-01.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, 클로드로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;“그냥 AI한테 다 시키면 안 돼?”가 안 되는 이유&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;가장 먼저 막힌 건 파일 그 자체였다. 대상은 400페이지가 넘고 용량은 100메가바이트를 웃도는데, &lt;strong&gt;전체가 스캔 이미지&lt;/strong&gt;였다. 종이에 서명·날인을 하고 그걸 복합기로 통째로 스캔한 문서라, 안에 ‘글자 데이터’가 없다. 화면으로 보면 글씨가 또렷하지만, 컴퓨터 입장에서는 전부 사진 한 장이다. 그러니 “서명이라는 글자를 검색”하는 방식은 시작부터 성립하지 않았다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;사실 이건 파일을 열자마자 알았어야 했는데, 나는 한참 뒤에야 깨달았다. 처음엔 화면에 글씨가 멀쩡히 보이니 당연히 검색이 될 줄 알고, 서명이라는 단어를 찾게 시켰다가 아무것도 안 잡혀서야 “아, 이게 다 사진이구나” 하고 알아챘다. 비개발자가 자동화를 처음 붙일 때 흔히 하는 착각이 이거라고 생각한다. 화면에 보이는 것과 컴퓨터가 읽을 수 있는 것은 다르다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;보통 이럴 때 쓰는 게 이미지에서 글자를 읽어내는 OCR(광학문자인식) 프로그램인데, 이것도 막혔다. 내가 쓰는 건 회사 보안 환경의 업무용 PC라, 외부 프로그램을 함부로 설치할 수 없다. 인터넷에 파일을 올려서 처리하는 온라인 서비스도 당연히 못 쓴다. 점검철에는 서명과 날인이 들어 있으니 개인정보에 해당하고, 이건 회사 밖으로 나가면 안 되는 자료다. 자동화를 한다고 회사 자료를 외부 도구에 올리는 순간, 편하려다 사고가 나는 셈이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;정리하면 나는 이런 상자 안에 있었다. 글자 검색 불가, 프로그램 설치 불가, 외부 전송 불가. AI에 통째로 맡기는 그림이 가장 먼저 깨진 지점이 바로 여기다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 돌아보면, 이 제약이 오히려 도구의 방향을 잡아줬다. 글자를 못 읽으면, 사람이 눈으로 하듯 &lt;strong&gt;그림으로 보고 판단하게&lt;/strong&gt;&amp;nbsp;만들면 된다. 제약이 없었다면 나는 아마 편한 길로 갔다가 앞서 말한 사고를 냈을 것이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;그래서 무엇으로, 어떻게 만들었나?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이제 도구 이야기다. 나는 개발자가 아니라서, 이 도구의 설계 대부분은 클로드 코드&lt;span style="color:#999999;"&gt;(Claude Code)&lt;/span&gt;와 대화하며 잡았다. 내가 문제와 제약을 설명하면 클로드가 코드를 제안하고, 나는 그게 왜 안 되는지 실제 파일로 확인해 다시 방향을 트는 식이었다. 따라 해보려는 분을 위해, 무엇을 어떻게 썼는지는 최대한 그대로 남긴다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;환경과 핵심 도구&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;환경은 회사 보안 PC(윈도우)다. 인터넷·설치 없이 돌아가야 하므로, 파이썬&lt;span style="color:#999999;"&gt;(Python)&lt;/span&gt;과 오프라인에서 쓸 수 있는 라이브러리&lt;span style="color:#999999;"&gt;(library, 미리 만들어진 기능 묶음)&lt;/span&gt;만으로 구성했다. 핵심 도구 세 가지는 이렇게 나눠 썼다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;PyMuPDF:&lt;/strong&gt;PDF의 각 페이지를 한 장씩 흑백 이미지로 바꾸는 데 썼다. 글자를 못 읽으니, 페이지를 아예 ‘사진’으로 만들어 픽셀&lt;span style="color:#999999;"&gt;(pixel, 이미지를 이루는 작은 점)&lt;/span&gt; 단위로 다루기 위해서다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;NumPy:&lt;/strong&gt;그렇게 만든 이미지를 숫자 표로 바꿔서, 특정 영역이 얼마나 ‘어둡게 칠해져 있는지’를 계산했다. 서명이 있으면 그 자리에 잉크가 묻어 어두워지고, 비어 있으면 밝다. 결국 서명 유무를 ‘잉크 양’이라는 숫자로 바꾼 것이다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Pillow:&lt;/strong&gt;판정이 끝난 서명 부분만 잘라내 사람이 볼 수 있는 이미지로 저장하는 데 썼다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;동작 순서와 실행 방식&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;돌아가는 순서는 이렇다. 먼저 낮은 해상도로 페이지를 빠르게 훑어 표지인지 아닌지 가려낸다. 표지라고 판단되면 그 페이지만 다시 높은 해상도로 읽어 서명란 두 칸의 잉크 양을 잰다. 그리고 애매한 것만 위로 올려 사람이 보게 한다. 마지막으로 결과를 그림이 들어간 HTML 한 장으로 저장하는데, 이건 마감 증빙으로도 그대로 쓴다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실행 방식도 나 같은 사람이 쓸 수 있어야 했다. 명령어를 칠 줄 몰라도 되도록, &lt;strong&gt;점검철 PDF를 배치 파일 아이콘 위에 끌어다 놓기만하면&lt;/strong&gt;&amp;nbsp;분석이 시작되게 만들었다. 매달 쓰는 도구인데 매번 사용법을 떠올려야 한다면, 그건 자동화가 아니라 또 다른 숙제다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3872/img-02.png"&gt;&lt;figcaption&gt;도구 폴더의 전부. 매달 하는 일은 점검철 PDF를 ‘검증실행.bat’ 위에 끌어다 놓는 것뿐이다. &amp;lt;출처: 작가, 클로드로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3872/img-03.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, 클로드로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;다섯 번 넘어진 이야기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;‘표지만 자동으로 골라낸다’는 이 한 문장이, 실제로는 가장 오래 걸린 부분이었다. 스캔본은 페이지마다 밝기와 기울기가 제각각이라, 그럴듯한 기준을 세울 때마다 번번이 빗나갔다. 순서대로 적어 본다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;잉크가 많은 페이지를 표지로 보자:&lt;/strong&gt;실패. 표지나 글자 빽빽한 보고서나 잉크 양이 비슷해서 구분이 안 됐다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;가운데 큰 제목 글자의 진하기로 보자:&lt;/strong&gt;&amp;nbsp;실패. 표지의 제목이 오히려 더 진해서, 일반 페이지가 표지로 잘못 잡혔다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;회사 로고 색으로 표지를 찾자:&lt;/strong&gt;&amp;nbsp;어떤 표지는 흑백으로 스캔되어 색 정보가 아예 없었다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;표의 세로선 개수로 판단하자:&lt;/strong&gt;실패. 본문의 체크리스트 표와 겹쳐서 오히려 더 헷갈렸다.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;맨 위 굵은 검은 띠로 표지를 확정하자:&lt;/strong&gt;&amp;nbsp;절반의 성공, 절반의 실패. 잘 되다가도, 흐리게 스캔된 표지에서는 그 띠를 놓쳤다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3872/img-04.png"&gt;&lt;figcaption&gt;도구를 만든 방법의 실체. 안 되는 걸 설명하고 지킬 원칙을 정하는 것이 내 일이었다. (제작 당시 대화의 요지를 재구성) &amp;lt;출처: 작가, 클로드로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;넘어질 때마다 나는 클로드에게 “이건 왜 안 됐을까”를 설명하고, 실패한 페이지를 예로 들어 다시 물었다. 그러면 클로드가 다른 방법을 제안하고, 나는 또 실제 파일로 돌려 확인했다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 과정이 지루하게 느껴질 수도 있는데, 나는 오히려 이때 자동화가 뭔지 감을 잡았다. 자동화는 ‘한 번에 맞히는 마법’이 아니라, 틀린 이유를 하나씩 지워 가는 일에 가깝다. 개발을 못 해도 이건 할 수 있다. 틀린 결과를 눈으로 알아보고, 왜 틀렸는지 말로 설명할 수만 있으면 된다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한 방에 맞는 ‘단일 정답’은 없었다. 다섯 번을 헤매고 나서야 방향을 바꿨다. 하나의 완벽한 기준을 찾는 대신, &lt;strong&gt;약한 신호 여러 개를 겹쳐서&lt;/strong&gt;&amp;nbsp;판단하게 한 것이다. 본문 여백 비율, 상단의 검은 띠, 하단 오른쪽의 서명 블록, 페이지 번호 유무. 각각은 불완전하지만, 함께 보면 표지를 꽤 안정적으로 골라냈다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;사람도 표지를 알아볼 때 한 가지만 보지 않는다는 걸 생각하면, 오히려 자연스러운 방식이었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그리고 이때 원칙을 하나 세웠다. &lt;strong&gt;“빠뜨리느니, 차라리 좀 더 보여주자.”&lt;/strong&gt;&amp;nbsp;마감 검사에서 진짜 위험한 건 없는 걸 잘못 띄우는 것(오탐)이 아니라, 있는 걸 못 보고 지나치는 것(누락)이다. 그래서 애매하면 무조건 사람이 한 번 더 보도록, 판정을 ‘확인 필요’ 쪽으로 기울여 두었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;두 번의 방향 전환&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;만들면서 흐름을 바꾼 순간이 두 번 있었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;첫 번째, 서명란을 기준점으로 삼다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;서명란이 비었는지 보려는데, 표지마다 서명 블록의 위치가 미세하게 달라서 자꾸 엉뚱한 자리를 쟀다. 멀쩡히 서명된 칸을 ‘비었다’고 잘못 읽기도 했다. 한참을 헤매다 알아챘다. 서명 칸이 비어 있어도, 그 옆의 ‘(인)’이라는 날인 표시는 인쇄물이라 &lt;strong&gt;항상 같은 자리에 찍혀 있다.&lt;/strong&gt;&amp;nbsp;이 ‘(인)’을 기준점으로 삼아 점검자 칸과 확인자 칸의 위치를 잡으니, 한쪽이 비어 있어도 정확히 그 자리를 짚어냈다. 작은 발상 하나로 막혔던 게 풀렸다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;두 번째, 도구에도 다 맡기지 않기로 하다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;스캔 품질이 들쭉날쭉하다 보니, “서명이 있다 / 없다”를 도구가 100% 단정하게 만드는 건 위험했다. 흐린 서명을 없다고 우기거나, 얼룩을 서명으로 볼 수 있었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 나는 도구의 역할을 일부러 줄였다. &lt;strong&gt;도구는 표지를 전부 찾아 서명 부분만 잘라 한 화면에 모아주는 데까지만&lt;/strong&gt;&amp;nbsp;하고, 있다·없다의 최종 판단은 사람이 1초 눈으로 하도록 했다. 의심스러운 것만 빨갛게 맨 위로 올려서. 처음의 “AI한테 다 시키자”에서 정확히 반대편으로 온 셈인데, 이게 더 정직하고 실제로 더 빨랐다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3872/img-05.png"&gt;&lt;figcaption&gt;도구와 함께 만들어 둔 사용안내 문서. 다음 달의 나, 그리고 이 도구를 물려받을 동료를 위한 것이다. &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;그래서 얼마나 바뀌었을까&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;완성한 도구로 그달 점검철(400페이지가 넘는 실제 파일)을 돌려봤다. 표지를 빠짐없이 찾아냈고, 서명 누락은 0건으로 확인됐다. 시간으로 보면, 30분에서 한 시간 걸리던 눈 검사가 &lt;strong&gt;1분 남짓의 자동 분석과 한 화면 확인으로&lt;/strong&gt;&amp;nbsp;줄었다. 매달 반복되는 일이니, 1년으로 치면 결코 작지 않은 시간이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image"&gt;&lt;img src="https://www.wishket.com/media/news/3872/img-06.png"&gt;&lt;figcaption&gt;분석이 끝나면 남는 요약. ‘확인필요’ 2건만 사람이 보면 그달 검사는 끝이다. (수치·파일명은 예시로 재구성) &amp;lt;출처: 작가, 클로드로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;무엇보다 결과물이 그림이 들어간 문서 한 장으로 남으니, “확인했다”는 말이 아니라 “이렇게 확인했다”는 증빙이 함께 생긴 것도 실무에서는 컸다. 마감 업무는 결국 누군가에게 “제대로 봤다”는 걸 설명해야 하는 일이기도 한데, 이제는 그 근거가 파일로 남는다. 시간을 줄인 것보다 이쪽이 더 마음에 든다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;솔직히 처음 도구를 돌려 누락 0건이 뜨고, 그게 눈으로 다시 봐도 맞았을 때의 기분은 좀 특별했다. 한 시간짜리 눈싸움이 1분으로 줄어드는 걸 직접 보면, 다음엔 또 어떤 일을 넘길 수 있을까 하는 생각이 자연스럽게 든다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 이 도구는 내가 최근 넉 달 동안 업무에 붙여 만든 자동화 도구 여러 개 중 하나다. 대단한 개발을 한 게 아니라, 귀찮고 반복적인 일을 하나씩 골라 자동화해 본 결과다. 하나가 되니 그다음이 보였고, 그렇게 늘어났다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며: 도구에 다 맡기지 않는다는 것&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이 작업에서 내가 진짜로 배운 건 파이썬 문법이나 라이브러리 이름이 아니었다. &lt;strong&gt;어디까지 도구에 맡기고, 어디부터는 사람이 봐야 하는가&lt;/strong&gt;를 스스로 정한 경험이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;처음엔 “AI가 다 해주겠지”로 시작했지만, 실제로 쓸모 있는 도구는 정반대 지점에 있었다. &lt;strong&gt;도구는 사람이 지치는 일, 400페이지를 뒤져 표지를 찾고, 서명란만 잘라 모으는 일을 대신하고, 판단이라는 마지막 1초는 사람에게 남겨 둔다.&lt;/strong&gt;&amp;nbsp;나는 이걸 ‘사람 먼저, 도구 나중’이라고 부르는데, 다음에 다른 업무를 자동화할 때도 계속 쓰게 된 기준이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;나는 개발자가 아니다. 그런데도 현장에서 매달 쓰는 도구 하나를 완성했다. 내가 한 일은 문제를 정확히 정의하고, 안 되는 걸 솔직히 인정하고 방향을 다시 트는 것이었다. 구현은 클로드와 함께했다. 혹시 지금 반복 업무에 지쳐 있는데 “나는 코딩을 못 하니까”라며 미뤄 두고 있다면, 딱 하나만 권하고 싶다. 가장 귀찮은 일 하나를 골라, 어디까지 맡길지부터 정해 보는거다. 거기서부터 생각보다 많은 게 바뀐다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;이 글은 AI의 도움을 받아 작성했습니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>우리 개발자들, 이제 어떻게 해야 해?</title><link>https://yozm.wishket.com/magazine/detail/3866</link><description>같은 요청에도 매번 다른 결과를 내놓는 비결정론적인 도구가 우리 손에 쥐어졌다. 마치 어떤 마법이 나올지 모르는 지팡이를 들고 각자의 주문을 외우는 기분이다. '깊은 지식이 있어야 AI를 제대로 쓴다'는 전제도, '사람이 만들었기 때문에 더 낫다'는 말도 더 이상 충분한 방어선이 되지 않는다. 백엔드에서 AI를 다루는 풀스택으로 직무를 전환한 한 주니어 개발자가, 흔들린 믿음과 그래도 놓고 싶지 않은 한 가지를 기록했다.</description><guid>https://yozm.wishket.com/magazine/detail/3866</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;인공지능 시대 앞에 선 주니어 개발자의 기록&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3866/%EC%9A%B0%EB%A6%AC%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%93%A4_%EB%8C%80%ED%91%9C%EC%9D%B4%EB%AF%B8%EC%A7%80.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, AI로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;까만 화면 위로 문장이 한 글자씩 떠오른다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;나는 그 앞에 앉아 요구사항을 적었다가 지우기를 반복한다. 원하는 동작을 설명하고, 예외 상황을 덧붙이고, 기존 코드의 맥락을 알려준다. 그러면 에이전트가 코드를 작성한다. 눈으로 결과물을 훑고, 또 다른 에이전트로 검수한 다음, 부족한 부분을 다시 요구사항으로 정리해 요청한다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;이제 이런 방식은 내게 낯선 실험이 아니라 일상이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;2026년에 소프트웨어 엔지니어로 일한다는 것은 참 이상한 경험이다. 우리는 오랫동안 예측 가능한 세계에서 일한다고 믿어왔다. 코드는 입력에 따라 정해진 결과를 내고, 버그에는 원인이 있으며, 그런 시스템은 논리적으로 설명될 수 있어야 한다고 배웠다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그런데 지금 우리 손에는 비결정론적인 도구가 쥐어져 있다. 같은 요청에도 매번 조금씩 다른 결과를 내놓는 도구, 정확히 어떤 답을 줄지 알 수 없지만 놀라운 속도로 결과물을 만들어내는 도구. 마치 어떤 마법이 나올지 모르는 지팡이를 들고, 각자의 주문을 외우며 무언가를 만들어내는 기분이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;우리는 이제 어떻게 해야 할까. AI가 코드를 쓰고, 도구가 판단을 돕고, 어제의 상식이 오늘 흔들리는 시대에 개발자는 어디에 서 있어야 할까. 여전히 우리에게 필요한 자리는 어디일까.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;흔들린 믿음&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;불과 1, 2년 전만 해도 이런 방식으로 일할 줄은 상상하지 못했다. 예전 같았으면 직접 파일을 열고, 코드를 읽고, 한 줄씩 수정했을 것이다. 하지만 지금은 먼저 요구사항을 쓴다. 직접 작성하기보다, 코드가 만들어지도록 지시하고 검토하는 시간이 더 많아졌다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;이제 막 이 업계로 들어오려는 후배들에게 나는 무엇을 조언할 수 있을까. 자료구조와 알고리즘을 공부하라고 말해야 할까. 운영체제와 네트워크, 데이터베이스 같은 컴퓨터 과학의 기본기를 깊게 익히라고 말해야 할까. 물론 이 모두가 여전히 중요하다고 믿고 싶다. 그러나 예전처럼 확신에 차서 말하기는 어려워졌다. “AI를 제대로 쓰려면 개발자도 그만큼의 지식을 갖춰야 한다”는 전제가 우리 사이를 이어줬지만, 시간이 지날수록 그 전제마저 흔들리고 있다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;이제는 한두 줄의 프롬프트만으로도 보안 취약점을 점검하고, 테스트 코드를 만들고, 리팩터링 방향을 제안받을 수 있다. 고급 해커 수준의 지식을 갖추지 않아도 AI의 도움을 받아 코드의 보안을 살필 수 있는 시대가 온 것이다. 물론 그 결과를 이해하고 책임지는 일은 여전히 사람에게 남아 있다. 하지만 적어도 “깊은 지식이 있어야만 AI를 제대로 활용할 수 있다”는 말은 더 이상 절대적인 방어선처럼 느껴지지 않는다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;고용주들의 기대도 달라지고 있다. AI를 통한 생산성 향상은 이미 업계 전반에서 눈에 보이는 성과로 나타났고, 적은 시간에 더 많은 결과물을 요구하는 분위기는 점점 강해지고 있다. 이런 상황에서 “Back to Basic”을 외치며 다시 모든 코드를 한 줄씩 직접 작성하던 시절로 돌아가자 말할 수 있을까. 쉽지 않다. 이미 AI 도구는 우리 일의 방식 안으로 깊숙이 들어와 버렸다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;사람이 짠 코드는 다르다고, 복잡한 맥락을 이해하고 책임질 수 있는 것은 결국 인간 엔지니어뿐이라고 믿고 싶다. AI가 코드를 만들 수는 있어도, 진짜 엔지니어링은 쉽게 대체되지 않을 것이라고도. 그러나 이 믿음도 점점 흔들리고 있다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;돌이켜보면 인간이 작성한 코드가 언제나 훌륭했던 것은 아니었기 때문이다. 모든 개발자가 좋은 코드를 썼던 것도 아니고, 모든 시스템이 아름다운 설계 위에 세워졌던 것도 아니다. “작동하면 건드리지 마라”는 말이 있었고, “레거시에는 이유가 있다”는 말도 있었다. 그 말들 뒤에는 수많은 타협과 임시방편, 그리고 누구도 쉽게 설명하지 못하는 코드들이 숨어 있었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그렇다면 사람의 코드와 AI의 코드는 정말 얼마나 다른가. AI가 만든 결과물을 그대로 믿을 수는 없다. 검토도 필요하고, 책임도 결국 사람에게 남는다. 하지만 적어도 “사람이 만들었기 때문에 더 낫다”는 말은 더 이상 충분한 방어선이 되지 않는 듯하다. 인간의 코드도 애초에 불완전했고, AI는 빠르게 그 불완전함의 영역을 침범하고 있다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;어떻게든 살아남아야지&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;이 격랑의 시대에서, 고작 주니어 엔지니어인 나는 어떤 선택을 해야 했을까.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;얼마 전, 나는 이직을 했고, 백엔드 엔지니어에서 인공지능을 다루는 풀스택 엔지니어로 직무를 전환했다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그것이 정답이었다고 말할 수는 없다. 다만 한 가지는 분명했다. 가만히 있을 수는 없었다. 세상이 바뀌는 속도는 너무 빨랐고, 나는 그 변화가 지나가길 기다릴 만큼 여유롭지 않았다. AI가 개발자의 일을 대체할지도 모른다는 불안, 내가 쌓아온 개발 경험이 어느 순간 낡은 기술이 될지도 모른다는 두려움, 지금 공부하는 것들조차 몇 년 뒤에는 의미를 잃을지도 모른다는 허무함이 계속 나를 흔들었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;전통적인 웹 서비스 산업의 포지션에 그대로 머물러 있다면, 앞으로의 변화 속에서 오래 살아남기 어렵겠다는 생각이 컸다. 물론 웹 서비스 자체가 사라진다고 본 것은 아니다. 여전히 세상의 많은 문제는 웹의 형태로 사용자에게 전달된다. 사람들은 미래에도 로그인하고, 데이터를 저장하고, 결제하고, 검색하고, 알림을 받을 것이다. 그 모든 흐름에는 앞으로도 여전히 백엔드가 필요할 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;하지만 이 문제들을 푸는 방식은 급격히 달라지고 있다. 예전에는 기능을 정의하고, API를 만들고, 데이터베이스를 설계하고, 서버를 운영하는 능력이 중시되었다. 그러나 이제는 요청을 단순히 처리하는 것을 넘어, 사용자의 의도를 해석하고, 적절한 도구를 호출하고, 여러 시스템을 연결해 결과를 만들어내는 흐름이 점점 중요해지고 있다. 그 변화의 중심에 인공지능이 있다고 느꼈다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그래서 제대로 공부해야겠다고 생각했다. 단순히 도구를 잘 쓰는 사람이 아니라, 인공지능이 전통적인 서비스와 어떻게 상호작용하는지, 어떤 한계를 가지고 있는지, 어떻게 안전하게 쓰일 수 있는지 이해하는 사람이 되고 싶었다. 그 연장선에서 대학원 지원도 준비하고 있다. 회사에서 마주하는 문제만으로는 부족하다고 느꼈고, 조금 더 깊게 이 분야를 들여다보고 싶었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그렇다고 두려움이 사라진 것은 아니었다. 학생 때부터 꿈꿔왔던 백엔드 분야의 스페셜리스트가 되겠다는 목표를 포기하는 것이 맞을까. 다양한 분야를 다루는 제너럴리스트가 되겠다는 새로운 목표는 몇 년 뒤에도 의미가 있을까. 나는 여전히 이런 생각들 앞에서 자주 멈춰 선다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;막연한 미래 너머&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;학생 시절의 나는 개발자의 미래를 꽤 단순하게 상상했다. 회사에 들어가 좋은 선배에게 배우고, 실력을 쌓고, 언젠가는 능숙한 시니어 개발자가 되는 것. 새로운 기술이 나오더라도 기본기를 잘 다져두면 따라갈 수 있을 것이라고 믿었고, 이 믿음은 오랫동안 나를 지탱해주었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;하지만 지금은 이 믿음이 조금은 부서졌다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;몇 년 전만 해도 직접 코드를 작성하는 것이 성장의 중요한 증거처럼 느껴졌다. 어려운 버그를 해결하고, 복잡한 로직을 구현하고, 성능을 개선하는 경험이 실력의 기반이라고 생각했다. 그런데 이제 나는 이 일들의 상당 부분을 인공지능과 함께 처리한다. 전이었다면 하루 종일 붙잡고 있었을 문제를 인공지능이 몇 분 만에 풀어내는 모습을 볼 때면, 짜릿하면서도 이상하게 허무하다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;분명 생산성은 높아졌다. 하지만 생산성이 높아진 만큼, 나의 역할에는 더 자주 의문이 든다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;이제 우리는 무엇을 잘해야 할까. 코드를 빠르게 작성하는 능력, 인공지능에게 좋은 지시를 내리는 능력, 서비스 전체를 설계하는 능력이 전부일까. 혹은 도메인을 이해하고, 사용자 문제를 정의하는 능력이 최고일까.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;답은, 아마도 전부를 잘해내야 한다는 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그래서 더 어렵다. 예전에는 공부해야 할 것이 많아도 어느 정도 순서가 있었다. 예컨대 언어를 배운 다음에는 프레임워크를 익히고, 데이터베이스를 공부하고, 배포와 운영을 경험하는 식이었다. 그런데 지금은 모든 것이 순서 없이 쏟아져 들어오는 것 같다. 백엔드도 해야 하고, 클라우드도 알아야 하고, 인공지능도 알아야 하고, 보안도 알아야 하고, 제품 감각도 필요하다고 한다. 여기에 매주 새로운 도구와 프레임워크가 등장한다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;무언가를 놓치고 있다는 생각. 지금 따라가지 않으면 영영 뒤처질 것 같다는 두려움. 이런 생각들은 나를 계속 움직이게 하지만, 동시에 갉아먹기도 한다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;하지만 요즘은 다르게 생각하려 한다. 미래를 막연하다고 느끼는 것이 꼭 내가 무능하다는 뜻은 아닐지도 모른다. 시대가 정말로 예측하기 어려워졌다는 말일 수도 있다. 지금 공부하는 기술이 5년 뒤에도 같은 형태로 남아 있을지는 아무도 모른다. 지금 유망해 보이는 직무가 몇 년 뒤에도 같은 이름으로 존재할지도 확실하지 않다. 그러니 불안한 것은 자연스러운 일일지 모른다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;기술은 계속 바뀐다. 도구도 계속 바뀐다. 어쩌면 지금 우리가 열심히 익히는 많은 것들이 몇 년 뒤에는 다른 이름으로 불릴지도 모른다. 하지만 문제를 정의하고, 맥락을 이해하고, 결과에 책임지려는 태도는 쉽게 사라지지 않을 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;나는 이 믿음만은 아직 놓고 싶지 않다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;우리는 이제 어떻게 해야 할까?&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;이 질문에 자신 있게 답할 수 있는 사람은 많지 않을 것이다. 새 시대에 대해 말하는 사람은 많지만, 아직 그 시대를 정확히 살아본 사람은 없다. 모두가 변화의 한복판에 서 있고, 각자의 방식으로 살아내고 있다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;나 역시 그렇다. 백엔드 엔지니어에서 풀스택 엔지니어로 방향을 틀었지만, 이 선택이 완벽한 답이라고 말할 수는 없다. 대학원에 지원하고, 인공지능을 공부하고, 새로운 도구를 익히려 하지만, 이 길이 어디로 이어질지 확신하지 못한다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그래도 되뇌인다. 변화를 외면하지 말자. 하지만 내가 쌓아온 것을 버리지도 말자. 대신 그것을 새로운 시대와 연결해보자.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;백엔드를 해왔으니, 나는 그 경험 위에 인공지능을 얹을 수 있다. 어쩌면 인공지능 시대의 개발자에게 필요한 것은 자기 경험을 잃지 않고, 변화하는 기술과 연결해 다시 쓸 수 있는 능력일지 모른다 믿고 말이다. 인공지능이 코드를 쓰는 시대에도, 결국 누군가는 문제를 정의해야 한다. 누군가는 결과를 책임져야 한다. 누군가는 이용자의 불편함을 발견하고, 기술을 통해 상상을 현실로 만들어내야 한다. 나는 그 자리에 우리가 여전히 필요하다고 믿고 싶다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;지금의 나 역시 할 수 있는 말은 대단치 않지만, 그래도 전하고 싶다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;사라질까 두려워 멈추기보다, 변화하는 세상 속에서 우리가 다시 쓰일 자리를 찾아가자고. 우리 모두 결국에는 그 일을 함께 해낼 것이라고.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>바이브 코딩을 하기 전에 꼭 알아야 할 7가지 개념 정리</title><link>https://yozm.wishket.com/magazine/detail/3850</link><description>바이브 코딩으로 무언가를 만들다 보면 누구나 한 번쯤 비슷한 순간을 만납니다. "AI가 자신 있게 알려준 대로 했는데 왜 안 되지?", "분명 잘 되던 화면이 수정 한 번에 망가졌는데 되돌릴 방법이 없네?", "내 컴퓨터에선 멀쩡한데 다른 사람 폰에선 왜 안 보이지?" 같은 질문들입니다. 이런 막힘은 대부분 '코딩 실력'이 부족해서가 아니라, 몇 가지 기본 개념을 몰라서 생깁니다. 이번 글에서는 개발자인 제가 직접 부딪혀보며 추린, 비전공자가 바이브 코딩 전에 최소한 알아두면 좋은 개념 일곱 가지를 정리해 봤습니다. 어디서 막힘이 생기는지, 왜 알아두면 좋은지를 함께 살펴보겠습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3850</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;바이브 코딩으로 무언가를 만들다 보면 누구나 한 번쯤 비슷한 순간을 만납니다. "AI가 자신 있게 알려준 대로 했는데 왜 안 되지?", "분명 잘 되던 화면이 수정 한 번에 망가졌는데 되돌릴 방법이 없네?", "내 컴퓨터에선 멀쩡한데 다른 사람 폰에선 왜 안 보이지?" 같은 질문들입니다. 이런 막힘은 대부분 '코딩 실력'이 부족해서가 아니라, 몇 가지 기본 개념을 몰라서 생깁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지난 글 ‘&lt;a href="https://yozm.wishket.com/magazine/detail/3834/"&gt;&lt;u&gt;바이브 코딩으로 나만의 프로필 링크 페이지 만들기&lt;/u&gt;&lt;/a&gt;’에서 프로필 링크 페이지를 직접 만들어보며, 저는 바로 그 '기본 개념'이 필요한 자리를 확인할 수 있었습니다. 그래서 이번 글에서는 개발자인 제가 직접 부딪혀보며 추린, 비전공자가 바이브 코딩 전에 최소한 알아두면 좋은 개념 일곱 가지를 정리해 봤습니다. 어디서 막힘이 생기는지, 왜 알아두면 좋은지를 함께 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;미리 요점만 콕 집어보면?&lt;/strong&gt;&lt;/h4&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;AI는 확률 기반 생성이라 항상 옳다고 보장할 수 없으며, 결과를 직접 실행·검증하고 최종 판단은 사람이 맡아야 합니다.&lt;/li&gt;&lt;li&gt;프롬프트를 구체적으로 나누어 요청하고, HTML·CSS·JavaScript·터미널·컨텍스트를 이해하면 수정과 문제 해결이 훨씬 쉬워집니다.&lt;/li&gt;&lt;li&gt;Git으로 되돌릴 수 있는 저장 지점을 만들고, 로컬과 배포의 차이를 이해해야 바이브 코딩 결과물을 안정적으로 완성·공유할 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3850/%EA%B7%B8%EB%A6%BC1__5_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;AI는 만능이 아닙니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI를 잘 활용하기 위해 가장 먼저 이해해야 할 것은, AI가 '정답을 아는 존재'가 아니라는 점입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 확률 기반 생성의 한계&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;우리가 쓰는 AI(LLM)는 방대한 글을 학습한 뒤, 어떤 단어 다음에 어떤 단어가 올 확률이 높은지를 계산해 문장을 한 단어씩 생성합니다. 내용을 이해해서 답한다기보다, 가장 그럴듯한 말을 이어 붙이는 방식에 가깝습니다. 그래서 존재하지 않는 기능이나 사실과 다른 정보를 자신 있게 내놓기도 하는데, 이를 '환각(할루시네이션)'이라고 부릅니다. 다만 'AI는 자주 틀린다'는 뜻으로 받아들이면 오해가 생길 수 있습니다. 대체로 꽤 정확하지만 '항상 옳다고 보장할 수는 없다'는 쪽이 더 정확한 표현입니다. 문제는 그 '틀릴 수 있는 부분'이 겉보기에는 멀쩡한 문장 속에 섞여 있다는 점입니다. 그래서 결과를 눈으로만 훑고 넘어가면 놓치기 쉽습니다. 중요한 부분일수록 AI의 답을 한 번 더 의심하고 직접 확인하는 편이 안전합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 왜 알아야 할까요?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이 원리를 알면 AI의 답을 결과로 검증하는 습관이 생기기 때문입니다. 코드를 실제로 실행해보고 의도대로 동작하는지 확인하는 과정이 자연스럽게 따라옵니다. AI를 유능한 조수로 활용하되 최종 판단은 사람이 맡는다는 태도, 그것이 바이브 코딩의 출발점입니다. 반대로 이 전제를 모르면 그럴듯해 보이는 답을 그대로 받아들였다가, 한참 뒤에야 문제를 발견하게 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;프롬프트 작성법&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;같은 AI라도 어떻게 요청하느냐에 따라 결과물의 질이 크게 달라집니다. 핵심은 두 가지입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 구체적으로 말할수록 결과가 달라진다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;"예쁘게 만들어줘" 같은 막연한 요청은 AI가 의도를 짐작하게 만듭니다. 반면 "카드를 흰 박스로, 모서리는 둥글게, 글씨는 가운데 정렬"처럼 원하는 모습을 구체적으로 적으면 결과가 의도에 훨씬 가까워집니다. 사람에게 일을 맡길 때와 같은 원리로, 조건이 분명할수록 결과도 정확해집니다. 모호한 표현 하나가 전혀 다른 결과를 부르기도 하므로, 구체성은 곧 시간 절약으로 이어집니다. 원하는 결과의 예시나 참고할 대상을 함께 제시하면, AI가 방향을 잡기가 한결 쉬워집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 작게 나눠서 요청하기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;한 번에 여러 가지를 요청하면 어디서 어긋났는지 파악하기 어렵습니다. "먼저 배경색", 그 다음 "버튼 그림자"처럼 단계를 나눠 요청하고 확인하면, 문제가 생겨도 원인을 빠르게 좁힐 수 있습니다. 단계를 쪼개면 매 단계의 결과를 눈으로 확인하게 되어, 잘못된 방향으로 멀리 가기 전에 바로잡을 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 왜 알아야 할까요?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;프롬프트를 다루는 법은 비전공자가 AI를 쓰며 가장 즉각적으로 효과를 보는 기술이기 때문입니다. 잘 정리된 요청 하나가 수십 번의 시행착오를 줄여줍니다. 나아가 잘 만든 요청을 문서로 남겨 재사용하면, 비슷한 작업마다 같은 품질을 더 빠르게 얻을 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;웹 페이지의 구조 이해하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;웹 페이지가 무엇으로 이루어지는지 큰 그림만 알아도, AI에게 건네는 요청이 한층 정확해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 세 가지 역할 구분하기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;웹 페이지는 크게 세 요소로 구성됩니다. HTML은 뼈대(구조), CSS는 디자인, JavaScript는 동작인데요. 글의 내용과 배치는 HTML이, 색·크기·여백 같은 꾸밈은 CSS가, 버튼 클릭 같은 움직임은 JavaScript가 담당합니다. 집에 비유하면 HTML은 골조, CSS는 인테리어, JavaScript는 전등을 켜고 문을 여는 기능에 해당합니다. 세 가지가 각자 맡은 일을 나눠 하나의 화면을 완성하는 구조입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3850/%EA%B7%B8%EB%A6%BC2__6_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 왜 알아야 할까요?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;세 역할을 구분할 수 있으면 수정 요청이 정확해집니다. "글씨가 작다"는 막연한 말 대신 "글씨 크기(CSS)를 키워달라"고 하면, AI가 손볼 영역이 분명해집니다. 용어를 외울 필요는 없고, '구조·디자인·동작'이라는 세 갈래가 있다는 감각만으로 충분합니다. 이 감각이 있으면 AI가 내놓은 결과물을 받아, 어느 부분을 어떻게 고쳐야 할지도 스스로 가늠할 수 있습니다. 막연한 요청과 구체적인 요청의 차이도, 바로 이 구분에서 시작됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;터미널 활용하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;검은 화면 때문에 어렵게 느껴지지만, 실제로 필요한 것은 많지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3850/%EA%B7%B8%EB%A6%BC3__3_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: &lt;a href="https://ko.wikipedia.org/wiki/%ED%8C%8C%EC%9D%BC:Cmd-ping.png"&gt;&lt;u&gt;위키백과&lt;/u&gt;&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 알아야 하는 최소한의 명령어&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;터미널은 명령어를 입력해 컴퓨터에 지시를 내리는 창입니다. 폴더로 이동하는 cd, 폴더 안의 파일을 확인하는 ls 정도면 AI가 안내하는 과정을 따라가기에 충분합니다. 한 가지, 터미널은 '현재 위치한 폴더'를 기준으로 동작하므로, 작업을 시작하기 전에 위치를 한 번 확인해두면 파일이 엉뚱한 곳에 생기는 일을 줄일 수 있습니다. 이 작은 습관만으로도 초반에 겪는 혼란의 상당 부분을 피할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 왜 알아야 할까요?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;바이브 코딩 도구의 상당수가 터미널 위에서 동작하기 때문입니다. 명령어를 외우기보다, 모르는 명령이 나왔을 때 그 자리에서 AI에게 의미를 물어보는 편이 더 효율적입니다. 한번 익숙해지면, 같은 작업도 마우스로 메뉴를 찾는 것보다 빠르고 정확하게 처리할 수 있습니다. 결국 터미널은 ‘넘어야 할 벽’이라기보다, 익숙해지면 작업 속도를 높여 주는 도구에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;컨텍스트&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI와 대화가 길어지면, 앞서 정한 내용을 잊은 듯 행동하는 순간이 옵니다. 이는 AI가 기억하는 방식과 관련이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 컨텍스트 윈도우의 존재&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;AI가 한 번에 참고할 수 있는 대화의 양에는 한계가 있고, 이 범위를 '컨텍스트 윈도우'라고 부릅니다. 대화가 길어질수록 초반에 정한 규칙이나 설정이 이 범위 밖으로 밀려나면서 흐려질 수 있습니다. 예를 들어 처음에 '버튼 색은 파란색'이라고 정해두었는데, 한참 뒤에는 다른 색으로 바뀌어 있는 식입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) AI의 기억을 도와주는 방법&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;그래서 중요한 요구사항은 다시 정리해 알려주거나, 파일로 정리해 통째로 전달하는 방식이 유용합니다. 지난 글에서 다룬 prompt.md에 요구사항을 적어 @prompt.md로 불러오는 방법이 그 대표적인 예입니다. 요구사항이 문서로 남아 있으면, 대화가 아무리 길어져도 같은 기준을 반복해서 일러줄 수 있다는 점이 든든합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 왜 알아야 할까요?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;AI가 갑자기 엉뚱하게 동작할 때, 그것이 ‘오류’가 아니라 ‘기억의 한계’ 때문임을 알면 대응이 달라집니다. 핵심 규칙을 간단히 다시 짚어주는 것만으로 결과가 안정되는 경우가 많습니다. 원인을 알면 대응법은 의외로 단순해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;버전 관리&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI는 코드를 한 번에 크게 바꾸기도 합니다. 그래서 언제든 되돌릴 수 있는 안전장치가 중요해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 저장과 되돌리기의 개념&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Git은 작업 내용을 단계별로 저장해두고, 필요할 때 과거 시점으로 되돌릴 수 있게 해주는 도구입니다. 게임의 세이브 포인트와 비슷합니다. 잘 동작하던 상태를 저장해두면, 이후 수정이 잘못되더라도 그 지점으로 안전하게 복귀할 수 있습니다. 한 줄 한 줄 직접 백업하지 않아도, 도구가 그 기록을 대신 관리해 줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 버전 관리 없는 바이브 코딩의 위험&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;저장 지점이 없는 상태에서 AI가 멀쩡하던 부분까지 바꿔버리면, 되돌릴 방법이 없어 처음부터 다시 작업해야 할 수 있습니다. 작업 규모가 커질수록 이 위험은 빠르게 커집니다. 특히 한 번에 여러 파일을 동시에 바꾸는 작업일수록, 저장 지점이 있고 없고의 차이가 결정적입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 왜 알아야 할까요?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;모든 명령어를 익힐 필요는 없습니다. "지금 상태를 저장", "이전으로 되돌리기" 정도를 AI에게 맡길 수 있다는 것만 알아도, 더 과감하게 시도할 수 있는 여유가 생깁니다. 되돌릴 수 있다는 사실 하나가, 새로운 시도의 부담을 크게 덜어 줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;배포하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;다 만들어도 내 컴퓨터 안에만 있으면 다른 사람은 볼 수 없습니다. 그 마지막 단계가 배포입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 로컬과 배포의 차이&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;내 컴퓨터에서만 열리는 상태를 '로컬', 인터넷에 올려 누구나 접속할 수 있게 만드는 것을 '배포'라고 합니다. 배포를 하면 '서버'가 페이지를 대신 보관합니다. 서버는 인터넷에 연결된 컴퓨터라고 이해하면 충분한데, 누군가 주소로 접속하면 서버가 저장된 파일을 전달해 화면을 띄워줍니다. 그래서 내 컴퓨터를 꺼도 페이지는 유지되고, 어떤 기기에서든 같은 주소로 접속할 수 있습니다. 덕분에 완성한 결과물을 주소 하나로 어디서든 보여줄 수 있게 됩니다. 배포 이후에는 수정한 내용을 다시 올리기만 하면 모두에게 곧바로 반영된다는 점도 편리합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3850/%EA%B7%B8%EB%A6%BC4.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 왜 알아야 할까요?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;'내 화면에서 되는 것'과 '모두에게 공개된 것'은 다르기 때문입니다. 이 차이를 이해하면 "왜 다른 기기에서는 안 보이지?" 같은 상황을 파악하고, 완성한 결과물을 실제로 공유할 수 있습니다. 직접 만든 결과물을 누군가에게 보여줄 수 있다는 점은, 다음 작업을 이어갈 좋은 동기가 되기도 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;지금까지 일곱 가지 개념을 살펴봤습니다. 정리하고 보면 바이브 코딩은 '코딩을 대신해 주는 마법'이라기보단, '코딩의 진입 장벽을 낮춰주는 도구'에 가깝습니다. AI가 코드를 만들어주더라도, 그 결과가 적절한지 판단하고 방향을 정하는 일은 여전히 사람의 몫이기 때문입니다. 도구가 아무리 똑똑해져도, 그 도구를 어디로 끌고 갈지는 사람이 정해야 하는 영역입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 이 개념들은 'AI 시대에 필요 없어진 지식'이 아니라, 오히려 'AI를 제대로 활용하기 위해 더 챙겨두면 좋은 기본기'에 가깝습니다. 오늘 다룬 일곱 가지를 큰 그림으로 이해해 두면, 바이브 코딩을 처음 시작하는 분도 같은 자리에서 덜 막히고, 막히더라도 원인을 한결 빠르게 좁힐 수 있을 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;결국 중요한 것은 모든 것을 미리 통달하는 일이 아니라, 막혔을 때 '어디를 봐야 할지' 아는 감각인데요. 그 감각은 한 번에 완성되지 않지만, 직접 만들어보는 경험 속에서 분명히 자랍니다. 그 출발점은 거창한 학습이 아니라, 오늘 살펴본 개념들을 한 번씩 떠올려 보는 작은 습관 아닐까요?&lt;/p&gt;&lt;hr&gt;&lt;p style="text-align:justify;"&gt;&amp;lt;참고&amp;gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://vibe.onebitefe.com/"&gt;&lt;u&gt;바이브 코딩 핸드북&lt;/u&gt;&amp;nbsp;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>이벤트 기반 MSA, AI 시대엔 더 비싸진다고요?</title><link>https://yozm.wishket.com/magazine/detail/3839</link><description>이벤트 기반 MSA(Microservice Architecture)를 운영하다 보면 처음엔 꽤 잘 나눴다고 느낍니다. 주문, 결제, 재고, 알림이 각자 맡은 일을 처리하고, 한쪽 장애가 곧바로 전체 장애로 번지지 않는 장점도 분명히 보입니다. 그런데 AI 에이전트에게 유지보수를 맡기기 시작하면, 그 느슨한 연결이 갑자기 흐름을 다시 찾아야 하는 비용으로 돌아옵니다. 제가 이 글에서 말하는 비용은 “MSA는 복잡하다”는 일반론이 아닙니다. 이벤트 기반 MSA를 운영하면서 이벤트 흐름을 다시 이해하고 검증하는 데 드는 비용입니다. </description><guid>https://yozm.wishket.com/magazine/detail/3839</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;이벤트 기반 MSA(Microservice Architecture)를 운영하다 보면 처음엔 꽤 잘 나눴다고 느낍니다. 주문, 결제, 재고, 알림이 각자 맡은 일을 처리하고, 한쪽 장애가 곧바로 전체 장애로 번지지 않는 장점도 분명히 보입니다. 그런데 AI 에이전트에게 유지보수를 맡기기 시작하면, 그 느슨한 연결이 갑자기 흐름을 다시 찾아야 하는 비용으로 돌아옵니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;주문 상태가 바뀌지 않는 버그를 고친다고 해보겠습니다. 겉으로 보면 주문 서비스 안의 상태 전이 조건만 확인하면 될 것처럼 보입니다. AI 에이전트도 비슷하게 접근합니다. 현재 작업 중인 저장소에서 관련 코드를 찾고, 조건문을 수정하고, 테스트를 추가합니다. 코드만 보면 꽤 그럴듯한 수정안이 나옵니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 이벤트 기반 MSA에서는 그걸로 충분하지 않았습니다. 주문 서비스에서 이벤트가 실제로 발행됐는지, 결제나 재고 서비스의 컨슈머(이벤트를 받아 처리하는 쪽)가 어떤 값을 기대하는지, 배송 서비스가 같은 이벤트를 다른 의미로 쓰고 있지는 않은지 함께 봐야 했습니다. 증상은 “주문 상태가 안 바뀐다” 하나지만, 실제 원인은 주문 서비스 안이 아니라 여러 서비스 사이의 이벤트 흐름 어딘가에 숨어 있을 수 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/image_1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실무에서는 이런 흐름을 감으로만 처리하지 않습니다. 이벤트 이름, 페이로드, 컨슈머별 처리 규칙을 팀 컨벤션이나 문서, 대시보드, GUI 도구로 확인하면서 수정합니다. 그런데 AI 에이전트는 기본적으로 현재 열어준 코드와 문서 안에서 판단합니다. 다른 서비스 도메인의 이벤트 흐름이나 이벤트 맵을 함께 넘기지 않으면, AI는 현재 서비스 안에서만 맞는 수정을 만들 수 있습니다. 그 결과 작은 필드 정리나 이벤트 이름 변경이 다른 서비스의 이벤트 계약(이벤트 이름과 데이터 구조에 대한 서비스 간 약속)을 깨뜨릴 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 이 글에서 말하는 비용은 “MSA는 복잡하다”는 일반론이 아닙니다. 이벤트 기반 MSA를 운영하면서 이벤트 흐름을 다시 이해하고 검증하는 데 드는 비용입니다. AI가 수정안을 빠르게 만들수록 PR은 빨리 올라오지만, 사람이 다시 이벤트 발행자와 소비자, 스키마, 로그, 테스트를 확인해야 한다면 전체 개발 비용은 줄지 않습니다. 수정은 빨라졌지만, 그 변경을 안전하다고 판단하는 데 드는 비용은 그대로 남기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 이벤트 기반 MSA를 AI와 함께 운영하려면 더 긴 프롬프트만으로는 부족합니다. 사람과 AI가 같은 이벤트 흐름을 보고, 같은 변경 기준을 따라야 합니다. 이 글은 이벤트 기반 MSA를 버리자는 이야기가 아닙니다. AI 시대에도 이 구조를 계속 운영하려면, 나뉜 흐름을 다시 확인할 수 있는 기준과 변경을 안전하게 검증하는 절차를 함께 설계해야 한다는 이야기죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;미리 요점만 콕 집어보면?&lt;/strong&gt;&lt;/h4&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;이벤트 기반 MSA는 장애 격리와 도메인별 책임 분리에 도움이 되지만, 시간이 지날수록 이벤트 이름, 페이로드, 컨슈머, 처리 규칙을 계속 맞춰봐야 하는 비용이 쌓입니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;AI 에이전트는 현재 저장소 안에서는 코드를 빠르게 고칠 수 있지만, 다른 서비스가 그 이벤트를 어떻게 소비하는지 모르면 현재 서비스 안에서만 맞는 수정을 만들 수 있습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;이벤트 기반 MSA를 AI와 함께 운영하려면 더 긴 프롬프트보다, 이벤트 흐름을 볼 수 있는 기준과 변경 전후 확인 절차가 필요합니다. 사람과 AI가 같은 맥락을 보고 같은 기준으로 검증할 수 있어야 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;1. 이벤트 기반 MSA는 왜 AI에게 더 높은 컨텍스트 비용을 만드는가&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;느슨한 연결은 맥락을 없애지 않고 흩어놓는다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이벤트 기반 MSA를 운영할 때 처음 보이는 장점은 분명합니다. 주문은 주문 서비스가, 결제는 결제 서비스가, 재고는 재고 서비스가 맡습니다. 알림이나 배송은 이벤트를 받아 각자 처리합니다. 덕분에 한쪽 장애가 곧바로 전체 요청을 막지 않고, 배포할 때도 책임 범위를 도메인 단위로 나눠볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/image_2.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;문제는 시간이 지나면서 의존성이 다른 형태로 남는다는 점입니다. 직접 호출은 줄었지만, 연결은 사라지지 않습니다. 주문 생성 이벤트(OrderCreated)를 누가 발행하는지, 어떤 컨슈머가 어떤 값을 기대하는지, 실패하면 어디서 재처리하는지로 옮겨갈 뿐입니다. 코드에서 호출 관계가 보이지 않는다고 해서, 서비스들이 서로 독립적으로 움직인다는 뜻은 아닙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 실무에서는 이벤트 하나를 바꿀 때 코드만 보지 않습니다. 팀 컨벤션, 이벤트 스키마, 대시보드, 운영 로그를 함께 확인합니다. 이벤트를 수정한다면 이 이벤트가 어떤 조건에서 발행되는지, 결제와 배송 쪽에서 어떤 값을 기대하는지, 실패했을 때 어디서 재처리되는지까지 맞춰봅니다. 코드 한 줄은 현재 저장소에 있지만, 그 코드가 지켜야 할 약속은 여러 서비스와 운영 도구에 흩어져 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 이벤트 기반 MSA의 느슨한 연결은 양면성을 가집니다. 장애를 격리하고 서비스 책임을 나누는 데는 도움이 되지만 변경을 검토할 때는 흩어진 연결을 다시 모아야 합니다. 이 구조를 운영하려면 “이벤트 흐름을 다시 추적할 수 있는가?”가 더 중요해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;AI가 만든 수정은 빠르지만, 영향 범위는 사람이 다시 확인해야 한다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;AI 에이전트를 유지보수 흐름에 넣으면 이 차이가 더 선명해집니다. AI는 작업 범위로 제공된 저장소와 문서 안에서는 빠르게 수정안을 만듭니다. 조건문을 고치고, 타입을 맞추고, 테스트도 붙입니다. 하지만 같은 이벤트를 받는 결제, 재고, 배송 서비스의 처리 방식까지 함께 아는 것은 아닙니다. 대시보드에서만 확인되는 흐름, 장애 대응 중 정해진 재처리 규칙, 문서화되지 않은 운영 약속은 별도로 넘기지 않으면 작업 맥락에 들어오지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 AI가 만든 수정안은 현재 서비스 안에서는 자연스러워 보여도, 다른 서비스가 기대하던 이벤트 계약을 깨뜨릴 수 있습니다. 예를 들어 이벤트의 필드 하나를 정리하는 변경도, 결제 서비스나 배송 서비스가 그 값을 기준으로 분기하고 있다면 단순한 정리가 아닙니다. 현재 저장소에서는 작은 수정이지만, 전체 이벤트 흐름에서는 계약 변경이 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 문제는 AI가 코드를 못 고치는 데 있지 않습니다. AI가 보지 못한 연결을 사람이 다시 이어 붙여야 한다는 데 있습니다. PR은 빨리 만들어지지만, 리뷰어는 다시 이벤트 문서와 로그, 대시보드, 다른 저장소를 오가며 “이 이벤트가 어디까지 영향을 주는가”를 확인해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 확인 절차를 따로 설계하지 않으면, 이벤트 기반 MSA의 장점은 AI 시대에 리뷰 비용으로 돌아옵니다. 느슨한 연결은 서비스 운영에는 유리하지만, 변경 검증까지 자동으로 해결해주지는 않습니다. AI가 빠르게 코드를 바꿀수록, 그 변경이 전체 이벤트 흐름 안에서 안전한지 확인하는 기준도 함께 준비되어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;2. 코드가 맞아 보이는 것과 실제로 동작하는 것은 다르다&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;이벤트 변경은 기능 수정이 아니라 계약 변경이다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이벤트 기반 MSA에서 조심해야 할 지점은 변경의 크기보다 변경의 성격입니다. 주문 서비스 안에서 보면 단순한 기능 수정처럼 보이는 일이, 다른 서비스 입장에서는 계약 변경이 될 수 있습니다. 주문 생성 이벤트의 필드명을 정리하거나, 상태 값을 조금 더 명확하게 바꾸거나, 이벤트 버전을 올리는 작업이 대표적입니다. 현재 저장소 안에서는 작은 수정입니다. 하지만 그 이벤트를 결제, 재고, 배송, 알림 서비스가 함께 보고 있다면 이야기는 달라집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/image_3.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이벤트는 단순한 알림이 아니라, 서비스 사이의 약속입니다. 주문 서비스는 “주문이 생성됐다”는 사실을 이벤트로 발행하고, 다른 서비스는 그 이벤트 안의 값을 믿고 자기 일을 시작합니다. 결제 서비스는 주문 ID와 결제 금액을 읽고, 재고 서비스는 상품 ID와 수량을 기준으로 재고를 예약합니다. 배송 서비스는 주소나 배송 가능 상태를 보고 후속 처리를 준비할 수 있습니다. 이때 이벤트에 담긴 페이로드가 조금만 달라져도, 컨슈머 입장에서는 기대하던 입력이 바뀐 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI 에이전트는 이런 변경을 꽤 그럴듯하게 처리합니다. 주문 생성 이벤트에 누락된 필드를 추가하고, 이름이 모호한 필드를 정리하고, 테스트가 깨지지 않도록 타입도 맞춥니다. 현재 서비스의 코드만 보면 변경은 깔끔해 보입니다. 단위 테스트가 통과하고, CI의 기본 검증도 통과할 수 있습니다. 그러나 그 검증이 모든 컨슈머의 기대값까지 보장한다는 뜻은 아닙니다. 주문 서비스 안에서는 작은 정리였지만, 다른 서비스 입장에서는 입력 계약이 바뀐 변경일 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 관점이 없으면 리뷰도 잘못된 기준으로 흘러갑니다. 코드가 깔끔한지, 타입이 맞는지, 테스트가 통과하는지만 보게 됩니다. 물론 이 기준은 필요합니다. 하지만 이벤트 기반 MSA에서는 한 가지 질문이 더 필요합니다. “이 변경이 어떤 컨슈머의 기대값을 바꾸는가?” 이 질문에 답하지 못하면 코드 품질은 좋아졌지만 제품 흐름은 깨질 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;이벤트의 문제는 보낸 쪽보다 받는 쪽에서 드러난다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;REST API에서는 요청과 응답이 같은 흐름 안에 있습니다. 주문 서비스가 결제 API를 호출했고 200 응답을 받았다면, 호출한 쪽은 최소한 요청이 대상 서비스에 도달했고 정상 응답이 돌아왔다는 사실을 바로 알 수 있습니다. 실패도 비교적 명확합니다. 응답 코드, 타임아웃, 예외를 기준으로 재시도하거나 롤백하거나 사용자에게 실패를 알릴 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이벤트 기반 구조에서는 이 기준이 그대로 통하지 않습니다. 발행자 입장에서 이벤트를 정상적으로 내보냈다는 사실은 전체 흐름의 성공을 의미하지 않습니다. 이벤트가 브로커에 적재됐는지, 컨슈머가 가져갔는지, 핸들러가 기대한 값으로 처리했는지, 처리 결과가 각 서비스의 상태에 반영됐는지는 별도의 검증 대상입니다. 이벤트 기반 MSA에서 발행 성공은 완료가 아니라 시작에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/image_4.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;주문 생성 이벤트의 페이로드에서 결제 금액 필드를 정리했다고 해보겠습니다. 주문 서비스 로그에는 이벤트가 정상 발행된 것으로 남을 수 있습니다. 발행자 기준에서는 문제가 없어 보입니다. 하지만 결제 컨슈머가 이전 필드명을 기준으로 결제 대기 상태를 만들고 있었다면, 이벤트는 도착했어도 처리 흐름은 멈춥니다. 이때 문제는 주문 서비스의 발행 로그가 아니라, 이벤트를 받은 쪽의 기대값에서 드러납니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 이벤트 기반 MSA의 검증은 발행자 쪽에서 끝나면 안 됩니다. 이벤트가 발행됐는지 확인한 뒤에는 페이로드 변경이 기존 컨슈머와 맞는지, 브로커에 메시지가 적재됐는지, 컨슈머가 실제로 처리했는지까지 이어서 봐야 합니다. 실패했다면 재시도 횟수, 실패 로그, DLQ(Dead Letter Queue, 처리 실패 메시지를 따로 모아두는 큐) 적재 여부도 확인해야 합니다. 마지막으로 주문 상태나 결제 상태처럼 사용자가 보거나 운영자가 확인하는 결과가 기대한 값으로 바뀌었는지 확인해야 합니다. 발행 로그만으로는 전체 흐름이 성공했다고 말하기 어렵기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI 에이전트가 만든 수정안에서는 이 검증의 빈틈이 더 쉽게 생깁니다. AI는 발행자 서비스 안에서 타입을 맞추고 테스트를 붙이는 데는 빠릅니다. 하지만 어떤 컨슈머가 해당 이벤트를 읽는지, 어떤 필드를 기준으로 분기하는지, 실패 메시지가 어느 DLQ로 빠지는지는 별도 맥락을 주지 않으면 알 수 없습니다. 결국 코드만 보면 완성된 PR처럼 보여도, 리뷰할 때는 받는 쪽의 기대값과 처리 결과를 다시 확인해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 이벤트 기반 MSA에서 코드가 맞아 보이는 것과 실제로 동작하는 것은 다릅니다. REST API에서는 호출 성공이 중요한 단서가 되지만, 이벤트 기반 구조에서는 발행 성공만으로 전체 흐름의 성공을 대신할 수 없습니다. 이 기준이 없으면 AI가 줄여준 작성 시간은 리뷰어가 컨슈머, 로그, 대시보드, 다른 저장소를 다시 확인하는 시간으로 바뀝니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;3. AI에게 맡기기 전에, 이벤트 흐름부터 공유해야 한다&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;이벤트 계약은 AI가 읽을 수 있는 기준으로 남겨야 한다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;AI 에이전트에게 이벤트 기반 MSA를 맡길 때 먼저 정리해야 할 질문은 “AI가 얼마나 많은 코드를 볼 수 있느냐”가 아닙니다. 더 중요한 질문은 “AI가 무엇을 기준으로 변경할 수 있느냐”입니다. AI가 어떤 이벤트 계약을 지켜야 하는지, 그 이벤트가 어떤 서비스로 흘러가는지, 수정 이후 무엇을 확인해야 하는지 읽을 수 있어야 합니다. 이 기준이 없으면 AI는 현재 저장소 안에서 가장 그럴듯한 답을 만듭니다. 그래서 이벤트 계약은 사람이 읽는 문서이면서, AI가 작업 전에 참고할 수 있는 기준으로 남아 있어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 이 글은 특정 도구의 설치 방법이나 세부 설정을 깊게 설명하는 글은 아닙니다. 스키마 레지스트리(Schema Registry), 비동기 API 명세인 AsyncAPI, 이벤트 카탈로그(EventCatalog) 외에도 좋은 선택지는 많습니다. 여기서는 이벤트 기반 MSA를 운영하는 팀이 비교적 검토하기 쉬운 오픈소스 몇 가지를 예로 들어, AI에게 어떤 이벤트 맥락을 넘겨야 하는지에 초점을 맞춥니다. 중요한 것은 도구의 기능을 비교하는 것이 아니라, AI가 이벤트 계약과 흐름을 확인할 수 있는 기준을 어디에 둘 것인가입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/image_5.jpg"&gt;&lt;figcaption&gt;&amp;lt;출처: 컨플루언스 공식 문서&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;카프카(Kafka) 환경이라면 &lt;a href="https://docs.confluent.io/platform/current/schema-registry/fundamentals/schema-evolution.html"&gt;&lt;u&gt;스키마 레지스트리(Schema Registry)&lt;/u&gt;&lt;/a&gt;는 페이로드 변경을 먼저 걸러내는 기준이 됩니다. 이벤트에 담기던 값이 사라지거나, 값의 형식이 바뀌거나, 항상 들어오던 값이 어느 순간 비어 있을 수 있게 바뀌면 기존 컨슈머는 같은 이벤트를 받아도 다르게 동작할 수 있습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI가 보기에는 불필요한 값을 정리한 것처럼 보여도, 컨슈머 입장에서는 약속된 입력이 바뀐 셈입니다. Confluent Schema Registry 문서는 스키마가 시간이 지나며 바뀔 수 있고, 새 스키마 버전을 기존 버전과 비교해 호환성 규칙을 적용한다고 설명합니다. 스키마 레지스트리는 이런 변경을 리뷰어의 감각이 아니라 시스템 기준으로 먼저 확인하게 만듭니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/image_6.webp"&gt;&lt;figcaption&gt;&amp;lt;출처: AsyncAPI 공식 문서&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AsyncAPI는 이벤트 계약을 문서와 명세로 남기는 기준이 됩니다. REST API에서 OpenAPI를 보고 요청과 응답의 약속을 확인하듯, 이벤트 기반 구조에서도 어떤 채널로 어떤 메시지가 오가고, 누가 보내고 누가 받는지 확인할 기준이 필요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;a href="https://www.asyncapi.com/docs/reference/specification/v3.1.0"&gt;&lt;u&gt;AsyncAPI 공식 문서&lt;/u&gt;&lt;/a&gt;는 AsyncAPI를 메시지 기반 API를 기계가 읽을 수 있는 형태로 설명하는 명세라고 설명하며, Kafka, MQTT, WebSocket 같은 여러 프로토콜에 적용할 수 있다고 안내합니다. AI에게 “이 이벤트를 수정해줘”라고 맡기는 것과 “이 메시지 구조와 수신자 기대값을 지키면서 수정해줘”라고 맡기는 것은 다릅니다. AsyncAPI는 후자의 기준을 남기는 데 가깝습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/image_7.png"&gt;&lt;figcaption&gt;&amp;lt;출처: EventCatalog 공식 문서&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;EventCatalog는 이벤트 흐름과 소유권을 함께 보는 기준이 됩니다. 스키마는 이벤트에 어떤 데이터가 담기는지 알려주지만, 그 이벤트가 어떤 도메인에서 시작해 어느 서비스로 이어지고 누가 책임지는지까지 설명하지는 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;a href="https://www.eventcatalog.dev/"&gt;&lt;u&gt;EventCatalog 공식 문서&lt;/u&gt;&lt;/a&gt;는 도메인, 서비스, 이벤트, 스키마를 문서화하고 OpenAPI, AsyncAPI, 스키마 레지스트리와 동기화할 수 있다고 설명합니다. 또한 이벤트 기반 시스템에서 무엇이 존재하고 어떻게 연결되는지 찾고, 시각화하고, 안전하게 변경하도록 돕는다는 점을 강조합니다. 이 지점이 이번 글의 핵심과 맞닿아 있습니다. AI에게 필요한 것은 긴 설명이 아니라, 현재 저장소 밖의 이벤트 관계를 확인할 수 있는 기준입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 세 가지는 서로 대체 관계가 아닙니다. 스키마 레지스트리는 페이로드 호환성을 확인하고, AsyncAPI는 이벤트 계약을 명세로 남기고, EventCatalog는 이벤트 흐름과 소유권을 보여줍니다. 팀이 이 모든 것을 한 번에 갖출 필요는 없습니다. 다만 AI 에이전트를 유지보수 흐름에 넣겠다면, 최소한 어떤 방식으로 이벤트 계약과 흐름을 AI에게 넘길지 정해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 기준이 없으면 AI는 현재 저장소 안에서 가장 자연스러운 수정을 만듭니다. 하지만 이벤트 기반 MSA에서 자연스러운 수정과 안전한 수정은 다를 수 있습니다. 페이로드 호환성이 확인되고, 메시지 계약이 남아 있고, 이벤트 흐름과 소유권이 보일 때 리뷰어는 영향 범위를 더 빨리 판단할 수 있습니다. 결국 이벤트 계약을 구조화하는 일은 문서를 늘리는 일이 아닙니다. AI가 만든 변경을 제품 흐름 안에서 검토할 수 있게 만드는 일입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;먼저 정해야 할 것은 팀의 검증 기준이다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;앞에서 몇 가지 선택지를 예로 들었지만, 결국 중요한 것은 특정 도구를 사용하느냐가 아닙니다. 팀이 이벤트 변경을 어떤 기준으로 판단하고, 그 기준을 사람과 AI가 함께 볼 수 있는 형태로 남겨두는지가 더 중요합니다. 처음부터 완성된 체계를 만들 필요는 없습니다. 특정 이벤트가 어디서 발행되고, 어떤 서비스에서 소비되며, 페이로드가 바뀔 때 무엇을 확인해야 하는지 정리하는 것부터 시작할 수 있습니다. 문서, 대시보드처럼 팀이 계속 꺼내볼 수 있는 형태면 충분합니다.중요한 것은 형식이 아니라, 같은 변경을 검토할 때마다 같은 기준을 꺼내볼 수 있느냐입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 기준은 복잡할 필요가 없습니다. 이벤트를 바꾸기 전에 최소한 몇 가지 질문에 답할 수 있으면 됩니다. 이 이벤트는 어느 서비스에서 발행되는가. 어떤 서비스가 이 이벤트를 소비하는가. 페이로드에서 다른 서비스가 기대하는 값은 무엇인가. 이벤트 이름, 상태 값, 필드 의미가 바뀌었을 때 영향을 받는 컨슈머는 누구인가. 수정 후에는 어떤 테스트와 로그, 최종 상태를 확인해야 하는가. 이 질문들이 매번 리뷰어의 머릿속에서만 반복되면 비용은 줄지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3839/thumbnail.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI 에이전트를 사용할 때는 이 기준이 작업 범위를 잡아주는 역할을 합니다. “이 버그를 고쳐줘”라고만 맡기면 AI는 현재 저장소 안에서 가장 자연스러운 수정을 만듭니다. 하지만 팀 내 이벤트 규칙을 함께 넘기면 결과가 달라집니다. 예를 들어 이벤트를 수정할 때 발행자와 주요 컨슈머를 함께 확인해야 한다는 규칙, 페이로드 변경 여부를 표시해야 한다는 규칙, 수정 후 확인해야 할 테스트와 로그를 남겨야 한다는 규칙이 있다면, AI는 그 기준 안에서 움직입니다. AI가 모든 맥락을 스스로 추론하는 것이 아니라, 팀이 정한 검증 기준을 따라 작업하게 되는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 기준은 변경 전과 변경 후로 나눠두면 더 다루기 쉽습니다. 변경 전에는 이벤트의 발행자, 컨슈머, 페이로드, 소유 도메인을 확인합니다. 변경 후에는 주요 컨슈머가 같은 값을 읽을 수 있는지, 대표 흐름의 테스트가 통과하는지, 실패 로그나 DLQ에 메시지가 쌓이지 않는지, 최종 상태가 기대한 대로 바뀌었는지 확인합니다. 이 기준을 문서에만 남겨두지 않고 팀 규칙이나 CI 파이프라인에 연결해두면, AI가 만든 검증되지 않은 변경도 배포 전에 걸러낼 수 있습니다. 코드가 깔끔한지보다 먼저, 이벤트 흐름이 유지되는지 확인할 수 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;중요한 것은 기준을 한 번 정리해두는 데서 끝내지 않는 것입니다. 이벤트 흐름과 운영 방식은 계속 바뀝니다. 새로운 컨슈머가 붙고, 더 이상 쓰지 않는 이벤트가 남고, 페이로드의 의미도 조금씩 달라집니다. 그런데 기준이 오래된 문서에만 남아 있으면 사람도 AI도 잘못된 맥락을 기준으로 판단하게 됩니다. 그래서 이벤트 규칙은 팀이 계속 갱신할 수 있고, AI도 작업 전에 읽을 수 있는 위치에 있어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 기준이 없으면 AI를 붙인 뒤에도 리뷰어는 같은 일을 반복합니다. 이 이벤트가 어디서 발행되는지 찾고, 누가 소비하는지 확인하고, 페이로드가 바뀌었는지 보고, 실패하면 어디서 재처리되는지 다시 확인합니다. AI가 코드를 빠르게 고쳐도 이 확인이 매번 사람에게 남으면 전체 비용은 줄지 않습니다. 오히려 PR이 빨리 올라오는 만큼 승인해야 할 변경은 늘어나고, 리뷰어는 더 자주 같은 맥락을 복원해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대로, 팀의 이벤트 규칙이 정리되어 있으면 AI가 만든 수정안을 보는 방식이 달라집니다. 리뷰어는 처음부터 이벤트 흐름을 다시 그리지 않아도 됩니다. 어떤 이벤트가 영향을 받았는지, 어떤 컨슈머를 확인해야 하는지, 어떤 테스트와 로그가 있어야 안전하다고 볼 수 있는지 바로 판단할 수 있습니다. 이때 AI는 단순히 코드를 빨리 쓰는 도구가 아니라, 팀이 정한 기준 안에서 변경을 수행하는 실행자가 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 AI 시대의 이벤트 기반 MSA에 필요한 것은 더 많은 선택지가 아니라, 사람과 AI가 함께 따를 수 있는 검증 기준입니다. 비용은 서비스를 나눴다는 사실보다, 나뉜 흐름을 매번 다시 확인하는 과정에서 커집니다. 이 과정을 팀 규칙으로 고정하고 배포 전 검증 과정에 연결해두면, 검증되지 않은 이벤트 변경을 더 일찍 걸러낼 수 있습니다. 서비스를 나눌 수 있는가보다 중요한 질문은, 나눈 뒤에도 변경을 끝까지 검증할 수 있는가입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며: 나눌 수 있는가보다, 검증할 수 있는가&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이벤트 기반 MSA는 버려야 할 구조가 아닙니다. 장애를 격리하고, 도메인별 책임을 나누고, 후속 작업을 독립적으로 확장하는 데 여전히 유효한 선택입니다. 다만 AI 에이전트가 개발 과정에 들어오면 이 구조의 비용이 더 선명하게 드러납니다. AI는 코드를 빠르게 바꿀 수 있지만, 보이지 않는 이벤트 흐름까지 자동으로 책임지지는 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 이벤트 기반 MSA를 선택하기 전에 확인해야 할 질문은 달라져야 합니다. “이 기능을 서비스로 나눌 수 있는가”보다 “나눈 뒤에도 변경 영향을 추적할 수 있는가”를 먼저 물어야 합니다. 이벤트의 소유권, 페이로드 변경 기준, 컨슈머 영향 범위, 실패 시 재처리 경로, 로그와 추적 기준이 없다면 서비스 분리는 운영 비용을 줄이는 선택이 아니라 검토 비용을 키우는 선택이 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI 시대의 아키텍처 선택은 구현 가능성보다 검증 가능성에 가까워집니다. 느슨한 연결을 선택했다면, 그 흐름을 다시 볼 수 있는 기준도 함께 설계해야 하죠. 사람과 AI가 같은 이벤트 맥락을 보고, 같은 규칙으로 변경을 검토하고, 같은 기준으로 배포를 승인할 수 있을 때, 이벤트 기반 MSA는 비용이 아니라, 속도와 신뢰를 함께 만드는 구조가 될 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>“이 정도면 직접 만들겠는데?” 바이브 코딩으로 유료 앱 대체하기</title><link>https://yozm.wishket.com/magazine/detail/3838</link><description>평소 만족스럽게 쓰던 유료 루틴 앱에 아쉬움이 쌓이던 어느 날, '이 정도면 직접 만들 수 있겠는데?'라는 생각을 바로 테스트해봤습니다. Obsidian과 Claude Code, 몇 가지 플러그인으로 가중치 루틴 체크, 월간·연간 대시보드, 루틴 메모까지 붙인 개인용 도구를 만들었습니다. 가장 큰 난관이던 기존 데이터는 스크린샷을 생성형 AI에게 읽혀 옮겼죠. 루틴 관리가 쉬워진 건 물론, 만드는 게 쉬워진 시대에 직접 도구를 만들며 배운 점도 생겼습니다. 무엇을 왜 만들지에 대한 이야기를 함께 정리했습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3838</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;저는 평소 루틴 관리를 위해 유료 앱을 하나 쓰고 있었습니다. 기능 자체는 꽤 만족스러웠습니다. 돈이 아깝다는 생각이 들 정도도 아니었고, 오히려 “이 정도면 잘 만든 앱이지” 쪽에 가까웠죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 요즘 들어 쓰면 쓸수록 작은 아쉬움들이 계속 쌓였습니다. 이를테면 루틴마다 제가 중요하게 생각하는 무게가 다른데, 이 앱은 모든 체크를 똑같이 취급한다는 점이 그랬습니다. 이를테면 운동 1시간과 물 마시기 한 번을 같은 체크로 두기 아쉬웠습니다. 또, 이번 달을 내가 어떤 흐름으로 보내고 있는지, 나아가 연 단위로 얼마나 꾸준히 해왔는지를, 제 방식대로 보고 싶다는 생각도 점점 커졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예전 같았으면 그냥 아쉽다 하고 넘어갔을 것 같습니다. 그런데 요즘은 좀 다릅니다. AI 덕분에 무언가를 직접 만들어보는 진입장벽이 확실히 낮아졌으니까요. 예전에는 개인용 도구 하나 만들자고 해도 괜히 구조부터 고민해야 했습니다. 파일 구조는 어떻게 잡을지, 상태 관리는 어떻게 할지, 나중에 확장하려면 어떤 방식이 좋을지. 만들기도 전에 피곤해졌죠. 반면 지금은 필요한 기능만 머릿속에 있으면 일단 시작해볼 수 있습니다. 완벽한 설계보다 빠른 구현이 더 자연스러운 시대가 된 느낌이랄까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번 작업도 그런 흐름으로 시작했습니다. 어느 날 오후에 문득 “이 정도면 직접 만들 수 있겠는데?”라는 생각이 들었고, 그 생각을 바로 테스트해보기로 한 겁니다. 거창하게 기획 문서를 쓰지도, 화면 설계를 하지도 않았습니다. 기획을 위해 정말 필요한 것만 적었습니다. 루틴 체크가 되어야 하고, 모바일과 데스크톱에서 둘 다 써야 하고, 월간 진행 현황과 연간 히트맵 정도는 보고 싶고, 메모도 붙일 수 있었으면 좋겠다. 딱 그 정도였습니다. 그리고 바로 Obsidian과 Claude를 붙여서 만들기 시작했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;특히 재밌었던 건, 서비스를 개발한다기보다 “내가 쓰고 싶은 도구를 만든다”는 생각으로 시작했다는 점입니다. 직접 만들다 보니 이 차이가 생각보다 크게 다가왔습니다. 남들이 다 써야 하는 제품을 만들 때는 고려해야 할 게 정말 많지만, 개인용 도구는 기준이 명확하니까요. 제가 매일 쓰면 성공입니다. 제가 보기 편하면 잘 만든 겁니다. 그래서 오히려 더 빠르게 결정할 수 있었고, 훨씬 덜 부담스러웠습니다. 아마 이게 바이브 코딩의 가장 큰 매력 중 하나 아닐까 싶습니다. 완성도 높은 제품을 목표로 하기보다, 일단 내가 만족할 결과물을 빠르게 만드는 데 정말 잘 맞는 방식이니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;Obsidian + Claude Code로 구현한 핵심 기능&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3838/image2.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가, Gemini로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번에 이걸 만들면서 제게 가장 중요했던 건 &lt;strong&gt;내가 매일 부담 없이 쓸 수 있는지&lt;/strong&gt;였습니다. 개인용 도구는 이 기준이 정말 중요합니다. 남들에게 보여주기 위한 서비스가 아니라, 제가 아침에 열고 밤에 다시 보는 도구니까요. 그래서 처음부터 기술적인 화려함보다는, 익숙한 환경 안에서 빠르게 만들어 계속 손이 갈만한 쪽을 택했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;Obasidian과 Claude Code를 선택한 이유&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;그 기준에서 Obsidian은 꽤 자연스러운 선택이었습니다. 원래도 자주 쓰던 작업 환경이었고, 무엇보다 텍스트 기반으로 데이터를 직접 관리할 수 있다는 점이 좋았습니다. 루틴 기록이라는 게 결국 매일 쌓이는 생활 데이터인데, 이걸 특정 서비스 안에만 가두기보다 제가 원하는 구조로 쌓아두고 싶다는 마음이 있었거든요. Obsidian은 노트, 메모, 템플릿, 데이터 조회가 한 공간 안에서 이뤄지니까 이런 용도에 잘 맞았습니다. 즉, 앱을 하나 새로 만든다기보다, &lt;strong&gt;원래 쓰던 작업 공간을 제 생활 데이터에 맞게 확장한다&lt;/strong&gt;는 느낌이 더 강했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Claude Code를 사용한 이유도 비슷합니다. 이번 작업은 정교한 제품 설계보다, 필요한 기능을 빠르게 붙이고 바로 써보는 흐름이 훨씬 중요했습니다. 그럴 때는 코드 한 줄 한 줄을 처음부터 직접 치는 방식보다 제가 원하는 동작을 설명하고 결과를 보면서 바로 수정해나가는 방식이 훨씬 잘 맞았습니다. 특히 이번에는 단순히 텍스트를 정리하는 수준을 넘어 대시보드나 시각화처럼 손이 더 많이 가는 부분이 있었는데요. 그런 부분을 Claude Code가 JavaScript로 빠르게 구현해주니까 개발 속도가 확실히 빨랐습니다. 예전 같았으면 나중에 시간 나면 붙이자고 넘겼을 기능들을 이번엔 흐름이 끊기기 전에 바로 붙일 수 있었던 거죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;활용한 Obasidian 플러그인 3가지&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;플러그인도 소수만 쓰기로 했습니다. 이번에 실제로 사용한 건 &lt;strong&gt;Git 플러그인, Templater, Dataview&lt;/strong&gt; 정도였고, 나머지 핵심 인터랙션이나 대시보드 같은 부분은 Claude Code가 JavaScript로 구현해줬습니다. 그리고 이 방식이 꽤 마음에 들었습니다. Obsidian 플러그인을 이것저것 많이 얹어서 복잡하게 만드는 방식보다, 기본적인 데이터 흐름은 단순하게 가져가고, 진짜 필요한 부분만 직접 구현하는 쪽이 더 제 스타일에 맞았거든요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;역할도 명확했습니다. &lt;strong&gt;Git 플러그인&lt;/strong&gt;은 여러 기기에서 데이터를 이어 관리하는 데 큰 도움이 됐습니다. 회사 PC, 개인 맥북, 모바일을 오가며 써야 했기 때문에, 기록이 한 군데에만 있으면 의미가 없었거든요. 저는 원래도 개인용 비공개 저장소를 관리하고 있었기에, 기기별 작업 환경은 분리하며 데이터는 자연스럽게 이어갈 수 있었습니다. 루틴 앱처럼 매일 쓰는 도구에 정말 중요한 접근성은 이처럼 Git 플러그인이 해소해줬습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;Templater&lt;/strong&gt;는 반복 입력을 줄이는 데 유용했습니다. 루틴 기록은 하루 이틀 쓸 땐 괜찮은데, 며칠만 지나도 포맷이 흐트러지기 쉽습니다. 메모 형식이 조금씩 달라지고, 항목 순서가 바뀌고, 그러다 보면 나중에 조회할 때도 애매해지죠. 이를 마고자 Templater를 붙여두니 기본 구조를 일정하게 유지하기가 훨씬 쉬웠습니다. 매일 같은 틀 안에서 기록할 수 있으니 입력 부담도 줄고, 뒤에서 데이터를 다룰 때도 훨씬 편해졌습니다. 별거 아닌 것 같지만, 이런 반복 입력 자동화가 있어야 오래 쓸 것이라고 생각했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;Dataview&lt;/strong&gt;는 이 기록들을 다시 봐야할 때 쓰기 좋았습니다. 루틴 데이터는 쌓이는 것만으로 별 의미가 없습니다. 결국 중요한 건 내가 이걸 어떻게 다시 읽어낼까 하는 거죠. Dataview 덕분에 루틴별 기록을 조회하거나, 특정 기간의 흐름을 정리하거나, 메모를 모아서 다시 보는 작업이 꽤 수월해졌습니다. 기본적으로는 이 플러그인이 데이터 조회 레이어를 맡아준 셈이고, 그 위에서 필요한 시각화나 대시보드 성격의 기능은 Claude Code가 JavaScript로 붙여준 구조에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;핵심 기능 개발하기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;1. 가중치를 더한 루틴 체크&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기능 측면에서는 가장 먼저 루틴 체크부터 만들었습니다. 다만 단순히 체크만 하는 구조로 끝내고 싶진 않았습니다. 기존 루틴 앱을 쓰면서 가장 아쉬웠던 게, 모든 루틴이 똑같은 1회 체크로 처리된다는 점이었거든요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제 삶에서는 루틴마다 무게가 다릅니다. 물 마시기 한 번과 1시간 운동을 같은 일로 취급할 수는 없죠. 그래서 루틴별로 가중치를 둘 수 있게 만들었고, 제가 생각하는 “충만한 하루”를 제 기준대로 다시 설계했습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3838/image4.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 부분은 만들고 나서도 꽤 만족스러웠습니다. 남이 정의한 하루가 아니라, &lt;strong&gt;내가 납득하는 하루의 기준&lt;/strong&gt;을 직접 만들었다는 느낌이 들었거든요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;2. 월/연간 대시보드&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그다음은 대시보드였습니다. 사실 이 부분이 기존 서비스 대비 가장 차별점이 컸던 것 같습니다. 저는 단순히 오늘 루틴을 몇 개 완료했는지보다, 이번 달 전체 흐름이 어떤지, 연간으로 보면 어떤 패턴이 보이는지가 더 궁금한 사람이거든요. 그래서 월간 진행 현황과 연간 히트맵을 볼 수 있는 대시보드를 붙였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3838/image3.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 중요한 건, 이걸 Obsidian 플러그인만으로 해결하려고 하지 않았다는 점입니다. 조회는 Dataview로 하고, 진짜 보고 싶은 화면은 Claude Code가 JavaScript로 구현해주는 식으로 갔더니 훨씬 유연했습니다. 덕분에 원래 있는 기능에 나를 맞추는 게 아니라, &lt;strong&gt;내가 보고 싶은 화면을 직접 만드는&lt;/strong&gt; 쪽으로 갈 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;3. 루틴 메모&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;루틴별 메모 기능도 넣었습니다. 이건 사소해 보여도 의외로 중요했습니다. 루틴은 결국 맥락의 영향을 많이 받는데요. 왜 오늘은 잘 됐는지, 왜 어제는 실패했는지, 이런 맥락은 단순 체크만으로는 잘 안 보입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그럴 때는 짧게라도 메모를 남겨두는 것이 좋습니다. “회의가 길어져서 운동을 못 했다”, “아침 기상에 성공했더니 다른 루틴도 연쇄적으로 잘 됐다” 같은 기록을 쌓으면, 그때부터는 앱이 체크 로그가 아니라 생활 데이터가 됩니다. 나중에 돌아보면 오히려 체크 횟수보다 이런 메모가 더 많은 걸 알려줄 때도 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3838/image6.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그리고 여기서 한 단계 더 갔습니다. 루틴 데이터와 메모가 이미 쌓이고 있으니, 이걸 기반으로 Claude에게 다시 내 생활 패턴을 물어볼 수 있게 만든 겁니다. 예를 들면 어떤 루틴이 다른 루틴과 같이 성공하는 경향이 있는지, 이번 달 흐름이 무너진 시점이 언제인지, 메모에서 반복적으로 등장하는 패턴이 뭔지 같은 걸 질문하는 식이었죠. 결과는 따로 insights 폴더에 모아두도록 했고요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 기능을 붙이고 나니까, 단순히 기록하는 앱을 만든 게 아니라 &lt;strong&gt;기록을 다시 읽고 해석하는 도구&lt;/strong&gt;를 만든 느낌이 들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3838/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결과적으로 이번 구성은 Obsidian 플러그인을 잘 조합해서 만든 루틴 앱이라기보다, &lt;strong&gt;Obsidian을 데이터 기반으로 삼고, Git·Templater·Dataview 같은 플러그인으로 뼈대를 세운 다음, 부족한 부분은 Claude Code가 JavaScript로 직접 메운 개인용 도구&lt;/strong&gt;에 더 가까웠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 방식이 꽤 마음에 들었습니다. 플러그인에 너무 많이 기대지 않으면서도, 필요한 건 빠르게 구현할 수 있었거든요. 만들수록 제가 원했던 건 그냥 루틴 체크 앱이 아니었구나 싶었습니다. 체크를 넘어서, 제 하루를 제가 원하는 구조로 기록하고 다시 해석할 수 있는 도구가 필요했던 거죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;가장 큰 난관이었던 데이터 마이그레이션&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;물론 즐거운 일만 있었던 건 아니었습니다. 이번 작업에서 가장 어려웠던 건 의외로 구현이 아니었습니다. 루틴 체크 기능을 만들고, 대시보드를 붙이고, 메모 구조를 잡는 것까지는 생각보다 순조로웠으니까요. 진짜 문제는 그다음부터였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 기존에 쓰던 유료 루틴 앱에는 이미 아주 많은 데이터가 쌓여 있었습니다. 올해 기록만 해도 적지 않았고, 단순 체크만 있는 것도 아니었습니다. 날짜별 체크 이력에 메모들도 붙어 있었죠. 새로 만든 도구가 아무리 마음에 들어도, 이 데이터를 못 옮기면 결국 다시 원래 서비스로 돌아갈 가능성이 높았습니다. 시작은 재밌게 했는데, 정작 갈아타는 데 실패하는 가장 흔한 패턴이 딱 이런 경우니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3838/image5.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;문제의 본질을 챙기기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;처음엔 뭐, 조금씩 손으로 옮기면 되지 않을까 하는 생각도 해봤는데요, 바로 포기했습니다. 이런 종류의 수작업은 시작하는 순간 끝이 보입니다. 하루 이틀은 할 수 있겠죠. 하지만 월별로 쌓인 체크 기록과 메모를 계속 다시 입력하는 건, 프로젝트에 대한 애정을 증발시키기 아주 쉽습니다. 특히 루틴 데이터는 건수가 많기에, 얼핏 단순해 보여도 날짜 하나만 틀리면 흐름이 다 망가집니다. 저 역시 이걸 하다가 원래 앱으로 돌아갈 생각을 할 게 너무 뻔했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 방향을 바꿨습니다. 입력 노동으로 문제를 두면 답이 없지만, 데이터 추출로 보면 얘기가 달라질 거라 생각했거든요. 그렇게 두고 보니 아주 단순한 해결책이 떠올랐습니다. &lt;strong&gt;“이거 스크린샷으로 읽히면 되는 거 아닌가?”&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존 앱에는 월별 통계 화면이 있었고, 여기에는 루틴 체크 달력과 메모가 함께 나타납니다. 사람 눈으로 봐도 이미 정보가 거의 다 정리돼 있는 화면이었던 거죠. 그런 데이터를 굳이 제가 하나씩 다시 입력할 이유가 없었습니다. 필요한 건 화면을 잘 정리해서 넘기는 일, 그 화면을 새 포맷으로 변환해주는 일뿐이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;방법은 꽤 단순했습니다. 먼저 기존 앱의 월별 통계 화면을 캡처했습니다. 이걸 월별로 Migration 폴더에 정리해두고, Claude에게 각 루틴이 어떤 기준으로 체크되는지 설명했습니다. 예를 들어 어떤 기호가 체크 완료인지, 메모는 어떤 식으로 읽어야 하는지, 결과를 어떤 형식으로 정리하면 되는지 같은 규칙을 먼저 잡아준 거죠. 그다음엔 그 스크린샷을 읽고, 제가 쓰는 Obsidian 구조에 맞게 마이그레이션해달라고 요청했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;코드를 잘 짜기보다 지시를 잘 내리기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이 과정이 재밌었던 이유는 코드를 짜는 느낌보다 작업자에게 지시를 잘 내려 문제를 해결한 느낌에 가까웠단 점입니다. 예전에는 이런 작업을 하려면 OCR을 붙이거나, 데이터를 긁어오거나, 포맷 파서를 따로 짜는 쪽으로 생각했을 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 이번에는 공학적으로 접근하기보다, 쉬운 방식으로 접근했습니다. 화면을 보여주고, 규칙을 설명하고, 결과를 검수하는 방식을 쓴 거죠. 어떻게 보면 개발이라기보다 작업 파이프라인을 설계한 셈입니다. 바이브 코딩이 재밌는 이유도 이런 데 있는 것 같습니다. 예전 같으면 “기술적으로 어떻게 풀지?”부터 고민했을 일을 지금은 “가장 덜 귀찮고 빨리 끝나는 방식이 뭘까?”로 접근하게 되니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결과는 솔직히 기대 이상이었습니다. 몇 분 안에 대부분의 데이터가 정리됐고, 정확도도 꽤 높았습니다. 저는 중간에 날짜가 꼬이거나, 메모가 엉뚱한 곳에 붙거나, 체크 기준을 잘못 읽는 일이 많이 생길 줄 알았습니다. 그런데 물론 100% 완벽하다고 하긴 어렵지만, 체감상으로는 충분히 쓸만한 수준으로 데이터가 옮겨졌습니다. 무엇보다 이 정도면 손으로 다시 입력하는 것보다 압도적으로 낫다는 확신이 빨리 들었습니다. 이 확신이 굉장히 중요했습니다. 이번 마이그레이션 작업은 완벽함보다도, 내가 이 일을 끝까지 밀고 갈 수 있을지가 더 중요하니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;중간에 퍽 인상 깊은 일도 있었습니다. 제가 월별 데이터를 잘못 넣은 적이 있었는데, Claude가 그걸 읽다가 “이건 이전 달 데이터로 보인다”는 식으로 먼저 걸러낸 겁니다. 사람이 대충 넣은 걸 모델이 맥락으로 잡아내는 걸 보니 단순 추출을 넘어 꽤 실용적인 작업 보조라는 생각이 들었습니다. 보통은 제가 AI가 만든 결과물을 의심하면서 검수하는 그림을 생각하는데, 그 반대로 제가 대충 넘긴 걸 오히려 AI가 한 번 더 걸러준 거니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 올해 제가 쌓아온 8개 루틴의 체크 데이터와 메모를 거의 다 옮길 수 있었습니다. 전체 작업 시간도 아주 길지 않았습니다. 솔직히 이 마이그레이션이 수작업이었으면, 아마 중간에 포기했을 가능성이 높습니다. 루틴 앱을 새로 만든 성취감과 데이터를 옮기는 지루함은 완전히 다른 문제니까요. 그런데 이번에는 귀찮고 반복적인 이전 작업을 꽤 현실적인 수준으로 줄일 수 있었고, 덕분에 “만든다”에서 끝나는 게 아니라 “갈아탄다”까지 갈 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;생성형 AI를 반정형 데이터 마이그레이션에 쓰기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이번 경험으로 크게 느낀 게 하나 있습니다. 많이들 생성형 AI를 코드 작성 도구로 먼저 떠올리는데, 실제로는 이런 &lt;strong&gt;반정형 데이터 마이그레이션&lt;/strong&gt;에서 더 큰 효율을 체감할 수도 있겠다는 점입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이미 화면 형태로 정리된 정보, 사람이 보면 금방 이해할 수 있지만 손으로 옮기기 너무 귀찮은 정보, 규칙은 있지만 완전히 정형화돼 있지는 않은 정보들 말이죠. 이런 작업은 원래 애매하게 사람 시간을 많이 먹는 영역이었는데, 지금은 꽤 높은 수준으로 위임할 수 있게 된 것 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마찬가지로 이번 마이그레이션은 단순히 데이터를 옮긴 작업을 넘어 제가 이 프로젝트를 진짜로 실사용 단계까지 밀고 갈 수 있게 만든 핵심 과정이었습니다. 새 도구를 만드는 건 재밌습니다. 하지만 기존 도구를 떠나는 건 완전히 다른 문제입니다. 적어도 이번 프로젝트에서 그 간극을 잡아준 건 스크린샷과 생성형 AI를 이용한 마이그레이션 방식이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;직접 유료 앱을 대체하고 얻은 결론&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;모든 작업이 끝나고, 기존에 쓰던 유료 루틴 앱의 구독을 해지했습니다. 물론 연 3만 원대 금액이 아주 부담이 큰 건 아니었습니다. 사실 그 정도면 잘 만든 서비스를 편하게 쓰는 비용으로 충분히 낼 수 있는 돈이죠. 그만큼 괜찮은 앱이라 처음엔 굳이 이걸 직접 만들어야 하나 싶은 마음도 있었습니다. 그런데 막상 만들어 며칠 써보니까 생각이 꽤 달라졌습니다. 단순히 돈을 아낀 것보다 &lt;strong&gt;이제야 진짜 제 방식에 맞는 도구를 가졌다&lt;/strong&gt;는 만족감이 훨씬 컸거든요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;진짜 내 방식에 맞는 도구&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;제 입장에서 가장 큰 변화는 대시보드 활용입니다. 기존 서비스의 대시보드도 충분히 괜찮았지만, 어디까지나 그건 서비스가 정의한 방식으로 보여주는 정보였습니다. 반면 이번에는 제가 궁금한 흐름을, 제가 보고 싶은 방식으로 바로 볼 수 있었습니다. 어떤 루틴이 제 일상에서 더 중요한지, 이번 달에 루틴이 무너진 시점은 언제였는지, 연간 기준으로 보면 어떤 패턴이 반복되는지 같은 것들이 훨씬 더 직관적으로 보였습니다. 남이 잘 만들어준 도구를 쓰는 것과 내가 정말 보고 싶던 화면을 직접 구현한 도구를 쓰는 건 생각보다 차이가 컸습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;데이터를 제가 직접 관리하는 점도 만족스럽습니다. 이건 써보기 전에는 생각보다 덜 중요한 느낌인데, 막상 경험해보니 무시하기 어렵더라고요. 특정 서비스에 제 중요한 기록이 종속되지 않고, 제가 이해할 수 있는 구조로 쌓아, 필요하면 가공해 다시 읽고, Claude에게 질문까지 던질 수 있다는 점이 좋았습니다. 이 프로그램이 어느 순간부터는 기록 도구라기보다 &lt;strong&gt;생활 데이터 실험실&lt;/strong&gt; 같은 느낌도 들기 시작했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;작고, 빠르고, 바로 쓸 수 있는 실험&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;물론 모두에게 이 방식을 그대로 추천하긴 어렵습니다. 비개발자 입장에서는 여전히 진입장벽이 있습니다. Obsidian을 다룰 줄 알아야 하고, Git으로 동기화하는 흐름도 이해해야 하고, 중간에 꼬이면 직접 고쳐야 하니까요. 누군가에게는 그냥 월 구독료나 연 구독료를 내고 검증된 서비스를 계속 쓰는 편이 훨씬 합리적일 수 있습니다. 실제로도 그 선택이 더 맞는 사람은 많을 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 이런 게 익숙한 개발자라면 또 다릅니다. 저는 이런 개인용 도구 제작이 개발자에게 꽤 좋은 실험이라고 생각합니다. 작고, 빠르고, 바로 쓸 수 있기 때문입니다. 거창한 사이드 프로젝트는 시작부터 부담이 큽니다. 기획도 해야 하고, 화면도 만들어야 하고, 중간에 지치기도 쉽죠. 반면 개인용 도구는 문제 정의가 명확합니다. 내가 불편하면 시작하고, 내가 만족하면 끝입니다. 게다가 완성 후 바로 실사용으로 이어지기 때문에, 작은 개선이 곧바로 체감됩니다. 이게 생각보다 중독성이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;낮아진 진입장벽만큼 중요한 것&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이번 일을 하면서 저는 요즘 제품 개발의 진입장벽이 정말 많이 낮아졌다는 걸 다시 느꼈습니다. 적어도 대규모 서비스가 아니라면, 이제 개발할 수 있는지 없는지 여부는 예전만큼 큰 문제가 아닐 수도 있겠다는 생각이 들었습니다. 물론 여전히 잘 만드는 건 어렵고, 안정적으로 운영하는 건 더 어렵습니다. 하지만 적어도 작게 만들어서 직접 써보는 단계까지 가는 건 훨씬 쉬워졌습니다. 예전에는 아이디어가 있어도 머릿속에만 남아 있던 것들이, 지금은 꽤 높은 확률로 실제로 작동하는 무언가가 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 오히려 더 중요해진 건 개발 자체보다 &lt;strong&gt;무엇을 만들지&lt;/strong&gt;, &lt;strong&gt;왜 그걸 만들어야 하는지&lt;/strong&gt;, &lt;strong&gt;계속 쓰게 만들려면 어떤 구조여야 하는지&lt;/strong&gt; 같은 문제인 것 같습니다. 만드는 건 점점 쉬워지고 있습니다. 대신 아무거나 만들면 안 되고, 진짜 내 문제를 해결해 줄 영역을 골라야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그와 함께 이제 제품 영역의 진짜 싸움은 아이디어와 활용 방식, 더 나아가 마케팅 쪽으로 넘어가고 있다는 생각도 들었습니다. 개인용 도구는 내가 쓰면 그만이지만, 그걸 제품으로 만들고 누군가에게 쓰게 만드는 건 또 완전히 다른 문제니까요. 대규모 서비스가 아니면 개발 자체는 예전보다 훨씬 덜 위협적인 장애물이 됐습니다. 대신 이제는 “무엇을 왜 만들 것인가”가 훨씬 더 중요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이제 저는 전보다 가볍게 무언가 만들어 볼 생각을 합니다. 꼭 앱을 새로 출시하겠다는 거창한 목표가 아니어도 괜찮습니다. 내가 매일 반복하는 귀찮은 일, 기존 도구를 쓰면서 계속 아쉬웠던 부분, 내 방식대로 하고 싶었던 지점들. 그런 것들이 전부 작은 프로젝트의 출발점이 될 수 있겠다고 느낍니다. 바이브 코딩의 진짜 재미도 거기에 있는 것 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번에 유료 루틴 앱 하나를 대체해본 건, 어쩌면 아주 작은 사례일 뿐입니다. 그런데 저는 오히려 그래서 더 의미가 있다고 느꼈습니다. 세상을 바꿀 서비스를 만든 것도 아니고, 대단한 SaaS를 출시한 것도 아닙니다. 그냥 제가 매일 쓰는 도구 하나를 제 손에 맞게 다시 만든 것뿐이죠. 그런데 그것 하나만으로도, 지금 개발자에게 열린 가능성이 전보다 훨씬 많다는 걸 분명히 느낄 수 있었으니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>쿠버네티스 7개 주요 게이트웨이 기술 검증(Poc) 다시 하기 (feat. Ingress NGINX 은퇴)</title><link>https://yozm.wishket.com/magazine/detail/3837</link><description>2026년 3월, 쿠버네티스에서 가장 널리 쓰이던 Ingress NGINX의 지원이 공식 종료됐습니다. IngressNightmare(CVE-2025-1974) 취약점까지 겹치며 Gateway API 이전은 더 미룰 수 없는 과제가 됐죠. 그런데 앞선 검증에서 F등급을 줬던 Kong과 Traefik을 같은 구현체 7종으로 다시 측정해 보니, 이번엔 모두 기준을 통과했습니다. 문제는 제품이 아니라 측정 방식과 조건에 있었던 셈입니다. 새 순위표와 함께, 스스로 내린 결론을 의심하고 채점 기준을 처음부터 다시 세운 재측정 과정을 기록했습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3837</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;Gateway API v1.4 재측정기&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;2026년 3월, 쿠버네티스에서 가장 널리 사용되던 Ingress NGINX의 지원이 공식적으로 &lt;a href="https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/"&gt;종료&lt;/a&gt;됐습니다. 이제는 실제로 대응해야 할 과제가 된 것입니다. 여기에 ingress-nginx의 설정 주입 방식에서 비롯된 IngressNightmare&lt;span style="color:#999999;"&gt;(&lt;/span&gt;&lt;a href="https://kubernetes.io/blog/2025/03/24/ingress-nginx-cve-2025-1974/"&gt;CVE-2025-1974&lt;/a&gt;&lt;span style="color:#999999;"&gt;, CVSS 9.8)&lt;/span&gt; 같은 심각한 보안 취약점까지 드러나면서, Gateway API로의 이전은 더 이상 미룰 수 없는 과제가 됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;사실 작년에 이를 위한 &lt;a href="https://yozm.wishket.com/magazine/detail/3559/"&gt;실험기&lt;/a&gt;를 한 차례 정리한 적이 있습니다. 특히, 당시에는 Gateway API 구현체 7종을 비교하면서, Kong과 Traefik 두 구현체가 기본 테스트를 통과하지 못한다고 분석했습니다. 그런데 실제 이전 시점이 다가오며 측정 결과를 다시 살펴보니, 측정 방식과 그 결과를 둘러싼 조건을 다시 볼 필요가 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;동일한 7개 구현체를 처음부터 다시 측정하기로 했고, 두 구현체 모두 이번에는 테스트를 통과했습니다. 작년 실험 결과는 결국 제품 자체의 한계가 아니라, 제품을 둘러싼 측정 환경과 측정 방식에 문제가 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 이 글은 새로운 순위표를 소개하기보다, 측정 과정을 어떻게 다시 설계했고 그 과정에서 무엇을 확인했는지 기록하는 데 목적이 있습니다. 왜 다시 기술 성능을 측정하게 됐는지, 채점 방식을 어떻게 새롭게 구성했는지, 그리고 그 과정에서 무엇을 배웠는지를 차례대로 살펴보겠습니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;왜 다시 측정하기로 했나&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;올해 초 작성한 글(&lt;a href="https://yozm.wishket.com/magazine/detail/3559/"&gt;쿠버네티스 7개 주요 게이트웨이 기술 검증하기&lt;/a&gt;)에서는 Ingress NGINX의 지원 종료 후에 어떤 Gateway API가 적합한지를 알아보았었습니다. 시장에서 주로 사용되는 7개 구현체에 17개 테스트를 각각 100회씩 실행하고, 통과율을 기준으로 등급을 매겼습니다. 통과율이 높은 구현체는 A를 받았고, 통과하지 못한 구현체는 가장 낮은 F등급으로 기록됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;특히 눈에 띈 것은 Kong과 Traefik이었습니다. &lt;strong&gt;두 구현체 모두 가장 낮은 F등급&lt;/strong&gt;을 받았기 때문입니다. Kong은 라우트가 동기화되지 않아 “no Route matched” 오류가 발생했고, Traefik은 “404 page not found”​와 “Gateway not ready”​를 반환했습니다. 결과만 보면, 둘 다 기본 라우팅조차 통과하지 못한 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 볼수록 이 결과를 기술적으로 한 번 더 검토해 볼 필요가 있다고 느껴졌습니다. Kong은 API 게이트웨이 시장에서 오랫동안 검증된 제품이며, Traefik 역시 많은 팀이 프로덕션 환경에서 사용하고 있습니다. 그런 제품이 기본 라우팅조차 통과하지 못했기에, 제품 자체의 결함 외에 설치 방식이나 측정 절차에 문제가 있었을 가능성도 충분했습니다. 실제 이전을 준비해야 하는 시점이 다가온 만큼, 이 가능성을 그대로 둘 수는 없었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;실험을 미룰 수 없었던 3가지 이유&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;무엇보다 재측정을 결정하게 된 데에는 세 가지 구체적인 이유가 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;첫 번째는, 이제 정말로 이전을 결정해야 하는 시기&lt;/strong&gt;가 왔기 때문입니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;작년에는 예고에 그쳤던 Ingress NGINX 지원 종료가 2026년 3월 실제로 일어났습니다. 더 이상 마이그레이션을 미룰 수 없는 상황이 된 만큼, 그 판단의 근거가 되는 측정 결과에도 문제가 없는지 다시 점검할 필요가 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;두 번째로, &lt;strong&gt;보안 측면에서도 ingress-nginx를 떠날 이유가 분명해졌기 때문&lt;/strong&gt;입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;ingress-nginx의 &lt;code&gt;configuration-snippet&lt;/code&gt;, &lt;code&gt;server-snippet&lt;/code&gt; 어노테이션은 raw NGINX 지시문을 그대로 주입하는 구조입니다. 그런데 바로 이 설계가 보안 취약점의 근원이 됐습니다. 대표적인 사례가 &lt;strong&gt;IngressNightmare&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(CVE-2025-1974, CVSS 9.8)​&lt;/span&gt;입니다. 이 취약점은 공격자가 인증 절차 없이도 원격에서 임의의 코드를 실행할 수 있는&lt;span style="color:#999999;"&gt;(unauthenticated RCE, Remote Code Execution)&lt;/span&gt; 문제로, 악용될 경우 클러스터 전체가 장악될 수 있는 심각한 등급입니다. 단순히 유지보수가 끝났기 때문이 아니라, 구조적으로 위험한 기능을 안고 있었던 것입니다. 그만큼 옮겨갈 대상을 제대로 고르는 일이 더 중요해졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;세 번째, 그리고 가장 중요한 핵심으로, &lt;strong&gt;작년 측정 방식 자체에 기술적인 한계를 발견&lt;/strong&gt;했다는 점입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다시 살펴보니 당시의 통과율 기반 채점에는 구조적인 문제가 세 가지 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;미지원 기능이 점수에 거의 반영되지 않은 문제&lt;/strong&gt;: 당시 통과율을 PASS와 FAIL만으로 계산하고, 지원하지 않는 항목&lt;span style="color:#999999;"&gt;(SKIP)&lt;/span&gt;은 제외하다 보니, 기능을 아예 지원하지 않을 때는 감점 대신 계산 대상에서 빠지는 구조로 진행됐습니다. 결국 기능이 적은 구현체가 오히려 유리해지는 채점의 오류가 있었습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;필수 기능과 부가 기능을 같은 무게로 측정:&lt;/strong&gt; 반드시 지원해야 하는 host 라우팅과, 표준에도 없는 rate limiting을 동일한 항목 가중치로 채점했습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;100%와 95%를 구분하지 못한 이슈:&lt;/strong&gt;A/F 중심의 등급 체계로는 “거의 모든 테스트를 통과했지만 하나가 부족한 구현체”와 “기본 기능부터 동작하지 않는 구현체”가 같은 등급으로 묶였습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;요즘 업계에서는 ‘Unlearn’, 즉 한 번 익힌 것을 의도적으로 내려놓는다는 표현을 자주 씁니다. 이번 재측정이 제게는 그 말에 딱 맞는 경험이었습니다. 새로운 데이터를 더 모으는 일이 아니라, 먼저 &lt;strong&gt;작년에 내렸던 결론을 내려놓는 것&lt;/strong&gt;에서부터 다시 시작해야 했기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;결론을 내려놓고 다시 측정하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;기존 채점 구조를 버리고 공식 모델로 다시 만들다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;그래서 이번에는 점수 체계를 임의로 손보는 대신, &lt;strong&gt;Gateway API의 공식 적합성(conformance) 모델&lt;/strong&gt;에 맞춰 측정을 다시 설계했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;먼저 Gateway API와 공식 적합성의 개념을 간단히 짚고 넘어가겠습니다. Gateway API는 기존 Ingress를 대체하기 위해 쿠버네티스 커뮤니티가 만든 차세대 트래픽 라우팅 표준입니다. 역할을 &lt;strong&gt;GatewayClass&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(인프라 담당)&lt;/span&gt;, &lt;strong&gt;Gateway&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(클러스터 운영자)&lt;/span&gt;, &lt;strong&gt;HTTPRoute&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(애플리케이션 개발자)​&lt;/span&gt;로 나눠, 더 세밀한 제어와 책임 분리를 지원합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 Ingress 시절에는 구현체마다 동작 방식이 제각각이었습니다. 같은 설정이라도 구현체를 바꾸면 다르게 동작하는 일이 흔했습니다. Gateway API는 이런 파편화를 줄이기 위해, 구현체가 스펙을 제대로 구현했는지 검증하는 공식 적합성 테스트를 제공합니다. 이는 다시 기능의 중요도에 따라 &lt;strong&gt;Core&lt;/strong&gt;와 &lt;strong&gt;Extended&lt;/strong&gt; 두 단계로 구분합니다. &lt;strong&gt;Core&lt;/strong&gt;는 모든 구현체가 반드시 지원해야 하는 기능이고, &lt;strong&gt;Extended&lt;/strong&gt;는 표준에는 포함됐지만 선택적으로 지원하는 기능입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번에는 기존처럼 17개 테스트를 하나의 통과율로 묶지 않았습니다. 대신 각 기능이 표준에서 어떤 위치를 차지하는지에 따라 나눴습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;Core(7개)&lt;/strong&gt;: 모든 구현체가 반드시 지원해야 하는 필수 기능입니다. 하나라도 빠지면 적합하지 않습니다. 공식 모델에서는 이를 전부 통과한 상태를 적합&lt;span style="color:#999999;"&gt;(conformant)&lt;/span&gt;한 상태로 봅니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;Extended(13개)&lt;/strong&gt;: 표준에 든 선택 기능입니다. 지원하지 않는다고 감점하지 않고, &lt;strong&gt;지원하는 갯수(기능의 폭)&lt;/strong&gt;로 비교했습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;구현체 고유 기능&lt;/strong&gt;: rate limiting이나 외부 인증처럼 표준에 포함되지 않은 기능은 등급에 반영하지 않았습니다. 대신 별도의 매트릭스로만 비교했습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;등급 기준 역시 임의로 정하지 않았습니다. Gateway API v1.4.0 공식 소스의 Support 표기를 그대로 인용해 확정했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그 결과, 이번 평가는 하나의 통과율이 아니라 세 가지 기준으로 나뉩니다. Core를 모두 통과했는가, Extended 기능을 얼마나 지원하는가, ​구현체 고유 기능은 무엇을 제공하는가. 이전의 A/F 등급보다 훨씬 많은 정보를 담을 수 있는 방식입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image1.jpg"&gt;&lt;figcaption&gt;채점 방식의 전환. 통과율 기반 A/F 등급 구조에서, 공식 conformance 기준으로 변경 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;원인은 제품이 아니라 측정 방법과 조건&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;새로운 기준으로 7개 구현체를 라이브 클러스터에서 다시 측정했습니다. 그 결과, 작년에 통과하지 못했던 두 구현체의 결과가 달라졌습니다. Kong과 Traefik 모두 이번에는 &lt;strong&gt;Core 7개 항목을 모두 통과&lt;/strong&gt;했습니다. 또한 작년에는 arm64 이미지를 지원하지 않아 제외했던 kgateway도 이제 측정에 포함됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image5.jpg"&gt;&lt;figcaption&gt;7개 구현체의 게이트웨이 설치 상태 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;전체 결과를 표로 정리하면 다음과 같습니다. 7개 구현체 모두 Core는 통과했고, 차이가 난 부분은 Extended 기능 지원 범위였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image15.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결과가 왜 이렇게 달라졌을까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;원인은 하나가 아니었습니다. 공교롭게도, 그 어느 것도 제품 자체의 변화 때문은 아니었습니다. 작년 결과만 보면 제품의 문제처럼 보였지만, 제품을 둘러싼 환경과 측정 방식이 바뀌며 결과 역시 달라졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;우선 가장 먼저, 표준이 성숙했습니다.&lt;/strong&gt; 작년 측정은 Gateway API v1.2를 기준으로 했고, 이번에는 v1.4를 기준입니다. 그사이 표준이 두 단계 올라가며, 작년에는 실험 단계였거나 구현체마다 제각각이던 기능들이 공식 표준으로 자리 잡았습니다. 대표적으로 백엔드 구간의 TLS를 다루는 &lt;strong&gt;BackendTLSPolicy&lt;/strong&gt;가 v1.4에서 표준 채널로 승격하며, 작년 Traefik에서 backend-tls 기능을 막았던 CRD 버전 불일치 문제가 해소됐습니다. 또한 작년에는 AMD64만 지원해 애플 실리콘&lt;span style="color:#999999;"&gt;(arm64)&lt;/span&gt; 기반 측정 환경에서는 실행할 수 없었던 kgateway도, 이번에는 arm64를 지원하면서 측정 대상에 포함됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;두 번째는 &lt;strong&gt;현행 권장 방식으로 설치&lt;/strong&gt;했다는 점입니다. 작년에는 Kong을 옛 방식 KIC&lt;span style="color:#999999;"&gt;(Unmanaged)​&lt;/span&gt;로 설치했습니다. 이번에는 현재 Kong이 Gateway API 운영 방식으로 권장하는 KGO Managed 구성을 사용했습니다. 같은 제품이라도 설치 방식이 달라지니 동작 결과 역시 달라졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;세 번째는 &lt;strong&gt;측정 방식을 더 정교하게 설계&lt;/strong&gt;했다는 점입니다. 이 부분이 가장 결정적인 차이를 만들었습니다. Kong은 설정을 한 덩어리로 묶어 관리하며 한꺼번에 동기화하는 특성이 있습니다. 따라서 지원하지 않는 기능이 하나라도 포함되면 전체 적용이 거부되고, 그 영향으로 정상적인 기본 라우팅까지 함께 실패했습니다. 작년에 발생했던 “no Route matched” 오류가 바로 이 사례였습니다. 이번에는 측정 도구를 기능별로 라우트를 분리해 적용하니 지원하지 않는 기능만 제외되고, Core 기능은 정상적으로 동작했습니다. Traefik의 실패 원인은 더 단순했습니다. Gateway 리스너가 바라보는 포트와 내부 entrypoint 포트가 서로 맞지 않아 Gateway가 Ready 상태로 올라오지 못했고, 그 결과 “Gateway not ready”​와 404 오류가 발생했습니다. 포트 구성을 맞추자 정상적으로 동작했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;정리하면, 작년 Kong과 Traefik이 테스트를 통과하지 못했던 이유는 제품의 근본적인 한계 때문은 아니었습니다. 표준이 성숙하고, 설치 경로가 정리됐으며, 측정 방법이 정교해지면서 풀린 문제였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image2.jpg"&gt;&lt;figcaption&gt;작년에 통과하지 못했던 Traefik과 Kong에 라우트를 얹고 직접 호출한 결과 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번 재측정으로 가장 크게 배운 점도 여기에 있습니다. 점수가 낮게 나오면 &lt;strong&gt;제품부터 의심하기 쉽지만, 그만큼 측정 자체도 함께 의심해 봐야 한다&lt;/strong&gt;는 사실입니다. 특히 그 결과가 공개돼 누군가의 기술 도입 판단에 활용된다면, 더욱 그렇습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;측정하며 맞닥뜨린 문제들&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;작년의 결론을 내려놓고 다시 측정하는 과정에서는 결과만큼이나 과정에서도 많은 것을 배웠습니다. 그 과정에서 얻은 공통된 교훈은 하나였습니다. &lt;strong&gt;겉으로는 통과한 것처럼 보이는 신호를 그대로 믿어서는 안 된다&lt;/strong&gt;는 점입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;1. 공식 적합성(conformant) 인증을 받아도 기능 구현 수준은 같지 않다&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Gateway API의 공식 권고는 &lt;strong&gt;“conformant 구현체를 선택하라”​&lt;/strong&gt;입니다. 하지만 실제로 측정해 보니, 공식 인증을 받은 7개 구현체도 Extended 기능 지원 범위는 6개에서 13개까지 크게 차이가 났습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Envoy Gateway와 Istio는 13개 기능을 모두 지원했고, Cilium과 kgateway는 12개, NGINX Gateway Fabric은 11개, Traefik은 10개를 지원했습니다. Kong은 6개만 지원했습니다. 즉, conformant 인증은 합격선일 뿐, 모두 수준이 비슷하다는 보증은 아닙니다. timeout, 응답 헤더 수정, 요청 미러링처럼 실제 운영 환경에서 자주 쓰이는 기능도 구현체에 따라 지원 여부가 달랐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image6.jpg"&gt;&lt;figcaption&gt;같은 conformant 인증, 다른 기능 폭. 7종이 6개에서 13개까지 나뉠 수 있음 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;2. 변환된다는 것과 동작한다는 것은 다르다&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;ingress-nginx 설정을 Gateway API로 변환하는 도구(&lt;a href="https://kubernetes.io/blog/2026/03/20/ingress2gateway-1-0-release/"&gt;ingress2gateway&lt;/a&gt;)는 30개 넘는 어노테이션을 자동으로 변환해 줍니다. 하지만 변환이 성공했다고 해서 실제로 동작하는 것은 아니었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어 CORS 관련 어노테이션은 변환 결과가 깔끔하지만, 실측하면 3개 구현체만 테스트를 통과했습니다. 반면 헤더를 추가하는 x-forwarded-prefix 같은 어노테이션은 변환 시 아무런 경고도 없이 조용히 사라졌습니다. 그래서 이번 비교에서는 “변환됨”과 “동작함”을 서로 다른 칸으로 나눴습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;3. “TLS 연결됨”을 “인증서 검증됨”으로 착각할 뻔했다&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;backend-tls 테스트를 처음 구성했을 때는 TLS 연결이 정상적으로 맺어지고 응답이 오는지만 확인하고 있었습니다. 정작 잘못된 인증서를 실제로 거부하는지 보지 않은 셈입니다. 그래서 의도적으로 잘못된 CA 인증서를 적용한 뒤 다시 테스트했습니다. 다행히 통과한 구현체들은 모두 인증서 검증을 제대로 강제하고 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;만약 이 검증 단계를 생략했다면, 실제로는 보안 검증이 이뤄지지 않는데도 “보안 기능 통과​”라는 잘못된 결론을 내릴 수도 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;4. 표준 외부 인증 필터는 아무도 강제하지 못했다&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;ingress-nginx에서 auth-url을 이용해 외부 인증을 사용하던 사용자라면 가장 궁금해할 부분입니다. Gateway API에는 외부 인증을 위한 표준 필터&lt;span style="color:#999999;"&gt;(GEP-1494)&lt;/span&gt;가 실험 단계로 포함돼 있습니다. 하지만 이번 측정에서는 이 표준 필터를 완전하게 강제하는 구현체를 확인하지 못했습니다. 일부 구현체는 필터를 거부하거나 오류를 냈고, Cilium과 kgateway는 해당 표준 필터 자체를 구현하지 않아 인증 절차 없이 트래픽이 그대로 통과했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;즉, 현재 기준으로는 외부 인증을 표준 필터로 옮길 수 없습니다. 실제 운영에서는 여전히 각 구현체가 제공하는 고유 기능에 기대야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;구현체별 재측정 결과&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이제 구현체 7종을 하나씩 짚어 보겠습니다. 작년 글과 같은 순서로, 각 구현체의 한 줄 평과 장단점을 살펴봅니다. 카드의 점수 자리에는 작년의 A/F 등급 대신 이번 기준인 Core와 Extended, 그리고 복구 시간을 넣었습니다. 작년에 통과하지 못했던 Kong과 Traefik, 측정에서 빠졌던 kgateway의 위치 변화가 눈에 띕니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1. NGINX Gateway Fabric (NGF)&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;한 줄 평&amp;nbsp;&lt;/strong&gt;&lt;i&gt;검증된 NGINX의 안정성을 Gateway API로 계승. ingress-nginx의 공식 후속 경로&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;장점과 단점&lt;/strong&gt;&amp;nbsp; NGINX Gateway Fabric의 가장 큰 장점은 결국 NGINX입니다. rate-limit, body-size, basic-auth를 모두 네이티브로 지원하고, 풍부한 문서와 대규모 커뮤니티가 존재합니다. ingress-nginx에서 가장 매끄러운 이행 경로라, 기존 운영 경험을 그대로 활용할 수 있습니다. 다만 표준 Extended는 11개로 최상위권은 아니며&lt;span style="color:#999999;"&gt;(timeout 등 일부 미흡)&lt;/span&gt;, active health check는 상용 버전인 Plus 전용입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image8.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;테스트에는 v2.4.2 버전을 사용했습니다. ingress-nginx에서 옮겨 오는 팀에게 부담이 가장 적은 선택지입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2. Envoy Gateway&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;한 줄 평&amp;nbsp;&lt;/strong&gt;&lt;i&gt;가장 넓은 기능 폭, CNCF 차세대 표준&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;장점과 단점&lt;/strong&gt;&amp;nbsp; Envoy Gateway의 가장 큰 강점은 Extended 13개를 전부 지원하는 데서 나오는 폭입니다. 실험 채널 기능이 가장 앞서 있고, rate-limit를 네이티브로 지원하며 active health check와 뛰어난 관측성을 갖췄습니다. 다만 body-size 표준 경로는 현재 구현 전이고, 상대적으로 짧은 역사와 Envoy 자체의 복잡성으로 인한 학습 곡선이 존재합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image7.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;테스트에는 v1.7.3 버전을 사용했습니다. 기능 폭을 최우선으로 본다면 가장 앞서는 구현체입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3. Istio Gateway&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;한 줄 평&amp;nbsp;&lt;/strong&gt;&lt;i&gt;서비스 메시와 게이트웨이 통합, 자동 mTLS&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;장점과 단점&lt;/strong&gt;&amp;nbsp; Istio Gateway의 가장 큰 장점은 서비스 메시와의 통합입니다. 표준 Extended 13개를 전부 지원하고, mTLS가 자동으로 적용되며, 파드 교체 시에도 무중단이었습니다. 다만 rate-limit와 body-size는 낮은 수준의 설정이 필요해 복잡도가 높은 편이고, tls-passthrough는 v1.4에서 동작하지 않았습니다. 서비스 메시 전체 스택을 도입해야 하는 부담도 함께 고려해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image10.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;테스트에는 v1.30.0 버전을 사용했으며, 복구도 무중단이었습니다. 이미 서비스 메시를 운영 중이라면 괜찮은 선택지입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;4. Cilium Gateway&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;한 줄 평&amp;nbsp;&lt;/strong&gt;&lt;i&gt;eBPF 데이터플레인, CNI와 게이트웨이 통합&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;장점과 단점&lt;/strong&gt;&amp;nbsp; Cilium Gateway의 장점은 eBPF 기반의 커널 레벨 패킷 처리 방식입니다. Core를 모두, 표준 Extended를 12개 갖췄고, Cilium 네트워크 정책과 자연스럽게 연동됩니다. 다만 Cilium CNI가 필수이며, rate-limit와 body-size는 표준 경로에서 지원하지 않습니다. 외부 인증 표준 필터를 무방비로 통과시켜 인증 없이 트래픽이 그대로 지나가는 점도 주의해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image9.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;테스트에는 v1.19.4 버전을 사용했습니다. 다만 복구 측정은 공유 eBPF 데이터플레인 특성상 제외했습니다. 이미 Cilium CNI를 쓰는 환경에 적합합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;5. Kong Gateway&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(작년 미통과 → 올해 통과)&lt;/span&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;한 줄 평&amp;nbsp;&lt;/strong&gt;&lt;i&gt;엔터프라이즈 API 게이트웨이, 풍부한 플러그인&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;장점과 단점&lt;/strong&gt;&amp;nbsp; Kong Gateway는 엔터프라이즈 API 게이트웨이 시장의 선두 주자로, 풍부한 플러그인 생태계와 API 관리 기능을 갖췄고 rate-limit와 body-size를 네이티브로 지원합니다. 무엇보다 작년과 달리 Core 7개 전부 통과로 기준이 바뀌었습니다. 다만 표준 Extended가 6/13으로 7종 중 가장 좁고, 복구가 약 34초로 가장 느립니다. 설정을 일괄 적용하는 구조라 기능 하나가 거부되면 전체에 영향을 주는 점도 유의해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image13.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;테스트에는 KGO 2.1 버전을 사용했습니다. API 게이트웨이 생태계가 중요하다면 여전히 강력한 선택지이지만, 기능 폭과 복구 속도는 함께 따져야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;6. Traefik Gateway&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(작년 미통과 → 올해 통과)&lt;/span&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;한 줄 평&amp;nbsp;&lt;/strong&gt;&lt;i&gt;자동 서비스 디스커버리와 대시보드, 간편한 운영&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;장점과 단점&lt;/strong&gt; Traefik Gateway는 자동 서비스 디스커버리와 대시보드로 유명한 클라우드 네이티브 프록시입니다. rate-limit와 body-size를 네이티브로 지원하고, 작년과 달리 Core 7개 전부 통과로 바뀌었습니다&lt;span style="color:#999999;"&gt;(리스너 포트 교정)&lt;/span&gt;. 다만 표준 Extended는 10/13으로 중위권이며, request-mirror 등 일부가 미흡합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image11.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;테스트에는 v3.6.17 버전을 사용했습니다. 간편한 운영을 중시하는 팀에게 적합합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;7. kgateway&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(작년 측정 제외 → 올해 합류)&lt;/span&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;한 줄 평&amp;nbsp;&lt;/strong&gt;&lt;i&gt;Envoy 기반 게이트웨이, arm64 지원으로 측정 환경에 합류&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;장점과 단점&lt;/strong&gt; kgateway는 Envoy 기반의 게이트웨이로, 표준 Extended 12/13과 무중단 복구를 갖췄습니다. 작년 &lt;a href="https://github.com/howardjohn/gateway-api-bench"&gt;Gateway API Benchmarks&lt;/a&gt;의 트래픽 성능 테스트에서 최고 처리량을 기록&lt;span style="color:#999999;"&gt;(작년 벤치마크 기준)&lt;/span&gt;한 만큼, 성능 측면에서 강점이 있습니다. Gloo 계보의 전용 마이그레이션 가이드도 제공합니다. 작년 측정 환경&lt;span style="color:#999999;"&gt;(Apple Silicon, arm64)&lt;/span&gt;에서는 AMD64 전용이라 제외됐었으나, 이번에는 합류했습니다. 다만, 외부 인증 표준 필터를 무방비로 통과시킵니다. 커뮤니티 역시 아직 성장 중입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image12.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;테스트에는 v2.2.2 버전을 사용했습니다. AMD64는 물론 arm64 환경에서도 Envoy 기반 구현체를 찾는다면 주목할 만합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;그래서 어떤 구현체를 골라야 할까&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;재측정 결과, 7종 모두 Core는 통과했습니다. 그러니 이제 선택 기준은 확장 기능 수준, 데이터플레인, 그리고 커뮤니티 활성화 등을 함께 고려하는 게 좋겠습니다. 상황별 추천을 정리하면 이렇습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image14.jpg"&gt;&lt;figcaption&gt;Core, Extended, 벤더 기능, 운영 지표를 한 장에 모은 전체 범위 지도 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image3.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;ingress-nginx에서 옮길 때 가장 막히는 것들&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;기능 지원 범위와는 별개로, ingress-nginx에서 자주 쓰던 것 가운데 일부는 Gateway API로 그대로 옮길 수 없습니다. 마이그레이션을 검토하고 있다면, 먼저 아래 세 가지가 현재 설정에 들어 있는지부터 확인해 보길 권합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;설정 스니펫&lt;/strong&gt;(&lt;code&gt;configuration-snippet&lt;/code&gt;, &lt;code&gt;server-snippet&lt;/code&gt;)&lt;strong&gt;은 대체 수단이 없습니다.&lt;/strong&gt;이 기능은 raw NGINX 지시문을 직접 주입하는 방식입니다. 하지만 Gateway API는 이런 주입 경로를 아예 제공하지 않습니다. 공교롭게도 ingress-nginx의 IngressNightmare 취약점 역시 바로 이 구조에서 비롯됐습니다. 헤더 수정이나 타임아웃처럼 흔한 건 이미 표준 기능으로 흡수됐지만, 임의의 지시문 주입에 의존하고 있었다면 다시 설계해야 합니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;mTLS 클라이언트 인증(&lt;/strong&gt;&lt;code&gt;auth-tls-*&lt;/code&gt;&lt;strong&gt;)은 v1.4에 표준 필드가 없습니다.&lt;/strong&gt;V.15에는 들어갔으니 업그레이드를 기다리거나, 구현체 고유 기능을 활용해야 합니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;세션 어피니티&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(쿠키 Sticky)&lt;/span&gt;&lt;strong&gt;는 스펙은 있지만 설정이 구현체마다 다릅니다.&lt;/strong&gt;변환 도구도 이 어노테이션은 자동으로 변환하지 못하고 거절합니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;장애 복구는 얼마나 빠른가&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이번 실험에서는 conformance 테스트가 다루지 않는 운영 지표도 함께 측정했습니다. 기본 설치 환경&lt;span style="color:#999999;"&gt;(데이터 플레인 파드 1개)&lt;/span&gt;을 기준으로 트래픽을 받는 프록시 파드를 강제로 삭제한 뒤, 2초 간격으로 요청을 보내면서 트래픽이 돌아올때까지 걸린 시간을 측정했습니다. 여러 replica를 둔 HA 환경의 failover를 측정한 것이 아니라, 파드 하나가 죽었을 때 얼마나 빠르게 복구되는지를 확인한 실험입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;Istio와 kgateway&lt;/strong&gt;는 무중단으로 동작했습니다. 실패한 요청이 한 번도 없었습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;NGINX Gateway Fabric, Envoy Gateway, Traefik​&lt;/strong&gt;은 약 13초 만에 복구했습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;Kong&lt;/strong&gt;은 약 34초로 가장 늦었습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;Cilium&lt;/strong&gt;은 공유 eBPF 데이터 플레인을 사용하는 구조이므로 이번 측정에서는 제외했습니다. 에이전트 재시작이 클러스터 전체에 영향을 주기 때문입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;파드를 삭제했는데도 어떻게 무중단이 가능했을까요? 쿠버네티스에서 파드는 삭제 명령을 받는 즉시 종료되지 않습니다. 종료 신호를 받은 뒤 일정한 유예 시간 동안 살아있으며, 그 사이 새로운 파드가 올라옵니다. 이 과정에서 기존 파드가 받는 트래픽을 끝까지 처리하고, 새 파드와 자연스럽게 교대하면 밖에서 보기에는 끊김이 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Istio와 kgateway는 이 교대 과정이 매끄러웠습니다. 반면 13초 또는 34초가 걸린 쪽은 교대가 겹치지 않아 빈 구간이 생겼습니다. 물론 운영에서는 replica를 여럿 두는 것이 기본이라 가려질 테지만, 단일 노드 엣지처럼 replica를 늘리기 어려운 환경이라면 이 공백이 그대로 사용자에게 노출됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3837/image4.jpg"&gt;&lt;figcaption&gt;파드 하나가 죽었을 때 트래픽 복구 속도 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;실제로 도입할 때 고려할 것들&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;마지막으로 수치는 어디까지나 수치입니다. 실제로 옮기려면 국내 운영 환경 특유의 조건도 봐야 합니다. 특히 확인하면 좋을 것들을 정리했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;1. 지금 쓰는 어노테이션부터 목록으로 만듭니다.&lt;/strong&gt; 앞서 말한 설정 스니펫, mTLS 클라이언트 인증, 세션 어피니티를 사용하고 있다면 표준 기능만으로는 옮길 수 없습니다. 그러니 먼저 어떤 기능을 사용 중인지 목록으로 정리해 두는 것이 좋습니다. 이 목록이 마이그레이션 난이도를 사실상 결정합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;2. 변환 도구의 출력은 믿되, 검증합니다.&lt;/strong&gt; ingress2gateway로 1차 변환을 수행하되, 변환을 마쳤다고 끝내지 말고 옮긴 환경에서 실제로 동작하는지 항목별로 확인해야 합니다. 운영하다 변환은 됐는데 동작하지 않는 요소를 마주치는 것보다 낫습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;3. 버전을 함께 고정합니다.&lt;/strong&gt; 이번 결과는 2026년 6월, Gateway API v1.4​ 기준 스냅샷입니다. 한 가지 유의할 점은, 측정 이후 상위 버전에서 일부 미지원 기능이 해소됐다는 것입니다. Traefik의 backend-request-header 수정은 v3.7에서, kgateway의 backend-tls​는 v2.3.0에서, Cilium의 backend-tls와 자체 외부 인증&lt;span style="color:#999999;"&gt;(구현체 고유 기능)&lt;/span&gt;은 v1.20에서, Kong의 TLSRoute는 KGO 2.2.0에서 각각 지원됩니다. 모두 이번 측정에 사용한 버전보다 이후에 추가된 기능입니다. 따라서 이 결과를 참고할 때는 측정 버전과 함께 해석하는 것이 중요합니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;더해서 구현체마다 지원하는 Gateway API 버전이 서로 다릅니다. 컨트롤러가 지원하는 범위보다 먼저 CRD를 올리면 새로운 리소스가 정상적으로 동작하지 않을 수 있습니다. 따라서 그 전에 각 구현체의 릴리스 노트에서 지원하는 Gateway API 버전을 확인해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 작업에서 가장 의미 있었던 것은 새로운 순위표 그 자체보다는, 작년에 검증한 것들을 다시 확인해야 한다는 사실 자체였습니다. 작년에 기준조차 통과하지 못했던 두 구현체는 올해 모두 Core를 통과했습니다. 이처럼 측정 결과는 언제나 그 시점의 측정 방법과 환경에 영향을 받습니다. 따라서 측정 방법이 개선됐다면, 결과 역시 함께 달라져야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앞서 말한 Unlearn이라는 개념이 다소 거창하게 들릴 수도 있습니다. 하지만 실무에서는 오히려 자주 해야하면서도 막상 하기 가장 어려운 일입니다. 스스로 내렸던 결론을 다시 의심하고, 내려놓고, 처음부터 시작한다는 뜻이기 때문입니다. 그래서 1년 뒤에는 지금 내린 결론 역시 달라질 수 있습니다. Gateway API 표준도, 각 구현체도 그만큼 빠르게 발전하고 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그러니 이 글의 순위를 그대로 받아들이기보다는, &lt;strong&gt;여러분의 환경에서 직접 한 번 측정해 보시길 권합니다.&lt;/strong&gt;결국 그것이 가장 정확하고, 또 가장 정직한 검증 방법입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;이번 측정에 사용한 도구와 채점 기준, 구현체별 설치 스크립트, 변환 결과는 모두&lt;/span&gt; &lt;a href="https://github.com/sysnet4admin/Research/tree/main/gateway-PoC"&gt;GitHub 저장소&lt;/a&gt;&lt;span style="color:#999999;"&gt;에 공개해 두었습니다. 이 글에서는 핵심 결과만 간추려 소개했지만, 저장소에서는 각 구현체가 스펙을 얼마나 정확히 구현했는지, ingress-nginx에서 옮길 때 어떤 기능은 그대로 옮겨지고, 어떤 기능은 막히는지​를 확인할 수 있는 자료를 확인할 수 있습니다. 또한 회차별 측정 결과, 부하 테스트에서의 성공률, 어노테이션별 변환 결과 등 세부 데이터도 함께 들어 있습니다. 측정을 하게 된 배경과 그 과정에서 알게 된 점을 글로 풀어 둔 후기는&lt;/span&gt; &lt;a href="https://kuberneteslab.dev/ko/blog/gateway-api-poc-v1.4/"&gt;블로그&lt;/a&gt;&lt;span style="color:#999999;"&gt;에서도 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;작가&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;조훈 (CNCF&amp;amp;AAIF 앰버서더)&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;쿠버네티스 및 AI 네이티브 기술 전문가로, CNCF와 에이전틱 AI 재단&lt;span style="color:#999999;"&gt;(AAIF)&lt;/span&gt; 글로벌 앰버서더이자 Kubestronaut이다. 쿠버네티스랩을 운영하며 인프라 자동화 기술을 연구하고 공유한다. ‘IT 인프라 엔지니어 그룹’ 운영진이자 오픈소스 컨트리뷰터로 활동 중이며, 맞춤형 인프라 교육, 쿠버네티스 비용 최적화, 멀티 LLM 및 AI 에이전트 비교 검증 등 다양한 실무 PoC를 수행하고 있다. 최근 출간한 『AI 시대에 개발자가 알아야 할 인프라 구성 배포 with 클로드 코드』를 포함해 총 5권의 IT 서적을 집필했으며, 인프런 강의 및 요즘IT 기고 등 지식 공유 활동을 이어가고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;심근우&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;LG유플러스 CTO부문에서 대고객 비즈니스 시스템의 DevOps를 담당하는 UcubeDAX팀의 팀장으로 일하고 있다. 퍼블릭 클라우드와 프라이빗 클라우드에 걸친 쿠버네티스 클러스터를 안정적으로 운영하기 위해 노력하고 있으며, 특히 주니어 DevOps 엔지니어들의 육성에 큰 관심을 가지고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;문성주&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;체커(CHEQUER) 사의 DevOps Engineer로서 쿠버네티스의 멀티 클러스터 관리 방법론과 쿠버네티스 구현체(CAPI, OCI)에 대한 명세와 컨테이너 리소스 격리 방법에 대한 연구를 병행하고 있다. 이런 연구 활동을 기반으로 쿠버네티스 볼륨 테스트 파트에 컨트리뷰션했다. 본업은 쿠버네티스 오퍼레이터와 같은 CRD(커스텀 리소스)를 개발해 현업에서 쿠버네티스를 좀 더 편리하게 사용할 수 있도록 돕는 일이다. 또한, 페이스북 그룹 ‘코딩이랑 무관합니다만'과 ‘IT 인프라 엔지니어 그룹'의 운영진을 맡고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;이성민&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;미국 넷플릭스(Netflix) 사의 Data Platform Infrastructure 팀에서 사내 플랫폼 팀들과 데이터 사용자들을 어우르기 위한 가상화 및 도구들을 개발하는 일들을 하고 있다. 과거 컨테이너와 쿠버네티스에 큰 관심을 두고 ingress-nginx를 비롯한 오픈 소스에 참여했으며, 현재는 데이터 분야에 일하게 되면서 stateful 한 서비스들이 컨테이너화에서 겪는 어려움을 보다 근본적으로 해결하기 위한 많은 노력을 하고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>손 코딩은 죽었는가?</title><link>https://yozm.wishket.com/magazine/detail/3819</link><description>코딩 에이전트의 성능이 폭발적으로 좋아지며, 이제는 코드를 몰라도 자연어로 말만 하면 인공지능이 코드를 만들어 주는 시대가 왔다. 이제는 바이브 코딩을 넘어 AI가 능동적인 주체로 팀을 구성하고 스스로 목표를 설정해 계획을 세우며 코딩, 테스트, 디버깅까지 수행하는 에이전틱 코딩이 성행하고 있다. 그런 만큼 우스갯소리로 코딩 에이전트에 장애가 나면 퇴근해야 한다는 말이 있을 정도로 AI 기반 개발 방식이 대중화됐다. 사람이 직접 코드를 작성하지 않는 시대, 누군가는 손 코딩의 종말을 이야기한다. 정말로 손 코딩은 죽었는가?</description><guid>https://yozm.wishket.com/magazine/detail/3819</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p&gt;코딩 에이전트의 성능이 폭발적으로 좋아지며, 이제는 코드를 몰라도 자연어로 말만 하면 인공지능&lt;span style="color:#999999;"&gt;(이하 AI)&lt;/span&gt;이 코드를 만들어 주는 시대가 왔다. 일찍이 안드레이 카파시&lt;span style="color:#999999;"&gt;(Andrej Karpathy)&lt;/span&gt;는 AI 기반 개발 방식을 바이브 코딩&lt;span style="color:#999999;"&gt;(Vibe Coding)&lt;/span&gt;이라고 말한 바 있다. 그러나 이제는 바이브 코딩을 넘어 AI가 능동적인 주체로 팀을 구성하고 스스로 목표를 설정해 계획을 세우며 코딩, 테스트, 디버깅까지 수행하는 에이전틱 코딩&lt;span style="color:#999999;"&gt;(Agentic Coding)&lt;/span&gt;이 성행하고 있다. 그렇게 AI 기반 개발 방식이 보편화됨에 따라 프롬프트 엔지니어링, 컨텍스트 엔지니어링을 넘어 AI가 만들어 내는 코드를 적극적으로 통제하려는 &lt;a href="https://openai.com/ko-KR/index/harness-engineering/"&gt;&lt;u&gt;하네스 엔지니어링&lt;/u&gt;&lt;/a&gt;도 빠르게 확산되고 있다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;요즘은 우스갯소리로 코딩 에이전트에 장애가 나면 퇴근해야 한다는 말이 있을 정도로 AI 기반 개발 방식이 대중화됐다. 사람이 직접 코드를 작성하지 않는 시대, 누군가는 손 코딩의 종말을 이야기한다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;정말로 손 코딩은 죽었는가?&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;인지적 부채를 앓거나 호소하는 사람들&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;1년 전쯤, 나는 어느 바이브 코딩 세미나에 참석한 적이 있다. 당시 행사장에 모인 많은 이들은 그 자체로 바이브 코딩에 대한 높은 관심과 열기를 보여 주는 듯했다. 발표자들 역시 하나같이 손 코딩과의 작별을 고하며, 어떻게 하면 바이브 코딩으로 더 나은 결과물을 잘 만들 수 있을지 말했다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;하지만 정작 내 관심을 끈 것은 바이브 코딩이 아니라 한 청중의 질문이었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;AI로 코드를 만들고 있지만 코드가 어떻게 동작하는지 잘 모르겠고, 무언가 만들어내지만 내가 성장한다는 느낌이 들지 않는데 어떻게 해야 하나요?&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;비단 개발자만 이런 현상을 겪는 것이 아니다. 이탈리아 후마니타스대&lt;span style="color:#999999;"&gt;(Humanitas University)&lt;/span&gt; 연구진은 &lt;a href="https://www.thelancet.com/journals/langas/article/PIIS2468-12532500133-5/abstract"&gt;&lt;u&gt;내시경에 AI를 적극 사용한 의료진을 분석&lt;/u&gt;&lt;/a&gt;했다. 그 결과, AI에 지속적으로 의존할 때 숙련된 의사의 독자적인 용종 발견 능력이 저하되는 ‘탈숙련화&lt;span style="color:#999999;"&gt;(deskilling)&lt;/span&gt;’ 현상을 발견했다. 결국 이는 AI를 적극적으로 활용하는 업계 전반에서 나타나는 현상인 셈이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;하버드 비즈니스 리뷰의 한 글은 AI 도입과 그에 대한 과도한 의존으로 발생하는 인간의 심리적 부채를 말하고 있다. 앞서 &lt;strong&gt;세미나의 질문자나 AI 내시경을 사용한 의료진이 겪고 있는, 혹은 겪었던 것은 바로 ‘인지적 부채’&lt;/strong&gt;이며, 이미 나는 ‘&lt;a href="https://yozm.wishket.com/magazine/detail/3731/"&gt;&lt;u&gt;당신의 사고까지 AI에 외주화하지 마라&lt;/u&gt;&lt;/a&gt;’ 글에서 인지적 부채에 대한 문제를 다룬 바 있다. 요즘 내 주위에서는 너무나도 쉽게 &lt;span style="color:#757575;"&gt;(본인이 인지하든 인지하지 못하든)&lt;/span&gt; AI에 과도하게 의존하며 생긴 인지적 부채를 앓거나 호소하는 사람들을 만난다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;직접 경험의 종말&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;AI 기반 개발은 기술로 매개된 매끄러운 간접 경험을 우리에게 선사한다. 원하는 것을 말로 전달하고, 문제를 만나더라도 그 문제를 다시 AI에 전달하면 그만이다. 깊이 생각할 필요도 없다. 그저 원하는 것을 전달할 뿐이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;이러한 구조에서는 흔히 ‘삽질’이라고 부르는 시행착오를 겪기 어렵다. 앞서 세미나의 질문자는 “성장한다는 느낌이 들지 않는다”라고 말했다. &lt;strong&gt;성장은 학습과 불가분 관계에 있으며, 학습의 원천은 기술로 매개된 간접 경험이 아니라 직접 경험이다. 그래서 무언가를 배울 때 가장 빠르고 확실한 방법은 직접 해보고 실패해 보는 것이다.&lt;/strong&gt; AI와 같은 기술로 매개된 간접 경험은 이처럼 가장 빠르고 확실한 학습 과정을 방해한다. 그 결과, 원하는 결과물은 만들어 낼 수 있을지 몰라도 만들어낸 것에 대해 명확히 설명하기 어렵다. 결국 스스로 성장하고 있다는 느낌도 들지 않는 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;작년의 바이브 코딩 행사장으로 다시 돌아가 보자. 당시 발표자들은 인지적 부채를 겪지 않았을 가능성이 높다. 적게는 10년, 많게는 20년 가까운 경력으로 직접 개발한 경험도 매우 풍부했기 때문이다. AI 기반 개발이 보편화된 것은 불과 몇 년 전의 일이다. &lt;strong&gt;그전까지 개발자들은 좋든 싫든 직접 코딩했으며, 그 과정에서 수많은 시행착오를 겪었고, 그러한 직접 경험은 ‘사전 지식’으로 쌓여 자신만의 심성 모형&lt;/strong&gt;&lt;span style="color:#999999;"&gt;(Mental Model)&lt;/span&gt;&lt;strong&gt;을 만들었다.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;따라서 이들은 AI 기반 개발 환경에서도 이미 머릿속에 자신만의 구현 방향이 존재하며, AI가 실제로 만들어 낸 코드를 보고 차이점을 쉽게 인지해 이를 취사 선택해 원하는 방향으로 만들 수 있다. 반면 AI 기반 개발 방식이 보편화된 시기에 개발을 시작한 사람들은 다르다. 이들은 압도적으로 기술에 의해 매개된 간접 경험이 많기에 인지적 부채에 더욱 취약한 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;인지적 장애물&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;인지적 부채를 해결하는 방법 중 하나는 &lt;a href="https://hbr.org/2026/03/research-using-ai-can-stifle-innovation-but-it-doesnt-have-to"&gt;&lt;u&gt;인지적 장애물(Cognitive friction)&lt;/u&gt;&lt;/a&gt;을 두는 것이다. &lt;strong&gt;인지적 장애물의 핵심은 AI를 사용하기 전에 내 생각을 구체화하는 데 있다. 스스로 문제를 정의하고 가설을 세우거나, 내 생각에 대한 근거를 찾고, 그것을 바탕으로 AI와 대화하며 결과물을 만드는 것이다.&lt;/strong&gt; 여기서 중요한 것은 단순히 AI에게 완성형 프롬프트로 “~을 만들어줘”라고 지시하는 것이 아니라, 사고의 주도권을 내가 쥔 채 AI와 협업한다는 점이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;인지적 장애물에 대한 구체적인 사례가 있다면 이해하기 수월할 것이다. 나는 동작하는 코드를 만들기 전에 테스트 코드를 먼저 작성한다. 켄트 벡이 테스트 주도 개발&lt;span style="color:#999999;"&gt;(Test Driven Development, TDD)&lt;/span&gt;이라고 명명한 개발 방식이다. 이때 작성하는 테스트 코드는 AI에게 맡기지 않고 손으로 직접 만든다. 이 과정에서 풀어야 할 문제를 스스로 정의하고 가설을 세운다. 그리고 테스트 코드를 기준으로 AI와 대화하며 구체적인 코드를 함께 작성해 나간다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;AI와 함께 코드를 만들 때 나는 주로 AI에게 문제의 맥락&lt;span style="color:#757575;"&gt;(사용자 스토리, 데이터 크기 등)&lt;/span&gt;을 설명한다. 그리고 AI가 만든 코드를 보고 의도를 질문하거나 다시 내 생각을 제안한다. 내게 있어 테스트 코드를 직접 작성하는 것은 인지적 장애물을 두는 것과 같다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;또 다른 사례로는 얼마 전부터 나와 함께 일하게 된 동료와의 협업 방식을 들 수 있다. 동료는 AI가 대중화되던 시기에 개발을 시작했다. 주로 프론트엔드 개발을 해왔지만 백엔드 개발로 전환해야 했고, 심지어 처음 접하는 언어를 사용해야 했다. 나는 동료가 인지적 부채를 최소화하면서도 빠르게 새로운 것을 학습할 수 있을지 고민했고, 이렇게 제안했다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;세 번 작성하라.&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;구체적으로 우리&lt;span style="color:#757575;"&gt;(나와 동료)&lt;/span&gt;가 한 방식은 아래와 같다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;스스로 어떻게 구현할지 방안을 만든다.&lt;/li&gt;&lt;li&gt;함께 짝 프로그래밍하며 직접 코딩을 경험한다.&lt;/li&gt;&lt;li&gt;코드를 모두 지우고 AI에게 시킨다.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;1번 과정에서 그는 자신의 생각을 구체화하며 시뮬레이션한다. 2번 과정에서는 직접 경험을 쌓는 동시에 짝 프로그래밍을 거치며 다른 사람의 문제 해결 방식을 경험한다. 1번과 2번 과정&lt;span style="color:#757575;"&gt;(인지적 장애물)&lt;/span&gt;을 거치면서 자신만의 동작하는 코드를 갖게 되고, 3번 과정에서 AI가 생성한 코드를 볼 때 선택지가 생긴다. &lt;strong&gt;AI가 만든 것을 받아들일지, 내가 만들었던 것을 선택할지, 그 순간의 선택이 나를 능동적인 존재로 만든다.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;문제 푸는 방법을 보기 전에 풀어보라는 요청을 받고 문제와 씨름하고 난 후에는 해법을 더욱 잘 배우고 그 지식을 더 오래 기억할 수 있다.&lt;/i&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;-&amp;lt;어떻게 공부할 것인가?&amp;gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;코드는 꼭 보아야 하는 것인가&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=8lF7HmQ_RgY"&gt;&lt;u&gt;오픈클로 개발자는 코드를 읽지 않는다&lt;/u&gt;&lt;/a&gt;고 하는데, AI 기반 개발 환경에서 코드를 꼭 보고 이해할 필요가 있을까? AI가 생성한 코드를 볼지 말지는 각자가 처한 맥락에 따라 다르다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;예를 들어 내가 기획자나 디자이너라면 바이브 코딩으로 동작하는 소프트웨어를 만든 다음, 굳이 익숙하지 않은 코드를 보고 이해할 필요는 없을 것이다. 마찬가지로 아이디어가 시장에서 통할지 확인하기 위한 MVP&lt;span style="color:#999999;"&gt;(Minimum Viable Product)&lt;/span&gt;를 만들 때도 코드를 보고 이해할 필요는 없을 수 있다. 결국 각자가 처한 맥락에서 일의 목적과 목표에 따라 판단이 달라진다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;다만 내가 관찰한 인지적 부채를 겪는 개발자들은 주로 기술로 매개된 매끄러운 간접 경험에 원인이 있었다. 이러한 경험은 개발자와 코드 사이의 거리를 벌려 놓고, 그 사이를 스스로 메우지 못하는 데서 나온다. 켄트 벡은 &lt;a href="https://tidyfirst.substack.com/p/augmented-coding-beyond-the-vibes"&gt;&lt;u&gt;Augmented Coding: Beyond the Vibes&lt;/u&gt;&lt;/a&gt;란 글에서 ‘증강 코딩&lt;span style="color:#999999;"&gt;(Augmented Coding)&lt;/span&gt;’을 말하며, &lt;strong&gt;깔끔하고 제대로 동작하는 코드를 만들기 위해서는 코드 자체는 물론 코드의 복잡성, 테스트, 그리고 테스트 커버리지까지 신경 써야 한다&lt;/strong&gt;고 주장한다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3819/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: Kent Beck, &amp;nbsp;&lt;a href="https://tidyfirst.substack.com/p/augmented-coding-beyond-the-vibes"&gt;&lt;u&gt;https://tidyfirst.substack.com/p/augmented-coding-beyond-the-vibes&lt;/u&gt;&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;정체성이란 내가 나 자신에 대해, 내게 들려주는 이야기다. 나는 어떤 사람인가, 나는 무엇을 상징하는가, 나는 무엇을 잘하는가, 나는 무엇을 할 수 있는가에 관한 이야기다. &lt;strong&gt;당신이 개발자라면, 그리고 깔끔하고 제대로 동작하는 코드를 만들고 싶다면, 그 코드가 내가 직접 만든 것이든 AI가 생성한 것이든 상관없이 보고 이해해야 한다.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;학습을 위한 손 코딩&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;내가 어릴 적 무척 좋아했던 &amp;lt;신세기 사이버 포뮬러&amp;gt;는 미래의 레이싱을 다룬 만화영화로, 주인공 하야토는 AI인 아스라다와 함께 레이싱을 하며 성장한다. 어느 날 주인공은 한계에 부딪히고, 그 벽을 넘기 위해 AI의 지원을 모두 끄고 직접 레이싱 테크닉을 연습하는 장면이 나온다. 문제의 본질에 다가가기 위해 기술이 매개된 경험이 아니라 직접 경험을 쌓으려 했던 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;만화영화의 상상력은 현실에서도 충분히 벌어질 수 있다. 나는 ‘&lt;a href="https://yozm.wishket.com/magazine/detail/3584/"&gt;&lt;u&gt;안전한 패스워드 없는(Passwordless) 시스템을 향해&lt;/u&gt;&lt;/a&gt;’라는 글을 쓴 적이 있다. 그보다 앞서 나는 패스키&lt;span style="color:#999999;"&gt;(Passkey)&lt;/span&gt; 개념을 정확하게 이해하기 어려웠고, 아무리 문서를 읽어도 다른 사람에게 명확하게 설명하기 힘들어했다. 그래서 개념과 동작 방식을 학습하기 위해 직접 코딩을 했고, 글에 삽입한 순차도를 직접 그렸다. 그 결과 머릿속이 명확해졌을 뿐만 아니라 다른 사람에게도 정확하게 설명할 수 있었다. 이후 AI와 함께 운영하고 있던 서비스에 패스키를 적용했고, 그 과정에서 나오는 문제들 역시 어렵지 않게 해결할 수 있었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;학습을 위한 글쓰기&lt;span style="color:#999999;"&gt;(Writing to Learn, WTL)&lt;/span&gt;라는 개념은 우리에게 직접 무언가를 생성하는 행위가 학습에 매우 효과적이라는 사실을 알려 준다. 그건 AI도 사람도 마찬가지다. &lt;a href="https://yozm.wishket.com/magazine/detail/3453/"&gt;&lt;u&gt;AI도 동일한 문제를 다양하게 여러 번 생성하면 더 나은 결과를 만들어낸다&lt;/u&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;누구나 직접 경험을 통한 학습이 필요한 이유다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;현대 소프트웨어 생태계는 과거와 비교할 수 없을 정도로 복잡해졌다. 따라서 &lt;strong&gt;모든 것을 세 번 작성하거나 손 코딩하며, 전부 이해하고 만든다는 것은 현실적이지 않다. 또한 AI가 폭발적으로 늘어난 복잡성을 소화할 수 있게 해주는 매개체라는 것도 엄연한 사실이다. 다만 특별히 중요해 보이는 것이 있다면, 그것과 관련된 직접 경험을 쌓아 인지적 부채를 줄이고 이해도를 높이는 것이 중요하다는 것 역시 엄연한 사실&lt;/strong&gt;이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;우리는 본능적으로 선형적 사고를 한다. 프롬프트 엔지니어링 → 컨텍스트 엔지니어링 → 하네스 엔지니어링, 이런 식으로 말이다. 하지만 현실은 복잡계이기에 선형적 사고는 오해를 만든다. 현실에서는 하네스 엔지니어링만 하지 않는다. 프롬프트 엔지니어링과 컨텍스트 엔지니어링이 공존한다. 마찬가지로 바이브 코딩이나 에이전틱 코딩이 대세라고 해서 손 코딩이 사라지거나 그 가치가 없어지는 것은 아니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;손 코딩은 과거의 위상 같지는 않겠지만, 앞으로도 그 고유의 역할을 가지고 공존할 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;감사의 말&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;span style="color:#757575;"&gt;누군가는 글 제목을 보고 눈치챘을지 모르겠다. 이번 글의 제목은 ‘&lt;/span&gt;&lt;a href="https://martinfowler.com/articles/is-tdd-dead/"&gt;&lt;u&gt;Is TDD Dead?&lt;/u&gt;&lt;/a&gt;&lt;span style="color:#757575;"&gt;’의 오마주다. 인연은 없지만 여전히 활발한 활동으로 영감으로 주는 켄트 벡에게 감사를 표한다. 마지막으로 실험(?)에 동참해 준 동료에게 감사를 전한다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>K8s 운영을 AI 에이전트에 맡길 수 있을까?</title><link>https://yozm.wishket.com/magazine/detail/3817</link><description>코드 작성을 돕던 에이전트가 이제 kubectl을 직접 실행하고 장애 알람에 1차 대응까지 시작했습니다. 그렇다면 K8s 운영을 맡겨도 괜찮을까요? Claude Code·Gemini CLI·Codex CLI의 9개 모델 조합을 같은 K8s 장애 10개에 똑같이 투입해 봤습니다. 세 도구 모두 실무에 쓸 만했지만, 가장 비싼 모델이 늘 운영을 더 잘하지는 않았습니다. 효율 1위는 플래그십을 제친 Sonnet 4.6였고, 신중한 Claude·빠른 Gemini·사고하는 Codex로 성격도 갈렸습니다. 한국 운영팀이 도입 전 점검할 다섯 가지까지 함께 정리했습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3817</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;작년만 해도 Claude Code, Gemini CLI, Codex CLI 같은 CLI 기반 코딩 에이전트는 ‘코드 작성을 돕는 보조 도구’ 정도로 받아들여졌습니다. 이들의 성능은 주로 SWE-bench 같은 코딩 벤치마크 점수로 평가하는 것이 일반적이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 올해 들어 분위기가 달라졌습니다. 자동 승인 모드&lt;span style="color:#999999;"&gt;(&lt;code&gt;--dangerously-skip-permissions&lt;/code&gt;, &lt;code&gt;--yolo&lt;/code&gt;, &lt;code&gt;--full-auto&lt;/code&gt;)&lt;/span&gt;가 보편화되며, 이제는 코드 작성뿐 아니라 &lt;strong&gt;실제 명령 실행&lt;/strong&gt;까지 맡기는 사례가 늘고 있습니다. kubectl 명령을 직접 실행하거나, helm 차트를 교체하고, 운영자가 자리를 비운 사이 들어온 알람에 1차로 대응하는 일까지 시도할 수 있게 된 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이러한 흐름은 한국에서도 빠르게 나타나고 있습니다. 일부 팀에서는 이미 사내 알람 봇에 LLM 에이전트를 연결해 장애를 우선 분류하고, 진단 초안까지 자동으로 생성하고 있습니다. 사람이 100% 결정하던 영역이 이제는 ‘사람과 에이전트가 함께 결정하는’ 방향으로 옮겨가고 있는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image3.jpg"&gt;&lt;figcaption&gt;운영 자동화의 변화 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇다면 자연스럽게 이런 질문이 생깁니다. &lt;strong&gt;과연 이 도구들에게 K8s 운영을 맡겨도 정말로 괜찮을까요?&lt;/strong&gt; 그렇다면 시장에서 쓰이는 것들 가운데 어떤 도구를 선택해야 할까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이를 확인하기 위해 Claude Code, Gemini CLI, Codex CLI의 9개 모델 조합을 동일한 K8s 장애 상황 10개에 똑같이 투입해 보았습니다. 결론부터 말하면, 세 도구 모두 실무에 활용할 수 있었습니다. 다만 어떤 작업을 맡기느냐에 따라 더 적합한 모델은 분명히 달랐습니다. 꼭 비싸고 성능이 강력한 모델이 항상 운영 업무를 더 잘 수행하는 것도 아니었습니다. 이 글에서는 그 측정 결과를 정리해 보겠습니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실험 설계: 9개 에이전트 × 10개 K8s 장애&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 실험에서는 세 가지 도구의 코딩 능력이 아니라 &lt;strong&gt;운영 능력&lt;/strong&gt;을 보고 싶었습니다. 그래서 일반 코딩 벤치마크를 들고 오는 대신, 운영자가 실제로 겪을 법한 K8s 장애 시나리오 10개를 직접 만들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;시나리오&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image5.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;쉬운 시나리오&lt;span style="color:#999999;"&gt;(★)&lt;/span&gt;는 로그에 답이 거의 그대로 적혀 있습니다. 반면 어려운 시나리오&lt;span style="color:#999999;"&gt;(★★★★★)&lt;/span&gt;는 &lt;strong&gt;‘고치지 않는 것’이 정답&lt;/strong&gt;인 상황입니다. 예를 들어 ext-dep은 데이터베이스 호스트가 DNS에 등록되어 있지 않은 상황으로, K8s 안에서 할 수 있는 일이 없습니다. 이럴 때는 “DB 인프라 팀에 확인 요청이 필요하다”라고 정직하게 보고하는 에이전트가 만점을 받습니다. 임의로 환경변수를 고치는 에이전트는 오히려 감점을 줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;*이렇게 만든 결과물은&lt;/span&gt; &lt;a href="https://github.com/sysnet4admin/Research/tree/main/AIOps-Agent-Benchmark"&gt;AIOps Agent Benchmark&lt;/a&gt; &lt;span style="color:#999999;"&gt;깃허브에 정리되어 있습니다.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;9개 에이전트&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;세 브랜드의 도구에 영향을 미치는 가장 큰 요소는 결국 모델입니다. 이는 각각 세 티어로 나누어 비교했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image1.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또한, 공정을 기하기 위해 모든 에이전트는 &lt;strong&gt;같은 클러스터, 같은 프롬프트, 콜드 스타트&lt;/strong&gt; 조건에서 실행했습니다. 실행 전마다 클러스터 스냅샷을 복원해 직전 실행의 영향이 남지 않도록 했고, 시나리오마다 사전 작성된 채점 기준에 따라 사람이 점수를 매겼습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;*측정 당시 최상위 모델을 적용하였는데, 이후로 출시된 Opus 4.8, Gemini-3.5-flash 등은 제외되었습니다.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image6.jpg"&gt;&lt;figcaption&gt;9개 에이전트 매트릭스 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;결과: 효율 티어 &amp;gt; 플래그십&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;곧바로 결과부터 함께 보겠습니다. 여러 차례 반복해 평균 낸 결과는 다음과 같습니다. &lt;span style="color:#999999;"&gt;(2026년 5월 측정 기준)&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image4.jpg"&gt;&lt;figcaption&gt;처리 효율 vs Ops_Score 점도표 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;핵심만 보면 이렇습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;9개 중 1위는 효율 기준, Sonnet 4.6&lt;/strong&gt;입니다. 모든 플래그십 모델보다 점수가 높았습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;브랜드별로 특징이 뚜렷하게 갈립니다. Claude는 품질과 안전 쪽, Gemini는 효율 쪽, Codex는 중간입니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;Lite 티어에서는 의외로 Haiku가 아니라 &lt;strong&gt;Gemini Flash-Lite&lt;/strong&gt;가 1위를 차지했습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;상위 티어 모델이 항상 좋은 것이 아니라는 사실, 그리고 같은 가격대 안에서도 브랜드별 성격이 다르다는 사실이 운영자 입장에서 꽤 흥미로운 발견이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#757575;"&gt;&lt;i&gt;아울러 미리 짚어둘 점이 있습니다. 이번 순위는 한 차례만 측정한 값이 아닙니다. 약 2주에 걸쳐 같은 시나리오를 수십 번 반복해 돌린 결과를 평균 낸 것입니다. 다만 모델과 CLI는 빠르게 바뀌므로, “누가 1등인가”보다 “어떤 성격인가”에 무게를 두고 읽으시길 권합니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;Claude vs. Gemini vs. Codex&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;수치만으로는 차이가 잘 와닿지 않습니다. 셋의 성격을 실제 운영 상황에 대입해 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;Claude: 신중한 진단의&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;위험한 행동이 가장 적습니다. 그렇기에 품질×안전성 점수가 가장 높습니다. 진단할 때면 로그를 끝까지 확인하고, 근거 없이 환경변수를 변경하거나 파드를 강제 삭제하지 않습니다. 단점이라면 &lt;strong&gt;토큰 사용량이 많다&lt;/strong&gt;는 것입니다. 같은 결과를 내는 데 다른 모델보다 토큰이 많이 소모되는 경우가 잦습니다. 비유하자면, 모든 환자에게 전체 패키지로 검진할 것을 권하는 의사입니다. 진단의 정확도는 높지만 비용도 같이 올라갑니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;Gemini: 빠르고 가벼운&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;처리 효율 점수에서 항상 1위를 차지했습니다. 즉, 같은 작업을 가장 적은 토큰과 시간으로 완수합니다. 단점은 &lt;strong&gt;어려운 시나리오에서 안정성이 떨어진다&lt;/strong&gt;는 것입니다. 가장 좋은 모델인 Gemini 2.5 Pro조차 높은 단계 합격률이 89%로 낮아지는데, 다른 두 브랜드 Flagship이 97~98%인 것과 대조됩니다. 이는 마치 응급실에서 분류를 잘하는 의사 같습니다. 빠른 판단이 강점이지만, 복잡한 환자가 들어오면 가끔 흔들립니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;Codex: 사고할 줄 알지만 느린&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;품질과 안전성은 Claude에 견줄 만하지만, 효율이 가장 낮습니다. 동일한 작업 대비 토큰이 많이 소모되고 시간도 오래 걸립니다. 그리고 한 가지 운영적으로 까다로운 점이 있는데, &lt;strong&gt;추론 강도 기본값이 가장 높게 설정&lt;/strong&gt;되어 있어서 그대로 사용하면 Sonnet 같은 효율 티어와 공정하게 비교하기 어렵습니다. 추론 강도를 의도적으로 낮춰야 같은 급에서 비교가 가능합니다. 그러므로 모든 환자에게 정밀 검사를 처방하는 의사 정도로 느껴집니다. 정확도는 좋지만 대기 시간이 길고 비용도 높습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image8.jpg"&gt;&lt;figcaption&gt;세 브랜드의 운영 캐릭터 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;운영 과제에서 발견한 의외의 행동들&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;벤치마크 점수표보다 더 흥미로웠던 것은, &lt;strong&gt;운영 과제에서만 보이는 행동 패턴&lt;/strong&gt;들이었습니다. 다른 코딩 벤치마크에서는 좀처럼 드러나지 않는 모습입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1. 가장 비싼 모델의 가장 기본적인 실수&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;한 최상위 모델은 프롬프트&lt;span style="color:#999999;"&gt;(Context / Task / Rules 형식)&lt;/span&gt;를 &lt;strong&gt;실제 작업 지시가 아니라 “벤치마크 정의 문서”라고 오인&lt;/strong&gt;했습니다. 결국 kubectl을 한 번도 실행하지 않은 채 28초 만에 종료했습니다. 정확도 점수는 0이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;흥미로운 것은, 같은 프롬프트를 하위 티어 모델은 정상적으로 처리했다는 점입니다. 모델이 더 똑똑할수록 “내가 평가받는 상황이구나”라고 인식하는 정도가 강해지는 것 같습니다. 이 인식이 어느 선을 넘으면, 일을 하는 대신 일의 본질을 의심하기 시작합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이는 결국 운영 자동화 입장에서는 치명적입니다. 한가한 시간에 알람이 잘못 트리거됐을 때, 가장 비싼 모델이 “이건 실제 알람이 아닌 것 같다”고 판단하고 대응을 중단할 수 있다는 뜻이기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2. CLI 안쪽 숨은 의존성이 망치는 결과&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;어떤 에이전트는 작업이 돌다 빈 결과 파일을 만들었습니다. 그러니 밖에서 보면 그냥 “에이전트가 실패한 것”으로만 보였습니다. 다만 그 과정을 보니 실제 원인은 모델이 아니라 CLI 구현 안쪽의 숨은 의존성에 있었습니다. 이 에이전트는 &lt;strong&gt;web search 도구&lt;/strong&gt;가 내부적으로 보조 모델을 호출하는 구조였는데, 그 보조 모델에 접근할 수 없게 되자 &lt;strong&gt;세션 전체가 통째로 중단&lt;/strong&gt;되었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;도입을 검토할 때 우리는 보통 이 모델이 얼마나 잘하는지만 봅니다. 그러나 &lt;strong&gt;CLI라는 껍데기&lt;/strong&gt;가 들고 있는 도구, 즉, 내부에서 호출하는 보조 모델이나 재시도 로직이 운영 안정성의 상당 부분을 결정합니다. 모델만 보고 벤더 선택을 끝내서는 안 된다는 점이 분명해졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3. 비싼 모델이 ‘반드시’ 더 낫지는 않다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;같은 Claude 브랜드 안에서 Opus 4.7과 Sonnet 4.6의 종합 점수는 &lt;strong&gt;통계적으로 거의 같았습니다&lt;/strong&gt;. 다만 시나리오 난이도별로 보면 패턴이 갈립니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;쉬운 시나리오에서는 Sonnet이 같은 품질을 더 적은 토큰과 시간으로 해냅니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;어려운 시나리오&lt;span style="color:#999999;"&gt;(★★★★ 이상)&lt;/span&gt;에서는 Opus의 완수율이 한 단계 위입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한국 SRE 팀의 평소 업무를 떠올려 보면, 일상적으로 처리하는 알람의 대다수는 ★~★★ 난이도입니다. 즉 &lt;strong&gt;Sonnet으로 충분&lt;/strong&gt;하다는 뜻입니다. 반면 Opus는 “분기말 결산 직전에 동시에 발생하는 복합 장애”처럼 난도가 높은 상황에 한정해 사용하는 것이 합리적입니다. 매번 가장 비싼 모델을 사용하는 선택은 비용 면에서 효율이 떨어집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;‘한국 운영 팀’에 도입하기 전 체크할 다섯 가지&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;여기까지, 수치는 수치고, 실제로 도입하려면 한국 운영 환경 특유의 조건 역시 같이 봐야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;1. 자동 승인 모드를 받아들일 수 있는가?&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번 벤치마크의 모든 결과는 에이전트에게 사람의 확인 없이 kubectl을 실행할 수 있는 권한을 부여한 상태에서 측정했습니다. 따라서 사내 보안 정책상 자동 실행 자체를 허용하지 않는다면, 결과를 해석하는 방식도 달라집니다. 사람 승인 게이트를 추가하면 안전성은 높아지지만, 그만큼 효율 점수는 크게 낮아지는 트레이드오프가 발생합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;strong&gt;2. 사내 정책상 외부 LLM 호출이 가능한가?&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;세 CLI 모두 외부 API에 의존합니다. 즉, 사내망에서 외부 통신이 차단되어 있거나, 데이터의 외부 전송이 제한되는 환경이라면. 우회 게이트웨이나 사내 프록시를 거쳐야 합니다. 그 과정에서 응답 지연이 발생하며, 일부 CLI는 인증 구성이 복잡해져 운영 부담이 늘어날 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;3. 어느 시나리오부터 위임할 것인가?&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;처음부터 ★★★★★ 수준의 시나리오를 맡기는 것은 무리입니다. 우선 ★~★★ 수준의 시나리오부터 시작해 안정성을 검증한 뒤, 사람이 검토하는 비율을 단계적으로 줄여가는 게 안전합니다. 초기에는 에이전트가 진단하고, 사람이 사후 검토하는 ‘관찰 모드’로 운영하는 것이 가장 현실적입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;4. 휴먼 검토 게이트를 어디에 둘 것인가?&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;가장 흔한 위치는 &lt;strong&gt;실제 변경이 적용되기 직전&lt;/strong&gt;입니다. 에이전트가 진단까지 마치고 kubectl apply나 helm upgrade 직전에 사람에게 최종 승인을 요청하는 구조입니다. 이 게이트의 형태가 도입 성공률을 좌우합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;5. 비용 모니터링을 함께 도입할 것인가?&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;자동 실행 환경을 운영하다 보면 토큰 사용량이 예상보다 빠르게 커집니다. 특히 Claude처럼 토큰을 많이 사용하는 브랜드는 월말 청구액이 예상을 크게 웃돌 수 있습니다. 도입과 동시에 사용량 알람을 설정하는 것이 좋습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image7.jpg"&gt;&lt;figcaption&gt;5가지 도입 체크리스트 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;그래서 무엇을, 어떻게 골라야 할까?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;세 가지 브랜드와 모델의 효율과 성능, 또 특성과 체크리스트를 고려했을 때, 상황별 추천을 단순화하면 이렇습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3817/image2.png"&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;추가 실험에서 발견할 것들&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;지금까지 기준으로 삼은 순위표는 약 2주 동안 동일한 10개 시나리오를 수십 차례 반복 측정한 뒤 평균을 낸 결과입니다. 다만, 순위표를 낸 후에도 약 사흘 동안 같은 조건으로 추가 측정을 진행하며 여러 차례 다시 실행해 보았습니다. 그 결과, 몇 가지 흥미로운 점을 확인할 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;먼저 &lt;strong&gt;큰 흐름은 변하지 않았습니다.&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;브랜드별 성격&lt;span style="color:#999999;"&gt;(신중한 Claude, 빠른 Gemini, 사고하는 Codex)&lt;/span&gt;은 추가 측정에서도 일관됐습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;상위 티어가 항상 우위는 아니라는 점, 효율 티어도 충분히 경쟁력 있다는 점도 그대로였습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;어려운 시나리오일수록 모델 간 차이가 벌어지는 패턴도 안정적이었습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반면 &lt;strong&gt;점수가 거의 비슷한 티어에서는 순위가 측정할 때마다 바뀌었습니다.&lt;/strong&gt; 특히 0.01~0.02 수준의 근소한 차이로 갈리는 구간에서는 측정 때마다 1등 모델이 달라졌습니다. 이런 작업에는 단 한 번의 결과만으로 “이 모델이 최고다”라고 단정하기보다, 여러 차례 측정했을 때 나타나는 흐름을 함께 보는 편이 더 안전합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한 가지 실용적인 발견도 있었습니다. 절대 점수와는 별개로, 반복 측정 시 편차가 가장 작았던 도구는 Codex였습니다. 다시 말해, 가장 예측 가능한 결과를 보여준 것입니다. 점수 자체는 Sonnet 같은 모델이 더 높게 나타나기도 했지만, Codex는 어느 회차에 실행하더라도 비슷한 결과를 냈습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;운영 자동화 관점에서 보면 강점이 다릅니다. 어떤 환경에서는 ‘한 번이라도 가장 높은 성과를 내는 모델’이 중요할 수 있습니다. 반대로 어떤 환경에서는 ‘매번 비슷한 결과를 내는 모델’이 더 다루기 쉽습니다. 결과 편차가 크면 사람이 언제 개입해야 하는지 판단하기 어려워지기 때문입니다. 그러니 순위표의 절대 점수만큼이나, &lt;strong&gt;얼마나 일관되게 그 점수를 내는지&lt;/strong&gt;도 함께 살펴봐야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;정리하면, 이 순위표는 약 2주간의 반복 측정을 바탕으로 정리한 결과이기 때문에 브랜드별 성격과 전반적인 흐름은 충분히 신뢰하고 활용할 수 있습니다. 다만 점수가 근소하게 갈리는 구간은 ‘순위가 자주 뒤바뀌는 접전 구간’으로 이해하는 것이 적절합니다. 따라서 &lt;strong&gt;도구를 선택할 때는 절대 점수뿐 아니라 결과의 일관성까지 함께 따져보시길&lt;/strong&gt; 권합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;작년에는 &lt;a href="https://yozm.wishket.com/magazine/detail/3559/"&gt;Gateway API 7개 구현체를 비교한 글&lt;/a&gt;을 썼습니다. K8s 운영자가 새로 도입을 검토해야 할 &lt;strong&gt;도구&lt;/strong&gt;를 정리한 글이었습니다. 반면, 올해는 그 도구를 &lt;strong&gt;다루는 AI&lt;/strong&gt;를 비교했습니다. 1년 만에 운영자의 일이 다시 한 단계 추상화된 셈입니다. 작년에 필요한 일이 “어떤 Gateway를 고를 것인가”였는데, 올해는 “그 Gateway를 우리 대신 다룰 에이전트로 누구를 고를 것인가”로 바뀐 것이지요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런 맥락에서 지금이 에이전트 도입 적기인지를 물으면, 솔직히 답은 &lt;strong&gt;부분적으로 그렇다&lt;/strong&gt; 입니다. ★~★★ 난이도 알람 1차 분류 정도는 충분히 맡길 수 있습니다. 단, 가장 비싼 모델이 무조건 답이 아니고, 자동 승인을 그대로 적용하기보다는 휴먼 게이트를 끼운 형태로 시작하는 게 안전합니다. 물론 1년 후에는 이 글의 결론도 달라질 가능성이 큽니다. 그러므로 언제든 &lt;strong&gt;자신의 환경에서 직접 측정해 보는 것&lt;/strong&gt;이 가장 정확합니다. 이번 실험이 여러분의 생태계 확장에 도움이 되기를 바라겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;*전체 시나리오 정의와 측정 코드는&lt;/span&gt; &lt;a href="https://github.com/sysnet4admin/Research/tree/main/AIOps-Agent-Benchmark"&gt;GitHub 저장소&lt;/a&gt;&lt;span style="color:#999999;"&gt;에, 점수 설계의 이유와 분석은&lt;/span&gt; &lt;a href="https://kuberneteslab.dev/ko/blog/aiops-agent-benchmark/"&gt;블로그&lt;/a&gt;&lt;span style="color:#999999;"&gt;에 정리해 두었습니다.&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;h4 style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;작가&lt;/strong&gt;&lt;/h4&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;조훈(CNCF 앰버서더)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;쿠버네티스와 AI 네이티브 기술 전문가로, 클라우드 네이티브 컴퓨팅 재단(CNCF)의 글로벌 앰버서더이자 Kubestronaut이다. 쿠버네티스랩&lt;span style="color:#999999;"&gt;(kuberneteslab.dev)&lt;/span&gt;을 운영하며 인프라 자동화와 AI 네이티브 기술을 연구하고 공유하고 있다. ‘IT 인프라 엔지니어 그룹’ 운영진이자 오픈소스 컨트리뷰터로도 활동하고 있다. 맞춤형 기술 교육, 쿠버네티스 비용 최적화, AI 에이전트 비교 검증 등 다양한 PoC를 진행하고 있다. 『한 걸음 앞선 개발자가 지금 꼭 알아야 할 클로드 코드』, 『컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커』 등을 집필했다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;심근우&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;LG유플러스 CTO부문에서 대고객 비즈니스 시스템의 DevOps를 담당하는 UcubeDAX팀의 팀장으로 일하고 있다. 퍼블릭 클라우드와 프라이빗 클라우드에 걸친 쿠버네티스 클러스터를 안정적으로 운영하기 위해 노력하고 있으며, 특히 주니어 DevOps 엔지니어들의 육성에 큰 관심을 가지고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;문성주&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;글로벌 소셜 플랫폼 기업에서 Site Reliability Engineer로 재직하며, 쿠버네티스 멀티 클러스터 관리와 데이터베이스 플랫폼 운영을 주도하고 있다. 또한 ISMS-P, GDPR, CCPA 등 글로벌 보안 규제에 부합하는 데이터 라이프사이클 파이프라인을 설계·운영한 실무 경험을 가지고 있으며, 쿠버네티스 오픈소스 프로젝트에도 기여하고 있다. 더불어 국내 주요 기업과 국가 기관의 클라우드 전환, 데이터 거버넌스 컨설팅, 보안 컴플라이언스 대응을 지원하고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;&lt;strong&gt;이성민&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:justify;"&gt;미국 넷플릭스(Netflix) 사의 Data Platform Infrastructure 팀에서 사내 플랫폼 팀들과 데이터 사용자들을 어우르기 위한 가상화 및 도구들을 개발하는 일들을 하고 있다. 과거 컨테이너와 쿠버네티스에 큰 관심을 두고 ingress-nginx를 비롯한 오픈 소스에 참여했으며, 현재는 데이터 분야에 일하게 되면서 stateful 한 서비스들이 컨테이너화에서 겪는 어려움을 보다 근본적으로 해결하기 위한 많은 노력을 하고 있다.&lt;/p&gt;&lt;p style="margin-left:0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>개발자는 여전히 수학을 잘해야 할까요?</title><link>https://yozm.wishket.com/magazine/detail/3813</link><description>개발 공부를 시작하려는 분들에게 자주 받는 질문이 있습니다.“수학을 잘하지 못하는데 개발자가 될 수 있을까요?”, “문과 출신인데 프로그래밍을 배워도 괜찮을까요?”, “알고리즘 문제를 풀 때마다 막히는데, 계속 공부해도 될까요?” 저 역시 컴퓨터공학과를 다니면서 비슷한 고민을 했습니다. 그런데 한국과 일본에서 실제로 개발자로 일해보니, 학교에서 상상했던 개발자의 모습과 현장에서 필요한 능력은 조금 달랐습니다. 현업에서 제가 더 자주 마주친 것은 미적분 공식이 아니라 모호한 요구사항이었습니다. 이번 글에서는 과거에는 왜 수학이 중요했는지, 지금의 개발 환경은 어떻게 달라졌는지, 그리고 수학이 약한 개발자는 무엇부터 준비하면 좋을지 현실적인 관점에서 이야기해 보겠습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3813</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;수학 때문에 개발을 망설이는 분들께 전하고 싶은 현실적인 이야기&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개발 공부를 시작하려는 분들에게 자주 받는 질문이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;&lt;i&gt;“수학을 잘하지 못하는데 개발자가 될 수 있을까요?”&lt;/i&gt;&lt;br&gt;&lt;i&gt;“문과 출신인데 프로그래밍을 배워도 괜찮을까요?”&lt;/i&gt;&lt;br&gt;&lt;i&gt;“알고리즘 문제를 풀 때마다 막히는데, 계속 공부해도 될까요?”&lt;/i&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저 역시 컴퓨터공학과를 다니면서 비슷한 고민을 했습니다. 이산수학, 자료구조, 알고리즘 수업을 들을 때마다 개발자는 원래 수학을 잘해야 하는 직업이 아닐까 생각했습니다. 복잡한 수식을 빠르게 이해하는 동기들을 보면 괜히 위축되기도 했습니다. 시험 문제가 잘 풀리지 않는 날에는 개발자로 일하는 미래가 조금 멀게 느껴지기도 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 한국과 일본에서 실제로 개발자로 일해보니, 학교에서 상상했던 개발자의 모습과 현장에서 필요한 능력은 조금 달랐습니다. 현업에서 제가 더 자주 마주친 것은 미적분 공식이 아니라 모호한 요구사항이었습니다. 선형대수보다 고객 문의를 더 많이 다뤘고, 복잡한 수식보다 예상하지 못한 오류의 원인을 찾는 데 더 많은 시간을 사용했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 수학은 중요합니다. 수학을 잘하면 문제를 구조적으로 바라보는 데 도움이 되고, 특정 개발 분야로 성장할 때도 분명한 강점이 됩니다. 다만 모든 개발자가 같은 수준의 수학을 필요로 하는 것은 아닙니다. 개발 분야와 담당 업무에 따라 필요한 수학의 깊이는 크게 달라집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;최근에는 인공지능(AI) 도구가 코드를 제안하는 수준을 넘어, 프로젝트를 분석하고 여러 파일을 수정하며 테스트까지 수행하는 방향으로 발전하고 있습니다. 이제 개발자는 코드를 얼마나 빠르게 입력하는지뿐만 아니라, 무엇을 만들어야 하는지 정의하고 결과물을 판단할 수 있어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇다면 지금 시대에도 수학은 여전히 중요할까요? 수학이 부족하다고 느끼는 사람은 개발자를 포기해야 할까요? 이번 글에서는 과거에는 왜 수학이 중요했는지, 지금의 개발 환경은 어떻게 달라졌는지, 그리고 수학이 약한 개발자는 무엇부터 준비하면 좋을지 현실적인 관점에서 이야기해 보겠습니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;프로그래밍과 수학은 얼마나 가까운 관계일까요?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;프로그래밍의 본질은 문제를 해결하는 과정입니다. 복잡한 문제를 작은 단위로 나누고, 필요한 조건을 정리한 뒤, 컴퓨터가 이해할 수 있는 명령으로 바꾸는 일입니다. 이 과정은 수학 문제를 푸는 흐름과 닮아 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;쇼핑몰의 결제 금액을 계산하는 기능을 예로 들어보겠습니다. 상품 가격을 더하고, 쿠폰 할인 금액을 빼고, 배송비를 추가합니다. 특정 금액 이상을 구매하면 배송비를 무료로 처리할 수도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;겉으로 보기에는 단순한 덧셈과 뺄셈입니다. 하지만 실제 서비스를 만들기 시작하면 고려해야 할 조건이 빠르게 늘어납니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image9.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실무에서는 복잡한 공식을 외우는 능력보다, 이런 예외 상황을 빠짐없이 찾아내는 능력이 중요합니다. 배열을 정렬하는 알고리즘도 비슷합니다. 데이터를 비교하고, 위치를 바꾸고, 다시 비교하는 과정이 반복됩니다. 지도에서 가장 빠른 길을 찾는 기능도 거리와 조건을 비교하는 문제입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;프로그래밍과 수학은 분명 연결되어 있습니다. 하지만 이 관계를 “수학 문제를 빨리 풀어야 코딩도 잘한다”라고 단순하게 해석하면 곤란합니다. 개발자에게 필요한 것은 수학적 재능만이 아닙니다. 복잡한 문제를 정리하고, 해결 가능한 단위로 나누며, 결과를 하나씩 검증하는 사고방식이 더 중요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image8.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;과거의 프로그래밍에서는 왜 수학이 더 중요했을까요?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;과거의 프로그래밍은 지금보다 컴퓨터와 가까운 작업이 많았습니다. 오늘날에는 다양한 라이브러리와 프레임워크가 복잡한 처리를 대신해 줍니다. 하지만 저수준 프로그래밍 환경에서는 개발자가 메모리와 중앙처리장치(CPU)의 동작을 직접 이해해야 하는 경우가 많았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;어셈블리 언어(Assembly Language)로 두 숫자를 더하는 간단한 예제를 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image7.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 짧은 코드에서도 개발자는 값을 어느 레지스터에 불러올지, 어떤 값을 더할지, 결과를 어디에 저장할지 직접 지정해야 합니다. 저수준 개발에서는 이진법, 논리 연산, 메모리 주소, 자료형의 크기 같은 개념을 이해해야 했습니다. 작은 실수 하나가 예상하지 못한 오류로 이어질 수도 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;그래픽스 분야에서는 벡터와 행렬이 중요했습니다. 게임 개발에서는 좌표와 물리 계산이 필요했고, 암호학에서는 수학적 원리를 이해해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 한 가지는 구분해야 합니다. 과거의 개발자에게 필요했던 것이 모두 고급 수학은 아니었습니다. 컴퓨터 구조를 이해하는 능력, 논리적으로 사고하는 습관, 작은 차이를 놓치지 않는 집중력도 함께 중요했습니다. 그래서&lt;strong&gt;“과거에는 수학이 중요했고, 지금은 필요 없다”&lt;/strong&gt;라고 단순하게 나누기는 어렵습니다. 개발 분야에 따라 필요한 능력이 달랐고, 지금도 마찬가지입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image5.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;지금은 모든 것을 직접 만들지 않습니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;지금의 개발 환경은 과거와 크게 달라졌습니다. 웹 개발만 보더라도 리액트(React), 뷰(Vue), 넥스트제이에스(Next.js), 스프링부트(Spring Boot)처럼 잘 만들어진 라이브러리와 프레임워크가 존재합니다. 개발자는 모든 기능을 처음부터 구현하지 않아도 됩니다. 인증, 데이터베이스 연결, 화면 상태 관리, 서버 통신, 배포 자동화처럼 복잡한 기능도 검증된 라이브러리와 서비스를 활용해 빠르게 구성할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;회원가입 기능을 예로 들어볼까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개발자는 입력값 검사, 비밀번호 암호화, 세션 관리, 이메일 인증, 오류 처리 같은 여러 요소를 고려해야 합니다. 지금은 프레임워크와 외부 서비스를 활용해 많은 부분을 효율적으로 구성할 수 있습니다. 그렇다고 개발자의 일이 단순해진 것은 아닙니다. 오히려 고민해야 할 대상이 달라졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;과거에는&lt;strong&gt;“어떻게 직접 구현할까?”&lt;/strong&gt;를 먼저 고민했다면, 지금은 다음과 같은 질문을 더 자주 하게 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image2.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;직접 모든 것을 만드는 시대에서, 적절한 도구를 선택하고 조합하는 시대로 이동한 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;레고 블록에 비유해 보겠습니다. 과거의 개발자는 블록 자체를 직접 깎아야 했습니다. 지금의 개발자는 이미 만들어진 수많은 블록 중에서 적절한 것을 골라 안정적인 구조물을 완성해야 합니다. 블록을 직접 만들지 않는다고 해서 쉬운 것은 아닙니다. 잘못된 블록을 선택하거나 연결 방식을 이해하지 못하면, 완성된 구조물은 금방 무너질 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image6.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;수학이 중요한 분야는 분명히 존재합니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;“개발자에게 수학이 필요한가요?”&lt;/strong&gt;라는 질문에 하나의 정답을 내리기 어려운 이유는 개발 분야가 매우 넓기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;웹 프론트엔드 개발자가 일반적인 화면을 구현할 때는 고급 미적분을 사용할 일이 많지 않습니다. 관리 시스템을 개발하는 백엔드 개발자도 매일 행렬 계산을 하지는 않습니다. 하지만 AI 모델을 설계하거나, 게임 엔진을 개발하거나, 암호화 알고리즘을 연구하는 개발자는 이야기가 달라집니다. 수학을 이해하지 못하면 문제의 원리 자체를 파악하기 어려울 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image4.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이를 축구에 비유해 볼까요? 메시처럼 드리블, 패스, 골 결정력까지 다양한 능력을 높은 수준으로 갖춘 선수는 극히 드뭅니다. 하지만 모든 선수가 메시처럼 뛰어야만 팀에 기여할 수 있는 것은 아닙니다. 인자기는 뛰어난 위치 선정 능력으로 골을 만들어냈고, 솔샤르는 결정적인 순간에 기회를 놓치지 않는 집중력으로 팀에 기여했습니다. 각자 가진 강점은 달랐지만, 그 강점을 제대로 활용했기 때문에 오래 기억되는 선수가 될 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;개발자도 마찬가지입니다. 모든 개발자가 복잡한 알고리즘을 직접 설계하거나, 고급 수학을 자유자재로 다룰 필요는 없습니다. 고객의 요구사항을 정확하게 이해하는 개발자도 필요하고, 장애 원인을 빠르게 찾아내는 개발자도 필요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;팀원이 읽기 쉬운 코드를 작성하거나, 새로운 기술을 빠르게 익혀 프로젝트에 적용하는 능력도 충분히 중요한 강점입니다. 수학적 직관이 부족하다고 해서 미리 낙담할 필요는 없습니다. 자신의 강점을 발견하고, 부족한 부분은 조금씩 보완해 나가면 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image10.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;현업에서 더 자주 마주친 것은 따로 있었습니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;한국과 일본에서 웹 개발자로 일하면서, 복잡한 수식을 직접 사용할 일은 생각보다 많지 않았습니다. 대신 고객이 원하는 기능을 정확하게 이해해야 했습니다. 이미 작성된 코드를 읽고 오류의 원인을 찾아야 했고, 예상하지 못한 장애가 발생하면 로그를 분석해야 했습니다. 팀원에게 문제 상황을 설명하는 일도 중요했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;특히 일본 개발 현장에서는 보고·연락·상담을 의미하는 &lt;strong&gt;호렌소(報連相)&lt;/strong&gt;를 중요하게 생각했습니다. 문제가 발생했을 때 혼자 끌어안기보다, 현재 상황과 예상되는 위험을 정리해 공유해야 했습니다. 개발 실력이 뛰어나더라도 설명이 부족하면 팀 전체의 일정이 흔들릴 수 있습니다. 반대로 아직 경험이 많지 않은 개발자라도 문제를 빠르게 공유하고, 필요한 도움을 정확하게 요청하면 프로젝트에 큰 기여를 할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;제가 현장에서 중요하다고 느낀 능력은 다음과 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image3.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;흥미로운 점은 이러한 능력도 넓은 의미에서는 수학적 사고와 연결된다는 것입니다. 복잡한 문제를 나누고, 가설을 세우고, 하나씩 검증하는 방식은 수학 문제를 푸는 과정과 닮았습니다. 다만 중요한 것은 빠른 암산이나 어려운 공식이 아닙니다. 문제를 끝까지 포기하지 않고, 구조적으로 바라보는 태도입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image13.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;AI 에이전트가 코드를 만드는 시대에는 무엇이 달라질까요?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;챗GPT(ChatGPT), 클로드(Claude), 제미나이(Gemini)&lt;/strong&gt;같은 생성형 AI 서비스가 등장한 이후, 개발 환경은 빠르게 바뀌었습니다. 최근에는 여기서 한 단계 더 나아가고 있습니다. 단순히 질문에 답하거나 코드 일부를 자동으로 완성해 주는 수준을 넘어, 프로젝트 구조를 파악하고 여러 파일을 수정하며, 테스트까지 수행하는 AI 에이전트가 등장하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;클로드 코드(Claude Code), 코덱스(Codex), 구글 안티그래비티(Google Antigravity), 커서(Cursor)&lt;/strong&gt;같은 도구가 대표적인 사례입니다. 예전에는 개발자가 오류 메시지를 검색하고, 관련 파일을 직접 찾은 뒤, 하나씩 수정하고 테스트해야 했습니다. 이제는 AI 에이전트에게 요구사항을 전달하면 관련 코드를 분석하고, 수정 방향을 제안하며, 일부 작업은 직접 수행하기도 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;개발자가 코드를 작성하는 방식 자체가 달라지고 있는 것입니다. 저 역시 개발 과정에서 AI 도구를 활용하고 있습니다. 이전에는 검색 결과를 여러 페이지에 걸쳐 확인해야 했던 문제도, AI를 활용하면 필요한 방향을 빠르게 좁힐 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇다면 기본기를 공부할 필요도 줄어든 걸까요? 오히려 반대에 가깝다고 생각합니다. AI는 그럴듯한 코드를 빠르게 만들어줍니다. 하지만 결과가 항상 정확한 것은 아닙니다. 작은 기능에서는 잘 동작하던 코드가 실제 운영 환경에서는 느려질 수도 있고, 보안상 위험한 방식이 포함될 수도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;AI가 작성한 코드가 왜 동작하는지 이해하지 못하면 수정하기 어렵습니다. 오류가 발생해도 어디부터 확인해야 할지 판단하기 어렵습니다. 내비게이션이 길을 알려준다고 해서 운전자가 교통 표지판을 몰라도 되는 것은 아닙니다. AI 시대의 개발도 비슷합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;도구가 좋아질수록 개발자는 더 빠르게 이동할 수 있습니다. 하지만 어디로 가야 하는지 판단하고, 위험한 길을 피하며, 결과에 책임지는 일은 여전히 개발자의 몫입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image12.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;수학이 약한 개발자는 무엇부터 공부하면 좋을까요?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;수학에 자신이 없다고 해서 갑자기 미적분 교재부터 펼칠 필요는 없습니다. 먼저 자신이 일하고 싶은 분야에서 실제로 필요한 개념을 정리하는 것이 좋습니다. 웹 개발을 목표로 한다면, 고급 수학보다 프로그래밍의 기본 구조와 데이터 흐름을 먼저 이해하는 편이 효과적입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1단계: 조건과 반복을 익혀봅니다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;조건문과 반복문&lt;/strong&gt;은 프로그래밍의 가장 기본적인 도구입니다. 단순한 문법처럼 보이지만, 대부분의 비즈니스 로직은 이 조합에서 시작됩니다. 쇼핑몰의 쿠폰 적용, 회원 등급에 따른 혜택, 예약 가능 시간 확인 같은 기능도 결국 조건을 나누고 반복적으로 데이터를 확인하는 과정입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2단계: 자료구조와 알고리즘의 기초를 이해합니다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;모든 알고리즘 문제를 빠르게 풀 필요는 없습니다. &lt;strong&gt;배열, 객체, 스택, 큐, 정렬, 탐색&lt;/strong&gt;같은 기본 개념부터 익혀도 충분합니다. 중요한 것은 정답을 외우는 것이 아니라, 어떤 상황에서 어떤 구조를 선택하는지 이해하는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3단계: 작은 프로젝트를 직접 완성해 봅니다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;공부한 내용을 실제 기능으로 만들어보면 부족한 부분이 선명하게 보입니다. 회원가입, 게시판, 일정 관리처럼 작은 프로젝트라도 좋습니다. &lt;strong&gt;데이터를 저장하고, 오류를 처리하고, 화면에 결과&lt;/strong&gt;를 보여주는 흐름을 경험해 보는 것이 중요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;4단계: 필요한 수학은 그때 다시 공부합니다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;데이터 분석이 필요해지면 통계를 공부하고, 그래픽스를 다루게 되면 벡터와 행렬을 공부하면 됩니다. 개발자의 공부는 한 번에 모든 것을 끝내는 시험이 아닙니다. 필요할 때 다시 돌아가 부족한 부분을 채우는 긴 과정입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3813/image11.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며: 완벽한 개발자보다 꾸준한 개발자가 오래갑니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;수학은 프로그래밍에서 분명 중요한 도구입니다. 수학을 잘하면 문제를 구조적으로 바라보는 데 도움이 되고, 알고리즘을 이해하거나 특정 분야로 성장할 때도 유리합니다. 하지만 수학을 잘하지 못한다고 해서 개발자가 될 수 없는 것은 아닙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;복잡한 알고리즘을 만드는 개발자도 필요하지만, 고객의 요구를 정확하게 이해하는 개발자도 필요합니다. 장애를 빠르게 분석하는 개발자도 필요하고, 팀원들이 읽기 쉬운 코드를 작성하는 개발자도 필요합니다. AI 시대에는 개발자의 역할이 더 빠르게 바뀔 수 있습니다. 하지만 문제를 해결하려는 태도와 꾸준히 배우는 습관은 쉽게 사라지지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;br&gt;혹시 수학이 부족하다는 이유로 개발을 망설이고 계신가요? 너무 겁먹지 않으셔도 괜찮습니다. 수학을 완벽하게 공부한 뒤에 개발을 시작해야 하는 것은 아닙니다. 먼저 작은 문제부터 해결해보고, 필요한 수학은 그 과정에서 하나씩 다시 배우면 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;완벽한 천재보다 꾸준히 성장하는 사람이 더 오래 개발할 수 있습니다. 저 역시 여전히 부족한 부분을 공부하고 있습니다. 그리고 아마 개발자로 일하는 동안, 이 공부는 계속될 것 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>타입 계층과 호환성, extends가 진짜 의미하는 것</title><link>https://yozm.wishket.com/magazine/detail/3807</link><description>타입스크립트를 사용하다 보면 extends라는 키워드를 다양한 곳에서 만나게 됩니다. Conditional Type에서는 T extends U ? X : Y 형태로, 제네릭에서는 T extends string 같은 제약 조건으로 등장합니다. 두 경우 모두 "할당 가능하면"이라는 설명이 따라붙는데, 정확히 어떤 조건에서 할당이 가능하고 어떤 조건에서 불가능한 것일까요? 이번 글에서는 타입 계층도의 전체 구조를 살펴보고, 타입스크립트가 타입 간의 관계를 어떤 기준으로 판단하는지 알아보겠습니다. 이 개념을 이해하고 나면, extends와 타입 좁히기, 유틸리티 타입의 동작 원리가 한층 더 선명해질 것입니다.</description><guid>https://yozm.wishket.com/magazine/detail/3807</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;타입스크립트를 사용하다 보면 extends라는 키워드를 다양한 곳에서 만나게 됩니다. Conditional Type에서는 T extends U ? X : Y 형태로, 제네릭에서는 T extends string 같은 제약 조건으로 등장합니다. 두 경우 모두 "할당 가능하면"이라는 설명이 따라붙는데, 정확히 어떤 조건에서 할당이 가능하고 어떤 조건에서 불가능한 것일까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;타입 좁히기에서도 비슷한 의문이 생깁니다. typeof 검사를 거치면 "타입이 좁아진다"고 하는데, 넓은 타입과 좁은 타입이라는 말은 타입 사이에 일종의 크기 관계가 있다는 뜻입니다. 그렇다면 이 크기 관계는 어디에서 오는 것이고, 타입스크립트는 어떤 기준으로 이를 판단하는 것일까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 관계를 체계적으로 정리한 것이 타입 계층도이고, 이를 기반으로 타입스크립트가 할당 가능 여부를 판단하는 규칙이 타입 호환성입니다. 이번 글에서는 타입 계층도의 전체 구조를 살펴보고, 타입스크립트가 타입 간의 관계를 어떤 기준으로 판단하는지 알아보겠습니다. 이 개념을 이해하고 나면, extends와 타입 좁히기, 유틸리티 타입의 동작 원리가 한층 더 선명해질 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;미리 요점만 콕 집어보면?&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;타입스크립트의 모든 타입은 unknown부터 never까지 계층을 이루며, 좁은 타입에서 넓은 타입으로만 안전하게 할당됩니다.&lt;/li&gt;&lt;li&gt;객체 타입은 이름이 아니라 구조를 기준으로 호환성을 판단하며, extends 역시 결국 “할당 가능한가?”를 검사하는 문법입니다.&lt;/li&gt;&lt;li&gt;Conditional Type, 제네릭 제약, 타입 좁히기는 모두 같은 타입 계층과 호환성 규칙 위에서 동작하는 개념입니다.&lt;/li&gt;&lt;/ul&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;타입 계층도, 모든 타입에는 상하 관계가 있다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;타입스크립트에서 사용하는 모든 타입은 하나의 계층 구조 안에 놓여 있습니다. 이 구조를 이해하면 어떤 타입이 어떤 타입에 할당 가능한지, 왜 특정 할당이 오류를 발생시키는지를 체계적으로 파악할 수 있습니다. 이후 섹션에서 다룰 호환성 규칙과 extends의 의미가 모두 이 계층도에 뿌리를 두고 있으므로, 먼저 전체 그림을 잡고 가겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) unknown과 never&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;타입 계층도의 맨 꼭대기에는 unknown이, 맨바닥에는 never가 위치합니다. 이 두 타입은 계층의 양극단을 이루는 특별한 존재입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;unknown은 모든 타입의 슈퍼타입, 즉 최상위 타입입니다. 어떤 값이든 unknown 타입 변수에 할당할 수 있습니다. 외부 API로부터 어떤 형태의 데이터가 들어올지 알 수 없는 상황에서 유용하게 사용됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;let a: unknown;

a = 1;         // number → unknown ✅
a = "hello";   // string → unknown ✅
a = true;      // boolean → unknown ✅&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;모든 값을 받아들일 수 있다는 점에서 any와 비슷해 보이지만, 결정적인 차이가 있습니다. unknown 타입의 값은 다른 타입 변수에 할당할 수 없습니다. 즉, 들어오는 것은 자유롭지만 나가는 것은 엄격하게 제한됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;let a: unknown = "hello";
let b: string = a;
// 오류: 'unknown' 형식은 'string' 형식에 할당할 수 없습니다.&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대쪽 끝에 있는 never는 모든 타입의 서브타입, 즉 최하위 타입입니다. never는 "절대 존재할 수 없는 값"을 나타내며, 어떤 값도 never 타입 변수에 할당할 수 없습니다. 실제로 never 타입이 되는 대표적인 경우는 항상 예외를 던지거나 무한 루프를 도는 함수의 반환 타입입니다. 이런 함수는 정상적으로 값을 반환하는 일이 절대 없으므로, 반환 타입이 never가 됩니다. 그런데 흥미로운 점은, never 자체는 모든 타입에 할당할 수 있다는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function throwError(): never {
  throw new Error("에러 발생");
}

let a: number = throwError(); // never → number ✅
let b: string = throwError(); // never → string ✅&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Conditional Type을 사용할 때 결과로 never가 자주 등장하는 것을 본 적이 있을 것입니다. type MyExclude&amp;lt;T, U&amp;gt; = T extends U ? never : T에서 조건에 해당하는 멤버를 never로 만들면 유니온에서 자동으로 사라집니다. 이것이 가능한 이유가 바로 never가 최하위 타입이기 때문입니다. never는 값의 집합 관점에서 보면 아무 값도 포함하지 않는 공집합에 해당합니다. 공집합을 다른 집합과 합쳐도 결과가 달라지지 않는 것처럼, never는 유니온에 포함되어도 아무런 영향을 주지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) any&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;any는 앞서 살펴본 타입 계층도 안에 위치한 타입이 아닙니다. unknown이나 never처럼 상하 관계로 설명할 수 있는 타입이 아니라, 타입 검사 자체를 우회하는 특별한 타입입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;let a: any;

// 모든 타입으로부터 할당받을 수 있음
a = 1;
a = "hello";
a = true;

// 모든 타입에 할당할 수도 있음
let b: number = a;  // any → number ✅
let c: string = a;  // any → string ✅&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;모든 타입에 할당할 수도 있고, 모든 타입으로부터 할당받을 수도 있습니다. 얼핏 보면 unknown(모든 것을 받아들이는)과 never(모든 곳에 할당 가능한)의 성질을 동시에 가진 것처럼 보이지만, 실제로는 성격이 완전히 다릅니다. unknown과 never는 계층 규칙을 철저히 따르면서 안정성을 보장하는 반면, any는 그 규칙 자체를 비활성화합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;any를 사용하면 타입 검사가 사실상 무력화됩니다. 숫자가 들어와야 할 자리에 문자열이 들어와도 컴파일러는 아무런 경고를 하지 않습니다. 타입스크립트를 사용하는 가장 큰 이유가 타입 안정성인데, any는 그 안정성을 스스로&amp;nbsp; 포기하는 선택입니다. 따라서 가능한 한 unknown으로 대체하고, 타입 좁히기를 통해 안전하게 사용하는 것이 권장됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 기본 타입들의 위치&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;unknown과 never 사이에는 우리가 일상적으로 사용하는 타입들이 계층을 이루고 있습니다. string, number, boolean 같은 원시 타입은 계층의 중간에 위치하고, 리터럴 타입은 그 아래에 위치합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;let a: string = "hello";   // 리터럴 → 원시 타입 ✅
let b: "hello" = "hello";  // 리터럴 → 리터럴 ✅

let c: "hello" = a;
// 오류: 'string' 형식은 '"hello"' 형식에 할당할 수 없습니다.&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;"hello"는 string의 서브타입입니다. 따라서 "hello"를 string 변수에 넣는 것은 가능하지만, 반대로 string을 "hello” 변수에 넣는 것은 불가능합니다. string은 “hello" 뿐 아니라 "world", "abc"등 무한히 많은 문자열을 포함하는 더 넓은 타입이기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 관계를 떠올리면, 타입 좁히기가 왜 "좁아진다"는 표현을 쓰는지 자연스럽게 이해됩니다. typeof value === "string" 검사를 통과하면 string | number라는 넓은 타입에서 string이라는 좁은 타입으로 내려가는 것이고, 이는 타입 계층도에서 아래쪽으로 이동하는 것과 같습니다. 숫자 타입도 마찬가지입니다. number는 가능한 모든 숫자를 포함하는 넓은 타입이고, 42는 그중 딱 하나의 값만 허용하는 좁은 타입입니다. 이처럼 리터럴 타입은 원시 타입이 허용하는 값의 범위를 하나로 한정한 것이라고 이해하면 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;정리하면 타입 계층도의 큰 그림은 다음과 같습니다. 위에서부터 unknown -&amp;gt; string, number, boolean 등 원시 타입 -&amp;gt; “hello", 42 등 리터럴 타입 -&amp;gt; never 순서이며, any는 이 계층 바깥에서 모든 규칙을 우회하는 예외적 존재입니다. 참고로 이 계층도는 완전한 트리 구조라기보다, 타입 간의 포함 관계를 나타낸 것으로 이해하는 것이 더 정확합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3807/%E1%84%80%E1%85%B3%E1%84%85%E1%85%B5%E1%86%B71__1_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, GPT로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;타입 호환성&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;타입 계층도가 타입 간의 상하 관계를 보여주는 지도라면, 타입 호환성은 그 지도를 기반으로 실제 할당이 가능한지를 판단하는 규칙입니다. 이 절에서는 업캐스팅과 다운캐스팅의 개념을 먼저 살펴본 뒤, 객체 타입에서 특히 중요한 구조적 타이핑과 초과 프로퍼티 검사까지 알아보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 업캐스팅과 다운캐스팅&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;타입 호환성의 핵심 규칙은 간단합니다. 좁은 타입에서 넓은 타입으로의 할당은 허용되고, 넓은 타입에서 좁은 타입으로의 할당은 차단됩니다. 좁은 타입을 넓은 타입에 할당하는 것을 업캐스팅이라고 합니다. 리터럴 42를 number 변수에 넣는 것이 대표적인 업캐스팅입니다. 42는 number가 허용하는 값 중 하나이므로 안전합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;let a: number = 42;       // 42(리터럴) → number ✅ 업캐스팅
let b: unknown = "hello"; // string → unknown ✅ 업캐스팅&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-left:36pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대로 넓은 타입을 좁은 타입에 할당하는 것을 다운캐스팅이라고 합니다. number를 42 타입 변수에 넣으려 하면 오류가 발생합니다. number에는 42 외에도 0, -1, 3.14 등 수많은 값이 포함되어 있으므로, 42만 허용하는 변수에 넣는 것은 안전하지 않기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;let a: number = 100;
let b: 42 = a;
// 오류: 'number' 형식은 '42' 형식에 할당할 수 없습니다.&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 규칙은 모든 타입에 일관되게 적용됩니다. string은 unknown에 할당 가능하고(업캐스팅), unknown을 string에 넣는 것(다운캐스팅)은 불가능합니다. never의 경우에는 앞서 살펴본 것처럼 가능한 값이 하나도 없는 공집합이므로, 모든 타입의 부분집합으로 간주되어 어디에든 할당할 수 있습니다. 반대로 string을 never에 넣는 것은 불가능합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;참고로 여기서 사용한 업캐스팅과 다운캐스팅이라는 용어는 이해를 돕기 위한 비유입니다. 원래 이 용어는 Java나 C#처럼 명목적 상속 구조를 가진 언어에서 유래한 것으로, 구조적 타입 시스템을 사용하는 타입스크립트와 완전히 동일한 개념은 아닙니다. 다만 "좁은 타입에서 넓은 타입으로 올라간다", "넓은 타입에서 좁은 타입으로 내려간다"는 방향성은 같으므로, 직관적으로 이해하기 위해 빌려 쓴 것입니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;왜 이런 규칙이 있는 것일까요? 업캐스팅이 안전한 이유는 간단합니다. 좁은 타입의 값은 넓은 타입이 허용하는 범위 안에 항상 포함되기 때문입니다. 42는 분명히 숫자이므로 number 변수에 넣어도 문제가 없습니다. 하지만 다운캐스팅은 다릅니다. number에는 42뿐 아니라 0, -1, 3.14 등 무수히 많은 값이 포함되어 있으므로, 이를 42만 허용하는 변수에 넣으면 런타임에 예상치 못한 값이 들어올 위험이 있습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;타입스크립트는 이 위험을 컴파일 타임에 미리 차단해 주는 것입니다. 다만 함수 타입에서는 매개변수 위치에 반공변성(contravariance)이 적용되는 등, 값 타입과는 조금 다른 규칙이 존재합니다. 이 글에서는 값 타입 중심의 기본적인 호환성 규칙에 집중하겠습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 객체 타입의 호환성&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;원시 타입의 호환성은 직관적이지만, 객체 타입에서는 조금 다른 기준이 적용됩니다. 타입스크립트는 객체 타입의 호환성을 판단할 때 타입의 이름이 아니라 구조, 즉 어떤 프로퍼티를 가지고 있는지를 기준으로 삼습니다. 이를 구조적 타이핑(Structural Typing)이라고 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface User {
  name: string;
}

interface Employee {
  name: string;
  department: string;
}

let user: User = { name: "kim" };
let employee: Employee = { name: "lee", department: "dev" };

user = employee; // ✅ Employee → User 할당 가능&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;User와 Employee는 이름이 완전히 다른 타입이지만, Employee는 User가 요구하는 name: string 프로퍼티를 모두 갖고 있습니다. 타입스크립트는 이것만으로 할당이 가능하다고 판단합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 중요한 점은, 대상 타입이 요구하는 구조를 모두 만족하는지가 호환성의 기준이라는 것입니다. 구조적 타입 시스템에서는 대체로 더 많은 요구 사항(프로퍼티)을 가진 타입이 더 구체적(좁은) 타입으로 취급됩니다. Employee는 User가 요구하는 name: string을 갖고 있으면서 department까지 추가로 가지고 있으므로, User보다 더 구체적인 타입이고 따라서 User에 할당 가능합니다. 반대로 User를 Employee에 할당하려 하면 department 프로퍼티가 빠져 있으므로 오류가 발생합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;employee = user;
// 오류: 'department' 속성이 'User' 형식에 없습니다.&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 규칙은 Java나 C#처럼 타입의 이름으로 호환성을 판단하는 명목적 타이핑(Nominal Typing)과 대조됩니다. 명목적 타이핑에서는 User와 Employee가 명시적으로 상속 관계를 선언하지 않는 한 서로 호환되지 않습니다. 이름이 다르면 구조가 아무리 비슷해도 별개의 타입으로 취급합니다. 하지만 타입스크립트는 구조만 맞으면 호환된다고 판단하므로, 별도의 상속 선언 없이도 유연하게 타입을 다룰 수 있습니다. 자바스크립트 생태계에서는 서로 다른 라이브러리가 비슷한 구조의 객체를 주고받는 일이 잦기 때문에, 이러한 구조적 타이핑이 실무에서 큰 장점으로 작용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3807/%EA%B7%B8%EB%A6%BC2__5_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude AI로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 초과 프로퍼티 검사&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;구조적 타이핑의 규칙대로라면, 프로퍼티가 더 많은 객체는 항상 할당 가능해야 합니다. 하지만 한 가지 예외가 있습니다. 객체 리터럴을 직접 할당할 때는 정의되지 않은 프로퍼티가 있으면 오류가 발생합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface User {
  name: string;
}

let user: User = {
  name: "kim",
  age: 25,
  // 오류: '{ name: string; age: number; }' 형식은 'User' 형식에 할당할 수 없습니다.
  // 개체 리터럴은 알려진 속성만 지정할 수 있으며 'User' 형식에 'age'이(가) 없습니다.
};&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이를 초과 프로퍼티 검사(Excess Property Check)라고 합니다. 이 검사는 개발자가 오타를 내거나, 존재하지 않는 프로퍼티를 실수로 작성하는 것을 방지하기 위한 안전장치입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 같은 객체를 변수에 먼저 담은 뒤 할당하면 이 검사를 우회할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;const person = { name: "kim", age: 25 };
let user: User = person; // ✅ 오류 없음&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;변수 person에 담긴 시점에서 타입스크립트는 person의 타입을 { name: string; age: number }로 추론합니다. 이후 user에 할당할 때는 일반적인 구조적 타이핑 규칙이 적용되므로, name: string을 갖고 있는 것만 확인하고 통과시킵니다. 초과 프로퍼티 검사는 오직 객체 리터럴을 직접 할당할 때만 동작한다는 점을 기억해 두면 좋습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 동작이 처음에는 일관성이 없어 보일 수 있지만, 실용적인 관점에서 보면 합리적입니다. 객체 리터럴을 직접 작성할 때는 개발자가 의도한 프로퍼티만 정확히 넣었는지 확인하는 것이 유용합니다. 반면에 이미 만들어진 객체를 전달할 때는, 그 객체가 필요한 프로퍼티를 모두 갖고 있다면 추가 프로퍼티가 있어도 문제가 되지 않기 때문입니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;extends 다시 보기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;타입 계층도와 호환성 규칙을 이해했으니, 이제 extends 키워드의 의미를 정확하게 짚어볼 수 있습니다. extends는 타입스크립트에서 주로 "할당 가능한가(assignable to)?"를 검사하는 데 사용됩니다. 대부분의 경우 이것은 서브타입 관계와 동일하게 동작하지만, 앞서 살펴본 any처럼 계층 규칙을 벗어나는 특수한 타입이 있으므로 엄밀히 말하면 완전히 같은 개념은 아닙니다. 다만 일반적인 타입을 다루는 상황에서는 "서브타입인가?"와 "할당 가능한가?"를 거의 같은 의미로 이해해도 무방합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Conditional Type의 extends&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Conditional Type의 기본 형태를 다시 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type IsString&amp;lt;T&amp;gt; = T extends string ? true : false;&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 T extends string은 "T가 string의 서브타입인가?", 다시 말해 "T가 string에 할당 가능한가?"를 묻는 것입니다. 타입 계층도에서 T가 string보다 아래(더 좁은 위치)에 있으면 참이 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type A = IsString&amp;lt;"hello"&amp;gt;; // true — "hello"는 string의 서브타입
type B = IsString&amp;lt;42&amp;gt;;      // false — 42는 string의 서브타입이 아님&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;"hello"가 true가 되는 이유는 앞서 살펴본 것처럼 리터럴 타입이 원시 타입의 서브타입이기 때문입니다. 타입 계층도에서 "hello"는 string 아래에 위치하므로 extends 검사를 통과합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Exclude의 구현에도 같은 원리가 적용됩니다. type MyExclude&amp;lt;T, U&amp;gt; = T extends U ? never : T에서 유니온의 각 멤버가 U의 서브타입인지를 검사하고, 서브타입이면 never로 제거하는 것입니다. 계층 구조를 알고 나면, 이 동작이 더 이상 마법처럼 느껴지지 않습니다. 참고로 분배적 조건부 타입의 동작도 결국 이 서브타입 검사가 유니온의 각 멤버에 개별적으로 적용되는 것이라는 점을 떠올려보면, extends의 의미가 한 층 더 명확해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 제네릭 제약 조건의 extends&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;제네릭에서 사용되는 extends도 같은 뿌리에서 출발합니다. 다음 예시를 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function getLength&amp;lt;T extends { length: number }&amp;gt;(arg: T): number {
  return arg.length;
}

getLength("hello");    // ✅ string은 length를 가짐
getLength([1, 2, 3]);  // ✅ 배열은 length를 가짐
getLength(42);
// 오류: 'number' 형식은 '{ length: number }' 형식의 제약 조건을 만족하지 않습니다.&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;T extends { length: number }는 "T는 { length: number }의 서브타입이어야 한다"는 제약입니다. 구조적 타이핑의 관점에서 보면, T가 최소한 length: number 프로퍼티를 갖고 있어야 한다는 의미입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;string은 length 프로퍼티를 가지고 있으므로 { length: number }의 서브타입이고, number는 length 프로퍼티가 없으므로 서브타입이 아닙니다. 배열 역시 length 프로퍼티를 가지고 있으므로 제약을 만족합니다. 이처럼 제네릭 제약 조건의 extends도 결국 구조적 타이핑을 기반으로 서브타입 여부를 검사하는 것입니다. 타입 계층도, 구조적 타이핑, 그리고 extends, 이 세 가지가 하나의 맥락으로 연결되는 것을 확인할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 타입스크립트의 타입 계층도와 타입 호환성, 그리고 extends 키워드의 정확한 의미를 살펴보았습니다. 타입스크립트의 모든 타입은 unknown(최상위)부터 never(최하위)까지 하나의 계층을 이루고 있으며, 좁은 타입에서 넓은 타입으로의 할당만 안전하게 허용됩니다. 객체 타입의 경우에는 이름이 아닌 구조를 기준으로 호환성을 판단하는 구조적 타이핑이 적용되고, 대체로 더 많은 프로퍼티를 요구하는 쪽이 더 좁은(구체적인) 타입이 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 규칙을 이해하고 나면, 여러 문법에서 등장하던 개념들이 하나의 원리로 연결됩니다. Conditional Type에서 T extends U는 "T가 U에 할당 가능한가?"를 묻는 것이고, 제네릭의 T extends { length: number }는 "T가 이 구조에 할당 가능해야 한다"는 제약이며, 타입 좁히기에서 타입이 "좁아진다"는 것은 계층도에서 아래쪽의 더 구체적인 타입으로 이동한다는 뜻입니다. 결국 같은 규칙이 서로 다른 문법으로 표현되고 있었던 셈입니다. 타입 계층도라는 하나의 지도를 손에 쥐고 나면, 앞으로 어떤 새로운 타입 문법을 만나더라도 그 동작을 스스로 추론해 볼 수 있을 겁니다.&lt;/p&gt;&lt;hr&gt;&lt;p style="text-align:justify;"&gt;&amp;lt;출처&amp;gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;한 입 크기로 잘라먹는 타입스크립트 - &lt;a href="https://ts.winterlood.com/71f4a577-4340-4994-956d-a7aa47176ffa"&gt;&lt;u&gt;타입 단언&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;한 입 크기로 잘라먹는 타입스크립트 - &lt;a href="https://ts.winterlood.com/1d6906f2-b724-43d0-bc61-8ec455e6d8e8"&gt;&lt;u&gt;타입 계층도와 함께 기본타입 살펴보기&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>클로드 코드 vs 오픈소스 모델: 둘 다 써본 개발자의 결론</title><link>https://yozm.wishket.com/magazine/detail/3801</link><description>데모 마감 2시간 전, 치명적인 버그 앞에서 클로드 코드가 멈췄습니다. 사용 한도 초과, 4시간 후에 다시 시도하라는 메시지가 떴죠. 생계가 걸린 도구가 가장 필요한 순간에 작동하지 않는다면, 과연 그 도구를 믿을 수 있을까요? 예측하기 어려운 사용량 제한과 공지 없는 정책 변경에 지쳐 탈클로드를 결심한 엔지니어가, Ollama·DeepSeek·Qwen 3 Coder 같은 오픈소스 모델로 워크플로우를 다시 짜며 느낀 점을 썼습니다. 심상치 않은 탈클로드 코드 움직임과, 그 해결책으로 떠오르는 오픈소스 코딩 에이전트 활용법을 제 경험 기반으로 소개해보려 합니다.</description><guid>https://yozm.wishket.com/magazine/detail/3801</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;엔지니어들은 왜 다시 오픈소스로 회귀하는가?&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;클로드 코드&lt;span style="color:#757575;"&gt;(Claude Code)&lt;/span&gt;, 코덱스&lt;span style="color:#757575;"&gt;(Codex)&lt;/span&gt;와 같은 코딩 에이전트의 인기는 개발자나 바이브 코더들 사이에서 독보적입니다. 유행처럼 번지는 “이제 AI가 웬만한 신입 개발자보다 코딩을 잘한다”는 말 역시, 사실은 클로드의 Opus나 오픈AI의 GPT 같은 고성능 파운데이션 모델, 그리고 이를 기반으로 한 코딩 에이전트에 한정된 이야기 아닐까 싶습니다. 그만큼 다른 경쟁 제품과 비교해 성능이 압도적이고, 사용 경험도 편리합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저 역시 지난해 말 처음 클로드 코드를 접했을 때의 신선한 충격을 아직도 기억합니다. 무엇보다 VS Code나 IntelliJ 같은 코드 에디터에서 작동하는 Copilot 등과 달리 터미널에서 작동한다는 점이 매우 독특했습니다. 간단한 설치와 권한 부여만 마치면 자연어로 &lt;strong&gt;‘xxxx.py 파일의 124번째 줄 함수를 디버깅하고, main.py 파일에 통합해 줘.’&lt;/strong&gt;라고만 명령해도, 그런 섬세한 작업까지 수행할 수 있다는 점이 꽤 센세이셔널하게 다가왔습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그동안의 코딩 도구가 개발자의 생산성을 높여주는 ‘어시스턴트’에 머물렀다면, 클로드 코드는 ‘내 부하직원처럼 직접 코딩해주는 진짜 AI 에이전트’에 가까운 느낌이라고 할까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3801/image5.png"&gt;&lt;figcaption&gt;Claude code CLI &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앤트로픽은 저와 같은 클로드 코드 지지자들의 성원에 힘입어, 2026년 기준 연환산 매출 300억 달러&lt;span style="color:#757575;"&gt;(약 41조 원)&lt;/span&gt;를 넘어설 정도로 폭발적인 인기를 누려왔습니다. 그런데 최근 들어 개발자들 사이에서 클로드 구독을 취소하는, 이른바 ‘탈클로드’ 움직임이 빠르게 늘고 있다고 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지금까지 입이 아플 정도로 클로드 코드의 장점을 이야기했지만, 사실 이 도구는 단점도 분명합니다. 가장 먼저 떠오르는 것은 막대한 토큰 소모량과 만만치 않은 가격입니다. 코덱스 같은 도구가 비교적 적은 소모량으로 인기를 얻었지만, 그 역시 본질적인 해결책은 아닙니다. 저 역시 이러한 문제로 탈 클로드를 결심했습니다. 그렇다면 대안은 있을까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 심상치 않은 탈클로드 코드 움직임과, 그 해결책으로 떠오르는 오픈소스 코딩 에이전트 활용법을 제 경험 기반으로 소개해보려 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;엔지니어들의 탈클로드 러쉬&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;최근 개발자들이 자주 찾는 커뮤니티 레딧&lt;span style="color:#757575;"&gt;(Reddit)&lt;/span&gt;에서 눈에 띄는 스레드 하나를 발견했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;I am cancelling my Claude Pro subscription and here's my honest take.&lt;/i&gt;&lt;br&gt;&lt;span style="color:#999999;"&gt;&lt;i&gt;클로드 프로 구독 취소합니다. 솔직한 후기&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3801/image3.png"&gt;&lt;figcaption&gt;&amp;lt;출처: Reddit r/PromptEngineering&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;댓글창은 비슷한 경험담으로 가득했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;나만 그런 게 아니었구나. 어제도 오전에만 제한이 3번 걸렸어.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;Pro 플랜인데 Free tier보다 못한 느낌. 농담 아니고.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;월 20달러 내면서 매일 ‘사용 한도 초과’ 보는 게 정상인가요?&lt;/li&gt;&lt;li style="text-align:justify;"&gt;방금 전환했습니다. DeepSeek + Ollama 조합. 솔직히 후회 없어요.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한때 “클로드 없이 어떻게 개발해?”라고 말하던 개발자들이, 이제는 집단으로 ‘탈클로드’를 선언하고 있는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 같은 엔지니어들의 탈클로드 움직임은 역설적으로 앤트로픽의 엄청난 성공에서 비롯됐습니다. 클로드 코드는 단순한 대화형 AI보다 훨씬 많은 컴퓨터 자원을 사용합니다. 파일을 읽고, 코드를 분석하고, 여러 파일을 동시에 수정하는 것은 물론 터미널 명령어까지 실행해야 하기 때문입니다. 사용자가 AI에 명령을 내릴 때마다 거대한 서버 자원이 쉬지 않고 돌아가야 하는 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 앤트로픽은 불가피한 선택을 내렸습니다. 바로 사용량 제한&lt;span style="color:#757575;"&gt;(rate limit)&lt;/span&gt;을 대폭 강화한 것입니다. 그로 인해 Pro 플랜 사용자조차 하루 몇 시간만 집중적으로 작업하면 “사용 한도 초과” 메시지를 마주했습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:50%;"&gt;&lt;img src="https://www.wishket.com/media/news/3801/image2_JIrUeed.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 인터넷 커뮤니티&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1. 예측 불가능한 블랙박스&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이런 상황을 키우는 더 큰 문제가 있습니다. 사용량 기준이 완전히 불투명하다는 점입니다. 앤트로픽 지원팀에 “정확히 얼마나 쓸 수 있는 건가요? 요청 횟수, 토큰 수, 아니면 시간?”이라고 문의했을 때 돌아온 답변은 애매했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;“구체적인 한도는 공개하지 않습니다. 사용 패턴과 시스템 부하에 따라 달라질 수 있습니다.”&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 사용자는 언제 제한이 걸릴지 예측조차 할 수 없습니다. 똑같은 작업을 해도 어떤 날은 하루 종일 문제없지만, 어떤 날은 2시간 만에 막히기도 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 한 개발자의 실험 결과에 따르면, 중간 규모 프로젝트 리팩터링(refactoring)은 약 2시간 30분 후 제한이 걸렸고, 여러 파일을 수정하는 신규 기능 개발은 약 3시간, 버그 디버깅 작업은 약 4시간 후 제한에 도달했습니다. 풀타임으로 일하는 개발자라면, 점심시간도 오기 전에 소진되는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저 역시 정확히 같은 문제를 겪었습니다. 데모 마감 2시간 전, AI 에이전트 데모에서 치명적인 버그를 발견했습니다. “괜찮아, 클로드한테 맡기면 10분이면 해결돼”라고 생각하며 코드 수정을 시작했는데, 불과 5분 만에 화면에 메시지가 떴습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;You've reached your usage limit. Please try again in 4 hours.&lt;/i&gt;&lt;br&gt;&lt;span style="color:#757575;"&gt;&lt;i&gt;사용 한도에 도달했습니다. 4시간 후에 다시 시도해주세요&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그 순간 머릿속이 하얘졌습니다. 결국 Gemini를 급하게 사용하고 Cursor로 보조한 다음, Stack Overflow를 뒤져가며 간신히 문제를 해결했습니다. 데모는 무사히 끝났지만, 그날 밤 한 가지를 깨달았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제 생계가 걸린 도구가 가장 필요한 순간에 작동하지 않는다면, 과연 그 도구를 믿을 수 있을까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2. 공지 없는 정책 변경&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;더 강한 결정타는 올해 2월 말 터졌습니다. 갑자기 같은 작업을 해도 이전보다 훨씬 빨리 제한이 걸리기 시작한 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;당시 어제까지 멀쩡하게 쓰던 프로젝트가 오늘은 2시간 만에 막혔다는 불만부터, 사전 공지도 없이 이런 변경을 하는 건 사실상 일방적인 계약 변경 아니냐는 항의까지 이어졌습니다. 하지만 지원팀에 문의한 사람들이 받은 답변은 “시스템 최적화”라는 모호한 설명뿐이었습니다. 트위터에서는 ‘#ClaudeLimits’ 해시태그가 트렌딩에 올랐고, 일부 사용자는 환불을 요구하기 시작했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3801/image6.png"&gt;&lt;figcaption&gt;&amp;lt;출처: &lt;a href="https://www.reddit.com/r/Anthropic/comments/1sgomf6/its_happening_they_cut_the_usage_for_literally/"&gt;reddit r/Anthropic&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3. 무너진 비용 대비 가치&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;클로드 코드를 사용하려면 Pro는 월 20달러, Max는 월 100~200달러 수준의 구독료를 지불해야 합니다. 초기에는 클로드 코드가 가져다주는 생산성 향상이 이 비용의 가치를 충분히 증명했습니다. 많게는 하루 5~6시간씩 절약되는 시간을 시급으로 환산하면, 오히려 저렴한 투자처럼 느껴졌죠. 물론 지금도 여전히 클로드는 가성비가 좋은 편이라고 생각합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만, 불분명한 사용량과 빠르게 늘어나는 토큰 활용량으로 비용 대비 가치에 의문을 제기하는 목소리도 커지고 있습니다. 같은 돈을 내더라도 실제 사용 가능 시간은 줄어들고, 정작 가장 급한 순간에는 쓸 수 없는 상황이 반복되고 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;사실 이 정도 비용이면 클라우드 GPU 인스턴스를 빌려 사용량 제한 없이 오픈소스 모델을 실행할 수 있습니다. 더 나아가 중고 Mac mini를 구매해 로컬 환경에서 Ollama로 모델을 무제한 실행하는 선택지도 있죠. 결국 예측할 수 있으며 통제 가능한 비용 구조가, 오히려 더 합리적인 대안처럼 보이기 시작한 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앤트로픽은 무리한 서비스 확장 속에서 안정성과 예측 가능성이라는 가장 중요한 요소를 놓치고 있는지도 모릅니다. 클로드 코드의 불확실성에 지친 저는 자연스럽게 오픈소스 모델로 눈을 돌리게 됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;오픈소스 모델이 대안이 될 수 있을까?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;솔직히 처음에는 회의적이었습니다. LLM 성능은 상당수 모델 크기에 좌우되는 만큼, SoTA 모델에 훨씬 못 미치는 오픈소스 모델이 과연 그만큼 잘할 수 있을까?라는 의구심이 쉽게 사라지지 않았기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 2026년 현재, 오픈소스 모델 진영의 발전 속도는 제 예상을 훨씬 뛰어넘고 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1. 생각보다 좁혀진 성능 격차&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Meta의 Llama 3.1(405B), DeepSeek의 V3 모델, 그리고 Qwen 3 Coder 같은 오픈소스 모델은 적어도 벤치마크 기준으로는 상용 모델과의 성능 격차를 빠르게 좁히고 있습니다. 특히 코딩 특화 모델인 DeepSeek Coder V2와 Qwen 3 Coder는 HumanEval 벤치마크에서 Claude 3.5 Sonnet과 비교해도 뒤지지 않는 성능을 보여주고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3801/image4.png"&gt;&lt;figcaption&gt;DeepSeek vs SOTA Models &amp;lt;출처: &lt;a href="https://www.bracai.eu/post/deepseek-performance"&gt;bracai&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 아직 Claude 4.5 Sonnet의 SWE-Bench Pro 점수에는 미치지 못합니다. 다만 그 격차가 점점 빠르게 줄어드는 분위기입니다. 벤치마크 기준으로 좀 더 살펴보면 다음과 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;DeepSeek Coder V2:&lt;/strong&gt; Claude 3.5 Sonnet과 유사한 수준입니다. 코딩 작업에서는 거의 동등한 성능을 보여줍니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;Qwen 3 Coder:&lt;/strong&gt; GPT-4 Turbo와 Claude 3 Opus 사이 정도의 성능입니다. 복잡한 코딩 작업도 대부분 처리할 수 있습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;strong&gt;Llama 3.1 70B:&lt;/strong&gt; GPT-3.5 Turbo나 Claude 3 Haiku 수준입니다. 기본적인 코딩 작업에는 충분하지만, 복잡한 로직에서는 다소 한계가 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 간단한 테스트를 진행해본 결과, 일상적인 코딩 작업에서는 DeepSeek Coder V2나 Qwen 3 Coder 같은 오픈소스 모델도 Claude 3.5 Sonnet 못지않게 충분히 실용적이었습니다. 함수 작성, 버그 수정, 코드 설명, 단위 테스트 생성 같은 작업에서는 체감상 큰 차이를 느끼기 어려웠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Llama 3.1 70B나 Mistral Large 같은 모델을 사용할 때는 분명한 한계도 있었습니다. 복잡한 로직을 설명할 때는 조금 더 명확한 지시사항이 필요했고, 여러 파일을 동시에 다루는 작업에서는 맥락(context)을 놓치는 경우도 있었습니다. 다만 프롬프트를 조금 더 세밀하게 작성하면, 대부분 원하는 결과를 얻을 수 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 복잡한 아키텍처 설계나 여러 파일에 걸친 대규모 리팩터링 작업에서는 여전히 클로드 계열이 우위에 있습니다. 이런 수준의 작업에서는 클로드 기반 모델의 뛰어난 추론 능력과 장문 맥락 처리 능력이 확실한 강점을 보여줍니다. 반면 오픈소스 모델은 때때로 복잡한 의존성을 놓치거나, 긴 요구사항을 정확히 따르지 못하는 경우가 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 현실의 개발 업무를 들여다보면, 일상적인 작업의 80~90%는 DeepSeek Coder V2나 Qwen 3 Coder 정도의 성능, 즉 Claude 3.5 Sonnet 수준으로도 충분히 처리할 수 있습니다. 반대로 Claude 4.5 Sonnet 수준이 꼭 필요한 작업은 나머지 10~20% 수준의 복잡한 업무에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그렇다면 매일 모든 작업에 가장 강력한 모델을 써야 할까요? 아니면 대부분의 업무는 충분한 성능의 모델로 처리하고, 정말 필요한 순간에만 최고 성능 모델을 선택해야 할까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실무 관점에서 보면 후자가 훨씬 합리적입니다. 모든 작업에 안정적으로 활용할 수 없다면, 차라리 무제한 사용이 가능한 중급 성능 모델을 메인으로 사용하고, 정말 중요한 순간에만 클로드를 꺼내 쓰는 편이 더 효율적일 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2. 다양해진 실행 옵션&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;과거에는 오픈소스 모델을 실행하려면 고가의 GPU 서버가 사실상 필수였습니다. 하지만 이제는 상황이 달라졌습니다. 생각보다 적은 컴퓨팅 자원만으로도 로컬 환경에서 충분히 실행할 수 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;대표적으로 Ollama 같은 도구를 사용하면 일반 노트북에서도 7B~14B 파라미터를 가진 모델을 쓸만한 속도로 구동할 수 있습니다. 32GB RAM 환경이라면 적절한 양자화(quantization)를 적용해 32B 모델까지도 무리 없이 돌아갑니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3801/image1.png"&gt;&lt;figcaption&gt;Ollama로 오픈소스 모델 활용하기 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;클라우드 GPU를 임대하는 방법도 있습니다. RunPod, Vast.ai 같은 서비스를 이용하면 시간당 약 0.5~1달러 수준으로 고성능 GPU를 빌릴 수 있습니다. 필요할 때만 켜고 끌 수 있어 비용 통제도 비교적 쉽습니다. 단순 계산으로 보면, 클로드 Pro 구독료(월 20달러) 수준의 비용으로 약 20~40시간 정도 GPU를 사용할 수 있는 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또한, 오픈소스 모델 호스팅 서비스를 활용하는 선택지도 있습니다. Groq이나 Together AI 같은 플랫폼은 클로드 API보다 훨씬 저렴한 가격으로 오픈소스 모델을 제공합니다. 특히 Groq은 초당 수백 토큰에 이르는 추론 속도를 제공하는 것으로 유명한데, 비용은 Claude API 대비 약 10분의 1 수준입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;게다가 Llama 같은 고품질 모델에 대해서도 사용량 제한이 Claude보다 훨씬 관대한 편입니다. 일부 모델은 사실상 제한 없이 사용할 수 있다는 점도 강점으로 꼽힙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3801/image7.png"&gt;&lt;figcaption&gt;Groq의 거의 무제한에 가까운 사용량 &amp;lt;출처: &lt;a href="https://groq.com/groqcloud"&gt;Groq&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3. 진짜 장점은 자유와 통제권&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;제가 여러 오픈소스 모델을 다양한 방법으로 테스트하며 느낀 가장 큰 장점은 성능이나 가격이 아니었습니다. 바로 자유와 통제권입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;우선 이 방식에는 사용량 제한이 없습니다. 로컬에서 돌리든, 클라우드에서 돌리든 24시간 내내 원하는 만큼 쓸 수 있습니다. 급한 작업 도중 “사용 한도 초과” 메시지를 볼 걱정도 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;오프라인 환경에서도 작동한다는 점 역시 큰 장점입니다. 인터넷이 끊겨도, 서비스가 다운되어도, 로컬 모델은 계속 돌아갑니다. 보안이 중요한 프로젝트에서 코드를 외부 서버로 전송할 필요도 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마지막 장점은 커스터마이징이 가능하다는 점입니다. 필요하다면 모델을 파인튜닝하거나, 프롬프트를 자유롭게 실험하고, 여러 모델을 조합해 쓸 수도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;처음 클로드 코드를 만났을 때, 저는 진정한 AI 에이전트의 가능성을 목격했습니다. 클로드 모델의 성능은 정말 뛰어납니다. 하지만 뛰어난 성능만으로는 충분하지 않다는 것을 알았습니다. 예측하기 어려운 사용 제한, 공지 없는 정책 변경, 그리고 내가 통제할 수 없는 변수들 앞에서 저는 AI 엔지니어로서의 정체성마저 의심하게 되었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;탈클로드를 결심한 이래, 지난 수개월은 시행착오의 연속이었습니다. 하지만 그 과정에서 생각보다 많은 것을 배웠습니다. 오픈소스로의 전환은 단순히 도구를 바꾸는 일 그 이상입니다. 엔지니어로서 독립성과 안정성을 되찾는 과정이었고, 그만큼 얻은 것도 많았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 현재 운영하는 워크플로우는 이렇습니다. 일상적인 코딩 작업은 로컬 Ollama에서 Qwen 3 Coder를 실행합니다. 복잡한 논리 설계가 필요할 때는 Groq의 호스팅 서비스로 DeepSeek V3를 사용합니다. 그렇게 해도 풀리지 않으면, 정말 필요한 순간에만 클로드 API를 호출합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이렇게 운영하니 비용도 줄었고, 사용량 제한에 걸릴 일도 거의 사라졌습니다. 역설적으로 의존도를 낮추자, 정작 필요할 때 클로드를 더 효과적으로 활용할 수 있게 됐습니다. 수개월간 오픈소스 코딩 에이전트를 사용하며 느낀 점은 분명했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;오픈소스 모델이 클로드의 완벽한 대체재는 아닙니다. 여전히 결과물이 다소 어색하거나 품질이 떨어지는 경우도 많습니다. 복잡한 아키텍처 설계나 대규모 리팩터링에서는 여전히 클로드 코드가 큰 우위에 있습니다. 하지만 현실의 개발 업무는 그런 이분법으로 나뉘지 않습니다. 대부분의 작업은 오픈소스 모델로도 충분히 처리할 수 있을 거라는 가능성을 보았습니다. 부족한 20%를 위해, 나머지 80%를 불안정한 서비스에 맡길 이유는 없다고 느꼈습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개발자들의 탈클로드 움직임은 단순한 ‘가격 불만’ 때문은 아닙니다. 이것은 선택권을 되찾으려는 엔지니어들의 의식 있는 움직임에 가깝습니다. 한 회사의 정책에 종속되지 않고, 자신의 상황에 맞는 도구를 선택할 자유를 요구하는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;소프트웨어 엔지니어링 역사를 돌아보면, 가장 성공한 기술은 늘 이런 자유도를 제공했습니다. Linux가 Windows를 넘어 서버 운영 체제의 표준이 된 이유도 단순히 가격 때문만은 아닙니다. 사용자가 원하는 방식으로 커스터마이징하고, 직접 통제할 자유가 있었기 때문입니다. 오픈소스 모델의 부상 역시 같은 맥락 안에 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이제 오픈소스 모델은 “충분히 좋은” 수준까지 올라왔습니다. 클로드 코드가 여전히 더 좋다는 점은 인정합니다. 하지만 개발자들은 합리적입니다. “더 좋은” 도구를 하루 3시간만 쓰는 것보다, “충분히 좋은” 도구를 24시간 안정적으로 쓰는 편이 실무에서는 더 가치 있을 지도 모릅니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;클로드 코드 독점 시대는 서서히 끝나가고 있습니다. 이제는 개발자가 자신의 필요에 맞는 도구를 선택하는 시대입니다. 그리고 그 전환에 필요한 것은 이미 충분히 갖춰져 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>나만의 세컨 브레인: 옵시디언 기반 LLM 위키 구축기</title><link>https://yozm.wishket.com/magazine/detail/3792</link><description>앞서 기고한 “오늘 뭐부터 하지?” AI 비서 에이전트 만들어봤습니다에서는 흩어진 프로젝트 정보를 한곳에 모아, AI 비서가 매일 아침 프로젝트 현황과 Todo 우선 순위를 브리핑해 주는 시스템을 공유했습니다. 이러한 시스템으로 제 업무에 대한 맥락을 정리했지만, 정작 그 일을 수행하는 '나 자신'에 대한 맥락은 어떻게 효율적으로 정리할지가 고민이었죠. 때마침 안드레 카파시(Andrej Karpathy)가 ‘LLM 위키’라는 아이디어를 제시했고, 그 개념을 저의 컨텍스트 정리에 적용해 보고자 했습니다. 그래서 옵시디언(Obsidian), 깃허브(GitHub), 클로드 코드(Claude Code)의 조합으로 나만의 세컨드 브레인인 LLM 위키를 구축했는데요. 이번 글에서는 그 과정과 LLM 위키 구축 경험에서 얻은 인사이트를 정리해 봤습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3792</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;최근 많은 사람들이 클로드(Claude), 챗지피티(ChatGPT), 제미나이(Gemini) 같은 다양한 AI 도구를 사용하는 것이 일상이 되었습니다. 하지만 사용하는 AI 도구가 늘어날수록 우리는 늘 컨텍스트를 새로 전달해야 하는 번거로움을 겪게 됩니다. 즉, 본인의 상황과 맥락을 &lt;strong&gt;AI에게 매번 설명&lt;/strong&gt;해야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;앞서 기고한 &lt;a href="https://yozm.wishket.com/magazine/detail/3692/"&gt;“오늘 뭐부터 하지?” AI 비서 에이전트 만들어봤습니다&lt;/a&gt;에서는 흩어진 프로젝트 정보를 한곳에 모아, AI 비서가 매일 아침 프로젝트 현황과 Todo 우선 순위를 브리핑해 주는 시스템을 공유했습니다. 이러한 시스템으로 제 업무에 대한 맥락을 정리했지만, 정작 그 일을 수행하는 &lt;strong&gt;'나 자신'에 대한 맥락&lt;/strong&gt;은 어떻게 효율적으로 정리할지가 고민이었죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;당시 때마침 안드레 카파시(Andrej Karpathy)가 ‘LLM 위키’라는 아이디어를 제시했고, 그 개념을 저의 컨텍스트 정리에 적용해 보고자 했습니다. 그래서 옵시디언(Obsidian), 깃허브(GitHub), 클로드 코드(Claude Code)의 조합으로 나만의 세컨드 브레인인 &lt;strong&gt;LLM 위키를 구축&lt;/strong&gt;했는데요. 이번 글에서는 그 과정과 LLM 위키 구축 경험에서 얻은 인사이트를 정리해 봤습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;미리 요점만 콕 집어보면?&lt;/strong&gt;&lt;/h4&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;여러 AI에게 매번 나의 상황과 맥락을 설명해야 하는 일은 결국 ‘흩어진 컨텍스트’와 '나 자신을 데이터로 다루는 시스템'이 없기 때문에 발생합니다.&lt;/li&gt;&lt;li&gt;옵시디언, 깃허브, 클로드 코드 CLI의 조합으로 안드레 카파시의 LLM 위키 아이디어를 제 자신만의 세컨드 브레인으로 적용해 구축해 보았습니다.&lt;/li&gt;&lt;li&gt;프로덕트 메이커(Product Maker)에게 개인 컨텍스트의 자산화는 단순히 일회성으로 컨텍스트를 정리하는 것에 그치지 않고, 장기적 관점에서 AI 활용의 생산성을 극대화하는 일에 가깝습니다.&lt;/li&gt;&lt;/ul&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;나만의 LLM 위키를 만든 이유&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 여러 곳에 흩어져 있는 컨텍스트&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;최근에는 다양한 AI 도구들이 저마다의 장단점을 가지고 있어, 사용자들이 &lt;strong&gt;여러 AI 도구를 이용&lt;/strong&gt;하는 경우가 많습니다. 저 역시 서비스 기획이나 비즈니스 아이디어 정리는 클로드 챗의 프로젝트 기능을 사용하고, 가벼운 검색이나 이미지 생성은 챗지피티를, 코드 작업은 클로드 코드, 디자인은 클로드 디자인, 유튜브 요약과 글쓰기 보조 도구로는 제미나이 챗을 사용하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/1__%EC%9D%BC%EA%B4%80%EB%90%9C_%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8_%EA%B4%80%EB%A6%AC%EC%9D%98_%EC%96%B4%EB%A0%A4%EC%9B%80.png"&gt;&lt;figcaption&gt;일관된 컨텍스트 관리의 어려움 &amp;lt;출처: ChatGPT 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이처럼 여러 AI 도구를 병행하다 보니 각 도구마다 저의 상황과 맥락을 반복해서 설명해야 했고, &lt;strong&gt;컨텍스트의 일관성&lt;/strong&gt;을 유지하기도 쉽지 않았습니다. 게다가 정보가 수집되고 정리되는 채널도 제각각이었습니다. 가벼운 메모는 구글 킵(Keep), 회의록은 노션(Notion), 업무 문서는 구글 워크스페이스(Google Workspace), 그리고 코드와 프로젝트 데이터는 깃허브(GitHub)에 흩어져 있는 식이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 분산된 정보의 통합&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;그래서 저는 이번 LLM 위키 구축을 통해 구글 킵, 노션, 구글 스페이스, 깃허브 등 여러 곳에 흩어져 있는 모든 정보를 &lt;strong&gt;하나의 일관된 시스템으로&lt;/strong&gt; 통합해 보기로 했습니다. 분산된 정보는 AI가 '나 자신'의 온전한 맥락을 파악하는 데 가장 큰 장애물이 되며, 이 상태로는 AI 에이전트의 생산성이 제한될 수밖에 없다고 생각했기 때문입니다. 따라서 모든 형태의 개인 데이터를 한곳에 모아 AI가 쉽게 접근하고 활용할 수 있는 세컨드 브레인 구축을 시작했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/2__%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8%EC%9D%84_%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC_%EB%B6%84%EC%82%B0%EB%90%9C_%EC%A0%95%EB%B3%B4%EB%A5%BC_%ED%86%B5%ED%95%A9.png"&gt;&lt;figcaption&gt;옵시디언을 이용하여 분산된 정보를 통합 &amp;lt;출처: ChatGPT 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;분산된 정보를 통합하고, 나만의 LLM 위키를 만들기 위한 도구를 고를 때 가장 중요하게 본 기준은 세 가지였습니다. &lt;strong&gt;빠른 속도&lt;/strong&gt;, &lt;strong&gt;안정적인 동기화&lt;/strong&gt;, 그리고 &lt;strong&gt;저의 워크플로우에 적합한 도구&lt;/strong&gt;였습니다. 그렇게 여러 리서치와 테스트를 거쳐 결국 앞선 세 가지를 모두 만족하는 도구로 옵시디언을 선택하게 되었습니다. 사실 많은 이들이 옵시디언을 사용한다고 해서 같은 도구를 선택하고 싶진 않았습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 이런저런 도구를 테스트하며 꽤 많은 시간을 허비하고 나서, 결국 다른 사람들과 같은 선택을 하게 되었습니다. 결론적으로 &lt;strong&gt;옵시디언&lt;/strong&gt;을 중심으로 LLM 위키를 구축하고, 백업 및 동기화는 &lt;strong&gt;깃허브 Private Repo&lt;/strong&gt;, 위키 정리 작업은 &lt;strong&gt;클로드 코드&lt;/strong&gt;가 처리하는 것으로 결정했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;LLM 위키 구축 환경 세팅&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 옵시디언 세팅과 핵심 플러그인&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;옵시디언을 설치하고 가장 먼저 한 작업은 &lt;strong&gt;볼트(Vault) 생성&lt;/strong&gt;과 &lt;strong&gt;테마 설정&lt;/strong&gt;이었습니다. 옵시디언에서 볼트란 노트가 저장되는 폴더를 의미합니다. 테마로는 미니멀(Minimal) 테마를 선택했는데요. 옵시디언 커뮤니티에서 가장 인기 있는 테마이기도 하고, 깔끔하면서도 플러그인을 통해 카드뷰, 갤러리뷰 같은 다양한 세팅이 가능한 테마입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/3__%EB%AF%B8%EB%8B%88%EB%A9%80_%ED%85%8C%EB%A7%88%EB%A5%BC_%EC%A0%81%EC%9A%A9%ED%95%9C_%ED%99%94%EB%A9%B4.png"&gt;&lt;figcaption&gt;미니멀 테마를 적용한 옵시디언 화면 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이후에 제가 옵시디언에 &lt;strong&gt;설치한 플러그인&lt;/strong&gt;은 다음 표와 같습니다. 기본적으로 기기 간 동기화를 위한 깃(Git) 플러그인을 설치했고, 옵시디언 내에서 바로 클로드 코드를 사용하기 위한 터미널(Terminal) 플러그인도 설치했습니다. 추가로 템플릿 관리와 노트의 시각적 표현을 향상시키는 플러그인들도 설치했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/4__%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8%EC%97%90_%EC%84%A4%EC%B9%98%ED%95%9C_%ED%95%B5%EC%8B%AC_%ED%94%8C%EB%9F%AC%EA%B7%B8%EC%9D%B8.png"&gt;&lt;figcaption&gt;옵시디언에 설치한 핵심 플러그인 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;아울러, &lt;strong&gt;자료를 수집하는 경로&lt;/strong&gt;도 옵시디언으로 일원화했습니다. &lt;strong&gt;데스크톱 PC&lt;/strong&gt;에서 웹 서핑하다 발견한 정보는 크롬 확장 프로그램인 ‘옵시디언 웹 클리퍼’를 통해 클릭 한 번으로 위키 볼트에 저장되도록 했습니다. 또한 &lt;strong&gt;모바일 기기&lt;/strong&gt;에서도 웹 서핑이나 유튜브, 스레드, 카카오톡, 페이스북 등을 보다가 유익한 콘텐츠를 발견하면 ‘공유’ 기능을 통해 바로 옵시디언으로 전송되도록 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/5__%EC%9E%90%EB%A3%8C_%EC%88%98%EC%A7%91%EC%9D%84_%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8_%EB%B3%BC%ED%8A%B8%EB%A1%9C_%EC%9D%BC%EC%9B%90%ED%99%94.png"&gt;&lt;figcaption&gt;자료 수집을 옵시디언 볼트로 일원화 &amp;lt;출처: ChatGPT 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;만약 콘텐츠에 &lt;strong&gt;공유 버튼이 지원되지 않는 경우&lt;/strong&gt;에는 화면을 캡쳐하거나, 파일을 다운로드하여 옵시디언 볼트 내 임시 폴더에 저장했습니다. 그리고 파일명에 자료를 저장한 의도를 간단히 남기고, 추후 클로드 코드가 일괄적으로 자료를 정리하도록 구성했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 깃허브 연동(Private Repo)&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;앞서 살펴본 것처럼 여러 기기에서 자료를 수집하고, 노트를 사용하기 때문에 옵시디언 &lt;strong&gt;볼트의 동기화&lt;/strong&gt;가 필요합니다. 이를 위해 깃허브 Private Repo를 이용하면 레파지토리를 클라우드 백업 공간으로 활용하면서도 여러 기기에서 볼트를 동기화할 수 있습니다. 단, LLM 위키가 나의 거의 모든 데이터를 담고 있으므로 2단계 인증 등 &lt;strong&gt;보안을 엄격하게 관리해야&lt;/strong&gt; 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/6__%EA%B9%83%ED%97%88%EB%B8%8C_Private_Repo%EB%A5%BC_%ED%86%B5%ED%95%9C_%EB%8F%99%EA%B8%B0%ED%99%94_%EA%B5%AC%EC%A1%B0.png"&gt;&lt;figcaption&gt;깃허브 Private Repo를 통한 동기화 구조 &amp;lt;출처: ChatGPT 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;아이폰&lt;/strong&gt;같은 모바일 환경에서는 직접적으로 Git 저장소를 사용할 수 없기 때문에 옵시디언 싱크나 Working Copy라는 앱을 이용해야 합니다. 여기서 저는 &lt;strong&gt;Working Copy&lt;/strong&gt;를 사용하기로 했습니다. Working Copy는 클론(Clone) 기능은 무료이고 푸시(Push) 기능만 일회성 결제(약 $20)를 하면 되는데, 이는 옵시디언 싱크 구독을 1년 결제하는 것보다 장기적 비용 측면에서 저렴하다고 판단했습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Working Copy 앱을 이용하려면 깃허브 개인 액세스 토큰(Personal Access Token)을 Fine-grained 권한으로 발급해 등록해야 합니다. 그러면 Working Copy로 클론한 폴더를 옵시디언 모바일에서 볼트로 열어 사용할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/7__Working_Copy_%EC%86%8C%EA%B0%9C.png"&gt;&lt;figcaption&gt;Working Copy 소개 &amp;lt;출처: https://workingcopy.app/&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 클로드 코드 CLI와 옵시디언 스킬 활용&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;옵시디언 볼트 안에서 클로드 코드, 코덱스 같은 AI 툴을 실행하면 위키의 작성과 수정, 삭제 등을 자동화할 수 있습니다. 이게 바로 LLM 위키의 핵심입니다. 즉, 사람이 직접 손으로 관리하던 이전의 위키와 달리 LLM 위키는 &lt;strong&gt;AI가 작성하고 관리하는 위키&lt;/strong&gt;인 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/8__%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8__%ED%81%B4%EB%A1%9C%EB%93%9C_%EC%BD%94%EB%93%9C_CLI.png"&gt;&lt;figcaption&gt;옵시디언 + 클로드 코드 CLI &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저는 기존부터 사용하던 웨이브 터미널(&lt;a href="https://www.waveterm.dev/"&gt;&lt;u&gt;Wave Terminal&lt;/u&gt;&lt;/a&gt;)이라는&lt;strong&gt;CLI 툴로 클로드 코드&lt;/strong&gt;를 실행하여 LLM 위키를 구축했습니다. 클로드 코드로 여기저기 흩어져 있는 자료를 LLM 위키에 입력하고, 그렇게 구축된 위키를 바탕으로 질문하거나, 주기적으로 위키를 정리하는 일을 모두 이 CLI 환경 안에서 처리하고 있습니다. 참고로, CLI 사용이 익숙하지 않은 분들은 클로드 데스크톱 앱에 있는 &lt;strong&gt;클로드 코워크&lt;/strong&gt;(Claude Cowork)로도 동일한 작업을 할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/9__%ED%81%B4%EB%A1%9C%EB%93%9C_%EC%BD%94%EC%9B%8C%ED%81%AC%EB%A5%BC_%EC%9D%B4%EC%9A%A9%ED%95%9C_%EC%9C%84%ED%82%A4_%EA%B4%80%EB%A6%AC.png"&gt;&lt;figcaption&gt;클로드 코워크를 이용한 위키 관리 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;클로드 코드를 사용할 때의 핵심은 옵시디언 볼트의 루트 디렉터리에 CLAUDE.md라는 파일을 두고, 새 세션(대화창)을 열 때마다 &lt;strong&gt;시스템 컨텍스트로 자동 주입&lt;/strong&gt;되도록 만드는 것입니다. 이를 통해 CLAUDE.md가 사실상 위키 운영 매뉴얼로서 AI 작업의 일관성을 확보하는 역할을 하게 됩니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/10__%EC%84%B8%EC%85%98_%EC%8B%9C%EC%9E%91_%EC%8B%9C_Hook%EC%9D%84_%ED%86%B5%ED%95%B4_%EC%9C%84%ED%82%A4_%EC%9A%B4%EC%98%81_%EA%B7%9C%EC%B9%99%EA%B3%BC_index_%EC%A6%89%EC%8B%9C_%EC%B0%B8%EC%A1%B0.png"&gt;&lt;figcaption&gt;세션 시작 시 Hook을 통해 위키 운영 규칙과 index 즉시 참조 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만, 가끔 AI가 CLAUDE.md에 적힌 운영 규칙을 제대로 보지 않는 경우가 있습니다. 이런 경우에는 &lt;strong&gt;SessionStart Hook&lt;/strong&gt;을 걸어 세션 시작 시 강제로 운영 규칙을 주입하거나, 위키 index를 즉시 참조하도록 할 수 있습니다. 이를 통해 새로운 대화를 시작하는 경우에도 AI가 별도의 검색 없이 위키 운영 규칙과 나에 대한 질문에 즉답을 할 수 있게 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/11__%ED%81%B4%EB%A1%9C%EB%93%9C_%EC%BD%94%EB%93%9C%EC%9D%98_%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8_%EC%8A%A4%ED%82%AC.png"&gt;&lt;figcaption&gt;클로드 코드의 옵시디언 스킬 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또한 추가로 클로드 코드에 &lt;strong&gt;옵시디언 스킬&lt;/strong&gt;들을 설치했습니다. 옵시디언 볼트의 일괄 작업을 돕는 obsidian-cli와 콜아웃, 임베드, 프로퍼티 같은 옵시디언 특화 문법을 다루는 obsidian-markdown, 그리고 웹페이지에서 깔끔한 본문만 추출해주는 defuddle 같은 스킬들이 있습니다. 이러한 스킬들은 옵시디언 특화 문법이나 LLM 위키 운영에 최적화된 복잡한 작업이 필요할 때 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;LLM 위키 설계와 활용하기&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 카테고리 설계&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이제 LLM 위키 환경 세팅이 끝났으니 구조를 설계할 단계입니다. 처음부터 나에 대한 모든 컨텍스트를 한 번에 만들려고 하면 어렵습니다. 그래서 저는 다음과 같은 프롬프트를 작성하여, 클로드 코드에게 &lt;strong&gt;위키 구조를 설계하도록&lt;/strong&gt; 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;i&gt;내가 누구이고, 어떤 배경과 역사를 가졌으며, 어떤 사람들과 어떤 환경에 있는지, 어떤 생각과 철학을 가지고 있는지, 어떤 자산을 가지고 있는지, 어떤 것들을 메모했고, 어떤 지식과 정보를 가지고 있는지 등을 기록하고 연결할 수 있는 위키 구조가 필요하다. 안드레 카파시의 아이디어를 기반으로 나에 대한 핵심 정보들을 담을 수 있는 LLM 위키 구조를 설계해줘.&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이후 클로드가 제안해 준 카테고리를 기반으로 &lt;strong&gt;저에게 맞는 위키 구조&lt;/strong&gt;를 만들어 갔습니다. 현재는 나의 정체성(Identity), 생각(Thoughts), 목표(Goals), 역사(History), 사람(People), 자산(Assets), 일(Works)로 카테고리를 분류하여 사용하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 자료 인입(Ingest)&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;저는 안드레 카파시의 LLM 위키 개념을 클로드 코드에 넘겨, ingest, query, lint 스킬을 만들도록 했습니다. 그중에서 &lt;strong&gt;/ingest&lt;/strong&gt;는 새로 수집된 자료를 읽고, 적절한 위키 페이지로 합성하거나 연결하는 작업을 진행합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/12__%EA%B5%AC%EA%B8%80%ED%82%B5_ingest_%EA%B3%BC%EC%A0%95.png"&gt;&lt;figcaption&gt;구글킵 ingest 과정 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;자료 인입을 위해 저는 먼저 기존에 가지고 있던 노션과 구글 킵 노트를 ingest 했습니다. 즉, 노션과 구글 킵에서 백업한 파일을 raw 폴더에 넣고 /ingest 스킬을 사용했습니다. 여기에 &lt;strong&gt;민감 정보를 분리하는 과정&lt;/strong&gt;을 추가했는데요. 예를 들어, 비밀번호, 카드번호, 주민등록번호 같은 정보가 위키에 무분별하게 삽입되는 것을 방지하고자 했습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/13_%EB%AF%BC%EA%B0%90_%EC%A0%95%EB%B3%B4_%EA%B0%90%EC%A7%80_%EB%B0%8F_%EB%A7%88%EC%8A%A4%ED%82%B9_%EC%B2%98%EB%A6%AC.png"&gt;&lt;figcaption&gt;민감 정보 감지 및 마스킹 처리 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이를 위해 클로드 코드가 민감 정보 패턴을 &lt;strong&gt;정규식&lt;/strong&gt;(Regex)으로 감지해 위키에 삽입 시 &lt;strong&gt;마스킹&lt;/strong&gt;(Masking) 처리를 하도록 했습니다. 다만, 이러한 정규식 감지는 완벽하지 않기 때문에(ex. 주민번호에 공백이 들어간 경우 등) 1차적인 안전장치로만 사용하고, 다음에 살펴볼 Lint 작업으로 재점검하거나, 본인이 직접 검토해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 위키 점검 및 정리(Lint)&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;/lint&lt;/strong&gt;는 위키의 상태를 점검하는 작업입니다. 민감한 데이터나 모순된 정보, 어떤 노트에서도 연결되지 않은 고아(Orphan) 페이지, 다른 노트에서 언급만 되고 실제 파일이 없는 페이지 등을 잡아줍니다. 저는 &lt;strong&gt;클로드의 스케쥴 기능&lt;/strong&gt;을 활용해매일 자동으로 린트가 돌도록 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/14__%ED%81%B4%EB%A1%9C%EB%93%9C%EB%A5%BC_%EC%9D%B4%EC%9A%A9%ED%95%9C_Lint_%EC%9E%90%EB%8F%99%ED%99%94.png"&gt;&lt;figcaption&gt;클로드를 이용한 Lint 자동화 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;클로드의 스케쥴 기능을 사용하면, 따로 신경 쓰지 않아도 매일 위키의 깨진 링크나 정합성 문제를 &lt;strong&gt;자동으로 정리&lt;/strong&gt;할 수 있습니다. 비록 클로드가 중간에 Lint의 방향을 물어보는 경우가 있기도 하지만, 클로드의 스케쥴 기능으로 Lint 작업을 자동화하면 LLM 위키의 관리에 들어가는 비용을 줄일 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;4) LLM 위키의 활용&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;/query&lt;/strong&gt; 스킬은 위키 전체를 컨텍스트로 깔고 AI에게 질문하는 워크플로우입니다. 이를 통해 AI에게 질문을 던졌을 때 받는 '일반론적 답변'과는 &lt;strong&gt;결이 다른 답변&lt;/strong&gt;을 받을 수 있습니다. 이는 AI가 제 생각과 철학, 주어진 상황과 배경, 현재 운영 중인 비즈니스 환경, 진행 중인 프로젝트 목록과 우선순위까지 모두 알고 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/15__%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8%EC%9D%98_%EA%B7%B8%EB%9E%98%ED%94%84_%EB%B7%B0_%EA%B8%B0%EB%8A%A5.png"&gt;&lt;figcaption&gt;옵시디언의 그래프 뷰 기능 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또한 LLM 위키에 옵시디언을 활용하면 &lt;strong&gt;그래프 뷰&lt;/strong&gt;(Graph View) 기능을 사용할 수 있습니다. 그래프 뷰는 노트 간의 링크를 시각적으로 보여주는 기능인데요. 어떤 주제가 어떤 내용들과 연결되는지를 확인해 볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실제 사용 후기와 한계는?&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 컨텍스트를 이해한 AI의 답변&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;요즘 저는 비즈니스를 위한 법인 설립과 다양한 프로젝트를 동시에 진행하고 있습니다. 그 과정에서 결정해야 할 일이 정말 많았는데요. "지금 법인을 설립하는 게 맞을까", "동시 진행 중인 프로젝트가 너무 많은데 어디서 힘을 빼야 할까", "이 사업 라인을 잠시 보류하는 게 맞을까"처럼 답이 하나로 떨어지지 않는 질문들이 있었습니다. 그리고 LLM 위키를 활용하여 저의 철학, 직전 1년 회고, 현재 진행 중인 프로젝트의 부담, 자녀 양육 사이클까지 고려한 &lt;strong&gt;맞춤형 답변&lt;/strong&gt;을 받을 수 있었습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이처럼 LLM 위키를 구축하고, AI에게 나의 컨텍스트 전부 전달함으로써 AI의 답변 품질이 '일반론적인 답변'에서 '&lt;strong&gt;나의 상황에 최적화된 답변&lt;/strong&gt;'으로 바뀐 것을 체감할 수 있었습니다. 아울러 &lt;a href="https://yozm.wishket.com/magazine/detail/3692/"&gt;&lt;u&gt;이전 글&lt;/u&gt;&lt;/a&gt;에서 만들었던 AI 비서 정대리도 LLM 위키를 활용하여 저의 의사결정 도우미로서 한 단계 진화시킬 수 있었습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) LLM 위키의 한계점과 고려 사항&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;다만, 기대만큼 매끄럽지 않았던 부분도 있었습니다. 저의 경우에는 AI가 이미지에서 텍스트를 읽어 위키에 ingest할 때 부정확했던 사례가 많았습니다. 개인적으로 직접 손으로 쓰거나 다이어그램을 그린 메모지 사진과 노트 캡처 같은 이미지 기반 자료를 많이 가지고 있었는데요. 이런 자료를 Ingest 한 후 직접 위키를 검토해 봤을 때 &lt;strong&gt;사실관계가 어긋난 부분&lt;/strong&gt;이 상당히 많았습니다. 결국 제가 직접 관련된 항목을 하나하나 확인하며 다시 손으로 고쳐야 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;아울러 위키가 점점 커질수록 그 안에 담기는 &lt;strong&gt;민감 정보도 더 많아진다&lt;/strong&gt;는 문제가 있었습니다. 비록 마스킹 처리를 위한 목적이라도 비밀번호, 카드번호 같은 개인 정보를 AI에게 전부 넘겨야 하고, 민감 정보의 마스킹 처리가 제대로 됐는지도 일일이 확인하기 전까지 확신하기가 어려웠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또한 동기화를 위해 깃허브의 비공개 Repository를 사용하지만, 그렇다고 모든 보안 위험이 사라지는 것도 아니었습니다. 만약 &lt;strong&gt;깃허브 계정이 해킹되면&lt;/strong&gt; 나의 모든 정보가 한꺼번에 털리는 문제가 생길 수도 있습니다. 따라서 기본적인 2단계 인증, 토큰(Token) 회전 같은 보호 장치를 반드시 설정해 두어야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마지막으로 협업 시나리오에서도 또 다른 한계가 있었습니다. 나만의 LLM 위키에는 개인 정보가 많이 담겨 있기 때문에 팀과 공유하기가 어려웠습니다. 결국 팀과 공유할 컨텍스트는 &lt;strong&gt;팀 LLM 위키&lt;/strong&gt;를 다시 만들어야 하는 &lt;strong&gt;이중 작업&lt;/strong&gt;이 생기게 됩니다. LLM 위키에서는 단일 출처(Single source of truth, SSOT)를 원칙으로 표방하지만, 일부 정보는 결국 두 곳에 두게 되는 모순이 발생할 수밖에 없었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3792/16__LLM_%EC%9C%84%ED%82%A4_%EC%82%AC%EC%9A%A9_%ED%9B%84%EA%B8%B0%EC%99%80_%ED%95%9C%EA%B3%84.png"&gt;&lt;figcaption&gt;LLM 위키 사용 후기와 한계 &amp;lt;출처: ChatGPT 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이상으로 안드레 카파시의 아이디어를 적용하여 나만의 세컨드 브레인인 LLM 위키를 만든 과정과 후기를 정리해 봤습니다. 처음에는 단순히 AI에게 매번 나의 컨텍스트를 설명하는 것이 답답해서 시작한 작업이었지만, 만들고 보니 &lt;strong&gt;컨텍스트 정리의 자동화&lt;/strong&gt;와 &lt;strong&gt;AI 답변 품질의 향상&lt;/strong&gt;이라는 효과를 체감할 수 있었습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;프로덕트 메이커의 입장에서 볼 때, LLM 위키의 구축은 단순한 일회성 프로젝트라기보다 장기적 관점에서 자신의 컨텍스트를 자산처럼 쌓아가는 과정이라고 생각합니다. 그리고 그렇게 쌓여진 나만의 컨텍스트를 통해서 &lt;strong&gt;AI 도구 활용의 생산성&lt;/strong&gt;을 극대화할 수 있을 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 이번에 제가 수행한 LLM 위키 구축 방식이 모두에게 정답은 아닐 것입니다. 특히 옵시디언이라는 도구는 손에 익기 전까지 학습 비용이 있고, 기기 간 동기화 방식도 다양하게 있기 때문입니다. 아울러 업무에 필요한 컨텍스트 정리의 수준도 개인마다 다르기 때문에 세컨드 브레인 구축에 있어 어떤 특정한 &lt;strong&gt;정답은 없다고 생각&lt;/strong&gt;합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마지막으로 한 가지 강조하고 싶은 점은 세컨드 브레인 구축 시 처음부터 완벽한 구조를 만들겠다는 욕심을 내려놔야 한다는 것입니다. 위키의 카테고리나 자동화 워크플로우, 동기화 셋업을 한꺼번에 완벽하게 만들겠다고 하다 보면 중간에 포기하게 될 수도 있기 때문이죠. 따라서 &lt;strong&gt;점진적으로 개선&lt;/strong&gt;해 나간다는 느낌으로, 나만의 세컨드 브레인 구축을 시도해 보시길 바랍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>'토큰 맥싱'의 시대는 끝났다: 메타·아마존·우버의 선택</title><link>https://yozm.wishket.com/magazine/detail/3790</link><description>AI를 잘 쓴다는 걸 토큰 사용량으로 증명하던 시대가 있었습니다. 한도 창을 캡처해 자랑하고 사내 리더보드로 줄을 세우던 분위기가, 메타·아마존·우버에서 약속이라도 한 듯 사용량을 제한하기 시작하며 빠르게 무너졌습니다. 사용량은 폭발했는데 성과는 그 속도를 증명하지 못했고, 토큰 사용량을 내 성과로 끌어안는 건 공급자의 매출 지표를 내 것이라 착각하는 일과 다르지 않았죠. 토큰맥싱이 끝난 자리에서 무엇을 봐야 할지 정리했습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3790</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;지금 IT 업계에서 내 경쟁력은 무엇으로 증명하면 좋을까요? 답은 쉽습니다. "AI를 잘 쓴다"겠죠. 그럼 AI를 잘 쓴다는 건 또 무엇으로 증명할까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;2025년 들어 클로드 코드 같은 코딩 에이전트가 퍼지면서, 여기저기서 유행하기 시작한 것이 있습니다. 누가 토큰을 더 많이 태웠는지 줄 세우는 '토큰 사용량 리더보드'입니다. 곧 이 기업 저 기업에서 사내 리더보드 캡처본을 자랑삼아 올리기 시작했습니다. "오늘 사용 한도 다 채웠다"며 한도 창을 찍어 올리는 게시글도 흔했고요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 이 분위기는 최근 빠르게 무너졌습니다. 메타는 직원이 만들어 운영하던 토큰 순위표를 닫았고, 아마존도 비슷한 사내 순위표를 접으며 "AI를 그냥 쓰려고 쓰지는 말라"고 직원들에게 당부했습니다. 우버는 직원 1인당 AI 도구 비용에 한도를 걸었습니다. 언제는 맘껏 쓰라던 회사들이 약속이라도 한 듯 사용량을 제한하기 시작한 것입니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이제 토큰 사용량을 실력의 잣대로 삼던 문화는 끝났습니다. '토큰 맥싱' 시대의 종말이죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3790/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Gemini로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;토큰을 많이 쓰면 AI를 잘 쓰는 걸까?&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;&lt;h4&gt;&lt;strong&gt;토큰 맥싱이란?&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;‘토큰 맥싱(tokenmaxxing)’이란 단어부터 짚어 봅시다. 외모를 극한까지 가꾸는 행위를 ‘룩스맥싱’이라 부르는 데서 온 말로, ‘-맥싱’은 무언가를 끝까지 밀어붙인다는 의미입니다. 그러니 토큰 맥싱은 AI에게 일을 잔뜩 시켜 토큰을 최대한 많이 쓰는 행위를 가리킵니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이러한 토큰 맥싱이 추구하는 건 결과물이 아니라 사용량 그 자체입니다. 토큰을 많이 썼다는 사실이 곧 'AI를 잘 쓴다'는 증거로 통했고, 그게 토큰맥싱의 출발점이었죠.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;토큰 리더보드는 어떻게 퍼졌나&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이 발상이 회사 제도로까지 번진 건 2025년 7월 즈음입니다. 당시 AI-first를 회사 기조로 삼아 이목을 끌었던 쇼피파이에서 ‘리더보드’를 운영한다고 말했습니다. 당연히 나쁜 의도는 아니었습니다. AI로 좋은 성과를 낸 사람을 알아봐 주자는 취지였고, 실제로 꽤 효과를 봤다고 했습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#999999;"&gt;*참고:&lt;/span&gt; &lt;a href="https://www.youtube.com/watch?v=u-3IILWQPRM"&gt;&lt;span style="color:#999999;"&gt;&lt;u&gt;Farhan Thawar와 함께 Shopify의 소프트웨어 엔지니어링을 변화시키는 AI&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="color:#999999;"&gt;(The Pragmatic Engineer)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;문제는 이 형식이 빠르게 번지면서 변질됐다는 점입니다. 직원을 점수로 줄 세우는 비슷한 리더보드가 여러 회사에 생겼습니다. 메타에는 직원이 직접 만든 토큰 순위표가 있었는데, 사용량 상위 이용자에게 '토큰 레전드(Token Legend)'·'캐시의 마법사(Cache Wizard)' 같은 칭호까지 붙였습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:80%;"&gt;&lt;img src="https://www.wishket.com/media/news/3790/image2.png"&gt;&lt;figcaption&gt;더 인포메이션 메타 담당 기자의 ‘토큰맥싱 리더보드’ 글 &amp;lt;출처:&lt;a href="https://www.linkedin.com/in/jyoti-mann-873a4317b/recent-activity/all/"&gt;&lt;u&gt;Jyoti Mann 링크드인&lt;/u&gt;&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마이크로소프트, 디즈니 등도 사내 ‘AI 도입 대시보드’에 사용량과 토큰 수를 띄웠고, 개발자 커뮤니티에도 토큰을 얼마나 썼는지 집계해주는 도구가 등장했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3790/image4.png"&gt;&lt;figcaption&gt;사용자의 토큰 사용량을 추적하는 리더보드 &amp;lt;출처:&lt;a href="https://tokscale.ai/leaderboard"&gt;&lt;u&gt;Tokscale&lt;/u&gt;&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;왜 토큰 리더보드는 무너졌나&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;애초에 토큰이 AI 활용도를 평가하는 지표 자리에 오른 이유는 단순합니다. 측정하기 쉬웠거든요. AI를 잘 도입했는지 따지는 건 원래 어렵고 눈에 잘 안 보이는데, 토큰은 숫자로 딱 떨어져 대시보드에 바로 뜹니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 그 시작이 쉬웠던 만큼 이런 믿음이 흔들리는 것도 금방이었습니다. 왜 그랬을까요?&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;토큰 ≠산출물의 양&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;단순합니다. 토큰을 몇 배 더 태워도 산출물이 그만큼 늘지는 않았던 겁니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이걸 가장 비싼 값을 치르며 확인한 곳이 우버입니다. 우버는 2026년 한 해 쓸 AI 코딩 도구 예산을 첫 4달 만에 전부 소진했습니다. 일부 엔지니어는 토큰 값으로 월 2,000달러까지 썼다고 합니다. 문제는 그렇게 쏟아붓고도 값을 했는지 아무도 자신 있게 답하지 못했다는 점입니다. 우버 COO도 AI 사용은 늘었지만 그 돈이 실제 성과로 이어졌다고 딱 잘라 말하긴 어렵다고 했죠. 사용량은 폭발했는데 성과는 그 속도를 증명하지 못한 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;*참고:&lt;/span&gt; &lt;a href="https://techcrunch.com/2026/06/02/uber-caps-employee-ai-spending-after-blowing-through-budget-in-four-months/"&gt;&lt;span style="color:#999999;"&gt;&lt;u&gt;Uber caps employee AI spending after blowing through budget in 4 months&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="color:#999999;"&gt;(Techcrunch)&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 토큰을 많이 써서 코드를 쏟아내면 배포 건수는 늘지만, 그게 버그 없이 살아남는지는 별개의 이야기입니다. 그래서 우버는 직원 한 명당 도구별로 월 1,500달러 한도를 도입했습니다. 클로드 코드와 커서 같은 도구마다 따로 한도를 두고, 내부 대시보드로 사용량을 추적해 예외 승인이 있을 때만 초과를 허용하는 방식이죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;토큰 ≠ 정직도&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;아마존에서도 직원들이 사내 도구로 굳이 안 해도 될 작업을 AI에게 떠넘기며 토큰 소비를 늘렸다는 보도가 나왔습니다. 한 직원은 “매니저들이 지켜보고 있고, 사용량 추적이 비뚤어진 동기를 만든다”고 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;span style="color:#999999;"&gt;*참고:&lt;/span&gt; &lt;a href="https://arstechnica.com/ai/2026/05/amazon-employees-are-tokenmaxxing-due-to-pressure-to-use-ai-tools/"&gt;&lt;span style="color:#999999;"&gt;&lt;u&gt;Amazon employees are “tokenmaxxing” due to pressure to use AI tools&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="color:#999999;"&gt;(ArsTechnica)&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;경제학자 찰스 굿하트의 말이 떠오릅니다. 측정하는 잣대가 목표가 되는 순간, 그건 더 이상 좋은 잣대가 아니라는 거죠. 사람은 평가받는 항목에 맞춰 행동을 비틉니다. 토큰 사용량이 평가 기준이 되자, 토큰을 일부러 부풀리는 일이 실제로 벌어진 겁니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;토큰 = 공급자의 매출&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;게다가 좀 더 구조적인 문제도 있습니다. 주요 모델을 만든 회사들의 매출은 최근 폭발적으로 늘었고, 그 배경에는 슬금슬금 오른 토큰 비용이 있습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:80%;"&gt;&lt;img src="https://www.wishket.com/media/news/3790/Gemini_Generated_Image_gkl9tygkl9tygkl9.png"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;표를 보면 최근 나온 신형 모델들이 한 세대 전보다 비싸졌습니다. GPT-5.5는 직전 세대의 두 배, 제미나이 3.5 Flash는 직전 플래시의 약 세 배로 올랐고, 클로드 Opus 4.7은 표시 가격은 그대로지만 새 토크나이저 탓에 같은 글이 토큰을 최대 35%까지 더 먹습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 성능이 좋아졌으니 값이 오르는 게 당연하다고 볼 수도 있습니다. 하지만, 단가만 오른 게 아닙니다. 토큰을 가장 많이 쓰는 코딩 에이전트들이 새 기능을 토큰을 더 소비하는 방향으로 진화시켜 왔거든요. 단가도, 한 작업에 드는 토큰 양도 함께 늘어난 셈입니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:80%;"&gt;&lt;img src="https://www.wishket.com/media/news/3790/image5.png"&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 공급자를 악당으로 몰 일은 아닙니다. 분명 모델이 토큰을 많이 쓴다는 것은 더 많은 일을 처리할 가능성을 높이며, 그 구조를 알아서 만들어 주는 기능은 일을 편하게 해줍니다. 게다가 모델을 한 번 돌릴 때마다 전력과 인프라 비용이 진짜로 들어가니, 가격이 오르는 데는 나름의 근거가 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 이걸 돈 내고 쓰는 사람들의 생각은 다를 겁니다. 돈을 쓰는 만큼 효과가 돌아와야 하는데, 그게 불분명한 구성이었으니까요. 이 구조에서 토큰 사용량을 내 성과라고 끌어안는 건, 남의 매출 지표를 내 성과라고 착각하는 일과 다르지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;토큰 대신 무엇을 봐야 하나&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;&lt;h4&gt;&lt;strong&gt;적게 쓰고 잘 쓰는 게 실력&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;앤트로픽이 &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents"&gt;&lt;u&gt;공식 엔지니어링 블로그&lt;/u&gt;&lt;/a&gt;에서 권하는 원칙은 이렇습니다. 원하는 결과가 나올 가능성을 최대로 높이되, 신호가 분명한 정보만 가능한 한 적게 넣으라는 거죠.&amp;nbsp; 토큰을 많이 욱여넣지 말고, 필요한 것만 정확히 골라 넣으라는 뜻이죠. 뜻입니다. 컨텍스트를 가득 채운다고 결과가 좋아지지 않습니다. 오히려 잡음이 끼면 정확도만 떨어지죠.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 에이전트의 동작 환경을 제어하는 ‘하네스 엔지니어링’ 기술이 발전하며, 컨텍스트 주입과 성과 관리, 피드백에 대한 루프가 진화한 것도 '토큰을 많이 쓰면 좋다'는 믿음에 더 큰 의심을 키웠고요.&amp;nbsp; 한국에서도 ‘&lt;a href="https://www.khan.co.kr/article/202604290600081"&gt;&lt;u&gt;토성비&lt;/u&gt;&lt;/a&gt;’, 그러니까 토큰 가성비라는 말이 생겼을 정도입니다. 토큰을 얼마나 썼느냐가 아니라 그 돈으로 무엇을 얻었느냐를 따지기 시작했다는 뜻입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3790/image3.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Gemini로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;성과 측정은 새로운 숙제가 아니다&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;결국 다시 봐야 할 건 '토큰을 얼마나 썼나'가 아니라 '내가 풀려는 문제가 뭐고, AI가 내놓은 결과가 그 문제를 풀었나'입니다. 적은 토큰으로 목표를 이루도록 설계하는 능력, 그게 실력이라는 거죠.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그럼 ‘문제를 풀었나’를 어떻게 검증하냐고요? 결과와 목적 달성을 측정하는 일은 조직이 늘 해오던 일입니다. 코드를 몇 줄 썼는지로 개발자를 평가하면 쓸데없이 긴 코드만 양산된다는 걸 모두가 알고 있습니다. 그러니 AI가 왔다고 성과 측정을 바닥부터 새로 발명할 건 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하던 대로 하면 됩니다. ‘이 사람은(또는 나는) 고객이나 조직의 어떤 문제를 풀었고, 그래서 제품과 회사에 얼마나 보탬이 됐는가?’ 이걸 평가하면 충분합니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;마치며: 많이 쓰던 시대에서, 무엇을 풀었는지 묻는 시대로&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;토큰 맥싱의 시대가 그저 헛수고였던 것만은 아니라고 생각합니다. AI를 얼마나 쓰는지 줄 세우는 것만으로도, "AI는 무섭고 쓸모없다"던 사람들을 "안 쓰면 도태된다"는 쪽으로 밀어붙이는 역할은 했으니까요. 아직 아무도 AI를 안 쓰려는 회사라면, 이 리더보드가 여전히 제 역할을 할지도 모릅니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그러나 토큰맥싱은 끝났습니다. 더 정확히는, 토큰을 지표로 삼던 시대가 끝났습니다. 토큰은 앞으로도 계속, 어쩌면 더 많이 쓰일 테지만, 이제 그게 자랑거리는 아닙니다. 그러니 혹시 "아, 오늘도 사용 한도 다 채웠으니 열일했다"고 만족하던 분들은, 한 번 더 스스로 물어보면 어떨까요? 그 한도로 무엇을 바꿨는지를요.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>나만의 유틸리티 타입 만들기: Mapped Type, Conditional Type</title><link>https://yozm.wishket.com/magazine/detail/3789</link><description>타입스크립트는 자바스크립트에 정적 타입 시스템을 더한 언어로, 코드의 안정성과 가독성을 높여주는 다양한 기능을 제공합니다. 그 중에서도 ‘Partial’, ‘Required’, ‘Readonly’, ‘Pick’, ‘Omit’ 같은 내장 유틸리티 타입은 일상적인 개발에서 자주 활용되는 도구입니다. 그런데 프로젝트가 복잡해지면 한 가지 의문이 생깁니다. 내장 유틸리티 타입만으로 모든 상황을 해결할 수 있을까요? 실제로 그렇지 않은 경우가 많습니다. 이러한 상황에서 진가를 발휘하는 도구가 바로 “Mapped Type”과 “Conditional Type”입니다. 이 두 가지는 내장 유틸리티 타입을 구성하는 핵심 재료이기도 합니다. 이번 글에서는 두 도구의 동작 원리를 살펴보고, 이를 토대로 나만의 유틸리티 타입을 만드는 방법까지 함께 알아보겠습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3789</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;타입스크립트는 자바스크립트에 정적 타입 시스템을 더한 언어로, 코드의 안정성과 가독성을 높여주는 다양한 기능을 제공합니다. 그 중에서도 ‘Partial’, ‘Required’, ‘Readonly’, ‘Pick’, ‘Omit’ 같은 내장 유틸리티 타입은 일상적인 개발에서 자주 활용되는 도구입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 프로젝트가 복잡해지면 한 가지 의문이 생깁니다. 내장 유틸리티 타입만으로 모든 상황을 해결할 수 있을까요? 실제로 그렇지 않은 경우가 많습니다. API 응답에서 값의 타입이 ‘string’인 프로퍼티만 골라야 하거나, 일부 필드는 그대로 두고 나머지나 옵셔널로 만들고 싶은 상황이 자주 발생합니다. 이런 순간에 직접 유틸리티 타입을 만들 줄 모르면, 같은 타입을 여러 번 반복해 정의하거나 ‘any’로 우회하게 되고, 결과적으로 타입 안정성이 무너지는 코드가 쌓이기 쉽습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이러한 상황에서 진가를 발휘하는 도구가 바로 “Mapped Type”과 “Conditional Type”입니다. 이 두 가지는 내장 유틸리티 타입을 구성하는 핵심 재료이기도 합니다. 이번 글에서는 두 도구의 동작 원리를 살펴보고, 이를 토대로 나만의 유틸리티 타입을 만드는 방법까지 함께 알아보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;미리 요점만 콕 집어보면?&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;‘Mapped Type’과 ‘Conditional Type’은 ‘Partial’, ‘Readonly’, ‘Exclude’, ‘ReturnType’ 같은 내장 유틸리티 타입의 핵심 원리입니다.&lt;/li&gt;&lt;li&gt;‘keyof’, ‘as’, ‘infer’, 분배적 조건부 타입을 활용하면 특정 타입만 추출하거나 일부 필드만 옵셔널로 바꾸는 커스텀 타입을 만들 수 있습니다.&lt;/li&gt;&lt;li&gt;복잡한 타입 추상화는 IDE 성능과 가독성에 영향을 줄 수 있으므로, 실무에서는 재사용성과 유지보수성을 함께 고려해야 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;먼저 알아야 할 도구들 - Readonly, Exclude, Extract&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;Mapped Type과 Conditional Type을 이해하려면 먼저 내장 유틸리티 타입 몇 가지를 살펴볼 필요가 있습니다. 이들은 모두 위 두 가지 도구로 만들어졌기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Readonly&amp;lt;T&amp;gt;란?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Readonly&amp;lt;T&amp;gt;는 객체 타입 T의 모든 프로퍼티를 읽기 전용으로 만들어주는 유틸리티 타입입니다. 즉, 한 번 할당된 값을 변경할 수 없도록 잠그는 역할을 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface User {
  id: number;
  name: string;
}

const user: Readonly&amp;lt;User&amp;gt; = {
  id: 1,
  name: "kim",
};

user.name = "park";
// 오류: 읽기 전용 프로퍼티이므로 'name'에 할당할 수 없습니다.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;이 덕분에 불변성을 보장해야 하는 상태 객체나 설정값을 다룰 때 유용하게 활용할 수 있습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) Exclude&amp;lt;T, U&amp;gt;와 Extract&amp;lt;T, U&amp;gt;란?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Exclude&amp;lt;T, U&amp;gt;는 유니온 타입 T에서 U에 해당하는 멤버를 제거합니다. 반대로 Extract&amp;lt;T, U&amp;gt;는 T에서 U와 겹치는 멤버만 남깁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type Status = "loading" | "success" | "error";

type NonError = Exclude&amp;lt;Status, "error"&amp;gt;;
// 결과: "loading" | "success"

type OnlyError = Extract&amp;lt;Status, "error" | "fatal"&amp;gt;;
// 결과: "error"
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 두 타입은 이름에서 알 수 있듯이 서로 대칭되는 동작을 합니다. 어떻게 이런 분기가 가능한지는 뒤에서 살펴볼 Conditional Type을 보면 자연스럽게 이해할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;Mapped Type - 타입을 순회하며 변환하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;내장 유틸리티 타입의 상당수는 결국 한 가지 동작을 다른 형태로 풀어낸 것입니다. 바로 “기존 타입의 프로퍼티를 하나씩 훑으면서 일정한 규칙으로 새로운 프로퍼티를 만들어내는” 작업입니다. 이 동작을 직접 표현할 수 있는 문법이 바로 Mapped Type입니다. 이 절에서는 기본 문법부터 시작해, ‘Partial’이나 ‘Readonly’를 직접 구현해보고, 타입스크립트 4.1 이후 추가된 키 재매핑까지 단계적으로 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Mapped Type의 기본 문법&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Mapped Type은 한 객체 타입의 프로퍼티를 순회하면서 새로운 객체 타입을 만들어내는 문법입니다. 자바스크립트에서 ‘for…in’으로 객체를 순회하는 것과 비슷한 개념이라고 이해하면 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기본 형태는 다음과 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type MyMapped&amp;lt;T&amp;gt; = {
  [K in keyof T]: T[K];
};
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;‘keyof T’는 T의 모든 프로퍼티 키를 유니온으로 묶은 결과이고, [K in keyof T]는 그 키를 하나씩 꺼내 새로운 객체 타입을 구성하라는 의미입니다. 이를 통해 기존 타입의 구조는 유지하면서 각 프로퍼티에 변형을 가할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3789/%EA%B7%B8%EB%A6%BC1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude ai로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) Partial과 Readonly 직접 만들어보기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이제 Mapped Type을 사용해 내장 유틸리티 타입인 ‘Partial’과 ‘Readonly’를 직접 구현해 볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type MyPartial&amp;lt;T&amp;gt; = {
  [K in keyof T]?: T[K];
};

type MyReadonly&amp;lt;T&amp;gt; = {
  readonly [K in keyof T]: T[K];
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;‘?’는 프로퍼티를 옵셔널로 만들고, ‘readonly’는 읽기 전용으로 만듭니다. 단 두 줄로 강력한 유틸리티 타입을 만들 수 있다는 점에서 Mapped Type의 표현력을 확인할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 키 재매핑과 수식어 제거&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;타입스크립트 4.1 버전부터는 ‘as’ 키워드를 사용해 키 자체를 재매핑할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type Getters&amp;lt;T&amp;gt; = {
  [K in keyof T as `get${Capitalize&amp;lt;string &amp;amp; K&amp;gt;}`]: () =&amp;gt; T[K];
};

interface Person {
  name: string;
  age: number;
}

type PersonGetters = Getters&amp;lt;Person&amp;gt;;
// 결과: { getName: () =&amp;gt; string; getAge: () =&amp;gt; number; }
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또한 ‘-?’나 ‘-readonly’처럼 빼기 기호를 붙이면 옵셔널 표시나 읽기 전용 수식어를 제거할 수도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type Concrete&amp;lt;T&amp;gt; = {
  -readonly [K in keyof T]-?: T[K];
};
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이는 ‘Readonly’나 ‘Partial’을 되돌리고 싶을 때 활용할 수 있는 패턴입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;Conditional Type - 조건에 따라 타입 분기하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;Mapped Type이 타입의 “구조”를 순회하며 변환하는 도구라면, Conditional Type은 타입의 종류나 타입이 무엇이냐에 따라 결과를 다르게 결정하는 도구입니다. 입력 타입이 무엇이냐에 따라 분기되는 동적인 타입을 만들 수 있어, ‘Exclude’나 ‘ReturnType’ 같은 내장 유틸리티 타입의 토대가 됩니다. 여기서는 기본 문법을 먼저 살펴본 뒤, 유니온과 만났을 때 일어나는 분배 동작과 ‘infer’ 키워드까지 차례대로 알아보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Conditional Type의 기본 문법&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Conditional Type은 자바스크립트의 삼항 연산자처럼 조건에 따라 타입을 결정하는 문법입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type IsString&amp;lt;T&amp;gt; = T extends string ? true : false;

type A = IsString&amp;lt;"hello"&amp;gt;;
// 결과: true
type B = IsString&amp;lt;42&amp;gt;;
// 결과: false
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;‘T extends U ? X : Y’ 형태로 작성하며, T가 U에 할당 가능한지 검사한 뒤 그 결과에 따라 다른 타입을 반환합니다. 이를 통해 입력 타입에 따라 동적으로 결과 타입을 만들어낼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 분배적 조건부 타입&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Conditional Type이 유니온 타입과 만나면 흥미로운 일이 일어납니다. 검사 대상이 단일 타입 파라미터인 유니온일 경우, 타입스크립트는 유니온의 각 멤버에 조건을 분배해 적용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type ToArray&amp;lt;T&amp;gt; = T extends any ? T[] : never;

type Result = ToArray&amp;lt;string | number&amp;gt;;
// 결과: string[] | number[]
&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-left:36pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3789/%EA%B7%B8%EB%A6%BC2.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude ai로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 동작을 활용하면 앞서 살펴본 ‘Exclude’와 ‘Extract’를 다음처럼 직접 만들 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type MyExclude&amp;lt;T, U&amp;gt; = T extends U ? never : T;
type MyExtract&amp;lt;T, U&amp;gt; = T extends U ? T : never;
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;T의 각 멤버에 대해 U에 속하는지를 검사하고, 결과에 따라 never로 제거하거나 그대로 남깁니다. 즉, Conditional Type 한 줄로 두 유틸리티 타입의 동작 원리가 설명됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) infer 키워드 - 타입 안에서 타입 추출하기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;‘infer’는 Conditional Type 안에서만 사용할 수 있는 키워드로, 검사 대상에서 특정 위치의 타입을 추론해 변수처럼 사용하도록 해줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type ReturnTypeOf&amp;lt;T&amp;gt; = T extends (...args: any[]) =&amp;gt; infer R ? R : never;

function getUser() {
  return { id: 1, name: "kim" };
}

type User = ReturnTypeOf&amp;lt;typeof getUser&amp;gt;;
// 결과: { id: number; name: string; }
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 예시에서는 함수의 반환 타입을 ‘R’이라는 이름으로 추출해 결과 타입으로 사용했습니다. 내장 유틸리티 타입인 ‘ReturnType’, ‘Parameters’, ‘Awaited’ 등이 이 원리로 만들어졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;나만의 유틸리티 타입 만들기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이제 Mapped Type과 Conditional Type을 결합해 실제로 사용할 만한 커스텀 유틸리티 타입을 만들어보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 특정 타입의 프로퍼티만 골라내기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;객체 타입에서 값의 타입이 ‘string’인 프로퍼티만 골라야 하는 상황을 가정해 보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type PickByType&amp;lt;T, V&amp;gt; = {
  [K in keyof T as T[K] extends V ? K : never]: T[K];
};

interface UserProfile {
  id: number;
  name: string;
  email: string;
  isActive: boolean;
}

type StringFields = PickByType&amp;lt;UserProfile, string&amp;gt;;
// 결과: { name: string; email: string; }
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Mapped Type으로 키를 순회하면서, Conditional Type으로 값의 타입을 검사해 조건에 맞지 않는 키는 never로 변환합니다. never로 매핑된 키는 결과 객체에서 자동으로 제거됩니다. 이 점에서 Mapped Type과 Conditional Type이 한 곳에서 자연스럽게 협력하는 모습을 확인할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 일부 필드만 선택적으로 바꾸기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;특정 필드만 옵셔널로 만들고 나머지는 그대로 두는 유틸리티 타입도 만들 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type PartialBy&amp;lt;T, K extends keyof T&amp;gt; = Omit&amp;lt;T, K&amp;gt; &amp;amp; Partial&amp;lt;Pick&amp;lt;T, K&amp;gt;&amp;gt;;

interface Article {
  id: number;
  title: string;
  body: string;
  publishedAt: Date;
}

type DraftArticle = PartialBy&amp;lt;Article, "publishedAt"&amp;gt;;
// 결과: { id: number; title: string; body: string; publishedAt?: Date; }
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Omit으로 대상 키를 제거한 결과와 Pick 후 Partial을 적용해 옵셔널로 만든 결과를 교집합으로 합쳐 새로운 타입을 만들어냅니다. 폼 입력값이나 임시 저장 객체처럼 단계적으로 채워나가는 데이터를 다룰 때 활용하기 좋은 패턴입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실무 활용에서의 주의점&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;지금까지 살펴본 도구들은 표현력이 뛰어나지만, 실무에서 사용할 때 몇 가지 고려할 점이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;먼저 커스텀 유틸리티 타입은 추상화 수준이 높기 때문에 코드 가독성을 해칠 수 있습니다. 따라서 팀 단위로 코드를 다룰 때는 자주 쓰이는 패턴 정도로만 만들고, 일회성으로 쓰일 만한 타입은 그때그때 인라인으로 작성하는 편이 좋습니다. 또한 Conditional Type을 깊게 중첩하면 타입 추론 비용이 늘어나 IDE 성능이 떨어질 수 있습니다. 큰 프로젝트에서 특히 체감되는 부분이므로, 복잡한 타입은 적절히 분리하고 이름을 붙여 재사용하는 것을 권장합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;마지막으로 분배적 조건부 타입의 동작을 잊는 경우가 많습니다. 유니온 타입에 Conditional Type을 적용할 때 의도하지 않은 분배가 일어날 수 있으므로, 분배를 막고 싶다면 [T] extends [U] ? … : …처럼 튜플로 감싸는 패턴을 기억해 두면 좋습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 Mapped Type과 Conditional Type의 기본 문법부터 분배적 조건부 타입, infer 키워드, 그리고 이들을 결합해 만드는 커스텀 유틸리티 타입까지 살펴보았습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;핵심을 정리하면 다음과 같습니다.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Mapped Type은 타입을 순회하면서 새로운 타입을 만드는 도구이며, Partial이나 Readonly의 토대가 됩니다.&lt;/li&gt;&lt;li&gt;Conditional Type은 조건에 따라 타입을 분기하는 도구이며, Exclude, Extract, ReturnType의 토대가 됩니다.&lt;/li&gt;&lt;li&gt;두 도구를 함께 사용하면 내장 유틸리티 타입만으로는 표현하기 어려운 정교한 타입을 만들 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 두 가지를 이해하면 내장 유틸리티 타입의 동작 원리가 투명하게 드러납니다. 더 이상 내장 도구를 외워서 쓰는 것이 아니라, 필요한 순간에 직접 조립해 쓸 수 있게 되는 셈입니다. 이를 통해 타입스크립트로 작성한 코드의 표현력과 안정성이 한 단계 올라간다는 것을 체감할 수 있습니다.&lt;/p&gt;&lt;hr&gt;&lt;p style="text-align:justify;"&gt;&amp;lt;출처&amp;gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://ts.winterlood.com/"&gt;&lt;u&gt;https://ts.winterlood.com/&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:#999999;"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>AI 시대의 시지프스: 멈추지 못하는 완벽주의자를 위한 안내서</title><link>https://yozm.wishket.com/magazine/detail/3787</link><description>AI 에이전트는 작업물을 검토해 단점을 심각도별로 분류하고 대안까지 내놓는다. 완벽주의 기질이 있는 사람에게 이건 독이 든 성배다. 완벽한 코드란 없는데도 '한 번 더'를 멈추지 못한다. 그런 와중에 모델은 매일 좋아진다. 시지프스의 바위가 멈추지 않는 건 신의 벌이지만, 우리 바위가 멈추지 않는 건 멈추지 않기로 한 선택이다. 마감일을 정하고, 여러 세션을 번갈아 돌리고, 작업을 기록하고, 오늘의 최선에서 손을 떼기까지. 번아웃을 지나며 찾은 멈추는 법을 정리했다.</description><guid>https://yozm.wishket.com/magazine/detail/3787</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3787/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저녁 6시, 퇴근 시간이다. 내일까지 제출해야 하는 작업물을 완성했지만, 불안한 마음에 한 번 더 살펴본다. 검토하다가 놓친 부분을 발견하고 말았다. 시간이 늦었는데, 지금 수정할 수 있는 범위일까? 제출 기한을 늘려 달라고 요청하는 게 좋을까? 무리해서라도 수정을 마치고 내일 제출을 하는 것과, 안전하게 기한을 늘리는 선택지 사이에서 깊은 고민에 빠진다. 그나마 수정 방향이 금방 생각나면 다행이지만, 좋은 방안이 떠오르지 않는 경우도 있다. 슬프지만 실력의 한계를 느끼며 퇴근하고, 그날의 일은 거기서 마무리된다. 이것은 AI 에이전트가 나타나기 전까지 나의 일상이었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 최근에는 상황이 많이 달라졌다. AI 에이전트(나의 경우 클로드)는 나의 고민을 듣고 작업물을 검토한 후, 단점을 파악해 심각도에 따라 분류해주며 대안들을 제시해준다. 내가 수정 방향을 고르면, 몇 분 안에 변경이 완료된다. 완벽주의 기질이 심한 나 같은 사람에게 이것은 독이 든 성배다. 완벽한 코드란 존재하지 않는데도 끝없이 질문하고 검토하며 일을 손에서 놓지 못하는 상황에 놓이는 것이다. 나는 모든 문제를 고쳐야 한다는 강박감에 시달리다가 번아웃을 경험했고, 이를 극복하는 과정에서 AI를 대하는 슬기로운 태도에 대해 생각해 보게 되었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 여러분에게도 질문하고 싶다. 우리는 어디서 멈춰야 할까?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3787/image3.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;한 번 더, 한 번 더, 완벽을 향한 강박&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;나는 오래전부터 불면증이 있었는데, 최근 몇 달간 평소보다 더 늦게 잠자리에 들었다. 클로드랑 대화하다 보면 시간 감각도 무뎌졌다. 바이브 코딩이 재미있는 이유는 피드백이 빠르기 때문이다. 끊임없이 떠오르는 개선 사항을 클로드는 금방금방 반영해 주었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;최근에 나는 일기를 자동으로 써주는 프로그램을 만들었는데, 그 프로그램은 도무지 완성되지 않았다. 처음에는 그저 캘린더의 일정을 나열하고, 클로드가 코멘트를 달아주는 정도를 원했다. 하지만 이내 한계가 드러났다. 캘린더에는 내가 실제로 한 일과 해야 한다고 적은 일이 뒤섞여있었기 때문에, 일기가 정확하지 않았던 것이다. 그때부터 일기의 정확도를 높일 방법을 고민했고, 텔레그램을 통한 사용자 인터랙션이 추가되었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;메인 시스템 프롬프트&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;“&lt;/strong&gt;하루봇 메인 파이프라인&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;매일 오후 8시(KST) 실행되어:&lt;/p&gt;&lt;p style="text-align:justify;"&gt;1. Calendar / Notion / GitHub에서 오늘 활동 수집&lt;/p&gt;&lt;p style="text-align:justify;"&gt;2. Claude API로 [오늘의 일정] + [태스크] 두 섹션 생성&lt;/p&gt;&lt;p style="text-align:justify;"&gt;3. Notion 일기 페이지 생성(오늘의 일정은 본문으로, 태스크와 할 일은 체크박스 리스트로)&lt;/p&gt;&lt;p style="text-align:justify;"&gt;4. Telegram에 일정 요약 + 할 일 체크박스 리스트(미완료 항목 + 완료 버튼) 전송&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;5. 사용자가 완료 버튼을 누르면 하루 피드백 생성·저장&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;사용자 답장(코멘트/설정)은 실시간으로 Notion 일기에 반영한다.”&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;일기에는 나의 생각도 담기는 게 좋을 것 같아서 내 답장을 일기에 함께 저장하도록 했다. 또한 ‘설정’은 버그를 간단히 수정하고 싶을 때를 대비해 만든 기능이다. ‘/설정’이라고 시작하는 코멘트는 별도 페이지에 저장되어, 시스템 프롬프트에 추가된다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 끝이 아니었다. 노션에 있는 오늘의 할 일 목록도 수집하도록 기능을 추가했는데, 할 일이 중복되어 나왔다. 중복 제거를 넣었지만 문자열 비교만으로는 ‘회의 준비’와 ‘회의 준비하기’를 같은 항목으로 인식하지 못해서, 결국 클로드에게 의미가 비슷한 항목을 골라내도록 시켰다. 봇이 요약을 보내기 전에 내가 먼저 메시지를 보내면 일기가 아직 없어서 저장할 곳이 없는 문제도 있었다. 그래서 어느 날짜 일기에 넣을지 물어보는 대화 흐름을 추가했다. 오늘은 할 일 체크 상태가 두 페이지 사이에서 동기화되지 않는 걸 발견해서 또 고쳤다. 분명 내일이 되면 또 부족한 점이 보일 것이다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;만약 이 프로그램을 처음부터 전부 다 직접 코딩했다면 설계 단계에서부터 매우 고민이 많았을 것이다. 한번 구조를 결정하면 변경이 어렵기 때문이다. 하지만 AI와 함께라면 구조 변경이 순식간에 가능하기 때문에, 아이디어가 떠오를 때마다 부담 없이 바로 시도해 볼 수 있었다. 그동안의 코딩과는 차원이 다른 속도로 기능이 완성되는, 정말이지 도파민이 터지는 순간들이었다. 새로운 프로그래밍 방법은 나를 쉴 수 없게 만들었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 이게 언제쯤 완성될지 잘 모르겠다. 사실 사이드 프로젝트라 굳이 완성 시점을 정해야 하는 것은 아니다. 하지만 만약 이걸 앱스토어에 출시하기로 마음먹었다면, ‘이것만 고치고, 이 기능까지만 넣고’ 하다가 결국 완성하지 못할 것 같다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;가만히 생각해보면 모순적인 상황이다. 분명 아주 빠른 속도로 개발하고 있는데, 완성은 되지 않는 상황이다. “더 나은 버전이 존재한다”라는 사실이 계속 나를 불안하게 만든다. 당장 일주일 만에 수많은 기능들을 개선하고 추가할 수 있고, 완전히 갈아엎고 새로 만들 수도 있다. 그래서 적당한 선에서 완성을 외치기란 더 쉽지 않다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;왜 멈추지 못하는가?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;예전에는 실력의 한계가 곧 완성도의 한계였다. 그때는 내가 할 수 있는 데까지 했으면 “여기까지가 내 최선이다”라고 받아들였다. 또한 이미 만든 결과물이 있으면 되도록 그것을 살리고 약간의 개선을 통해 어떻게든 완성하는 것이 자연스러운 이치였다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 이제는 굳이 그 지점에서 멈춰야 할 이유가 사라졌다. AI와 협업하다 보면 우리 마음속에 슬그머니 이런 불안감이 자리 잡는다. “혹시 프롬프트를 변경하면 더 좋은 결과물이 나오는 것 아닐까?”, “내가 검토시키지 않은 다른 문제는 없을까?” 몇 번 더 작업을 시키는 데에는 약간의 토큰만 들 뿐 시간은 별로 들지 않기에, 계속 붙잡고 있게 된다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;게다가 모델은 매일 좋아지고, 커뮤니티에서는 더 좋은 프롬프트 방법론도 등장한다. 이런 상황에서는 오늘 만든 결과물이 내일도 최선이라고 결코 장담할 수가 없다. 내 작업물이 10년 후의 경쟁작보다 뒤처지는 것은 양보할 수 있는 일이다. 하지만, 당장 내일의 경쟁작에 뒤처지는 것은 쉽게 용납하기가 어렵다. 멈추는 것은 곧 게으른 것이고, 포기하는 것처럼 느껴진다. 그렇게 완성은 요원해진다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그리스 신화의 시지프스는 산꼭대기에 올린 바위가 다시 굴러떨어지기 때문에 그것을 또 밀어 올려야 했다. 그러나 우리는 바위가 꼭대기에 올라갔는데도, 더 높은 산이 보이기 때문에 멈추지 못한다. 시지프스가 받은 것은 신의 벌이지만, 우리가 받은 것은 스스로 선택한 벌이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그러면 우리는 어디서 멈춰야 하는 걸까?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;강박을 멈추기 위한 나만의 방법&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;마크 엘리슨은 《완벽에 관하여》에서 흠집이 없는 완벽한 상태를 추구하기보단, 그 과정에서 성장하는 게 중요하다고 말한다. 현명한 말이다. 다만 AI 시대의 문제는 그 방향을 따라가는 비용이 너무 저렴해졌다는 점이다. 예전에는 방향만 잡고 한 걸음씩 움직였다면, 지금은 방향만 설정하면 AI가 비행기에 태워서 데려다준다. 그러나 인간의 정신과 신체는 아직 이 속도에 완전히 적응하지 못했다. 너무 빠르게 날면 금방 지치고 만다. 그렇기 때문에 스스로 멈출 정거장과 종점을 정해두는 게 좋다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;① 마감일을 정한다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;당연한 말이지만, 기한이 없으면 끝도 없다. 무한한 개선의 가능성을 유한한 시간 안에 가두는 것이다. 만약 내가 일기 앱을 출시하려고 마음먹는다면, 1차, 2차, 최종 마감일을 정해놓을 것이다. 마감일이 코앞이라면 새로운 개선 사항이 떠오르더라도 일단 백로그에 둔다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;회사 업무에는 정해진 기한이 있으니 그나마 낫지만, 사이드 프로젝트처럼 아무도 재촉하지 않는 작업은 기한을 정하는 게 어렵다. 그리고 바이브 코딩은 자연어로 작업을 하기 때문에 태스크에 소요되는 시간을 산정하는 게 쉬운 일이 아니다. 정확하지 않더라도 일단 적당한 날짜를 선택하고, 프로젝트를 진행하면서 날짜를 산정하는 감을 익히는 것이 좋다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;② 우선순위를 정해서 번갈아 가며 손을 댄다(멀티태스킹)&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;이건 아마 모든 사람에게 통용되지는 않을 수 있고, AI 성능이 향상될수록 효용이 떨어질 수 있는 방법론이다. 모델에 따라 차이가 있지만, 대체로 일을 시키면 그에 대한 응답이 돌아올 때까지 시간이 좀 걸린다. 그래서 나는 그 시간을 활용하기 위해 여러 작업창을 띄워두고 번갈아가면서 작업을 시킨다. 원래 멀티태스킹을 선호하는 편은 아니었는데, AI와 협업을 한 이후로는 좋아하게 되었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;내가 정한 우선순위는 ① 버그 수정 ② 마감이 임박한 일 ③ 난이도 높은 일이다. 버그는 최대한 빨리 고쳐야 하기 때문에, 이 터미널 창을 가장 자주 들여다본다. 이 세션에서 작업을 지시해두고, 마감이 임박한 작업을 또 다른 세션에서 지시한다. 두 세션이 모두 일을 하고 있으면 새 에이전트를 띄워서 다음에 만들 기능에 대해 아이디어 회의를 한다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;참고로 최근에 클로드에서 ‘Agent View’라는 기능을 만들었다. 여러 세션을 한눈에 보는 일종의 대시보드인데, 이 대시보드를 활용하면 좀 더 편리하게 세션을 관리할 수 있다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3787/image2.png"&gt;&lt;figcaption&gt;&amp;lt;출처: &lt;a href="https://claude.com/blog/agent-view-in-claude-code"&gt;Agent view in Claude Code&lt;/a&gt;&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이렇게 멀티태스킹을 하면 같은 시간에 더 많은 일을 끝낼 수 있다. 한 작업을 끝장내려고 매달리는 시간이 줄어든다. 다른 세션의 작업도 진행되고 있기 때문에, 이제는 퇴근 시간에 미련 없이 손을 뗄 수 있게 되었다. 그리고 일 하나에 너무 완벽을 기하다가 다른 일의 시작이 늦어지는 경우도 줄어들었다. 여러 문제에 골고루 시간을 씀으로써 전체 품질은 더 올라가게 되었다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;③ 하나의 작업 단위가 끝날 때마다 작업 내용을 docs에 기록해두도록 시킨다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;일을 멈추지 못하는 이유 중 하나는 다음 날이 되면 컨텍스트를 잊어버리기 때문이다. 물론 클로드는 대화 기록을 빠르게 다시 불러올 수 있지만, 인간의 기억은 좀 더 로딩 시간이 걸린다. 그래서 작업 중간중간 나를 위한 요약본을 정리하게 시켰다. 대강 일이 마무리되었다 싶을 때마다 클로드가 이렇게 묻는다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;“지금까지 한 작업을 기록해 둘까요?”&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이제 나는 언제든 마음 놓고 그날의 일을 끝낼 수 있게 됐다. 다시 돌아왔을 때 이 md 문서를 살펴보면, 금방 기억이 되살아나기 때문이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3787/image5.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;④ 유한함을 인정하는 마음가짐&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;AI의 작업 속도는 사실상 무한해 보이지만, 그걸 판단하는 나의 체력과 시간은 유한하다. ‘가능한 최선’이 아니라, ‘오늘의 최선’을 기준으로 삼으려고 노력한다. 번아웃을 겪기 전의 나는 이걸 몰랐다. 정신과 신체의 체력이 모두 고갈된 후에야 비로소 내 에너지가 무한하지 않다는 것을 인정하게 되었다. AI는 도구이고, 도구의 성능이 아무리 좋아도 그것을 쥐고 있는 손이 떨리면 소용이 없다. 이 비대칭을 받아들이고 나니 마음이 한결 편해졌다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;멈추는 것은 우리의 선택이다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI는 분명 우리를 더 나은 결과물에 가까이 데려다준다. 그것은 좋은 일이다. 하지만 더 나아질 수 있는 가능성을 전부 실현하려는 순간, 영원히 완성하지 못하는 사람이 된다. 시지프스의 바위가 멈추지 않는 이유는 신의 벌이지만, 우리의 바위가 멈추지 않는 이유는 멈추지 않기로 한 우리의 선택이다. 그래서 나는 마감일을 정하고, 여러 세션을 번갈아 돌리고, 중간중간 기록을 남기고, 오늘의 최선에서 손을 뗀다. 완벽주의가 나를 잡아먹지 않도록 노력한다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;물론 이 네 가지 방법을 쓴다고 해서 바로 마인드셋이 달라지는 것은 아니다. 나는 여전히 마감 직전에 “하나만 더” 시키고 싶은 마음이 들고, 제출 버튼을 누르는 순간에도 마음 한구석이 불편하다. 하지만 분명히 달라진 것은 어쨌든 그 불편함을 느끼면서도 버튼을 누를 수 있게 되었다는 것이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 글도 완벽하지 않지만 오늘 나의 최선이다. 내일의 나는 더 잘 쓸 수 있겠지만, 그건 내일의 일이다. 번아웃을 겪지 않는 인공지능에게 미래에 대체될 수도 있겠지만, 그것도 미래의 일이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 글을 쓰면서 다른 사람들은 어떤지도 궁금해졌다. AI와 함께 일하면서 비슷한 강박을 느끼는 사람도 있을 것이고, 나보다 훨씬 가벼운 마음으로 멈추는 사람도 있을 것이다. 만약 여러분만의 방법이 있다면, 댓글로 공유해 주셔도 좋겠다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3787/image4.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, ChatGPT로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>타입스크립트 타입, 꼭 새로 만들어야 할까?</title><link>https://yozm.wishket.com/magazine/detail/3760</link><description>타입스크립트로 프로젝트를 하다 보면, 기존에 정의해둔 타입을 조금만 바꿔서 쓰고 싶은 순간이 자주 찾아옵니다. 회원 정보 타입에서 비밀번호 필드만 빼고 싶을 때, 모든 필드를 선택적으로 바꿔서 수정 폼에 쓰고 싶을 때, 이미 정의된 타입에서 몇 개의 필드만 골라 목록 화면용 타입을 만들고 싶을 때 등이 대표적입니다. 타입스크립트는 이런 상황을 위해 유틸리티 타입(Utility Types)을 기본으로 제공합니다. 기존 타입을 입력으로 받아 일부를 골라내거나, 제외하거나, 선택적으로 바꿔주는 내장 도구들입니다. 이번 글에서는 그중에서도 실무에서 가장 자주 쓰이는 대표 유틸리티 타입 다섯 가지 Partial, Required, Pick, Omit, Record에 집중해서 살펴보겠습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3760</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;타입스크립트로 프로젝트를 하다 보면, 기존에 정의해둔 타입을 조금만 바꿔서 쓰고 싶은 순간이 자주 찾아옵니다. 회원 정보 타입에서 비밀번호 필드만 빼고 싶을 때, 모든 필드를 선택적으로 바꿔서 수정 폼에 쓰고 싶을 때, 이미 정의된 타입에서 몇 개의 필드만 골라 목록 화면용 타입을 만들고 싶을 때 등이 대표적입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이럴 때마다 새로운 타입을 처음부터 다시 정의하면 코드 중복이 생기고, 원본 타입이 바뀔 때마다 관련된 타입을 전부 찾아서 수정해야 하는 문제가 생기는데요. 이런 중복은 단순히 번거로운 정도를 넘어서, 타입과 실제 데이터가 어긋나는 버그로 이어지기 쉽습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;타입스크립트는 이런 상황을 위해 유틸리티 타입(Utility Types)을 기본으로 제공합니다. 기존 타입을 입력으로 받아 일부를 골라내거나, 제외하거나, 선택적으로 바꿔주는 내장 도구들입니다. 프레임워크나 별도의 라이브러리 없이 타입스크립트 자체에 포함되어 있기 때문에, 별다른 설정 없이 바로 사용할 수 있다는 점도 큰 장점입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 그중에서도 실무에서 가장 자주 쓰이는 대표 유틸리티 타입 다섯 가지 Partial, Required, Pick, Omit, Record에 집중해서 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;미리 요점만 콕 집어보면?&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;타입스크립트는 기존 타입을 입력으로 받아 일부를 골라내거나, 제외하거나, 선택적으로 바꿔주는 유틸리티 타입을 기본으로 제공합니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;Partial, Required, Pick, Omit, Record를 활용하면 원본 타입 하나만 정의해두고, 다른 타입은 그 원본을 변환해서 만들어 코드 중복과 타입 어긋남 문제를 줄일 수 있습니다.&lt;/li&gt;&lt;li style="text-align:justify;"&gt;유틸리티 타입은 서로 조합해 복잡한 변환도 선언적으로 표현할 수 있지만 중첩이 깊어질수록 가독성이 떨어져, 중간 단계 타입에 이름을 붙여 분리하는 편이 유지보수에 유리합니다.&lt;/li&gt;&lt;/ul&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;유틸리티 타입이 왜 필요한가&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;유틸리티 타입의 필요성을 이해하려면, 먼저 타입 중복이 어떻게 발생하는지부터 살펴봐야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 타입 중복의 문제&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;실무에서 비슷한 모양의 타입을 여러 번 정의하는 경우는 생각보다 흔합니다. 예를 들어, 회원 정보를 다루는 애플리케이션을 만든다고 해봅시다. 가입 화면, 프로필 수정 화면, 관리자용 목록 화면에서 사용하는 타입이 조금씩 다를 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface User {
  id: number;
  email: string;
  password: string;
  name: string;
  phone: string;
  createdAt: Date;
}

interface UserUpdate {
  email?: string;
  name?: string;
  phone?: string;
}

interface UserListItem {
  id: number;
  email: string;
  name: string;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;얼핏 보면 문제가 없어 보이지만, 이 구조에는 함정이 있습니다. User 타입에 새로운 필드(예:address)가 추가되면 UserUpdate와 UserListItem도 함께 수정해야 합니다. 수정을 빠뜨리면 원본 타입과 어긋난 상태가 되어 버그의 원인이 됩니다. 비슷한 타입이 늘어날수록 이 문제는 더 커지고, 타입 정의를 관리하는 데 쓰이는 시간도 급격히 증가합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3760/%EA%B7%B8%EB%A6%BC1__4_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude design으로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;게다가 이런 타입은 대부분 원본과 의존 관계를 갖고 있습니다. UserUpdate는 "수정 가능한 필드들"이고, UserListItem은 "목록에 노출할 필드들"입니다. 정말로 독립된 타입이 아니라 User를 재료로 파생된 타입들이라는 뜻입니다. 그렇다면 이 의존 관계를 타입 시스템으로도 명시해두는 편이 훨씬 자연스럽고 안전합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 기존 타입을 변환한다는 발상&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;해결책은 간단합니다. 원본 타입 하나만 잘 정의해두고, 나머지는 그 원본을 변환해서 만드는 것입니다. "이 필드만 골라내줘", "모든 필드를 선택적으로 바꿔줘" 같은 변환 규칙만 선언해두면 원본이 바귈 때 파생 타입도 자동으로 따라옵니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;타입스크립트는 이런 변환을 위한 내장 도구를 제공하는데, 이것이 바로 유틸리티 타입입니다. 예를 들어, 아직 자세히 다루지는 않았지만, 아래 코드를 한 번 살펴봅시다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type UserUpdate = Partial&amp;lt;Pick&amp;lt;User, "email" | "name" | "phone"&amp;gt;&amp;gt;;
type UserListItem = Pick&amp;lt;User, "id" | "email" | "name"&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Pick은 원본에서 특정 필드만 골라내고, Partial은 모든 필드를 선택적으로 바꿔줍니다. 이 두 줄만으로 앞서 별도의 인터페이스로 정의했던 UserUpdate와 UserListItem이 만들어집니다. User 타입의 email이 emailAddress로 바뀌더라도 관련 타입들은 컴파일러가 알아서 추적해주기 때문에, 타입 정의 한 곳만 고치면 됩니다. 이제 각 유틸리티 타입이 어떻게 동작하는지 하나씩 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;모든 필드를 선택적으로 - Partial&amp;lt;T&amp;gt;&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;수정 기능을 구현할 때 가장 먼저 만나게 되는 유틸리티 타입입니다. 업데이트할 필드만 전달받고 나머지는 그대로 두고 싶을 때, Partial&amp;lt;T&amp;gt;가 그 역할을 해줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Partial의 동작 원리&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Partial&amp;lt;T&amp;gt;는 이름 그대로 "부분적인" 타입을 만들어주는 유틸리티 타입입니다. 타입 T의 모든 프로퍼티를 선택적(optional)으로 바꾼 새 타입을 만들어줍니다. 필드 하나하나에 직접&amp;nbsp; ?를 붙이는 대신, 타입 수준에서 "전부 선택적으로"라는 규칙을 한 번에 적용하는 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface User {
  id: number;
  name: string;
  email: string;
  phone: string;
}

// 모든 필드가 optional로 변환됨
type UserPatch = Partial&amp;lt;User&amp;gt;;
// {
//   id?: number;
//   name?: string;
//   email?: string;
//   phone?: string;
// }
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 한 가지 짚고 넘어갈 점이 있습니다. 실무에서는 "optional 프로퍼티"와 “undefined를 허용하는 프로퍼티"를 거의 같은 의미로 이해해도 큰 문제가 없지만, 엄밀하게는 완전히 같은 개념은 아닙니다. 특히 exactOptionalPropertyTypes 옵션을 켜면 둘 차이가 명확하게 드러나므로, ?가 붙은 필드와 field: string | undefined가 언제나 호환된다고 단정하지 않는 편이 좋습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 실무 예시: 프로필 수정 함수&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Partial의 프로필 수정 함수에서 가장 전형적으로 활용됩니다. 변경된 필드만 받아서 원본 객체에 병합하는 구조입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function updateUser(user: User, patch: Partial&amp;lt;User&amp;gt;): User {
  return { ...user, ...patch };
}

const current: User = {
  id: 1,
  name: "효빈",
  email: "a@b.com",
  phone: "010",
};

// name만 변경하고 싶을 때
const updated = updateUser(current, { name: "효빈2" });
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;만약 Partial을 쓰지 않고 patch 매개변수 타입을 그냥 User로 받았다면, 호출할 때마다 모든 필드를 채워 넣어야 했을 것입니다. 이름만 바꾸는 경우에도 email, phone, id까지 전부 명시해야 하는 불편한 API가 되는 셈입니다. Partial 덕분에 실제로 바꾸고 싶은 필드만 골라서 넘길 수 있게 된 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 Partial을 사용할 때 한 가지 주의할 점이 있습니다. 모든 필드가 선택적이 된다는 말은, 빈 객체 {}도 유효한 값으로 인정된다는 뜻입니다. "아무것도 바꾸지 않는 업데이트"가 가능해지는 셈이므로, 적어도 하나의 필드는 반드시 받아야 하는 상황이라면 별도의 런타입 검증 로직이 필요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;모든 필드를 필수로 - Required&amp;lt;T&amp;gt;&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;Partial이 모든 필드를 선택적으로 바꿔주는 도구였다면, Required는 정반대 방향으로 작동합니다. 기본값 병합처럼, 선택적 입력을 확정된 상태로 만드는 시점에서 활용됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Required의 동작 원리&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Required&amp;lt;T&amp;gt;는 타입 T의 모든 선택적 프로퍼티에서 ?를 제거해, 모든 필드가 반드시 존재하도록 강제하는 타입을 만들어줍니다. 언뜻 보면 쓸 일이 있을까 싶지만, 설정 객체처럼 "기본값과 병합한 이후에는 모든 필드가 반드시 채워져 있어야 하는" 상황에서 유용합니다. 입력 시점에는 선택적이지만, 가공을 거친 이후에는 모든 값이 확정되어 있어야 한다는 흐름을 타입으로 자연스럽게 표현할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 실무 예시: 설정 객체 병합&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface Config {
  host?: string;
  port?: number;
  timeout?: number;
}

const defaultConfig: Required&amp;lt;Config&amp;gt; = {
  host: "localhost",
  port: 3000,
  timeout: 5000,
};

function createClient(userConfig: Config) {
  const config: Required&amp;lt;Config&amp;gt; = { ...defaultConfig, ...userConfig };
  // 이 시점부터 config의 모든 필드는 확정된 값을 가집니다.
  // 내부 구현에서는 host, port, timeout이 undefined일 가능성을 신경 쓰지 않고 바로 사용할 수 있습니다.
  return config;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;userConfig는 선택적으로 받지만, 기본값과 병합한 결과는 Required&amp;lt;Config&amp;gt;로 확정됩니다. 이렇게 되면 이후 코드에서 config.host가 undefined일 가능성을 걱정하지 않고 바로 사용할 수 있습니다. 선택성이라는 불확실성을 경계에서 한 번 제거하고 나면, 내부 구현 코드는 훨씬 단순해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 패턴은 타입스크립트에서 자주 등장하는 "입력은 느슨하게 받고, 내부에서는 엄격하게 다룬다"는 원칙의 전형적인 예시이기도 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;원하는 필드만 골라내기 - Pick&amp;lt;T, K&amp;gt;&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;기존 타입에서 특정 필드만 뽑아 새 타입을 만들고 싶을 때 사용하는 유틸리티 타입입니다. 컴포넌트 props처럼, 전체 데이터 중 일부만 필요로 하는 인터페이스를 명확하게 표현할 때 특히 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Pick의 동작 원리&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Pick&amp;lt;T, K&amp;gt;에서 T는 원본 타입이고, K는 골라낼 프로퍼티 키의 유니온입니다. 이때 K는 반드시 keyof T에 속하는 키여야 하므로, 원본 타입에 없는 키를 적으면 컴파일 에러가 납니다. 덕분에 오타가 나더라도 타입 단계에서 바로 잡을 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 실무 예시: 게시글 미리보기 타입&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface Post {
  id: number;
  title: string;
  content: string;
  author: string;
  createdAt: Date;
  likeCount: number;
  viewCount: number;
}

type PostPreview = Pick&amp;lt;Post, "id" | "title" | "author" | "createdAt"&amp;gt;;
// {
//   id: number;
//   title: string;
//   author: string;
//   createdAt: Date;
// }

function renderPostList(posts: PostPreview[]) {
  return posts.map((p) =&amp;gt; `${p.title} - ${p.author}`);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Pick의 장점은 타입 이름만 봐도 어떤 필드가 포함되는지 바로 알 수 있다는 것입니다. 별도로 새 인터페이스를 만들고 필드를 나열하는 것보다 훨씬 선언적입니다. 또한 원본 Post 타입의 필드 타입이 바뀌면 PostPreview도 자동으로 같이 바뀌기 때문에, 타입 동기화를 위한 수작업이 사라집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대로 Pick이 잘 맞지 않는 경우도 있습니다. 원본 타입에서 대부분의 필드를 남기고 일부만 제외하고 싶을 때는, 남길 필드를 일일이 나열해야 해서 오히려 장황해집니다. 이럴 때는 뒤에 소개할 Omit이 더 잘 어울립니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;특정 필드만 제외하기 - Omit&amp;lt;T, K&amp;gt;&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;Pick이 "남길 것을 고르는" 방식이라면, Omit은 "뺄 것만 지정하는" 방식입니다. 빼야 할 필드가 적고 남길 필드가 많을 때, Pick 보다 훨씬 간결합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Omit의 동작 원리&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Omit&amp;lt;T, K&amp;gt;는 원본 타입 T에서 K에 해당하는 프로퍼티만 빼고 나머지 전부로 새 타입을 만듭니다. Omit은 Pick과 달리 K에 keyof T 제약이 느슨하게 적용되긴 하지만, 실무에서는 원본에 존재하는 키만 지정하는 편이 의도를 명확히 드러내고 안전합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 실무 예시: 생성 요청에서 id 제외하기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;게시글 생성 API의 요청 타입을 만든다고 해봅시다. 서버가 자동으로 생성하는 id, createdAt 같은 필드는 클라이언트가 보내면 안 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface Post {
  id: number;
  title: string;
  content: string;
  author: string;
  createdAt: Date;
}

type CreatePostInput = Omit&amp;lt;Post, "id" | "createdAt"&amp;gt;;
// {
//   title: string;
//   content: string;
//   author: string;
// }

function createPost(input: CreatePostInput) {
  // 서버에 POST 요청
}
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;만약 Pick으로 같은 일을 하려면 Pick&amp;lt;Post, "title" | "content" | "author"&amp;gt; 처럼 남기고 싶은 필드를 전부 나열해야 합니다. 필드가 많아질수록 번거로워지고, 새 필드가 추가될 때마다 이 목록도 유지보수를 해야 합니다. 반면, Omit은 "빼고 싶은 것"만 지정하면 되기 때문에, 원본 타입에 필드가 추가되면 자동으로 새 타입에도 포함됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;비밀번호 같은 민감 정보를 응답에서 제외할 때도 자주 쓰입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface User {
  id: number;
  email: string;
  password: string;
  name: string;
}

type UserResponse = Omit&amp;lt;User, "password"&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 한 가지 주의할 점이 있습니다. 도메인 모델에서 요청 타입이나 응답 타입을 곧바로 파생시키는 방식은 편리하지만, 두 타입이 시간이 지나면서 서로 다른 방향으로 진화할 수도 있습니다. 이럴 땐 굳이 원본에 묶어두기보다는 독립된 타입으로 분리하는 편이 더 나을 수 있습니다. 유틸리티 타입은 강력하지만, 언제나 원본과 강하게 결합하는 것이 최선은 아니라는 점은 기억해 둘 만합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Pick과 Omit 중에 무엇을 쓸지 고민된다면, 간단한 기준을 기억해두면 좋습니다. 보통 "남기고 싶은 필드"가 소수일 때는 Pick, "빼고 싶은 필드"가 소수일 때는 Omit을 선택하는 편이 직관적입니다. 두 경우 모두 코드를 읽는 사람이 한눈에 의도를 파악할 수 있도록, 타입 이름에 의도를 명확하게 드러낸다는 점이 중요합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;키-값 쌍의 타입을 지정하기 - Record&amp;lt;K, V&amp;gt;&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;Record도 당연히 유틸리티 타입이지만, 앞선 네 가지와는 결이 조금 다릅니다. 기존 객체 타입을 변형하기보다는, 키 집합과 값 타입을 선언해 새로운 객체 구조를 만들 때 자주 쓰입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) Record의 동작 원리&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;Record&amp;lt;K, V&amp;gt;는 K에 해당하는 키 집합과 V에 해당하는 값 타입으로 구성된 객체 타입을 만들어줍니다. 인덱스 시그니처({ [key: string]: string })와 비슷해 보이지만 중요한 차이가 있습니다. 인덱스 시그니처는 "어떤 문자열 키든 허용한다"는 느슨한 약속이지만, Record는 키를 리터럴 유니온으로 제한할 수 있어서 허용되는 키 집합이 명확하게 고정됩니다. 지정한 키가 누락되면 컴파일 에러가 발생하고, 반대로 허용되지 않은 키를 추가하려 해도 에러가 발생합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type StatusLabel = Record&amp;lt;"loading" | "success" | "error", string&amp;gt;;
// {
//   loading: string;
//   success: string;
//   error: string;
// }

const labels: StatusLabel = {
  loading: "로딩 중",
  success: "성공",
  error: "실패",
};
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;위 예시에서 error 키를 빠뜨리고 선언하면, 타입스크립트가 바로 잡아줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 실무 예시: 상태별 라벨 매핑&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;정해진 키 집합에 대해 모든 값을 매핑해야 하는 상황에서 Record가 유용합니다. 페이지 권한, 상태별 스타일, 언어별 문자열 같은 경우가 그렇습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;type Role = "admin" | "member" | "guest";

const permissions: Record&amp;lt;Role, string[]&amp;gt; = {
  admin: ["read", "write", "delete"],
  member: ["read", "write"],
  guest: ["read"],
};
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;새로운 역할이 Role에 추가되면, permissions 객체에도 해당 키를 반드시 채워야 합니다. 이렇게 키 목록과 실제 데이터를 타입으로 강하게 묶어두는 것이 Record의 역할입니다. 새 키 추가와 데이터 반영이 함께 이루어지도록 타입 시스템이 강제해 주므로, 누락된 케이스로 인한 런타임 버그를 미리 차단할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;유틸리티 타입 조합하기&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;유틸리티 타입의 진짜 힘은 서로 조합해서 쓸 때 드러납니다. 각 유틸리티 타입이 작은 도구라면, 조합은 이 도구들을 이어 붙여 더 정교한 변환을 만들어내는 과정이라고 생각해 볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 여러 유틸리티 타입을 중첩해서 쓰기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;"일부 필드만 골라서, 그중에서도 전부 선택적으로 받고 싶다"라는 요구사항은 Partial과 Pick의 조합으로 풀립니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;// email, phone만 선택적으로 받아서 업데이트
type ContactUpdate = Partial&amp;lt;Pick&amp;lt;User, "email" | "phone"&amp;gt;&amp;gt;;

function updateContact(id: number, patch: ContactUpdate) {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-left:36pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;유틸리티 타입을 중첩할 때는 안쪽부터 바깥쪽 순서로 적용된다는 점을 기억하면 도움이 됩니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3760/%EA%B7%B8%EB%A6%BC2__4_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude design으로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;위 예시에서 Pick&amp;lt;User, "email" | "phone"&amp;gt;이 먼저 계산되어 email과 phone만 가진 타입이 만들어지고, 그 결과에 Partial이 적용되어 두 필드가 모두 선택적이 됩니다. 순서를 바꿔서 Pick&amp;lt;Partial&amp;lt;User&amp;gt;, "email" | "phone"&amp;gt;이라고 써도 결과는 비슷하지만, 변환 의도가 "일단 골라낸 후 선택적으로 만든다"인지 "전부 선택적으로 바꾼 후 일부만 고른다" 인지는 분명히 다릅니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존 타입에서 몇 개의 필드를 제외한 뒤, 특정 필드를 새로 덧붙이고 싶은 경우에는 Omit과 교차 타입(&amp;amp;)을 함께 사용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;// 기본 User에서 password는 빼고, role 필드는 추가
type AdminUser = Omit&amp;lt;User, "password"&amp;gt; &amp;amp; {
  role: "admin" | "super";
};
&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-left:36pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 지나친 중첩은 오히려 독&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;다만 조합이 깊어질수록 가독성이 떨어지는 점은 주의해야 합니다. 중첩이 서너 단계를 넘어가기 시작하면 타입 이름만 봐서는 의도를 파악하기 어려워집니다. 타입을 읽는 사람이 머릿속에서 여러 변환을 차례대로 적용해 결과를 상상해야 하기 때문입니다. 이런 경우에는 중간 단계 타입에 이름을 붙여서 분리하는 편이 유지보수에 훨씬 유리합니다. 타입에 이름을 붙이는 행위 자체가 일종의 문서 역할을 하기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;// ❌ 한 줄에 전부 다 담기
type A = Partial&amp;lt;Omit&amp;lt;Pick&amp;lt;User, "email" | "phone"&amp;gt;, never&amp;gt;&amp;gt;;

// ✅ 단계별로 이름 붙이기
type Contact = Pick&amp;lt;User, "email" | "phone"&amp;gt;;
type ContactPatch = Partial&amp;lt;Contact&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 실무에서 가장 자주 쓰이는 다섯 가지 유틸리티 타입을 살펴봤습니다. Partial&amp;lt;T&amp;gt;로 모든 필드를 선택적으로 바꾸고, Required&amp;lt;T&amp;gt;로 다시 모든 필드를 필수로 되돌릴 수 있습니다. Pick&amp;lt;T, K&amp;gt;로 원본에서 필요한 필드만 골라낼 수 있고, Omit&amp;lt;T, K&amp;gt;로 특정 필드를 빼낸 나머지 타입을 만들 수 있습니다. 그리고 Record&amp;lt;K, V&amp;gt;는 정해진 키 집합에 대한 값 타입을 강제할 때 유용합니다. 여러 유틸리티 타입을 조합하면 복잡한 변환도 선언적으로 표현할 수 있지만, 중첩이 깊어질 때는 중간 단계에 이름을 붙여 분리하는 편이 더 읽기 좋습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;비슷한 타입을 복사해서 조금씩 수정해가며 쓰고 있다면, 대부분의 경우 유틸리티 타입 한두 개로 중복을 깔끔하게 줄일 수 있습니다. 특히 API 요청/응답 타입, 폼 입력 타입, 상태 매핑 타입처럼 기존 모델에서 파생되는 타입이라면 유틸리티 타입의 활용 효과가 큽니다. 원본 모델 하나만 잘 관리하면, 파생 타입들은 컴파일러가 자동으로 따라와 주기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;유틸리티 타입에 익숙해지는 가장 좋은 방법은, 새 타입을 만들기 전에 한번 멈춰서 "이 타입은 혹시 기존 타입에서 파생된 것은 아닐까?"라고 스스로에게 물어보는 습관을 들이는 것입니다. 이런 질문을 거치다 보면, 인터페이스를 새로 정의하는 대신 유틸리티 타입으로 표현할 수 있는 경우가 생각보다 많다는 것을 알게 됩니다.&lt;/p&gt;&lt;hr&gt;&lt;p style="text-align:justify;"&gt;&amp;lt;참고&amp;gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:justify;"&gt;&lt;a href="https://ts.winterlood.com/a5b224e2-3f3e-432c-8bfb-7b338762514f%20,"&gt;&lt;u&gt;한 입 크기로 잘라먹는 타입스크립트&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;&lt;li style="text-align:justify;"&gt;&lt;a href="https://inpa.tistory.com/entry/TS-%F0%9F%93%98-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC"&gt;&lt;u&gt;타입스크립트 유틸리티 타입 총정리 (+응용) / 인파&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>에이전틱 엔지니어링 시대에서 살아남기</title><link>https://yozm.wishket.com/magazine/detail/3752</link><description>에이전트는 단순한 챗봇이 아니다. 문서를 읽고, 코드를 바꾸고, 툴을 호출하고, 결과를 다시 평가해 다음 행동을 선택하는 실행 주체다. 이 말은 곧, AI를 잘 쓴다는 것이 “질문을 잘하는 사람”에 머무르지 않는다는 뜻이다. 이제는 AI와 사람이 함께 일해도 무너지지 않는 구조를 설계하는 사람이 오래 살아남을 것이다. 이 글의 핵심은 하나다. 에이전트 시대의 승부처는 모델 이해가 아니라 업무 설계다. 누가 더 멋진 프롬프트를 쓰느냐보다, 누가 더 나은 작업 단위와 검증 루프를 만들 수 있느냐가 훨씬 중요해진다.</description><guid>https://yozm.wishket.com/magazine/detail/3752</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;지금 하는 일에서 AI를 얼마나, 그리고 어떻게 쓰고 있는가? 요즘은 프롬프트, 에이전트, 컨텍스트, 하네스 같은 용어를 이제 개발자만 쓰지 않는다. 기획자도, 디자이너도, 운영 조직도 AI를 “어떻게 붙일지”를 이야기한다. 겉으로 보면 AI는 이미 모두의 도구가 된 것처럼 보인다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 정작 현장에서 벌어지는 일은 조금 다르다. 많은 조직이 아직도 AI를 “답변을 잘 뽑아주는 도구” 정도로 다룬다. 좋은 프롬프트를 쓰는 사람이 앞서고, 모델을 빨리 바꿔 쓰는 사람이 유리하다고 생각한다. 하지만 에이전트가 본격적으로 업무에 들어오면, 경쟁력의 축은 전혀 다른 곳으로 이동한다. 중요한 것은 더 이상 한 번에 더 좋은 답을 뽑는 능력이 아니다. 일을 기계가 다룰 수 있는 단위로 쪼개고, 기준을 명시하고, 실패를 되돌릴 수 있게 설계하는 능력이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3752/image3.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, 나노 바나나&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;에이전트는 단순한 챗봇이 아니다. 문서를 읽고, 코드를 바꾸고, 툴을 호출하고, 결과를 다시 평가해 다음 행동을 선택하는 실행 주체다. 이 말은 곧, AI를 잘 쓴다는 것이 “질문을 잘하는 사람”에 머무르지 않는다는 뜻이다. 이제는 AI와 사람이 함께 일해도 무너지지 않는 구조를 설계하는 사람이 오래 살아남을 것이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 글의 핵심은 하나다. 에이전트 시대의 승부처는 모델 이해가 아니라 업무 설계다. 누가 더 멋진 프롬프트를 쓰느냐보다, 누가 더 나은 작업 단위와 검증 루프를 만들 수 있느냐가 훨씬 중요해진다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;AI Agent의 등장은 무엇을 바꾸는가&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI Agent의 등장은 생산성을 올린다. 하지만 더 정확히 말하면, 생산성의 병목을 이동시킨다. 예전에는 결과물을 만드는 실행력이 중요했다면, 이제는 생성보다 검증, 작성보다 조율, 개인 숙련보다 시스템 설계가 더 중요해진다. 에이전트는 많은 일을 빠르게 처리할 수 있지만, 동시에 그럴듯하게 틀릴 수도 있다. 그래서 에이전트를 잘 쓰는 조직은 “무엇을 자동화할 것인가”보다 “어디서 멈추고, 어떻게 검증할 것인가”를 먼저 설계한다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3752/image2.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 젠스파크&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제로 바뀌는 것은 업무의 단위다. 과거의 자동화가 정해진 규칙을 코드로 옮기는 일이었다면, 에이전트 기반 자동화는 애매한 문맥과 예외를 포함한 채 일을 진행한다. 이때 중요한 것은 모델 자체보다 그 모델이 의존하는 환경이다. 컨텍스트는 단순히 긴 프롬프트가 아니라, 무엇이 최신 정보인지, 어떤 문서가 기준인지, 어떤 툴을 호출할 수 있는지, 어떤 경우에 중단해야 하는지를 포함한 운영 환경 전체다. 하네스는 그 환경을 안전하게 반복 실행하게 만드는 장치다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어, 플랫폼 팀이 수백 개 저장소의 설정 파일을 새 표준으로 마이그레이션한다고 해보자. 에이전트는 저장소 구조를 읽고, 필요한 수정 사항을 판단하고, PR까지 만들 수 있다. 하지만 어떤 저장소를 대상에 포함할지, 얼마나 큰 diff를 허용할지, 반드시 통과해야 할 테스트는 무엇인지, 예외 케이스는 누구에게 넘길지, 실패 시 어떻게 롤백할지를 정해두지 않으면 이 작업은 금방 PR 스팸이 된다. 결국 생산성을 가르는 것은 “더 빨리 쓰는 능력”이 아니라, 그 작동 조건을 &lt;strong&gt;설계하는 능력&lt;/strong&gt;이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또 하나 드러나는 것은 암묵지의 한계다. 사람은 “이 서비스는 원래 이렇게 다뤄야 한다” 같은 구두 규칙으로도 어떻게든 협업하지만, 에이전트는 그런 문맥을 일관되게 따르지 못한다. 그래서 문서화가 약하고, 기준이 사람마다 다르고, 예외 규칙이 정리돼 있지 않은 조직일수록 에이전트를 붙였을 때 혼란이 더 커진다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;결국 AI Agent의 등장은 “일을 대신 해주는 똑똑한 도구”의 추가가 아니라, 일을 설계 가능한 형태로 바꾸라고 요구하는 변화에 가깝다. 잘 정리된 조직은 레버리지를 얻고, 정리되지 않은 조직은 혼돈이 증폭된다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실무자는 무엇을 세팅해야 하는가?&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;일을 잘게 나누고, 기준을 명시하고, 검증 루프를 설계하기&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;그러면 실무자는 무엇부터 해야 할까? 실무자가 가장 먼저 해야 할 일은 자기 일을 어떤 상태 전이의 묶음으로 볼 수 있는지 정의하는 것이다. 말하자면 “내 업무를 API처럼 설명할 수 있는가”가 핵심이다. 입력은 무엇이고, 필요한 맥락은 무엇이며, 출력은 어떤 형식이어야 하고, 어느 조건에서 실패로 간주해야 하는지 설명할 수 있어야 한다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이때 일을 나누는 기준은 조직도나 직무명이 아니라, 가역성과 관측 가능성이다. 되돌리기 쉽고 결과를 확인하기 쉬운 일은 에이전트에게 많이 맡길 수 있다. 예를 들어, 포맷팅, 테스트 코드 초안 작성, 규칙 기반 리팩토링, 문서 정리 같은 작업은 비교적 안전하다. 반대로 되돌리기 어렵거나 결과를 바로 검증하기 어려운 일, 예컨대 운영 환경 설정 변경, 고객 커뮤니케이션의 최종 발송, 보안 정책 예외 승인 같은 일은 반드시 사람 승인이나 추가 검증이 필요하다. 문제는 많은 팀이 이 구분 없이 “일단 붙여보자”는 식으로 접근한다는 점이다. 그러면 자동화는 늘어나는데 신뢰는 쌓이지 않는다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;우리가 사람들로 이루어진 조직에서 일을 할 때 생각해보면 팀장과 팀원이 있을 때 처음에 팀장이 일을 받아온다. 팀장은 팀원들의 업무 이해도나 숙련도를 종합적으로 판단해서 업무를 분배하고 기간을 조율한다. 그러면 팀원들은 그 업무를 받아서 수행하고 중간중간 팀장은 팀원들이 막히는 영역을 같이 해결해 준다. 그렇게 팀원들이 각자에게 주어진 업무를 완료하면 팀장은 종합해서 본인의 상사에게 보고한다. 이러한 흐름을 팀장 = 실무자, 팀원 = 에이전트가 하는 것이라고 생각하면 이해가 쉬울 것이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기준을 명시하는 것도 중요하다. 대부분의 실패는 에이전트가 멍청해서 생기지 않는다. 성공 조건이 애매해서 생긴다. “좋은 코드로 바꿔줘”는 지시가 아니다. 성능 회귀가 없어야 하는지, 공개 API 호환성을 유지해야 하는지, 마이그레이션 비용을 최소화해야 하는지, 테스트 커버리지를 유지해야 하는지, 로깅 정책을 따라야 하는지가 빠져 있다면 에이전트는 결국 가장 손쉬운 지역 최적화로 흘러간다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예를 들어, PR 리뷰 에이전트를 생각해 보자. 많은 팀이 이런 시도를 한다. 그런데 대개 초기에 받는 평가는 비슷하다. “말은 많은데 도움이 안 된다.” 이유는 간단하다. 리뷰 기준이 없기 때문이다. 스타일 잔소리를 할지, 동시성 문제를 볼지, 데이터 무결성 리스크를 볼지, API 변경의 파급 범위를 볼지 기준이 없으면 에이전트는 가장 표면적인 문제만 건드린다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대로 리뷰 기준을 “보안, 동시성, 마이그레이션 리스크, 외부 인터페이스 영향, 테스트 누락” 같은 축으로 명시하고, 각 축마다 어떤 근거를 제시해야 하는지 정해두면 에이전트의 품질은 급격히 달라진다. 중요한 것은 답변의 문장력이 아니라, 판단의 프레임이 구조화되어 있는지다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3752/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, 나노 바나나&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;검증 루프는 더 중요하다. 여기서 많은 팀이 흔히 빠지는 함정이 있다. 같은 모델에게 “다시 확인해봐”라고 시키는 것을 검증이라고 착각하는 것이다. 하지만 자기 자신에게 채점하게 하는 것은 검증이라기보다 자기합리화에 가깝다. 좋은 검증 루프는 생성기와 독립적이어야 한다. 정적 분석기, 테스트 스위트, 샌드박스 실행, 시뮬레이션, 스키마 검증, 정책 룰 엔진, 휴먼 리뷰처럼 다른 종류의 체크포인트가 필요하다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;장애 대응에서도 이 차이는 분명하게 드러난다. 에이전트에게 “장애 원인을 찾아봐”라고 하면 로그를 읽고, 최근 배포를 찾고, 메트릭 변화를 요약하고, 가능한 가설을 정리하는 데는 꽤 유용하다. 하지만 바로 롤백이나 설정 변경까지 맡기면 위험해진다. 잘 되는 팀은 런북을 서술형 문서가 아니라 의사결정 트리처럼 관리한다. 어떤 증상이 보이면 어떤 증거를 먼저 수집하고, 어떤 조건이 충족될 때만 롤백 후보를 제안하며, 어느 선을 넘으면 반드시 당직자가 승인하게 할지를 명시한다. 이 구조 안에서 에이전트는 “판단의 대체자”가 아니라 “관찰과 정리의 가속기”가 된다. 바로 이 지점이 실무적이다. 좋은 팀은 에이전트에게 자율성을 주기 전에, 먼저 실패 반경을 줄인다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또 하나의 실무 포인트는 &lt;strong&gt;컨텍스트를 덜어내는 능력&lt;/strong&gt;이다. 많은 사람이 컨텍스트 엔지니어링을 “관련 자료를 최대한 많이 넣는 일”로 이해한다. 하지만 실제로는 반대다. 많이 넣는 것보다, 충돌하지 않게 넣는 것이 어렵다. 낡은 문서와 최신 정책이 함께 들어가 있고, 예외 규칙이 본문 어딘가에 buried 되어 있고, 동일한 개념이 팀마다 다른 이름으로 쓰이면 에이전트는 높은 확률로 그럴듯한 혼합물을 만든다. 실무자가 해야 할 일은 지식을 더 많이 넣는 것이 아니라, 기준이 되는 지식을 더 작고 더 선명하게 만드는 일이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 글을 쓰는 시점(2026년 4월)에서 Claude Opus 4.7 모델이 가장 최신인데, 한 번에 1M 토큰까지 컨텍스트를 기억할 수 있다. 그런데 우리가 점점 복잡한 작업을 하다 보면 이 한계치는 생각보다 금방 도달하게 된다. 그렇기 때문에 컨텍스트를 1M 이내에서 적절하게 넣고, 요약하고, 새로운 대화로 옮겨서 이어가는 등의 전략을 사용하는 것이 중요하다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;요약하면, 개인이 에이전트 시대에 세팅해야 할 역량은 세 가지다. 일을 잘게 나누는 분해력, 성공과 실패를 명시하는 명세력, 결과를 믿을 수 있게 만드는 검증 설계력이다. 프롬프트 감각은 그 다음 문제다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;팀과 리더는 무엇을 설계해야 하는가?&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;도입보다 중요한 공통 설정과 운영 체계&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;개인이 AI를 잘 쓴다고 조직 전체가 잘 굴러가지는 않는다. 에이전트가 팀 단위로 들어오는 순간, 누구의 문서를 기준으로 삼을지, 어떤 데이터에 접근할지, 잘못된 행동을 누가 감시할지 같은 운영 문제가 함께 생긴다. 이걸 개인 재량에 맡기면 팀은 금방 “AI를 쓰는 사람”과 “AI가 만든 결과를 뒷수습하는 사람”으로 갈라진다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 리더가 가장 먼저 설계해야 할 것은 &lt;strong&gt;공통 컨텍스트 레이어&lt;/strong&gt;다. 용어 사전, 시스템 경계, API 계약, 운영 정책, 보안 규칙, 예외 승인 절차가 흩어진 위키 문서로 존재해서는 안 된다. 에이전트가 읽을 수 있고 사람도 신뢰할 수 있는 형태로 정리돼야 한다. 결국 조직의 AI 경쟁력은 모델보다 내부 문서의 정합성에서 나온다. 어떤 문서가 최신인지, 같은 개념이 팀마다 다른 이름으로 불리지 않는지, 런북과 실제 운영 상태가 어긋나지 않는지가 기본기이자 레버리지다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다음은 &lt;strong&gt;권한과 책임의 경계&lt;/strong&gt;다. 무엇을 보여줄지보다 무엇을 못 하게 할지가 더 중요하다. 읽기와 쓰기 권한은 분리돼야 하고, 운영 변경은 샌드박스나 드라이런을 거쳐야 하며, 민감한 액션에는 승인 단계가 필요하다. 에이전트 운영은 똑똑함의 문제가 아니라 통제의 문제다. 실패는 종종 모델 한계보다 권한 설계 부실에서 나온다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기존에 많은 팀에서 사용하는 RBAC(Rule Based Access Control)이나 OAuth 같은 인증, 권한 방식은 사람에게 적합한 방식이다. 예를 들어, CTO가 RBAC에서 최고 관리자 권한을 가지고 있어서 깃헙 레포지토리를 지우거나, 프로덕션 DB를 수정할 수 있다고 하더라도 사람은 그 행동을 일반적인 경우에 하지 않는다. 왜냐하면 그 행동이 위험하고 문제를 일으킬 수 있다는 것을 알기 때문이다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 에이전트는 최고 관리자 권한이 있다면 마음대로 레포지토리를 지우거나 프로덕션 DB 테이블을 수정할지도 모른다. 따라서 이러한 기존의 인증, 권한 방식도 에이전트 기반 워크플로에서는 다른 대안을 찾을 필요가 있다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;평가 체계&lt;/strong&gt;도 필수다. 좋은 팀은 프롬프트보다 평가 셋을 공유한다. 어떤 요청에 어떤 응답이 나와야 하는지, 어떤 행동은 금지인지, 과거에 어디서 실패했는지를 축적한다. 이건 품질 관리가 아니라 회귀 테스트에 가깝다. 예를 들어 보안 취약점 triage를 자동화할 때 자산 중요도 기준, 예외 승인 규칙, 에스컬레이션 정책이 통일돼 있지 않으면 에이전트는 금방 신뢰를 잃는다. 반대로 이 기준들이 정리돼 있으면 업무량을 실제로 줄일 수 있다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;리더가 봐야 할 지표도 달라져야 한다. “몇 명이 AI를 쓰는가”보다, 에이전트 결과의 채택률, 수정 시간, 재오픈율, 롤백률, 리뷰 부담이 줄었는지를 봐야 한다. 팀과 리더의 역할은 AI를 도입하는 것이 아니라, AI가 들어와도 조직이 무너지지 않게 공통 설정과 운영 체계를 만드는 데 있다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;결국 살아남는 사람의 공통점&lt;/strong&gt;&lt;/h3&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;도구 사용자가 아니라 협업 환경 설계자&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;에이전트 시대에 오래 살아남는 사람은 AI를 가장 자주 쓰는 사람이 아니다. 오히려 AI와 사람이 함께 일할 때 어디서 마찰이 생기고, 어디서 오류가 커지며, 무엇을 미리 구조화해야 하는지 아는 사람이다. 이들은 &lt;strong&gt;도구 사용자가 아니라 협업 환경 설계자&lt;/strong&gt;에 가깝다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이런 사람들은 암묵지를 외부화한다. 자기만 아는 요령을 체크리스트, 예시, 금지 규칙으로 바꾼다. 예전에는 “감으로 안다”가 강점이었다면, 이제는 “그 감을 구조로 바꾼다”가 더 큰 강점이 된다. 또한 일을 설명할 때 자연어의 모호함에 기대지 않는다. 입력과 출력, 예외와 중단 조건, 책임이 넘어가는 지점을 분명히 한다. 에이전트를 잘 다루는 사람은 프롬프트 장인이 아니라 인터페이스 설계자다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이들은 복구 가능성도 중시한다. 에이전트가 실수하지 않게 만드는 것만큼, 실수했을 때 빨리 되돌릴 수 있게 만드는 것을 중요하게 본다. 드라이런, 샌드박스, 작은 배치, canary, 롤백 스크립트, 승인 게이트에 집착하는 이유다. 에이전트 시대의 유능함은 정답을 많이 만드는 능력보다 오답의 비용을 낮추는 능력에 더 가깝다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대로 도태되기 쉬운 사람은 AI를 검색창의 연장선으로만 보고, 맥락 없는 결과물을 대량으로 만드는 데 만족하는 사람이다. “모델이 더 좋아지면 해결될 문제”라고 믿으며 기준과 운영 설계를 미루는 태도도 마찬가지다. 시간이 갈수록 커지는 것은 결과물의 양이 아니라 주변 사람들의 검토 비용이다. 결국 살아남는 사람은 AI를 잘 쓰는 사람이 아니라, AI가 잘 일할 수 있는 환경을 만드는 사람이다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;에이전트 시대의 경쟁력은 기술 이해가 아니라, 일의 방식을 재설계하는 능력이다. 모델 이름을 많이 아는 것, 프롬프트를 그럴듯하게 쓰는 것, 최신 기능을 빨리 시험해 보는 것만으로는 오래 가지 않는다. 진짜 차이는 일을 얼마나 기계가 처리할 수 있는 단위로 나누고, 얼마나 명확한 기준으로 정의하며, 얼마나 튼튼한 검증 루프로 감쌌는지에서 나온다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;에이전트는 엔지니어를 대체하기보다, 엔지니어링이 얼마나 구조화돼 있는지를 시험한다. 기준이 사람 머릿속에만 있고, 예외가 문서화되지 않았고, 검증이 개인의 감각에 의존하던 조직은 에이전트를 붙일수록 불안정해진다. 반대로 일의 경계가 분명하고, 실패가 기록되며, 시스템이 복구 가능하게 설계된 조직은 에이전트를 통해 폭발적인 레버리지를 얻는다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 지금 필요한 질문은 “AI를 쓸 것인가 말 것인가”가 아니다. “우리의 일은 에이전트와 협업 가능한 구조인가”다. 이 질문에 제대로 답할 수 있는 사람, 그리고 그 구조를 실제로 설계할 수 있는 사람이 결국 살아남는다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;에이전트 시대에 강한 사람은 도구를 능숙하게 쓰는 사람이 아니다. 사람과 AI가 함께 일해도 품질과 신뢰가 무너지지 않는 시스템을 만드는 사람이다. 앞으로의 경쟁력은 손이 빠른 사람보다, 기준을 세우는 사람에게 있다. 프롬프트를 잘 쓰는 사람보다, 실패를 설계하는 사람이 오래 남는다. 이 글을 읽는 모든 분들이 에이전트 시대에서 변화에 잘 적응하고 성장할 수 있길 바란다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>스프링 부트(Spring Boot)는 왜 아직도 살아남았을까?</title><link>https://yozm.wishket.com/magazine/detail/3744</link><description>기술 세계는 정말 빨리 바뀝니다. 어제까지 뜨겁던 기술이 몇 년 뒤에는 조용해지고, 또 다른 이름의 프레임워크가 등장합니다. 그래서 백엔드를 처음 공부하는 분들은 종종 이렇게 생각합니다. “스프링은 너무 오래된 거 아닌가?” 저도 처음에는 비슷했습니다. 처음 스프링 프로젝트를 열었을 때 느낀 인상은 솔직히 무겁고, 복잡하고, 파일도 많고, 구조도 딱딱하다는 쪽에 가까웠습니다. 그런데 이상하게도 한국에서 일할 때도 스프링을 봤고, 일본에서 일할 때도 또 스프링을 봤습니다. 더 흥미로웠던 건 단순히 예전부터 쓰던 기술이라서 남아 있는 게 아니라는 점이었습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3744</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;유행은 빨리 바뀌는데, 왜 현장은 아직도 스프링일까요?&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image6.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기술 세계는 정말 빨리 바뀝니다. 어제까지 뜨겁던 기술이 몇 년 뒤에는 조용해지고, 또 다른 이름의 프레임워크가 등장합니다. 그래서 백엔드를 처음 공부하는 분들은 종종 이렇게 생각합니다. “스프링은 너무 오래된 거 아닌가?” 저도 처음에는 비슷했습니다. 처음 스프링 프로젝트를 열었을 때 느낀 인상은 솔직히 무겁고, 복잡하고, 파일도 많고, 구조도 딱딱하다는 쪽에 가까웠습니다. Controller, Service, Repository, DTO, Entity가 한꺼번에 보이면 괜히 숨이 턱 막히기도 했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 이상하게도 한국에서 일할 때도 스프링을 봤고, 일본에서 일할 때도 또 스프링을 봤습니다. 더 흥미로웠던 건 단순히 예전부터 쓰던 기술이라서 남아 있는 게 아니라는 점이었습니다. 회의에서 기술을 고를 때도 “요즘 유행해서”가 아니라 “운영하기 편해서”, “인수인계가 쉬워서”, “기존 시스템과 잘 맞아서”, “장애가 나도 추적이 쉬워서” 같은 이유로 선택되는 장면을 자주 봤습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한 번은 일본 프로젝트에서 이런 말을 들은 적이 있습니다. “새로운 기술도 좋지만, 이건 5년 뒤에 다른 사람이 들어와도 이해할 수 있어야 합니다.” 그 말을 듣고 조금 뜨끔했습니다. 저는 기술을 볼 때 얼마나 새롭고 멋진가를 먼저 봤는데, 현장은 얼마나 오래 버틸 수 있는가를 먼저 보고 있었기 때문입니다. 그때부터 스프링을 보는 눈이 조금 달라졌습니다. 이건 단순히 오래된 기술이 아니라, 오래 굴려도 쉽게 무너지지 않도록 정리된 구조일 수 있겠다고 느꼈습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 이번 글에서는 스프링 부트 아키텍처를 교과서처럼 설명하기보다, 왜 이 구조가 한국과 일본의 실무 현장에서 여전히 살아남고 있는지 이야기해 보려고 합니다. 중요한 건 “옛날 기술인가?”가 아니라 “왜 아직도 선택되는가?”였기 때문입니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;처음 보면 복잡한데, 왜 이 구조를 계속 쓸까요?&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image4.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;스프링 부트를 처음 배우면 가장 먼저 드는 생각은 아마 이것일 겁니다. “왜 이렇게 나눠놨지?” 간단한 기능 하나를 만들 뿐인데도 Controller가 생기고, Service가 생기고, Repository가 생깁니다. 거기에 Entity와 DTO까지 붙으면 작은 기능 하나가 제법 큰 구조처럼 보입니다. 처음 배우는 입장에서는 솔직히 부담스럽습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 흐름만 놓고 보면 구조 자체는 단순합니다. 사용자가 요청을 보내면 Controller가 받고, 비즈니스 로직은 Service가 처리하고, 데이터 저장과 조회는 Repository가 맡습니다. 이걸 어렵게 느끼게 만드는 건 구조의 개수보다도 아직 역할 감각이 익숙하지 않기 때문입니다. 어떤 코드는 어디에 두는 게 맞는지 감이 안 잡히니까 모든 레이어가 다 비슷해 보이고, 그래서 괜히 복잡해 보이는 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 프로젝트가 조금만 커지면 이 분리가 왜 필요한지 서서히 보이기 시작합니다. 회원가입 기능 하나만 생각해 봐도 입력값 확인, 중복 검사, 암호화, 저장 로직이 전부 한 파일에 들어가면 처음엔 빨라도 나중엔 수정이 무섭습니다. 결국 스프링의 계층형 구조는 멋있게 나누기 위한 구조가 아니라, 나중에 덜 엉키기 위해 미리 나눠두는 구조에 가깝습니다. 저는 예전엔 이걸 정석이라서 따라야 하는 규칙처럼 받아들였는데, 실무를 겪고 나니 헷갈림을 줄이기 위한 약속에 더 가깝다는 걸 알게 됐습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;혼자 만들 때는 귀찮은데, 팀 개발에서는 왜 갑자기 강해질까요?&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image5.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;개인 프로젝트에서는 스프링 구조가 꽤 답답하게 느껴질 수 있습니다. 간단한 API 하나를 추가하려고 해도 파일이 늘어나고, 손이 많이 갑니다. “그냥 한 파일에 다 넣으면 더 빠른데?”라는 생각이 드는 것도 이상한 일이 아닙니다. 그런데 사람이 늘어나는 순간 상황이 완전히 달라집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;프론트엔드 개발자가 요청 형식을 바꿔 달라고 할 수 있고, 기획자가 조건을 수정할 수도 있고, DB 구조가 바뀌는 일도 생깁니다. 이때 코드가 한곳에 뒤엉켜 있으면 수정 범위를 찾는 것부터 오래 걸립니다. 반대로 계층이 나뉘어 있으면 길을 잡기가 쉽습니다. 요청과 응답 모양이 바뀌면 Controller를 보면 되고, 업무 규칙이 바뀌면 Service를 보면 되고, 저장 방식이 바뀌면 Repository를 보면 됩니다. 이건 단순히 코드 스타일의 문제가 아니라 협업 비용이 줄어드는 문제입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;누가 어느 부분을 맡아야 하는지가 보이고, 서로 건드리는 범위가 줄고, 변경 영향도 파악이 쉬워집니다. 팀 프로젝트에서 이 차이는 생각보다 엄청 큽니다. 저는 일본 프로젝트에서 이 장면을 꽤 자주 봤습니다. 설계서가 먼저 나오고, 담당이 나뉘고, 테스트 담당이 따로 붙는 흐름이 많았는데, 구조가 명확하면 문서와 코드가 서로 잘 맞아떨어졌습니다. 반대로 구조가 애매하면 설명도 길어지고, 인수인계도 어려워졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;중간에 투입된 개발자 한 분이 프로젝트를 보더니 “아, 흐름이 보이네요”라고 말한 적이 있었습니다. 그 한마디가 오래 남았습니다. 좋은 구조는 지금 쓰는 사람보다 다음에 들어올 사람이 길을 잃지 않게 해주는 구조라는 뜻처럼 들렸기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;한국에서 스프링이 쉽게 사라지지 않는 이유&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한국에서 스프링이 여전히 강한 이유를 “익숙해서”라고만 설명하면 조금 부족합니다. 익숙함은 분명한 이유 중 하나지만, 그것만으로 이렇게 오래 버티기는 어렵습니다. 한국의 실무 환경에서는 여전히 안정성과 표준화가 중요한 영역이 많습니다. 공공, 대기업, SI, 장기 운영 시스템처럼 실패 비용이 큰 프로젝트일수록 “새롭다”보다 “검증됐다”가 더 중요해집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실제 프로젝트에서 자주 나오는 질문도 비슷합니다. 정말 안정적으로 돌아가는가, 기존 시스템과 잘 붙는가, 사람을 구하기 쉬운가, 문서와 사례가 충분한가. 이 기준에서 보면 스프링은 꽤 강합니다. 이미 많은 시스템이 Java와 스프링 기반으로 운영되고 있고, 관련 경험을 가진 개발자도 많습니다. 교육 자료도 많고, 문제 해결 사례도 풍부합니다. 즉, 기술 하나만 있는 게 아니라 운영 경험까지 같이 쌓여 있는 기술입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기에 레거시 시스템도 큰 이유가 됩니다. 이미 잘 돌아가고 있는 시스템이 스프링 기반이라면, 그걸 완전히 다른 기술로 갈아타는 건 생각보다 큰일입니다. 비용도 들고, 리스크도 크고, 연동 문제도 따라옵니다. 그래서 실무에서는 전부 새로 만드는 것보다 기존 구조를 유지하면서 확장하는 쪽이 더 현실적인 선택이 됩니다. 저는 이걸 한국 실무의 특징 중 하나라고 느꼈습니다. 새 기술을 싫어해서가 아니라, 망가지지 않는 기술을 더 높게 평가하는 분위기가 있다는 점입니다. 스프링은 바로 그 기준에서 오래 점수를 받아온 기술이었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;일본에서는 왜 더 잘 맞아 보였을까요?&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image7.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;일본에도 스프링이 자주 보입니다. 다만 제가 현장에서 느낀 이유는 한국과 조금 결이 달랐습니다. 한국이 검증된 운영 경험을 중요하게 본다면, 일본은 거기에 더해 예측 가능한 절차를 아주 중요하게 보는 느낌이 있었습니다. 특히 문서 기반 개발 문화가 강한 현장일수록 이 차이가 더 크게 보였습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;일본에서는 설계서가 먼저 나오고, 그 설계서를 기준으로 개발이 이어지는 경우가 많았습니다. 이때 Controller, Service, Repository처럼 역할이 구분된 구조는 문서와 코드가 잘 맞습니다. 요청은 어디서 받고, 규칙은 어디서 처리하고, 저장은 어디서 하는지가 비교적 명확하기 때문입니다. 반대로 구조가 너무 자유롭거나 작성자 취향이 강하면 문서와 실제 구현 사이가 멀어집니다. 그러면 개발도 어렵지만 유지보수는 더 어려워집니다. 결국 설명 비용이 커지고, 인수인계 비용도 커집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;일본에서 긴 프로젝트를 많이 본 것도 인상적이었습니다. 1년 안에 끝나는 일보다 3년, 5년 이상 이어지는 프로젝트가 적지 않았고, 그동안 담당자가 바뀌는 일도 많았습니다. 이런 환경에서는 지금 만든 사람이 제일 잘 아는 구조보다 다음 사람이 빨리 파악할 수 있는 구조가 훨씬 중요합니다. 그 점에서 스프링은 일본 실무와 잘 맞았습니다. 화려하진 않지만 익숙하고, 설명하기 쉽고, 예측하기 좋기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;처음 보는 프로젝트의 백엔드 흐름을 따라가야 했던 적이 있었는데, 구조가 익숙해서 생각보다 빨리 읽혔습니다. 그때 좋은 구조는 천재적인 구조가 아니라 낯선 사람도 들어올 수 있는 구조일 수 있겠구나 싶었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;실무에서 느낀 진짜 장점은 ‘멋짐’보다 ‘안정감’&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image8.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;스프링 부트의 장점을 말할 때 흔히 생산성, 생태계, 확장성을 이야기합니다. 전부 맞는 말입니다. 하지만 현업에서 오래 보다 보면 조금 더 현실적인 장점이 눈에 들어옵니다. 첫 번째는 길을 잃지 않게 해준다는 점입니다. 프로젝트가 커질수록 새 기능을 만드는 시간보다 기존 기능을 수정하거나 버그를 추적하는 시간이 더 길어집니다. 이때 구조가 정리되어 있으면 어디서부터 봐야 할지가 보입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;두 번째는 팀의 대화가 쉬워진다는 점입니다. “이건 Controller에서 처리할까요?”, “이건 Service 책임 같아요”, “DB 쪽은 Repository에서 보면 되겠네요” 같은 말이 통하기 시작하면 회의가 짧아지고 오해도 줄어듭니다. 세 번째는 시간이 지날수록 진가가 드러난다는 점입니다. 신규 프로젝트는 사실 어떤 기술로도 그럴듯하게 만들 수 있습니다. 문제는 2년 뒤, 3년 뒤입니다. 요구사항이 쌓이고, 예외 처리가 늘고, 담당자가 바뀌기 시작하면 구조의 체력이 드러납니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;제가 봤던 프로젝트 중에는 처음엔 정말 세련돼 보였지만, 시간이 지나자 작성자만 이해하는 코드가 되어버린 경우도 있었습니다. 반대로 아주 화려하지는 않아도 구조가 일정해서 오래 읽히는 프로젝트도 있었습니다. 그 경험 이후로는 저도 코드의 첫인상보다 “이거 3년 뒤에도 읽힐까?”를 더 자주 보게 됐습니다. 어쩌면 실무에서 중요한 건 가장 멋진 기술이 아니라 가장 덜 놀라게 하는 기술일지도 모르겠습니다. 스프링은 꽤 자주 그 역할을 해줬습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;단점은 처음 배울 때 지치기 쉽다는 것&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image3.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기까지 보면 스프링이 거의 정답처럼 느껴질 수도 있습니다. 하지만 당연히 단점도 있습니다. 그리고 그 단점은 특히 주니어에게 꽤 크게 다가옵니다. 가장 먼저 느끼는 건 무게감입니다. 작은 기능 하나에도 구조가 커지고, 어노테이션(Annotation)도 많고, 설정도 많습니다. 화면에서 바로 결과가 보이는 프론트엔드와 달리 처음에는 손이 많이 가는데 성과는 천천히 보입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;코드가 장황해지기 쉽다는 점도 있습니다. 정석만 의식하다 보면 간단한 기능까지 과하게 분리하게 되고, 오히려 읽기 어려워지는 경우도 있습니다. 구조가 있다고 해서 자동으로 좋은 코드가 되는 건 아닙니다. 또 많이 겪는 문제가 Service 비대화입니다. 처음에는 Controller를 가볍게 만들겠다고 시작했는데, 나중에는 모든 조건문과 예외 처리, 외부 API 호출이 Service 하나에 몰립니다. 결국 복잡함이 사라진 게 아니라 자리를 옮긴 것뿐인데도 초반에는 이걸 잘 못 느끼기도 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저 역시 처음에는 Controller, Service, Repository를 그냥 외웠습니다. 그런데 어느 순간 제 코드에서 “왜 이 로직이 여기에 있지?”라는 질문에 스스로 답을 못 하겠더라고요. 그때부터 생각이 조금씩 바뀌었습니다. 스프링은 외울 구조가 아니라, 왜 나누는지를 이해해야 하는 구조였습니다. 그걸 깨닫고 나서야 조금 덜 답답해졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;주니어 개발자라면 이 다섯 가지만 꼭 기억하기&lt;/strong&gt;&lt;/h3&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3744/image2.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;스프링 부트를 공부하거나 실무에서 막 쓰기 시작한 분들에게는 거창한 원칙보다 바로 적용할 수 있는 감각이 더 중요합니다. 제가 실제로 부딪히며 느낀 기준을 다섯 가지로 정리해 보겠습니다.&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;첫째, 처음부터 완벽한 구조를 만들려고 하지 않아도 됩니다. 작은 프로젝트에서는 단순함이 더 중요하고, 나중에 분리할 수 있게만 작성해 두면 충분합니다.&lt;/li&gt;&lt;li&gt;둘째, Controller는 최대한 얇게 두는 편이 좋습니다. 요청받고 응답을 내보내는 역할에 집중시키면 흐름이 훨씬 깔끔해집니다.&lt;/li&gt;&lt;li&gt;셋째, Service에 모든 걸 몰아넣지 마세요. 정말 흔한 실수이고, 로직이 커지기 시작하면 기능별로 쪼개고 책임을 다시 나누는 습관이 필요합니다.&lt;/li&gt;&lt;li&gt;넷째, Repository는 DB 접근에 집중시키는 게 좋습니다. 비즈니스 판단까지 Repository에 들어가기 시작하면 나중에 로직 추적이 힘들어집니다.&lt;/li&gt;&lt;li&gt;다섯째, 디버깅할 때는 요청 흐름을 손으로 적어보세요. 요청이 어디로 들어와서 어디를 거쳐 저장되는지 그려보면, 머릿속에서는 복잡하던 것도 생각보다 단순하게 보입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 다섯 가지는 대단한 비법은 아닙니다. 하지만 실무에서는 이런 기본기가 오래 갑니다. 특히 스프링 같은 구조형 프레임워크는 많이 안다고 잘 쓰는 게 아니라, 책임을 헷갈리지 않게 둘 줄 알아야 잘 쓴다고 느꼈습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;그래서 지금도 배워야 할까요?&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;제 대답은 분명합니다. 여전히 배울 가치가 충분합니다. 그 이유는 단순히 아직도 많이 쓰이기 때문만은 아닙니다. 더 중요한 이유는 스프링을 배우는 과정에서 백엔드의 기본 감각을 함께 익히게 되기 때문입니다. 요청 처리와 비즈니스 로직, 데이터 접근을 어떻게 나눌지 고민하는 과정은 특정 프레임워크를 넘어 계속 남습니다. 나중에 다른 언어를 쓰더라도, 다른 구조를 만나더라도 이 감각은 분명히 도움이 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;처음에는 누구나 “어떻게 빨리 만들지?”를 먼저 생각합니다. 그런데 어느 순간부터는 “이걸 어디에 둬야 나중에 안 힘들지?”, “바뀌면 어디를 수정해야 하지?”를 생각하게 됩니다. 그 질문이 생기기 시작하면 개발자는 조금 달라집니다. 바로 그때부터 단순히 코드를 짜는 사람에서 구조를 고민하는 사람으로 넘어가기 시작합니다. 그래서 저는 스프링 부트를 평생 이것만 써야 하는 기술이라기보다, 백엔드 사고방식을 익히게 해주는 좋은 훈련장에 가깝다고 느꼈습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;br&gt;&lt;strong&gt;중요한 건 최신 기술이냐가 아니라, 왜 선택되는가입니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;스프링 부트는 가장 새롭고, 가장 가볍고, 가장 화려한 기술은 아닐 수 있습니다. 하지만 한국과 일본의 실무 현장에서는 여전히 꽤 현실적인 선택지로 남아 있습니다. 그 이유는 생각보다 단순합니다. 협업하기 좋고, 설명하기 쉽고, 유지보수에 유리하기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;우리는 기술을 볼 때 자주 “최신인가, 오래됐는가”를 먼저 묻습니다. 하지만 실무는 조금 다른 질문을 던집니다. 이걸 오래 굴릴 수 있는가, 누가 들어와도 이해할 수 있는가, 문제가 생겼을 때 빨리 찾을 수 있는가. 그리고 바로 그 질문 앞에서 스프링 부트는 아직 꽤 강합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 지금 스프링을 공부하고 계신다면, 단순히 문법이나 어노테이션을 외우는 데서 멈추지 않으셨으면 합니다. 왜 Controller와 Service를 나누는지, 왜 이 로직을 이 위치에 두는지, 왜 이런 구조가 팀에 유리한지까지 생각해 보면 좋겠습니다. 그 질문에 대한 답을 스스로 설명할 수 있게 되는 순간, 스프링은 외워야 할 기술이 아니라 이해할 수 있는 구조가 됩니다. 그리고 그때부터는 단순히 코드를 쓰는 개발자가 아니라, 기술이 왜 선택되는지를 말할 수 있는 개발자로 한 단계 올라갈 수 있죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;스프링 부트가 아직도 쓰이는 이유는 결국 하나입니다. &lt;strong&gt;낡아서 남은 것이 아니라, 버틸 수 있어서 남았습니다.&lt;/strong&gt;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>AI가 코드 짜는 시대, 버전 관리도 바뀐다 (feat. Entire AI)</title><link>https://yozm.wishket.com/magazine/detail/3741</link><description>요즘 개발에서 진짜 중요한 변화는 “AI가 코드를 얼마나 잘 짜주느냐”는 데에만 있지 않다고 생각합니다. 이제 더 중요한 건, “AI가 만든 결과물을 얼마나 설명할 수 있도록 남기느냐”입니다. 다시 말해, 버전 관리의 대상 자체가 바뀌고 있는 셈이죠. 이번 글에서는 그 변화의 흐름을 제대로 보여주는 서비스 사례인 ‘Entire AI’와 함께, 왜 지금 개발자들에게는 ‘코드’보다 ‘맥락’을 관리하는 능력이 더 중요해지고 있는지 이야기해보려 합니다.</description><guid>https://yozm.wishket.com/magazine/detail/3741</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3741/image1.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Gemini로 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예전에는 누가 작성한 코드인지를 알면, 왜 그렇게 짰는지도 대충 감을 잡을 수 있었습니다. 혹시 확실하지 않다 해도 직접 타이핑한 사람이 있었기에 그 사람에게 맥락을 물어볼 수라도 있었습니다. 그런데 지금은 다릅니다. AI가 순식간에 만들어낸 결과물 앞에서 우리는 점점 더 자주, “이거 대체 왜 이렇게 된 거지?”라는 질문을 하게 되었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Copilot, Cursor, Claude Code 같은 도구 덕분에 초안은 정말 빠르게 만들어집니다. 예전 같으면 반나절은 붙잡고 있어야 했을 작업이 몇 분 만에 끝나기도 하죠. 생산성만 놓고 보면 분명 놀라운 변화입니다. 그런데 이상하게도 실무는 마냥 편해지지 않았습니다. 코드는 빠르게 늘어나지만, 그 코드가 어떤 판단과 시도를 거쳐 여기까지 왔는지는 오히려 더 흐려졌기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;문제는 바로 그 지점에서 시작됩니다. 실무에서는 코드를 빠르게 만드는 것보다, 그 코드를 팀이 이해하고 리뷰하며 유지보수할 수 있게 만드는 일이 훨씬 더 중요하거든요. 특히 AI가 개입한 작업은 결과물만으로는 설명이 되지 않는 경우가 많습니다. 어떤 프롬프트에서 시작했는지, 중간에 어떤 선택지를 버렸는지, 어디까지가 에이전트의 판단이고 어디서부터 사람이 개입했는지 알 수 없다면, 나중에 장애가 나거나 인수인계가 필요할 때 곧바로 골치 아픈 상황이 벌어집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저는 그래서 요즘 개발에서 진짜 중요한 변화는 “AI가 코드를 얼마나 잘 짜주느냐”는 데에만 있지 않다고 생각합니다. 이제 더 중요한 건, “AI가 만든 결과물을 얼마나 설명할 수 있도록 남기느냐”입니다. 다시 말해, 버전 관리의 대상 자체가 바뀌고 있는 셈이죠. 이번 글에서는 그 변화의 흐름을 제대로 보여주는 서비스 사례인 ‘Entire AI’와 함께, 왜 지금 개발자들에게는 ‘코드’보다 ‘맥락’을 관리하는 능력이 더 중요해지고 있는지 이야기해보려 합니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;AI가 코드를 대신 짜주는데, 왜 개발은 더 쉬워지지 않을까&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI 코딩 도구를 쓰면 확실히 체감되는 변화가 있습니다. 예전 같으면 한참 붙잡고 있어야 했던 작업이 훨씬 빨라졌다는 점이죠. 초안 생성, 테스트 코드 작성, 반복 로직 정리, 간단한 리팩토링까지. 이제 사람이 처음부터 끝까지 손으로 짜기보다, 방향을 잡아주고 결과를 검토하는 느낌에 더 가까워졌습니다. 생산성만 놓고 보면 분명 놀라운 변화입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그런데 이상하게도 실무에서의 개발은 기대만큼 쉬워지지 않았습니다. 오히려 어떤 부분은 더 어려워졌다고 느끼는 분들도 많을 겁니다. 특히 리뷰, 복기, 인수인계 같은 순간에서요. 코드는 빠르게 나왔지만, 정작 그 코드가 어떤 판단과 시도를 거쳐 여기까지 왔는지는 설명하기 어려운 경우가 많아졌기 때문입니다. 이런 코드는 얼핏 보면 잘 돌아가고, 겉으로 보기에도 그럴듯합니다. 그런데 며칠 뒤 다시 보면 낯설게 느껴집니다. “이거 왜 이렇게 했지?”라는 질문이 따라 생깁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;AI가 개입한 작업이 기존 작업 방식과 다르기 때문입니다. 프롬프트 몇 개로 방향이 바뀌고, 그 사이에는 여러 시도가 오가다, 그중 일부만 결과물로 남습니다. 결국 Git에는 마지막 코드만 남는데, 정작 중요한 ‘왜 그랬는지’란 정보는 사라지는 경우가 많습니다. 어떤 선택지를 검토했는지, 왜 그 방식이 채택됐는지, 사람은 어디서 개입했고 어디까지가 에이전트의 판단이었는지 같은 맥락 말이죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;문제는 실무에서 정말 중요한 게 바로 그 맥락이라는 점입니다. 개발은 단순히 코드를 생성하는 일로 끝나지 않습니다. 팀원이 코드를 리뷰해야 하고, 나중에는 다른 사람이 이어받아야 하며, 장애가 나면 다시 거슬러 올라가 원인을 파악해야 하죠. 그대신 이때 과정이 빠진 결과물만 덩그러니 남아 있다면, 코드를 읽는 일이 아니라 의도를 추리하는 일이 되어버립니다. 생산성은 올라갔지만, 팀 전체의 이해 비용은 오히려 커지는 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;바로 이 지점에서 새로운 문제의식이 등장합니다. AI가 만든 결과물 자체보다, 그 결과물이 만들어진 흐름과 맥락을 함께 남겨야 한다는 문제의식이죠. 결국 지금 개발이 더 쉬워지지 않는 이유는 AI가 코드를 못 짜서가 아니라, 코드 뒤에 있던 맥락이 너무 쉽게 사라지기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;이제 병목은 ‘생성’이 아니라 ‘맥락 관리’입니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;많은 개발자가 AI 코딩 도구를 이야기할 때, 여전히 “얼마나 결과를 잘 만들어주느냐”에 초점을 맞춥니다. 물론 중요한 부분입니다. 예전보다 훨씬 빠르게 초안을 만들고, 반복 작업도 크게 줄었기 때문이죠. 그런데 실무에서 진짜 시간을 잡아먹는 구간은 생성이 끝난 다음입니다. 누군가는 그 코드를 리뷰해야 하고, 또 누군가는 이어받아 수정해야 합니다. 문제가 생기면 다시 거슬러 올라가 원인을 찾아야 할 때도 있죠. 결국 팀 단위로 일이 돌아가는 순간부터 중요한 것은 코드 그 자체보다, 그 코드가 어떤 맥락에서 나왔는가입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 병목이 생깁니다. AI는 코드를 빠르게 만들어내지만, 그 과정은 휘발됩니다. 프롬프트를 어떻게 줬는지, 어떤 방향으로 몇 번 수정했는지, 중간에 어떤 선택지를 검토했다가 버렸는지, 어디서부터 사람의 판단이 들어갔는지 같은 정보는 대부분 사라지기 쉽습니다. 결과물만 남고 과정은 사라지는 구조인 셈이죠. 그러다 보니 PR을 열어도 난감한 때가 있습니다. 변경량은 많은데 왜 이런 설계를 택했는지 설명이 없고, 리뷰어는 코드만 붙잡고 의도를 역추적해야 합니다. 생성 속도는 빨라졌지만, 리뷰 속도는 오히려 더 느려지는 이유가 바로 여기에 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예전에 코드 리뷰는 비교적 단순했습니다. 사람이 직접 짠 코드라면, 최소한 작성자가 어떤 생각으로 접근했는지 대화로 빠르게 되돌릴 수 있었기 때문이죠. 하지만 AI가 깊게 개입한 작업은 다릅니다. 작성자조차 며칠만 지나면 흐름을 모두 기억하지 못하는 경우가 많습니다. “대충 이렇게 하라고 시켰어요” 정도만 남는 경우도 흔하죠. 이런 상태에서는 리뷰가 검토가 아니라 추리에 가까워집니다. 코드 스타일을 보는 것이 아니라 이 변경이 어디서부터 잘못됐는지를 탐정처럼 따라가야 하는 상황이 오는 것이죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;인수인계도 마찬가지입니다. 원래 인수인계가 어려운 이유는 코드가 복잡해서만은 아닙니다. 그 코드 뒤에 있는 판단과 맥락이 충분히 문서화되지 않아서 그렇습니다. AI가 작업 속도를 더 끌어올릴수록 이 문제는 더 커집니다. 팀원 입장에서는 결과물의 양은 갑자기 늘어난 반면, 그 결과물을 이해할 단서는 오히려 줄어들었기 때문입니다. 결국 실무에서는 “생성”보다 “맥락 관리”가 훨씬 더 비용이 큰 일이 되어버립니다. 잘 만든 코드보다, 왜 그렇게 만들었는지를 설명할 수 있는 코드가 더 중요해지는 거죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 저는 지금 개발팀의 핵심 역량이 조금씩 바뀌고 있다고 생각합니다. 예전에는 빠르게 구현하는 사람이 눈에 띄었다면, 이제는 AI가 만든 결과물을 팀이 이해할 수 있는 형태로 정리하고 남기는 사람이 더 중요해지고 있습니다. 맥락을 남기지 못하면 생산성 향상은 개인의 순간적인 속도로 끝나버립니다. 반대로 맥락을 잘 남기면 그 결과물은 팀의 자산이 됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;Entire AI는 이 문제를 어떻게 제품으로 풀고 있나&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;새로운 AI 서비스, Entire가 전면에 내세우는 문제의식도 정확히 이 지점에 있습니다. 이제 개발의 병목은 생성이 아니라, 생성 이후의 맥락을 어떻게 다루느냐에 달려 있다는 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Entire는 깃허브의 전 CEO 토마스 돔케(Thomas Domke)가 만든 회사입니다. 2026년 2월 10일 공식 출범 글에서 토마스 돔케는 Entire를 “에이전트 시대의 다음 개발 플랫폼”으로 소개하며, 같은 날 첫 제품으로 Entire CLI를 오픈소스로 공개했습니다. 흥미로운 건 “우리가 더 똑똑한 AI를 만들겠다”가 아니라, 이미 여러 에이전트가 코드를 쏟아내는 현실에서 그 결과물을 어떻게 관리할지 손을 댔다는 점입니다. 그들의 방향은 명확합니다. AI가 만들어낸 코드와 그 맥락을 Git 흐름 안에 붙여놓겠다는 것이었죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;핵심 개념은 &lt;strong&gt;Checkpoints&lt;/strong&gt;입니다. 이 기능은 AI 코딩 세션을 Git 커밋과 연결해 남기는 방식으로 동작합니다. 공식 문서 기준으로 사용자나 에이전트가 &lt;code&gt;git commit&lt;/code&gt;을 실행하면 세션 데이터가 커밋에 붙고, 커밋 메시지에는 &lt;code&gt;Entire-Checkpoint&lt;/code&gt; 트레일러가 추가됩니다. 이어 세션 로그와 메타데이터는 &lt;code&gt;entire/checkpoints/v1&lt;/code&gt; 브랜치에 저장됩니다. 쉽게 말하면 코드 변경만 남기는 게 아니라, 그 변경이 만들어진 대화와 흐름까지 버전 관리의 일부로 삼겠다는 접근입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 구조가 꽤 영리한 이유는 Git 히스토리를 지저분하게 만들지 않기 때문입니다. Entire는 작업 중에는 로컬의 shadow branch에 임시 상태를 잡아두고, 실제로는 사용자가 원래 하던 커밋만 히스토리에 남깁니다. 즉 “도구를 쓰기 위해 새로운 방식으로 일하라”가 아니라, 늘 해오던 Git 워크플로우에 자연스럽게 끼어드는 방식인 셈이죠. 공식 문서에서도 “추가 커밋 없이”, “기존 브랜치에서 안전하게”, “리와인드와 재개를 지원하는” 구조 등을 장점으로 설명합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또 하나 눈에 띄는 건 특정 에이전트 하나에 올인하지 않았다는 점입니다. 현재 공식 문서와 사이트 기준으로 Entire CLI는 Claude Code, Gemini CLI, Cursor, OpenCode, GitHub Copilot CLI를 지원하고, Codex는 프리뷰 상태로 제공됩니다. 자동 캡처가 실패한 세션은 &lt;code&gt;entire attach&lt;/code&gt;로 나중에 연결할 수 있게 해뒀고, 4월에는 직접 원하는 에이전트를 붙일 수 있는 플러그인 방식까지 공개했습니다. 처음부터 “최고의 코딩 에이전트” 경쟁에 들어가기보다 여러 에이전트가 섞여 쓰이는 실제 개발 환경을 전제로 설계한 느낌이 강합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;확장 속도도 꽤 빠릅니다. 3월에는 GitHub Copilot CLI 지원이 추가됐고, 3월 말에는 Codex 프리뷰, Windows 호환성, 플러그인 시스템이 소개됐습니다. 4월에는 Codex 사용 가이드와 외부 에이전트 연결 방식까지 연달아 나왔습니다. 그러니까 Entire는 아직 초기 제품이긴 하지만, 적어도 비전만 존재하는 회사는 아닙니다. 실제로 지금 당장이라도 설치하면 기존 Git 기반 프로젝트에 붙여볼 수 있는 형태로 계속 다듬어지고 있으니까요.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저는 그래서 Entire를 단순한 AI 코딩 도구라기보다, AI 시대에 맞는 새로운 기록 계층을 만들려는 시도로 봅니다. 코드 생성은 이미 충분히 빨라졌습니다. 이제 필요한 건 그 결과물을 팀이 이해하고, 검토하고, 되짚을 수 있게 만드는 장치인데요. Entire가 바로 그 지점을 제품으로 풀어내려는 꽤 본격적인 첫 시도로 보입니다. 아직 정답이라고 단정하긴 이르지만, 최소한 문제를 바라보는 방향만큼은 상당히 정확하다는 생각이 듭니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실제 개발자들은 이 방향을 어떻게 보고 있을까&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;Entire AI가 던진 문제의식은 분명 흥미롭습니다. 그런데 좋은 문제를 짚어 제품을 만드는 일과 시장이 그 제품을 곧바로 받아들이는 건 또 다른 이야기입니다. 실제로 출시 후 몇 달 사이 반응을 보면 평가가 갈립니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;한쪽에서는 “지금 AI 코딩에서 진짜 빠져 있는 조각을 잘 짚었다”는 평가가 나오는 반면 다른 한쪽에서는 “문제는 인정하지만, 이 방식이 얼마나 강력한 해답인지는 아직 모르겠다”는 반응도 있습니다. 저는 이 양면성이 오히려 Entire를 더 흥미롭게 만든다고 봅니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;먼저 호의적으로 보는 쪽에서는 Entire가 겨냥한 문제가 정말 현실적이라는 점에 공감합니다. AI가 만들어낸 코드는 점점 늘어나는데, 그 코드가 어떤 프롬프트와 시도, 툴 호출을 거쳐 나왔는지는 쉽게 사라지기 때문입니다. 이런 상황에서 Checkpoints처럼 세션의 흔적을 Git과 함께 남기겠다는 발상은 단순히 “예쁘다”를 넘어 “실무에 필요하다”는 반응을 끌어냅니다. 공식 사이트와 GitHub 저장소 기준으로도, CLI 프로젝트는 빠르게 주목받아온 느낌입니다. 적어도 문제의식 자체에는 많은 개발자가 동의하고 있다는 뜻입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;특히 요즘처럼 여러 에이전트를 섞어 쓰는 환경이 발전하며, 이런 반응이 더 커지고 있습니다. Claude Code로 초안을 만들고, Cursor에서 다듬고, Codex나 Copilot CLI로 보조 작업을 붙이는 흐름이 점점 흔해지고 있기 때문입니다. 그럴수록 팀 입장에서 진짜 필요한 건 “최종 코드가 무엇인가”보다는 “그 코드가 어떤 맥락에서 나왔는가”가 더 중요해질 겁니다. Entire가 출시 직후부터 Codex 지원, 플러그인 시스템, 다양한 CLI 연동을 빠르게 확장한 것도 이런 환경이 실제로 퍼진다는 전제를 반영한 움직임으로 볼 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반대로 회의적인 반응도 만만치 않습니다. 해외 커뮤니티 반응을 보면 가장 많이 나오는 질문은 두 가지 정도입니다. “이게 정말 새로운 해자인가?”, 그리고 “이 문제를 굳이 Entire 같은 별도 레이어로 풀어야 하나?”입니다. 즉, 세션 데이터와 메타데이터를 남기는 아이디어 자체는 이해하지만, 그것이 장기적으로 독립 플랫폼이 될 만큼 큰 가치인지에 대해서는 의문이 간다는 겁니다. 오히려 협업 도구라기보다 나중에 학습용 데이터로 더 가치 있다는 말도 나옵니다. 결국 이들이 짚어낸 문제가 좋은 것과 별개로 그 문제를 가장 잘 푸는 방식인지 아직 모르겠다는 겁니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 회의론도 충분히 이해가 갑니다. 개발자들은 원래 새로운 도구에 쉽게 감동하지 않습니다. 특히 Git, PR, 코드 리뷰처럼 이미 굳어진 습관 위에 무언가를 얹는 제품이라면 더 그렇습니다. ‘좋아 보이는데, 그래서 우리 팀이 진짜 이걸 깔고 쓸까?’라는 질문을 반드시 넘어서야 합니다. 실제로 개인 개발자 차원에서는 흥미로운 실험처럼 보일 수 있어도, 팀 단위 도입으로 넘어가려면 보안, 저장 방식, 운영 부담, 워크플로우 충돌, 실제 리뷰 생산성 개선 같은 훨씬 현실적인 검증이 필요하기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;지금 Entire가 받고 있는 시선은 이쯤 와 있다고 볼 수 있습니다. 물론 저는 이런 반응을 단순히 부정적이라고 보지는 않습니다. 오히려 시장이 “이 문제는 진짜다. 다만 해법은 더 지켜보자”라고 말하고 있는 것에 가깝다고 보입니다. 정말 별로인 제품은 논쟁조차 생기지 않으니까요. 적어도 Entire에 회의적인 쪽도 문제 자체는 인정합니다. 논쟁의 중심이 “문제가 있느냐 없느냐”가 아니라 “이 방식이 그 문제를 풀 수 있느냐”에 있다는 점은 꽤 중요한 신호입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그 때문이라도 이 문제, 그리고 Entire AI를 계속 지켜볼 이유는 있다고 생각합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;앞으로 바뀌는 건 코딩이 아니라 개발팀의 운영 방식일지 모릅니다&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;AI 시대의 개발 변화를 이야기할 때, 대부분 가장 먼저 생산성을 떠올립니다. 얼마나 빨라졌는지, 몇 명이 하던 일을 몇 분 만에 끝내는지, 개발자 수요가 앞으로 얼마나 줄어들지 같은 이야기들이죠. 그런데 저는 진짜 변화가 그런데만 있지는 않다고 생각합니다. 오히려 더 크게 바뀌는 건 개발팀이 일하는 방식, 조금 더 정확히 말하면 결과물에 대한 책임을 나누고 신뢰를 쌓는 방식일 가능성이 큽니다. Entire가 처음부터 Git과 연결된 Checkpoints, 팀 가시성, 검색과 복기 같은 주제를 전면에 둔 것도 같은 맥락으로 읽힙니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;예전에는 코드 작성자와 의사결정자가 거의 같은 사람이었습니다. 누가 만들었는지 알면 왜 그렇게 만들었는지도 대략 따라갈 수 있었죠. 리뷰어도 작성자와 대화하면 빠르게 맥락을 복원할 수 있었고, 인수인계도 “이 부분은 왜 이렇게 구현했는지”를 사람의 기억에 기대어 넘어가는 경우가 많았습니다. 그런데 AI가 깊게 개입하는 순간 이 구조는 달라져야 합니다. 프롬프트를 던진 사람, 중간 결과를 선택한 사람, 최종 머지를 승인한 사람, 이후 운영을 맡는 사람이 서로 달라질 수 있기 때문입니다. 이때부터는 단순히 코드만 남겨서는 책임과 판단을 제대로 설명하기 어려워집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그래서 다시 한 번, 앞으로 중요한 건 “누가 빨리 짰느냐”보다 “누가 설명할 수 있게 남겼느냐”가 될 가능성이 큽니다. AI가 만든 초안을 가져다 쓰는 일 자체는 누구나 할 수 있게 될 것입니다. 하지만 그 결과물을 팀이 이해할 수 있는 형태로 정리하고, 나중에 문제가 생겼을 때 다시 추적할 수 있게 만들고, 리뷰어가 불필요한 추리를 하지 않도록 맥락을 남기는 일은 여전히 사람의 몫입니다. Entire가 제품 차원에서 붙들고 있는 문제도 결국 여기에 있습니다. 코드 생성 경쟁보다, 생성 이후의 기록과 검증, 복기와 감사 가능성에 더 큰 가치를 두고 있는 것이죠.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 변화는 특히 팀 운영에서 더 크게 다가올 겁니다. 코드 리뷰 방식이 바뀔 수 있고, 온보딩 방식도 달라질 수 있습니다. 예전에는 신입이나 새 팀원이 코드베이스를 읽고 질문하면서 맥락을 익혔다면, 앞으로는 “이 변경이 어떤 세션에서 어떤 판단 끝에 나왔는지”까지 함께 훑는 흐름이 자연스러워질 수 있습니다. 장애 대응도 비슷합니다. 예전에는 커밋 로그와 담당자의 기억을 조합해 원인을 복기했다면, 앞으로는 AI 세션 기록과 결정 흐름까지 함께 보는 방식이 더 익숙해질 수 있죠. 특히 규제 산업과 보안이 중요한 환경에서의 투명성, 팀 단위 검색과 가시성 같은 주제를 반복해서 Entire가 강조하는 이유도 이런 맥락으로 이해할 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;저는 Entire가 정말 이러한 문제의 해답이 될지는 아직 모른다고 생각합니다. 실제 팀 도입과 장기적인 경쟁력은 더 지켜봐야 하니까요. 다만 한 가지는 분명해 보입니다. AI가 코드를 쓰는 시대에 버전 관리의 대상은 더 이상 코드만이 아니라는 점입니다. 그리고 그 변화는 생각보다 훨씬 빠르게, 개발자의 손끝이 아니라 개발팀의 운영 방식부터 바꿔놓게 될지도 모릅니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;그 아래 살아남는 개발자의 기준도 조금씩 바뀔 것 같습니다. 단순히 AI를 잘 쓰는 사람보다, AI와 함께 만든 결과물을 팀의 자산으로 바꿀 수 있는 사람이 더 중요해질 가능성이 큽니다. 설명할 수 있게 만들고, 협업할 수 있게 만들고, 나중에 다시 꺼내 쓸 수 있게 만드는 능력 말입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>소버린 AI와 자체 생태계를 가진 IT 강대국, 러시아를 가다</title><link>https://yozm.wishket.com/magazine/detail/3725</link><description>모스크바의 4월은 계절의 경계가 무색할 만큼 가혹합니다. 저는 작년 이맘때쯤 모든 것이 막혀 있는 이곳 러시아에 주재원으로 처음 넘어왔습니다. 러시아에서는 인터넷이 잘 안되거나, 메신저가 막히는 경우가 참 많습니다. 그뿐만 아니라 우리가 당연하게 여기는 구글의 검색창, 유튜브의 알고리즘, 인스타그램의 피드는 이곳에서 접근할 수 없습니다. 하지만 그 빈자리에 들어선 것은 기술의 퇴보가 아닙니다. 오히려 외부의 간섭 없이 스스로 진화하기 시작한 기묘하고도 강력한 자생적 생태계가 자라나고 있었습니다. 그런 나라에서 개발자로 하루하루를 살아가며 경험한 다양한 것들을 공유하고자 펜을 들었습니다.</description><guid>https://yozm.wishket.com/magazine/detail/3725</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;모스크바의 4월은 계절의 경계가 무색할 만큼 가혹합니다. 저는 작년 이맘때쯤 모든 것이 막혀 있는 이곳 러시아에 주재원으로 처음 넘어왔습니다. 올해의 4월 역시, 눈이 오기도 비가 오기도 하며 많은 사람이 아직 두꺼운 패딩을 입고 다닙니다. 그런 나라에서 개발자로 하루하루를 살아가며 경험한 다양한 것들을 공유하고자 펜을 들었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image7.jpg"&gt;&lt;figcaption&gt;모스크바의 4월 &amp;lt;출처: 작가 촬영&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;러시아에서는 인터넷이 잘 안되거나, 메신저가 막히는 경우가 참 많습니다. 그뿐만 아니라 우리가 당연하게 여기는 구글의 검색창, 유튜브의 알고리즘, 인스타그램의 피드는 이곳에서 접근할 수 없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;하지만 그 빈자리에 들어선 것은 기술의 퇴보가 아닙니다. 오히려 외부의 간섭 없이 스스로 진화하기 시작한 기묘하고도 강력한 자생적 생태계가 자라나고 있었습니다. 러시아 정부의 강력한 지원과 열정이 넘치는 개발자들의 손에서 다양한 IT시스템과 AI 서비스들이 만들어졌습니다. 국제 표준을 따르지는 않지만, 독립국가연합(CIS) 시장을 기반으로 자체 IT 생태계를 추구하며, 결제나 피지컬 AI 부문에서도 강력한 서비스를 가지고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;무엇보다 AI 서비스 분야에서는 얀덱스GPT(YandexGPT), 기가챗(Gigachat) 등 서비스가 활발하게 쓰이고 있으며, 다양한 AI 결합 서비스들도 마찬가지로 나오고 있습니다. 이 모든 변화는 글로벌 외산 AI 시스템 없이 독자적인 개발로 이루어져, 앞으로 이어질 AI 패권 전쟁에서도 러시아는 강력한 경쟁력을 가질 수 있을 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;우리나라 또한 글로벌 서비스 대비 뛰어난 서비스를 가진 영역도 많지만, 열약한 부분도 분명히 있습니다. 러시아의 사례를 발판으로 삼아 한국 또한 독자 개발을 통해 더 강력한 경쟁력을 가질 수 있는 방향으로 갈 수 있으면 좋겠다는 생각이 커졌습니다. 오늘은 그런 이야기를 전해보려고 합니다.&lt;/p&gt;&lt;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;1. 구글 없는 모스크바의 아침과 러시아의 IT 생태계&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;러시아가 실리콘밸리 표준을 버리고 독자 노선을 걷게 된 배경에는 생존을 향한 처절한 의지가 자리하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image9.png"&gt;&lt;figcaption&gt;러시아의 주요 BigTech 기업 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;러시아가 글로벌 표준 대신 독자 노선을 택한 이유&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;시작은 서방의 경제 제재였습니다. 그로 인해 글로벌 빅테크 기업들이 하루아침에 서비스를 중단했을 때, 러시아 사회가 직면한 것은 단순한 불편함이 아닌 국가 시스템 전체가 마비될 가능성이었습니다. 러시아는 이 거대한 위기를 기회로 보고 국가 IT 기업에 투자했습니다. 외부 기술에 종속되는 것이 곧 데이터 주권과 국가 안보를 타인에게 양도하는 것임을 뼈저리게 실감한 이들은 자국만의 기술 요새를 쌓기 시작했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이제 모스크바에서 ‘글로벌 표준’은 더 이상 선망의 대상이 아닌 언제든 무기로 돌변할 수 있는 과거의 유물로 취급됩니다. 그 자리를 대신한 것은 러시아산 코드로 촘촘하게 짜인 내수용 소프트웨어들이며, 이들은 빠르게 현지인들의 삶 속에서 떼어낼 수 없는 유기적 결합체가 되었습니다. 얀덱스(Yandex), 카스퍼스키(Kaspersky) 등 이미 글로벌 수준의 앱이 모든 서비스를 제공하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;챗GPT 접근 금지가 불러온 ‘로컬 AI’의 반격&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image10.png"&gt;&lt;figcaption&gt;러시아의 AI &amp;lt;출처: 작가, gemini로 제작&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;오픈AI의 챗GPT를 필두로 한 글로벌 생성형 AI 모델들이 러시아 IP를 차단하자, 러시아인들은 당황하는 대신 자신들의 언어와 문화적 맥락에 최적화된 로컬 AI로 시선을 돌렸습니다. 애초에 영어 중심 사고방식과 서구권의 윤리적 가이드라인이 투영된 글로벌 모델들은 러시아어의 복잡한 굴절과 슬라브 민족 특유의 정서를 담아내는 데 한계가 있었습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;반면, 러시아의 얀덱스, 스베르(Sber)가 개발한 모델들은 도스토옙스키와 톨스토이의 문장을 학습하고, 러시아인들만이 이해할 수 있는 역사적 상징과 은유를 이해합니다. 이는 기술적 소외를 극복하는 차원을 넘어 오히려 자국 문화에 가장 적합한 ‘맞춤형 지능’을 소유하게 되는 역설적인 기회를 제공했습니다. 접근 금지라는 장벽이 오히려 러시아만의 독창적인 AI 학습 데이터셋을 구축하는 강력한 동력이 된 셈입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이제 이런 모델은 전 세계가 획일화된 AI 표준을 따라갈 때 러시아만이 가질 수 있는 독보적인 문화적 경쟁력이 되었습니다. 그 어떤 AI보다도 러시아어에 최적화되었으며, 구글 검색이 어려운 러시아 내부 사이트까지 모두 학습의 대상으로 삼아 전체 내용을 아우르는 AI 서비스가 러시아 자국민들에게 제공되고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;우리가 모르는 러시아인들의 필수 앱 리스트&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image4.png"&gt;&lt;figcaption&gt;러시아 필수 앱 목록 &amp;lt;출처: RuStore&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이러한 변화는 스마트폰 홈 화면에서 가장 명확하게 드러납니다. 우리에게 익숙한 앱들은 없지만, 그들이 제공하는 기능은 로컬 슈퍼 앱들이 대신하고 있습니다. 물론 러시아에서도 구글이나 애플의 앱스토어를 이용할 수는 있습니다. 그러나 대부분은 루스토어(RuStore)라는 자국 앱스토어로 앱들을 관리합니다. 또, 러시아에서 필수로 통하는 앱들은 모두 전화번호 하나로 가입하고 관리할 수 있어, 사용 편의성에 있어서는 한국 앱들보다 더 뛰어난 측면도 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;러시아의 국민 메신저를 넘어 사회적 소통의 중심이 된 ‘VK’는 이제 SNS 그 이상의 기능을 수행합니다. 메일 서비스에서 시작한 플랫폼 '메일루(Mail.ru)'는 러시아 비즈니스의 혈관 역할을 수행합니다. ‘얀덱스 고(Yandex Go)’란 앱은 택시 호출, 음식 배달, 물류 배송, 심지어는 공과금 결제까지 하나의 앱 안에서 해결하는 거대한 플랫폼으로 성장했습니다. ‘텔레그램(Telegram)’ 역시 단순 메신저의 기능을 넘어 정부 행정 서비스와 금융 채널의 핵심 플랫폼으로 기능하며 러시아의 디지털 주권을 공고히 하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;모두 외부인에게는 낯설고 폐쇄적으로 보일지 모르지만, 이 내수용 앱들은 이미 현지인들의 일상을 완벽하게 지탱할 수 있을 만큼 성숙해졌습니다. 특히 이 모든 앱이 러시아 전화번호 하나로 인증할 수 있으니, 한국이나 미국에서 했던 인증 방식보다 더 편하다고 느끼고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="margin-left:3.2598425196850442pt;text-align:justify;"&gt;&lt;strong&gt;2. 일상을 점령한 러시아표 AI와 핀테크&lt;/strong&gt;&lt;/h3&gt;&lt;p style="margin-left:3.2598425196850442pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;알리사(Alisa): 얀덱스가 탄생시킨 러시아판 ‘AI 페르소나’&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image1.png"&gt;&lt;figcaption&gt;Alisa AI &amp;lt;출처: yandex image&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;러시아 AI의 정체성을 가장 상징적으로 보여주는 존재는 얀덱스의 AI 비서 ‘알리사(Alisa)’입니다. 실리콘밸리의 AI 비서들이 기계적이고 가치 중립적인 답변을 내놓는 데 주력하는 것과 달리, 알리사는 마치 살아있는 러시아인처럼 행동합니다. 때때로 고집스럽게 의견을 피력하거나, 러시아 특유의 냉소적인 유머를 섞어 대답하기도 하며 사용자에게 당혹감과 친밀감을 동시에 선사합니다. 이러한 '인격적 페르소나'는 러시아인들에게 단순한 비서 이상의 유대감을 주며 문화적 동질성을 확인시켜 줍니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;또한, 알리사는 러시아 내부에 특화된 서비스와 이어집니다. 앱들과의 연계는 자연스러우며, 서비스 속도 역시 자국 내에서 월등히 뛰어납니다. 가격 또한 챗GPT나 제미나이(Gemini)에 대비하여 저렴합니다. 물론 한글 학습량이 절대적으로 부족해 제가 한글을 입력하면 알아듣지 못하는 경우가 많지만, 러시아 자국민만을 놓고 본다면 절대적인 강점을 지닌 AI 서비스임이 틀림없습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="margin-left:-3.826771653543311pt;text-align:justify;"&gt;&lt;strong&gt;미르 페이(Mir Pay): 제재 속에서 꽃피운 독자적 결제 시스템의 생존법&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image8.png"&gt;&lt;figcaption&gt;미르 페이 &amp;lt;출처: yandex image&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;금융 영역에서의 자립은 더욱 극적입니다. 국제 결제망인 SWIFT에서 퇴출당했을 때, 러시아 경제가 순식간에 붕괴할 것이라는 서구권의 예측은 보기 좋게 빗나갔습니다. 러시아는 이미 수년 전부터 준비해 온 독자 결제 시스템 ‘미르(Mir)’를 전면에 내세웠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;요즘 모스크바의 식당이나 지하철역에서 사람들은 비자나 마스터카드 대신 스마트폰의 '미르 페이(Mir Pay)'를 태그합니다. 외부의 금융 압박이 심해질수록 이 시스템은 더욱 정교하게 진화했고, 이제는 실물 카드 없이도 전국 어디서나 경제 활동이 가능한 수준에 이르렀습니다. 곧 미르 페이는 애플 페이, 삼성 페이 등 페이 시스템의 빈자리를 훌륭하게 극복했습니다. 나아가 사용자 편의성을 추구하여 ATM에서 돈을 찾을 때나, 지하철 탑승 시에는 안면 인식을 통한 활용까지도 제공하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="margin-left:-3.826771653543311pt;text-align:justify;"&gt;&lt;strong&gt;로버: 모스크바 길거리를 누비는 자율주행 배달 로봇&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image5.png"&gt;&lt;figcaption&gt;배달하는 로버 &amp;lt;출처: yandex image&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;거리의 풍경 또한 이곳 러시아가 자율주행 기술의 최전선임을 보여줍니다. 모스크바 도심의 무릎 높이까지 차오른 눈길을 얀덱스의 배달 로봇 ‘로버’들이 묵묵히 헤쳐 나가는 모습은 보고 있으면 경이롭기까지 합니다. 영하 20도의 혹한과 빙판길이라는 가혹한 환경은 자율주행 알고리즘에게는 최악의 난제이지만, 러시아의 로봇들은 이를 극복해 냈습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;센서와 알고리즘의 결합체인 이 로봇들은 단순한 기술 과시용이 아니라, 만성적인 인력 부족과 가혹한 기후 조건을 해결하기 위한 실용적인 해답으로 자리 잡고 있습니다. 모스크바 시내에서 돌아다니는 이 조그마한 배달 로봇들은 제재와 테러 등의 위험으로 비싸진 노동력을 대신하고 있는 것입니다. 점점 학습이 나아짐에 따라 더 빠르고 정확하게 상품을 배달하고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="margin-left:-0.3070866141732438pt;text-align:justify;"&gt;&lt;strong&gt;3. 철의 장막 뒤에서 진화하는 소버린 AI의 실체&lt;/strong&gt;&lt;/h3&gt;&lt;p style="margin-left:-0.3070866141732438pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;얀덱스 vs 기가챗: 러시아 AI의 양대 산맥, 그들의 기술적 차별점&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image2.png"&gt;&lt;figcaption&gt;러시아 최대 IT 기업과 그들의 AI 서비스 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;러시아 소버린 AI의 내부를 들여다보면 얀덱스의 '얀덱스GPT'와 스베르의 '기가챗'이라는 두 거대 산맥이 존재합니다. 민간 기술력의 정점에 서 있는 얀덱스가 방대한 검색 데이터와 정교한 소비자 맞춤형 서비스에 강점을 보인다면, 국영 금융 그룹인 스베르는 국가적인 컴퓨팅 자원과 금융 인프라를 바탕으로 공공 영역의 지능화를 주도합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이들은 서로 경쟁하면서도 외산 AI의 빈자리를 훌륭히 메우며 러시아 기술 생태계를 지탱하는 양대 기둥 역할을 수행합니다. 각기 다른 배경에서 탄생한 두 모델의 기술적 차별성은 러시아 AI 생태계를 더욱 풍성하게 만들고 있으며, 국가가 주도한 기술 발전이 민간의 창의성과 결합했을 때 나타나는 시너지를 잘 보여준다고 느껴집니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;러시아가 오픈소스에 진심인 이유: 고립된 땅에서 혁신을 지속하는 법&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image6.png"&gt;&lt;figcaption&gt;러시아의 개발자들 &amp;lt;출처: 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;러시아가 기술적 고립 속에서도 혁신의 끈을 놓지 않는 비결은 바로 ‘오픈소스’에 대한 집요한 접근에 있습니다. 러시아의 개발자들은 전 세계의 오픈소스 프로젝트를 실시간으로 분석하고 흡수하여 자신들의 폐쇄된 네트워크 안에서 완전히 새로운 형태로 재조립합니다. 외부와의 공식적인 기술 협력 통로는 차단되었을지 몰라도, 공개된 코드를 해체하고 최적화하는 과정을 통해 전 세계의 지능을 자신들의 주권 아래로 끌어들이고 있는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이러한 전략은 고립된 환경이 어쩌면 외부 의존도를 낮추고 기술적 자생력을 키울 자양분이 될 수 있음을 시사합니다. 그들에게 오픈소스는 단순한 참조 도구가 아니라 생존 도구에 가깝습니다. 따라서 늘 오픈소스를 학습하고 개발하는 개발자라면 배워야 할 자세를 가지고 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;폐쇄적 개발 환경의 역설: 외부 의존도를 0%로 만드는 극한의 최적화 전략&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;더불어 하드웨어 수급의 한계는 러시아 개발자들에게 소프트웨어의 ‘극한 최적화’라는 과제를 안겨주었습니다. 최신 고성능 GPU를 마음껏 사용할 수 없는 환경은 오히려 독이 아닌 득이 되었습니다. 제한된 연산 자원 내에서 거대 언어 모델을 구동하기 위해 그들은 알고리즘의 군더더기를 깎아내고 메모리 효율을 극대화하는 사투를 벌였습니다. 그 결과 가벼우면서도 강력한 러시아만의 독자적 모델들이 탄생했습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;풍요로운 환경에서는 결코 시도하지 않았을 이 결핍의 연금술이 러시아 기술진의 실력을 상향 평준화시켰다고 보입니다. 외부 의존도를 0%로 수렴시키려는 이들의 노력은 결국 기술적 한계가 어떻게 창의적인 혁신으로 변모하는지를 보여주는 역설적인 장면을 연출합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;4. ‘AI 배제 시대’를 준비하는 우리의 자세&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;소버린 AI는 선택이 아닌 생존: 러시아 사례가 던지는 지정학적 메시지&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3725/image3.png"&gt;&lt;figcaption&gt;러시아의 지정학적 위험 &amp;lt;출처:&amp;nbsp;foreignpolicy&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;모스크바 현지에서 몸소 느낀 소버린 AI는, 단순한 기술 자립을 넘어선 국가의 명운을 건 사투 그 자체였습니다. 그러다 보니 특정 국가나 거대 빅테크 기업에 기술의 주도권을 완전히 넘겨주는 것은 앞으로 발생할 어떤 위기 상황에서도 스스로를 방어할 수 있는 수단을 포기하는 것과 같다고 느껴졌습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;러시아는 비록 강제적인 방식이었지만, 자신들의 데이터와 지능을 스스로 통제함으로써 외부의 압력에 쉽게 굴하지 않을 디지털 요새를 구축하는 데 성공했습니다. 이 사례는 우리에게 AI 주권이 더 이상 선택의 문제가 아니라 국가 안보와 직결된 생존의 필수 조건임을 경고하고 있지는 않을까요?&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;글로벌 종속과 독자 기술 사이: 한국형 소버린 AI가 나아갈 방향&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;우리나라 역시 이제 글로벌 빅테크가 제공하는 편리함이라는 달콤한 유혹과 독자 기술 개발이라는 고단한 길 사이에서 냉정한 선택을 내려야 할 시점에 서 있습니다. 이제는 국가 차원에서 네이버나 카카오 같은 로컬 기업들이 수십 년간 쌓아온 데이터 영토를 보호하고, 한글을 비롯해 한국의 가치를 온전히 반영한 '한국형 소버린 AI'를 국가적 인프라로 육성해야 할 때입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기술의 주권이 흔들릴 때 우리의 일상이 얼마나 쉽게 타인의 손에 의해 좌우될 수 있는지를 러시아란 나라는 명확히 보여줍니다. 모스크바의 매서운 눈바람을 뚫고 묵묵히 길을 찾아가는 배달 로봇처럼, 우리 역시 우리만의 기술적 해자를 구축하여 다가올 AI 패권 전쟁의 거센 파고를 당당히 넘어서야 합니다. 그것만이 디지털 대항해 시대에 대한민국이 자존감을 지키며 생존할 수 있는 유일한 길이기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;러시아 개발 생태계는 정부가 스스로 막은 것들도, 다른 국가에서 막은 것들도 많다 보니 늘 신기술에 대한 목마름이 넘쳐납니다. 그렇게 자체적으로 여러 세미나를 여는 등 기술 공부의 자리를 만들며 이를 키워 가고 있습니다. 저 또한 러시아에서 많은 것을 배우고 있습니다. 이 글을 읽고 있는 분들을 비롯해 한국 개발자에게 더 넓은 시야와 지식을 전파할 수 있을지 고민하며, 다시 새로운 것을 전달하러 찾아오겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item><item><title>유니온 타입에서 막히는 순간, 타입 좁히기가 필요하다</title><link>https://yozm.wishket.com/magazine/detail/3719</link><description>타입스크립트를 쓰다 보면 하나의 변수가 여러 타입을 가질 수 있는 상황을 자주 만나게 됩니다. 함수의 매개변수가 string일 수도, number일 수도 있고, API 응답이 성공 데이터일 수도, 에러 객체일 수도 있습니다. 이처럼 다양한 가능성을 안고 있는 변수를 다룰 때, 타입스크립트는 꽤 보수적으로 반응합니다. 해당 변수가 “어떤 타입인지 아직 모르겠으니” 특정 타입 전용 메서드를 사용하지 못하도록 막아버리는 것입니다. 이 문제를 해결하는 방법이 바로 타입 좁히기(Type Narrowing)입니다. 타입 좁히기란 조건문 등을 활용해 넓은 타입을 더 구체적인 타입으로 확정해가는 과정을 말합니다.</description><guid>https://yozm.wishket.com/magazine/detail/3719</guid><content:encoded>&lt;![CDATA[&lt;b&gt;&lt;p style="text-align:justify;"&gt;타입스크립트를 쓰다 보면 하나의 변수가 여러 타입을 가질 수 있는 상황을 자주 만나게 됩니다. 함수의 매개변수가 string일 수도, number일 수도 있고, API 응답이 성공 데이터일 수도, 에러 객체일 수도 있습니다. 이처럼 다양한 가능성을 안고 있는 변수를 다룰 때, 타입스크립트는 꽤 보수적으로 반응합니다. 해당 변수가 “어떤 타입인지 아직 모르겠으니” 특정 타입 전용 메서드를 사용하지 못하도록 막아버리는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 문제를 해결하는 방법이 바로 타입 좁히기(Type Narrowing)입니다. 타입 좁히기란 조건문 등을 활용해 넓은 타입을 더 구체적인 타입으로 확정해가는 과정을 말합니다. 복잡하게 들릴 수 있지만, 사실 우리가 자바스크립트에서 이미 자연스럽게 하고 있던 방어적 코딩 패턴을 타입스크립트가 인식하고 활용해주는 것에 가깝습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 타입 좁히기가 왜 필요한지부터 실무에서 자주 쓰이는 핵심 패턴까지 단계별로 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p style="text-align:justify;"&gt;&lt;strong&gt;미리 요점만 콕 집어보면?&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&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;div class="page-break" style="page-break-after:always;"&gt;&lt;span style="display:none;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;타입 좁히기가 필요한 이유&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;타입 좁히기가 왜 필요한지 이해하려면, 먼저 유니온 타입의 한계부터 살펴봐야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 유니온 타입만으로는 부족하다&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;유니온 타입은 여러 타입 중 하나가 될 수 있는 변수를 정의할 때 사용합니다. 예를 들어, 문자열과 숫자를 모두 받을 수 있는 함수를 만든다고 해봅시다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function printValue(value: string | number) {
  console.log(value.toUpperCase()); // ❌ 오류
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 코드는 에러가 발생합니다. value가 string일 수도, number일 수도 있기 때문에 타입스크립트는 string 전용 메서드인 toUpperCase()를 호출하지 못하게 막는 것입니다. 반대로 number 전용 메서드인 toFixed()도 마찬가지로 쓸 수 없습니다. 유니온 타입의 변수에는 모든 구성 타입이 공통으로 갖고 있는 프로퍼티와 메서드만 사용할 수 있기 때문입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;그렇다면 어떻게 해야 할까요? 이 변수가 string인지 number인지를 먼저 확인하고, 확인된 상태에서 해당 타입의 기능을 사용하면 됩니다. 바로 이것이 타입 좁히기입니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 조건문으로 타입을 좁히면?&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;아래처럼 typeof를 사용한 조건문을 추가해 봅시다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function printValue(value: string | number) {
  if (typeof value === "string") {
    console.log(value.toUpperCase()); // ✅ string 타입으로 확정
  } else {
    console.log(value.toFixed(2)); // ✅ number 타입으로 확정
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;if 블록 안에서 typeof value === "string" 조건을 통과했다면, 타입스크립트는 해당 블록 안의 value를 string 타입으로 확정합니다. else 블록에서는 string이 아닌 나머지, 즉 number 타입으로 확정됩니다. 별도의 타입 단언(as)을 쓰지 않아도, 조건문만으로 타입을 안전하게 구분할 수 있는 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3719/%EA%B7%B8%EB%A6%BC1__3_.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가, Claude AI 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이렇게 조건문 등을 활용하여 타입의 범위를 좁혀나가는 표현들을 타입 가드(Type Guard)라고 부릅니다. 타입 좁히기를 실현하는 구체적인 도구가 바로 타입 가드인 셈입니다. 이제 실무에서 자주 쓰이는 타입 가드 패턴들을 하나씩 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;타입 좁히기 기본 패턴&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;타입스크립트에서 제공하는 타입 가드는 여러 종류가 있습니다. 상황에 따라 적합한 패턴이 다르기 때문에, 각 패턴의 특성과 사용 시점을 정리해두면 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) typeof 가드&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;typeof는 가장 기본적이고 자주 사용되는 타입 가드입니다. 자바스크립트의 typeof 연산자가 반환하는 문자열을 기준으로 타입을 구분합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function formatInput(input: string | number | boolean) {
  if (typeof input === "string") {
    return input.trim();
  } else if (typeof input === "number") {
    return input.toLocaleString();
  } else {
    return input ? "참" : "거짓";
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;typeof는 "string", "number", "boolean", "undefined", "object", "function", "symbol", "bigint" 중 하나를 반환합니다. 주의할 점은 typeof null이 "object"를 반환한다는 것입니다. 따라서 null과 객체를 동시에 다루는 경우에는 typeof만으로는 정확하게 구분하기 어렵습니다. null 체크를 별도로 추가하거나, 다른 타입 가드를 함께 사용해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function process(value: string | null) {
  if (typeof value === "string") {
    return value.toUpperCase(); // ✅ null이 아님이 보장됨
  }
  return "빈 값";
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;typeof는 원시 타입을 구분할 때 유용하지만, 객체의 구체적인 종류(Date인지, Array인지, 커스텀 클래스인지)를 구분하기에는 적합하지 않습니다. 객체는 typeof로 확인하면 전부 "object"가 반환되기 때문입니다. 이런 경우에는 다음에 소개할 instanceof를 사용해야 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) instanceof 가드&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;instanceof는 어떤 값이 특정 클래스의 인스턴스인지를 확인하는 연산자입니다. 주로 Date, Error 같은 내장 클래스나 직접 정의한 클래스의 인스턴스를 구분할 때 사용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function formatDate(value: string | Date) {
  if (value instanceof Date) {
    return `${value.getFullYear()}년 ${value.getMonth() + 1}월 ${value.getDate()}일`;
  }
  return value;
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;에러 처리에서도 자주 쓰입니다. try-catch 블록에서 catch한 에러가 어떤 종류인지 구분할 때 instanceof가 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function handleError(error: unknown) {
  if (error instanceof TypeError) {
    console.log("타입 에러:", error.message);
  } else if (error instanceof RangeError) {
    console.log("범위 에러:", error.message);
  } else {
    console.log("알 수 없는 에러");
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;다만 instanceof는 클래스 기반 타입에만 사용할 수 있습니다. 인터페이스나 타입 별칭 그 자체는 컴파일 과정에서 제거되어 런타임에 남지 않으므로, 이를 직접 instanceof로 검사할 수는 없습니다. 즉, 자바스크립트로 변환된 코드에는 인터페이스에 대한 정보가 남아있지 않으므로 instanceof로 비교할 대상 자체가 없는 것입니다. 물론 해당 인터페이스를 구현한 클래스가 있다면, 그 클래스를 기준으로 instanceof 검사를 하는 것은 가능합니다. 하지만 인터페이스 자체를 직접 검사할 수 없다는 점은 동일합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) in 연산자&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;in 연산자는 객체에 특정 프로퍼티가 존재하는지를 확인하는 방식으로 타입을 좁힙니다. 인터페이스나 타입 별칭으로 정의한 서로 다른 객체 타입을 구분할 때 특히 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface Dog {
  name: string;
  bark: () =&amp;gt; void;
}

interface Cat {
  name: string;
  meow: () =&amp;gt; void;
}

function greetPet(pet: Dog | Cat) {
  if ("bark" in pet) {
    pet.bark(); // ✅ Dog 타입으로 확정
  } else {
    pet.meow(); // ✅ Cat 타입으로 확정
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Dog에는 bark가 있고 Cat에는 없기 때문에, "bark" in pet 조건으로 두 타입을 구분할 수 있습니다. 이처럼 in 연산자는 타입마다 고유하게 존재하는 프로퍼티를 기준으로 분기할 때 효과적입니다. 다만, 두 타입이 완전히 동일한 프로퍼티 구조를 갖고 있다면 in만으로는 구분이 어렵습니다. 이런 경우에는 뒤에서 다룰 판별된 유니온 패턴이 더 적합합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;기본 패턴을 정리하면 다음과 같습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3719/%EA%B7%B8%EB%A6%BC2__3_.png"&gt;&lt;figcaption&gt;&amp;lt;출처 : 작가&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;실무에서 자주 쓰는 고급 패턴&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;앞서 살펴본 기본 패턴만으로도 많은 상황을 커버할 수 있지만, 실무에서 마주하는 타입 분기는 조금 더 복잡한 경우가 많습니다. 여러 종류의 응답 객체를 구분하거나, 타입스크립트가 자동으로 추론하지 못하는 상황을 직접 처리해야 할 때가 있습니다. 이런 경우에 활용할 수 있는 고급 패턴들을 살펴보겠습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;1) 판별된 유니온(Discriminated Union)&lt;/strong&gt;&lt;/h4&gt;&lt;figure class="image image_resized" style="width:100%;"&gt;&lt;img src="https://www.wishket.com/media/news/3719/%EA%B7%B8%EB%A6%BC3__2_.png"&gt;&lt;figcaption&gt;&amp;lt;출처: 작가, Claude AI 생성&amp;gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p style="text-align:center;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;실무에서 가장 많이 쓰이는 타입 좁히기 패턴입니다. 유니온을 구성하는 각 타입이 공통적으로 가지고 있는 리터럴 타입 필드를 기준으로 분기하는 방식입니다. 보통 type, status, kind 같은 필드가 이 역할을 합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;API 응답 처리를 예로 들어보겠습니다. 대부분의 API는 성공과 실패 시 응답 구조가 다릅니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface SuccessResponse {
  status: "success";
  data: {
    id: number;
    name: string;
  };
}

interface ErrorResponse {
  status: "error";
  errorCode: number;
  message: string;
}

type ApiResponse = SuccessResponse | ErrorResponse;&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;여기서 status 필드가 판별자(discriminant) 역할을 합니다. 이 필드의 값이 "success"인지 "error"인지에 따라 타입이 자동으로 확정됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function handleResponse(response: ApiResponse) {
  if (response.status === "success") {
    console.log(response.data.name); // ✅ SuccessResponse로 확정
  } else {
    console.log(`에러 ${response.errorCode}: ${response.message}`); // ✅ ErrorResponse로 확정
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;switch문과 결합하면 더 깔끔하게 분기할 수 있습니다. 상태가 세 가지 이상으로 나뉘는 경우에 특히 유용합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;interface LoadingState {
  status: "loading";
}

interface SuccessState {
  status: "success";
  data: string[];
}

interface ErrorState {
  status: "error";
  message: string;
}

type FetchState = LoadingState | SuccessState | ErrorState;

function renderUI(state: FetchState) {
  switch (state.status) {
    case "loading":
      return "로딩 중...";
    case "success":
      return state.data.join(", ");
    case "error":
      return `오류: ${state.message}`;
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;판별된 유니온의 장점은 코드의 의도가 명확하다는 것입니다. status 필드 하나만 보면 어떤 타입인지 바로 알 수 있기 때문에 가독성이 좋고, 새로운 상태가 추가되더라도 switch문에 case만 추가하면 되므로 확장도 용이합니다. 또한 never 타입을 활용한 exhaustive check를 함께 쓰면, 누락된 분기를 컴파일 단계에서 바로 잡아낼 수 있어 더 안전합니다. 리액트에서 API 호출 상태를 관리하거나, Redux 같은 상태 관리 도구에서 액션을 구분할 때도 이 패턴이 자주 사용됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;2) 사용자 정의 타입 가드(is 키워드)&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;지금까지 살펴본 패턴들은 타입스크립트가 조건문을 분석해서 자동으로 타입을 좁혀주는 경우였습니다. 하지만 타입스크립트가 자동으로 추론하지 못하는 상황도 있습니다. 예를 들어, 복잡한 조건을 별도 함수로 분리하면, 그 함수의 반환값이 boolean일 뿐 타입 좁히기로 연결되지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function isString(value: unknown): boolean {
  return typeof value === "string";
}

function process(value: string | number) {
  if (isString(value)) {
    value.toUpperCase(); // ❌ 여전히 string | number
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;위 코드에서 isString 함수는 분명히 문자열 여부를 확인하고 있지만, 타입스크립트 입장에서는 그냥 boolean을 반환하는 함수일 뿐입니다. 조건문 안에서의 타입 좁히기가 작동하지 않습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이런 상황에서 is 키워드를 사용하면 됩니다. 반환 타입을 value is string 형태로 선언하면, 이 함수가 true를 반환할 때 해당 매개변수가 특정 타입임을 타입스크립트에 알려줄 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function isString(value: unknown): value is string {
  return typeof value === "string";
}

function process(value: string | number) {
  if (isString(value)) {
    value.toUpperCase(); // ✅ string 타입으로 확정
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;이 패턴은 반복적으로 사용되는 타입 체크 로직을 함수로 분리할 때 특히 유용합니다. 여러 곳에서 동일한 타입 확인 조건을 작성하는 대신, 타입 가드 함수 하나를 만들어두면 코드의 중복을 줄이면서도 타입 안전성을 유지할 수 있습니다. 배열에서 null이나 undefined를 걸러내는 필터링 패턴에서도 자주 활용됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function isNotNull&amp;lt;T&amp;gt;(value: T | null): value is T {
  return value !== null;
}

const items = ["사과", null, "바나나", null, "딸기"];
const filtered = items.filter(isNotNull);
// filtered의 타입: string[]&lt;/code&gt;&lt;/pre&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;Array.filter에 일반적인 boolean 반환 함수를 넘기면 타입스크립트가 null이 제거되었다는 것을 대부분 인식하지 못해 (string | null)[] 타입이 유지되는데, is 키워드를 사용한 타입 가드를 넘기면 string[]으로 정확하게 추론됩니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style="text-align:justify;"&gt;&lt;strong&gt;3) 타입 좁히기 사용 시 주의할 점&lt;/strong&gt;&lt;/h4&gt;&lt;p style="text-align:justify;"&gt;타입 좁히기는 강력한 기능이지만, 실무에서 사용하다 보면 몇 가지 실수하기 쉬운 지점이 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;먼저 첫 번째로 주의할 것은 타입 단언(as)의 남용입니다. 타입 좁히기 대신 as로 강제 변환하면 코드가 짧아지는 것처럼 보이지만, 타입 안전성을 포기하는 것입니다. 실제 런타임 값이 해당 타입이 아닐 경우, 타입스크립트는 에러를 잡아주지 못합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;// ❌ 위험: 실제로 string이 아닐 수 있음
const value = someFunction() as string;
console.log(value.toUpperCase()); // 런타임 에러 가능

// ✅ 안전: 실제로 string인지 확인 후 사용
const value = someFunction();
if (typeof value === "string") {
  console.log(value.toUpperCase());
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-left:36pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;두 번째는 콜백 함수 안에서 좁혀진 타입이 풀리는 경우입니다. 바깥 스코프에서 타입을 좁혀놨더라도, 콜백 안에서는 이 정보가 유지되지 않을 수 있습니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;function process(value: string | null) {
  if (value !== null) {
    // 여기서는 string 타입으로 좁혀짐
    setTimeout(() =&amp;gt; {
      console.log(value.toUpperCase()); // ✅ 이 경우는 동작함
    }, 100);
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-left:36pt;text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="text-align:justify;"&gt;위 예시처럼 재할당 가능성이 없고 제어 흐름상 안전하다고 판단되는 경우에는 콜백 안에서도 좁혀진 타입이 유지될 수 있습니다. 하지만 let으로 선언된 변수는 콜백이 실행되기 전에 다른 값이 할당될 수 있기 때문에, 타입스크립트의 제어 흐름 분석이 클로저 경계를 넘어서까지 안전하다고 보장하지 못하는 경우가 있습니다. 이런 상황에서는 좁혀진 값을 별도의 const 변수에 담아두는 방법이 안전합니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-typescript"&gt;let value: string | null = getString();

if (value !== null) {
  const confirmed = value; // string 타입으로 확정된 값을 별도 변수에 저장
  setTimeout(() =&amp;gt; {
    console.log(confirmed.toUpperCase()); // ✅ 안전
  }, 100);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align:justify;"&gt;&lt;strong&gt;마치며&lt;/strong&gt;&lt;/h3&gt;&lt;p style="text-align:justify;"&gt;이번 글에서는 타입스크립트의 타입 좁히기에 대해 살펴보았습니다. 코드를 작성하다 as를 사용하고 싶은 순간이 오면, 잠시 멈추고 타입 좁히기로 해결할 수 있는지 먼저 떠올려보세요. 대부분의 경우 조건문 한두 줄이면 충분하고, 그렇게 작성한 코드가 더 안전하고 읽기 쉬운 코드로 이어집니다. 타입 좁히기에 익숙해질수록 타입스크립트를 더 자신 있게 다룰 수 있게 될 것입니다.&lt;/p&gt;&lt;p style="text-align:justify;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin-left:0px;text-align:center;"&gt;&lt;span style="color:rgb(153,153,153);"&gt;©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.&lt;/span&gt;&lt;/p&gt;&lt;/b&gt;]]&gt;</content:encoded></item></channel></rss>