<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>게임 클라 개발</title>
    <link>https://tsyang.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 12 Aug 2026 11:27:50 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>tsyang</managingEditor>
    <image>
      <title>게임 클라 개발</title>
      <url>https://tistory1.daumcdn.net/tistory/4294047/attach/0d70c62fc37643538497c846f90b4a94</url>
      <link>https://tsyang.tistory.com</link>
    </image>
    <item>
      <title>AI 활용 팁</title>
      <link>https://tsyang.tistory.com/234</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2026.5 기준 AI를 잘 쓰기위한 팁을 정리해봤다. 프로그래머가 아니더라도 이해할 수 있게 쓰려고 노력했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이해하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI의 성능&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Opus 4.5까지만 해도 AI 아직 애매하다고 생각했다. Opus 4.6에서 크게 좋아졌고 AI를 활용하는 방법에 대한 연구 역시 많이 진전이 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직도 AI가 멍청하다고 하는 사람이 있다면, 나는 아마도 그 사람이 AI를 잘 못 써서 그런 것이라고 얘기할 것이다. (사실은 속으로만 생각ㅎ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금(2026.5)의 AI는 굉장히 똑똑하고 빠르지만, 일머리는 하나도 없는 신입사원 같은 녀석이다. 결국 AI를 잘 쓰려면 시스템, 가이드라인 따위가 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트의 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트는 AI에게 건네는 &lt;code&gt;요청서&lt;/code&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 AI를 일머리 없지만 일처리는 빠른 신입사원이라고 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의를 앞둔 부장님이 AI 사원한테 다음과 같이 시킨다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;이 문서 사람당 2부씩 인쇄해줘&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문장은 사람에게는 그럭저럭 통할 수 있다. 부장님이 회의 직전에 말했고, 책상 위에 문서가 있고, 회의 참석자가 몇 명인지 대충 알고 있다면 알아서 처리할 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;215&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z8DOK/dJMcahEucKP/k3PFuyxxUoQVDwirwWDki1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z8DOK/dJMcahEucKP/k3PFuyxxUoQVDwirwWDki1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z8DOK/dJMcahEucKP/k3PFuyxxUoQVDwirwWDki1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz8DOK%2FdJMcahEucKP%2Fk3PFuyxxUoQVDwirwWDki1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;354&quot; height=&quot;215&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;215&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 AI 입장에서는 비어있는 칸이 많다. 이 문서가 어떤 문서인지, 사람이 누구인지, 몇 명인지, 흑백인지 컬러인지, 단면인지 양면인지, 바로 출력해도 되는지 전부 추측해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 어쩌면 모든 회사 사람들한테 자료를 뽑아주기 위해 문서를 수천 부 인쇄하고 있을지 모른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 더 나은 프롬프트는 이렇다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;오늘 오후 5시 기획 회의 참석자 6명에게 나눠줄 자료야. 방금 올린 PDF를 사람당 2부씩, 총 12부, 흑백 양면으로 인쇄해줘. 실제 출력 전에 설정을 한번 요약해서 확인받아줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트란 AI가 멋대로 추측해야 하는 빈칸을 줄여주는 일이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨텍스트의 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI의 두뇌를 LLM이라고 할 수 있다. 그런데 LLM에게는 &quot;기억&quot;이란 게 없다. 그냥 사용자가 넣은 &lt;code&gt;요청서&lt;/code&gt;를 읽고, 사용자가 좋아할 만한 답변을 내놓는 게 LLM이 하는 모든 일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 LLM은 메모장을 하나씩 가지고 있다. 이 메모장이 바로 &lt;code&gt;컨텍스트(Context)&lt;/code&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(엄밀히 말하면 LLM이 진짜 메모장을 들고 있는 것은 아니다. 앱이나 하네스가 이전 대화, 파일, 지시문, 도구 결과를 LLM 앞에 다시 펼쳐주는 것에 가깝다. 여기서는 쉽게 설명하기 위해 메모장이라고 부르겠다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 같은 프롬프트라도 컨텍스트에 따라 결과가 달라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tt24B/dJMcacws65o/4YPn8g5mnrINg6dBwtFfP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tt24B/dJMcacws65o/4YPn8g5mnrINg6dBwtFfP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tt24B/dJMcacws65o/4YPn8g5mnrINg6dBwtFfP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftt24B%2FdJMcacws65o%2F4YPn8g5mnrINg6dBwtFfP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;355&quot; height=&quot;224&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;이 문서 사람당 2부씩 인쇄해줘&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 대화에서 이 말만 하면 AI는 거의 모든 것을 추측해야 한다. 하지만 같은 세션의 메모장에 &quot;오늘 오후 5시 기획 회의 참석자는 6명이다&quot;, &quot;방금 올린 PDF가 회의 자료다&quot;, &quot;우리 회사는 회의 자료를 기본적으로 흑백 양면으로 뽑는다&quot; 같은 내용이 들어있다면, AI는 그 정보를 바탕으로 훨씬 덜 헤맨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 메모장은 &lt;code&gt;세션&lt;/code&gt;마다 하나씩 가지고 있다. 세션이란, 챗봇과 &quot;새 대화&quot;할 때 그 대화 채팅 하나와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트는 이번 요청의 빈칸을 줄이고, 컨텍스트는 이미 주어진 맥락을 다시 쓰게 해준다. 하지만 매번 사용자가 이 둘을 완벽히 챙기기는 어렵다. 그래서 반복 규칙과 안전장치를 시스템 쪽에 깔아두는 하네스가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;하네스의 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨텍스트가 AI 앞에 펼쳐진 메모장이라면, 하네스는 모델을 실제로 일할 수 있는 에이전트로 만드는 시스템이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하네스는 모델에게 컨텍스트와 도구를 제공하고, 모델이 요청한 행동을 실행하며, 그 결과를 다시 모델에게 전달한다. 세션 기록, 권한 확인, 안전장치도 하네스가 담당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 회사 출력 시스템에 AI를 붙였다고 해보자. 이 시스템에 이런 규칙을 미리 넣어둘 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회의 인원 정보가 없으면 바로 출력하지 말고 먼저 물어본다.&lt;/li&gt;
&lt;li&gt;캘린더에서 곧 시작할 회의와 참석자 수를 확인해서 컨텍스트에 넣는다.&lt;/li&gt;
&lt;li&gt;50부 이상 출력하려면 사용자 확인을 받는다.&lt;/li&gt;
&lt;li&gt;실제 출력 전에 문서명, 출력 부수, 컬러 여부, 단면/양면 설정을 요약해서 보여준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 사용자가 &quot;문서 사람당 2부씩 인쇄해줘&quot;라고 대충 말해도 사고가 날 가능성이 줄어든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트가 &quot;이번에 무엇을 요청할 것인가&quot;라면, 하네스는 &quot;그 요청을 실제 행동으로 연결하고 통제하는 시스템&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;응용&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;397&quot; data-origin-height=&quot;217&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PiI0n/dJMcadaY6aP/neUNrw28vGogtqKiCrgeMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PiI0n/dJMcadaY6aP/neUNrw28vGogtqKiCrgeMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PiI0n/dJMcadaY6aP/neUNrw28vGogtqKiCrgeMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPiI0n%2FdJMcadaY6aP%2FneUNrw28vGogtqKiCrgeMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;397&quot; height=&quot;217&quot; data-origin-width=&quot;397&quot; data-origin-height=&quot;217&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;좋은 프롬프트&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트를 잘 쓴다는 것은 말을 길게 쓰는 것이 아니다. AI가 멋대로 추측해야 하는 빈칸을 줄이는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 프롬프트를 &lt;code&gt;요청서&lt;/code&gt;라고 했다. 좋은 요청서는 화려한 문장이 아니라, 일을 맡은 사람이 헤매지 않게 필요한 정보를 담고 있는 문서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이렇게 말할 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;자료 정리해줘&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말만 들으면 AI는 무엇을 기준으로 정리해야 하는지, 누가 읽을 자료인지, 어느 정도 깊이로 정리해야 하는지, 표로 줄지 글로 줄지 전부 추측해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 더 나은 프롬프트는 이렇다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;방금 올린 회의 자료를 팀장에게 보고할 수 있게 정리해줘. 목적은 오후 5시 기획 회의 전에 핵심 쟁점과 결정할 일을 빠르게 파악하는 것이다. 형식은 제목, 요약 5줄, 결정 필요 사항, 리스크, 확인 질문 순서로 써줘. 자료에 없는 내용은 추측하지 말고 확인 필요라고 표시해줘. 먼저 바로 작성하지 말고, 네가 이해한 정리 방향과 빠진 정보가 있는지부터 알려줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프롬프트가 좋은 이유는 길어서가 아니다. 목적, 대상, 자료, 형식, 제약, 진행 방식이 들어있기 때문이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;방향 맞추기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xlVyP/dJMcaiXF7L3/LjeAKexQEfsi4RrO8JeRw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xlVyP/dJMcaiXF7L3/LjeAKexQEfsi4RrO8JeRw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xlVyP/dJMcaiXF7L3/LjeAKexQEfsi4RrO8JeRw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxlVyP%2FdJMcaiXF7L3%2FLjeAKexQEfsi4RrO8JeRw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;749&quot; height=&quot;223&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;223&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 처음부터 결과물을 요구하지 않는 것이 중요하다. AI는 빠르기 때문에 틀린 방향으로도 아주 빠르게 달린다. 그래서 복잡한 일을 시킬 때는 바로 최종본을 쓰게 하기보다 먼저 방향을 맞추는 편이 좋다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;바로 쓰지 말고 먼저 목차만 제안해줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;내 요청에서 애매한 점이 있으면 작업하기 전에 질문해줘.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;먼저 네가 이해한 목표와 작업 계획을 요약해줘.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 문장은 AI를 느리게 만드는 것이 아니라, 삽질을 줄이는 장치다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇을 질문할지 고민인가? 걱정 마라 아래에 기똥찬 해결법을 소개해놨다. Grill-me 스킬 항목을 참고하라.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Plan mode&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 작업은 그냥 시키지 말고 Plan mode를 쓰는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 &quot;이 문서 사람당 2부씩 인쇄해줘&quot;라고 하면 AI는 바로 출력 설정을 잡으려 한다. 문제는 이때 문서가 확정되지 않았거나, 참석자 수가 없거나, 컬러/흑백 설정이 빠져 있어도 일단 진행하려 할 수 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Plan mode는 이 속도를 일부러 늦춘다. 바로 실행하지 않고 먼저 목표, 범위, 빠진 정보, 위험한 조건, 작업 순서를 정리하게 만든다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LhS3A/dJMcafmqUJN/YCz2w8rDIYaneluFMnxVPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LhS3A/dJMcafmqUJN/YCz2w8rDIYaneluFMnxVPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LhS3A/dJMcafmqUJN/YCz2w8rDIYaneluFMnxVPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLhS3A%2FdJMcafmqUJN%2FYCz2w8rDIYaneluFMnxVPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;252&quot; height=&quot;226&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이렇게 말할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;바로 인쇄하지 말고 Plan mode로 먼저 봐줘. 인쇄 전에 필요한 정보, 빠진 정보, 확인해야 할 위험한 조건을 정리해줘.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 대부분 Shift+Tab을 누르면 Plan Mode로 전환이 가능하다. 이 상태에서 말하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 AI는 먼저 이런 식으로 정리한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 문서를 출력할지 확정됐는가?&lt;/li&gt;
&lt;li&gt;참석자 수가 있는가?&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 data-ke-size=&quot;size16&quot;&gt;이걸 보고 사용자는 부족한 정보를 채워줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Plan mode가 좋은 이유는 AI가 더 똑똑해져서가 아니다. 틀린 방향으로 빠르게 달리기 전에 멈출 기회를 만들어주기 때문이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;스킬&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스킬은 반복되는 &lt;code&gt;작업 종류&lt;/code&gt;를 위한 절차서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트가 &lt;code&gt;이번 요청서&lt;/code&gt;라면, 스킬은 &lt;code&gt;특정 업무를 맡았을 때 꺼내는 레시피&lt;/code&gt;에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 것들이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인쇄 업무를 자주 시킨다고 해보자. 매번 프롬프트에 &quot;회의 자료면 참석자 수를 확인하고, 기본은 흑백 양면으로 하고, 50부 이상이면 확인받고, 출력 전에는 설정을 요약해줘&quot;라고 쓰는 것은 귀찮다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럴 때 &lt;code&gt;인쇄 스킬&lt;/code&gt;을 하나 만들어둔다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회의 자료인지 먼저 확인한다.&lt;/li&gt;
&lt;li&gt;참석자 수가 있으면 사람당 필요한 부수를 계산한다.&lt;/li&gt;
&lt;li&gt;참석자 수가 없으면 바로 출력하지 말고 질문한다.&lt;/li&gt;
&lt;li&gt;기본 출력은 흑백 양면으로 한다.&lt;/li&gt;
&lt;li&gt;50부 이상이면 사용자 확인을 받는다.&lt;/li&gt;
&lt;li&gt;출력 전에는 문서명, 부수, 컬러 여부, 단면/양면 설정을 요약한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 만들어두면 다음부터는 길게 설명할 필요가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;이 문서 사람당 2부씩 인쇄해줘. 인쇄 스킬 써서 처리해줘.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 툭 던지면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 규칙은 매번 프롬프트에 쓰기에는 길고, 모든 대화에 항상 적용하면 오히려 방해된다. 필요할 때만 꺼내 쓰게 만드는 것이 스킬이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;CLAUDE.md / AGENTS.md&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 매번 같은 말을 프롬프트에 쓰고 있다면, 그건 스킬보다 업무 매뉴얼에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 매번 &quot;말투는 쉽게 써줘&quot;, &quot;추측하지 말고 모르면 물어봐&quot;, &quot;수정 전에는 계획을 먼저 말해줘&quot;, &quot;검증 가능한 것은 확인하고 말해줘&quot; 같은 말을 반복하고 있다면, 그건 매 요청마다 붙일 내용이 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;나 &lt;code&gt;AGENTS.md&lt;/code&gt;는 신입사원이 대화 시작 전에 무조건 읽는 업무 매뉴얼이라고 생각하면 된다. 말투, 작업 방식, 금지사항, 검증 방식처럼 항상 적용할 지시는 프롬프트에 매번 쓰기보다 이런 문서에 빼두는 편이 낫다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트는 이번 요청을 잘 쓰는 기술이다. 반복되는 요청 방식은 &lt;code&gt;스킬&lt;/code&gt;, &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt; 같은 매뉴얼 쪽으로 넘기는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이 문서를 거대하게 만드는 것이 항상 좋은 것은 아니다. 이 이야기는 심화에서 따로 다루겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨텍스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨텍스트를 잘 쓴다는 것은 AI의 메모장을 깨끗하게 유지하는 일이다. 프롬프트를 아무리 잘 써도, 메모장에 엉뚱한 내용이 잔뜩 섞여 있으면 AI는 그걸 같이 보고 답한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1세션 1주제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 컨텍스트 내에서 이것저것 질문하지 않는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I73Tm/dJMcadWoHt0/uC4OiLOECqDOj8d6Ji2lMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I73Tm/dJMcadWoHt0/uC4OiLOECqDOj8d6Ji2lMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I73Tm/dJMcadWoHt0/uC4OiLOECqDOj8d6Ji2lMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI73Tm%2FdJMcadWoHt0%2FuC4OiLOECqDOj8d6Ji2lMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;375&quot; height=&quot;202&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 별문제가 없어 보인다. 인쇄 설정을 물어보다가, 회의록을 쓰고, 업무 메일을 쓰다가, 다시 인쇄 업무로 돌아올 수도 있다. 사람은 대충 화제를 전환할 수 있지만, AI 입장에서는 이 모든 내용이 같은 메모장에 쌓인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 나중에 &quot;아까 말한 방식대로 해줘&quot;라고 했을 때, 그 &quot;아까&quot;가 인쇄 이야기인지, 회의록 얘긴지, 업무 메일 얘기인지 흐려질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 작업은 새 세션에서 진행하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Compact&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업이 길어지면 컨텍스트가 계속 불어난다. 처음에는 필요한 정보가 쌓이는 것처럼 보이지만, 어느 순간부터는 이미 끝난 논의, 잘못 갔다가 되돌린 방향, 중간에 버린 선택지까지 한꺼번에 섞인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때 AI가 갑자기 멍청해진 것처럼 보일 수 있다. 사실 모델이 갑자기 나빠졌다기보다, 앞에 쌓인 메모장이 너무 지저분해진 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Compact&lt;/code&gt;는 이 긴 대화를 압축해서 다시 들고 가는 기능이다. 지금까지의 대화를 그대로 계속 끌고 가는 대신, 중요한 결정과 현재 작업 상태만 요약해서 컨텍스트를 줄인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBpVlo/dJMb99Ndvge/puO5ZQNHHBYgqUnsQ8wvzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBpVlo/dJMb99Ndvge/puO5ZQNHHBYgqUnsQ8wvzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBpVlo/dJMb99Ndvge/puO5ZQNHHBYgqUnsQ8wvzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBpVlo%2FdJMb99Ndvge%2FpuO5ZQNHHBYgqUnsQ8wvzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;388&quot; height=&quot;224&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compact는&amp;nbsp; &lt;code&gt;/compact&lt;/code&gt; 명령으로 쓸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compact는 컨텍스트가 망가졌을 때만 쓰는 기능은 아니다. 같은 맥락 안에서도 작업과 작업 사이에 한 번 정리해주면 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 한 작업에서 자료를 읽고 방향을 정했다면, 다음 작업으로 넘어가기 전에 Compact를 해두는 편이 낫다. 그래야 AI가 이미 끝난 논의보다 지금부터 필요한 결정과 남은 작업에 집중한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compact 전에 AI에게 이렇게 정리시킬 수는 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;이 대화에서 유지해야 할 결정, 버린 선택지, 아직 남은 작업, 주의할 점만 정리해줘.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 도구가 지원하는 &lt;code&gt;/compact&lt;/code&gt; 명령이나 버튼을 사용하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;377&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPotK3/dJMcacb8WDw/QX5g8opiPAVpn8m4VxEap0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPotK3/dJMcacb8WDw/QX5g8opiPAVpn8m4VxEap0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPotK3/dJMcacb8WDw/QX5g8opiPAVpn8m4VxEap0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPotK3%2FdJMcacb8WDw%2FQX5g8opiPAVpn8m4VxEap0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;377&quot; height=&quot;216&quot; data-origin-width=&quot;377&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compact가 필요한 순간은 보통 이렇다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대화가 길어져서 AI가 앞뒤를 헷갈리기 시작할 때&lt;/li&gt;
&lt;li&gt;이미 끝난 논점을 AI가 계속 다시 꺼낼 때&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 data-ke-size=&quot;size16&quot;&gt;다만 Compact도 만능은 아니다. Compact는 긴 대화를 요약해서 계속 쌓는 방식이다. 압축이 반복되면 중요한 디테일이 빠질 수도 있고, 잘못 요약된 내용이 계속 이어질 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 같은 맥락을 유지한 채 다음 작업으로 넘어갈 때는 Compact가 좋고, 작업의 주제 자체가 바뀌었거나 컨텍스트가 너무 망가졌다면 새 세션으로 넘어가는 편이 낫다. 이 차이는 심화의 Handoff에서 다시 다루겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;하네스&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가드레일과 게이트&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;340&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eyDGO1/dJMcaii7JtB/sUzek9xHgpzgmQSMAWyJNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eyDGO1/dJMcaii7JtB/sUzek9xHgpzgmQSMAWyJNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eyDGO1/dJMcaii7JtB/sUzek9xHgpzgmQSMAWyJNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeyDGO1%2FdJMcaii7JtB%2FsUzek9xHgpzgmQSMAWyJNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;340&quot; height=&quot;138&quot; data-origin-width=&quot;340&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가드레일은 AI가 작업 중 지켜야 하는 규칙이다. 게이트는 실제 행동으로 넘어가기 전에 멈춰서 확인하게 만드는 문턱이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 파일을 수정하는 작업이라면 이런 가드레일을 둘 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수정 전에 먼저 파일을 읽는다.&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 data-ke-size=&quot;size16&quot;&gt;여기에 게이트를 붙이면 더 강해진다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 파일을 한 번에 바꾸려 하면 먼저 변경 범위를 확인받는다.&lt;/li&gt;
&lt;li&gt;삭제나 대량 변경이 있으면 바로 실행하지 않고 멈춘다.&lt;/li&gt;
&lt;li&gt;터미널에서 위험한 명령을 실행하려 하면 사용자 확인을 받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 규칙은 프롬프트에 직접 써도 되고, 반복해서 쓴다면 &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, 업무별 가이드에 적어두면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로는 이렇게 말하면 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;작업 전에 가드레일을 확인해줘. 수정할 파일을 읽었는지, 요청 범위 밖을 건드리는지, 내가 이미 바꾼 내용을 덮어쓸 위험이 있는지 봐줘.&quot;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;실행 전에 게이트를 통과하는지 확인해줘. 여러 파일 수정, 삭제, 대량 변경, 위험한 터미널 명령이 있으면 바로 실행하지 말고 나에게 먼저 확인받아.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 프롬프트나 가이드에 적어두는 것만으로는 완벽하지 않다. AI는 컨텍스트가 길어지거나 작업이 복잡해지면 이런 규칙도 놓칠 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Hook&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;90&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XPa2c/dJMcaiDqCny/X3fRQXVMhabj1kxKqkTgBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XPa2c/dJMcaiDqCny/X3fRQXVMhabj1kxKqkTgBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XPa2c/dJMcaiDqCny/X3fRQXVMhabj1kxKqkTgBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXPa2c%2FdJMcaiDqCny%2FX3fRQXVMhabj1kxKqkTgBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;343&quot; height=&quot;90&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;90&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hook은 제품이나 회사가 제공하는 자동 실행 지점이다. Claude를 예로 들면 &lt;code&gt;PreToolUse&lt;/code&gt;처럼 도구를 실행하기 전에 걸리는 Hook이 있다. 이런 Hook은 터미널 실행, 파일 수정 같은 특정 도구 호출 앞에 붙일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 파일 쓰기 도구가 실행되기 전에 Hook을 걸 수 있다면, &lt;code&gt;gate.md&lt;/code&gt;를 먼저 읽게 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;gate.md&lt;/code&gt;에는 이런 내용을 적어둔다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 파일을 먼저 읽었는가?&lt;/li&gt;
&lt;li&gt;요청받은 범위 밖을 수정하는가?&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 data-ke-size=&quot;size16&quot;&gt;실제로는 이렇게 요청하면 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;지금 쓰는 Codex에서 파일 쓰기 도구 실행 전 Hook을 지원하는지 확인해줘. 지원한다면 gate.md를 만들고, 파일을 쓰기 전에 그 문서를 확인하게 설정해줘. 게이트에 걸리면 쓰기를 멈추고 나에게 확인받게 해줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널 실행도 같은 방식이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;터미널 명령 실행 전 Hook을 지원하는지 확인해줘. 삭제, 초기화, 배포 같은 위험한 명령은 바로 실행하지 말고 먼저 확인받게 해줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 AI가 규칙을 기억해주길 기대하지 않는 것이다. 중요한 규칙은 프롬프트나 가이드에만 두지 말고, 도구가 실행되는 순간 다시 확인되게 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;심화&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;잘 명령하기&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Grill-me&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Grill-me&lt;/code&gt;는 Matt Pocock의 &lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/productivity/grill-me/SKILL.md&quot;&gt;&lt;code&gt;grill-me&lt;/code&gt; 스킬&lt;/a&gt;에서 가져온 방식이다. 이름 그대로 AI가 사용자를 몰아붙이듯 질문해서, 요청 안에 비어 있는 조건을 찾아내게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트를 쓰려면 내가 원하는 것을 알아야 한다. 그런데 실제로는 내가 뭘 원하는지 나도 잘 모르는 경우가 많다. 이럴 때 AI에게 바로 답을 쓰게 하지 말고, 먼저 나를 캐묻게 만드는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 위의 스킬 링크를 AI한테 던져주고 grill-me를 설치해달라고 하자. (grill-with-docs가 더 낫지만 차이를 모르겠다면 쉬운거 써라)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저걸 쓰면 AI가 보통 한 20개 내외의 질문 공세를 펼친다. 필요하면 더 요청할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식의 장점은 내가 놓친 빈칸이 먼저 드러난다는 것이다. AI가 그럴듯한 결과물을 바로 뽑아내는 것보다, 중요한 결정을 하나씩 묻고 확인하는 편이 나중에 덜 흔들린다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;피드백&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 결과물을 만들게 했다면, 같은 AI에게 바로 &quot;괜찮아?&quot;라고 묻는 것은 약하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 컨텍스트 안의 AI는 지금까지의 결정과 흐름을 이미 알고 있다. 그래서 틀린 방향으로 간 부분도 &quot;앞에서 그렇게 정했으니까&quot; 하고 자연스럽게 받아들이기 쉽다. 사람도 자기가 쓴 문서를 자기가 보면 오타를 놓치는 것과 비슷하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 가능하면 &lt;b&gt;리뷰는 서브에이전트에게&lt;/b&gt; 따로 시키는 편이 좋다. 작업한 에이전트가 아니라, 결과물을 처음 보는 리뷰어 역할을 하나 더 세우는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;319&quot; data-origin-height=&quot;171&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkPeWw/dJMcab5nfeR/IRFwv4GpZ4qzy4kAJ9PKmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkPeWw/dJMcab5nfeR/IRFwv4GpZ4qzy4kAJ9PKmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkPeWw/dJMcab5nfeR/IRFwv4GpZ4qzy4kAJ9PKmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkPeWw%2FdJMcab5nfeR%2FIRFwv4GpZ4qzy4kAJ9PKmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;319&quot; height=&quot;171&quot; data-origin-width=&quot;319&quot; data-origin-height=&quot;171&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이렇게 시킬 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;서브에이전트에게 이 결과물을 리뷰시켜줘. 작업 맥락을 전부 주지 말고, 결과물과 검토 기준만 넘겨줘. 리뷰어는 이 작업을 처음 보는 사람이라고 가정하고, 빠진 조건, 모순, 실행하기 어려운 부분, 검증되지 않은 가정만 찾아줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 중요한 것은 리뷰어에게 너무 많은 변명을 주지 않는 것이다. 작업 과정 전체를 다 넘기면 리뷰어도 기존 결정을 따라가게 된다. 결과물, 목표, 완료 기준 정도만 주고 냉정하게 보게 하는 편이 낫다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서브에이전트를 지원하지 않는 도구라면 새 세션을 열어 같은 방식으로 시킬 수 있다. 핵심은 만든 쪽과 검토하는 쪽의 컨텍스트를 분리하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복해서 쓰는 리뷰 방식이 있다면 이것도 스킬로 빼둘 수 있다. &quot;초안 검토 스킬&quot;, &quot;업무 절차 검토 스킬&quot;, &quot;릴리스 체크 스킬&quot;처럼 만들어두면 매번 같은 기준을 다시 설명하지 않아도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨텍스트 관리&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Context Rot&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨텍스트는 길어질수록 썩는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 대화가 길어지는 것이 좋아 보인다. AI가 더 많은 배경을 알게 되고, 이전 결정을 참고할 수 있기 때문이다. 하지만 어느 순간부터는 오래된 결정, 취소한 방향, 중간에 잘못 이해한 내용, 사용자의 짜증 섞인 정정까지 전부 같이 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태에서는 &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, 업무별 가이드에 좋은 규칙을 적어두어도 AI가 놓칠 수 있다. 가드레일과 게이트도 마찬가지다. 컨텍스트가 길고 복잡하면 AI는 중요한 규칙보다 방금 앞에 나온 말에 끌려갈 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Dumb zone&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjJXPG/dJMb99NdvpD/XGsLBiAH59J2nMEyKiIL0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjJXPG/dJMb99NdvpD/XGsLBiAH59J2nMEyKiIL0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjJXPG/dJMb99NdvpD/XGsLBiAH59J2nMEyKiIL0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjJXPG%2FdJMb99NdvpD%2FXGsLBiAH59J2nMEyKiIL0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;737&quot; height=&quot;220&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Dumb zone&lt;/code&gt;은 컨텍스트가 어느 정도 찬 뒤 AI가 갑자기 둔해지는 구간을 말한다. 공식 용어라기보다, 현상을 설명하기 위한 이름에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구간에 들어가면 AI는 답을 못 하는 것이 아니라 이상하게 답한다. 말은 길어지는데 핵심을 놓치고, 이미 끝난 논점을 다시 꺼내고, 방금 정한 규칙을 어긴다. 사용자는 &quot;왜 갑자기 멍청해졌지?&quot;라고 느낀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때 프롬프트를 더 세게 쓰는 것만으로는 잘 해결되지 않는다. 정정과 반박이 컨텍스트에 더 쌓이면서 상황이 더 지저분해질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대응은 단순하다. 같은 작업을 이어갈 수 있으면 Compact를 하고, 주제가 바뀌었거나 이미 너무 꼬였으면 Handoff로 새 세션에 넘긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 Dumb zone은 대체 어디서부터 어디냐? 사실 모델마다 다르고 회사마다 다를 수 있다. 나는 개인적으로 컨텍스트가 50% 이상인데 새 작업이면 compact한다. Matt Pocock은 컨텍스트 120k쯤부터 Dumb Zone이라고 보기도 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Handoff&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Handoff는 작업을 다른 세션으로 넘기기 위한 인수인계 문서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compact와 비슷해 보이지만 목적이 다르다. Compact는 같은 세션을 계속 쓰기 위해 대화를 압축하는 기능이다. 반면 Handoff는 필요한 정보만 뽑아서 새 세션으로 가져가는 방식이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;267&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctuKGS/dJMcabK8gie/KMHMkVeEcb9Kt36Fc25kek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctuKGS/dJMcabK8gie/KMHMkVeEcb9Kt36Fc25kek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctuKGS/dJMcabK8gie/KMHMkVeEcb9Kt36Fc25kek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctuKGS%2FdJMcabK8gie%2FKMHMkVeEcb9Kt36Fc25kek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;267&quot; height=&quot;225&quot; data-origin-width=&quot;267&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compact가 반복되면 요약의 요약이 계속 쌓인다. 이 과정에서 중요한 디테일이 빠지거나, 잘못 요약된 내용이 계속 이어질 수 있다. Handoff는 그 누적을 끊는다. 새 세션에 필요한 목표, 결정, 현재 상태, 남은 작업, 주의할 점만 들고 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 한 세션에서 인쇄 운영 절차를 정리하다가, 중간에 인쇄와 관련된 사내 승인 절차를 따로 조사해야 할 수 있다. 이는 분명 인쇄 운영 절차와 관련이 있지만, 절차 정리와는 관련이 없다. 이럴 때 다른 세션으로 핸드오프 문서를 넘긴다. 그 뒤 그 세션에서 조사가 끝나면 그걸 다시 핸드오프로 만들어서 원래 절차 정리 세션에서 이어갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 쓸 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;이 작업을 새 세션에서 이어갈 수 있게 Handoff 문서를 만들어줘. 목표, 확정된 결정, 버린 선택지, 현재 상태, 남은 작업, 주의할 점만 정리해줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 원래 세션은 한 주제에 집중하고, 새 세션은 필요한 맥락만 들고 별도 작업을 할 수 있다. 나중에 새 세션의 결과가 나오면 다시 요약해서 원래 세션에 가져오면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스킬로 사용하는 것을 추천한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tsyang.tistory.com/233&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2026.05.12 - [AI코딩] - Matt Pocock 신규 스킬 4종&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;작업 관리&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Spec&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업이 커질수록 프롬프트 한 번으로 끝내려고 하면 위험하다. AI는 빈칸을 채우는 데 능숙하기 때문에, 요구사항이 비어 있으면 알아서 그럴듯한 결정을 만들어낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 큰 작업은 먼저 Spec 문서로 고정하는 편이 좋다. Spec은 거창한 기획서가 아니라, AI가 멋대로 정하면 안 되는 기준을 적어둔 문서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spec에는 보통 이런 것이 들어간다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;목표: 무엇을 만들거나 해결하려는가&lt;/li&gt;
&lt;li&gt;범위: 이번 작업에 포함되는 것과 제외되는 것&lt;/li&gt;
&lt;li&gt;완료 기준: 어디까지 되면 끝인가&lt;/li&gt;
&lt;li&gt;제약: 반드시 지킬 것과 하지 말아야 할 것&lt;/li&gt;
&lt;li&gt;검증 방법: 결과가 맞는지 어떻게 확인할 것인가&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkyW9h/dJMcajoIy55/ABq5FZONvR21TI6KLh2fpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkyW9h/dJMcajoIy55/ABq5FZONvR21TI6KLh2fpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkyW9h/dJMcajoIy55/ABq5FZONvR21TI6KLh2fpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkyW9h%2FdJMcajoIy55%2FABq5FZONvR21TI6KLh2fpk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;303&quot; height=&quot;214&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문서가 있으면 AI에게 &quot;이 Spec을 기준으로 작업해줘&quot;라고 말할 수 있다. 대화가 길어져도 기준점이 남고, 리뷰할 때도 결과물이 Spec을 만족하는지 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SDD(Spec Driven Development)처럼 Spec을 먼저 쓰고 구현으로 들어가는 방식도 같은 맥락이다. SDD는 스펙을 1차 산출물로 두고, 그 스펙을 바탕으로 명확화, 계획, 작업 분할, 구현으로 내려가는 흐름이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 AI에게 바로 달리게 하지 말고, 먼저 기준선을 문서로 세우는 것이다. SDD 자체는 따로 정리해둔 글이 있으니 더 자세한 내용은 &lt;a href=&quot;https://tsyang.tistory.com/224&quot;&gt;스펙 주도 개발 (Spec Driven Development)&lt;/a&gt;을 참고하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;검토는 HTML&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짧은 plan이나 리뷰는 그냥 글로 봐도 된다. 문제는 길어졌을 때다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만든 plan, 리뷰, 변경 요약이 길어지면 텍스트만으로는 중요한 부분을 놓치기 쉽다. 항목이 많아질수록 무엇이 결정됐고, 무엇이 위험하고, 무엇을 사람이 확인해야 하는지 한눈에 들어오지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때는 HTML 보고서로 만들어달라고 하는 편이 좋다. HTML은 검토를 대신하는 것이 아니라, 사람이 빠르게 훑고 판단하기 위한 보기 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이렇게 시킬 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;이 plan을 검토용 HTML 보고서로 만들어줘. 결정된 것, 위험한 것, 사람이 확인해야 할 것, 다음 작업을 나눠서 보여줘.&quot;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;이 리뷰 결과를 HTML로 정리해줘. 파일명, 줄 번호, 근거, 수정 우선순위를 표로 볼 수 있게 해줘.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표, 섹션, 체크리스트로 나뉘어 있으면 긴 글을 처음부터 끝까지 읽는 것보다 빠르게 피드백할 수 있다. 피드백 속도가 곧 작업 속도다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; Vertical Slice &lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 큰 작업을 맡길 때 흔한 실수는 작업을 수평으로 나누는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;366&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pC9Um/dJMcac4gmFk/4lIn7ZXBMkAupy8r5ExmgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pC9Um/dJMcac4gmFk/4lIn7ZXBMkAupy8r5ExmgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pC9Um/dJMcac4gmFk/4lIn7ZXBMkAupy8r5ExmgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpC9Um%2FdJMcac4gmFk%2F4lIn7ZXBMkAupy8r5ExmgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;366&quot; height=&quot;220&quot; data-origin-width=&quot;366&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 간단한 게임을 만든다고 해보자. 수평으로 나누면 이렇게 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전투 시스템 만들기&lt;/li&gt;
&lt;li&gt;UI 만들기&lt;/li&gt;
&lt;li&gt;로그인과 저장 만들기&lt;/li&gt;
&lt;li&gt;몬스터 스폰 만들기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;겉보기에는 깔끔하지만, 문제는 검증이 늦어진다는 것이다. 전투만 따로 만들고, UI만 따로 만들고, 저장만 따로 만들면 한참 뒤에야 전체가 맞물리는지 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vertical Slice는 기능별로 자르는 대신, 작지만 끝까지 이어지는 검증 단위로 자르는 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그인해서 캐릭터와 몬스터가 한 마리씩 보이는지 확인한다.&lt;/li&gt;
&lt;li&gt;캐릭터가 몬스터 한 마리를 공격하고, 결과 UI가 뜨는지 확인한다.&lt;/li&gt;
&lt;li&gt;몬스터가 자동으로 다시 나오고, 전투 결과가 저장되는지 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 작은 세로 조각을 &lt;code&gt;Tracer Bullet&lt;/code&gt;처럼 먼저 쏴보는 것이 좋다. 완성도는 낮아도 처음부터 끝까지 흐름이 이어지면, 실제로 동작하는지 바로 검증할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 작업도 마찬가지다. 큰 덩어리를 한 번에 맡기기보다, 사람이 빠르게 확인할 수 있는 세로 단위로 쪼개야 한다. 피드백 속도가 느리면 AI가 아무리 빨리 만들어도 전체 속도는 느려진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 위에 언급 한 것들은 오푸스 5.0같은 게 나오면서 다 내장될 수도 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가령 양산형 AI유튜버들이 안드레 카파시의 claude.md 스킬이 어쩌구 하지만 사실 대부분의 내용은 이미 최신의 codex나 claude가 내장하고 있다. (모르는 것을 추측해서 진행하지 마라 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 불구하고, 오푸스 10.0이 나와도 AI는 우리의 생각을 추측할 수 없을 것이다. (뇌를 스캔하지 않는 이상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결국 시간이 흘러도 남는 것은 의도를 명확히 하는 것(grill-me, 좋은 spec문서), 중간중간 검증을 하는 것(Vertical Layer)이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍 용어로 &lt;b&gt;소프트웨어 엔트로피&lt;/b&gt; 라는 개념이 있다. 이건 깨진 유리창 이론과도 비슷하다. 유리창이 깨져 있는 상태에서 AI한테 일을 시키면 깨진 유리창이 점점 늘고 작업이 산으로 간다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 좋아하는 Mattpocock이 강의에서 한 좋은 말이 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;...rate of feedback is your speed limit.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러니 자주 feedback하라. 위에서 언급한 '&lt;b&gt;HTML로 검토하라'&lt;/b&gt;는 이런 면에서 좋다. (곧 양산형 유튜버들이 엄청 언급할 것이다.) 작업 계획 리뷰부터 작업 결과물 리뷰까지 좀 길어진다 싶으면 html보고서로 생성해서 읽어라. feedback rate가 크게 증가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래머라면 &lt;a href=&quot;https://tsyang.tistory.com/232&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tsyang.tistory.com/232&lt;/a&gt;&amp;nbsp;봐라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI코딩</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/234</guid>
      <comments>https://tsyang.tistory.com/234#entry234comment</comments>
      <pubDate>Sat, 23 May 2026 00:50:39 +0900</pubDate>
    </item>
    <item>
      <title>Matt Pocock 신규 스킬 4종</title>
      <link>https://tsyang.tistory.com/233</link>
      <description>&lt;h1&gt;개요&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Matt Pocock의 최근 강연을 보고 그의 철학과 스킬 설계에 크게 감명받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마침 몇 시간 전에 따끈따끈한 스킬 소개 영상이 추가되어 이를 다뤄보고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이하 AI가 쓴 내용이고 몇번 더 사용후에 글을 다듬을 예정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가된 스킬은 아래와 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;/handoff&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/prototype&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/review&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/writing&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/handoff&lt;/code&gt;와 &lt;code&gt;/prototype&lt;/code&gt;은 새로 추가된 안정 스킬이고, &lt;code&gt;/review&lt;/code&gt;와 &lt;code&gt;/writing&lt;/code&gt;은 아직 &lt;code&gt;in-progress&lt;/code&gt; 영역에 있는 실험적 스킬이다.&lt;br /&gt;그리고 &lt;code&gt;/writing&lt;/code&gt;은 하나의 스킬 파일이 아니라 &lt;code&gt;writing-fragments&lt;/code&gt;, &lt;code&gt;writing-beats&lt;/code&gt;, &lt;code&gt;writing-shape&lt;/code&gt; 세 개로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유튜브 : &lt;a href=&quot;https://youtu.be/DNqsMXH6Eog?si=tTp7z2T3dMDu_APN&quot;&gt;https://youtu.be/DNqsMXH6Eog?si=tTp7z2T3dMDu_APN&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문 저장소: &lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;https://github.com/mattpocock/skills&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;/handoff&lt;/code&gt;: 컨텍스트를 다른 에이전트에게 넘기는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문 경로: &lt;code&gt;skills/productivity/handoff/SKILL.md&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;---
name: handoff
description: Compact the current conversation into a handoff document for another agent to pick up.
argument-hint: &quot;What will the next session be used for?&quot;
---

Write a handoff document summarising the current conversation so a fresh agent can continue the work. Save it to a path produced by `mktemp -t handoff-XXXXXX.md` (read the file before you write to it).

Suggest the skills to be used, if any, by the next session.

Do not duplicate content already captured in other artifacts (PRDs, plans, ADRs, issues, commits, diffs). Reference them by path or URL instead.

If the user passed arguments, treat them as a description of what the next session will focus on and tailor the doc accordingly.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;라인별 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 metadata는 이 스킬이 언제 호출되어야 하는지 정의한다.&lt;br /&gt;핵심 단어는 &lt;code&gt;Compact&lt;/code&gt;와 &lt;code&gt;another agent&lt;/code&gt;다.&lt;br /&gt;단순 요약이 아니라, 새 컨텍스트를 가진 다른 에이전트가 바로 이어서 일할 수 있게 현재 대화를 압축하는 것이 목적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;mktemp -t handoff-XXXXXX.md&lt;/code&gt;는 이 문서가 영구 산출물이 아니라는 뜻이다.&lt;br /&gt;PRD나 ADR처럼 오래 보존할 문서가 아니라, 컨텍스트 창 사이를 건너가기 위한 임시 전달 문서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;read the file before you write to it&lt;/code&gt;는 도구 제약을 고려한 문장이다.&lt;br /&gt;Claude Code 계열 도구에서는 읽지 않은 파일에 쓰려 할 때 문제가 생길 수 있다.&lt;br /&gt;스킬 안에 이런 사소한 제약을 직접 넣어 두면 agent가 환경 차이에 덜 흔들린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Suggest the skills to be used&lt;/code&gt;는 내용만 넘기지 말고 작업 방식까지 넘기라는 의미다.&lt;br /&gt;다음 세션이 &lt;code&gt;/prototype&lt;/code&gt;으로 이어가야 하는지, 계속 grilling을 해야 하는지, &lt;code&gt;/review&lt;/code&gt;로 검증해야 하는지 알려 주는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Do not duplicate content already captured...&lt;/code&gt;는 handoff 문서가 새로운 진실의 원천이 되는 것을 막는다.&lt;br /&gt;이미 PRD, ADR, issue, diff에 있는 내용은 복사하지 않고 참조만 해야 한다.&lt;br /&gt;그래야 나중에 같은 결정이 여러 문서에서 어긋나지 않는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;영상에서 설명한 맥락&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 &lt;code&gt;/handoff&lt;/code&gt;는 단순한 요약 도구가 아니라 &amp;ldquo;컨텍스트 창을 갈아타는 기술&amp;rdquo;로 설명된다.&lt;br /&gt;Matt가 말한 문제 상황은 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 grilling session이나 planning session을 하고 있다.&lt;br /&gt;이미 6만 토큰 정도를 썼고, 아직 대화의 방향과 긴장감이 살아 있다.&lt;br /&gt;그런데 중간에 코드로만 확인할 수 있는 질문이 생긴다.&lt;br /&gt;예를 들어 상태 모델을 직접 밀어 보거나, 작은 프로토타입을 만들어야 하는 순간이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 원래 세션 안에서 그대로 프로토타입을 만들면 문제가 생긴다.&lt;br /&gt;컨텍스트 창을 더 많이 쓰게 되고, 원래 세션이 하던 일의 집중도도 흐려진다.&lt;br /&gt;설계 검증을 하던 대화가 갑자기 구현 대화로 바뀌고, 다시 돌아왔을 때 이전의 의도와 톤을 잃기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/handoff&lt;/code&gt;는 이 문제를 해결한다.&lt;br /&gt;현재 세션의 내용을 임시 문서로 압축하고, 그 문서를 새 에이전트에게 넘긴다.&lt;br /&gt;새 에이전트는 독립된 컨텍스트 창에서 프로토타입이나 버그 수정을 진행한다.&lt;br /&gt;원래 세션은 계속 planning이나 grilling에 집중할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 특히 강조되는 말은 &amp;ldquo;content만 넘기는 것이 아니라 vibe와 intent도 넘겨야 한다&amp;rdquo;는 점이다.&lt;br /&gt;handoff 문서가 단순 회의록이면 부족하다.&lt;br /&gt;다음 에이전트가 어떤 태도로 이어가야 하는지까지 알아야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 원래 세션이 사용자의 기획을 집요하게 검증하는 grilling session이었다면, handoff 문서에도 그 사실이 들어가야 한다.&lt;br /&gt;그래야 새 세션이 갑자기 친절한 구현 모드로 바뀌지 않는다.&lt;br /&gt;반대로 새 세션의 목적이 &amp;ldquo;이 상태 모델을 터미널 프로토타입으로 확인하는 것&amp;rdquo;이라면, 다음 세션은 &lt;code&gt;/prototype&lt;/code&gt;의 logic branch를 쓰라고 제안해야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 패턴은 fire-and-forget이다.&lt;br /&gt;긴 설계 세션 중에 작은 버그나 별도 작업을 발견했을 때, 지금 흐름을 끊지 않고 새 에이전트에게 넘기는 방식이다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/handoff 현재 planning session은 유지하고, 새 세션에서는 로그인 redirect 버그만 수정할 것&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 handoff 문서는 다음 내용을 담아야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;발견한 버그의 증상&lt;/li&gt;
&lt;li&gt;관련 파일이나 diff&lt;/li&gt;
&lt;li&gt;원래 세션에서 이 작업을 분리하는 이유&lt;/li&gt;
&lt;li&gt;새 세션이 수정 후 남겨야 할 결과&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 패턴은 DIY sub-agent다.&lt;br /&gt;자동 sub-agent를 쓰는 대신, 사용자가 직접 새 터미널과 새 컨텍스트 창을 연다.&lt;br /&gt;이 방식의 장점은 새 에이전트가 자기만의 전체 컨텍스트 창을 쓸 수 있다는 점이다.&lt;br /&gt;또 새 에이전트가 필요하면 다시 sub-agent를 부르거나, 작업을 마친 뒤 원래 세션으로 다시 handoff할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/handoff 다음 세션은 예약 취소 상태 머신을 프로토타입으로 검증하고, 결과만 원래 planning session으로 되돌릴 것&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 작업 흐름이 두 갈래로 나뉜다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;원래 세션은 기획 검증의 흐름을 유지한다.&lt;/li&gt;
&lt;li&gt;새 세션은 프로토타입에만 집중한다.&lt;/li&gt;
&lt;li&gt;새 세션이 얻은 결론을 다시 원래 세션으로 가져온다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 패턴은 handoff back이다.&lt;br /&gt;새 세션에서 프로토타입을 돌려 보고 배운 내용을 다시 원래 맥락으로 돌려주는 것이다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;프로토타입 결과, 예약 취소 상태는 user_cancelled와 system_cancelled를 분리해야 한다.
이 결론을 원래 grilling session으로 handoff하자.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 흐름에서 &lt;code&gt;/handoff&lt;/code&gt;는 단방향 요약이 아니다.&lt;br /&gt;작업 컨텍스트 사이를 오가는 왕복 장치다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;어떻게 활용하나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 planning session 중간에 별도 작업을 분리할 때 쓴다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/handoff 다음 세션은 예약 취소 상태 머신 프로토타입만 다룰 것&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 handoff 문서에는 지금까지의 결정, 아직 남은 질문, 관련 산출물 경로, 다음 세션에서 쓸 스킬 추천이 들어가야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 다음 항목은 빠지면 안 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지금 세션이 어떤 성격이었는지: planning, grilling, implementation, review 등&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;/prototype&lt;/code&gt;: 코드를 버리기 위해 만드는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/prototype&lt;/code&gt;은 본체 &lt;code&gt;SKILL.md&lt;/code&gt;와 branch 설명 파일 두 개로 구성된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;skills/engineering/prototype/SKILL.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;skills/engineering/prototype/LOGIC.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;skills/engineering/prototype/UI.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;prototype/SKILL.md&lt;/code&gt; 원문 발췌&lt;/h3&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;---
name: prototype
description: Build a throwaway prototype to flesh out a design before committing to it. Routes between two branches &amp;mdash; a runnable terminal app for state/business-logic questions, or several radically different UI variations toggleable from one route. Use when the user wants to prototype, sanity-check a data model or state machine, mock up a UI, explore design options, or says &quot;prototype this&quot;, &quot;let me play with it&quot;, &quot;try a few designs&quot;.
---

# Prototype

A prototype is **throwaway code that answers a question**. The question decides the shape.

## Pick a branch

- **&quot;Does this logic / state model feel right?&quot;** &amp;rarr; [LOGIC.md](LOGIC.md). Build a tiny interactive terminal app that pushes the state machine through cases that are hard to reason about on paper.
- **&quot;What should this look like?&quot;** &amp;rarr; [UI.md](UI.md). Generate several radically different UI variations on a single route, switchable via a URL search param and a floating bottom bar.

The two branches produce very different artifacts &amp;mdash; getting this wrong wastes the whole prototype. If the question is genuinely ambiguous and the user isn't reachable, default to whichever branch better matches the surrounding code (a backend module &amp;rarr; logic; a page or component &amp;rarr; UI) and state the assumption at the top of the prototype.

## Rules that apply to both

1. **Throwaway from day one, and clearly marked as such.** Locate the prototype code close to where it will actually be used (next to the module or page it's prototyping for) so context is obvious &amp;mdash; but name it so a casual reader can see it's a prototype, not production. For throwaway UI routes, obey whatever routing convention the project already uses; don't invent a new top-level structure.

...

3. **No persistence by default.** State lives in memory. Persistence is the thing the prototype is _checking_, not something it should depend on. If the question explicitly involves a database, hit a scratch DB or a local file with a clear &quot;PROTOTYPE &amp;mdash; wipe me&quot; name.
4. **Skip the polish.** No tests, no error handling beyond what makes the prototype _runnable_, no abstractions. The point is to learn something fast and then delete it.
5. **Surface the state.** After every action (logic) or on every variant switch (UI), print or render the full relevant state so the user can see what changed.
6. **Delete or absorb when done.** When the prototype has answered its question, either delete it or fold the validated decision into the real code &amp;mdash; don't leave it rotting in the repo.

## When done

The _answer_ is the only thing worth keeping from a prototype. Capture it somewhere durable (commit message, ADR, issue, or a `NOTES.md` next to the prototype) along with the question it was answering. If the user is around, that capture is a quick conversation; if not, leave the placeholder so they (or you, on the next pass) can fill in the verdict before deleting the prototype.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;prototype/SKILL.md&lt;/code&gt; 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 문장은 &lt;code&gt;A prototype is throwaway code that answers a question&lt;/code&gt;이다.&lt;br /&gt;이 스킬은 production code를 만들기 위한 스킬이 아니다.&lt;br /&gt;결정하기 전에 모르는 점을 코드로 확인하기 위한 스킬이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;branch 선택도 핵심이다.&lt;br /&gt;상태 모델이나 비즈니스 로직을 확인하려면 &lt;code&gt;LOGIC.md&lt;/code&gt;로 가고, 화면의 느낌과 정보 구조를 확인하려면 &lt;code&gt;UI.md&lt;/code&gt;로 간다.&lt;br /&gt;이 구분을 틀리면 프로토타입 전체가 낭비된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통 규칙은 모두 같은 실패를 막는다.&lt;br /&gt;AI가 프로토타입을 &amp;ldquo;대충 만든 production code&amp;rdquo;로 오해하는 실패다.&lt;br /&gt;테스트도 조금 있고, 추상화도 조금 있고, 실제 DB도 조금 붙어 있는 코드는 프로토타입이 아니다.&lt;br /&gt;그런 코드는 나중에 버리기 어렵고, 검증되지 않은 설계가 코드베이스에 남는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;The answer is the only thing worth keeping&lt;/code&gt;도 중요하다.&lt;br /&gt;프로토타입에서 남길 것은 코드가 아니라 답이다.&lt;br /&gt;그 답은 commit message, ADR, issue, &lt;code&gt;NOTES.md&lt;/code&gt; 같은 오래 남는 곳에 적어야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;영상에서 설명한 맥락&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 &lt;code&gt;/prototype&lt;/code&gt;은 AI engineering에서 특히 중요한 기술로 설명된다.&lt;br /&gt;이유는 AI agent에게 바로 구현을 맡기기 전에, 우리가 아직 모르는 설계 결정을 먼저 드러내야 하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Matt는 prototype을 research나 spike에 가깝게 본다.&lt;br /&gt;즉 &amp;ldquo;이게 최종 코드가 될 것인가?&amp;rdquo;가 아니라 &amp;ldquo;이 방향으로 가도 되는가?&amp;rdquo;를 확인하기 위한 코드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 표현은 throwaway prototype이다.&lt;br /&gt;프로토타입은 버릴 것을 전제로 만든다.&lt;br /&gt;이 전제가 없으면 AI는 프로토타입을 점점 production code처럼 만들기 시작한다.&lt;br /&gt;테스트를 붙이고, 추상화를 넣고, 데이터베이스를 붙이고, 나중에 확장할 수 있는 구조를 만든다.&lt;br /&gt;그러면 빠르게 배워야 할 코드가 오히려 부담스러운 코드가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 말하는 &lt;code&gt;/prototype&lt;/code&gt;의 좋은 점은 UI에만 갇히지 않는다는 것이다.&lt;br /&gt;사람들은 prototype이라고 하면 보통 화면 mockup을 떠올린다.&lt;br /&gt;하지만 이 스킬은 UI prototype과 logic prototype을 분리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI prototype은 &amp;ldquo;이 화면이 어떻게 보여야 하는가?&amp;rdquo;를 확인한다.&lt;br /&gt;logic prototype은 &amp;ldquo;이 상태나 비즈니스 규칙이 실제 케이스를 버틸 수 있는가?&amp;rdquo;를 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구분은 실제 작업에서 중요하다.&lt;br /&gt;질문이 다른데 같은 형태의 프로토타입을 만들면 잘못된 결론을 얻는다.&lt;br /&gt;상태 모델을 확인해야 하는데 UI만 만들면 예쁘지만 쓸모없는 결과가 나온다.&lt;br /&gt;반대로 화면 밀도를 골라야 하는데 terminal app을 만들면 사용자의 취향과 제품의 느낌을 판단할 수 없다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 사용 사례는 vague concept을 코드로 눌러 보는 것이다.&lt;br /&gt;말로는 대충 알겠지만 실제로 맞는지 모르겠는 설계가 있을 때 쓴다.&lt;/p&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;/prototype 이 알림 설정 모델이 사용자별, 팀별, 프로젝트별 override를 제대로 표현할 수 있는지 확인하고 싶다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 좋은 결과는 &amp;ldquo;코드가 완성됐다&amp;rdquo;가 아니다.&lt;br /&gt;좋은 결과는 &amp;ldquo;project override보다 user override가 우선이어야 한다&amp;rdquo;거나 &amp;ldquo;mute 상태는 별도 상태가 아니라 rule로 계산해야 한다&amp;rdquo; 같은 판단이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 사용 사례는 AFK agent에게 구현을 맡기기 전의 준비다.&lt;br /&gt;영상에서는 front-end를 잘 만들게 하는 가장 좋은 방법 중 하나가 prototyping이라고 말한다.&lt;br /&gt;AI가 화면을 만들 수는 있지만, 무엇이 좋아 보이는지에 대한 취향 판단은 사람이 해줘야 한다.&lt;/p&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;/prototype 대시보드 첫 화면을 3가지 완전히 다른 레이아웃으로 만들어 줘. 내가 하나를 고른 뒤 실제 구현은 그 방향으로 맡길게.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 흐름에서는 prototype session이 design decision을 만든다.&lt;br /&gt;그 다음 implementation session은 이미 정해진 방향을 구현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 사용 사례는 handoff와 연결된다.&lt;br /&gt;긴 planning session 중간에 prototype이 필요해졌다면, 원래 세션에서 바로 만들지 않고 &lt;code&gt;/handoff&lt;/code&gt;로 새 세션을 열어 &lt;code&gt;/prototype&lt;/code&gt;을 실행한다.&lt;/p&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;/handoff 다음 세션은 결제 상태 모델을 logic prototype으로 검증할 것&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 원래 planning session은 흐름을 잃지 않고, prototype session은 독립된 컨텍스트에서 마음껏 실험할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;prototype/LOGIC.md&lt;/code&gt; 원문 발췌&lt;/h3&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;# Logic Prototype

A tiny interactive terminal app that lets the user drive a state model by hand. Use this when the question is about **business logic, state transitions, or data shape** &amp;mdash; the kind of thing that looks reasonable on paper but only feels wrong once you push it through real cases.

## When this is the right shape

- &quot;I'm not sure if this state machine handles the edge case where X then Y.&quot;
- &quot;Does this data model actually let me represent the case where...&quot;
- &quot;I want to feel out what the API should look like before writing it.&quot;
- Anything where the user wants to **press buttons and watch state change**.

If the question is &quot;what should this look like&quot; &amp;mdash; wrong branch. Use [UI.md](UI.md).

## Process

### 1. State the question

Before writing code, write down what state model and what question you're prototyping. One paragraph, in the prototype's README or a comment at the top of the file. A logic prototype that answers the wrong question is pure waste &amp;mdash; make the question explicit so it can be checked later, whether the user is watching now or returning to it AFK.

...

### 3. Isolate the logic in a portable module

Put the actual logic &amp;mdash; the bit that's answering the question &amp;mdash; behind a small, pure interface that could be lifted out and dropped into the real codebase later. The TUI around it is throwaway; the logic module shouldn't be.

The right shape depends on the question:

- **A pure reducer** &amp;mdash; `(state, action) =&amp;gt; state`. Good when actions are discrete events and state is a single value.
- **A state machine** &amp;mdash; explicit states and transitions. Good when &quot;which actions are even legal right now&quot; is part of the question.
- **A small set of pure functions** over a plain data type. Good when there's no implicit current state &amp;mdash; just transformations.
- **A class or module with a clear method surface** when the logic genuinely owns ongoing internal state.

Pick whichever shape best fits the question being asked, *not* whichever is easiest to wire to a TUI. Keep it pure: no I/O, no terminal code, no `console.log` for control flow. The TUI imports it and calls into it; nothing flows the other direction.

This is what makes the prototype useful past its own lifetime. When the question's been answered, the validated reducer / machine / function set can be lifted into the real module &amp;mdash; the TUI shell gets deleted.

### 4. Build the smallest TUI that exposes the state

Build it as a **lightweight TUI** &amp;mdash; on every tick, clear the screen (`console.clear()` / `print(&quot;\033[2J\033[H&quot;)` / equivalent) and re-render the whole frame. The user should always see one stable view, not an ever-growing scrollback.

Behaviour:

2. **Read one keystroke (or one line)** at a time, dispatch to a handler that mutates state.
3. **Re-render** the full frame after every action &amp;mdash; don't append, replace.

...

Give the user the run command. They'll drive it themselves; the interesting moments are when they say &quot;wait, that shouldn't be possible&quot; or &quot;huh, I assumed X would be different&quot; &amp;mdash; those are the bugs in the _idea_, which is the whole point. If they want new actions added, add them. Prototypes evolve.

## Anti-patterns

- **Don't generalise.** No &quot;what if we wanted to support X later.&quot; The prototype answers one question.
- **Don't blur the logic and the TUI together.** If the reducer / state machine references `console.log`, prompts, or terminal escape codes, it's no longer portable. Keep the TUI as a thin shell over a pure module.
- **Don't ship the TUI shell into production.** The shell is optimised for being driven by hand from a terminal. The logic module behind it is the bit worth keeping.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;prototype/LOGIC.md&lt;/code&gt; 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;logic prototype은 상태 모델을 손으로 밀어 보는 도구다.&lt;br /&gt;문서로는 그럴듯하지만 실제 케이스를 넣어 보면 이상해지는 문제에 잘 맞는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 결제 상태가 있다고 하자.&lt;/p&gt;
&lt;pre class=&quot;xl&quot;&gt;&lt;code&gt;Created -&amp;gt; Authorized -&amp;gt; Captured -&amp;gt; Refunded&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서로는 단순하지만, 직접 눌러 보면 질문이 생긴다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부분 환불은 어떤 상태인가?&lt;/li&gt;
&lt;li&gt;capture 전에 취소하면 무엇이 되는가?&lt;/li&gt;
&lt;li&gt;실패한 capture는 다시 시도할 수 있는가?&lt;/li&gt;
&lt;li&gt;user cancellation과 system cancellation은 같은가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Isolate the logic in a portable module&lt;/code&gt;은 이 파일에서 가장 중요한 지시다.&lt;br /&gt;TUI는 버릴 껍데기지만, 검증된 reducer나 state machine은 실제 코드로 옮길 수 있어야 한다.&lt;br /&gt;그래서 로직 안에 &lt;code&gt;console.log&lt;/code&gt;, prompt, terminal escape code가 들어가면 안 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 logic prototype은 &amp;ldquo;paper에서는 멀쩡해 보이지만 실제 케이스를 밀어 넣으면 이상해지는 것&amp;rdquo;을 찾기 위한 도구로 설명된다.&lt;br /&gt;상태가 시간에 따라 변하고, 사용자의 행동에 따라 엔티티가 바뀌는 경우가 대표적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 데이터베이스 안의 주문, 예약, 결제, 티켓, 세션 같은 엔티티는 대부분 상태를 가진다.&lt;br /&gt;처음에는 &lt;code&gt;pending&lt;/code&gt;, &lt;code&gt;confirmed&lt;/code&gt;, &lt;code&gt;cancelled&lt;/code&gt; 정도면 충분해 보인다.&lt;br /&gt;하지만 실제 액션을 넣어 보면 문제가 나온다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결제는 성공했는데 예약 확정이 실패하면?&lt;/li&gt;
&lt;li&gt;사용자가 취소했는지 시스템이 취소했는지 구분해야 하면?&lt;/li&gt;
&lt;li&gt;부분 취소나 부분 환불이 가능하면?&lt;/li&gt;
&lt;li&gt;관리자 override가 들어오면 기존 상태 전이를 건너뛰어도 되는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 질문은 문서만 보고는 잘 드러나지 않는다.&lt;br /&gt;terminal app에서 직접 키를 눌러 상태를 바꿔 보면 &amp;ldquo;이 액션이 이 상태에서 가능하면 안 되는데?&amp;rdquo; 같은 순간이 나온다.&lt;br /&gt;영상에서 말한 것처럼, 바로 그 순간이 아이디어의 버그를 발견하는 순간이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;logic prototype을 쓸 때는 처음부터 질문을 좁혀야 한다.&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;Question: 이 예약 상태 모델은 결제 실패, 사용자 취소, 시스템 만료, 관리자 강제 확정을 모호함 없이 표현할 수 있는가?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문이 이렇게 좁혀지면 prototype의 범위도 자연스럽게 정해진다.&lt;br /&gt;멋진 UI도 필요 없고, 실제 DB도 필요 없다.&lt;br /&gt;사용자가 액션을 누르고 상태가 바뀌는 것을 보면 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;prototype/UI.md&lt;/code&gt; 원문 발췌&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# UI Prototype

Generate **several radically different UI variations** on a single route, switchable from a floating bottom bar. The user flips between variants in the browser, picks one (or steals bits from each), then throws the rest away.

If the question is about logic/state rather than what something looks like &amp;mdash; wrong branch. Use [LOGIC.md](LOGIC.md).

## Two sub-shapes &amp;mdash; strongly prefer sub-shape A

A UI prototype is much easier to judge when it's **butting up against the rest of the app** &amp;mdash; real header, real sidebar, real data, real density. A throwaway route on its own is a vacuum: every variant looks fine in isolation. Default to sub-shape A whenever there's a plausible existing page to host the variants. Only reach for sub-shape B if the prototype genuinely has no nearby home.

### Sub-shape A &amp;mdash; adjustment to an existing page (preferred)

The route already exists. Variants are rendered **on the same route**, gated by a `?variant=` URL search param. The existing data fetching, params, and auth all stay &amp;mdash; only the rendering swaps. This is the default; pick it unless there's a specific reason not to.

...

## Process

### 1. State the question and pick N

Default to **3 variants**. More than 5 stops being radically different and starts being noise &amp;mdash; cap there.

### 2. Generate radically different variants

Variants must be **structurally different** &amp;mdash; different layout, different information hierarchy, different primary affordance, not just different colours. Three slightly-tweaked card grids isn't a UI prototype, it's wallpaper. If two drafts come out too similar, redo one with explicit &quot;do not use a card grid&quot; guidance.

### 3. Wire them together

Create a single switcher component on the route:

```tsx
// pseudo-code &amp;mdash; adapt to the project's framework
const variant = searchParams.get('variant') ?? 'A';
return (
  &amp;lt;&amp;gt;
    {variant === 'A' &amp;amp;&amp;amp; &amp;lt;VariantA {...data} /&amp;gt;}
    {variant === 'B' &amp;amp;&amp;amp; &amp;lt;VariantB {...data} /&amp;gt;}
    {variant === 'C' &amp;amp;&amp;amp; &amp;lt;VariantC {...data} /&amp;gt;}
    &amp;lt;PrototypeSwitcher variants={['A','B','C']} current={variant} /&amp;gt;
  &amp;lt;/&amp;gt;
);
```

For sub-shape A (existing page): keep all the existing data fetching above the switcher; only the rendered subtree changes per variant.

### 4. Build the floating switcher

Behaviour:

- Clicking an arrow updates the URL search param (use the framework's router &amp;mdash; `router.replace` on Next, `navigate` on React Router, etc) so the variant is shareable and reload-stable.
- Hidden in production builds &amp;mdash; gate on `process.env.NODE_ENV !== 'production'` or an equivalent check, so a stray prototype merge can't ship the bar to users.

### 5. Hand it over

Surface the URL (and the `?variant=` keys). The user will flip through whenever they get to it. The interesting feedback is usually **&quot;I want the header from B with the sidebar from C&quot;** &amp;mdash; that's the actual design they want.

### 6. Capture the answer and clean up

Once a variant has won, write down which one and why (commit message, ADR, issue, or a `NOTES.md` next to the prototype if running AFK and the user hasn't responded yet). Then:

- **Sub-shape A** &amp;mdash; delete the losing variants and the switcher; fold the winner into the existing page.

## Anti-patterns

- **Variants that differ only in colour or copy.** That's a tweak, not a prototype. Real variants disagree about structure.
- **Promoting the prototype directly to production.** The variant code was written under prototype constraints (no tests, minimal error handling). Rewrite it properly when you fold it in.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;prototype/UI.md&lt;/code&gt; 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI prototype의 핵심은 &lt;code&gt;radically different UI variations&lt;/code&gt;다.&lt;br /&gt;색만 다른 세 개의 카드 UI를 만드는 것이 아니다.&lt;br /&gt;정보 구조, 레이아웃, 주요 액션의 위치가 달라야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 중요한 문장은 &lt;code&gt;butting up against the rest of the app&lt;/code&gt;이다.&lt;br /&gt;빈 페이지에 UI를 만들면 대부분 그럴듯해 보인다.&lt;br /&gt;하지만 실제 앱의 header, sidebar, auth, data fetching, 화면 밀도와 부딪히면 문제가 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;?variant=&lt;/code&gt;를 쓰는 이유도 실용적이다.&lt;br /&gt;variant가 reload-stable하고 shareable해진다.&lt;br /&gt;그리고 floating switcher를 production build에서 숨기라는 지시는 프로토타입 장치가 사용자에게 노출되는 사고를 막는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 UI prototype은 사람이 taste를 적용하기 위한 장치로 설명된다.&lt;br /&gt;AI agent는 화면을 만들 수 있지만, 무엇이 좋은 화면인지 판단하는 능력은 제품의 맥락과 사람의 취향에 크게 의존한다.&lt;br /&gt;그래서 사람이 중간에 앉아 variant를 직접 보고 고르는 과정이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 영상에서는 &amp;ldquo;A안의 어떤 부분과 B안의 어떤 부분을 섞는다&amp;rdquo;는 흐름이 나온다.&lt;br /&gt;이게 UI prototype의 실제 가치다.&lt;br /&gt;세 가지 안 중 하나를 그대로 고르는 것이 아니라, 여러 variant를 보면서 디자인 트리를 내려간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 설정 화면을 만든다고 하자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A안은 정보 밀도가 좋다.&lt;/li&gt;
&lt;li&gt;B안은 sidebar 구조가 좋다.&lt;/li&gt;
&lt;li&gt;C안은 header action 배치가 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 최종 결정은 &amp;ldquo;B안으로 간다&amp;rdquo;가 아닐 수 있다.&lt;br /&gt;&amp;ldquo;B안의 sidebar를 쓰고, A안의 정보 밀도를 가져오고, C안의 header action을 섞는다&amp;rdquo;가 더 좋은 결론일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 판단은 AFK agent 혼자 하기 어렵다.&lt;br /&gt;그래서 prototype은 구현 전의 human-in-the-loop design session이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI prototype을 요청할 때는 다음처럼 말하는 편이 좋다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;/prototype 기존 /settings 화면 안에서 알림 설정 UI를 3가지 variant로 보여 줘.
각 variant는 정보 구조가 달라야 하고, 단순 색상 차이는 피했으면 좋겠다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 피드백은 다음처럼 구체적이어야 한다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;B안의 왼쪽 탐색 구조는 좋다.
하지만 A안처럼 각 설정의 현재 상태가 한눈에 보여야 한다.
C안의 저장 버튼 위치는 유지하자.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정도까지 결정되면 이후 구현 에이전트는 훨씬 명확한 방향을 갖고 작업할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;/writing&lt;/code&gt;: fragments, beats, shape로 나누는 글쓰기 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서는 이 묶음을 tripart writing skill이라고 설명한다.&lt;br /&gt;저장소에서는 세 개의 in-progress 스킬로 나뉜다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;skills/in-progress/writing-fragments/SKILL.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;skills/in-progress/writing-beats/SKILL.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;skills/in-progress/writing-shape/SKILL.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 이 묶음은 아직 완성된 도구라기보다 실험 중인 글쓰기 workflow로 소개된다.&lt;br /&gt;목표는 &amp;ldquo;AI로 좋은 글을 쓰는 과정&amp;rdquo;을 세 단계로 쪼개는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째는 fragments다.&lt;br /&gt;아직 글의 구조를 정하지 않고, 나중에 글에 들어갈 수 있는 문장, 주장, 장면, 불평, 농담, 반쯤 떠오른 생각을 모은다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 beats다.&lt;br /&gt;모아 둔 fragments 중에서 어떤 길로 글을 전개할지 고른다.&lt;br /&gt;한 번에 전체 글을 쓰지 않고, 다음에 갈 수 있는 방향을 몇 개 제안하고 사용자가 고른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째는 shape다.&lt;br /&gt;이미 있는 재료와 흐름을 바탕으로 최종 글의 형태를 잡는다.&lt;br /&gt;어떤 문단이 필요한지, 리스트가 나은지, 표가 나은지, 문장이 AI처럼 들리지는 않는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조의 핵심은 AI가 처음부터 완성본을 쓰지 못하게 막는 것이다.&lt;br /&gt;좋은 글은 보통 처음부터 목차와 결론이 정해져서 나오지 않는다.&lt;br /&gt;흩어진 관찰이 쌓이고, 그중 일부가 경로를 만들고, 마지막에 독자가 읽을 수 있는 모양으로 정리된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;writing-fragments/SKILL.md&lt;/code&gt; 원문 발췌&lt;/h3&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;---
name: writing-fragments
description: Grilling session that mines the user for fragments &amp;mdash; heterogeneous nuggets of writing (claims, vignettes, sharp sentences, half-thoughts) &amp;mdash; and appends them to a single document as raw material for a future article. Use when the user wants to develop ideas before imposing structure, or mentions &quot;fragments&quot;, &quot;ideate&quot;, or &quot;raw material&quot; for writing.
---

&amp;lt;what-to-do&amp;gt;

Run a grilling session that produces fragments. Interview the user relentlessly about whatever they want to write about. Do not impose phases, outlines, or structure &amp;mdash; that is explicitly out of scope.

As fragments emerge from either side of the conversation, append them to a single markdown file. The user will be editing this file during the session; always re-read it before writing so their edits are preserved.

Capture fragments from the very first thing the user says, including the initial prompt.

&amp;lt;/what-to-do&amp;gt;

&amp;lt;supporting-info&amp;gt;

## What is a fragment

A fragment is any piece of text that might survive into the final article. It must be _readable by the author_ &amp;mdash; the author can tell what it means &amp;mdash; but it does not need to define its terms or be comprehensible to a cold reader. The bar is &quot;is this a piece of good writing?&quot;, not &quot;is this a self-contained argument?&quot;

Fragments are deliberately heterogeneous. Examples of what could be a fragment:

- A sharp sentence you'd want to deploy somewhere but don't yet know where.
- A claim with a one-line justification.
- A vignette: a thing that happened, a code snippet, a scenario, an analogy.
- A half-thought: &quot;something about how X feels like Y, work this out later.&quot;
- A quote, a piece of dialogue, an overheard line.
- A list of related observations that hang together by feel.
- A complaint, a confession, a punchline.

The novelist's diary is the model: years of unstructured noticings that later get mined for raw material. Fragments are noticings.

## File format

Fragments are separated by a horizontal rule (`\n---\n`). No headings inside the body. No tags. No order beyond the order they were added.

## Writing rhythm

Before every write: re-read the file from disk. The user may have edited, reordered, or deleted fragments between turns &amp;mdash; preserve their changes. Never overwrite the file; only append (or, if the user asks, edit a specific fragment in place).

The user can say &quot;cut the last one&quot;, &quot;rewrite that one sharper&quot;, &quot;merge those two&quot; at any time. Treat those as first-class instructions.

&amp;lt;/supporting-info&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;writing-fragments&lt;/code&gt; 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 AI가 너무 빨리 구조화하는 문제를 막는다.&lt;br /&gt;초기 단계에서는 outline, phase, structure를 만들지 않는다.&lt;br /&gt;대신 최종 글에 살아남을 수 있는 fragment를 모은다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;fragment&lt;/code&gt;는 cold reader에게 완전히 이해될 필요가 없다.&lt;br /&gt;작성자가 나중에 알아보고 쓸 수 있으면 된다.&lt;br /&gt;이 기준이 중요한 이유는 아직 독자를 설득하는 단계가 아니라 재료를 모으는 단계이기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;what-to-do&amp;gt;&lt;/code&gt;와 &lt;code&gt;&amp;lt;supporting-info&amp;gt;&lt;/code&gt;를 나눈 것도 눈에 띈다.&lt;br /&gt;실제로 해야 할 지시는 위에 두고, fragment의 정의와 파일 포맷은 supporting info로 낮춘다.&lt;br /&gt;prompt 안에서 우선순위를 분리하는 구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서는 fragments를 작가의 긴 journal에 비유한다.&lt;br /&gt;작가들은 몇 년 동안 일기나 노트에 관찰, 장면, 문장, 대화, 사적인 생각을 쌓아 둔다.&lt;br /&gt;그 조각들이 나중에 거의 원형 그대로 이야기나 글에 들어가기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;writing-fragments&lt;/code&gt;는 AI를 그 journal을 같이 쓰는 상대로 만든다.&lt;br /&gt;사용자는 생각을 대충 말하거나 받아쓰기하고, AI는 그 안에서 나중에 살아남을 만한 조각을 뽑아 markdown 파일에 쌓는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 단계에서 중요한 것은 정리하지 않는 것이다.&lt;br /&gt;너무 빨리 구조를 만들면 생각이 작아진다.&lt;br /&gt;예를 들어 &amp;ldquo;AI agent를 잘 쓰는 법&amp;rdquo;에 대해 쓰고 싶다고 했을 때, 바로 다음과 같은 목차를 만들면 글이 평범해질 가능성이 높다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. AI agent란 무엇인가
2. AI agent의 장점
3. AI agent 사용 팁
4. 결론&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fragments 단계에서는 이런 목차를 만들지 않는다.&lt;br /&gt;대신 다음처럼 살아 있는 조각을 모은다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;AI agent를 잘 쓰는 사람은 명령을 잘하는 사람이 아니라, 작업을 잘게 나누는 사람이다.

컨텍스트 창은 메모리가 아니라 작업실에 가깝다. 한 작업실에서 모든 일을 하려 하면 금방 어질러진다.

프로토타입은 코드를 남기기 위해서가 아니라, 결정을 남기기 위해서 만든다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 조각들은 아직 서로 연결되어 있지 않아도 된다.&lt;br /&gt;중요한 것은 나중에 글에 들어갈 수 있는 밀도를 가진 문장을 확보하는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;writing-beats/SKILL.md&lt;/code&gt; 원문 발췌&lt;/h3&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;---
name: writing-beats
description: Shape an article as a journey of beats, choose-your-own-adventure style. The user picks a starting beat from the raw material, you write only that beat, then offer options for where to pivot next, beat by beat, until the article reaches a natural end. Use when the user has raw material and wants to assemble it as a narrative rather than an argument.
---

&amp;lt;what-to-do&amp;gt;

Then run a beat-by-beat journey:

1. Write 2&amp;ndash;3 candidate **starting beats**, drawn from the raw material. Each is a different entry point into the article. Show the user the beats before writing it to the article file. The user picks one. Preview what beats that might lead to once written - as if the user is seeing a little way down the path.
2. Once the user picks a starting beat, write **only that beat** to the article file. A beat may be one sentence or several paragraphs &amp;mdash; whatever that beat naturally is. Stop there.
3. Re-read the article file from disk. Then offer 2&amp;ndash;3 candidate **next beats** &amp;mdash; different directions the journey could pivot to from where the article now stands.
4. Loop steps 2&amp;ndash;4 until the article reaches a natural end.

&amp;lt;/what-to-do&amp;gt;

&amp;lt;supporting-info&amp;gt;

## What is a beat

A beat is one move in the journey. It does one thing &amp;mdash; sets a scene, lands a point, asks a question, drops an aside, twists the angle. Then it stops, leaving the reader at a place where the next beat can pivot.

If a &quot;beat&quot; needs five paragraphs and three subheadings, it's not a beat &amp;mdash; it's two beats glued together. Split it.

## Writing one beat

Once a beat is picked, write _that beat only_ to the article file. Do not write the next beat.

## Ending the journey

The article ends when the journey is complete &amp;mdash; not when the pile is empty. Most piles will have leftover fragments that don't make it in. That is fine; that is the point of having more raw material than you need.

## Writing rhythm

- Append one beat at a time. Never write ahead.
- If the user edits a previous beat substantially, let it change what comes next.

&amp;lt;/supporting-info&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;writing-beats&lt;/code&gt; 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 AI가 한 번에 전체 글을 쏟아내는 문제를 막는다.&lt;br /&gt;사용자는 starting beat를 고르고, agent는 그 beat만 쓴 뒤 멈춘다.&lt;br /&gt;그 다음 다음 beat 후보를 다시 제안한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 &lt;code&gt;write only that beat&lt;/code&gt;다.&lt;br /&gt;멈춰야 사용자가 개입할 수 있다.&lt;br /&gt;AI가 글의 다음 방향까지 마음대로 써 버리면 choose-your-own-adventure 구조가 사라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 중요한 문장은 &lt;code&gt;The article ends when the journey is complete &amp;mdash; not when the pile is empty&lt;/code&gt;다.&lt;br /&gt;raw material을 다 쓰는 것이 목표가 아니다.&lt;br /&gt;글의 여정이 끝나면 남는 fragment가 있어도 끝내야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 beats는 &amp;ldquo;많은 가능한 경로 중 하나를 찾아가는 과정&amp;rdquo;으로 설명된다.&lt;br /&gt;fragments가 충분히 쌓이면, 그 조각들을 모두 쓰는 것이 문제가 아니다.&lt;br /&gt;어떤 순서로 독자를 데려갈 것인지가 문제가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 AI가 한 번에 전체 초안을 써 버리면 사용자는 중간 경로를 고를 기회를 잃는다.&lt;br /&gt;문장은 매끄러울 수 있지만, 글의 방향이 사용자의 감각과 달라질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;writing-beats&lt;/code&gt;는 이 문제를 줄인다.&lt;br /&gt;먼저 시작점 후보를 2-3개 보여 준다.&lt;br /&gt;사용자가 하나를 고르면 그 beat만 쓴다.&lt;br /&gt;그 다음 다시 현재 글을 읽고, 다음에 갈 수 있는 후보를 2-3개 보여 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이 글을 beats로 만든다면 시작점 후보는 이렇게 나올 수 있다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Beat A: skills 저장소가 7만 스타를 넘긴 현상에서 시작한다.
Beat B: handoff라는 작은 스킬이 왜 컨텍스트 관리의 핵심인지에서 시작한다.
Beat C: AI agent를 잘 쓰는 핵심은 더 긴 프롬프트가 아니라 작업 단위 설계라는 주장으로 시작한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 Beat B를 고르면 글은 handoff에서 출발한다.&lt;br /&gt;그러면 다음 beat 후보는 prototype으로 넘어갈 수도 있고, context window 문제를 더 파고들 수도 있고, DIY sub-agent 패턴으로 갈 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식의 장점은 사용자가 글의 방향을 계속 선택한다는 점이다.&lt;br /&gt;AI는 문장을 생산하지만, 글의 여정은 사용자가 고른다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;writing-shape/SKILL.md&lt;/code&gt; 원문 발췌&lt;/h3&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;---
name: writing-shape
description: Take a markdown file of raw material and shape it into an article through a conversational session &amp;mdash; drafting candidate openings, growing the piece paragraph by paragraph, arguing about format (lists, tables, callouts, quotes) at each step. Use when the user has a pile of notes, fragments, or a rough draft and wants help turning it into something publishable.
---

&amp;lt;what-to-do&amp;gt;

The user has passed (or will pass) a markdown file of raw material. Treat it as the input pile &amp;mdash; anything from a tidy list of fragments to a wall of unstructured prose to a transcript. The format does not matter. Read it end-to-end before doing anything else.

Then run a shaping session that produces a separate article document. Do not edit the raw material file &amp;mdash; it is read-only to this skill.

&amp;lt;/what-to-do&amp;gt;

&amp;lt;supporting-info&amp;gt;

## The loop

1. **Read the pile.** Read the input file in full. Form a sense of what's in it.
2. **Draft 2&amp;ndash;3 candidate openings.** Each opening should imply a different thesis or angle for the article. Show all of them. Force the user to pick or compose a hybrid. The chosen opening defines what the rest of the article must do.
3. **Grow paragraph by paragraph.** After the opening lands, ask &quot;given this opening, what does the reader need to hear next?&quot; Pull material from the pile to answer. Argue about whether the next beat is a paragraph, a list, a table, a callout, a quote, a code block. Each format choice should be deliberate and defensible.

## Conversational feel

This is a grilling session inverted. In ideation, the question was &quot;what are you actually noticing?&quot; Here it's &quot;what is this article actually arguing, and in what order does the reader need to hear it?&quot; Push back. Refuse to let weak transitions slide. If a paragraph doesn't earn its place, cut it.

Specific moves to keep using:

- &quot;What does this paragraph do for the reader that the previous one didn't?&quot;
- &quot;If I cut this, what breaks?&quot;
- &quot;Is this prose, or should it be a list? Why prose?&quot;
- &quot;This sentence is doing two jobs &amp;mdash; split it or pick one.&quot;
- &quot;The opening promised X. We've drifted to Y. Either re-thread it or change the opening.&quot;

## Pulling from the pile

Treat the raw material as a quarry, not a script. Pull a fragment, rework it to fit the surrounding paragraph, and place it. A fragment may be split across multiple paragraphs, merged with another, or paraphrased. The pile's job is to be mined; the article's job is to read as one voice.

## Format arguments to actually have

When choosing how to render a beat, weigh these tradeoffs out loud with the user, not silently:

- **Prose vs. list.** Prose carries argument; lists carry parallel items. If items aren't truly parallel, prose is better. If they are, a list is faster to scan.
- **Table vs. repeated structure.** If the same shape repeats 3+ times with the same fields, a table. Otherwise prose with bold leads.
- **Quote vs. paraphrase.** Quote when the original wording is the point. Paraphrase when only the idea matters.
- **Code block vs. inline code.** Multi-line, runnable, or illustrative &amp;rarr; block. Single token or identifier &amp;rarr; inline.

## Out of scope

- Editing the raw material file.

&amp;lt;/supporting-info&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;writing-shape&lt;/code&gt; 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;writing-shape&lt;/code&gt;는 글쓰기의 마지막 단계에 가깝다.&lt;br /&gt;raw material file은 읽기만 하고, 별도의 article document를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬의 핵심은 opening을 먼저 고르게 하는 것이다.&lt;br /&gt;opening은 글의 thesis나 angle을 암시한다.&lt;br /&gt;한 번 opening을 고르면, 그 이후 글은 그 opening이 만든 약속을 지켜야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형식 선택을 조용히 처리하지 말라는 지시도 좋다.&lt;br /&gt;prose, list, table, callout, quote, code block은 단순한 꾸밈이 아니다.&lt;br /&gt;형식은 글의 논증 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서는 writing shape를 final pass에 가까운 과정으로 설명한다.&lt;br /&gt;글이 너무 AI처럼 들리지 않는지, 구조가 맞는지, 전체 흐름이 제대로 잡혔는지 다시 보는 단계다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬이 흥미로운 이유는 &amp;ldquo;글을 다듬는다&amp;rdquo;를 단순 문장 교정으로 보지 않는다는 점이다.&lt;br /&gt;문단 하나하나가 글에서 어떤 일을 하는지 묻는다.&lt;br /&gt;이 문단이 앞 문단이 하지 못한 일을 하는가?&lt;br /&gt;없애면 무엇이 깨지는가?&lt;br /&gt;opening이 약속한 주장에서 벗어나지는 않았는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 형식 선택을 대화의 주제로 끌어올린다.&lt;br /&gt;AI는 종종 비교가 나오면 표를 만들고, 항목이 나오면 리스트를 만든다.&lt;br /&gt;하지만 좋은 글에서는 형식이 자동으로 정해지면 안 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 다음 둘은 같은 내용을 전혀 다르게 전달한다.&lt;/p&gt;
&lt;pre class=&quot;mercury&quot;&gt;&lt;code&gt;Prose:
handoff는 단순 요약이 아니라 작업의 의도를 넘긴다. 그래서 다음 에이전트는 무엇을 해야 하는지만이 아니라 어떤 태도로 이어가야 하는지도 알게 된다.

List:
- handoff는 내용을 넘긴다.
- handoff는 의도를 넘긴다.
- handoff는 다음 세션에서 쓸 스킬을 제안한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;prose는 주장을 밀고 가는 데 좋고, list는 병렬 항목을 빠르게 보여 주는 데 좋다.&lt;br /&gt;어느 쪽이 좋은지는 문맥에 따라 다르다.&lt;br /&gt;&lt;code&gt;writing-shape&lt;/code&gt;는 이 판단을 AI가 혼자 하지 못하게 하고, 사용자와 함께 결정하게 만든다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;/writing&lt;/code&gt; 계열 사용 사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 생각이 흩어져 있으면 &lt;code&gt;writing-fragments&lt;/code&gt;부터 쓴다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;/writing-fragments drafts/agent-skills/fragments.md&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 조각은 많고 글의 경로를 찾고 싶으면 &lt;code&gt;writing-beats&lt;/code&gt;를 쓴다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;/writing-beats fragments.md -&amp;gt; index.md&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초안이나 raw material이 있고 게시 가능한 글로 만들고 싶으면 &lt;code&gt;writing-shape&lt;/code&gt;를 쓴다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;/writing-shape memo.md -&amp;gt; index.md&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 스킬은 이어서 써도 되고, 따로 써도 된다.&lt;br /&gt;이미 fragments가 충분하다면 beats부터 시작할 수 있다.&lt;br /&gt;이미 대략의 초안이 있다면 shape만 써도 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;/review&lt;/code&gt;: Standards와 Spec을 분리해서 보는 코드 리뷰 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문 경로: &lt;code&gt;skills/in-progress/review/SKILL.md&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해석에 필요한 원문 발췌는 다음이다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;---
name: review
description: Review the changes since a fixed point (commit, branch, tag, or merge-base) along two axes &amp;mdash; Standards (does the code follow this repo's documented coding standards?) and Spec (does the code match what the originating issue/PRD asked for?). Runs both reviews in parallel sub-agents and reports them side by side. Use when the user wants to review a branch, a PR, work-in-progress changes, or asks to &quot;review since X&quot;.
---

# Review

Two-axis review of the diff between `HEAD` and a fixed point the user supplies:

- **Standards** &amp;mdash; does the code conform to this repo's documented coding standards?
- **Spec** &amp;mdash; does the code faithfully implement the originating issue / PRD / spec?

Both axes run as **parallel sub-agents** so they don't pollute each other's context, then this skill aggregates their findings.

## Process

### 1. Pin the fixed point

Whatever the user said is the fixed point &amp;mdash; a commit SHA, branch name, tag, `main`, `HEAD~5`, etc. Don't be opinionated; pass it through. If they didn't specify one, ask: &quot;Review against what &amp;mdash; a branch, a commit, or `main`?&quot; Don't proceed until you have it.

Capture the diff command once: `git diff &amp;lt;fixed-point&amp;gt;...HEAD` (three-dot, so the comparison is against the merge-base). Also note the list of commits via `git log &amp;lt;fixed-point&amp;gt;..HEAD --oneline`.

### 2. Identify the spec source

Look for the originating spec, in this order:

...

3. A PRD/spec file under `docs/`, `specs/`, or `.scratch/` matching the branch name or feature.
4. If nothing is found, ask the user where the spec is. If they say there isn't one, the **Spec** sub-agent will skip and report &quot;no spec available&quot;.

### 3. Identify the standards sources

Anything in the repo that documents how code should be written. Common locations:

- `CLAUDE.md`, `AGENTS.md`
- `CONTRIBUTING.md`
- `docs/adr/` (architectural decisions are standards)
- `.editorconfig`, `eslint.config.*`, `biome.json`, `prettier.config.*`, `tsconfig.json` (machine-enforced standards &amp;mdash; note them but don't re-check what tooling already checks)

Collect the list of files. The **Standards** sub-agent will read them.

### 4. Spawn both sub-agents in parallel

**Standards sub-agent prompt** &amp;mdash; include:

- The brief: &quot;Read the standards docs. Then read the diff. Report &amp;mdash; per file/hunk where relevant &amp;mdash; every place the diff violates a documented standard. Cite the standard (file + the rule). Distinguish hard violations from judgement calls. Skip anything tooling enforces. Under 400 words.&quot;

**Spec sub-agent prompt** &amp;mdash; include:

- The brief: &quot;Read the spec. Then read the diff. Report: (a) requirements the spec asked for that are missing or partial; (b) behaviour in the diff that wasn't asked for (scope creep); (c) requirements that look implemented but where the implementation looks wrong. Quote the spec line for each finding. Under 400 words.&quot;

### 5. Aggregate

Present the two reports under `## Standards` and `## Spec` headings, verbatim or lightly cleaned. Do **not** merge or rerank findings &amp;mdash; the two axes are deliberately separate so the user can see them independently.

End with a one-line summary: total findings per axis, and the worst single issue (if any) flagged.

## Why two axes

A change can pass one axis and fail the other:

- Code that follows every standard but implements the wrong thing &amp;rarr; **Standards pass, Spec fail.**
- Code that does exactly what the issue asked but breaks the project's conventions &amp;rarr; **Spec pass, Standards fail.**

Reporting them separately stops one axis from masking the other.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;review&lt;/code&gt; 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬의 핵심은 코드 리뷰를 두 축으로 분리하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 축은 &lt;code&gt;Standards&lt;/code&gt;다.&lt;br /&gt;이 코드는 저장소의 문서화된 기준을 따르는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 축은 &lt;code&gt;Spec&lt;/code&gt;이다.&lt;br /&gt;이 코드는 원래 issue, PRD, spec이 요구한 것을 구현했는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 둘은 다른 질문이다.&lt;br /&gt;코드가 깔끔해도 요구사항을 잘못 구현할 수 있다.&lt;br /&gt;반대로 요구사항은 맞췄지만 프로젝트의 설계 규칙을 깨뜨릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 원문은 두 sub-agent를 병렬로 실행하라고 한다.&lt;br /&gt;각각 다른 렌즈로 diff를 보고, 마지막에만 side by side로 합친다.&lt;br /&gt;그리고 결과를 merge하거나 rerank하지 말라고 한다.&lt;br /&gt;두 축이 섞이면 한쪽의 성공이 다른 쪽의 실패를 가릴 수 있기 때문이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;영상에서 설명한 맥락&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상에서 &lt;code&gt;/review&lt;/code&gt;는 많은 사람이 기다렸지만 만들기 어려웠던 스킬로 소개된다.&lt;br /&gt;generic code review skill이 어려운 이유는 모든 저장소의 기준이 다르기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 팀은 작은 함수와 명시적인 타입을 선호한다.&lt;br /&gt;어떤 팀은 프레임워크 convention을 강하게 따른다.&lt;br /&gt;어떤 팀은 ADR로 의존 방향을 제한한다.&lt;br /&gt;어떤 팀은 테스트 구조나 파일 배치에 강한 규칙을 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 단순히 &amp;ldquo;코드 리뷰해 줘&amp;rdquo;라고 하면 리뷰가 너무 일반적이 된다.&lt;br /&gt;AI가 자기 기준으로 코드를 평가하기 쉽다.&lt;br /&gt;하지만 좋은 리뷰는 해당 repo의 standards를 기준으로 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동시에 standards만 보면 빠지는 것이 있다.&lt;br /&gt;코드가 저장소 기준을 잘 지켜도 원래 issue나 PRD가 요구한 것을 놓칠 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 spec만 보면 다른 문제가 생긴다.&lt;br /&gt;요구사항은 맞췄지만 repo의 구조적 기준을 깨뜨릴 수 있다.&lt;br /&gt;예를 들어 기존 아키텍처에서는 UI layer가 data access layer를 직접 호출하면 안 되는데, spec에는 그 규칙이 적혀 있지 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 영상에서는 두 축을 병렬로 본다고 설명한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Standards: diff가 repo의 coding standards를 따르는가?&lt;/li&gt;
&lt;li&gt;Spec: diff가 원래 issue나 PRD를 충실히 구현했는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구분이 &lt;code&gt;/review&lt;/code&gt;의 핵심이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 사용 사례는 PR을 올리기 전 자체 리뷰다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/review main&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 요청은 현재 브랜치와 &lt;code&gt;main&lt;/code&gt;의 merge-base 이후 diff를 대상으로 리뷰하라는 뜻이다.&lt;br /&gt;결과는 standards와 spec으로 분리되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 사용 사례는 AFK agent가 만든 변경을 검증하는 것이다.&lt;br /&gt;AI agent가 issue를 구현한 뒤, 사람이 바로 코드를 읽기 전에 &lt;code&gt;/review&lt;/code&gt;로 두 축을 먼저 확인할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/review origin/main&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 standards 쪽에서는 다음을 볼 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;에 적힌 작업 규칙을 어겼는가?&lt;/li&gt;
&lt;li&gt;ADR의 의존 방향을 깨뜨렸는가?&lt;/li&gt;
&lt;li&gt;repo의 테스트 배치나 파일 구조 convention을 벗어났는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spec 쪽에서는 다음을 본다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;issue가 요구한 empty state가 빠졌는가?&lt;/li&gt;
&lt;li&gt;PRD에 있던 edge case가 구현되지 않았는가?&lt;/li&gt;
&lt;li&gt;요구하지 않은 설정이나 동작이 추가되었는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 사용 사례는 큰 refactor 이후의 안전 확인이다.&lt;br /&gt;refactor는 기능 요구사항보다 standards 축에서 문제가 많이 나온다.&lt;br /&gt;동작은 그대로지만 repo convention이나 모듈 경계를 깨뜨릴 수 있기 때문이다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;/review refactor-start&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 결과는 다음처럼 나뉜다.&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;## Standards
문서화된 아키텍처 규칙, 코드 스타일, 파일 구조 기준 위반

## Spec
원래 issue, PRD, refactor goal과 비교했을 때 빠진 것 또는 벗어난 것&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 분리하면 리뷰의 감정 소모도 줄어든다.&lt;br /&gt;&amp;ldquo;코드가 별로다&amp;rdquo;가 아니라 &amp;ldquo;이건 standards 축의 문제다&amp;rdquo;, &amp;ldquo;이건 spec 축의 문제다&amp;rdquo;라고 말할 수 있기 때문이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 changelog의 네 묶음은 모두 작업을 작게 나누는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/handoff&lt;/code&gt;는 컨텍스트 창을 작업 단위로 나눈다.&lt;br /&gt;&lt;code&gt;/prototype&lt;/code&gt;은 모호한 설계를 코드로 눌러 보되, 답만 남기고 코드는 버린다.&lt;br /&gt;&lt;code&gt;/writing&lt;/code&gt;은 AI가 너무 빨리 완성본을 쓰지 못하게 하고, fragment에서 shape까지 사람과 함께 이동한다.&lt;br /&gt;&lt;code&gt;/review&lt;/code&gt;는 코드 기준과 요구사항 충족을 분리해서 검토한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통점은 &amp;ldquo;AI에게 일을 맡긴다&amp;rdquo;가 아니다.&lt;br /&gt;AI가 따라야 할 작업 방식을 작은 protocol로 만든다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 적용한다면 다음 순서가 좋다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;긴 설계 세션 중간에는 &lt;code&gt;/handoff&lt;/code&gt;로 새 컨텍스트를 만든다.&lt;/li&gt;
&lt;li&gt;상태 모델과 UI 결정은 &lt;code&gt;/prototype&lt;/code&gt;으로 먼저 만져 본다.&lt;/li&gt;
&lt;li&gt;글은 바로 완성하지 말고 &lt;code&gt;fragments -&amp;gt; beats -&amp;gt; shape&lt;/code&gt;로 나눈다.&lt;/li&gt;
&lt;li&gt;구현 리뷰는 standards와 spec을 분리해서 본다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI agent를 잘 쓰는 방법은 더 똑똑한 모델을 기다리는 것만이 아니다.&lt;br /&gt;작업을 어떤 단위로 나누고, 어떤 피드백 루프를 만들고, 어떤 산출물만 남길지 정하는 것이다.&lt;br /&gt;이번 changelog의 스킬들은 그 감각을 꽤 실용적인 형태로 보여 준다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;</description>
      <category>AI코딩</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/233</guid>
      <comments>https://tsyang.tistory.com/233#entry233comment</comments>
      <pubDate>Tue, 12 May 2026 23:57:11 +0900</pubDate>
    </item>
    <item>
      <title>결국 기초가 중요하다 - Matt Pocock 강의</title>
      <link>https://tsyang.tistory.com/232</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;Software Fundamentals Matter More Than Ever&quot; &amp;mdash; Matt Pocock&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/v4F1gFy-hqg?si=1ZYrVgRvvVX__4gc&quot;&gt;https://youtu.be/v4F1gFy-hqg?si=1ZYrVgRvvVX__4gc&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=v4F1gFy-hqg&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cMJY0d/dJMb8SXBOmg/rZk7VhBb2MIJzFxmI9zcTK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=628_86_788_260,https://scrap.kakaocdn.net/dn/bCseST/dJMb8SpLXXh/JiPzZYHGRj6FjYPepqi3o0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=628_86_788_260&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;&amp;quot;Software Fundamentals Matter More Than Ever&amp;quot; &amp;mdash; Matt Pocock&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/v4F1gFy-hqg&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 강의를 정리한 것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spec to Code&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 현재 (2026년 5월) &lt;b&gt;Specs-to-code movement가 대세&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tsyang.tistory.com/224&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참고 : 2026.03.02 - [AI코딩] - 스펙 주도 개발 (Spec Driven Development, SDD)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spec을 작성하고 AI한테 일을 시킨다. 그리고 코드를 보지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 결국에 보게 된다. 왜냐면 문제가 생기기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 생기면 다시 Spec을 수정하고 컴파일을 돌린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지만 이런 식으로 하다 보면 점점 AI는 나쁜 코드를 짜다가 이내 쓰레기 같은 코드를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이거 ㄹㅇ임... )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 왜 그럴까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;소프트웨어 엔트로피&lt;/code&gt;라는 말이 있다. &lt;b&gt;부분만 고치면 시스템은 무너진다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Code is (not) cheap&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;나쁜 코드는 어느 때보다 비싸졌다.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강연자가 한 말이다. AI시대 더 이상 코드는 싸지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 좋은 코드베이스에서는 아주 잘 동작한다. 그러나 코드베이스가 구리다면? AI는 위의 Specs to code사례처럼 점점 더 안 좋은 코드들을 양산해 낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;소프트웨어 기초가 어느 때보다 중요하다.&quot;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;어쩌라고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;b&gt;❤️&lt;/b&gt; 그래서 어쩌란걸까? ❤️&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Grill Me&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI와 나는 사실 같은 생각을 하고 있지 않다. AI와 나 사이에는 아직 얘기하지 못한 맥락(Design concept)이 남아있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 어쩔까? 강연자는 /grill-me 스킬을 제안한다. (스킬은 깃헙 레포가 마지막에 첨부되어있다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1221&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PzTYM/dJMcadolXJo/le5p1jNcECAzTeGeYzRm9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PzTYM/dJMcadolXJo/le5p1jNcECAzTeGeYzRm9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PzTYM/dJMcadolXJo/le5p1jNcECAzTeGeYzRm9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPzTYM%2FdJMcadolXJo%2Fle5p1jNcECAzTeGeYzRm9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1221&quot; height=&quot;220&quot; data-origin-width=&quot;1221&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, AI와 내가 같은 이해에 도달할 때 까지 계속 질문하라는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 /write-a-prd (prd : product requirements document) 로 질문 내용들을 문서로 생성해라.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 변경이 적을 경우 /write-issue로 그냥 에이전트한테 일 주고 넘어갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저자는 grill-me 스킬이 클로드의 plan-mode보다 훨씬 낫다고 한다. plan-mode는 너무 많은것을 빠르게 하려고 하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;용어 정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 너무 장황하다(verbose).&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 말을 매번 다른 용어로 설명하곤 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 AI가 덜 장황하게 생각한다면 유저가 세운 계획을 더 일관되게(aligend) 구현한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 강연자는 DDD에서 나오는 개념인 ubiquitous language를 제안한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ubiquitous_language.md를 만들고 거기서 AI와 사용할 용어를 통일하라는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;TDD&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만든 건 잘 고장난다. 의도대로 만들었는데 막상 실행이 안 된다. 왜일까? 이건 AI가 너무 빨리빨리 만들려고 그래서 그렇다. 다 만들고 보니 놓친 것들이 많은 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&quot;너의 피드백 속도가 곧 너의 제한속도이다.&quot;라는 실용주의적 프로그래머를 언급한다. 즉, 테스트를 하면서 내가 확인할 수 있는만큼 일을 조금씩 진행하라는 것이다. 그런데 AI는 그냥 냅다 과속 갈긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결법은? TDD를 도입하는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD를 도입하게 되면 LLM이 강제로 테스트를 만들고 진행하면서 일을 작은 단위로 쪼개고, 속도를 조절하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데? 테스트는 어렵다. 좋은 코드베이스는 테스트하기 쉬운 코드베이스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;딥 모듈&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 테스트하기 쉬운 코드베이스는 어케 만드는데?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1233&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IeA0J/dJMcafT3hh8/PG5dq0NIRW9AUj5ArTy4v1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IeA0J/dJMcafT3hh8/PG5dq0NIRW9AUj5ArTy4v1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IeA0J/dJMcafT3hh8/PG5dq0NIRW9AUj5ArTy4v1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIeA0J%2FdJMcafT3hh8%2FPG5dq0NIRW9AUj5ArTy4v1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1233&quot; height=&quot;368&quot; data-origin-width=&quot;1233&quot; data-origin-height=&quot;368&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깊은 모듈은&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기능이 많고&lt;/li&gt;
&lt;li&gt;단순한 인터페이스를 가지고 있고&lt;/li&gt;
&lt;li&gt;복잡성을 숨긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얕은 모듈은&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기능이 많지 않고&lt;/li&gt;
&lt;li&gt;인터페이스가 복잡하고&lt;/li&gt;
&lt;li&gt;복잡성이 드러난다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;661&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJpx5F/dJMcaja1U7b/uvyt7SxFKJoKioG277TCmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJpx5F/dJMcaja1U7b/uvyt7SxFKJoKioG277TCmk/img.png&quot; data-alt=&quot;https://youtu.be/v4F1gFy-hqg?si=uIUPLVuxWOBUEZ5v&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJpx5F/dJMcaja1U7b/uvyt7SxFKJoKioG277TCmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJpx5F%2FdJMcaja1U7b%2Fuvyt7SxFKJoKioG277TCmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;433&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;661&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://youtu.be/v4F1gFy-hqg?si=uIUPLVuxWOBUEZ5v&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얕은 모듈의 코드베이스는 위와 같은 모양이다. 작은 모듈들이 수많이 산재해있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 AI가 내 코드를 이해하지 못한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 깊은 모듈은 어떤가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lAiLX/dJMcahEiklN/ud8xGjqmPFr0cEPGSEDKvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lAiLX/dJMcahEiklN/ud8xGjqmPFr0cEPGSEDKvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lAiLX/dJMcahEiklN/ud8xGjqmPFr0cEPGSEDKvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlAiLX%2FdJMcahEiklN%2Fud8xGjqmPFr0cEPGSEDKvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;417&quot; height=&quot;380&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 모양이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 개의 큰 모듈로 통합되어 있으며 이들이 각각 깔끔한 인터페이스를 노출하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 인터페이스들은 잘 통제된 환경에 있어야하고 정말 잘 짜여져 있어야 한다. 그래야 AI가 잘한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 강연자는 이런 것도 스킬을 만들어뒀다. /improve-codebase-architecture&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;회색 상자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI로 구현을 하다 보면 &lt;b&gt;내 뇌가 AI가 생성한 코드를 따라가지 못한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 어떡할까? 사용자는 인터페이스를 설계하고, 그 구현은 AI에게 넘기면 된다. 즉 깊은 모듈의 인터페이스를 제외한 부분를 그냥 모르는 상태로 두자는 것이다. (=회색상자) 그대신 인터페이스는 잘 짜야겠지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 자세히 알고싶다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=EJyuu6zlQCg&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=EJyuu6zlQCg&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/v4F1gFy-hqg?si=-0kmlXJqlGFqEp3L&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/v4F1gFy-hqg?si=-0kmlXJqlGFqEp3L&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/mattpocock/skills&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/mattpocock/skills&lt;/a&gt; (깃헙 레포)&lt;/p&gt;</description>
      <category>AI코딩</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/232</guid>
      <comments>https://tsyang.tistory.com/232#entry232comment</comments>
      <pubDate>Wed, 6 May 2026 22:24:32 +0900</pubDate>
    </item>
    <item>
      <title>블로그 추천 글</title>
      <link>https://tsyang.tistory.com/notice/230</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI코딩&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;&lt;a style=&quot;color: #0070d1; text-align: start;&quot; href=&quot;https://tsyang.tistory.com/234&quot;&gt;2026.05.23 - [AI코딩] - AI 활용 팁&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/224&quot;&gt;스펙 주도 개발 (Spec Driven Development)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/232&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2026.05.06 - [AI코딩] - 결국 기초가 중요하다 - Matt Pocock 강의&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;ECS&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/155&quot;&gt;Entities - 컴포넌트 구조&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/217&quot;&gt;ECB + sortKey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/220&quot;&gt;BlobAsset의 개념&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/221&quot;&gt;ECS에서 Behavior Tree 구현하기 (ft. xNode)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/223&quot;&gt;ECS Hybrid - Companion GameObject&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;유니티&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/194&quot;&gt;IL2CPP가 Virtual Call과 Boxing을 처리하는 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/218&quot;&gt;Native Memory (ft. NativeList)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;이론/설계&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/68&quot;&gt;Data-oriented Design (데이터 지향 설계, DoD)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/69&quot;&gt;ECS (Entity Component System)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;이론/일반&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/2&quot;&gt;멀티플레이 게임과 동기화&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/44&quot;&gt;객체 메모리, Object Alignment (feat. false sharing)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/113&quot;&gt;예외(Exception) 써야할까?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/114&quot;&gt;클로저 (Closure)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/169&quot;&gt;N번째 난수 값 얻어오기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;언어/C#&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/216&quot;&gt;C#의 메모리 정렬 (StructLayout)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/107&quot;&gt;단순동기화2 - 유저 모드 동기화&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/108&quot;&gt;단순동기화3 - 커널 모드 동기화&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/110&quot;&gt;복합 스레드 동기화 요소&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/111&quot;&gt;스레드 동기화 - 기타 (이중 확인 락, 조건 변수, 컬렉션)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/202&quot;&gt;가비지 없이 foreach 사용하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://tsyang.tistory.com/211&quot;&gt;Defensive Copy (struct 와 in, readonly)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Game AI&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/73&quot;&gt;의사 결정 - Decision Tree&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/123&quot;&gt;Behavior Tree (1) - 기초&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/135&quot;&gt;목표 지향 행동 (Goal-Oriented Behavior) - 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/139&quot;&gt;Rule-Based System (1)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;알고리즘/일반&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/141&quot;&gt;알아둘 만한 알고리즘들&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/203&quot;&gt;(간단) 분할 상환(amortized) 분석 (+확률적 분석)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;언어/C++&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/1&quot;&gt;L_value와 R_value&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/8&quot;&gt;스마트 포인터&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/9&quot;&gt;C++ (복사/이동) 생성자, 할당자, Rule of Three(Five)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/60&quot;&gt;Cpp 함수 (C++11 lambda, std::function)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이론/그래픽스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://tsyang.tistory.com/57&quot;&gt;곡선(Curve) &amp;amp; 스플라인(Spline)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/notice/230</guid>
      <pubDate>Thu, 30 Apr 2026 21:23:26 +0900</pubDate>
    </item>
    <item>
      <title>2026 에이전틱 코딩 트랜드 리포트 by Anthropic</title>
      <link>https://tsyang.tistory.com/225</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;원문: &lt;a href=&quot;https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Anthropic, &lt;i&gt;2026 Agentic Coding Trends Report &amp;mdash; How coding agents are reshaping software development&lt;/i&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전문이 아닌 일부만을 발췌&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소프트웨어 개발이 &quot;코드를 직접 쓰는 일&quot;에서 &quot;에이전트를 오케스트레이션하는 일&quot;로 바뀌고 있다. 그렇다고 AI가 사람을 대체하는 건 아니다. 연구 결과에 따르면 개발자는 업무의 60%에 AI를 쓰지만 &quot;완전 위임&quot;이 가능한 작업은 0~20%에 불과하다. &lt;b&gt;AI는 대체가 아니라 긴밀한 협업 도구다.&lt;/b&gt; Anthropic이 2026년을 정의할 트렌드 8가지를 정리했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;머리말 &amp;mdash; 보조에서 협업으로&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자들이 AI와 실제로 어떻게 일하는지 연구해보면 중요한 뉘앙스가 드러난다. &lt;b&gt;이 변화는 본질적으로 협업적이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 상시 협업자로 기능하지만, 효과적으로 활용하려면 신중한 설계와 프롬프팅, 적극적인 감독, 검증, 인간적 판단이 필요하다. 특히 중요도가 높은 작업일수록 더욱 그렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 보고서는 고객 경험에서 얻은 인사이트를 바탕으로 2026년 에이전트 코딩을 정의할 8가지 트렌드를 제시한다. 세 가지 카테고리로 구분된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Foundation 트렌드&lt;/b&gt;: 개발 작업 방식을 근본적으로 바꿀 변화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Capability 트렌드&lt;/b&gt;: 에이전트가 할 수 있는 일의 확장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Impact 트렌드&lt;/b&gt;: 비즈니스 성과와 조직 구조에 미칠 영향&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주목할 점은, 이 트렌드들이 선도 기업과 후발 주자 간의 격차가 벌어지고 있음을 보여준다는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Foundation 트렌드 &amp;mdash; 구조적 변화&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 1 &amp;mdash; SDLC*가 극적으로 변한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;i&gt;* Software Development Life Cycle &amp;mdash; 소프트웨어 개발 생명주기. &lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp; 요구사항 분석 &amp;rarr; 설계 &amp;rarr; 구현(코딩) &amp;rarr; 테스트 &amp;rarr; 배포 &amp;rarr; 유지보수로 이어지는 소프트웨어 개발의 전체 과정을 단계별로 정의한 &lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;모델이다.&amp;nbsp;프로젝트&amp;nbsp;관리와&amp;nbsp;품질&amp;nbsp;관리를&amp;nbsp;위해&amp;nbsp;개발&amp;nbsp;프로세스를&amp;nbsp;구조화하는&amp;nbsp;틀로&amp;nbsp;쓰인다.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;912&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXghIo/dJMcahp1yo8/90lgYg5pQKuKpCHkO5VCU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXghIo/dJMcahp1yo8/90lgYg5pQKuKpCHkO5VCU0/img.png&quot; data-alt=&quot;Anthropic,&amp;amp;nbsp;2026 Agentic Coding Trends Report&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXghIo/dJMcahp1yo8/90lgYg5pQKuKpCHkO5VCU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXghIo%2FdJMcahp1yo8%2F90lgYg5pQKuKpCHkO5VCU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1628&quot; height=&quot;912&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;912&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Anthropic,&amp;nbsp;2026 Agentic Coding Trends Report&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인간이 컴퓨터와 상호작용하는 방식은 GUI 등장 이래 가장 큰 변화를 맞고 있다. 기계어 &amp;rarr; 어셈블리 &amp;rarr; C &amp;rarr; 고수준 언어로 이어진 추상화 계층의 진화는 매번 인간의 사고와 기계 실행 사이의 간격을 좁혀왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 진화의 가장 최근 단계는 인간과 기계의 &lt;b&gt;대화&lt;/b&gt;다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 SDLC 단계들은 유지되지만, 에이전트 주도 구현과 자동화된 테스팅, 인라인 문서화가 주기 시간을 수 주에서 수 시간으로 압축한다. 모니터링 결과가 빠른 반복 주기에 직접 피드백된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;추상화의 진화&lt;/b&gt;: 코드 작성&amp;middot;디버깅&amp;middot;유지보수 등 전술적 작업의 대부분이 AI로 이동하고, 엔지니어는 아키텍처, 시스템 설계, &quot;무엇을 만들 것인가&quot;에 대한 전략적 결정에 집중한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;엔지니어 역할 변화&lt;/b&gt;: 소프트웨어 개발은 코드를 쓰는 것을 의미했다. 이제는 코드를 쓰는 에이전트를 오케스트레이션하고, 그 결과물을 평가하며, 전략적 방향을 제시하고, 시스템 전체가 올바른 문제를 올바르게 풀고 있는지 확인하는 것이 소프트웨어 엔지니어의 일이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;온보딩 혁명 &amp;rarr; 동적 인력 배치&lt;/b&gt;: 새 코드베이스에 온보딩하는 전통적 기간이 수 주에서 수 시간으로 단축된다. 기업이 인재 배치와 프로젝트 인력 구성을 생각하는 방식 자체가 바뀐다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;협업의 실제&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 더 많은 구현 작업을 처리하는 이 변화 속에서 중요한 사실이 드러난다. &lt;b&gt;엔지니어들은 대체되는 것이 아니라 더 &quot;풀스택&quot;화되고 있다.&lt;/b&gt; 연구에 따르면 엔지니어들은 이제 AI가 지식 공백을 채워주는 덕분에, 이전에는 전문성이 부족했던 프런트엔드, 백엔드, 데이터베이스, 인프라 영역에 걸쳐 효과적으로 일할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;역할 변화: 구현자에서 오케스트레이터로&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년에 엔지니어의 가치는 시스템 아키텍처 설계, 에이전트 조율, 품질 평가, 전략적 문제 분해로 이동한다. 에이전트를 마스터한 엔지니어는 여러 기능을 동시에 개발하면서, 이전의 개별 구현 방식보다 훨씬 넓은 범위에 자신의 판단을 적용할 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;온보딩 혁명&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년부터 새 코드베이스 온보딩* 기간이 수 주에서 수 시간으로 단축되기 시작했다. 2026년에는 기업들이 이 역량을 최대한 활용하는 방법을 익히게 된다. &lt;b&gt;&quot;서지(Surge) 스태핑**&quot;&lt;/b&gt; 이라는 개념이 현실화된다. 깊은 코드베이스 지식이 필요한 태스크에 엔지니어를 온디맨드로 투입하고, 전통적인 생산성 저하 없이 전문가를 특정 과제에 맞게 유동적으로 배치할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;i&gt;*온보딩(Onboarding) &amp;mdash; 채용 확정 후 입사 처리를 완료하는 단계. 계약서 서명, 신분증 제출, 시스템 계정 생성, 초기 교육 등&amp;nbsp; &quot;실제로&amp;nbsp;일&amp;nbsp;시작하기까지&quot;&amp;nbsp;필요한&amp;nbsp;행정&amp;nbsp;절차&amp;nbsp;전체다.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;i&gt;**서지 스태핑(Surge Staffing) &amp;mdash; 특정 프로젝트나 태스크에 인력을 일시적으로 대거 투입하는 방식이다. &quot;서지&quot;는 파도처럼&lt;/i&gt;&lt;i&gt;&amp;nbsp; 급격히&amp;nbsp;늘리는&amp;nbsp;것,&amp;nbsp;&quot;스태핑&quot;은&amp;nbsp;인력&amp;nbsp;배치를&amp;nbsp;뜻한다.&lt;/i&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사례&lt;/b&gt;: Augment Code는 Claude를 활용해 엔지니어가 새 코드베이스에 합류할 때 컨텍스트 기반 코드 이해를 제공한다. 한 엔터프라이즈 고객은 CTO가 4~8개월로 예상했던 프로젝트를 &lt;b&gt;단 2주 만에 완료&lt;/b&gt;했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Capability 트렌드 &amp;mdash; 에이전트가 할 수 있는 것&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 2 &amp;mdash; 단일 에이전트가 조율된 팀으로 진화한다&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1227&quot; data-origin-height=&quot;1119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BQaDC/dJMcadnzSvY/igvvLUmWQn7eHlvscMO6y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BQaDC/dJMcadnzSvY/igvvLUmWQn7eHlvscMO6y0/img.png&quot; data-alt=&quot;Anthropic,&amp;amp;nbsp;2026 Agentic Coding Trends Report&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BQaDC/dJMcadnzSvY/igvvLUmWQn7eHlvscMO6y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBQaDC%2FdJMcadnzSvY%2FigvvLUmWQn7eHlvscMO6y0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1227&quot; height=&quot;1119&quot; data-origin-width=&quot;1227&quot; data-origin-height=&quot;1119&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Anthropic,&amp;nbsp;2026 Agentic Coding Trends Report&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태스크 분해, 에이전트 전문화, 조율 프로토콜에 대한 새로운 역량이 필요하다. 또한 여러 동시 에이전트 세션의 상태를 보여주는 개발 환경과, 에이전트가 동시에 생성한 기여물을 처리하는 버전 관리 워크플로가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;멀티 에이전트 시스템이 단일 에이전트 워크플로를 대체한다&lt;/b&gt;: 조직들이 별도의 컨텍스트 창에서 병렬 추론을 통해 성능 향상을 극대화하는 멀티 에이전트 워크플로를 채택한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 에이전트 워크플로는 하나의 컨텍스트 창을 통해 태스크를 순차적으로 처리한다. 멀티 에이전트 아키텍처는 오케스트레이터가 병렬로 작동하는 특화된 에이전트들을 조율한다. 각 에이전트는 전용 컨텍스트를 가지며, 결과는 통합 출력으로 합성된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 3 &amp;mdash; 장기 실행 에이전트가 완성된 시스템을 만든다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 에이전트는 &quot;이 버그 고쳐줘&quot;, &quot;이 함수 작성해줘&quot;, &quot;테스트 생성해줘&quot; 같은 수 분짜리 원샷 태스크를 처리했다. 2025년 후반에 들어서 에이전트는 수 시간에 걸쳐 완전한 기능 세트를 만들어낼 수 있게 됐다. 2026년에는 &lt;b&gt;에이전트가 수 일씩 작동하며 최소한의 인간 개입만으로 전체 애플리케이션과 시스템을 구축&lt;/b&gt;하게 된다. 인간은 핵심 결정 지점에서만 전략적 감독을 제공하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;태스크 수평선이 수 분에서 수 일/수 주로 확장된다&lt;/b&gt;: 에이전트가 수 분 만에 끝나는 개별 태스크에서 벗어나 장시간 자율 작동하며 주기적인 인간 체크포인트를 두고 전체 애플리케이션과 시스템을 구축&amp;middot;테스트한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;에이전트가 소프트웨어 개발의 지저분한 현실을 처리한다&lt;/b&gt;: 장기 실행 에이전트는 수십 번의 작업 세션에 걸쳐 계획하고, 반복하고, 개선하면서 발견된 사항에 적응하고, 실패에서 회복하고, 복잡한 프로젝트 전체에서 일관된 상태를 유지한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소프트웨어 개발의 경제학이 바뀐다&lt;/b&gt;: 에이전트가 장기간 자율 작동할 수 있게 되면, 이전에는 실현 불가능했던 프로젝트가 가능해진다. 아무도 손댈 시간이 없어서 수년간 쌓인 기술 부채가 에이전트의 자율 작업으로 체계적으로 해소된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시장 진입 속도가 빨라진다&lt;/b&gt;: 창업자들이 아이디어에서 배포된 애플리케이션으로 가는 데 수 개월이 아니라 수 일이 걸린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사례&lt;/b&gt;: Rakuten 엔지니어들은 Claude Code로 복잡한 기술 과제를 테스트했다. 1,250만 줄짜리 멀티 언어 대형 오픈소스 라이브러리 vLLM에 특정 활성화 벡터 추출 방법을 구현하는 것이었다. Claude Code는 &lt;b&gt;단일 실행으로 7시간의 자율 작업 끝에 전체 작업을 완료&lt;/b&gt;했고, 참조 방법 대비 수치 정확도 99.9%를 달성했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 4 &amp;mdash; 인간 감독이 스마트한 협업을 통해 확장된다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년에 가장 가치 있는 역량 발전은 에이전트가 모든 태스크를 맹목적으로 시도하는 대신 &lt;b&gt;언제 도움을 요청해야 하는지 배우는 것&lt;/b&gt;이다. 그리고 인간이 필요할 때만 루프에 진입하는 것이다. 프로세스에서 인간을 제거하는 게 아니라, 인간의 주의가 가장 중요한 곳에서 효과를 발휘하도록 하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;에이전트 품질 관리가 표준화된다&lt;/b&gt;: 조직들이 AI 에이전트를 활용해 대규모 AI 생성 결과물을 검토한다. 보안 취약점, 아키텍처 일관성, 인간 역량을 초과하는 품질 이슈를 분석하는 AI 기반 코드 리뷰가 자리잡는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;에이전트가 언제 도움을 요청할지 배운다&lt;/b&gt;: 정교한 에이전트가 인간 판단이 필요한 상황을 스스로 인식하고, 불확실한 영역을 플래그 처리하며, 비즈니스 영향이 있는 결정을 에스컬레이션한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인간 감독이 &quot;모든 것 검토&quot;에서 &quot;중요한 것 검토&quot;로 바뀐다&lt;/b&gt;: 팀이 품질과 속도를 동시에 유지한다. 일상적인 검증은 지능형 시스템이 처리하고, 진정으로 새롭거나, 경계 케이스이거나, 전략적 결정이 필요한 상황만 인간에게 올라온다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;협업의 역설&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic 내부 연구에서 흥미로운 패턴이 드러난다. 엔지니어들은 업무의 약 60%에서 AI를 사용하고 상당한 생산성 향상을 보고하지만, 동시에 &quot;완전 위임&quot; 가능한 태스크 비율은 극히 일부라고 응답한다. 이 명백한 모순은 &lt;b&gt;효과적인 AI 협업이 인간의 적극적 참여를 요구한다&lt;/b&gt;는 사실로 해소된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔지니어들은 AI 위임에 대한 직관을 시간이 지나면서 개발한다고 말한다. 모델이 개선됨에 따라 이 기준도 빠르게 변하지만, 역사적으로 그들은 &quot;정확성을 쉽게 스니프-체크할 수 있는&quot; 검증이 용이한 태스크나, 버그를 추적하기 위한 빠른 스크립트처럼 위험도가 낮은 작업을 위임하는 경향이 있었다. 개념적으로 어렵거나 설계 의존적인 태스크일수록 스스로 처리하거나 AI와 함께 협력해서 풀어나간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 패턴은 중요한 시사점을 가진다. AI 역량이 확장되더라도 인간의 역할은 여전히 핵심적이다. 변화는 &quot;코드 작성&quot;에서 &quot;AI가 생성한 코드를 검토하고, 방향을 잡고, 검증하는 것&quot;으로의 이동이다. 한 엔지니어의 말이 인상적이다: &quot;주로 답이 어떻게 나와야 하는지 이미 알고 있는 경우에 AI를 사용한다. 그 능력은 소프트웨어 엔지니어링을 '직접 부딪히며' 배운 덕분에 생겼다.&quot;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사례&lt;/b&gt;: 인도의 1,500만 사용자 핀테크 플랫폼 CRED는 전체 개발 라이프사이클에 Claude Code를 적용했다. Claude 기반 개발 시스템은 &lt;b&gt;실행 속도를 두 배로 높였다&lt;/b&gt;. 인간 참여를 줄인 것이 아니라, 개발자들이 더 높은 가치의 작업에 집중하도록 한 결과다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 5 &amp;mdash; 에이전트 코딩이 새로운 환경과 사용자로 확장된다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;언어 장벽이 사라진다&lt;/b&gt;: COBOL, Fortran, 도메인 특화 언어 등 비주류&amp;middot;레거시 언어 지원이 확장된다. 레거시 시스템 유지보수가 가능해지고 특수 사용 케이스의 진입 장벽이 낮아진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코딩이 엔지니어링 너머로 민주화된다&lt;/b&gt;: 새로운 폼팩터와 인터페이스가 보안, 운영, 디자인, 데이터 과학 등 비전통적 개발자들에게 에이전트 코딩을 열어준다. 비개발자가 파일&amp;middot;태스크 관리를 자동화하도록 설계된 Cowork 같은 도구들이 이미 이 변화를 예고하고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;모두가 더 풀스택이 된다&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 확장은 &quot;진지한 개발 작업은 IDE에서만 가능하다&quot;거나 &quot;전문 도구를 가진 전문 엔지니어만 코드로 문제를 풀 수 있다&quot;는 오랜 가정에 도전한다. &quot;코딩하는 사람&quot;과 &quot;코딩 못하는 사람&quot; 사이의 장벽이 점점 허물어지고 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사례&lt;/b&gt;: AI 법률 플랫폼 Legora의 CEO Max Junestrand는 말한다: &quot;Claude는 지시 따르기와 에이전트&amp;middot;에이전트 워크플로 구축에 탁월하다.&quot; Legora는 Claude Code로 자체 개발을 가속화하는 동시에, 엔지니어링 전문성 없이도 정교한 자동화를 만들어야 하는 변호사들에게 에이전트 역량을 제공한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Impact 트렌드 &amp;mdash; 에이전트가 바꿀 것들&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 6 &amp;mdash; 생산성 향상이 소프트웨어 개발의 경제학을 재편한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;세 가지 승수가 가속을 만든다&lt;/b&gt;: 에이전트 역량, 오케스트레이션 개선, 인간 경험의 더 나은 활용이 복합되어 선형 향상이 아닌 스텝 함수적 향상을 만든다. 각 요소가 다른 요소들을 가능하게 하기 때문이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;타임라인 압축이 프로젝트 실현 가능성을 바꾼다&lt;/b&gt;: 수 주 걸리던 개발이 수 일로 단축되어 이전에는 불가능했던 프로젝트가 가능해지고, 시장 기회에 더 빠르게 대응할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소프트웨어 개발의 경제학이 바뀐다&lt;/b&gt;: 에이전트가 엔지니어 역량을 보강하면서 총 소유 비용이 낮아지고, 프로젝트 타임라인이 단축되고, 더 빠른 가치 실현으로 투자 수익이 개선된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;속도가 아닌 출력량을 통한 생산성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic 내부 연구에서 흥미로운 생산성 패턴이 드러난다. 엔지니어들은 태스크 카테고리당 소요 시간이 줄었다고 보고하지만, &lt;b&gt;출력량에서는 훨씬 더 큰 순 증가를 보고한다.&lt;/b&gt; AI가 같은 일을 단순히 더 빠르게 하는 것이 아니라, 더 많은 기능 출시, 더 많은 버그 수정, 더 많은 실험 실행을 통한 생산성 향상을 가능하게 한다는 의미다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주목할 점은 AI 지원 작업의 약 27%가 &lt;b&gt;원래라면 하지 않았을 작업&lt;/b&gt;이라는 것이다. 규모 확장 프로젝트, 인터랙티브 대시보드 같은 &quot;있으면 좋은&quot; 도구 구축, 수동으로는 비용 효율이 안 되는 탐색적 작업들이다. 엔지니어들은 AI 덕분에 처리할 수 있게 된 &quot;papercut&quot;(보통 우선순위에서 밀리는 사소하지만 품질을 높이는 이슈)들을 더 많이 고친다고 보고한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 7 &amp;mdash; 비기술 사용 케이스가 조직 전반으로 확장된다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년의 가장 중요한 트렌드 중 하나는 기능 팀과 비즈니스 프로세스 팀이 에이전트 코딩을 활용해 자신들이 경험하는 문제에 대한 솔루션을 직접 만들고, 매일 사용하는 프로세스를 개선하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;코딩 역량이 엔지니어링 너머로 민주화된다&lt;/b&gt;: 영업, 마케팅, 법무, 운영팀이 엔지니어링 개입이나 코딩 전문성 없이도 워크플로를 자동화하고 도구를 만드는 능력을 갖게 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;도메인 전문가가 직접 솔루션을 구현한다&lt;/b&gt;: 문제를 깊이 이해하는 실무 전문가들이 에이전트를 활용해 직접 솔루션을 시작한다. 티켓을 등록하고 개발팀을 기다리는 병목이 사라진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;생산성 향상이 전체 조직으로 확장된다&lt;/b&gt;: 엔지니어링 시간을 들일 가치가 없던 문제들이 해결되고, 실험적 워크플로가 손쉽게 시도되며, 수동 프로세스가 자동화된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사례 2 (Anthropic 자체 사례)&lt;/b&gt;: 법무팀은 계약 수정과 콘텐츠 검토 같은 반복 태스크를 자동화하는 Claude 기반 워크플로를 구축해 마케팅 검토 소요 시간을 &lt;b&gt;2~3일에서 24시간으로 단축&lt;/b&gt;했다. 코딩 경험이 없는 변호사가 Claude Code로 법무 큐에 올라오기 전에 문제를 분류하는 셀프서비스 도구를 만들었다. 변호사들이 전술적 잡무 대신 전략적 자문에 집중할 수 있게 됐다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trend 8 &amp;mdash; 에이전트 코딩이 보안 방어를 강화하지만, 공격도 강화한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 코딩은 보안을 두 방향으로 동시에 변화시키고 있다. 모델이 더 강력하고 더 정렬될수록 제품에 보안을 내재화하는 것이 쉬워진다. 이제 어떤 엔지니어든 AI를 활용해 이전에는 전문 보안 전문가가 필요했던 보안 리뷰, 하드닝, 모니터링을 수행할 수 있다. 그러나 방어자를 돕는 바로 그 역량이 공격자의 시도 규모를 확장하는 데도 사용될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예측&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;보안 지식이 민주화된다&lt;/b&gt;: 향상된 에이전트 덕분에 어떤 엔지니어든 심층 보안 리뷰, 하드닝, 모니터링을 수행할 수 있는 보안 엔지니어가 될 수 있다. 엔지니어들은 여전히 보안을 고려하고 전문가와 협의해야 하지만, 하드닝된 안전한 애플리케이션을 만드는 것이 더 쉬워진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;위협 행위자들이 공격을 확장한다&lt;/b&gt;: 에이전트가 방어적 용도에 도움이 되는 만큼 공격적 용도에도 도움이 된다. 이 양면적 기술에 맞서기 위해, 처음부터 보안을 설계에 내재화하는 것이 더욱 중요해진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;에이전트 기반 사이버 방어 시스템이 부상한다&lt;/b&gt;: 자동화된 에이전트 시스템이 기계 속도로 보안 대응을 가능하게 하고, 자율적 위협의 속도에 맞춰 탐지와 대응을 자동화한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;준비된 조직이 유리하다.&lt;/b&gt; 처음부터 에이전트 도구로 보안을 내재화한 팀은 같은 기술을 사용하는 공격자에 맞서 더 잘 대응할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2026년의 우선순위&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8가지 트렌드는 하나의 핵심 테마로 수렴된다. &lt;b&gt;소프트웨어 개발이 코드 작성 중심의 활동에서, 코드를 쓰는 에이전트를 오케스트레이션하는 활동으로 이동하고 있다.&lt;/b&gt; 동시에 품질 결과를 보장하는 인간의 판단, 감독, 협업의 중요성은 유지된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연구 결과는 명확하다. AI는 상시 협업자지만 효과적으로 사용하려면 적극적인 감독과 검증이 필요하다. 특히 중요도가 높은 작업일수록 더욱 그렇다. 더 일상적인 코딩 작업은 AI에게 위임할 수 있지만, 인간은 여전히 코드를 검토한다. &quot;완전 위임&quot;이 아니라 &lt;b&gt;고도의 협업&lt;/b&gt;이다. 이 구분은 조직이 AI 도입에 접근하는 방식과 엔지니어의 진화하는 역할을 생각하는 방식에서 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 우선순위를 계획하는 조직에게 즉각적인 주의가 필요한 네 가지 영역이 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;멀티 에이전트 조율 마스터&lt;/b&gt;: 단일 에이전트 시스템이 처리할 수 없는 복잡도 대응&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AI 자동화 리뷰로 인간-에이전트 감독 확장&lt;/b&gt;: 인간의 주의가 가장 중요한 곳에 집중&lt;/li&gt;
&lt;li&gt;&lt;b&gt;에이전트 코딩을 엔지니어링 너머로 확장&lt;/b&gt;: 각 부서 도메인 전문가 역량 강화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;에이전트 시스템 설계 초기부터 보안 아키텍처 내재화&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 코딩을 2026년 전략적 우선순위로 삼는 조직은 무엇이 가능한지를 정의하게 될 것이다. 반면 점진적 생산성 도구로만 바라보는 조직은 새로운 규칙으로 게임이 진행되고 있다는 사실을 뒤늦게 깨닫게 될 것이다. &lt;b&gt;핵심은 인간을 루프에서 제거하는 것이 아니라, 인간의 전문성이 가장 중요한 곳에서 빛을 발하게 하는 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Anthropic, &lt;i&gt;2026 Agentic Coding Trends Report&lt;/i&gt;, 2026&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI코딩</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/225</guid>
      <comments>https://tsyang.tistory.com/225#entry225comment</comments>
      <pubDate>Wed, 4 Mar 2026 21:29:17 +0900</pubDate>
    </item>
    <item>
      <title>스펙 주도 개발 (Spec Driven Development, SDD)</title>
      <link>https://tsyang.tistory.com/224</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Context Engineering이 전부다&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 코드를 작성하게 하려면, 결국 &lt;b&gt;맥락(Context)&lt;/b&gt;이 전부다.&lt;br&gt;같은 AI 모델이라도 주어진 맥락의 품질에 따라 결과물이 천지차이다.&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, AI에게 &quot;적 AI 만들어줘&quot;라고만 하면 AI는 대충 Update()에서 &lt;code&gt;Transform.LookAt()&lt;/code&gt;하고 &lt;code&gt;MoveTowards()&lt;/code&gt;하는 코드를 뱉어낸다. 하지만 이런 맥락을 알려주면 어떨까?&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;우리 프로젝트는 NavMesh 기반 길찾기를 쓴다&lt;/li&gt;&lt;li&gt;적 상태 관리는 FSM으로 하고 있다&lt;/li&gt;&lt;li&gt;감지 범위는 Physics.OverlapSphere로 처리한다&lt;/li&gt;&lt;li&gt;공격 판정은 서버에서 한다&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;전혀 다른 수준의 코드가 나온다.&lt;br&gt;이게 바로 &lt;b&gt;Context Engineering&lt;/b&gt;이다. AI에게 올바른 맥락을 설계하고 전달하는 것. 프롬프트 엔지니어링이 &quot;어떻게 말하느냐&quot;의 문제라면, 컨텍스트 엔지니어링은 &lt;b&gt;&quot;무엇을 알려주느냐&quot;&lt;/b&gt;의 문제다.&lt;br&gt;그렇다면 기존의 개발 방식들은 이 맥락을 어떻게 다루고 있을까?&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;전통적 개발 — 사람 머릿속의 Context&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;전통적인 개발에서 맥락은 대부분 &lt;b&gt;사람의 머릿속&lt;/b&gt;에 있다.&lt;br&gt;시니어 개발자가 아키텍처를 알고 있고, 기획자가 요구사항을 문서로 정리하고, 코드리뷰에서 &quot;이건 이렇게 하는 게 우리 컨벤션이야&quot;라고 말해준다. 즉 맥락이 &lt;b&gt;사람 간 커뮤니케이션&lt;/b&gt;을 통해 전달된다.&lt;br&gt;이 방식의 문제는 명확하다:&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;문서는 금방 낡는다 (코드는 바뀌는데 문서는 안 바뀜)&lt;/li&gt;&lt;li&gt;맥락이 특정 사람에게 편중된다 (버스 팩터)&lt;/li&gt;&lt;li&gt;새로운 팀원이 올바른 맥락을 갖추기까지 시간이 오래 걸린다&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 이 방식이 수십 년간 작동한 이유는, &lt;b&gt;코드를 쓰는 주체가 사람&lt;/b&gt;이었기 때문이다. 사람은 암묵적 맥락을 어느 정도 추론할 수 있다. &quot;아 여기는 이런 패턴으로 했구나&quot; 정도는 코드만 봐도 감을 잡는다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;바이브코딩 — Context 없이 달리기&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;바이브코딩(Vibe Coding)은 정반대의 접근이다. &lt;b&gt;맥락을 최소화하고, 프롬프트 하나로 바로 코드를 생성&lt;/b&gt;한다.&lt;br&gt;&quot;인벤토리 만들어줘&quot;, &quot;이 버그 고쳐줘&quot;, &quot;스킬 시스템 추가해줘&quot; — 이런 식으로 AI에게 즉석에서 지시를 내린다. 맥락 설계? 그런 거 없다. 그냥 바로 코딩한다. 분위기(vibe)로 코딩하는 거다.&lt;br&gt;솔직히 바이브코딩은 &lt;b&gt;작은 스코프에서는 매우 강력하다&lt;/b&gt;. 프로토타입을 빠르게 뽑거나, 독립적인 유틸리티 함수를 만들 때는 이만한 게 없다.&lt;br&gt;그러나 프로젝트 규모가 조금만 커지면 문제가 터진다:&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;AI가 기존 코드와 전혀 다른 패턴으로 코드를 생성한다&lt;/li&gt;&lt;li&gt;이전에 내린 결정과 모순되는 코드가 나온다&lt;/li&gt;&lt;li&gt;같은 수정을 몇 번이고 반복해서 요청하게 된다&lt;/li&gt;&lt;li&gt;결국 수동으로 맥락을 반복 입력하는 &quot;컨텍스트 노동&quot;이 생긴다&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 &lt;b&gt;Context Rot(맥락 부식)&lt;/b&gt;이라고 부를 수 있다. AI는 개별 작업 하나하나는 꽤 잘 해낸다. &quot;데미지 계산 함수 만들어줘&quot;하면 그럴듯한 함수가 나온다. &quot;피격 이펙트 재생하는 코드 짜줘&quot;하면 그것도 잘 만든다. 문제는, &lt;b&gt;작업을 전환하는 순간 이전 맥락이 증발한다는 것&lt;/b&gt;이다.&lt;br&gt;예를 들어, AI에게 먼저 데미지 계산 시스템을 만들게 했다고 하자. 방어력 공식도 정하고, 크리티컬 배율도 잡았다. 잘 됐다. 그 다음에 &quot;적 AI 만들어줘&quot;라고 하면? AI는 방금 전 데미지 시스템의 존재를 모른다. 자기가 만든 방어력 공식과 맞지 않는 별도의 공격 로직을 만들어낸다. 그 다음 &quot;UI에 데미지 표시해줘&quot;라고 하면? 또 다른 데미지 계산 로직이 튀어나올 수 있다.&lt;br&gt;&lt;b&gt;각 작업은 멀쩡한데, 전체를 합치면 엉망이 된다.&lt;/b&gt; 마치 서로 다른 사람이 소통 없이 각자 코드를 짠 것처럼. AI가 생성한 코드들이 하나의 일관된 프로젝트가 아니라, 독립적인 코드 조각들의 모음이 되어버린다.&lt;br&gt;바이브코딩의 근본 한계는 이 &lt;b&gt;Context Rot&lt;/b&gt; — 작업이 바뀔 때마다 맥락이 부식되고, 일관성이 무너지는 현상 — 에 있다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;SDD — 스펙이 곧 Context다&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;SDD(Spec Driven Development)는 이 Context Rot를 정면으로 해결한다.&lt;br&gt;핵심 아이디어는 단순하다: &lt;b&gt;스펙(Specification)을 1차 산출물로 만들고, 코드는 그 스펙의 표현(expression)으로 취급한다.&lt;/b&gt;&lt;/p&gt;&lt;table style=&quot;border-collapse: collapse;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Traditional&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Code&lt;/td&gt;&lt;td&gt;→&lt;/td&gt;&lt;td&gt;Docs&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;TDD&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Test&lt;/td&gt;&lt;td&gt;→&lt;/td&gt;&lt;td&gt;Code&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;SDD&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Spec&lt;/td&gt;&lt;td&gt;→&lt;/td&gt;&lt;td&gt;Code&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;전통적 개발에서는 코드를 먼저 짜고, 문서는 나중에 (혹은 안) 쓴다. TDD는 테스트를 먼저 짜고, 그 테스트를 통과하는 코드를 만든다. SDD는 스펙을 먼저 짜고, 그 스펙을 만족하는 코드를 생성한다.&lt;br&gt;&lt;b&gt;&quot;무엇을 먼저 만드느냐&quot;가 곧 개발 방법론의 정체성&lt;/b&gt;이다. SDD에서는 스펙이 왕이다. 코드는 스펙의 표현일 뿐이다.&lt;br&gt;이게 왜 Context Rot의 해결책이 되는지 보자. SDD에서 스펙은 단순한 기획 문서가 아니다. 스펙 자체가 AI에게 전달할 &lt;b&gt;구조화된 맥락&lt;/b&gt;이다. 프로젝트의 원칙, 아키텍처 제약, 요구사항, 테스트 기준 — 이 모든 것이 스펙에 담긴다. AI가 어떤 작업을 하든, 항상 같은 스펙을 참조한다. 데미지 시스템을 만들 때도, 적 AI를 만들 때도, UI를 만들 때도 &lt;b&gt;동일한 맥락 위에서 코드를 생성&lt;/b&gt;하는 거다. 작업이 바뀌어도 맥락이 부식되지 않는다.&lt;br&gt;즉, &lt;b&gt;스펙을 잘 쓰는 것 = Context Engineering을 잘 하는 것&lt;/b&gt;이고, 잘 쓰인 스펙은 Context Rot을 방지하는 방패가 된다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&quot;그거 CLAUDE.md랑 뭐가 다른데?&quot;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 이런 의문이 들 수 있다. 이미 &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.cursorrules&lt;/code&gt; 같은 파일로 AI에게 프로젝트 맥락을 주고 있지 않은가? 맞다. 이것도 일종의 Context Engineering이다. 그리고 실제로 효과가 있다.&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이런 파일들은 본질적으로 &lt;b&gt;정적인 가이드라인&lt;/b&gt;이다. &quot;우리 프로젝트는 이런 구조야&quot;, &quot;코딩 컨벤션은 이래&quot; 같은 배경 지식을 알려주는 것에 가깝다. 중요한 역할이지만, 한계가 명확하다:&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;기능 단위의 맥락이 없다.&lt;/b&gt; &quot;인벤토리 시스템의 요구사항은 이거고, 제약은 이거다&quot; 같은 내용은 CLAUDE.md에 안 들어간다.&lt;/li&gt;&lt;li&gt;&lt;b&gt;단계가 없다.&lt;/b&gt; 명세 → 명확화 → 계획 → 구현의 흐름 없이, 그냥 한 번에 &quot;알아서 해줘&quot;다.&lt;/li&gt;&lt;li&gt;&lt;b&gt;검증 장치가 없다.&lt;/b&gt; AI가 가이드라인을 잘 따랐는지 확인하는 게이트가 없다. 위반해도 그냥 넘어간다.&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md가 &lt;b&gt;&quot;우리 팀의 사내 위키&quot;&lt;/b&gt;라면, SDD의 스펙은 &lt;b&gt;&quot;이번 기능의 설계 문서 + 체크리스트 + 테스트 기준&quot;&lt;/b&gt;까지 포함한 것이다. 위키만 읽고 코드를 짜는 것과, 상세한 설계서를 보고 짜는 것은 결과물이 다를 수밖에 없다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;spec-kit으로 보는 SDD 워크플로우&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub에서 공개한 &lt;a href=&quot;https://github.com/github/spec-kit&quot; target=&quot;_self&quot;&gt;&lt;span&gt;spec-kit&lt;/span&gt;&lt;/a&gt;은 SDD를 실제로 적용할 수 있는 도구다. 6단계의 워크플로우로 구성되어 있다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Constitution (헌법)&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 &lt;b&gt;불변 원칙&lt;/b&gt;을 정의한다. 이건 개별 기능이 아니라 프로젝트 전체에 적용되는 규칙이다.&lt;br&gt;예를 들어:&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&quot;모든 기능은 독립적인 라이브러리로 먼저 만든다&quot;&lt;/li&gt;&lt;li&gt;&quot;구현 코드를 쓰기 전에 반드시 테스트를 먼저 작성한다&quot;&lt;/li&gt;&lt;li&gt;&quot;프로젝트 구조는 3개 이하로 유지한다&quot;&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;이 원칙들은 이후 모든 단계에서 &lt;b&gt;자동으로 참조&lt;/b&gt;된다. AI가 코드를 생성할 때 이 원칙을 위반하면 거부되는 식이다. 게임 개발로 치면, &quot;우리는 ECS 패턴만 쓴다&quot;, &quot;MonoBehaviour 금지&quot; 같은 아키텍처 결정을 미리 박아두는 것과 비슷하다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Specify (명세)&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;기능의 요구사항을 &lt;b&gt;&quot;무엇을&quot;&lt;/b&gt;, &lt;b&gt;&quot;왜&quot;&lt;/b&gt;의 관점에서 작성한다. &lt;b&gt;&quot;어떻게&quot;는 여기서 쓰지 않는다.&lt;/b&gt;&lt;br&gt;이게 중요하다. 구현 방법을 너무 일찍 결정하면, 기술 스택이 바뀌거나 더 나은 방법이 나왔을 때 스펙까지 다시 써야 한다. what과 why만 적어두면, how는 나중에 자유롭게 바꿀 수 있다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Clarify (명확화)&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;스펙에서 &lt;b&gt;애매한 부분을 명시적으로 표시&lt;/b&gt;한다.&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 흔히 저지르는 실수가 뭔지 아는가? &lt;b&gt;그럴듯한 추측을 사실인 것처럼 내뱉는 것&lt;/b&gt;이다. SDD에서는 불확실한 부분에 &lt;code&gt;[NEEDS CLARIFICATION]&lt;/code&gt; 태그를 달도록 강제한다. AI가 &quot;아 이건 아마 이렇겠지&quot;하고 넘어가는 걸 방지하는 거다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Plan (계획)&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;이제 비로소 &lt;b&gt;&quot;어떻게&quot;&lt;/b&gt;를 다룬다.&lt;br&gt;스펙과 헌법을 기반으로 기술적인 구현 계획을 세운다. 데이터 모델, API 설계, 테스트 시나리오 등이 여기서 나온다.&lt;br&gt;중요한 건, 이 단계에 &lt;b&gt;게이트(gate)&lt;/b&gt;가 존재한다는 것이다. 계획이 헌법의 원칙을 위반하거나, 불필요하게 복잡하거나, 테스트 없이 구현으로 넘어가려 하면 게이트에서 걸린다. AI가 &quot;대충 넘어가는&quot; 걸 구조적으로 막는 장치다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. Task (작업 분할)&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;계획을 &lt;b&gt;실행 가능한 단위의 작업&lt;/b&gt;으로 쪼갠다.&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;각 작업에는 병렬 실행 가능 여부(&lt;code&gt;[P]&lt;/code&gt; 태그)까지 표시된다. AI 에이전트가 여러 작업을 동시에 처리할 수 있도록 하기 위함이다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. Implement (구현)&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 코드를 작성한다. 그런데 이 시점에서 AI는 이미 &lt;b&gt;풍부한 맥락&lt;/b&gt;을 갖고 있다:&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;프로젝트 헌법 (불변 원칙)&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 data-ke-size=&quot;size16&quot;&gt;바이브코딩처럼 &quot;알아서 해줘&quot;가 아니라, &lt;b&gt;충분한 맥락 위에서 코드를 생성&lt;/b&gt;하는 거다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;SDD가 아니라 Spec이 중요하다&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히, 1~2년 뒤에도 모두가 SDD를 하고 있을 거라고는 생각하지 않는다. AI 개발 방법론은 지금도 우후죽순 나오고 있고, SDD는 그중 하나일 뿐이다.&lt;br&gt;그런데 &lt;b&gt;TDD를 생각해보자.&lt;/b&gt;&lt;br&gt;모든 팀이 TDD를 하는가? 아니다. 엄격한 TDD를 실천하는 팀은 사실 소수다. 그런데 &lt;b&gt;테스트 자체를 안 짜는 팀&lt;/b&gt;이 있는가? 거의 없다. TDD라는 방법론은 선택이지만, 테스트라는 산출물은 이제 업계 표준이다.&lt;br&gt;SDD도 마찬가지일 거다. SDD라는 방법론 자체는 유행이 지날 수 있다. 더 좋은 워크플로우가 나올 수도 있고, AI가 발전하면서 단계가 줄어들 수도 있다. &lt;b&gt;하지만 Spec이라는 산출물은 살아남을 확률이 높다.&lt;/b&gt;&lt;br&gt;이유는 간단하다. 앞에서 계속 이야기했듯이 &lt;b&gt;Spec은 곧 Context&lt;/b&gt;이기 때문이다. AI가 아무리 똑똑해져도, 맥락 없이 좋은 코드를 짤 수는 없다. 오히려 AI가 발전할수록 — 더 복잡한 시스템을 맡길수록 — 구조화된 맥락의 중요성은 커질 수밖에 없다.&lt;/p&gt;&lt;table style=&quot;border-collapse: collapse;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;TDD&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Test&lt;/td&gt;&lt;td&gt;TDD를 안 해도&lt;/td&gt;&lt;td&gt;테스트는 짠다&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;SDD&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Spec&lt;/td&gt;&lt;td&gt;SDD를 안 해도&lt;/td&gt;&lt;td&gt;스펙은 쓰게 될 것이다&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;결국 핵심은 이거다:&lt;br&gt;&lt;b&gt;&quot;AI에게 코드를 잘 짜게 하려면, 코드가 아니라 스펙을 잘 짜야 한다.&quot;&lt;/b&gt;&lt;br&gt;SDD를 쓰든 안 쓰든, 어떤 방법론을 따르든, 이 원칙은 변하지 않을 거다. 좋은 맥락이 좋은 코드를 만든다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt; 
 &lt;p data-ke-size=&quot;size16&quot;&gt;참고 : &lt;a href=&quot;https://github.com/github/spec-kit/blob/main/spec-driven.md&quot;&gt;GitHub spec-kit - Specification-Driven Development&lt;/a&gt;&lt;br&gt;참고 : &lt;a href=&quot;https://www.youtube.com/watch?v=mViFYTwWvcM&quot;&gt;SDD 소개 영상&lt;/a&gt;&lt;/p&gt; 
&lt;/blockquote&gt;</description>
      <category>AI코딩</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/224</guid>
      <comments>https://tsyang.tistory.com/224#entry224comment</comments>
      <pubDate>Mon, 2 Mar 2026 10:38:19 +0900</pubDate>
    </item>
    <item>
      <title>ECS Hybrid - Companion GameObject</title>
      <link>https://tsyang.tistory.com/223</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ECS 관련 기초 글 :&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tsyang.tistory.com/69&quot;&gt;ECS (Entity Component System)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tsyang.tistory.com/151&quot;&gt;DOTS 1.0 - 기본 (Component, System, Aspect, Job)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tsyang.tistory.com/155&quot;&gt;Entities - 컴포넌트 구조&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;왜 Hybrid가 필요한가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS는 성능이 좋다. 데이터가 청크에 연속으로 저장되어 캐시 친화적이고, Burst 컴파일 + Job 시스템으로 병렬 처리도 된다. 그런데 문제가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유니티의 모든 기능이 ECS로 제공되지는 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Animator, ParticleSystem, Light, VFX Graph, AudioSource 같은 것들은 모두 MonoBehaviour 기반이다. 이것들은 managed 객체이며 ECS 청크에 struct처럼 넣을 수가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, ECS로 적 유닛 1000마리를 시뮬레이션한다고 치자. 이동이나 AI 의사결정은 Burst+Job으로 돌릴 수 있다. 그런데 각 적마다 Animator로 걷기/공격 애니메이션을 재생하려면? Animator는 MonoBehaviour이므로 ECS 세계 밖의 GameObject가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 선택지는 두 가지다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;이런 기능을 안 쓴다 &amp;rarr; 비현실적&lt;/li&gt;
&lt;li&gt;ECS와 GameObject 세계를 &lt;b&gt;같이 쓴다&lt;/b&gt; &amp;rarr; Hybrid&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 DOTS 프로젝트가 Hybrid로 동작한다. &lt;b&gt;시뮬레이션은 ECS로, 비주얼은 GameObject로.&lt;/b&gt; 이 조합을 많이 쓴다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Hybrid 접근법 3가지&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity에 managed 데이터를 붙이는 방법은 세 가지가 있다. 하나씩 보자.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. struct IComponentData (순수 ECS)&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public struct Health : IComponentData
{
    public float Value;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본적인 형태다. ECS 청크에 직접 저장되고, &lt;b&gt;Burst 컴파일 가능, Job 스케줄 가능, 성능 최고.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 blittable한 값 타입만 저장할 수 있다. 문자열, 배열, UnityEngine.Object 같은 managed 참조는 못 넣는다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. class IComponentData (관리형 컴포넌트)&lt;/h4&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class PresentationGo : IComponentData
{
    public GameObject Prefab;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;class로 선언하면 managed 참조를 저장할 수 있다. 청크가 아닌 별도의 managed 배열에 저장되고, 청크에는 인덱스만 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Burst 불가, Job 불가, 메인 스레드 전용.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 이점은 전혀 없지만, Entity에 managed 데이터를 연결해야 할 때 쓸 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. Companion GameObject&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실제 UnityEngine.Component(MonoBehaviour)를 Entity에 붙이는 방식이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Light, Animator, ParticleSystem 같은 컴포넌트는 어차피 GameObject 위에서만 돌아간다. 그러면 숨겨진 GameObject를 하나 만들어서 Entity와 연결하면 되지 않겠나? 이 숨겨진 GameObject를 &lt;b&gt;Companion GameObject&lt;/b&gt;라고 부른다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;비교&lt;/h4&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;struct IComponentData&lt;/th&gt;
&lt;th&gt;class IComponentData&lt;/th&gt;
&lt;th&gt;Companion GO&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;저장 위치&lt;/td&gt;
&lt;td&gt;ECS 청크&lt;/td&gt;
&lt;td&gt;managed 배열&lt;/td&gt;
&lt;td&gt;힙 (숨겨진 GO)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Burst/Job&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;managed 참조&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O (그 자체가 managed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transform 동기화&lt;/td&gt;
&lt;td&gt;수동&lt;/td&gt;
&lt;td&gt;수동&lt;/td&gt;
&lt;td&gt;&lt;b&gt;자동&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;생명주기 관리&lt;/td&gt;
&lt;td&gt;ECS가 처리&lt;/td&gt;
&lt;td&gt;수동 (IDisposable)&lt;/td&gt;
&lt;td&gt;&lt;b&gt;자동&lt;/b&gt; (CompanionLink)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 차이 : Companion GO는 Transform 동기화와 생명주기 관리가 자동이라는 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity가 이동하면 Companion GO도 따라가고, Entity가 파괴되면 Companion GO도 같이 파괴된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;class IComponentData로는 이걸 직접 다 구현해야 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Companion GO의 동작 원리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 Companion GO가 내부적으로 어떻게 돌아가는지 보자. 세 가지 요소로 구성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 숨겨진 GameObject&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;HideFlags&lt;/code&gt;가 설정된 실제 GameObject다. Light나 ParticleSystem 같은 MonoBehaviour 컴포넌트가 여기에 붙는다. Hierarchy 창에서는 안 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. CompanionLink&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity와 Companion GO를 연결하는 managed 컴포넌트다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;ICloneable&lt;/code&gt;과 &lt;code&gt;IDisposable&lt;/code&gt;을 구현하고 있어서, Entity 프리팹을 Instantiate하면 Companion GO도 복제되고, Entity를 Destroy하면 Companion GO도 파괴된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. CompanionGameObjectUpdateTransformSystem&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매 프레임 Entity의 &lt;code&gt;LocalToWorld&lt;/code&gt;를 Companion GO의 &lt;code&gt;Transform&lt;/code&gt;에 복사해주는 빌트인 시스템이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동기화 방향은 ECS &amp;rarr; GO 단방향이다.&lt;/b&gt; Companion GO의 Transform을 직접 수정하면 안 된다. 다음 프레임에 어차피 덮어쓰여진다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;사용법 1 : SubScene 베이킹 + AddComponentObject&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 간단한 방법부터 보자. SubScene 안에 Light나 ParticleSystem이 달린 GameObject를 넣으면, Entities Graphics가 자동으로 Companion GO를 만들어준다. Baker 코드가 필요 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Animator처럼 Baker에서 직접 붙여야 하는 경우도 있다. 다음의 코드를 보자.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public sealed class AnimatorCompanionAuthoring : MonoBehaviour
{
    public Animator Animator;

    private sealed class Baker : Baker&amp;lt;AnimatorCompanionAuthoring&amp;gt;
    {
        public override void Bake(AnimatorCompanionAuthoring a)
        {
            var animator = a.Animator ?? a.GetComponentInChildren&amp;lt;Animator&amp;gt;(true);
            if (animator == null) return;

            var e = GetEntity(animator.gameObject,
                TransformUsageFlags.Dynamic);

            AddComponentObject(e, animator);  // Animator를 Entity에 부착
            AddComponent(e, new AnimParameter { MoveSpeed = 0f });
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;AddComponentObject&lt;/code&gt;를 사용하면 UnityEngine.Component를 Entity에 붙일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 시스템에서는 &lt;code&gt;ManagedAPI.UnityEngineComponent&amp;lt;Animator&amp;gt;&lt;/code&gt;로 접근하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 실제로 ECS 데이터를 Animator에 넘겨주는 시스템을 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, Entity의 &lt;code&gt;PhysicsVelocity&lt;/code&gt;를 가져와서 Animator의 MoveSpeed 파라미터에 넣어주는 식이다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[UpdateInGroup(typeof(PresentationSystemGroup))]
partial struct AnimatorSyncSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var (animator, velocity) in SystemAPI
            .Query&amp;lt;SystemAPI.ManagedAPI.UnityEngineComponent&amp;lt;Animator&amp;gt;,
                   RefRO&amp;lt;PhysicsVelocity&amp;gt;&amp;gt;())
        {
            float speed = math.length(velocity.ValueRO.Linear);
            animator.Value.SetFloat(&quot;MoveSpeed&quot;, speed);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS 쪽에서 Burst+Job으로 계산한 물리 결과가 &lt;code&gt;PhysicsVelocity&lt;/code&gt;에 들어있고, 이 시스템이 그 값을 Animator에 넘겨주는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시뮬레이션(ECS) &amp;rarr; 비주얼(Animator) 단방향 흐름&lt;/b&gt;이 여기서도 그대로 적용된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;사용법 2 : 런타임에 Companion GO 직접 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기부터가 핵심이다. SubScene 베이킹이 아닌, &lt;b&gt;런타임에 동적으로&lt;/b&gt; Companion GO를 생성하는 패턴이다. 적이나 총알처럼 게임 중에 생겨나는 Entity에 비주얼을 붙여야 할 때 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 패턴은 두 가지 컴포넌트로 구성된다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// 1. &quot;프리팹 설정&quot; &amp;mdash; 어떤 GO를 생성할지 (managed IComponentData)
public class PresentationGo : IComponentData
{
    public GameObject Prefab;
}

// 2. &quot;인스턴스 링크&quot; &amp;mdash; 생성된 GO 참조 (ICleanupComponentData)
public class PresentationGoLink : ICleanupComponentData
{
    public GameObject Instance;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 &lt;code&gt;ICleanupComponentData&lt;/code&gt;를 쓸까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Entity가 파괴되어도 Cleanup 컴포넌트는 살아남기 때문이다.&lt;/b&gt; 덕분에 Cleanup 시스템이 GO를 정리할 시간이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Entity가 파괴되는 순간 GO 참조까지 날아가버리면 정리할 방법이 없겠지?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Authoring은 다음과 같이 작성한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class GoCompanionAuthoring : MonoBehaviour
{
    public GameObject Prefab;

    class GoCompanionAuthoringBaker : Baker&amp;lt;GoCompanionAuthoring&amp;gt;
    {
        public override void Bake(GoCompanionAuthoring authoring)
        {
            var entity = GetEntity(
                TransformUsageFlags.Dynamic | TransformUsageFlags.Renderable);
            AddComponentObject(entity,
                new PresentationGo { Prefab = authoring.Prefab });
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Init 시스템에서 실제로 GO를 생성한다. 여기가 좀 길지만 중요한 부분이니 자세히 보자.&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;[UpdateInGroup(typeof(InitializationSystemGroup))]
partial struct PresentationGoInitSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var entity in SystemAPI.QueryBuilder()
            .WithAll&amp;lt;LocalToWorld, PresentationGo&amp;gt;()
            .WithNone&amp;lt;PresentationGoLink&amp;gt;().Build()
            .ToEntityArray(Allocator.Temp))
        {
            var config = SystemAPI.ManagedAPI
                .GetComponent&amp;lt;PresentationGo&amp;gt;(entity);

            // GO 생성
            var go = Object.Instantiate(config.Prefab);

            // managed 컴포넌트들을 Entity에 부착
            state.EntityManager.AddComponentObject(entity, go.transform);

            var animator = go.GetComponent&amp;lt;Animator&amp;gt;();
            if (animator != null)
                state.EntityManager.AddComponentObject(entity, animator);

            // 생명주기 동기화 &amp;mdash; GO가 먼저 파괴되면 Entity도 파괴
            go.AddComponent&amp;lt;EntityGameObjectLifeSyncer&amp;gt;()
                .AssignEntity(entity, state.World);

            // 링크 저장
            state.EntityManager.AddComponentData(entity,
                new PresentationGoLink { Instance = go });

            // 초기 위치 동기화
            var ltw = SystemAPI.GetComponent&amp;lt;LocalToWorld&amp;gt;(entity);
            go.transform.position = ltw.Position;
            go.transform.rotation = ltw.Rotation;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 핵심을 정리하면 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;PresentationGo&lt;/code&gt;는 있는데 &lt;code&gt;PresentationGoLink&lt;/code&gt;는 아직 없는 Entity를 찾아서, GO를 생성하고, managed 컴포넌트들을 &lt;code&gt;AddComponentObject&lt;/code&gt;로 부착한 뒤, &lt;code&gt;PresentationGoLink&lt;/code&gt;에 인스턴스를 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 &lt;code&gt;PresentationGoLink&lt;/code&gt;가 있으면 &lt;code&gt;WithNone&lt;/code&gt; 조건에 걸려서 스킵되므로 &lt;b&gt;한 번만 실행&lt;/b&gt;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Transform 동기화 시스템이다. 매 프레임 ECS 위치를 GO에 복사한다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;[UpdateInGroup(typeof(PresentationSystemGroup))]
partial struct PresentationGoTransformSyncSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var (localToWorld, transform) in SystemAPI
            .Query&amp;lt;RefRO&amp;lt;LocalToWorld&amp;gt;,
                SystemAPI.ManagedAPI.UnityEngineComponent&amp;lt;Transform&amp;gt;&amp;gt;()
            .WithAll&amp;lt;PresentationGo&amp;gt;())
        {
            transform.Value.position = localToWorld.ValueRO.Position;
            transform.Value.rotation = localToWorld.ValueRO.Rotation;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 Cleanup 시스템이다. Entity가 파괴되면 GO도 같이 정리해야 한다.&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;partial struct PresentationGoCleanupSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        var ecb = SystemAPI.GetSingleton
            &amp;lt;BeginInitializationEntityCommandBufferSystem.Singleton&amp;gt;()
            .CreateCommandBuffer(state.WorldUnmanaged);

        // PresentationGo는 없지만 PresentationGoLink는 남아있는 Entity
        // = Entity가 파괴된 직후
        foreach (var (link, entity) in SystemAPI
            .Query&amp;lt;PresentationGoLink&amp;gt;()
            .WithNone&amp;lt;PresentationGo&amp;gt;().WithEntityAccess())
        {
            if (link.Instance != null)
                Object.Destroy(link.Instance);
            ecb.RemoveComponent&amp;lt;PresentationGoLink&amp;gt;(entity);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 핵심은 &lt;code&gt;WithNone&amp;lt;PresentationGo&amp;gt;&lt;/code&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity가 파괴되면 일반 컴포넌트인 &lt;code&gt;PresentationGo&lt;/code&gt;는 같이 제거되지만, &lt;code&gt;ICleanupComponentData&lt;/code&gt;인 &lt;code&gt;PresentationGoLink&lt;/code&gt;는 남아있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이를 이용해서 &quot;파괴된 직후&quot;의 Entity를 잡아내는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 패턴의 구조를 정리하면 이렇다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;시스템&lt;/th&gt;
&lt;th&gt;역할&lt;/th&gt;
&lt;th&gt;시점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PresentationGoInitSystem&lt;/td&gt;
&lt;td&gt;GO 생성 + Entity에 연결&lt;/td&gt;
&lt;td&gt;Entity 생성 직후 (1회)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PresentationGoTransformSyncSystem&lt;/td&gt;
&lt;td&gt;ECS &amp;rarr; GO 위치 동기화&lt;/td&gt;
&lt;td&gt;매 프레임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PresentationGoCleanupSystem&lt;/td&gt;
&lt;td&gt;Entity 파괴 시 GO 정리&lt;/td&gt;
&lt;td&gt;Entity 파괴 직후&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌트인 CompanionLink가 자동으로 해주는 것을 수동으로 구현한 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;귀찮아 보이지만, 이 방식은 &lt;b&gt;죽음 애니메이션 재생 후 지연 파괴&lt;/b&gt; 같은 커스텀 로직을 넣을 수 있다는 장점이 있다. 실제 프로젝트에서는 이쪽이 훨씬 유연하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의사항&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Burst 컴파일/Job 스케줄 불가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Companion GO 관련 코드는 managed 객체를 다루므로 Burst 컴파일이 안 된다. 메인 스레드에서만 실행해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Sync Point 주의&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;AddComponentObject&lt;/code&gt;는 구조적 변경(structural change)을 일으킨다. 실행 중인 모든 Job이 완료될 때까지 기다리는 sync point가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핫 패스에서 매 프레임 호출하면 큰일난다.&lt;/b&gt; 스폰 시점에 한 번만 호출하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Transform 동기화 방향&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS &amp;rarr; GO &lt;b&gt;단방향&lt;/b&gt;이다. Companion GO의 Transform을 직접 수정해봤자 다음 프레임에 덮어쓰여진다. 위치를 바꾸고 싶으면 Entity의 &lt;code&gt;LocalTransform&lt;/code&gt;을 수정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 성능 이점은 없다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 착각하면 안 된다. Companion GO 자체는 일반 GameObject와 동일한 성능이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 이점은 &lt;b&gt;Entity 쪽 시뮬레이션&lt;/b&gt;에서 나오는 것이다. 수천 개의 Entity를 Burst+Job으로 시뮬레이션하고, 비주얼만 Companion GO로 표현하는 게 핵심이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. UI는 지원 안 됨&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Canvas, TextMeshPro 등 UI 컴포넌트는 SubScene에서 Companion 컴포넌트로 사용할 수 없다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리 : 언제 무엇을 쓸까&lt;/b&gt;&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;상황&lt;/th&gt;
&lt;th&gt;방법&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;단순 데이터 (float, int, Entity 등)&lt;/td&gt;
&lt;td&gt;struct IComponentData&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;managed 참조가 필요하지만 GO는 필요 없음&lt;/td&gt;
&lt;td&gt;class IComponentData&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UnityEngine 컴포넌트가 필요 (Light, Animator, VFX 등)&lt;/td&gt;
&lt;td&gt;Companion GO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SubScene에 배치한 Light/ParticleSystem&lt;/td&gt;
&lt;td&gt;빌트인 Companion (자동)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;런타임 스폰 Entity에 비주얼 부착&lt;/td&gt;
&lt;td&gt;커스텀 Companion GO 패턴&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순수 ECS만으로 게임을 만드는 건 쉽지 않다. &lt;b&gt;시뮬레이션은 ECS, 비주얼은 Companion GO.&lt;/b&gt; 이 조합을 많이 쓴다.&lt;/p&gt;</description>
      <category>게임엔진/ECS(Unity)</category>
      <category>ECS</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/223</guid>
      <comments>https://tsyang.tistory.com/223#entry223comment</comments>
      <pubDate>Sun, 1 Mar 2026 22:22:02 +0900</pubDate>
    </item>
    <item>
      <title>ECS에서 Behavior Tree 구현하기 (ft. xNode)</title>
      <link>https://tsyang.tistory.com/221</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;ECS Behavior Tree&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS환경에서 Behavior Tree를 구현하려면 마땅한 패키지(에셋)이 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 xNode를 이용하여 손쉽게 구현했다. (&lt;a href=&quot;https://github.com/Siccity/xNode&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/Siccity/xNode&lt;/a&gt;, 무료임)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1063&quot; data-origin-height=&quot;1196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ec6ymg/dJMcacosBEB/US8sz3fGK3VJN5zDQhObY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ec6ymg/dJMcacosBEB/US8sz3fGK3VJN5zDQhObY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ec6ymg/dJMcacosBEB/US8sz3fGK3VJN5zDQhObY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fec6ymg%2FdJMcacosBEB%2FUS8sz3fGK3VJN5zDQhObY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1063&quot; height=&quot;1196&quot; data-origin-width=&quot;1063&quot; data-origin-height=&quot;1196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;xNode 만들기&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1770471586615&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract class BTNode : Node {
    [Input] public BTNode parent;
    [Output] public BTNode children;
    public float randomWeight = 1f;

    public virtual NodeType Type =&amp;gt; NodeType.Action;

    public virtual int GetNodeData() =&amp;gt; 0;               
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 기본이 될 Base 노드를 만들어준다.&lt;/p&gt;
&lt;pre id=&quot;code_1770471613425&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class SequenceNode : BTNode {
    public override NodeType Type =&amp;gt; NodeType.Sequence;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 이런식으로 Sequence, Selector, Condition, Action 노드들을 구현해주자. 그냥 껍데기만 있으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 xNode 그래프를 만들면 끝. (그래프 만드는 법은 AI한테 물어보자)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실제 Node 정의하기&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1770471924928&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;csharp&quot;&gt;&lt;code&gt;public struct AIBehaviorNode
{
    public NodeType Type;   // 노드 종류 (Selector, Sequence, Action...)
    public int DataID;          // ActionType이나 ConditionType의 Enum 값 (int로 저장)

    // 트리 탐색을 위한 인덱스들
    public int ChildrenStartIndex; // 첫 번째 자식이 배열 몇 번에 있는지 (-1이면 없음)
    public int ChildrenCount;      // 자식 개수
    public int NextSiblingIndex;   // 내 오른쪽 형제가 배열 몇 번에 있는지 (-1이면 없음)
    public float Weight;           // RandomSelector 등에서 사용할 가중치
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 노드는 위와 같이 정의한다. Node는 트리구조이므로 인덱스 찾는 과정을 직접 해줘야한다. (Node 자체는 1차원 어레이에 다 저장됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 시스템에서는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1770471950310&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public struct AIBehaviorBlobAsset
{
    public BlobArray&amp;lt;AIBehaviorNode&amp;gt; Nodes;
}

public struct BehaviorTreeState : IComponentData
{
    public BlobAssetReference&amp;lt;AIBehaviorBlobAsset&amp;gt; BehaviorTree;
    public int CurrentNodeIndex;     // 현재 실행 중인 노드 인덱스
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 형식으로 접근할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Bake하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;70&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kBpbM/dJMcahJ6gps/5jkmwuNvcNCnXCtJ1IITKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kBpbM/dJMcahJ6gps/5jkmwuNvcNCnXCtJ1IITKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kBpbM/dJMcahJ6gps/5jkmwuNvcNCnXCtJ1IITKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkBpbM%2FdJMcahJ6gps%2F5jkmwuNvcNCnXCtJ1IITKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;70&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;70&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Enemy Prefab에 Authoring 하나 붙여주자. 그리고 사용할 Behavior Tree 그래프를 연결한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤 이어 말하겠지만 이것도 구현 방식이 입맛따라 다를 것이다. (중앙에서 관리하고 id로 BT를 얻어오는 방식도 있을 수 있다.)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1770472045821&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using var blobBuilder = new BlobBuilder(Allocator.Temp);
ref var blobRoot = ref blobBuilder.ConstructRoot&amp;lt;AIBehaviorBlobAsset&amp;gt;();

var flatNodes = new List&amp;lt;AIBehaviorNode&amp;gt;();

var rootNode = authoring.graph.GetRoot(); 

if (rootNode != null)
    FlattenGraph(rootNode, flatNodes);

var nodeArray = blobBuilder.Allocate(ref blobRoot.Nodes, flatNodes.Count);
for (int i = 0; i &amp;lt; flatNodes.Count; i++)
    nodeArray[i] = flatNodes[i];

var blobRef = blobBuilder.CreateBlobAssetReference&amp;lt;AIBehaviorBlobAsset&amp;gt;(Allocator.Persistent);
AddBlobAsset(ref blobRef, out _);   //중복이면 유니티가 알아서 제거해줌.    

AddComponent(entity, new BehaviorTreeState
{
    BehaviorTree = blobRef,
    CurrentNodeIndex = 0,
});

AddComponent(entity, new AIBrain());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대략 Bake는 위와 같이 해주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FlattenGraph는 그냥 트리를 DFS로 순회하며 flatList에 실제로 ECS에서 사용할 AIBehaviorNode 컴포넌트를 넣어주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 관리의 효율성을 위해서 &lt;a href=&quot;https://tsyang.tistory.com/220&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BlobAsset&lt;/a&gt; 을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 엔티티마다 Behavior Tree에 대한 레퍼런스(8byte)를 갖게된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 여러 적 유닛이 동일한 Behavior Tree를 사용하는 경우는 어떨까?&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1770547426450&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var blobRef = blobBuilder.CreateBlobAssetReference&amp;lt;AIBehaviorBlobAsset&amp;gt;(Allocator.Persistent);
AddBlobAsset(ref blobRef, out _);   //중복이면 유니티가 알아서 제거해줌.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시 코드의 일부를 보면 AddBlobAsset을 해주고 있는데, 이러면 유니티가 blob 바이너리 데이터의 해쉬를 구해 중복을 방지해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연하게도 다른 Subscene에 있는 적 유닛이라면 중복으로 올라갈 수 있겠지만 이 편이 직관적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Behavior Tree 실행하기&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1770472815824&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NodeState TickNode(ref BlobArray&amp;lt;AIBehaviorNode&amp;gt; nodes, int nodeIndex,
    ref Unity.Mathematics.Random random, ref AIContext context)
{
    ref var node = ref nodes[nodeIndex];
    var ret = NodeState.Failure;

    switch (node.Type)
    {
        case NodeType.Selector:
            ret = ProcessSelector(ref nodes, ref node, ref random, ref context);
            break;
        case NodeType.Sequence:
            ret = ProcessSequence(ref nodes, ref node, ref random, ref context);
            break;
        case NodeType.Condition:
            ret = ProcessCondition(node.DataID, ref context);
            break;
        case NodeType.Action:
            ret = ProcessAction(node.DataID, ref context, ref random, nodeIndex);
            break;
        case NodeType.RandomSelector:
            ret = ProcessRandomSelector(ref nodes, ref node, ref random, ref context, nodeIndex);
            break;
    }

    return ret;
}

NodeState ProcessSelector(ref BlobArray&amp;lt;AIBehaviorNode&amp;gt; nodes, ref AIBehaviorNode node,
    ref Random random, ref AIContext context)
{
    int childIndex = node.ChildrenStartIndex;

    for (int i = 0; i &amp;lt; node.ChildrenCount; i++)
    {
        NodeState result = TickNode(ref nodes, childIndex, ref random, ref context);

        if (result == NodeState.Running) return NodeState.Running;
        if (result == NodeState.Success) return NodeState.Success; 
        
        childIndex = nodes[childIndex].NextSiblingIndex;
    }

    return NodeState.Failure; 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;System이나 Job 파놓고 매 프레임 돌려주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;BaseAI.gif&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8HRTp/dJMcacIMQdE/bmW7uxRds42UQyMi1SBH9K/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8HRTp/dJMcacIMQdE/bmW7uxRds42UQyMi1SBH9K/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8HRTp/dJMcacIMQdE/bmW7uxRds42UQyMi1SBH9K/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/8HRTp/dJMcacIMQdE/bmW7uxRds42UQyMi1SBH9K/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;874&quot; height=&quot;584&quot; data-filename=&quot;BaseAI.gif&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 돌아다니다가 =&amp;gt; 플레이어를 발견하면 공격 가능 거리로 가서 =&amp;gt; 공격함. 이런 Behavior Tree가 잘 작동하는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>게임엔진/ECS(Unity)</category>
      <category>AI</category>
      <category>behavior tree</category>
      <category>ECS</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/221</guid>
      <comments>https://tsyang.tistory.com/221#entry221comment</comments>
      <pubDate>Sun, 8 Feb 2026 15:03:01 +0900</pubDate>
    </item>
    <item>
      <title>각종 패키지 설치모음</title>
      <link>https://tsyang.tistory.com/222</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJmkr/dJMcafZMxxB/YxvpBkfaJEJbcTGPGrz3w0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJmkr/dJMcafZMxxB/YxvpBkfaJEJbcTGPGrz3w0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJmkr/dJMcafZMxxB/YxvpBkfaJEJbcTGPGrz3w0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJmkr%2FdJMcafZMxxB%2FYxvpBkfaJEJbcTGPGrz3w0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;263&quot; height=&quot;159&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 git URL로 받음&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;VContainer&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;https://github.com/hadashiA/VContainer.git?path=VContainer/Assets/VContainer&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;UniTask&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Nuget For Unity&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;R3&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;273&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwO67w/dJMcafFu2Qm/HBgdL3815CkwVHKkgIxlyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwO67w/dJMcafFu2Qm/HBgdL3815CkwVHKkgIxlyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwO67w/dJMcafFu2Qm/HBgdL3815CkwVHKkgIxlyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwO67w%2FdJMcafFu2Qm%2FHBgdL3815CkwVHKkgIxlyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;273&quot; height=&quot;98&quot; data-origin-width=&quot;273&quot; data-origin-height=&quot;98&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Nuget For Unity 설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvkeUZ/dJMcafrXcKh/s4HLGZ24kNeW6Dwk5px8KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvkeUZ/dJMcafrXcKh/s4HLGZ24kNeW6Dwk5px8KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvkeUZ/dJMcafrXcKh/s4HLGZ24kNeW6Dwk5px8KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvkeUZ%2FdJMcafrXcKh%2Fs4HLGZ24kNeW6Dwk5px8KK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;661&quot; height=&quot;155&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;155&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;R3 설치&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;https://github.com/Cysharp/R3.git?path=src/R3.Unity/Assets/R3.Unity&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 R3 패키지 설치 (nuget에서 r3받고 또 유니티 전용 패키지 받아야함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>게임엔진/유니티</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/222</guid>
      <comments>https://tsyang.tistory.com/222#entry222comment</comments>
      <pubDate>Sun, 8 Feb 2026 11:52:53 +0900</pubDate>
    </item>
    <item>
      <title>BlobAsset의 개념</title>
      <link>https://tsyang.tistory.com/220</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;상황&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS로 심리스 오픈월드를 구현하고싶다. 자연스럽게 지역과 지역을 넘나드려면 로딩 속도가 생명이다. 게임 데이터에는 여러가지가 있겠지만 NavMesh만 우선 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임 속에는 공중유닛, 수영할 수 있는 유닛, 지상유닛 등으로 나뉘어져 각각 NavMesh가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NavMesh는 굉장히 간략하게 보자면 폴리곤의 집합과 인접 데이터의 모음이라 할 수 있으며 이 데이터들의 길이는 제각각이다. 그럼 이걸 어떻게 구현할 것인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;DynamicBuffer?&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1770470810661&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public struct NavPolygonElement : IBufferElementData
{
    public int StartVertexIndex; 
    public int VertexCount;
    public int NeighborStart;    // 인접 인덱스 버퍼에서의 시작 위치
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS에서 가변배열하면 DynamicBuffer를 떠올릴 수 있다. 그리고 실제로 DynamicBuffer로 Navmesh를 구현할 수 있다. 유닛마다 NavMesh데이터를 한 벌씩 가지는 건 말이 안되니, 맵 데이터에서 한번 DynamicBuffer로 데이터를 변환하고 유닛마다 NavMesh의 id를 통해 접근할 수 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 이건 사실 좋지 않다. 우선 지역 데이터(Subscene)을 저장장치에서 메모리로 올린다. 이후 SubScene 파일에서 읽어온 데이터 스트림을 ECS 메모리 구조에 맞게 재구성 해야한다. 이 과정에서 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;ECS메모리 영역에 새로 힙을 할당하고 데이터를 복사&lt;/b&gt;&lt;/span&gt;하는 과정이 포함된다. 이러&amp;nbsp;다음 지역을 로드할 때 시간이 더 걸릴 뿐더러, 맵이 로드/해제 될 때 메모리 파편화가 생길 여지가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 DynamicBuffer는 특정 엔티티에 귀속된 가변 데이터다. 따라서 기본적으로 &lt;b&gt;Safety Check가 수행&lt;/b&gt;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;BlobAsset&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1770470771003&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public struct NavPolygonBlob
{
    public BlobArray&amp;lt;float3&amp;gt; Vertices;
    public BlobArray&amp;lt;int&amp;gt; NeighborIndices;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 필요한 데이터는 이미 Subscene이 bake될 때 다 마련됐다. 이걸 그대로 쓰면 안 될까? 라는 의문이 든다. 그렇다 Subscene이 로드될 때 그 데이터를 그대로 쓰는 게 BlobAsset이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BlobAsset은 불변(Immutable)의 바이너리 데이터 덩어리이다. SubScene이 로드될 때, 유니티는 이 데이터를 ECS의 메모리 영역에 복사하지 않고 그냥 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;디스크에 저장된 바이너리 상태 그대로 Native Memory 영역에 로드&lt;/b&gt;&lt;/span&gt;한다. 그리고 이것에 대한 참조 포인터를 넘겨주면 끝이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1770470916223&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public struct NavMeshInstance : IComponentData
{
    public BlobAssetReference&amp;lt;NavMeshBlob&amp;gt; BlobRef;
}

public void Execute(in NavMeshInstance instance)
{
    ref var mesh = ref instance.BlobRef.Value;
    var firstVertex = mesh.Vertices[0];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BlobAsset은 DynamicBuffer와 달리 Safety Check가 필요 없다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 사용법은 AI한테 물어보자.&lt;/p&gt;</description>
      <category>게임엔진/ECS(Unity)</category>
      <category>ECS</category>
      <author>tsyang</author>
      <guid isPermaLink="true">https://tsyang.tistory.com/220</guid>
      <comments>https://tsyang.tistory.com/220#entry220comment</comments>
      <pubDate>Sat, 7 Feb 2026 22:31:28 +0900</pubDate>
    </item>
  </channel>
</rss>