<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>agentnote 님의 블로그</title>
    <link>https://agentnote.tistory.com/</link>
    <description>agentnote 님의 블로그 입니다.
Threads, Instagram: @agent.note</description>
    <language>ko</language>
    <pubDate>Sat, 24 Oct 2026 02:49:15 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>agentnote</managingEditor>
    <item>
      <title>사내 서비스 셋을 티켓 시스템 하나로 잇기: AI 도우미 요청과 회의록 할 일이 티켓이 되기까지 (MCP는 왜 아직 아닌가)</title>
      <link>https://agentnote.tistory.com/13</link>
      <description>&lt;!-- 제목: 사내 서비스 셋을 티켓 시스템 하나로 잇기: AI 도우미 요청과 회의록 할 일이 티켓이 되기까지 (MCP는 왜 아직 아닌가) | 태그: Claude Code, MCP, 사내 AI 도입, AI 에이전트, 업무 자동화, API 연동, 빌드 로그, 생성형 AI --&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;&lt;strong&gt;요약.&lt;/strong&gt; 운영 대시보드의 AI 도우미가 받은 요청과, 보고서 서비스에 올라온 회의록의 할 일을 업무 티켓 시스템으로 보내도록 이었습니다. 서비스끼리 짝지어 잇지 않고, 모두 티켓 시스템의 연동 API 하나에만 맞췄습니다. 티켓을 만드는 일은 MCP가 아니라 이 연동 API로 합니다. MCP 서버는 사람을 대신해 티켓을 읽고 처리하는 창구로 따로 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;5화의 N×M 문제가 회사 안에서 생겼다&lt;/h2&gt;
&lt;p&gt;저희 팀에는 사내 서비스가 셋 있습니다. 업무 화면을 모은 운영 대시보드, 할 일을 관리하는 업무 티켓 시스템, 보고서와 회의록을 올리는 보고서 서비스입니다.&lt;/p&gt;
&lt;p&gt;일은 대시보드와 보고서 서비스에서 생기고, 처리는 티켓 시스템에서 합니다. 대시보드를 쓰다가 &quot;이 표에 이것도 보여 주면 좋겠다&quot;는 요청이 생기고, 회의가 끝나면 할 일이 생깁니다. 이걸 티켓 시스템으로 바로 보내는 것이 이번 작업의 목표였습니다.&lt;/p&gt;
&lt;p&gt;서비스가 둘일 때는 짝지어 이으면 됩니다. 하지만 AI를 쓰는 사내 앱은 계속 늘어납니다. &lt;a href=&quot;https://agentnote.tistory.com/11&quot;&gt;5화&lt;/a&gt;에서 본 &quot;앱 N개 × 도구 M개&quot; 문제가 회사 안에서도 그대로 생깁니다.&lt;/p&gt;
&lt;p&gt;이번 작업에서 제가 한 일은 기획입니다. 어떤 서비스가 무엇을 티켓으로 보낼지, 사람이 어디서 확인할지를 정했습니다. 코드는 대부분 Claude Code가 썼습니다.&lt;/p&gt;
&lt;p&gt;{경험: 사용자가 채움 — Claude Code 없이 했다면 이 연결에 무엇이 더 필요했을지, 또는 직접 기획만 하면서 느낀 점 한두 문장}&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;가운데 하나에 맞추기: 티켓 시스템의 연동 API&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVZEos/dJMcab0AljW/V7eflrvuWYfkTeIFlDq9OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVZEos/dJMcab0AljW/V7eflrvuWYfkTeIFlDq9OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVZEos/dJMcab0AljW/V7eflrvuWYfkTeIFlDq9OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVZEos%2FdJMcab0AljW%2FV7eflrvuWYfkTeIFlDq9OK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 1. 서비스들은 서로 잇지 않고 가운데 티켓 시스템에만 맞춥니다.&lt;/p&gt;

&lt;p&gt;구조는 단순합니다. 티켓 시스템이 가운데에 서고, 다른 서비스는 티켓 시스템의 연동 API 하나에만 맞춥니다. 서비스가 하나 늘어도 그 서비스가 연동 API에 한 번 맞추면 끝입니다.&lt;/p&gt;
&lt;p&gt;연동 API는 두 번에 걸쳐 자랐습니다. 7월 말 첫판은 공용 키 하나로 티켓을 만드는 것이 전부였고, 프로젝트와 담당자는 서버에 고정돼 있었습니다. 10월 중순 둘째 판에서 많은 것이 바뀌었습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;서비스별 키.&lt;/strong&gt; 부르는 서비스마다 키를 따로 줍니다. 키 하나를 끊어도 다른 서비스는 멈추지 않습니다. 짝마다 키를 나눠 갖는 방식은 서비스가 늘면 키도 곱으로 늘어난다는 메모가 설계 문서에 남아 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;받는 쪽이 정한다.&lt;/strong&gt; 어느 프로젝트가 어느 서비스의 티켓을 받을지는 티켓 시스템에서 프로젝트 담당자가 켭니다. 기본은 꺼짐입니다. 담당자로 지정할 수 있는 사람인지도 티켓 시스템이 판단합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;두 번 보내도 한 장.&lt;/strong&gt; 만들기 요청에 중복 방지 키를 붙입니다. 같은 키가 다시 오면 새로 만들지 않고 처음 만든 티켓을 돌려줍니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;상태는 부르는 쪽이 조회.&lt;/strong&gt; 티켓 시스템이 밖으로 알려 주는 기능(웹훅)이 없어서, 부르는 서비스가 키 묶음으로 상태를 한꺼번에 물어봅니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;요청 기록.&lt;/strong&gt; 모든 호출을 요청 번호와 함께 남겨, 문제가 생기면 양쪽에서 같은 번호로 찾습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;티켓 만들기는 왜 MCP가 아닐까&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/11&quot;&gt;5화&lt;/a&gt;와 &lt;a href=&quot;https://agentnote.tistory.com/12&quot;&gt;6화&lt;/a&gt;에서 MCP를 다뤘으니, 티켓도 MCP로 만든다고 짐작하기 쉽습니다. 그런데 티켓을 만드는 일은 MCP가 아니라 위의 연동 API로 합니다.&lt;/p&gt;
&lt;p&gt;티켓 시스템에는 MCP 서버가 따로 있습니다. 도구는 다섯 개입니다. 티켓 목록, 상세, 검색, 상태 바꾸기, 댓글 달기입니다. 이 서버는 &quot;특정 사람을 대신해, 그 사람의 권한으로&quot; 움직이도록 설계됐습니다. 요청마다 그 사람의 로그인 토큰을 확인하고, 그 사람으로서 티켓 시스템을 부릅니다.&lt;/p&gt;
&lt;p&gt;반면 대시보드나 보고서 서비스가 만드는 티켓은 서비스가 보내는 티켓입니다. 사람의 권한보다 &quot;어느 서비스가 보냈나&quot;가 중요합니다. 그리고 MCP 도구에는 티켓 만들기와 첨부가 없습니다. 그래서 대시보드 기획 문서에는 이렇게 정리돼 있습니다. 만들기와 상태 조회는 연동 API로, MCP는 개발팀의 Claude Code가 티켓을 읽고 처리하는 쪽에 씁니다. 연동 계약 문서의 원칙도 &quot;연동 API 먼저, MCP는 나중&quot;입니다.&lt;/p&gt;
&lt;p&gt;MCP를 안 쓰는 게 아니라 쓰는 자리가 다릅니다. 앞으로 AI를 쓰는 사내 앱이 사용자를 대신해 티켓을 찾고 댓글을 다는 일은 MCP 서버가 맡습니다. 예를 들어 보고서 서비스의 대화형 검색 챗봇은 지금 도구를 쓰지 않는데, 나중에 이런 앱이 MCP 클라이언트가 될 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;AI 도우미에게 한 말이 티켓이 되기까지&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b44E26/dJMcaiyBXGO/iJ0NXhKIzuhb2mJC0locfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b44E26/dJMcaiyBXGO/iJ0NXhKIzuhb2mJC0locfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b44E26/dJMcaiyBXGO/iJ0NXhKIzuhb2mJC0locfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb44E26%2FdJMcaiyBXGO%2FiJ0NXhKIzuhb2mJC0locfK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 2. 모델은 초안과 목업까지 만들고, 티켓은 사람이 등록을 눌러야 생깁니다.&lt;/p&gt;

&lt;p&gt;대시보드에는 화면 구석에 AI 도우미가 있습니다. 사용자가 &quot;이 표에 지난달 값도 보여 주세요&quot;처럼 말하면 다음 순서로 티켓이 됩니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;정리.&lt;/strong&gt; 모델이 대화를 읽고 &quot;어느 화면의, 지금은 어떻고, 바꾸면 어떻게, 그대로 둘 것은&quot;으로 정리합니다. 애매하면 확인 질문을 하나 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;초안.&lt;/strong&gt; 제목, 요청, 이유, 급한 정도를 채웁니다. 요청은 사용자 말 그대로 쓰고 지어내지 않게 했습니다. 모델이 실패하면 사용자 원문으로 만든 초안을 대신 돌려줍니다. 코드 주석에는 &quot;요청을 잃는 쪽이 어색한 초안보다 비싸다&quot;고 적혀 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;목업.&lt;/strong&gt; 바뀐 화면을 그림으로 보여 줍니다. 빠른 스케치는 지금 화면의 한 조각을 모델에게 주고 바뀐 HTML을 받아 그립니다. 모델이 준 HTML은 믿지 않습니다. 허용한 태그만 남기고, 스크립트가 돌지 않는 샌드박스에서 그립니다. 더 정식 목업이 필요하면 컨테이너에서 &lt;strong&gt;헤드리스 Claude Code&lt;/strong&gt;를 돌립니다. 운영 중인 코드 판을 받아 화면을 고친 HTML을 만들고, 헤드리스 브라우저로 찍습니다. 도구는 파일 읽기와 쓰기만 주고, 외부 MCP는 끄고, 비용과 시간에 상한을 걸었습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;사람이 등록.&lt;/strong&gt; 확인 카드에서 제목, 마감, 참조자를 고치고 &quot;등록&quot;을 눌러야 티켓이 생깁니다. 모델은 초안까지만 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;티켓과 첨부.&lt;/strong&gt; 티켓을 먼저 만들고, 바뀌기 전·후 그림을 첨부로 올립니다. 첨부가 실패해도 티켓은 남고, 다시 보낼 때는 빠진 파일만 보냅니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;완료 알림.&lt;/strong&gt; 상태를 되돌려 받다가 티켓이 끝나면, 사용자가 다음에 들어왔을 때 도우미가 말풍선으로 알려 줍니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;회의록의 할 일 한 줄이 티켓이 되기까지&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n2uD0/dJMcaik0wsk/xtP3X1Tthky1lJWsP50STK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n2uD0/dJMcaik0wsk/xtP3X1Tthky1lJWsP50STK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n2uD0/dJMcaik0wsk/xtP3X1Tthky1lJWsP50STK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn2uD0%2FdJMcaik0wsk%2FxtP3X1Tthky1lJWsP50STK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 3. 담당자와 기한은 모델이 아니라 표와 규칙이 정합니다.&lt;/p&gt;

&lt;p&gt;보고서 서비스에는 회의록이 올라옵니다. 회의록은 정해진 템플릿을 따르고, 끝에 할 일 표(내용, 담당, 기한)가 있습니다.&lt;/p&gt;
&lt;p&gt;여기서는 모델에게 맡기는 범위를 일부러 좁혔습니다. 할 일과 담당, 기한은 표에서 규칙으로 읽습니다. 모델은 각 줄의 종류를 분류하는 일만 합니다. 모델이 원문에 없는 할 일을 지어내면 버립니다.&lt;/p&gt;
&lt;p&gt;담당 칸에 적힌 이름은 관리자가 만든 규칙에 맞춥니다. 규칙에는 이름과 별칭, 받을 프로젝트, 담당자와 참조자가 있고, 한 명에게 줄지 돌아가며 줄지도 정합니다. 기본은 &quot;검토&quot; 모드라서, 규칙에 없거나 애매한 줄은 확인함에 쌓이고 관리자가 승인합니다. 티켓이 만들어진 뒤에는 주기적으로 상태를 받아 회의록 위키에 &quot;완료&quot;, &quot;진행 중&quot;, &quot;다시 열림&quot;을 표시합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;연결을 튼튼하게 만든 다섯 가지&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZA8Nl/dJMcaik0wtR/QM9kSfOafURJoLkzlGD910/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZA8Nl/dJMcaik0wtR/QM9kSfOafURJoLkzlGD910/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZA8Nl/dJMcaik0wtR/QM9kSfOafURJoLkzlGD910/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZA8Nl%2FdJMcaik0wtR%2FQM9kSfOafURJoLkzlGD910%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 4. 대부분 한 번씩 문제가 생긴 뒤에 들어간 장치입니다.&lt;/p&gt;

&lt;p&gt;처음부터 다 갖춘 것은 아닙니다. 대부분 문제가 한 번 생긴 뒤에 들어갔습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;중복 방지 키를 무엇으로 만들까.&lt;/strong&gt; 같은 회의록을 고쳐서 다시 올렸더니 티켓이 겹쳤습니다. 키를 &quot;할 일 문장 + 규칙 이름&quot;으로 바꿨습니다. 담당자로 만들면 돌아가며 배정할 때마다, 규칙 번호로 만들면 규칙을 지웠다 다시 만들 때마다 키가 바뀌기 때문입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;거절과 일시 오류를 나누기.&lt;/strong&gt; 요청이 잘못돼 거절되면(4xx) 다시 보내도 또 거절됩니다. 이런 줄은 사람에게 넘깁니다. 연결이 끊기거나 서버 오류일 때만 나중에 다시 보냅니다. 두 서비스의 연결 코드 모두 오류를 던지지 않고 결과로 돌려줍니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;재시도 상한.&lt;/strong&gt; 먼저 만든 보고서 서비스는 일시 오류 재시도에 상한이 없었습니다. 나중에 만든 대시보드는 그걸 보고 상한부터 넣었습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;연동 꺼짐&quot;을 장애와 따로.&lt;/strong&gt; 티켓 시스템에서 프로젝트 받기를 꺼 두면, 보내는 쪽에서는 그게 장애처럼 보였습니다. 지금은 &quot;연결 실패&quot;와 &quot;연동 꺼짐&quot;을 다르게 표시합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;같은 내부망이면 내부 주소로.&lt;/strong&gt; 처음에는 티켓 시스템의 공용 주소로 불렀는데 계속 시간 초과가 났습니다. 같은 내부망 안인데도 트래픽이 인터넷으로 나갔다가 들어와서 방화벽 규칙에 맞지 않았던 것입니다. 내부 주소로 바꾸자 해결됐습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;Claude Code로 세 저장소를 맞춘 방법: 계약 문서 하나&lt;/h2&gt;
&lt;p&gt;서비스마다 저장소가 따로 있고, Claude Code 세션도 저장소마다 따로 돌았습니다. 보고서 서비스 쪽 세션은 &quot;티켓을 이렇게 보내겠다&quot;를 알고, 티켓 시스템 쪽 세션은 &quot;이렇게 받겠다&quot;를 압니다. 둘이 서로의 코드를 보지 않으니 어긋나기 쉽습니다.&lt;/p&gt;
&lt;p&gt;그래서 연동 계약 문서 하나를 두 세션이 함께 읽는 기준으로 삼았습니다. 요청과 응답 모양, 오류 코드, 중복 방지 키 규칙이 모두 이 문서에 있습니다. 그리고 계약대로 동작하는지 실제 서버에 대고 확인하는 점검 스크립트를 두었습니다. 대시보드를 붙일 때도 이 문서와 앞서 만든 보고서 서비스의 코드를 읽고 시작해서, 재시도 상한 같은 교훈을 그대로 가져왔습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;내 팀에 적용한다면&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;가운데를 먼저 정하기.&lt;/strong&gt; 일이 모이는 시스템 하나를 정하고, 다른 서비스는 거기에만 맞추게 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;모델에게 맡길 범위를 좁게.&lt;/strong&gt; 담당자, 기한, 최종 등록처럼 틀리면 곤란한 것은 규칙과 사람에게 둡니다. 모델은 초안과 분류만 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP와 연동 API의 자리를 나누기.&lt;/strong&gt; 서비스가 기계적으로 보내는 일은 서비스 키를 쓰는 연동 API로, 사람을 대신해 읽고 처리하는 일은 MCP로 둡니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;저장소가 여럿이면 계약 문서 하나.&lt;/strong&gt; Claude Code 세션이 여럿이어도 같은 문서를 읽게 하면 덜 어긋납니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 처음부터 MCP 하나로 다 하면 안 되나요?&lt;/strong&gt;
할 수는 있습니다. 다만 MCP 서버가 &quot;사람 대신&quot; 움직이게 만들었다면, 서비스가 보내는 티켓을 같은 창구로 받으면 누구의 권한으로 만들었는지가 흐려집니다. 그래서 저희는 둘을 나눴습니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 모델이 만든 티켓 초안이 틀리면요?&lt;/strong&gt;
그래서 사람이 등록을 눌러야 티켓이 생기게 했습니다. 회의록 쪽도 기본이 검토 모드라서, 애매한 줄은 관리자가 보고 승인합니다.&lt;/p&gt;</description>
      <category>AI/Engineering</category>
      <category>ai 에이전트</category>
      <category>api 연동</category>
      <category>claude code</category>
      <category>MCP</category>
      <category>빌드 로그</category>
      <category>사내 AI 도입</category>
      <category>생성형 ai</category>
      <category>업무 자동화</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/13</guid>
      <comments>https://agentnote.tistory.com/13#entry13comment</comments>
      <pubDate>Thu, 22 Oct 2026 15:38:16 +0900</pubDate>
    </item>
    <item>
      <title>MCP 서버 만들기: Python SDK로 함수 세 개, 26줄 첫 MCP 서버 (직접 짜면 400줄인 이유까지)</title>
      <link>https://agentnote.tistory.com/12</link>
      <description>&lt;!-- 제목: MCP 서버 만들기: Python SDK로 함수 세 개, 26줄 첫 MCP 서버 (직접 짜면 400줄인 이유까지) | 태그: MCP, MCP 서버, Model Context Protocol, Python, MCP Inspector, AI 에이전트, Claude, LLM, ai-engineering-from-scratch --&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;&lt;strong&gt;요약.&lt;/strong&gt; MCP 서버는 요청 한 줄을 읽고, 형식이 맞는지 확인하고, 맞는 함수를 불러서, 답 한 줄을 쓰는 프로그램입니다. 규격을 손으로 다 짜면 약 400줄이 나옵니다. 공식 Python SDK를 쓰면 평범한 함수에 &lt;code&gt;@mcp.tool()&lt;/code&gt; 표시 하나를 붙이는 것으로 끝나고, 같은 노트 서버가 26줄이 됩니다. 함수 이름과 설명, 인자 타입은 그대로 모델이 읽는 도구 설명이 됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;5화에서 이어지는 질문: MCP 서버는 직접 만들 수 있을까&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/11&quot;&gt;5화&lt;/a&gt;에서는 MCP를 쓰는 쪽에서 구조를 봤습니다. AI 앱(호스트) 안의 클라이언트가 서버 하나와 1대1로 붙고, 서버는 도구·리소스·프롬프트를 내놓습니다. 공식 파일 서버에 메시지를 보내 도구 14개를 받아 보기도 했습니다.&lt;/p&gt;
&lt;p&gt;그럼 반대쪽은 어떨까요? 팀에서 매번 손으로 찾는 정보가 있다면, 그걸 MCP 서버로 만들어 AI 앱에 붙일 수 있을까요? 만든다면 코드가 얼마나 필요할까요?&lt;/p&gt;
&lt;p&gt;이번 화는 같은 노트 서버를 두 번 만들어 보며 답을 찾습니다. 한 번은 원본 레슨처럼 표준 라이브러리만으로, 한 번은 공식 Python SDK로 만듭니다.&lt;/p&gt;
&lt;p&gt;{경험: 사용자가 채움 — MCP 서버를 처음 만들어 보기 전에 짐작했던 것, 또는 회사에서 &quot;이걸 서버로 만들면 좋겠다&quot; 싶었던 일 한 가지}&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;MCP 서버가 하는 일: 읽고, 확인하고, 부르고, 쓴다&lt;/h2&gt;
&lt;p&gt;MCP 서버를 식당 주문 창구에 비유해 보겠습니다. 손님(앱)이 주문서(요청)를 창구에 넣으면, 직원(서버)이 양식이 맞는지 보고, 맞는 주방(함수)에 넘기고, 음식(결과)을 한 접시씩 내줍니다.&lt;/p&gt;
&lt;p&gt;실제 순서도 같습니다. 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/07-building-an-mcp-server&quot;&gt;13-07 Building an MCP Server&lt;/a&gt;는 서버의 뼈대를 다섯 단계로 설명합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d5QpNa/dJMcaatJYfU/mH3pjoWIRAoRTakBxUADK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d5QpNa/dJMcaatJYfU/mH3pjoWIRAoRTakBxUADK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d5QpNa/dJMcaatJYfU/mH3pjoWIRAoRTakBxUADK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd5QpNa%2FdJMcaatJYfU%2FmH3pjoWIRAoRTakBxUADK1%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 1. 요청 하나를 처리하는 순서. 확인 단계에서 떨어지는 갈래가 두 개 있습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;한 줄 읽기.&lt;/strong&gt; 앱이 서버를 자기 컴퓨터에서 띄우면(stdio 방식), 요청은 표준 입력으로 JSON 한 줄씩 들어옵니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자기소개 확인.&lt;/strong&gt; 5화에서 본 대로 MCP 최신 판(2026-07-28)은 처음 인사를 없앴습니다. 대신 요청마다 &lt;code&gt;_meta&lt;/code&gt;에 &quot;나는 이 판을 쓰고, 이런 기능이 있다&quot;를 싣습니다. 서버는 이것부터 봅니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;맞는 함수 부르기.&lt;/strong&gt; 메서드 이름(&lt;code&gt;tools/list&lt;/code&gt;, &lt;code&gt;tools/call&lt;/code&gt; 등)을 보고 처리할 함수를 고릅니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;결과 감싸기.&lt;/strong&gt; 결과에 &quot;완료&quot; 표시와 서버 정보를 붙입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;한 줄 쓰기.&lt;/strong&gt; 표준 출력에 JSON 한 줄로 답하고, 그 요청은 잊습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;2단계에서 자기소개가 빠지면 서버는 앞 요청의 정보로 채우지 않고 오류(-32602)로 돌려보냅니다. 모르는 판이면 -32022와 함께 자기가 아는 판 목록을 알려 줍니다. 서버는 앞 요청을 기억하지 않습니다. 그래서 같은 서버 프로세스가 여러 클라이언트를 번갈아 받아도, 앞사람의 설정이 뒷사람 요청에 새어 들어가지 않습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;직접 짜면 약 400줄: 원본 레슨의 노트 서버&lt;/h2&gt;
&lt;p&gt;레슨은 이 뼈대를 Python 표준 라이브러리만으로 구현합니다. 노트를 다루는 서버이고, 도구 3개(노트 만들기, 목록, 검색), 리소스(노트 내용), 프롬프트 1개(노트 검토 요청)를 내놓습니다. &lt;code&gt;code/main.py&lt;/code&gt;는 409줄입니다. TypeScript 판(&lt;code&gt;main.ts&lt;/code&gt;)도 같은 일을 합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X3Msh/dJMcafhuaE7/TCG5zZyaBhGFwmgRKlgRak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X3Msh/dJMcafhuaE7/TCG5zZyaBhGFwmgRKlgRak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X3Msh/dJMcafhuaE7/TCG5zZyaBhGFwmgRKlgRak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX3Msh%2FdJMcafhuaE7%2FTCG5zZyaBhGFwmgRKlgRak%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 2. 왼쪽은 서버가 직접 해야 하는 일, 오른쪽은 그 일을 SDK에 맡긴 코드입니다.&lt;/p&gt;

&lt;p&gt;400줄 대부분은 &quot;노트&quot;와 상관없는 일입니다. 요청마다 자기소개를 검증하고, 메서드별로 나누고, 결과를 같은 모양으로 감싸고, 도구 목록을 늘 같은 순서로 내놓고, 상황에 맞는 오류 코드를 고릅니다. 레슨은 모든 성공 결과가 감싸기 함수 하나를 거치게 해서, 처리기 하나가 필드를 빠뜨리는 실수를 막습니다.&lt;/p&gt;
&lt;p&gt;레슨 코드는 함께 들어 있는 테스트 10개를 모두 통과하고, 데모도 설명대로 돌아갑니다. 검색어를 비워서 부르면 &quot;검색어가 비어 있다&quot;는 결과가, JSON이 아닌 줄을 보내면 파싱 오류가 돌아옵니다.&lt;/p&gt;
&lt;p&gt;직접 짜 보면 좋은 점이 있습니다. 규격이 서버에 무엇을 요구하는지 하나도 빠짐없이 보입니다. 하지만 노트 검색 하나를 붙이자고 매번 400줄을 쓸 수는 없습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;Python SDK로 MCP 서버 만들기: 함수에 표시 하나&lt;/h2&gt;
&lt;p&gt;같은 서버를 &lt;a href=&quot;https://github.com/modelcontextprotocol/python-sdk&quot;&gt;공식 Python SDK&lt;/a&gt;(PyPI &lt;code&gt;mcp&lt;/code&gt; 2.3.0)로 다시 만들면 이렇게 됩니다. 도구를 1개로 줄였지만 리소스와 프롬프트는 그대로 있습니다.&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from mcp.server import MCPServer

mcp = MCPServer(&amp;quot;notes-sdk&amp;quot;)
NOTES = {&amp;quot;note-1&amp;quot;: &amp;quot;Stateless requests and JSON-RPC.&amp;quot;, &amp;quot;note-2&amp;quot;: &amp;quot;Provider envelopes differ.&amp;quot;}


@mcp.tool()
def notes_search(query: str, limit: int = 10) -&amp;gt; list[str]:
    &amp;quot;&amp;quot;&amp;quot;Search note bodies by keyword.&amp;quot;&amp;quot;&amp;quot;
    return [k for k, v in sorted(NOTES.items()) if query.lower() in v.lower()][:limit]


@mcp.resource(&amp;quot;notes://{note_id}&amp;quot;)
def note(note_id: str) -&amp;gt; str:
    &amp;quot;&amp;quot;&amp;quot;Read one note.&amp;quot;&amp;quot;&amp;quot;
    return NOTES[note_id]


@mcp.prompt()
def review_note(note_id: str) -&amp;gt; str:
    &amp;quot;&amp;quot;&amp;quot;Ask for a review of one note.&amp;quot;&amp;quot;&amp;quot;
    return f&amp;quot;Review this note and propose improvements:\n\n{NOTES[note_id]}&amp;quot;


if __name__ == &amp;quot;__main__&amp;quot;:
    mcp.run()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;26줄입니다. 평범한 Python 함수 세 개에 각각 &lt;code&gt;@mcp.tool()&lt;/code&gt;, &lt;code&gt;@mcp.resource()&lt;/code&gt;, &lt;code&gt;@mcp.prompt()&lt;/code&gt;를 붙였을 뿐입니다. 검증, 결과 감싸기, 오류 코드, 표준 입출력은 SDK가 맡습니다.&lt;/p&gt;
&lt;p&gt;더 흥미로운 것은 도구 설명이 어디서 오느냐입니다. 이 서버에 &quot;무엇을 할 수 있나요?&quot;(&lt;code&gt;tools/list&lt;/code&gt;)를 물으면, 함수를 그대로 옮긴 도구 설명이 돌아옵니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhBjz8/dJMcaggjhYy/MKpBZaAaILMaBtnEghuT1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhBjz8/dJMcaggjhYy/MKpBZaAaILMaBtnEghuT1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhBjz8/dJMcaggjhYy/MKpBZaAaILMaBtnEghuT1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhBjz8%2FdJMcaggjhYy%2FMKpBZaAaILMaBtnEghuT1K%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 3. 실제 `tools/list` 응답을 줄였습니다. 기본값이 없는 `query`만 필수가 됩니다.&lt;/p&gt;

&lt;p&gt;함수 이름은 도구 이름이 되고, docstring은 도구 설명이 됩니다. 인자 타입(&lt;code&gt;query: str, limit: int = 10&lt;/code&gt;)은 입력 스키마가 되는데, 기본값이 없는 &lt;code&gt;query&lt;/code&gt;만 필수로 표시됩니다. 반환 타입 &lt;code&gt;list[str]&lt;/code&gt;은 출력 스키마가 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/8&quot;&gt;2화&lt;/a&gt;에서 본 것처럼 모델은 이 도구 설명만 보고 언제 무엇을 부를지 정합니다. 그러니 MCP 서버를 만들 때 가장 공들일 곳은 코드 줄 수가 아닙니다. 함수 이름과 docstring을 모델이 알아듣게 쓰는 일입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;직접 만든 서버, 어떤 클라이언트와 통할까&lt;/h2&gt;
&lt;p&gt;여기서 5화의 &quot;바뀌는 중&quot;이 다시 나옵니다. MCP에는 지금 두 판이 함께 쓰입니다. 처음에 인사(&lt;code&gt;initialize&lt;/code&gt;)를 나누는 2025-11-25 판과, 인사 없이 요청마다 자기소개를 싣는 2026-07-28 판입니다.&lt;/p&gt;
&lt;p&gt;두 서버에 클라이언트 다섯 가지로 접속해 본 결과입니다(2026-10-19 기준).&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLfSlZ/dJMcaggjh0G/MExih9jWWJraRy8ii4DSm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLfSlZ/dJMcaggjh0G/MExih9jWWJraRy8ii4DSm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLfSlZ/dJMcaggjh0G/MExih9jWWJraRy8ii4DSm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLfSlZ%2FdJMcaggjh0G%2FMExih9jWWJraRy8ii4DSm0%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 4. ○는 도구 목록과 호출까지 성공, ×는 연결 실패입니다.&lt;/p&gt;

&lt;p&gt;레슨 서버는 일부러 최신 판만 받도록 만들었습니다. 레슨도 이 점을 밝힙니다. 그래서 최신 판으로 말하는 Python SDK 클라이언트와는 잘 통합니다. 하지만 이전 판으로 말하는 TypeScript SDK 1.32.1 클라이언트와, 기본 설정으로 띄운 MCP Inspector(서버 점검 도구)는 &quot;&lt;code&gt;_meta&lt;/code&gt;가 필요하다&quot;는 오류를 받고 연결하지 못했습니다.&lt;/p&gt;
&lt;p&gt;SDK 서버는 다섯 가지 모두와 통했습니다. 최신 판으로 물으면 최신 판으로, 이전 판으로 인사하면 이전 판으로 답합니다. 레슨이 연습문제로 남겨 둔 &quot;두 판 모두 받기&quot;를 SDK가 기본으로 해 줍니다.&lt;/p&gt;
&lt;p&gt;그래서 이번 화의 결론은 이렇습니다. 규격을 이해하려면 레슨처럼 직접 짜 보는 것이 좋습니다. 실제로 앱에 붙일 서버는 SDK로 만드는 편이 안전합니다. 명세는 앞서가고 도구들은 아직 따라가는 중이기 때문입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;MCP 서버 오류는 두 종류: 모델이 고칠 수 있게&lt;/h2&gt;
&lt;p&gt;서버를 만들면 오류를 어떻게 돌려줄지도 정해야 합니다. &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/server/tools&quot;&gt;MCP 명세 2026-07-28 Tools 절&lt;/a&gt;은 오류를 두 종류로 나눕니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1wOfu/dJMcairDDLU/lqLrUwFeFgXOIvr9QNbJs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1wOfu/dJMcairDDLU/lqLrUwFeFgXOIvr9QNbJs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1wOfu/dJMcairDDLU/lqLrUwFeFgXOIvr9QNbJs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1wOfu%2FdJMcairDDLU%2FlqLrUwFeFgXOIvr9QNbJs0%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 5. 왼쪽은 요청 자체가 틀린 경우, 오른쪽은 요청은 맞는데 실행이 실패한 경우입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;프로토콜 오류&lt;/strong&gt;: 요청 자체가 잘못된 경우입니다. 자기소개가 없거나, 모르는 판이거나, JSON이 아닌 경우입니다. JSON-RPC의 &lt;code&gt;error&lt;/code&gt;로 돌려줍니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;도구 실행 오류&lt;/strong&gt;: 요청 모양은 맞는데 도구가 돌다 실패한 경우입니다. 검색어가 비었거나, 바깥 API가 실패한 경우입니다. 정상 결과에 &lt;code&gt;isError: true&lt;/code&gt;를 달아 돌려줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;차이는 누가 그 오류를 보느냐입니다. 명세는 도구 실행 오류를 앱이 모델에게 보여 줘야 한다고(SHOULD) 적습니다. 모델이 &quot;검색어가 비어 있다&quot;는 문장을 읽고 고쳐서 다시 부를 수 있게 하려는 것입니다. 그러니 도구 안에서 실패했을 때는 &quot;잘못된 요청&quot;보다 &quot;검색어를 한 글자 이상 넣어 주세요&quot;처럼 모델이 읽고 고칠 수 있는 문장으로 돌려주는 것이 좋습니다.&lt;/p&gt;
&lt;p&gt;SDK 서버에 필수 인자 &lt;code&gt;query&lt;/code&gt;를 빼고 부르면, SDK가 알아서 검증 오류 문구를 &lt;code&gt;isError: true&lt;/code&gt;로 돌려줍니다. 타입 힌트가 스키마이자 검증 규칙이 되는 셈입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;실행하다 막힌 곳 두 가지&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;printf로 한꺼번에 보내면 답이 일부만 온다.&lt;/strong&gt; 5화처럼 &lt;code&gt;printf&lt;/code&gt;로 요청 세 줄을 파이프로 보내면, SDK 서버는 세 번 중 응답을 1개, 2개, 1개만 돌려줬습니다. 입력이 끝나면(stdin EOF) 처리 중인 요청을 기다리지 않고 종료하기 때문입니다. &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio&quot;&gt;명세 stdio 절&lt;/a&gt;이 &quot;stdin이 닫히면 곧 종료해야 한다&quot;고 하니 잘못된 동작은 아닙니다. 한 줄씩 동기로 처리하는 레슨 서버는 같은 방법으로 보내도 전부 답했습니다. SDK 서버를 확인할 때는 아래 &quot;따라 해 보기&quot;의 Inspector를 쓰면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;도구 안에서 print()를 쓰면.&lt;/strong&gt; stdio 서버는 표준 출력에 MCP 메시지만 써야 합니다. 로그는 표준 오류(stderr)로 보냅니다. &lt;a href=&quot;https://modelcontextprotocol.io/docs/develop/build-server&quot;&gt;공식 튜토리얼 &quot;Build an MCP server&quot;&lt;/a&gt;는 stdout에 쓰면 &quot;JSON-RPC 메시지가 망가지고 서버가 깨진다&quot;고 경고합니다. 검색 도구 안에 &lt;code&gt;print()&lt;/code&gt; 한 줄을 넣고 Python SDK 클라이언트로 불러 보면, 클라이언트 쪽에 파싱 오류가 찍혔습니다. 이번에는 그 줄만 버려지고 호출 결과는 정상으로 왔지만, 클라이언트마다 처리가 다를 수 있습니다. 로그는 Python 표준 &lt;code&gt;logging&lt;/code&gt;(기본 출력이 stderr)으로 남기는 습관을 들이는 게 좋습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;따라 해 보기&lt;/h2&gt;
&lt;p&gt;준비물은 &lt;a href=&quot;https://docs.astral.sh/uv/&quot;&gt;uv&lt;/a&gt;(Python 패키지 실행 도구)와 Node.js입니다. API 키는 필요 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 서버 파일 만들기.&lt;/strong&gt; 위의 26줄 코드를 &lt;code&gt;notes_server.py&lt;/code&gt;로 저장합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Inspector로 도구 목록 보기.&lt;/strong&gt; MCP Inspector는 공식 서버 점검 도구입니다. &lt;code&gt;--cli&lt;/code&gt;를 주면 화면 없이 명령줄에서 요청을 보내고 결과를 보여 줍니다.&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;# 최신 판(2026-07-28)으로 도구 목록 묻기
npx -y @modelcontextprotocol/inspector --cli uv run --with mcp python notes_server.py --protocol-era modern --method tools/list

# 기본값(이전 판)으로 도구 부르기
npx -y @modelcontextprotocol/inspector --cli uv run --with mcp python notes_server.py --method tools/call --tool-name notes_search --tool-arg query=json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;첫 명령에서 그림 3의 도구 설명이, 둘째 명령에서 &lt;code&gt;note-1&lt;/code&gt;이 나오면 성공입니다. 두 판 모두 답한다는 것도 함께 확인됩니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. (선택) Claude Code에 붙이기.&lt;/strong&gt; &lt;a href=&quot;https://code.claude.com/docs/en/mcp&quot;&gt;Claude Code 공식 문서 &quot;Connect Claude Code to tools via MCP&quot;&lt;/a&gt;에 따르면 아래처럼 등록합니다. &lt;code&gt;--&lt;/code&gt; 앞은 Claude Code 옵션, 뒤는 서버를 띄우는 명령입니다. 기본 범위는 &quot;이 프로젝트, 나만&quot;입니다. 이 글의 실행 기록에는 이 단계가 없으니, 해 보신 분은 결과를 알려 주세요.&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;claude mcp add notes -- uv run --with mcp python /절대/경로/notes_server.py
claude mcp list
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;이런 데 쓸 수 있다&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;자주 묻는 조회 하나를 읽기 전용 도구로.&lt;/strong&gt; 팀이 매번 손으로 찾는 정보(문서 검색, 상태 조회)를 함수 하나로 만들고 &lt;code&gt;@mcp.tool()&lt;/code&gt;을 붙입니다. 그러면 채팅 도구든 코드 편집기든 MCP를 아는 앱 어디서나 부를 수 있습니다. 처음에는 도구 하나로 시작합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;쓰기 도구의 권한은 서버 안에서 막기.&lt;/strong&gt; 지우기·바꾸기 도구를 만든다면, 도구에 붙이는 &quot;위험한 도구&quot; 표시(&lt;code&gt;destructiveHint&lt;/code&gt;)에 기대지 않습니다. 명세는 이 표시를 클라이언트가 그대로 믿지 말라고 합니다. 권한 확인은 서버 함수 안에서 직접 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;오류 문구를 모델이 읽을 문장으로.&lt;/strong&gt; 입력이 틀렸을 때 &quot;날짜는 YYYY-MM-DD 형식으로, 오늘 이후만&quot;처럼 돌려주면 모델이 스스로 고쳐 다시 부릅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. MCP 서버를 만들려면 꼭 SDK를 써야 하나요?&lt;/strong&gt;
아닙니다. 원본 레슨처럼 표준 라이브러리만으로도 만들 수 있고, 규격을 이해하는 데는 그 편이 좋습니다. 다만 2026년 10월 기준으로 앱과 도구가 쓰는 판이 섞여 있어서, 두 판을 모두 받는 공식 SDK로 만드는 편이 연결 문제가 적습니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 도구, 리소스, 프롬프트를 다 만들어야 하나요?&lt;/strong&gt;
아닙니다. Anthropic의 Mahesh Murag는 MCP 워크숍에서 &quot;처음에는 도구로 시작해 서버를 이해하고, 그다음 프롬프트와 리소스로 가라&quot;고 조언합니다. 레슨의 서버 설계 도우미도 &quot;쓸 데 없는 리소스·프롬프트를 지어내지 말라&quot;는 규칙을 둡니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 만든 서버가 연결되는지 어떻게 확인하나요?&lt;/strong&gt;
MCP Inspector를 씁니다. 위 &quot;따라 해 보기&quot;처럼 &lt;code&gt;--cli&lt;/code&gt;로 도구 목록과 호출을 확인합니다. 공식 튜토리얼에 따르면 Inspector는 기본값이 이전 판이므로, &lt;code&gt;--protocol-era modern&lt;/code&gt;으로 최신 판도 한 번 더 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;더 깊이: MCP 명세, 레슨, 공식 튜토리얼, 워크숍, 코드&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MCP 명세 2026-07-28, Tools.&lt;/strong&gt; &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/server/tools&quot;&gt;Tools 절&lt;/a&gt;에서 서버를 만들 때 직접 걸리는 규칙만 추렸습니다. 도구는 모델이 고르는(model-controlled) 기능이고, 안전을 위해 호출을 거부할 수 있는 사람이 늘 있어야 합니다(SHOULD). &lt;code&gt;tools/list&lt;/code&gt;는 정해진 순서로 돌려줘야 합니다(SHOULD). 목록이 흔들리면 캐시와 프롬프트 캐시 적중률이 떨어지기 때문입니다. 도구 이름은 1~128자, 영문·숫자·&lt;code&gt;_&lt;/code&gt;·&lt;code&gt;-&lt;/code&gt;·&lt;code&gt;.&lt;/code&gt;만 씁니다(SHOULD). &lt;code&gt;readOnlyHint&lt;/code&gt;, &lt;code&gt;destructiveHint&lt;/code&gt; 같은 annotations는 신뢰할 수 있는 서버가 아니면 클라이언트가 믿지 않아야 합니다(MUST). &lt;code&gt;outputSchema&lt;/code&gt;를 주면 &lt;code&gt;structuredContent&lt;/code&gt;가 그 스키마를 따라야 하고(MUST), 하위 호환을 위해 같은 JSON을 text로도 넣는 것이 좋습니다(SHOULD). SDK 서버의 실제 응답도 &lt;code&gt;content&lt;/code&gt;에 &quot;note-1&quot;을, &lt;code&gt;structuredContent&lt;/code&gt;에 &lt;code&gt;{&quot;result&quot;: [&quot;note-1&quot;]}&lt;/code&gt;를 함께 담았습니다. 비규범 절 &quot;Stateful Tools&quot;는 프로토콜 세션이 없으니, 상태가 필요하면 만들기 도구가 핸들(예: &lt;code&gt;basket_id&lt;/code&gt;)을 돌려주고 다음 호출의 인자로 받으라고 안내합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;명세와 구현이 다른 곳: 없는 도구 이름.&lt;/strong&gt; 명세의 &quot;Error Handling&quot;은 알 수 없는 도구를 프로토콜 오류(-32602)의 예시로 듭니다. 그런데 레슨 서버와 SDK 2.3.0 서버는 둘 다 없는 도구 &lt;code&gt;notes_delete&lt;/code&gt;를 부르면 도구 실행 오류(&lt;code&gt;isError: true&lt;/code&gt;, &quot;Unknown tool: notes_delete&quot;)로 돌려줍니다. 레슨은 테스트 이름도 &lt;code&gt;test_unknown_tool_is_tool_level_error&lt;/code&gt;입니다. 실행 오류는 모델에게 보여 주는 쪽(SHOULD)이라, 모델이 &quot;그런 도구가 없다&quot;를 읽고 고칠 기회가 생기기는 합니다. 어느 쪽이 맞는지는 이 글에서 판단하지 않습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;명세 2026-07-28, stdio와 하위 호환.&lt;/strong&gt; &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio&quot;&gt;stdio 절&lt;/a&gt;에 따르면 클라이언트가 서버를 하위 프로세스로 띄우고, 메시지는 줄바꿈으로 구분하며 메시지 안에 줄바꿈을 넣으면 안 됩니다(MUST NOT). 서버는 stdout에 MCP 메시지가 아닌 것을 쓰면 안 되고(MUST NOT), 로그는 stderr에 써도 됩니다(MAY). 종료는 클라이언트가 stdin을 닫고, 기다리고, 안 끝나면 SIGTERM, SIGKILL 순서입니다. 두 판을 다 아는 클라이언트는 먼저 &lt;code&gt;server/discover&lt;/code&gt;로 탐침합니다. 최신 판 응답이 오면 최신 판으로, 그 밖의 오류나 무응답이면 이전 판의 &lt;code&gt;initialize&lt;/code&gt;로 내려갑니다. Python SDK &lt;code&gt;Client&lt;/code&gt;의 &lt;code&gt;mode=&quot;auto&quot;&lt;/code&gt;가 이 방식이고, 그래서 그림 4에서 레슨 서버와 SDK 서버 모두와 통했습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;원본 레슨 13-07.&lt;/strong&gt; &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/07-building-an-mcp-server&quot;&gt;레슨&lt;/a&gt;의 모토는 &quot;요즘 MCP 서버는 핸드셰이크를 기억하지 않는다&quot;입니다. 첫 메시지에서 받은 클라이언트 능력을 저장해 두는 서버는 만들기는 쉽지만, 같은 프로세스가 여러 클라이언트를 받거나 원격 요청이 다른 워커로 가면 남은 상태가 엉뚱한 요청에 새어 들어갑니다. 노트 같은 앱 데이터는 남겨도 되지만, 다음 요청의 해석을 바꾸는 숨은 프로토콜 상태는 두지 말라고 합니다. 리소스 목록과 읽기 결과에는 캐시 힌트(&lt;code&gt;ttlMs&lt;/code&gt;, &lt;code&gt;cacheScope&lt;/code&gt;)를 붙이고, 사용자별 데이터는 &lt;code&gt;private&lt;/code&gt;로 둡니다. 레슨 서버의 실제 값은 &lt;code&gt;tools/list&lt;/code&gt; 60000/public, &lt;code&gt;resources/read&lt;/code&gt; 5000/private였습니다. 서버가 사용자 입력이 필요하면 스스로 요청을 보내지 않고 &quot;입력 필요&quot; 결과를 돌려줍니다. 연습문제는 다섯 개입니다. 그중 &quot;파괴적 도구 &lt;code&gt;notes_delete&lt;/code&gt;에 실제 권한 검사 넣기&quot;와 &quot;2025-11-25 이전 판 어댑터를 따로 만들기&quot;는 이번 화 결론과 바로 이어집니다. &lt;code&gt;outputs/skill-mcp-server-scaffolder.md&lt;/code&gt;는 도메인을 주면 최신 판 서버 설계를 한 쪽짜리로 내 주는 스킬입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;공식 튜토리얼 &lt;a href=&quot;https://modelcontextprotocol.io/docs/develop/build-server&quot;&gt;Build an MCP server&lt;/a&gt;.&lt;/strong&gt; 도구 2개짜리 날씨 서버를 만들어 Claude 데스크톱 앱에 붙입니다. Python은 &lt;code&gt;uv add &quot;mcp[cli]&quot;&lt;/code&gt; 뒤 &lt;code&gt;MCPServer&lt;/code&gt;를 쓰고, &quot;타입 힌트와 docstring으로 도구 정의를 자동으로 만든다&quot;고 설명합니다. Claude 데스크톱 앱 연결은 설정 파일(&lt;code&gt;claude_desktop_config.json&lt;/code&gt;)의 &lt;code&gt;mcpServers&lt;/code&gt;에 &lt;code&gt;uv&lt;/code&gt; 실행 명령과 절대 경로를 넣고 앱을 다시 시작하는 방식입니다. TypeScript 탭은 새 패키지 &lt;code&gt;@modelcontextprotocol/server&lt;/code&gt;의 &lt;code&gt;serveStdio&lt;/code&gt;를 쓰는데, 튜토리얼에 따르면 클라이언트마다 판을 협상해서 두 판 모두에 답합니다. 이 TypeScript 경로는 이번에 직접 돌려 보지 않았습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mahesh Murag(Anthropic), &quot;Building Agents with Model Context Protocol&quot; 워크숍.&lt;/strong&gt; 5화에서 본 &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&quot;&gt;영상&lt;/a&gt;의 뒷부분입니다. 2025년 초 녹화라 연결 방식은 이전 판 기준입니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&amp;amp;t=22m48s&quot;&gt;22:48&lt;/a&gt;에서 Claude 데스크톱 앱에 GitHub 서버와 Asana 서버를 붙여, 이슈를 가져와 Asana 작업으로 넣는 데모를 합니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&amp;amp;t=24m56s&quot;&gt;24:56&lt;/a&gt;에서 발표자는 두 서버 모두 커뮤니티가 만들었고 각각 수백 줄 정도이며, 주로 도구를 드러내는 일이라 로직이 많지 않다고 말합니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&amp;amp;t=48m13s&quot;&gt;48:13&lt;/a&gt;에서는 출시 때 서버 15개 남짓을 각각 45분쯤에 Claude와 함께 썼다고 말하고, 도구부터 시작하라고 조언합니다. 측정값이 아니라 발표자의 말입니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&amp;amp;t=1h09m51s&quot;&gt;69:51&lt;/a&gt;에서는 디버깅에 Inspector를 쓰라고 권합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;코드.&lt;/strong&gt; &lt;a href=&quot;https://github.com/modelcontextprotocol/python-sdk&quot;&gt;modelcontextprotocol/python-sdk&lt;/a&gt;(MIT, PyPI &lt;code&gt;mcp&lt;/code&gt; 2.3.0)는 &lt;code&gt;MCPServer&lt;/code&gt;와 데코레이터 세 개, &lt;code&gt;mcp dev server.py&lt;/code&gt;로 Inspector를 여는 명령을 제공합니다. 같은 패키지의 &lt;code&gt;Client&lt;/code&gt;는 &lt;code&gt;mode&lt;/code&gt;를 &lt;code&gt;'auto'&lt;/code&gt;와 &lt;code&gt;'legacy'&lt;/code&gt; 중에서 고릅니다. &lt;a href=&quot;https://github.com/modelcontextprotocol/inspector&quot;&gt;modelcontextprotocol/inspector&lt;/a&gt;(npm 2.11.0)는 &lt;code&gt;--cli&lt;/code&gt; 모드와 &lt;code&gt;--protocol-era modern|legacy&lt;/code&gt;를 지원하고, 라이선스는 MIT에서 Apache-2.0으로 옮겨 가는 중입니다. TypeScript SDK &lt;code&gt;@modelcontextprotocol/sdk&lt;/code&gt; 1.32.1은 2025-11-25를 최신 판으로 알고 있어서, 그림 4에서 레슨 서버와 통하지 않았습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;다음 화 예고.&lt;/strong&gt; 5화와 6화에서 MCP 서버를 쓰고 만들어 봤습니다. 7화에서는 에이전트 스킬을 다룹니다. 도구를 붙이는 것과 일하는 방법을 가르치는 것은 어떻게 다를까요?&lt;/p&gt;
&lt;hr style=&quot;border:0;border-top:1px solid #dcdfe3;margin:36px 0;&quot; /&gt;
&lt;p&gt;원본: rohitg00/ai-engineering-from-scratch (MIT, © 2026 Rohit Ghumare). 이 글은 원문을 바탕으로 직접 정리하고 재구성했습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top:32px;&quot;&gt;출처&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 13-07 Building an MCP Server (폴더 커밋 8050434): &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/07-building-an-mcp-server&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/07-building-an-mcp-server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 명세 2026-07-28, Tools: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/server/tools&quot;&gt;https://modelcontextprotocol.io/specification/2026-07-28/server/tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 명세 2026-07-28, stdio: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio&quot;&gt;https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 명세 2026-07-28, Transports: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/basic/transports&quot;&gt;https://modelcontextprotocol.io/specification/2026-07-28/basic/transports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 명세 2026-07-28, Server Discovery: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/server/discover&quot;&gt;https://modelcontextprotocol.io/specification/2026-07-28/server/discover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 공식 튜토리얼, Build an MCP server: &lt;a href=&quot;https://modelcontextprotocol.io/docs/develop/build-server&quot;&gt;https://modelcontextprotocol.io/docs/develop/build-server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude Code 공식 문서, Connect Claude Code to tools via MCP: &lt;a href=&quot;https://code.claude.com/docs/en/mcp&quot;&gt;https://code.claude.com/docs/en/mcp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;modelcontextprotocol/python-sdk: &lt;a href=&quot;https://github.com/modelcontextprotocol/python-sdk&quot;&gt;https://github.com/modelcontextprotocol/python-sdk&lt;/a&gt; (PyPI &lt;a href=&quot;https://pypi.org/project/mcp/&quot;&gt;https://pypi.org/project/mcp/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;modelcontextprotocol/inspector: &lt;a href=&quot;https://github.com/modelcontextprotocol/inspector&quot;&gt;https://github.com/modelcontextprotocol/inspector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Mahesh Murag, Building Agents with Model Context Protocol (영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&quot;&gt;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;5화 MCP 구조: &lt;a href=&quot;https://agentnote.tistory.com/11&quot;&gt;https://agentnote.tistory.com/11&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/Engineering</category>
      <category>ai 에이전트</category>
      <category>ai-engineering-from-scratch</category>
      <category>Claude</category>
      <category>LLM</category>
      <category>MCP</category>
      <category>MCP Inspector</category>
      <category>mcp 서버</category>
      <category>model context protocol</category>
      <category>python</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/12</guid>
      <comments>https://agentnote.tistory.com/12#entry12comment</comments>
      <pubDate>Tue, 20 Oct 2026 13:56:42 +0900</pubDate>
    </item>
    <item>
      <title>MCP란? AI 앱과 도구를 잇는 표준 규격 MCP 구조 쉽게 정리 (호스트&amp;middot;클라이언트&amp;middot;서버, 도구&amp;middot;리소스&amp;middot;프롬프트)</title>
      <link>https://agentnote.tistory.com/11</link>
      <description>&lt;!-- 제목: MCP란? AI 앱과 도구를 잇는 표준 규격 MCP 구조 쉽게 정리 (호스트·클라이언트·서버, 도구·리소스·프롬프트) | 태그: MCP, Model Context Protocol, MCP 서버, AI 에이전트, Claude, Anthropic, LLM, 생성형 AI, ai-engineering-from-scratch --&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;&lt;strong&gt;요약.&lt;/strong&gt; MCP(Model Context Protocol)는 AI 앱과 바깥 도구·데이터를 잇는 공통 규격입니다. 예전에는 AI 앱마다, 도구마다 연결 코드를 따로 짰습니다. MCP를 쓰면 도구 쪽은 &quot;MCP 서버&quot;를 한 번 만들고, MCP를 아는 AI 앱이면 어디서나 그 서버를 붙여 씁니다. 서버가 내놓는 것은 세 가지입니다. 모델이 골라 쓰는 &lt;strong&gt;도구&lt;/strong&gt;, 앱이 골라 붙이는 &lt;strong&gt;리소스&lt;/strong&gt;, 사용자가 골라 쓰는 &lt;strong&gt;프롬프트&lt;/strong&gt;입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;4화에서 이어지는 질문: 도구는 어디서 오나&lt;/h2&gt;
&lt;p&gt;1막(0~4화)에서는 에이전트가 무엇이고 어떻게 도는지 봤습니다. &lt;a href=&quot;https://agentnote.tistory.com/8&quot;&gt;2화&lt;/a&gt;에서는 모델이 &quot;이 도구를 이 값으로 불러 줘&quot;라고 글자를 쓰면 프로그램이 대신 실행한다는 것을 봤습니다.&lt;/p&gt;
&lt;p&gt;그런데 그 도구 목록은 누가 만들까요? 2화 예제에서는 앱을 만드는 사람이 날씨 조회 함수를 직접 짜서 넣었습니다. 파일을 읽고, 깃허브 이슈를 보고, 일정을 확인하는 도구도 다 그렇게 넣어야 할까요? 그리고 Claude 앱, 코드 편집기, 사내 챗봇처럼 AI 앱이 여러 개면 같은 도구를 앱마다 다시 짜야 할까요?&lt;/p&gt;
&lt;p&gt;2막(세상과 연결되기)의 첫 질문입니다. 이번 화는 이 문제를 푸는 공통 규격, MCP의 구조를 다룹니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;MCP가 푸는 문제: 앱 N개 × 도구 M개&lt;/h2&gt;
&lt;p&gt;AI 앱이 3개이고 붙이고 싶은 도구가 3개라고 해 봅시다. 앱마다 도구마다 연결 코드를 따로 짜면 연결이 9개 필요합니다. 앱이나 도구가 하나 늘 때마다 연결 수는 곱으로 늘어납니다.&lt;/p&gt;
&lt;p&gt;Anthropic의 Mahesh Murag는 MCP 워크숍에서 이를 &quot;N×M 문제&quot;라고 부르고, MCP가 이것을 평평하게 만들려 한다고 설명합니다. 앱은 MCP를 한 번 맞추고, 도구도 MCP를 한 번 맞춥니다. 그러면 연결은 앱 수 더하기 도구 수, 3+3=6개면 됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/larQJ/dJMcadql1yv/wV9odHsKouVaGsUK2hovE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/larQJ/dJMcadql1yv/wV9odHsKouVaGsUK2hovE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/larQJ/dJMcadql1yv/wV9odHsKouVaGsUK2hovE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlarQJ%2FdJMcadql1yv%2FwV9odHsKouVaGsUK2hovE0%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 1. 앱과 도구가 각자 규격 하나만 맞추면 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot;&gt;MCP 공식 소개 페이지&lt;/a&gt;는 MCP를 &quot;AI 앱을 위한 USB-C 포트&quot;에 비유합니다. 기기마다 충전 단자가 다르면 케이블을 기기마다 챙겨야 합니다. 단자가 USB-C 하나면 같은 케이블이 어디에나 맞습니다. MCP 서버는 USB-C 단자를 단 주변기기, MCP를 지원하는 AI 앱은 USB-C 포트가 있는 노트북인 셈입니다.&lt;/p&gt;
&lt;p&gt;다만 비유와 다른 점이 하나 있습니다. 케이블은 꽂으면 전기가 흐르고 끝이지만, MCP는 꽂은 뒤에 대화를 합니다. 앱이 서버에 &quot;무엇을 할 수 있나요?&quot;라고 묻고, 받은 목록에서 골라 부릅니다. 이 대화가 실제로 어떻게 생겼는지는 아래에서 직접 봅니다.&lt;/p&gt;
&lt;p&gt;MCP는 Anthropic이 2024년 11월에 공개했고, 2025년 12월 Linux Foundation 산하 재단(Agentic AI Foundation)에 기증했습니다. 지금은 한 회사의 기능이 아니라 공개 규격입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;MCP 구조: 호스트, 클라이언트, 서버&lt;/h2&gt;
&lt;p&gt;MCP에는 세 역할이 나옵니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;호스트&lt;/strong&gt;: 사용자가 쓰는 AI 앱입니다. Claude 앱이나 코드 편집기 같은 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;서버&lt;/strong&gt;: 도구와 데이터를 내놓는 쪽입니다. 파일 서버, 깃허브 서버, 일정 서버처럼 하나가 한 가지 영역을 맡습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;클라이언트&lt;/strong&gt;: 호스트 안에서 서버 하나와 연결을 맡는 부분입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/architecture&quot;&gt;MCP 명세&lt;/a&gt;는 호스트가 클라이언트 여럿을 만들고 관리하며, 클라이언트 하나는 서버 하나와 1대1로 연결된다고 정의합니다. 서버를 세 개 붙이면 호스트 안에 클라이언트가 세 개 생기는 구조입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYTlbM/dJMcaiyyoTg/8CsidL64y63hA2KkUMUds0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYTlbM/dJMcaiyyoTg/8CsidL64y63hA2KkUMUds0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYTlbM/dJMcaiyyoTg/8CsidL64y63hA2KkUMUds0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYTlbM%2FdJMcaiyyoTg%2F8CsidL64y63hA2KkUMUds0%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 2. 호스트 하나에 클라이언트 여럿, 클라이언트 하나에 서버 하나.&lt;/p&gt;

&lt;p&gt;이 구조에서 중요한 점은 모델이 서버와 직접 이야기하지 않는다는 것입니다. Anthropic의 MCP 대담에서 MCP 공동 제작자 David Soria Parra는 &quot;모델은 API와 직접 대화하지 않는다&quot;고 말합니다. 모델이 보는 것은 호스트가 건네준 도구 설명과 결과뿐입니다. 서버를 부르고, 결과를 모델에게 넘기고, 위험한 실행을 막는 일은 호스트가 합니다. 2화에서 본 &quot;모델은 글자만 쓰고 실행은 프로그램이 한다&quot;와 같은 구조입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;서버가 내놓는 세 가지: 도구, 리소스, 프롬프트&lt;/h2&gt;
&lt;p&gt;MCP 서버가 내놓는 것은 세 종류입니다. 셋을 가르는 기준은 &lt;strong&gt;누가 고르느냐&lt;/strong&gt;입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wXIEi/dJMcajc0C8j/h2LZVeewD9ewaXwLczIcUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wXIEi/dJMcajc0C8j/h2LZVeewD9ewaXwLczIcUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wXIEi/dJMcajc0C8j/h2LZVeewD9ewaXwLczIcUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwXIEi%2FdJMcajc0C8j%2Fh2LZVeewD9ewaXwLczIcUk%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 3. 세 가지 기본 요소와 각각을 고르는 주체. 명세의 정의를 따랐습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;도구 (모델이 고름)&lt;/strong&gt;: 파일 읽기, 이슈 만들기처럼 실행하는 기능입니다. 모델이 도구 설명을 보고 언제 부를지 정합니다. 2화의 함수 호출이 바로 이것입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;리소스 (앱이 고름)&lt;/strong&gt;: 파일 내용, 문서, 데이터처럼 읽을거리입니다. 앱이 어떤 것을 모델에게 보여 줄지 정합니다. 사용자가 대화에 파일을 첨부하는 모습을 떠올리면 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;프롬프트 (사용자가 고름)&lt;/strong&gt;: &quot;이 코드 리뷰해 줘&quot;처럼 미리 만들어 둔 지시문 틀입니다. 사용자가 슬래시 명령 같은 메뉴에서 골라 씁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mahesh Murag는 리소스를 왜 도구로 합치지 않았냐는 질문에 &quot;모델이 고르는 것과 앱이 고르는 것을 깔끔하게 나누고 싶었다&quot;고 답합니다. 누가 고르느냐가 다르면 권한과 안전장치도 달라지기 때문입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;실제로 주고받는 메시지: 공식 파일 서버에 물어보기&lt;/h2&gt;
&lt;p&gt;구조를 봤으니 실제 대화를 볼 차례입니다. MCP 공식 저장소의 참조 서버 중 하나인 파일 서버(&lt;code&gt;server-filesystem&lt;/code&gt;)를 띄우고, 허용 폴더를 하나로 정한 뒤 메시지를 보내 보면 아래처럼 대화가 오갑니다. 메시지는 JSON-RPC라는 형식의 짧은 JSON 한 줄씩입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wybVs/dJMcaaHjebb/AMe0zeviSuXk9XrWkA19Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wybVs/dJMcaaHjebb/AMe0zeviSuXk9XrWkA19Qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wybVs/dJMcaaHjebb/AMe0zeviSuXk9XrWkA19Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwybVs%2FdJMcaaHjebb%2FAMe0zeviSuXk9XrWkA19Qk%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 4. 2026-10-16에 공식 파일 서버(npm 1.0.0)와 주고받은 실제 응답을 줄였습니다.&lt;/p&gt;

&lt;p&gt;흐름은 이렇습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;인사.&lt;/strong&gt; 클라이언트가 &lt;code&gt;initialize&lt;/code&gt;로 자기가 아는 규격 판과 기능을 알리면, 서버가 자기 이름과 판(2025-11-25)을 답합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;목록 묻기.&lt;/strong&gt; &lt;code&gt;tools/list&lt;/code&gt;를 보내자 도구 14개가 왔습니다. 파일 읽기, 쓰기, 고치기, 폴더 만들기, 검색 같은 것들입니다. 도구마다 이름, 설명, 받을 값의 모양이 붙어 있습니다. 이 설명이 그대로 모델에게 건네지는 도구 설명이 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;부르기.&lt;/strong&gt; &lt;code&gt;tools/call&lt;/code&gt;로 허용 폴더 안의 &lt;code&gt;notes.txt&lt;/code&gt;를 읽게 하자 내용(&quot;회의록: 다음 주 화요일 배포&quot;)이 돌아왔습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;거절.&lt;/strong&gt; 허용 폴더 밖의 시스템 파일을 읽게 하자 &quot;허용된 폴더 밖&quot;이라는 오류가 돌아왔습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;두 가지가 눈에 띕니다. 하나는 안전장치가 서버에도 있다는 점입니다. 모델이 엉뚱한 파일을 읽으려 해도 서버가 막습니다. 다른 하나는 응답 순서입니다. 3번과 4번을 연달아 보냈는데 4번 답이 먼저 왔습니다. 그래서 메시지마다 번호(&lt;code&gt;id&lt;/code&gt;)를 붙여 어느 질문의 답인지 짝을 맞춥니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;MCP 연결 방식은 지금 바뀌는 중&lt;/h2&gt;
&lt;p&gt;여기까지가 판이 바뀌어도 그대로인 부분입니다. 이제 바뀌는 부분입니다.&lt;/p&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/06-mcp-fundamentals&quot;&gt;13-06 MCP Fundamentals&lt;/a&gt;는 위 4번 같은 &quot;인사&quot;가 없는 방식을 가르칩니다. 2026년 7월 28일에 나온 &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/changelog&quot;&gt;MCP 명세 최신판&lt;/a&gt;이 인사 절차와 연결 단위 세션을 없앴기 때문입니다. 대신 요청마다 &quot;나는 이 판을 쓰고, 이런 기능이 있다&quot;는 자기소개를 붙입니다. 명세는 이를 &quot;MCP는 무상태 프로토콜&quot;이라고 적습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qnFiL/dJMcagghPCX/EiQ2GDaIhczq8DfnSes9T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qnFiL/dJMcagghPCX/EiQ2GDaIhczq8DfnSes9T0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qnFiL/dJMcagghPCX/EiQ2GDaIhczq8DfnSes9T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqnFiL%2FdJMcagghPCX%2FEiQ2GDaIhczq8DfnSes9T0%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 5. 왼쪽은 많이 쓰는 공식 서버가 지금 쓰는 방식, 오른쪽은 명세 최신판.&lt;/p&gt;

&lt;p&gt;왜 바꿨을까요? 레슨의 설명은 이렇습니다. 서버 한 대가 여러 클라이언트의 요청을 번갈아 받을 때, 앞 요청에서 들은 정보를 기억해 두면 다음 요청에 엉뚱한 권한을 적용할 수 있습니다. 요청이 스스로를 설명하면 어느 서버가 받아도 같은 판단을 내립니다. 원격 서버를 여러 대로 늘리기도 쉬워집니다.&lt;/p&gt;
&lt;p&gt;그런데 위 실험의 공식 파일 서버는 아직 인사하는 쪽(2025-11-25 판)입니다. 최신판의 첫 요청인 &lt;code&gt;server/discover&lt;/code&gt;를 보내자 &quot;그런 메서드 없음&quot;으로 답했습니다. 최신판으로 인사를 청해도 2025-11-25로 낮춰서 답했습니다. 이 서버가 쓰는 공식 TypeScript SDK(1.32.0)도 2025-11-25를 최신으로 알고 있었습니다. 명세는 앞서가고, 도구들은 따라가는 중입니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/10&quot;&gt;4화&lt;/a&gt;에서 모델이 빨리 바뀌어도 남는 것을 이야기했습니다. MCP도 비슷합니다. 연결 절차는 최신판에서 크게 바뀌었지만, 호스트·클라이언트·서버 구조와 &quot;도구는 모델이, 리소스는 앱이, 프롬프트는 사용자가 고른다&quot;는 기준은 그대로입니다. 처음 공부할 때는 이 뼈대를 잡아 두고, 연결 절차는 쓰는 SDK의 판을 확인하면 됩니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;레슨 코드로 돌려 보면&lt;/h2&gt;
&lt;p&gt;원본 레슨 두 편의 예제는 외부 패키지 없이 Python만으로 돌아가고, 함께 들어 있는 테스트도 모두 통과합니다(13-06 7개, 13-09 18개). 다만 설명하는 범위보다 코드가 좁습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/06-mcp-fundamentals&quot;&gt;13-06&lt;/a&gt; 본문은 도구·리소스·프롬프트 세 가지를 설명하지만, 예제 서버는 도구만 처리합니다. 리소스나 프롬프트를 요청하면 &quot;그런 메서드 없음&quot;이 돌아옵니다. 검색 도구도 실제로 검색하지 않고, 받은 검색어를 문장에 끼워 돌려줍니다. 메시지 모양을 보여 주는 예제로 보면 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/09-mcp-transports&quot;&gt;13-09 MCP Transports&lt;/a&gt; 본문은 연결 통로 두 가지(아래 &quot;더 깊이&quot;)를 다 설명하지만, 코드는 HTTP 쪽만 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;따라 해 보기&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. 레슨 예제로 메시지 모양 보기 (Python만 있으면 됨).&lt;/strong&gt;&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -O https://raw.githubusercontent.com/rohitg00/ai-engineering-from-scratch/main/phases/13-tools-and-protocols/06-mcp-fundamentals/code/main.py
python3 main.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;요청 네 개와 응답이 차례로 출력됩니다. 요청마다 &lt;code&gt;_meta&lt;/code&gt; 안에 판과 기능이 반복해서 들어 있는지, 마지막 요청(없는 판 &lt;code&gt;2027-01-01&lt;/code&gt;)이 어떤 오류를 받는지 보세요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 공식 파일 서버에 직접 물어보기 (Node.js 필요).&lt;/strong&gt; 빈 폴더 하나를 만들고 안에 텍스트 파일을 하나 넣은 뒤, 서버를 띄워 메시지를 보냅니다. 아래는 위 실험의 요청 세 개를 줄인 것입니다.&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p ~/mcp-test &amp;amp;&amp;amp; echo &amp;quot;hello mcp&amp;quot; &amp;gt; ~/mcp-test/notes.txt
printf '%s\n' \
 '{&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;id&amp;quot;:1,&amp;quot;method&amp;quot;:&amp;quot;initialize&amp;quot;,&amp;quot;params&amp;quot;:{&amp;quot;protocolVersion&amp;quot;:&amp;quot;2025-11-25&amp;quot;,&amp;quot;capabilities&amp;quot;:{},&amp;quot;clientInfo&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;me&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;0&amp;quot;}}}' \
 '{&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;method&amp;quot;:&amp;quot;notifications/initialized&amp;quot;}' \
 '{&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;id&amp;quot;:2,&amp;quot;method&amp;quot;:&amp;quot;tools/list&amp;quot;}' \
 | npx -y @modelcontextprotocol/server-filesystem ~/mcp-test
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인사에 대한 답과 도구 목록이 JSON으로 나옵니다. 앱이 서버에 붙을 때 화면 뒤에서 오가는 대화가 이것입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;이런 데 쓸 수 있다&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;팀 문서 폴더를 읽기 전용으로 연결하기.&lt;/strong&gt; 파일 서버를 허용 폴더 하나로 묶어 AI 앱이 팀 문서를 찾아 읽게 합니다. 쓰기 도구는 끄거나 사람 승인을 거치게 둡니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자주 쓰는 사내 조회 기능을 서버 하나로 만들기.&lt;/strong&gt; 채팅 도구, 코드 편집기, 사내 챗봇에 따로 붙이던 기능을 MCP 서버 하나로 만들면 MCP를 아는 앱 어디서나 씁니다. 서버를 직접 만드는 법은 6화에서 다룹니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;팀 공용 지시문을 프롬프트로 내놓기.&lt;/strong&gt; &quot;주간 보고 정리&quot; 같은 팀 템플릿을 서버의 프롬프트로 두면, 사용자가 메뉴에서 골라 씁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. MCP와 함수 호출(Function Calling)은 무엇이 다른가요?&lt;/strong&gt;
함수 호출은 모델이 &quot;이 도구를 이 값으로&quot;라고 쓰는 방식이고, MCP는 그 도구를 어디서 가져오고 어떻게 부르는지에 대한 규격입니다. MCP 서버가 내놓은 도구 목록이 호스트를 거쳐 모델에게 함수 호출용 도구 설명으로 건네집니다. 둘은 경쟁 관계가 아니라 위아래 층입니다. 함수 호출은 &lt;a href=&quot;https://agentnote.tistory.com/8&quot;&gt;2화&lt;/a&gt;에서 다뤘습니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. MCP는 Claude에서만 쓰나요?&lt;/strong&gt;
아닙니다. Anthropic이 만들었지만 &lt;a href=&quot;https://www.anthropic.com/news/donating-the-model-context-protocol-and-establishing-of-the-agentic-ai-foundation&quot;&gt;2025년 12월 Linux Foundation 산하 Agentic AI Foundation에 기증&lt;/a&gt;한 공개 규격입니다. Mahesh Murag의 워크숍(2025년 2월)만 해도 Claude 앱 말고 여러 코드 편집기와 에이전트 도구가 MCP 클라이언트로 나옵니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 아무 MCP 서버나 붙여도 안전한가요?&lt;/strong&gt;
조심해야 합니다. 서버의 도구 설명은 그대로 모델에게 들어가고, 도구는 실제로 파일을 쓰거나 지울 수 있습니다. 믿을 수 있는 서버만 붙이고, 허용 범위를 좁히고, 쓰기 도구는 승인을 거치게 하는 것이 기본입니다. MCP 보안은 4막(15화)에서 따로 다룹니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;더 깊이: MCP 명세, 강의 세 편, 보안 논문, 코드&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MCP 명세 2026-07-28 (최신판).&lt;/strong&gt; &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/&quot;&gt;명세&lt;/a&gt;가 이번 화의 주 출처입니다. 판은 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25를 거쳐 2026-07-28이 최신입니다. 메시지 형식은 JSON-RPC 2.0입니다. 요청에는 번호(&lt;code&gt;id&lt;/code&gt;)와 메서드 이름이 붙고, 응답은 같은 번호로 결과나 오류를 돌려줍니다. 서버의 세 기본 요소는 메서드로 나뉩니다. 도구는 &lt;code&gt;tools/list&lt;/code&gt;와 &lt;code&gt;tools/call&lt;/code&gt;, 리소스는 &lt;code&gt;resources/list&lt;/code&gt;와 &lt;code&gt;resources/read&lt;/code&gt;, 프롬프트는 &lt;code&gt;prompts/list&lt;/code&gt;와 &lt;code&gt;prompts/get&lt;/code&gt;입니다. &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/changelog&quot;&gt;변경 기록&lt;/a&gt;의 큰 변화는 이렇습니다. &lt;code&gt;initialize&lt;/code&gt; 인사와 프로토콜 세션을 없앴습니다. 요청마다 &lt;code&gt;_meta&lt;/code&gt;에 판(&lt;code&gt;io.modelcontextprotocol/protocolVersion&lt;/code&gt;)과 클라이언트 기능을 반드시 싣습니다. 서버는 판과 기능을 알려 주는 &lt;code&gt;server/discover&lt;/code&gt;를 반드시 구현합니다. 모르는 판이 오면 오류 코드 -32022와 지원하는 판 목록을 돌려줍니다. 서버가 먼저 클라이언트에게 요청을 보내던 방식도 없앴습니다. 서버가 사용자에게 물어볼 것이 있으면 &quot;입력 필요&quot; 결과를 돌려주고, 클라이언트가 답을 붙여 원래 요청을 다시 보냅니다. 클라이언트 쪽 기능 중 sampling, roots, logging은 폐지 예정이고, 서버가 사용자에게 추가 정보를 묻는 elicitation만 남았습니다. 옛 판의 인사 절차는 &lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle&quot;&gt;2025-11-25 명세의 lifecycle&lt;/a&gt;에 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;연결 통로 두 가지 (원본 레슨 13-09).&lt;/strong&gt; 앱이 서버를 자기 컴퓨터에서 직접 띄울 때는 &lt;strong&gt;stdio&lt;/strong&gt;를 씁니다. 표준 입력에 JSON 한 줄을 쓰고, 표준 출력으로 답을 받습니다. 위 실험과 &quot;따라 해 보기&quot;가 이 방식입니다. 네트워크 너머 서버에는 &lt;strong&gt;Streamable HTTP&lt;/strong&gt;를 씁니다. 최신판에서는 주소 하나(&lt;code&gt;/mcp&lt;/code&gt;)에 요청마다 POST를 보내고, 답은 JSON 하나나 그 요청 전용 스트림으로 받습니다. 세션 번호(&lt;code&gt;Mcp-Session-Id&lt;/code&gt;)와 끊긴 스트림 이어 받기는 없어졌습니다. 레슨은 HTTP 헤더에 메서드와 도구 이름을 한 번 더 적고 본문과 같은지 확인해야 한다고 강조합니다(다르면 -32020). 중간 관문이 헤더만 보고 &quot;읽기&quot;를 허락했는데 본문은 &quot;삭제&quot;를 실행하는 혼동을 막기 위해서입니다. 레슨 예제 서버로 확인하면 잘못된 Origin은 403, 헤더 불일치는 -32020, 모르는 판은 -32022, GET·DELETE는 405를 돌려줍니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stanford CME295 Lecture 7 &quot;Agentic LLMs&quot; (Afshine·Shervine Amidi, 2025년 11월).&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h28m50s&quot;&gt;MCP 구간 1:28:50~1:31:52&lt;/a&gt;, 약 3분입니다. 모델마다 도구를 정의하는 방식이 달라 같은 도구를 여러 번 구현하게 되는 중복을 문제로 꼽고, MCP를 도구를 모델에 노출하는 방식의 표준화로 소개합니다. 서버가 호스트 안의 클라이언트와 1대1로 연결된다는 점도 짚습니다. 리소스와 프롬프트 설명은 짧고 느슨해서, 정의는 명세를 따르는 편이 낫습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mahesh Murag(Anthropic), &quot;Building Agents with Model Context Protocol&quot; 워크숍 (AI Engineer Summit 2025).&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&quot;&gt;영상&lt;/a&gt;. &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&amp;amp;t=128s&quot;&gt;2:08&lt;/a&gt;에서 MCP의 뿌리를 LSP(편집기와 언어 도구 사이의 규격)에 둡니다. 언어 서버를 한 번 만들면 어느 편집기든 붙는 것처럼, MCP 서버도 한 번 만들면 어느 클라이언트든 붙습니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&amp;amp;t=364s&quot;&gt;6:04&lt;/a&gt;에 N×M 문제가 나오고, &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&amp;amp;t=621s&quot;&gt;10:21&lt;/a&gt;부터 도구는 모델, 리소스는 앱, 프롬프트는 사용자가 고른다는 설명이 이어집니다. 2025년 2월 녹화라 그 뒤 바뀐 연결 방식은 반영돼 있지 않습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Anthropic, &quot;The Model Context Protocol (MCP)&quot; 대담 (2025년 6월).&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=CQywdSdi5iA&quot;&gt;영상&lt;/a&gt;. 해설 영상이 아니라 MCP를 만든 사람들의 대담입니다. &lt;a href=&quot;https://www.youtube.com/watch?v=CQywdSdi5iA&amp;amp;t=197s&quot;&gt;3:17&lt;/a&gt;에 시작 이야기가 나옵니다. David Soria Parra가 Claude 데스크톱 앱과 코드 편집기 사이를 복사·붙여넣기로 오가는 게 답답했다고 합니다. &lt;a href=&quot;https://www.youtube.com/watch?v=CQywdSdi5iA&amp;amp;t=512s&quot;&gt;8:32&lt;/a&gt;에서는 공개 규격으로 낸 이유를 말합니다. 닫힌 생태계에는 연동을 만드는 사람들이 투자하지 않는다는 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MCP 보안 논문.&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/2503.23278v3&quot;&gt;Hou 외, &quot;Model Context Protocol (MCP): Landscape, Security Threats, and Future Research Directions&quot;(arXiv 2503.23278, v3 2025년 10월)&lt;/a&gt;. 초록 기준으로, MCP 서버의 일생을 만들기·배포·운영·유지보수 네 단계로 나눕니다. 공격자 네 유형과 위협 시나리오 16개를 분류하고, 단계별 대응책을 제안합니다. 15화(MCP 보안)에서 자세히 봅니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;코드.&lt;/strong&gt; 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/06-mcp-fundamentals&quot;&gt;13-06&lt;/a&gt;과 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/09-mcp-transports&quot;&gt;13-09&lt;/a&gt;의 &lt;code&gt;code/main.py&lt;/code&gt;는 표준 라이브러리만으로 최신판 메시지와 HTTP 서버를 보여 줍니다. 실제로 쓰는 서버는 &lt;a href=&quot;https://github.com/modelcontextprotocol/servers&quot;&gt;modelcontextprotocol/servers&lt;/a&gt;에 있습니다. 이 저장소에는 MCP 운영 그룹이 관리하는 참조 서버 7개(Everything, Fetch, Filesystem, Git, Memory, Sequential Thinking, Time)만 남아 있습니다. 더 많은 서버는 MCP 레지스트리에서 찾도록 안내합니다. 라이선스는 기존 코드 MIT, 새 기여분 Apache-2.0으로 옮겨 가는 중입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;다음 화 예고.&lt;/strong&gt; 이번 화는 MCP 서버를 쓰는 쪽에서 구조를 봤습니다. 6화에서는 MCP 서버를 직접 만들어 봅니다.&lt;/p&gt;
&lt;hr style=&quot;border:0;border-top:1px solid #dcdfe3;margin:36px 0;&quot; /&gt;
&lt;p&gt;원본: rohitg00/ai-engineering-from-scratch (MIT, © 2026 Rohit Ghumare). 이 글은 원문을 바탕으로 직접 정리하고 재구성했습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top:32px;&quot;&gt;출처&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 13-06 MCP Fundamentals: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/06-mcp-fundamentals&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/06-mcp-fundamentals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 13-09 MCP Transports: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/09-mcp-transports&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/09-mcp-transports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 명세 2026-07-28: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/&quot;&gt;https://modelcontextprotocol.io/specification/2026-07-28/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 명세 2025-11-25, Lifecycle: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle&quot;&gt;https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP 소개 페이지: &lt;a href=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot;&gt;https://modelcontextprotocol.io/docs/getting-started/intro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anthropic, Introducing the Model Context Protocol (2024-11-25): &lt;a href=&quot;https://www.anthropic.com/news/model-context-protocol&quot;&gt;https://www.anthropic.com/news/model-context-protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anthropic, Donating the Model Context Protocol and establishing the Agentic AI Foundation (2025-12-09): &lt;a href=&quot;https://www.anthropic.com/news/donating-the-model-context-protocol-and-establishing-of-the-agentic-ai-foundation&quot;&gt;https://www.anthropic.com/news/donating-the-model-context-protocol-and-establishing-of-the-agentic-ai-foundation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford CME295 Lecture 7 (영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h28m50s&quot;&gt;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h28m50s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Mahesh Murag, Building Agents with Model Context Protocol (AI Engineer Summit 2025, 영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&quot;&gt;https://www.youtube.com/watch?v=kQmXtrmQ5Zg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anthropic, The Model Context Protocol (MCP) (영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=CQywdSdi5iA&quot;&gt;https://www.youtube.com/watch?v=CQywdSdi5iA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Hou et al., MCP: Landscape, Security Threats, and Future Research Directions (arXiv 2503.23278): &lt;a href=&quot;https://arxiv.org/abs/2503.23278v3&quot;&gt;https://arxiv.org/abs/2503.23278v3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;modelcontextprotocol/servers: &lt;a href=&quot;https://github.com/modelcontextprotocol/servers&quot;&gt;https://github.com/modelcontextprotocol/servers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/Engineering</category>
      <category>ai 에이전트</category>
      <category>ai-engineering-from-scratch</category>
      <category>Anthropic</category>
      <category>Claude</category>
      <category>LLM</category>
      <category>MCP</category>
      <category>mcp 서버</category>
      <category>model context protocol</category>
      <category>생성형 ai</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/11</guid>
      <comments>https://agentnote.tistory.com/11#entry11comment</comments>
      <pubDate>Sun, 18 Oct 2026 10:47:12 +0900</pubDate>
    </item>
    <item>
      <title>모든 AI 일을 에이전트로 시켜야 할까? 워크플로와 에이전트의 차이, 워크플로 패턴 5가지 쉽게 정리</title>
      <link>https://agentnote.tistory.com/10</link>
      <description>&lt;!-- 제목: 모든 AI 일을 에이전트로 시켜야 할까? 워크플로와 에이전트의 차이, 워크플로 패턴 5가지 쉽게 정리 | 태그: AI 에이전트, 워크플로 패턴, Building Effective Agents, 프롬프트 체이닝, LLM, Claude, Anthropic, 생성형 AI, ai-engineering-from-scratch --&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;&lt;strong&gt;요약.&lt;/strong&gt; AI에게 여러 단계짜리 일을 시키는 방법은 두 가지입니다. 사람이 순서를 미리 정해 두는 &lt;strong&gt;워크플로&lt;/strong&gt;와, 모델이 다음에 할 일을 스스로 정하는 &lt;strong&gt;에이전트&lt;/strong&gt;입니다. Anthropic은 가장 단순한 방법부터 쓰고, 단계를 미리 알 수 없을 때만 에이전트를 쓰라고 권합니다. 워크플로에는 자주 쓰는 모양이 다섯 가지 있습니다. 앞 단계 결과를 다음 단계로 넘기는 체이닝, 입력 종류에 따라 담당을 나누는 라우팅, 여러 호출을 한꺼번에 돌리는 병렬화, 지휘 모델이 일을 나눠 주는 오케스트레이터-워커, 쓰고 평가하고 고치기를 반복하는 평가자-최적화입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;3화에서 이어지는 질문: 프롬프트 하나로 안 되는 일&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/9&quot;&gt;3화 &quot;단계별로 생각해 봐&quot;&lt;/a&gt;에서는 모델에게 한 번 잘 묻는 법을 다뤘습니다. 그런데 실제 일은 한 번 묻고 끝나지 않는 경우가 많습니다. 회의록을 정리하고, 할 일을 뽑고, 담당자별로 메시지를 쓰는 일처럼요.&lt;/p&gt;
&lt;p&gt;이런 일을 AI에게 맡길 때 요즘은 &quot;에이전트를 만들자&quot;는 말부터 나옵니다. &lt;a href=&quot;https://agentnote.tistory.com/7&quot;&gt;1화&lt;/a&gt;에서 본 것처럼 에이전트는 생각하고, 도구를 쓰고, 결과를 보고, 다시 생각하는 루프를 돕니다. 똑똑하지만 몇 바퀴를 돌지, 비용이 얼마나 들지 미리 알 수 없습니다.&lt;/p&gt;
&lt;p&gt;이번 화의 질문은 이것입니다. 여러 단계짜리 일은 모두 에이전트에게 맡겨야 할까요?&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;워크플로와 에이전트의 차이: 누가 순서를 정하나&lt;/h2&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/12-anthropic-workflow-patterns&quot;&gt;14-12 Anthropic's Workflow Patterns&lt;/a&gt;은 Anthropic의 글 &lt;a href=&quot;https://www.anthropic.com/research/building-effective-agents&quot;&gt;&quot;Building Effective Agents&quot;&lt;/a&gt;를 바탕으로 둘을 이렇게 나눕니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;워크플로&lt;/strong&gt;: 사람이 미리 짜 둔 순서대로 모델과 도구를 부릅니다. 순서도를 사람이 그립니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;에이전트&lt;/strong&gt;: 모델이 다음에 무엇을 할지, 어떤 도구를 쓸지 스스로 정합니다. 순서도를 모델이 그립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;주방에 비유하면 워크플로는 공정표가 붙은 주방입니다. 손질, 조리, 담기 순서가 정해져 있어 빠르고, 재료비가 예측되고, 문제가 생기면 몇 번째 단계인지 바로 압니다. 에이전트는 &quot;알아서 맛있게&quot;라고 셰프에게 맡기는 쪽입니다. 처음 보는 주문도 해내지만, 몇 단계가 걸릴지 미리 모릅니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bs1Qgf/dJMb999fugw/W1iObsXIR0fscG2h6hvNY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs1Qgf/dJMb999fugw/W1iObsXIR0fscG2h6hvNY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs1Qgf/dJMb999fugw/W1iObsXIR0fscG2h6hvNY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs1Qgf%2FdJMb999fugw%2FW1iObsXIR0fscG2h6hvNY1%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 1. 차이는 순서를 누가 정하느냐입니다.&lt;/p&gt;

&lt;p&gt;어느 쪽이 더 낫다는 이야기는 아닙니다. 레슨은 워크플로가 싸고 빠르고 고치기 쉬운 대신, 에이전트는 정해진 답이 없는 일을 풀 수 있지만 왜 실패했는지 따지기 어렵다고 정리합니다. Anthropic 글의 권고는 분명합니다. 가장 단순한 방법부터 쓰고, 그걸로 부족할 때만 복잡하게 만들라는 것입니다. 많은 경우 검색 결과와 예시를 곁들인 호출 한 번으로 충분하다고도 적습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;워크플로 패턴 다섯 가지&lt;/h2&gt;
&lt;p&gt;Anthropic 글은 실제로 자주 본 워크플로를 다섯 가지 모양으로 정리합니다. 다섯 가지 모두 바탕은 같습니다. 검색, 도구, 메모리를 붙인 언어 모델 하나입니다. &lt;a href=&quot;https://agentnote.tistory.com/8&quot;&gt;2화&lt;/a&gt;에서 본 함수 호출이 여기서 &quot;도구&quot;입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zYTin/dJMcabMZAPg/gxJNYam4ITh9KZKDeKsZUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zYTin/dJMcabMZAPg/gxJNYam4ITh9KZKDeKsZUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zYTin/dJMcabMZAPg/gxJNYam4ITh9KZKDeKsZUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzYTin%2FdJMcabMZAPg%2FgxJNYam4ITh9KZKDeKsZUk%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 2. 다섯 패턴과 각각 언제 쓰는지.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 체이닝(프롬프트 체이닝): 이어 붙이기.&lt;/strong&gt; 첫 호출의 답이 다음 호출의 입력이 됩니다. 마케팅 문구를 쓰고 그 문구를 번역하는 식입니다. 단계 사이에 코드로 검사하는 문을 둘 수 있습니다. 예를 들어 개요를 쓴 뒤 &quot;필요한 항목이 다 들어갔나&quot;를 확인하고 나서 본문으로 넘어갑니다. 일이 정해진 단계로 깔끔하게 나뉠 때 씁니다. 시간은 더 들지만 단계마다 쉬운 일만 시키니 정확해집니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 라우팅: 나눠 보내기.&lt;/strong&gt; 먼저 입력을 분류하고, 종류마다 다른 처리로 보냅니다. 고객 문의를 환불, 오류 신고, 영업 문의로 나눠 각각 다른 지시문으로 답하는 식입니다. 쉬운 질문은 작고 싼 모델로, 어려운 질문은 큰 모델로 보내는 것도 라우팅입니다. 종류가 뚜렷하고 분류를 정확히 할 수 있을 때 씁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 병렬화: 동시에 돌리기.&lt;/strong&gt; 두 가지 모양이 있습니다. 일을 독립된 조각으로 나눠 동시에 맡기는 &lt;strong&gt;나눠 맡기기&lt;/strong&gt;와, 같은 일을 여러 번 시켜 결과를 모으는 &lt;strong&gt;투표&lt;/strong&gt;입니다. 투표는 &lt;a href=&quot;https://agentnote.tistory.com/9&quot;&gt;3화&lt;/a&gt;에서 본 &quot;여러 번 풀게 하고 다수결&quot;과 같은 생각입니다. 속도가 필요하거나, 여러 관점으로 봐야 믿을 수 있을 때 씁니다. 코드 리뷰를 여러 번 돌려 취약점을 찾는 예가 글에 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 오케스트레이터-워커: 지휘자와 일꾼.&lt;/strong&gt; 지휘하는 모델이 일을 받아 하위 작업으로 쪼개고, 일꾼 모델들에게 나눠 준 뒤 결과를 합칩니다. 병렬화와 다른 점은 쪼개는 방식이 미리 정해져 있지 않다는 것입니다. 여러 파일을 한꺼번에 고쳐야 하는 코딩처럼, 어떤 하위 작업이 필요할지 미리 알 수 없을 때 씁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. 평가자-최적화: 쓰고 고치기.&lt;/strong&gt; 한 모델이 답을 쓰면 다른 모델이 평가하고 피드백을 줍니다. 통과할 때까지 반복합니다. 평가 기준이 분명하고, 고칠수록 실제로 나아질 때 씁니다. 글에는 문학 번역을 다듬는 예가 나옵니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;레슨 코드로 돌려 보면: 이름과 실제가 다른 곳&lt;/h2&gt;
&lt;p&gt;레슨 예제는 다섯 패턴을 각각 짧은 함수 하나로 만들고, 정해진 답을 돌려주는 가짜 모델로 흐름을 보여 줍니다. API 키 없이 바로 돌아갑니다. 다섯 패턴을 다 돌리는 데 모델 호출은 모두 20번입니다.&lt;/p&gt;
&lt;p&gt;그런데 코드를 읽어 보면 두 군데가 설명과 다릅니다.&lt;/p&gt;
&lt;p&gt;첫째, &lt;strong&gt;병렬화 코드가 실제로는 동시에 돌지 않습니다.&lt;/strong&gt; 레슨 설명은 &quot;여러 호출을 동시에&quot;라고 하는데, 코드는 다섯 번을 차례로 부릅니다. 호출 한 번에 1초가 걸리도록 가짜 모델을 바꿔 재 보니 레슨 코드는 5.0초, 동시에 부르도록 고친 코드는 1.0초가 걸렸습니다. 투표 결과(예 3표, 아니오 2표)는 같습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BQtGU/dJMcablReFO/HZKZVpoIkCKqaVXS0a5Rgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BQtGU/dJMcablReFO/HZKZVpoIkCKqaVXS0a5Rgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BQtGU/dJMcablReFO/HZKZVpoIkCKqaVXS0a5Rgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBQtGU%2FdJMcablReFO%2FHZKZVpoIkCKqaVXS0a5Rgk%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 3. 가짜 모델, 호출당 1초로 고정한 조건입니다. 실제 API는 호출마다 걸리는 시간이 다릅니다.&lt;/p&gt;

&lt;p&gt;둘째, &lt;strong&gt;오케스트레이터-워커 코드에는 지휘하는 모델이 없습니다.&lt;/strong&gt; 일꾼마다 &quot;작업에 python이라는 단어가 있으면 실행&quot; 같은 조건이 붙어 있고, 그 조건으로 일꾼을 고릅니다. 설명대로라면 지휘 모델이 작업을 보고 일을 나눠야 합니다. 레슨 코드는 단순화한 버전으로 보고, 원래 모양은 아래 &quot;더 깊이&quot;의 Anthropic 예제 코드에서 확인하는 게 좋습니다.&lt;/p&gt;
&lt;p&gt;패턴 이름만 보고 코드를 가져다 쓰면 이런 차이를 놓치기 쉽습니다. &quot;병렬&quot;이라고 적혀 있어도 정말 동시에 도는지, &quot;지휘자&quot;가 정말 판단을 하는지 한 번은 확인해야 합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;쓰고 고치기는 어떻게 도나&lt;/h2&gt;
&lt;p&gt;다섯 패턴 중 평가자-최적화는 레슨 예제 출력으로 보면 이해가 쉽습니다. 과제는 &quot;ReAct를 한 줄로 요약하기&quot;입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Csm4m/dJMcahzv21G/9uKiKrD4VD5ztyhl61HSDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Csm4m/dJMcahzv21G/9uKiKrD4VD5ztyhl61HSDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Csm4m/dJMcahzv21G/9uKiKrD4VD5ztyhl61HSDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCsm4m%2FdJMcahzv21G%2F9uKiKrD4VD5ztyhl61HSDK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 4. 레슨 예제의 실제 출력입니다. 가짜 모델이라 답은 미리 정해져 있습니다.&lt;/p&gt;

&lt;p&gt;1회차 답은 &quot;생각과 도구 호출을 반복한다&quot;였고, 평가에서 &quot;관찰(observation)이 빠졌다&quot;는 이유로 떨어집니다. 이 피드백을 붙여 다시 쓰게 하자 &quot;생각, 행동, 관찰을 끝날 때까지 번갈아 한다&quot;가 나오고 통과합니다. &lt;a href=&quot;https://agentnote.tistory.com/7&quot;&gt;1화&lt;/a&gt;에서 본 ReAct 루프의 세 단계가 그대로 들어간 답입니다.&lt;/p&gt;
&lt;p&gt;여기서 꼭 챙길 것은 멈춤 조건입니다. 레슨이 함께 주는 패턴 선택 지침은 반복 횟수 상한이 없는 평가 루프를 금지합니다. 평가가 계속 떨어뜨리면 끝없이 돌 수 있기 때문입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;에이전트는 언제 쓸까: 네 가지 질문&lt;/h2&gt;
&lt;p&gt;그럼 에이전트는 언제 쓸까요? Anthropic 글을 함께 쓴 Barry Zhang은 강연 &quot;How We Build Effective Agents&quot;에서 네 가지를 먼저 따져 보라고 합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIzkDw/dJMcahsRzKY/UWKSvaGbjkVdEaHCZZGueK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIzkDw/dJMcahsRzKY/UWKSvaGbjkVdEaHCZZGueK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIzkDw/dJMcahsRzKY/UWKSvaGbjkVdEaHCZZGueK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIzkDw%2FdJMcahsRzKY%2FUWKSvaGbjkVdEaHCZZGueK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 5. Barry Zhang 강연(AI Engineer Summit 2025)의 체크리스트를 정리했습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;일이 복잡하고 모호한가.&lt;/strong&gt; 갈림길을 전부 그릴 수 있으면 그냥 그 순서도를 만드는 게 싸고 다루기 쉽습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;그만한 가치가 있나.&lt;/strong&gt; 에이전트는 이것저것 시도하느라 토큰을 많이 씁니다. 건당 예산이 아주 작은 대량 고객 응대라면 흔한 경우만 워크플로로 처리하는 편이 낫다고 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;모델이 해낼 수 있나.&lt;/strong&gt; 코딩 에이전트라면 코드를 쓰고, 디버깅하고, 실수에서 회복할 수 있어야 합니다. 막히는 곳이 있으면 비용과 시간이 몇 배로 늘어납니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;틀렸을 때 비용과 발견이 어떤가.&lt;/strong&gt; 실수가 치명적이고 찾기 어렵다면 맡기기 어렵습니다. 읽기 전용 권한이나 사람 확인으로 줄일 수 있지만, 그만큼 맡길 수 있는 일도 줄어듭니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;그는 코딩을 좋은 예로 듭니다. 설계 문서에서 코드 변경까지 가는 길은 복잡하고, 좋은 코드는 가치가 크고, 결과를 테스트로 검증할 수 있기 때문입니다. 원본 레슨도 비슷하게 정리합니다. 단계를 셀 수 있거나, 비용 상한이 필요하거나, 감사 담당자가 흐름을 읽어야 하는 일은 워크플로가 낫습니다. 다음 단계가 앞 결과에 달린 조사나, 아직 정답 흐름을 모르는 새 영역은 에이전트가 낫습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;모델이 빨리 바뀌어도 남는 것&lt;/h2&gt;
&lt;p&gt;요즘은 모델이 바뀌는 속도가 너무 빨라서, 지난달에 익힌 요령이 이번 달엔 쓸모없어지는 일이 흔합니다. &lt;a href=&quot;https://agentnote.tistory.com/9&quot;&gt;3화&lt;/a&gt;에서 본 &quot;단계별로 생각해 봐&quot;도 최신 Claude 모델에서는 대안으로 밀려났습니다.&lt;/p&gt;
&lt;p&gt;그래서 이번 화에서는 특정 요령보다 오래 갈 판단 기준을 남겨 두려 합니다. &quot;순서를 미리 알 수 있는가&quot;라는 질문은 모델이 바뀌어도 그대로입니다. Barry Zhang도 처음부터 복잡하게 만들면 고치는 속도가 떨어진다며, 모델과 도구와 지시문이라는 기본 요소부터 다듬으라고 합니다. 단순하게 만들어 두면 더 나은 모델이 나왔을 때 갈아 끼우기도 쉽습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;따라 해 보기: 한 번에 시키기 vs 나눠 시키기&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. 채팅 창에서 체이닝 해 보기 (API 키 없이).&lt;/strong&gt; 긴 글 하나를 골라 두 가지로 시켜 보세요.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;한 번에: &quot;이 글을 세 줄로 요약하고, 요약을 바탕으로 제목 다섯 개를 지어 줘.&quot;&lt;/li&gt;
&lt;li&gt;나눠서: 먼저 &quot;이 글을 세 줄로 요약해 줘.&quot; 답을 확인하고 고친 뒤, 새 대화에서 &quot;이 요약으로 제목 다섯 개를 지어 줘.&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;두 번째가 체이닝입니다. 중간에 요약을 사람이 확인한 게 &quot;단계 사이의 검사 문&quot;입니다. 어느 쪽이 더 나았는지보다, 중간 결과를 확인할 수 있다는 게 어떤 차이를 만드는지 보세요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 레슨 코드 돌려 보기 (Python만 있으면 됨).&lt;/strong&gt; 원본 레슨 예제는 외부 패키지 없이 돌아갑니다.&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -O https://raw.githubusercontent.com/rohitg00/ai-engineering-from-scratch/main/phases/14-agent-engineering/12-anthropic-workflow-patterns/code/main.py
python3 main.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다섯 패턴의 흐름이 차례로 출력됩니다. 출력을 본 뒤 &lt;code&gt;parallel_vote&lt;/code&gt; 함수를 열어, 정말 동시에 부르는지 직접 확인해 보세요.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;이런 데 쓸 수 있다&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;문의 메일 분류 후 담당별 답변 초안 (라우팅).&lt;/strong&gt; 계정, 결제, 오류 신고, 기타로 나누고 종류마다 다른 지시문으로 초안을 씁니다. 분류가 애매하면 사람에게 넘기는 기준을 함께 둡니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;회의록에서 할 일 뽑기 (체이닝 + 검사).&lt;/strong&gt; 회의록 정리 → 할 일 추출 → 담당자별 메시지. 중간에 &quot;할 일마다 담당자와 기한이 있나&quot;를 코드로 검사합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;여러 관점 코드 리뷰 (병렬화 + 평가자-최적화).&lt;/strong&gt; 보안, 가독성, 테스트 관점을 동시에 돌려 합치고, 기준을 통과할 때까지 정해진 횟수만큼만 고쳐 쓰게 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 워크플로와 에이전트는 어떻게 구분하나요?&lt;/strong&gt;
순서를 누가 정하는지 보면 됩니다. &lt;a href=&quot;https://www.anthropic.com/research/building-effective-agents&quot;&gt;Anthropic &quot;Building Effective Agents&quot;&lt;/a&gt;는 미리 정한 코드 경로로 모델과 도구를 엮으면 워크플로, 모델이 자기 과정과 도구 사용을 스스로 정하면 에이전트로 나눕니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 멀티에이전트 프레임워크를 꼭 써야 하나요?&lt;/strong&gt;
처음에는 필요 없는 경우가 많습니다. Anthropic 글은 프레임워크가 실제 프롬프트와 응답을 가려 디버깅을 어렵게 할 수 있으니 API를 직접 부르는 것부터 시작하라고 권합니다. 원본 레슨도 3단계 체이닝에 프레임워크를 쓰는 것을 과설계로 봅니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 일꾼 모델 여러 개를 쓰면 멀티에이전트인가요?&lt;/strong&gt;
꼭 그렇지는 않습니다. 원본 레슨의 패턴 선택 지침은 일꾼 셋을 둔 오케스트레이터-워커를 &quot;멀티에이전트&quot;라고 부르지 말라고 합니다. 일꾼은 스스로 판단하며 도는 에이전트가 아니라 한 번씩 부르는 모델 호출이기 때문입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;더 깊이: Anthropic 글, 강연 두 편, Self-Refine 논문, 코드&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Anthropic &quot;Building Effective Agents&quot; (Erik Schluntz, Barry Zhang, 2024-12-19).&lt;/strong&gt; &lt;a href=&quot;https://www.anthropic.com/research/building-effective-agents&quot;&gt;원문&lt;/a&gt;. 이번 화의 주 출처입니다. 패턴마다 언제 쓰는지를 이렇게 적습니다. 체이닝은 정해진 하위 작업으로 깔끔하게 나뉠 때, 시간을 정확도와 맞바꾸는 방법입니다. 라우팅은 종류가 뚜렷하고 분류가 정확할 때 씁니다. 병렬화는 나눠서 빨라지거나 여러 관점이 필요할 때 쓰고, 안전 검사를 본 답변과 별도 호출로 돌리는 예도 듭니다. 오케스트레이터-워커는 필요한 하위 작업을 미리 알 수 없을 때, 평가자-최적화는 평가 기준이 분명하고 반복 개선의 효과가 측정될 때 씁니다. 에이전트는 시간과 비용을 성능과 맞바꾼다고 보고, 에이전트를 만들 때의 원칙 세 가지로 단순함, 투명함(계획 단계를 드러내기), 도구 설명과 테스트를 꼽습니다. 부록은 고객 지원과 코딩을 에이전트가 특히 잘 맞는 사례로 듭니다. 코딩은 자동 테스트로 결과를 검증할 수 있기 때문입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Barry Zhang, &quot;How We Build Effective Agents&quot; (AI Engineer Summit 2025, 15분).&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=D7_ipDqhtwk&quot;&gt;영상&lt;/a&gt;. 핵심은 세 가지입니다(&lt;a href=&quot;https://www.youtube.com/watch?v=D7_ipDqhtwk&amp;amp;t=52s&quot;&gt;0:52&lt;/a&gt;). 모든 일에 에이전트를 만들지 말 것, 단순하게 유지할 것, 에이전트 입장에서 생각할 것. 체크리스트는 &lt;a href=&quot;https://www.youtube.com/watch?v=D7_ipDqhtwk&amp;amp;t=2m57s&quot;&gt;2:57&lt;/a&gt;부터입니다. 건당 예산이 10센트 정도인 대량 고객 지원이라면 3만~5만 토큰밖에 쓸 수 없으니 흔한 경우만 워크플로로 처리하라는 예를 듭니다. &lt;a href=&quot;https://www.youtube.com/watch?v=D7_ipDqhtwk&amp;amp;t=5m38s&quot;&gt;5:38&lt;/a&gt;에서는 에이전트를 &quot;루프 안에서 도구를 쓰는 모델&quot;로 정의하고, 환경·도구·시스템 프롬프트 세 가지만 먼저 다듬으라고 합니다. &lt;a href=&quot;https://www.youtube.com/watch?v=D7_ipDqhtwk&amp;amp;t=8m03s&quot;&gt;8:03&lt;/a&gt;의 &quot;에이전트처럼 생각하기&quot;에서는 매 단계 모델이 아는 건 컨텍스트에 들어 있는 것뿐이니, 시스템 프롬프트와 도구 설명을 Claude에게 보여 주고 어디가 모호한지 물어보라고 권합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stanford Webinar &quot;Agentic AI&quot; (Insop Song).&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=kJLiOGle3Lw&quot;&gt;영상&lt;/a&gt;. 설명란 챕터 시각이 실제와 어긋나 자막 기준으로 적습니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=31m53s&quot;&gt;31:53&lt;/a&gt;에서 사람이 프롬프트를 미리 쪼개 잇는 방식(체이닝)과 모델에게 계획을 세우게 하는 방식을 대비합니다. 워크플로와 에이전트를 가르는 &quot;누가 쪼개느냐&quot;와 같은 이야기입니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=33m15s&quot;&gt;33:15&lt;/a&gt;의 고객 지원 예는 환불 문의를 규정 확인, 주문 확인, 제품 확인으로 나누고 마지막은 사람이 승인합니다. &lt;a href=&quot;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=39m00s&quot;&gt;39:00&lt;/a&gt;의 &quot;디자인 패턴&quot;은 Anthropic의 다섯 가지와 다른 분류(계획, 반성, 도구 사용, 멀티에이전트)입니다. 이 중 반성(reflection)은 코드를 검토해 피드백을 받고 그 피드백으로 다시 고쳐 쓰는 예로 설명하는데, 평가자-최적화와 같은 모양입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Self-Refine 논문.&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/2303.17651&quot;&gt;Madaan 외, &quot;Self-Refine: Iterative Refinement with Self-Feedback&quot;(arXiv 2303.17651, 2023년 3월)&lt;/a&gt;. 같은 모델 하나가 초안을 쓰고, 스스로 피드백을 주고, 그 피드백으로 고치기를 반복합니다. 추가 학습이 필요 없습니다. 초록에 따르면 대화 응답부터 수학 추론까지 7개 과제에서 GPT-3.5, ChatGPT, GPT-4 모두 한 번에 쓴 답보다 선호됐고, 과제 성능이 평균 약 20%p 올랐습니다. Anthropic 글의 평가자-최적화는 쓰는 모델과 평가하는 모델을 나눈다는 점이 다르고, 원본 레슨은 평가자-최적화를 Self-Refine의 일반형으로 봅니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;코드.&lt;/strong&gt; 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/12-anthropic-workflow-patterns&quot;&gt;14-12&lt;/a&gt;의 &lt;code&gt;code/main.py&lt;/code&gt;는 표준 라이브러리만으로 다섯 패턴을 보여 줍니다(위 &quot;따라 해 보기&quot;). 실제 모델로 돌리는 참조 구현은 &lt;a href=&quot;https://github.com/anthropics/claude-cookbooks/tree/main/patterns/agents&quot;&gt;anthropics/claude-cookbooks의 &lt;code&gt;patterns/agents&lt;/code&gt;&lt;/a&gt;(MIT)에 있습니다. &lt;code&gt;basic_workflows&lt;/code&gt; 노트북의 &lt;code&gt;parallel()&lt;/code&gt;은 &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;로 실제로 동시에 부르고, &lt;code&gt;route()&lt;/code&gt;는 분류 전에 이유부터 쓰게 한 뒤 선택을 XML 태그로 받습니다. 3화의 생각의 사슬을 라우팅 판단에 쓴 셈입니다. &lt;code&gt;orchestrator_workers&lt;/code&gt; 노트북은 지휘 모델이 입력을 보고 작업 목록을 만들고, 작업마다 일꾼 모델을 부릅니다. 노트북은 Anthropic API 키가 있어야 돌아가고 요금이 듭니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;다음 화 예고.&lt;/strong&gt; 1막은 여기까지입니다. 에이전트가 무엇이고(0화), 어떻게 돌고(1화), 도구를 어떻게 쓰고(2화), 어떻게 말을 걸고(3화), 일을 어떻게 나누는지(4화) 봤습니다. 2막은 에이전트를 바깥세상과 연결하는 이야기입니다. 5화에서는 도구를 연결하는 표준 규격인 MCP의 구조를 다룹니다.&lt;/p&gt;
&lt;hr style=&quot;border:0;border-top:1px solid #dcdfe3;margin:36px 0;&quot; /&gt;
&lt;p&gt;원본: rohitg00/ai-engineering-from-scratch (MIT, © 2026 Rohit Ghumare). 이 글은 원문을 바탕으로 직접 정리하고 재구성했습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top:32px;&quot;&gt;출처&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 14-12 Anthropic's Workflow Patterns: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/12-anthropic-workflow-patterns&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/12-anthropic-workflow-patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anthropic, Building Effective Agents (2024-12-19): &lt;a href=&quot;https://www.anthropic.com/research/building-effective-agents&quot;&gt;https://www.anthropic.com/research/building-effective-agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Barry Zhang, How We Build Effective Agents (AI Engineer Summit 2025, 영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=D7_ipDqhtwk&quot;&gt;https://www.youtube.com/watch?v=D7_ipDqhtwk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford Webinar, Agentic AI (Insop Song), 31:53 (영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=31m53s&quot;&gt;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=31m53s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Madaan et al., Self-Refine (arXiv 2303.17651): &lt;a href=&quot;https://arxiv.org/abs/2303.17651&quot;&gt;https://arxiv.org/abs/2303.17651&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;anthropics/claude-cookbooks, patterns/agents (MIT): &lt;a href=&quot;https://github.com/anthropics/claude-cookbooks/tree/main/patterns/agents&quot;&gt;https://github.com/anthropics/claude-cookbooks/tree/main/patterns/agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/Engineering</category>
      <category>ai 에이전트</category>
      <category>ai-engineering-from-scratch</category>
      <category>Anthropic</category>
      <category>Building Effective Agents</category>
      <category>Claude</category>
      <category>LLM</category>
      <category>생성형 ai</category>
      <category>워크플로 패턴</category>
      <category>프롬프트 체이닝</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/10</guid>
      <comments>https://agentnote.tistory.com/10#entry10comment</comments>
      <pubDate>Thu, 15 Oct 2026 14:25:10 +0900</pubDate>
    </item>
    <item>
      <title>AI에게 &amp;quot;단계별로 생각해 봐&amp;quot;라고 하면 정말 더 잘할까? 프롬프트 기법 쉽게 정리 (퓨샷, 생각의 사슬)</title>
      <link>https://agentnote.tistory.com/9</link>
      <description>&lt;!-- 제목: AI에게 &quot;단계별로 생각해 봐&quot;라고 하면 정말 더 잘할까? 프롬프트 기법 쉽게 정리 (퓨샷, 생각의 사슬) | 태그: 프롬프트 엔지니어링, 프롬프트 기법, Chain-of-Thought, 퓨샷 프롬프트, LLM, ChatGPT, Claude, 생성형 AI, ai-engineering-from-scratch --&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;&lt;strong&gt;요약.&lt;/strong&gt; 같은 AI라도 어떻게 묻느냐에 따라 답이 달라집니다. 잘 묻는 방법은 크게 세 가지입니다. 원하는 것을 구체적으로 적기, 질문과 답의 예시를 몇 개 함께 보여 주기(퓨샷), 바로 답하지 말고 풀이 과정을 먼저 써 보게 하기(생각의 사슬)입니다. 2022년 연구에서는 질문 뒤에 &quot;단계별로 생각해 보자&quot; 한 줄만 붙여도 수학 문제 정답률이 몇 배로 올랐습니다. 다만 최신 Claude 모델처럼 답하기 전에 스스로 생각하는 기능이 있는 모델에는, 이 한 줄 대신 그 기능에 맡기라는 것이 공식 권고입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;2화에서 이어지는 질문: 모델에게 어떻게 말해야 할까&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/8&quot;&gt;2화 &quot;AI는 글자만 쓰는데, 어떻게 도구를 쓸까?&quot;&lt;/a&gt;에서 모델은 도구를 직접 누르지 않고, 무엇을 부를지 &quot;결정&quot;만 한다고 했습니다. &lt;a href=&quot;https://agentnote.tistory.com/7&quot;&gt;1화&lt;/a&gt;의 에이전트도 매 단계 다음에 할 일을 결정합니다.&lt;/p&gt;
&lt;p&gt;그럼 모델은 무엇을 보고 결정할까요? 우리가 보낸 글, 즉 &lt;strong&gt;프롬프트&lt;/strong&gt;(모델에게 보내는 질문과 지시)뿐입니다. 그래서 같은 모델이라도 프롬프트를 어떻게 쓰느냐에 따라 결정이 달라집니다.&lt;/p&gt;
&lt;p&gt;이번 화에서는 두 가지를 알아봅니다. 같은 모델에게 어떻게 말하면 더 잘 답할까요? 그리고 자주 들리는 &quot;단계별로 생각해 봐&quot;는 정말 효과가 있을까요?&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;같은 모델, 다른 답: 지시를 구체적으로&lt;/h2&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/01-prompt-engineering&quot;&gt;11-01 Prompt Engineering&lt;/a&gt;은 이렇게 시작합니다. 모델에게 보낸 글은 단어 하나까지 모두 &quot;이렇게 해 달라&quot;는 요청으로 읽히고, 모델은 그 말을 곧이곧대로 따른다는 것입니다.&lt;/p&gt;
&lt;p&gt;&quot;마케팅 메일 써 줘&quot;라고만 하면 어디서 본 듯한 메일이 나옵니다. 누가 읽는지, 어떤 말투인지, 몇 줄인지, 꼭 넣을 숫자와 마지막에 누를 버튼 문구까지 정해 주면 같은 모델에서 전혀 다른 메일이 나옵니다. 레슨은 답이 평범한 이유를 모델이 아니라 질문에서 찾습니다.&lt;/p&gt;
&lt;p&gt;레슨이 꼽는 기본기는 이렇습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;역할&lt;/strong&gt;: &quot;당신은 ~입니다&quot;로 시작해 관점을 정합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;지시&lt;/strong&gt;: 형식, 길이, 독자, 넣을 것과 뺄 것을 적습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;출력 형식&lt;/strong&gt;: 번호 목록, 표, JSON처럼 답의 모양을 정합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;제약&lt;/strong&gt;: &quot;하지 마라&quot;, &quot;항상 해라&quot;, &quot;만약 ~면 ~해라&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;여기까지는 사람에게 일을 맡길 때와 다르지 않습니다. 이번 화에서 더 들여다볼 것은 두 가지입니다. 예시를 함께 주는 방법, 그리고 답보다 풀이를 먼저 쓰게 하는 방법입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;퓨샷 프롬프트: 견본 서류를 먼저 보여 준다&lt;/h2&gt;
&lt;p&gt;서류 양식을 처음 받으면 작성 요령을 길게 읽는 것보다, 다 채워진 견본 한두 장을 보는 게 빠릅니다. 모델도 비슷합니다.&lt;/p&gt;
&lt;p&gt;질문만 주는 방식을 &lt;strong&gt;제로샷&lt;/strong&gt;이라고 부릅니다. 질문 앞에 &quot;이런 질문에는 이렇게 답한다&quot;는 예시를 몇 개 붙이는 방식이 &lt;strong&gt;퓨샷&lt;/strong&gt;입니다. 예시를 준다고 모델 자체가 바뀌지는 않습니다. 그 대화 안에서만 통하는 본보기입니다.&lt;/p&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&quot;&gt;11-02 Few-Shot, Chain-of-Thought&lt;/a&gt;의 예제 코드는 같은 수학 문제를 세 가지로 묻습니다. 그림 1은 이때 코드가 실제로 만드는 프롬프트입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpEAf8/dJMcadDBMrZ/9fExhHBr96nz2ml1hmb0IK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpEAf8/dJMcadDBMrZ/9fExhHBr96nz2ml1hmb0IK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpEAf8/dJMcadDBMrZ/9fExhHBr96nz2ml1hmb0IK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpEAf8%2FdJMcadDBMrZ%2F9fExhHBr96nz2ml1hmb0IK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 1. 차이는 문장 몇 개입니다. 퓨샷은 견본 3개 때문에 질문이 약 10배 길어집니다.&lt;/p&gt;

&lt;p&gt;다만 예시를 붙이는 데도 비용이 듭니다. 쓸 만한 예시를 고르는 데 시간이 들고, 예시가 많을수록 프롬프트가 길어져 요금과 응답 시간도 늘어납니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;생각의 사슬(Chain-of-Thought): 암산 대신 연습장에 풀기&lt;/h2&gt;
&lt;p&gt;그림 1의 세 번째 칸을 보세요. 답 자리에 &quot;Let's think step by step(단계별로 생각해 보자)&quot;을 미리 써 둡니다. 그러면 모델은 숫자부터 내놓지 않고 풀이를 먼저 씁니다. 이렇게 답을 내기 전에 풀이 과정을 먼저 쓰게 하는 방법을 &lt;strong&gt;생각의 사슬(Chain-of-Thought, CoT)&lt;/strong&gt; 이라고 부릅니다.&lt;/p&gt;
&lt;p&gt;비유하면 암산 대신 연습장에 푸는 것입니다. 레슨도 이를 연습장(scratch paper)이라고 부릅니다. 언어 모델은 앞에 쓴 글자를 보고 다음 글자를 정합니다. 그래서 중간 계산을 글로 써 두면, 그 계산이 다음 단계의 근거가 됩니다. 모델이 사람처럼 생각한다는 뜻은 아닙니다. 써 둔 글자가 다시 읽힌다는 뜻입니다.&lt;/p&gt;
&lt;p&gt;효과는 생각보다 컸습니다. 2022년에 나온 한 연구는 이 한 줄만 붙여 수학 문장제 정답률이 어떻게 바뀌는지 쟀습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YRoha/dJMcaf2CVxS/P9uYPPD7Ad9yLLBKKJdjvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YRoha/dJMcaf2CVxS/P9uYPPD7Ad9yLLBKKJdjvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YRoha/dJMcaf2CVxS/P9uYPPD7Ad9yLLBKKJdjvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYRoha%2FdJMcaf2CVxS%2FP9uYPPD7Ad9yLLBKKJdjvK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 2. 2022년 모델 기준 숫자입니다. 출처는 아래 &quot;더 깊이&quot;에 있습니다.&lt;/p&gt;

&lt;p&gt;이 숫자를 지금 모델에 그대로 대입하면 안 됩니다. 요즘 모델은 한 줄 없이도 이 문제들을 훨씬 잘 풉니다. 그래도 풀이를 쓰게 하면 좋은 점이 하나 남습니다. 틀렸을 때 어디서 틀렸는지 읽을 수 있다는 것입니다.&lt;/p&gt;
&lt;p&gt;생각의 사슬이 늘 이득은 아닙니다. 레슨은 단순한 사실 질문이나 한 단계짜리 분류에서는 글자만 늘고 얻는 게 없다고 봅니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;자기 일관성: 여러 번 풀게 하고 다수결&lt;/h2&gt;
&lt;p&gt;한 걸음 더 나간 방법도 있습니다. 같은 문제를 여러 번 풀게 하고, 가장 많이 나온 답을 고르는 것입니다. 이를 &lt;strong&gt;자기 일관성(Self-Consistency)&lt;/strong&gt; 이라고 부릅니다.&lt;/p&gt;
&lt;p&gt;매번 조금씩 다르게 풀도록 temperature(답의 무작위성을 정하는 값)를 조금 올려 둡니다. 풀이 과정은 버리고 마지막 답만 셉니다. 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&quot;&gt;11-02&lt;/a&gt;의 예시 풀이 다섯 개를 레슨 코드의 투표 함수에 넣으면 그림 3처럼 나옵니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mHvc9/dJMcacZd3Y9/8z90WsspeZ9xxA5YurqcPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mHvc9/dJMcacZd3Y9/8z90WsspeZ9xxA5YurqcPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mHvc9/dJMcacZd3Y9/8z90WsspeZ9xxA5YurqcPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmHvc9%2FdJMcacZd3Y9%2F8z90WsspeZ9xxA5YurqcPK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 3. 다섯 번 중 네 번 나온 24를 답으로 고릅니다.&lt;/p&gt;

&lt;p&gt;단점도 분명합니다. 다섯 번 부르면 비용도 다섯 배입니다. 다섯 번이 모두 같은 방향으로 틀리면 투표로도 고칠 수 없습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;견본의 실수도 그대로 따라 한다&lt;/h2&gt;
&lt;p&gt;퓨샷에는 함정이 하나 있습니다. 모델은 견본의 좋은 점만 따라 하지 않습니다.&lt;/p&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&quot;&gt;11-02&lt;/a&gt;의 견본 풀이는 &quot;The answer is 72.&quot;처럼 마침표로 끝납니다. 그런데 레슨의 채점 코드는 마침표까지 숫자로 읽어 &lt;code&gt;72.&lt;/code&gt;와 &lt;code&gt;72&lt;/code&gt;를 다른 답으로 봅니다. 모든 문제를 맞히는 가짜 모델이 견본 형식대로 답하게 하고 채점하면 그림 4처럼 나옵니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6x4Dq/dJMcagOd44M/V569kGZKMCrmH5iWm5NtE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6x4Dq/dJMcagOd44M/V569kGZKMCrmH5iWm5NtE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6x4Dq/dJMcagOd44M/V569kGZKMCrmH5iWm5NtE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6x4Dq%2FdJMcagOd44M%2FV569kGZKMCrmH5iWm5NtE1%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 4. 네 방식 모두 다섯 문제를 다 맞히고도 0%로 채점됩니다.&lt;/p&gt;

&lt;p&gt;같은 레슨의 견본 하나는 원래 수학 문제와 조건이 달라져 있었고, 풀이도 원래 정답과 다른 답으로 끝났습니다. 기본 설정에서는 쓰이지 않는 견본이지만, 견본 수를 늘리면 틀린 풀이가 모범 답안으로 들어갑니다. 그래서 견본을 쓰기 전에 견본부터 검사해야 합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;최신 Claude 모델에도 통할까&lt;/h2&gt;
&lt;p&gt;위 숫자는 2022년 모델로 잰 것입니다. 요즘 모델에도 그대로 통할까요? 2026년 10월 기준 &lt;a href=&quot;https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices&quot;&gt;Claude 공식 문서 &quot;Prompting best practices&quot;&lt;/a&gt;로 확인해 보면, 네 가지 중 둘은 그대로이고 둘은 달라졌습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;구체적인 지시: 오히려 더 중요해졌습니다.&lt;/strong&gt; 문서는 최신 Claude 모델이 지시를 정확히 따르도록 학습됐다고 설명합니다. 원하는 게 있으면 모델이 알아서 짐작하길 기대하지 말고 분명히 적으라고 합니다. 문서는 Claude를 &quot;똑똑하지만 우리 팀 사정은 모르는 신입 직원&quot;에 빗댑니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;예시(퓨샷): 여전히 권장합니다.&lt;/strong&gt; 문서는 예시를 답의 형식, 말투, 구조를 맞추는 가장 믿을 만한 방법 중 하나로 꼽고, 3~5개를 권합니다. 대신 예시끼리 충분히 다르게 만들라고 합니다. 의도하지 않은 패턴까지 따라 할 수 있어서입니다. 앞에서 본 마침표 사례와 같은 이야기입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;단계별로 생각해 봐&quot;: 이제는 대안입니다.&lt;/strong&gt; 최신 Claude 모델에는 답하기 전에 따로 생각하는 기능(thinking)이 있습니다. 문서는 손으로 단계별 풀이를 시키는 방법을 이 기능이 꺼져 있을 때 쓰는 대안(fallback)으로 소개합니다. Claude Opus 5.5, Sonnet 5.5 같은 최신 모델에서는 생각하는 기능에 맡기라고 하고, 답 안에 풀이를 따로 적어 달라는 요청은 거절될 수 있다고 적습니다. 단계를 하나하나 정해 주기보다 &quot;충분히 생각해 봐&quot; 같은 넓은 지시가 더 나은 경우가 많다고도 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자기 일관성: 문서에 나오지 않습니다.&lt;/strong&gt; 여러 번 풀어 다수결하는 방법은 Claude 문서에서 찾지 못했습니다. 연구에서 나온 기법으로 알아 두면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&quot;&gt;11-02&lt;/a&gt;도 같은 방향입니다. 답하기 전에 스스로 길게 생각하도록 만든 추론 모델에는 이 주문이 필요 없거나 오히려 해로울 수 있다고 적습니다. 아래 &quot;더 깊이&quot;의 스탠퍼드 강의는 한 걸음 더 나가, 요즘 모델은 예시 없이 지시만 잘 써도 비슷하거나 더 나은 결과가 나올 수 있다고 봅니다.&lt;/p&gt;
&lt;p&gt;그렇다고 생각의 사슬을 몰라도 되는 건 아닙니다. 요즘 모델의 생각하는 기능도 답하기 전에 풀이할 자리를 따로 준다는 점에서 닮았습니다. 왜 풀이를 먼저 쓰면 잘 맞히는지 알면, 그 기능을 언제 켜고 얼마나 쓸지 판단하기도 쉬워집니다.&lt;/p&gt;
&lt;p&gt;정리하면 이렇습니다. 먼저 지시를 구체적으로 씁니다. 형식이나 기준이 말로 잘 전해지지 않으면 서로 다른 예시를 몇 개 붙입니다. 풀이는 생각하는 기능이 있는 모델이면 그 기능에 맡기고, 없는 모델에서만 &quot;단계별로 생각해 봐&quot;를 붙입니다. 여러 번 풀어 다수결하는 방법은 틀리면 손해가 큰 일에만 씁니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;따라 해 보기: 같은 질문을 두 가지로 물어보기&lt;/h2&gt;
&lt;p&gt;API 키 없이 채팅 창에서 해 볼 수 있습니다. 쓰는 AI(ChatGPT, Claude 등)에 아래 문제를 두 번 물어보세요. 한 번은 그대로, 한 번은 끝에 &quot;단계별로 생각해 보세요.&quot;를 붙여서요.&lt;/p&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;저글러가 공 16개를 던집니다. 공의 절반은 골프공이고, 골프공의 절반은 파란색입니다. 파란 골프공은 몇 개일까요?&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;요즘 모델은 둘 다 맞힐 가능성이 높습니다(정답 4). 생각하는 기능이 켜진 모델은 한 줄을 붙이지 않아도 먼저 생각한 뒤 답합니다. 맞고 틀림보다 두 답의 모양이 어떻게 다른지 비교해 보세요.&lt;/p&gt;
&lt;p&gt;프롬프트 두 개를 여러 질문에 나란히 돌려 보고 싶다면 오픈소스 평가 도구 promptfoo가 있습니다. 아래 설정은 실제 모델 대신 받은 글을 그대로 돌려주는 &lt;code&gt;echo&lt;/code&gt;를 써서 키 없이 돌아갑니다. 비교 틀만 보여 주고 정확도는 재지 않습니다.&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;# promptfooconfig.yaml
providers:
  - echo
prompts:
  - &amp;quot;Q: {{question}} A:&amp;quot;
  - &amp;quot;Q: {{question}} A: Let's think step by step.&amp;quot;
tests:
  - vars:
      question: &amp;quot;A juggler can juggle 16 balls. Half of the balls are golf balls, and half of the golf balls are blue. How many blue golf balls are there?&amp;quot;
    assert:
      - type: icontains
        value: &amp;quot;step by step&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;PROMPTFOO_DISABLE_TELEMETRY=1 npx -y promptfoo@latest eval -c promptfooconfig.yaml --no-share
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;echo&lt;/code&gt;를 실제 모델로 바꾸고 검사를 &lt;code&gt;contains: &quot;4&quot;&lt;/code&gt;로 바꾸면 진짜 정답률 비교가 됩니다(API 키 필요).&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 프롬프트 엔지니어링은 아직 필요한가요?&lt;/strong&gt;
요령보다 원하는 것을 분명히 쓰는 일이 더 중요해졌습니다. 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/01-prompt-engineering&quot;&gt;11-01&lt;/a&gt;은 프롬프트 엔지니어링을 지시를 잘 쓰는 일로 정의하고, &lt;a href=&quot;https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices&quot;&gt;Claude 공식 문서&lt;/a&gt;도 최신 모델은 적힌 지시를 정확히 따르니 바라는 것을 분명히 적으라고 합니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 견본은 몇 개가 좋나요?&lt;/strong&gt;
원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&quot;&gt;11-02&lt;/a&gt;와 &lt;a href=&quot;https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices&quot;&gt;Claude 공식 문서&lt;/a&gt; 모두 3~5개를 권합니다. 숫자보다 중요한 건 내용입니다. 실제 질문과 비슷하면서도, 예시끼리는 충분히 달라야 엉뚱한 패턴을 따라 하지 않습니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. &quot;단계별로 생각해 봐&quot;는 아무 질문에나 붙이면 되나요?&lt;/strong&gt;
여러 단계 계산이나 판단이 필요한 질문에서 효과가 납니다. 단순한 사실 질문에서는 답만 길어집니다. Claude Opus 5.5, Sonnet 5.5처럼 생각하는 기능이 있는 모델은 이 한 줄 대신 그 기능에 맡기라는 것이 공식 권고입니다. 다른 회사 모델도 그 회사 문서를 먼저 확인하세요.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;더 깊이: CoT 논문 세 편, 스탠퍼드 강의, 코드&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;생각의 사슬 논문.&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/2201.11903&quot;&gt;Wei 외, &quot;Chain-of-Thought Prompting Elicits Reasoning in Large Language Models&quot;(arXiv 2201.11903, 2022년 1월)&lt;/a&gt;. 초록의 주장은 세 가지입니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;중간 풀이 단계를 쓰게 하면 복잡한 추론을 훨씬 잘합니다.&lt;/li&gt;
&lt;li&gt;충분히 큰 모델에서는 풀이가 적힌 예시 몇 개만 프롬프트에 넣어도 이 능력이 나타납니다.&lt;/li&gt;
&lt;li&gt;산술, 상식, 기호 추론에서 세 종류 대형 모델 모두 좋아졌습니다. 5,400억 매개변수 모델에 풀이 예시 8개만 주고 초등 수학 문장제 벤치마크(GSM8K)에서 당시 최고 성능을 냈습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 논문의 방식은 그림 1의 가운데 칸, 풀이가 있는 견본입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;Let's think step by step&quot; 논문.&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/2205.11916&quot;&gt;Kojima 외, &quot;Large Language Models are Zero-Shot Reasoners&quot;(arXiv 2205.11916, 2022년 5월, NeurIPS 2022)&lt;/a&gt;. 견본 없이 답 앞에 &quot;Let's think step by step&quot; 한 줄만 붙이는 방식입니다(그림 1의 세 번째 칸). 같은 한 줄이 산술, 기호, 논리 과제에 두루 통했다고 보고합니다. 그림 2의 숫자가 이 초록에 있습니다. InstructGPT(text-davinci-002)에서 MultiArith 17.7% → 78.7%, GSM8K 10.4% → 40.7%입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;자기 일관성 논문.&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/2203.11171&quot;&gt;Wang 외, &quot;Self-Consistency Improves Chain of Thought Reasoning in Language Models&quot;(arXiv 2203.11171, 2022년 3월, ICLR 2023)&lt;/a&gt;. 가장 그럴듯한 풀이 하나만 고르는 대신 서로 다른 풀이를 여럿 뽑고, 가장 많이 나온 최종 답을 고릅니다. 어려운 문제일수록 정답에 이르는 길이 여러 갈래라는 직관입니다. 초록은 GSM8K +17.9%, SVAMP +11.0%, AQuA +12.2% 등의 향상을 보고합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stanford CME295 3강 &quot;Prompting&quot;(&lt;a href=&quot;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h7m7s&quot;&gt;1:07:07&lt;/a&gt;).&lt;/strong&gt; 프롬프트 구조에는 정해진 이론이 없지만, 맥락·지시·입력·제약 네 부분으로 보는 게 좋은 사고 틀이라고 설명합니다(&lt;a href=&quot;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h11m45s&quot;&gt;1:11:45&lt;/a&gt;). 제로샷과 퓨샷을 소개한 뒤 이렇게 덧붙입니다(&lt;a href=&quot;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h16m49s&quot;&gt;1:16:49&lt;/a&gt;). 퓨샷이 대체로 낫지만 늘 그렇지는 않고, 요즘 추론 가능한 모델은 지시를 잘 쓰면 예시를 준 것과 비슷하거나 더 낫다는 것입니다. 예시가 모델을 몇 가지 본보기 안에 가둘 수 있다는 이유를 들고, 이 연구는 아직 진행 중이라고 덧붙입니다.&lt;/p&gt;
&lt;p&gt;생각의 사슬(&lt;a href=&quot;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h18m47s&quot;&gt;1:18:47&lt;/a&gt;)에서는 쓸모를 하나 더 꼽습니다. 풀이가 읽을 수 있는 글이라 디버깅이 쉽다는 것입니다(&lt;a href=&quot;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h20m12s&quot;&gt;1:20:12&lt;/a&gt;). 풀이에 엉뚱한 연도가 나오면, 문맥에 날짜를 잘못 넣었다는 걸 바로 알 수 있습니다. 글자가 늘어 느려지기는 하지만 대체로 감수할 만하다고 봅니다. 자기 일관성(&lt;a href=&quot;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h21m38s&quot;&gt;1:21:38&lt;/a&gt;)은 여러 번 뽑아 최종 답만 다수결하는 방법으로 설명합니다. 답을 꺼내기 쉽게 &quot;답을 맨 끝에 쓰라&quot;고 시키라는 팁과, 여러 번 부르는 일은 동시에 돌릴 수 있어 기다리는 시간이 가장 느린 한 번 수준이라는 설명도 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stanford CS230 8강 &quot;Agents, Prompts, and RAG&quot;(Kian Katanforoosh, &lt;a href=&quot;https://www.youtube.com/watch?v=k1njvbBmfsw&amp;amp;t=17m51s&quot;&gt;17:51&lt;/a&gt;).&lt;/strong&gt; 기본 원칙으로 &quot;이 문서 요약해&quot;를 &quot;재생에너지 과학 논문 10쪽을 정책 결정자를 위해 핵심 발견 중심 다섯 줄로&quot;처럼 독자·형식·초점을 정한 지시로 바꾸는 예를 듭니다(&lt;a href=&quot;https://www.youtube.com/watch?v=k1njvbBmfsw&amp;amp;t=21m41s&quot;&gt;21:41&lt;/a&gt;). 퓨샷 예로는 &quot;제품은 괜찮은데 기대보다는 아쉬웠다&quot;라는 리뷰의 어조 분류를 듭니다(&lt;a href=&quot;https://www.youtube.com/watch?v=k1njvbBmfsw&amp;amp;t=27m53s&quot;&gt;27:53&lt;/a&gt;). 업계마다 기준이 주관적이라, 라벨을 붙인 예시 세 개로 원하는 기준을 맞춘다는 설명입니다. 프롬프트를 고친 뒤에는 처음엔 사람이 직접 보고, 이후 promptfoo 같은 도구와 다른 모델을 심판으로 쓰는 평가로 넘어가라고 권합니다(&lt;a href=&quot;https://www.youtube.com/watch?v=k1njvbBmfsw&amp;amp;t=38m&quot;&gt;38:00&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;코드.&lt;/strong&gt; 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/01-prompt-engineering&quot;&gt;11-01&lt;/a&gt;의 예제는 API 키 없이 돌아갑니다(모델 자리는 가짜). 프롬프트 패턴 10개를 데이터로 두고 채우는 함수와 길이·키워드·형식을 검사하는 채점기를 볼 수 있습니다. &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&quot;&gt;11-02&lt;/a&gt;의 예제는 OpenAI API 키가 필요합니다. 실제 모델로 돌린다면 그림 4의 마침표 문제부터 고쳐야 숫자가 제대로 나옵니다. &lt;a href=&quot;https://github.com/promptfoo/promptfoo&quot;&gt;promptfoo&lt;/a&gt;(MIT)는 프롬프트와 모델을 나란히 평가하는 도구이고, &lt;a href=&quot;https://github.com/stanfordnlp/dspy&quot;&gt;DSPy&lt;/a&gt;(MIT)는 &lt;code&gt;ChainOfThought&lt;/code&gt;, &lt;code&gt;majority&lt;/code&gt; 같은 모듈로 같은 기법을 코드로 짜 맞춥니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;다음 화 예고.&lt;/strong&gt; 프롬프트 하나로 안 되는 일은 여러 단계로 나눕니다. 4화에서는 에이전트를 만들 때 자주 쓰는 워크플로 패턴을 다룹니다.&lt;/p&gt;
&lt;hr style=&quot;border:0;border-top:1px solid #dcdfe3;margin:36px 0;&quot; /&gt;
&lt;p&gt;원본: rohitg00/ai-engineering-from-scratch (MIT, © 2026 Rohit Ghumare). 이 글은 원문을 바탕으로 직접 정리하고 재구성했습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top:32px;&quot;&gt;출처&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 11-01 Prompt Engineering: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/01-prompt-engineering&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/01-prompt-engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 11-02 Few-Shot, Chain-of-Thought, Tree-of-Thought: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/11-llm-engineering/02-few-shot-cot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Wei et al., Chain-of-Thought Prompting (arXiv 2201.11903): &lt;a href=&quot;https://arxiv.org/abs/2201.11903&quot;&gt;https://arxiv.org/abs/2201.11903&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kojima et al., Large Language Models are Zero-Shot Reasoners (arXiv 2205.11916): &lt;a href=&quot;https://arxiv.org/abs/2205.11916&quot;&gt;https://arxiv.org/abs/2205.11916&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Wang et al., Self-Consistency (arXiv 2203.11171): &lt;a href=&quot;https://arxiv.org/abs/2203.11171&quot;&gt;https://arxiv.org/abs/2203.11171&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford CME295 Lecture 3, Prompting 1:07:07 (영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h7m7s&quot;&gt;https://www.youtube.com/watch?v=Q5baLehv5So&amp;amp;t=1h7m7s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford CS230 Lecture 8, Agents, Prompts, and RAG, 17:51 (영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=k1njvbBmfsw&amp;amp;t=17m51s&quot;&gt;https://www.youtube.com/watch?v=k1njvbBmfsw&amp;amp;t=17m51s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;promptfoo/promptfoo (MIT): &lt;a href=&quot;https://github.com/promptfoo/promptfoo&quot;&gt;https://github.com/promptfoo/promptfoo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;stanfordnlp/dspy (MIT): &lt;a href=&quot;https://github.com/stanfordnlp/dspy&quot;&gt;https://github.com/stanfordnlp/dspy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude 공식 문서, Prompting best practices (2026-10-12 확인): &lt;a href=&quot;https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices&quot;&gt;https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/Engineering</category>
      <category>ai-engineering-from-scratch</category>
      <category>Chain-of-Thought</category>
      <category>ChatGPT</category>
      <category>Claude</category>
      <category>LLM</category>
      <category>생성형 ai</category>
      <category>퓨샷 프롬프트</category>
      <category>프롬프트 기법</category>
      <category>프롬프트 엔지니어링</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/9</guid>
      <comments>https://agentnote.tistory.com/9#entry9comment</comments>
      <pubDate>Mon, 12 Oct 2026 10:03:43 +0900</pubDate>
    </item>
    <item>
      <title>AI는 글자만 쓰는데, 어떻게 도구를 쓸까? 함수 호출(Function Calling) 쉽게 정리 (도구 호출 4단계)</title>
      <link>https://agentnote.tistory.com/8</link>
      <description>&lt;!-- 제목: AI는 글자만 쓰는데, 어떻게 도구를 쓸까? 함수 호출(Function Calling) 쉽게 정리 (도구 호출 4단계) | 태그: 함수 호출, Function Calling, AI 에이전트, 도구 호출, LLM, Claude, 생성형 AI, AI 개발, ai-engineering-from-scratch --&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;&lt;strong&gt;요약.&lt;/strong&gt; 언어 모델은 글자만 내놓습니다. 계산기나 날씨 API를 직접 누르지 못합니다. 대신 &quot;이 도구를 이 값으로 불러 달라&quot;는 정해진 형식의 요청을 쓰고, 실제 실행은 모델 바깥의 프로그램이 합니다. 결과는 다시 모델에게 돌아갑니다. 이 약속을 &lt;strong&gt;함수 호출(도구 호출)&lt;/strong&gt; 이라고 부르고, 설명 → 결정 → 실행 → 관찰 네 단계로 돕니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;1화에서 이어지는 질문: 에이전트는 어떻게 도구를 쓸까&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/7&quot;&gt;1화 &quot;AI 에이전트는 왜 몇 번씩 다시 시도할까?&quot;&lt;/a&gt;에서는 에이전트가 생각하고, 행동하고, 결과를 관찰하는 고리를 봤습니다. 그런데 &quot;행동&quot;은 &quot;도구를 부른다&quot; 한 줄로 넘어갔습니다.&lt;/p&gt;
&lt;p&gt;그런데 언어 모델은 글자를 이어 쓰는 프로그램입니다. &lt;a href=&quot;https://agentnote.tistory.com/1&quot;&gt;0화&lt;/a&gt;에서 본 Claude Code는 어떻게 파일을 읽고 명령을 실행할까요? 이번 화는 그 연결 부분을 엽니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;언어 모델은 글자만 낸다&lt;/h2&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&quot;&gt;13-01 The Tool Interface&lt;/a&gt;는 문제를 이렇게 정리합니다. 모델이 내놓는 것은 다음에 올 글자(토큰)의 확률뿐입니다. &quot;지금 서울 날씨 어때?&quot;라고 물으면 그럴듯한 문장은 쓰지만, 날씨 서비스에 접속하지는 못합니다.&lt;/p&gt;
&lt;p&gt;그래서 역할을 나눕니다. 모델은 &quot;무엇을 부를지&quot;를 글자로 쓰고, 모델을 감싼 프로그램이 그 요청을 받아 진짜로 실행합니다. 레슨은 이 프로그램을 &lt;strong&gt;호스트&lt;/strong&gt;라고 부릅니다. 에이전트 앱, Claude Code, 직접 짠 스크립트가 모두 호스트입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;함수 호출이란? 메뉴판과 주문서&lt;/h2&gt;
&lt;p&gt;식당에 비유하면 쉽습니다. 손님은 주방에 들어가지 못하고, 메뉴판을 보고 주문서를 씁니다. 직원이 주문서를 확인해 주방에 넘기고 요리를 가져다줍니다.&lt;/p&gt;
&lt;p&gt;함수 호출도 같습니다. 호스트가 모델에게 &lt;strong&gt;도구 목록&lt;/strong&gt;을 줍니다. 도구마다 이름, 언제 쓰는지에 대한 설명, 받는 값의 형식(스키마)이 적혀 있습니다. 모델은 필요하다고 판단하면 &lt;strong&gt;도구 호출&lt;/strong&gt;을 씁니다. 도구 이름과 값을 정해진 칸에 채운 요청입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxWoNb/dJMcabFRTsn/ykkDoku32kgiGtkJqb9ao1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxWoNb/dJMcabFRTsn/ykkDoku32kgiGtkJqb9ao1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxWoNb/dJMcabFRTsn/ykkDoku32kgiGtkJqb9ao1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxWoNb%2FdJMcabFRTsn%2FykkDoku32kgiGtkJqb9ao1%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 1. 모델은 요청을 쓰고, 실행은 호스트가 합니다. 원본 레슨 코드를 실행한 출력입니다(날씨 값은 코드 안의 가짜 값).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview&quot;&gt;Claude API 공식 문서 &quot;Tool use with Claude&quot;&lt;/a&gt;도 같은 순서로 설명합니다. Claude가 &lt;code&gt;tool_use&lt;/code&gt; 블록으로 도구 이름과 값을 돌려주면, 앱이 실행하고 &lt;code&gt;tool_result&lt;/code&gt;로 결과를 보냅니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;도구 호출 4단계: 설명 → 결정 → 실행 → 관찰&lt;/h2&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&quot;&gt;13-01 The Tool Interface&lt;/a&gt;는 이 과정을 네 단계로 나누고, 단계마다 누가 맡는지 짚습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;설명&lt;/strong&gt;: 호스트가 도구 목록을 알려 줍니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;결정&lt;/strong&gt;: 모델이 바로 답할지, 어떤 도구를 어떤 값으로 부를지 고릅니다. 결과와 짝짓도록 호출마다 번호(id)가 붙습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;실행&lt;/strong&gt;: 호스트가 값을 검사한 뒤 실제로 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;관찰&lt;/strong&gt;: 호스트가 결과를 대화에 붙여 모델을 다시 부릅니다. 모델이 더 부를 도구가 없거나 횟수 상한에 닿을 때까지 반복합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQu2Lj/dJMb99VEe1P/ng7Lax0iKk0U9DD3lehlkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQu2Lj/dJMb99VEe1P/ng7Lax0iKk0U9DD3lehlkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQu2Lj/dJMb99VEe1P/ng7Lax0iKk0U9DD3lehlkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQu2Lj%2FdJMb99VEe1P%2Fng7Lax0iKk0U9DD3lehlkk%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 2. 고르는 건 모델이고, 실행하는 건 프로그램입니다.&lt;/p&gt;

&lt;p&gt;4단계 관찰이 바로 1화의 &quot;관찰&quot;입니다. 도구 결과가 대화에 붙어 돌아오기 때문에, 모델은 그걸 읽고 다음 행동을 고칠 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;실행 전에 거른다: 값 검사와 확인 단계&lt;/h2&gt;
&lt;p&gt;모델이 쓴 호출이 늘 맞지는 않습니다. 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&quot;&gt;13-01 The Tool Interface&lt;/a&gt;는 모델이 없는 칸을 지어내거나 타입을 틀리는 일이 흔하다고 보고, 호스트가 실행 전에 스키마로 검사해야 한다고 말합니다.&lt;/p&gt;
&lt;p&gt;레슨의 연습 문제 2번과 3번을 실행한 결과가 그림 3입니다. 두 숫자를 더하는 &lt;code&gt;add&lt;/code&gt; 도구에 값을 세 가지로 넣고, 메일을 보내는 가짜 도구도 하나 붙였습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dOYwoG/dJMcaf9hJ69/DevlJg8BCuypmqzCDcB0XK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dOYwoG/dJMcaf9hJ69/DevlJg8BCuypmqzCDcB0XK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dOYwoG/dJMcaf9hJ69/DevlJg8BCuypmqzCDcB0XK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdOYwoG%2FdJMcaf9hJ69%2FDevlJg8BCuypmqzCDcB0XK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 3. 칸이 빠지거나 타입이 틀린 호출은 실행 전에 걸립니다.&lt;/p&gt;

&lt;p&gt;여기서 눈여겨볼 점은 두 가지입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;검사는 모델이 아니라 호스트가 합니다.&lt;/li&gt;
&lt;li&gt;레슨은 도구를 읽기만 하는 것과 &lt;strong&gt;결과가 남는 것&lt;/strong&gt;(메일 보내기, 파일 지우기, 결제)으로 나눕니다. 결과가 남는 도구는 사람 확인을 거치게 하라고 권합니다. 다만 레슨 코드는 &quot;확인하겠다&quot;는 줄만 찍고 그대로 실행합니다. 실제로 멈추고 묻는 부분은 연습 문제로 비어 있습니다.&lt;/li&gt;
&lt;li&gt;검사에 걸린 호출을 어떻게 할지도 레슨 본문과 코드가 다릅니다. 레슨 본문은 실제 서비스가 세 가지 중 하나를 한다고 설명합니다. 에러를 모델에게 알려 주거나, 깨진 JSON을 고치거나, 검사 에러를 넣어 모델에게 다시 묻는 것입니다. 레슨 코드는 에러를 출력하고 거기서 멈춥니다. 에러를 모델에게 돌려주는 쪽은 &lt;a href=&quot;https://agentnote.tistory.com/7&quot;&gt;1화&lt;/a&gt;에서 본 &quot;에러도 관찰&quot; 구조와 같습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://agentnote.tistory.com/1&quot;&gt;0화&lt;/a&gt;에서 Claude Code가 파일 수정 전에 확인을 거친다고 했던 것도 같은 생각입니다. 고르는 것은 모델이 해도, 실행 직전의 문은 프로그램이 지킵니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;회사마다 모양은 달라도 같은 구조&lt;/h2&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/02-function-calling-deep-dive&quot;&gt;13-02 Function Calling Deep Dive&lt;/a&gt;는 OpenAI, Anthropic(Claude), Google Gemini의 함수 호출 형식을 나란히 비교합니다. 칸 이름과 감싸는 위치가 다르고, OpenAI는 값을 JSON 문자열로, 나머지 둘은 객체로 돌려줍니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rH7z6/dJMcadqeaFs/GEA1HvgqWzy4mJ4WffdDAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rH7z6/dJMcadqeaFs/GEA1HvgqWzy4mJ4WffdDAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rH7z6/dJMcadqeaFs/GEA1HvgqWzy4mJ4WffdDAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrH7z6%2FdJMcadqeaFs%2FGEA1HvgqWzy4mJ4WffdDAK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align:center;color:#5d6577;font-size:14px;margin-top:6px;&quot;&gt;그림 4. 이름표만 다르고 구조는 같습니다.&lt;/p&gt;

&lt;p&gt;레슨 코드로 세 형식의 응답을 풀면 모두 같은 도구 이름과 값이 나옵니다. 한 곳에서 배운 구조가 다른 곳에서도 그대로 통합니다.&lt;/p&gt;
&lt;div style=&quot;background:#f3f5f9;border-left:4px solid #1f2a44;border-radius:6px;padding:18px 22px;margin:8px 0 28px;line-height:1.8;&quot;&gt;&lt;p&gt;&lt;strong&gt;레슨과 지금 공식 문서가 다른 점.&lt;/strong&gt; 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/02-function-calling-deep-dive&quot;&gt;13-02 Function Calling Deep Dive&lt;/a&gt;는 Anthropic(Claude)에 strict 모드 플래그가 없고, 모델이 스키마를 &quot;대체로 지킨다&quot;고 적습니다. 같은 레슨의 비교표에는 &quot;항상 강제된다&quot;고 적혀 있어 레슨 안에서도 설명이 엇갈립니다. 2026년 10월 기준 &lt;a href=&quot;https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use&quot;&gt;Claude API 공식 문서 &quot;Strict tool use&quot;&lt;/a&gt;는 도구 정의에 &lt;code&gt;strict: true&lt;/code&gt;를 넣으면 Claude의 도구 호출이 스키마와 정확히 맞도록 보장한다고 설명합니다. 이 글은 공식 문서를 따랐습니다. API 기능은 빨리 바뀌니, 레슨이나 블로그 글보다 공식 문서를 마지막 기준으로 삼는 편이 안전합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;따라 해 보기: API 키 없이 도구 호출 루프 돌려 보기&lt;/h2&gt;
&lt;p&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&quot;&gt;13-01 The Tool Interface&lt;/a&gt;와 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/02-function-calling-deep-dive&quot;&gt;13-02 Function Calling Deep Dive&lt;/a&gt;의 예제 코드는 API 키 없이 돌아갑니다. Python 3만 있으면 됩니다.&lt;/p&gt;
&lt;pre style=&quot;background:#1e2330;color:#e8eaf0;padding:16px 18px;border-radius:8px;overflow-x:auto;line-height:1.6;&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;B=https://raw.githubusercontent.com/rohitg00/ai-engineering-from-scratch/main/phases/13-tools-and-protocols
curl -sfL &amp;quot;$B/01-the-tool-interface/code/main.py&amp;quot; -o tool_interface.py &amp;amp;&amp;amp; python3 tool_interface.py
curl -sfL &amp;quot;$B/02-function-calling-deep-dive/code/main.py&amp;quot; -o function_calling.py &amp;amp;&amp;amp; python3 function_calling.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;첫 번째 파일은 &lt;code&gt;DECIDE&lt;/code&gt;, &lt;code&gt;EXECUTE&lt;/code&gt;, &lt;code&gt;OBSERVE&lt;/code&gt; 순서로 네 단계를 찍습니다. 그다음 파일 맨 아래 질문 목록의 &lt;code&gt;&quot;please add 7 and 35&quot;&lt;/code&gt;를 &lt;code&gt;&quot;please add 7&quot;&lt;/code&gt;로 바꿔 다시 돌려 보세요. 숫자가 하나뿐이라 덧셈 도구가 불리지 않고, 맞는 도구가 없다는 답이 나옵니다. 두 번째 파일은 같은 도구가 세 회사 형식으로 어떻게 바뀌는지 보여 줍니다.&lt;/p&gt;
&lt;p&gt;단, 예제의 &quot;모델&quot;은 키워드로 도구를 고르는 가짜 함수입니다. 실제 언어 모델로 바꾸면 결정 단계만 달라집니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 함수 호출을 하면 AI가 직접 프로그램을 실행하나요?&lt;/strong&gt;
아닙니다. 모델은 &quot;이 도구를 이 값으로 불러 달라&quot;는 요청만 씁니다. 실행은 앱이 합니다. &lt;a href=&quot;https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview&quot;&gt;Claude API 공식 문서&lt;/a&gt;는 앱이 실행하는 도구(client tools)와 Anthropic 서버에서 실행하는 도구(웹 검색 같은 server tools)를 나눠 설명하는데, 어느 쪽이든 모델 자신이 실행하는 구조는 아닙니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 그냥 &quot;JSON으로 답해&quot;라고 시키면 안 되나요?&lt;/strong&gt;
형식이 깨질 수 있습니다. 원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&quot;&gt;13-01&lt;/a&gt;은 괄호 빠짐, 지어낸 칸, 틀린 타입을 예로 듭니다. 함수 호출은 호출을 답과 다른 칸에 담습니다. &lt;a href=&quot;https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview&quot;&gt;Claude API 공식 문서&lt;/a&gt;는 도구 정의에 &lt;code&gt;strict: true&lt;/code&gt;를 넣으면 호출이 스키마와 정확히 맞도록 보장한다고 설명합니다.&lt;/p&gt;
&lt;p style=&quot;margin-top:20px;&quot;&gt;&lt;strong style=&quot;color:#1f2a44;&quot;&gt;Q. 도구 설명은 어떻게 써야 하나요?&lt;/strong&gt;
원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&quot;&gt;13-01&lt;/a&gt;의 예제는 &quot;지금 날씨를 물을 때 쓴다. 예보나 지난 날씨에는 쓰지 않는다&quot;처럼 쓸 때와 쓰지 않을 때를 함께 적습니다. 모델은 이 설명을 보고 도구를 고릅니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top:44px;padding-bottom:8px;border-bottom:2px solid #1f2a44;&quot;&gt;더 깊이: Toolformer, Gorilla, 강의, 코드&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Toolformer 논문.&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/2302.04761&quot;&gt;Schick 외, &quot;Toolformer: Language Models Can Teach Themselves to Use Tools&quot;(arXiv 2302.04761, 2023년 2월)&lt;/a&gt;. 초록의 주장은 세 가지입니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;언어 모델은 예시 몇 개만으로 새 과제를 풀면서도, 산수나 사실 찾기 같은 기본기에는 약합니다. 훨씬 작은 모델이 더 잘하는 영역입니다.&lt;/li&gt;
&lt;li&gt;Toolformer는 어떤 API를 언제, 어떤 값으로 부르고, 결과를 다음 글자 예측에 어떻게 넣을지 스스로 배우게 한 모델입니다. API마다 시연 몇 개만 있으면 되는 자기 지도 방식입니다. 계산기, 질의응답 시스템, 검색 엔진 두 개, 번역기, 달력을 도구로 썼습니다.&lt;/li&gt;
&lt;li&gt;여러 과제에서 제로샷 성능이 크게 오르고, 언어 모델 본래 능력은 유지됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Gorilla 논문.&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/2305.15334&quot;&gt;Patil 외, &quot;Gorilla: Large Language Model Connected with Massive APIs&quot;(arXiv 2305.15334, 2023년 5월)&lt;/a&gt;. 초록은 당시 최고 모델도 API를 부를 때 정확한 값을 만들지 못하고, 잘못된 사용법을 지어내는 경향이 있다고 지적합니다. 문서 검색기를 붙여 미세 조정한 Gorilla가 API 호출 작성에서 GPT-4를 넘었고, 문서가 바뀌어도 따라간다고 보고합니다. 이 팀의 &lt;a href=&quot;https://github.com/ShishirPatil/gorilla&quot;&gt;gorilla 저장소&lt;/a&gt;에는 함수 호출 평가 리더보드(BFCL)도 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;openai-agents-python 코드.&lt;/strong&gt; OpenAI의 오픈소스 에이전트 라이브러리 &lt;a href=&quot;https://github.com/openai/openai-agents-python&quot;&gt;openai-agents-python&lt;/a&gt;은 파이썬 함수에 &lt;code&gt;@function_tool&lt;/code&gt;을 붙이면 함수 이름, 설명 주석(docstring), 매개변수로 도구 설명과 스키마를 자동으로 만듭니다. 1단계 &quot;설명&quot;이 실제로 어떤 JSON이 되는지 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stanford CME295 7강 &quot;Tool calling&quot;(&lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=59m28s&quot;&gt;59:28&lt;/a&gt;).&lt;/strong&gt; 강의는 이 글의 세 단계와 같은 흐름을 이렇게 나눕니다(&lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h8m20s&quot;&gt;1:08:20&lt;/a&gt;부터).&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;함수의 겉모양(이름, 입력, 출력, 설명)만 모델 앞에 넣습니다. 모델이 할 일은 함수를 짜는 게 아니라 &quot;어떤 값을 넣을지&quot; 채우는 것뿐입니다. 함수 안쪽 구현은 코드에만 있고 모델은 보지 못합니다.&lt;/li&gt;
&lt;li&gt;호출을 실행합니다. 강의 표현으로는 &quot;언어 모델과 아무 상관 없는&quot; 단계입니다. 결과는 정해진 구조로 돌아옵니다.&lt;/li&gt;
&lt;li&gt;결과를 모델에게 다시 넣어 사람 말로 답하게 합니다. JSON 그대로가 아니라 자연어 답이 목표입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;모델이 이걸 어떻게 배우는지도 다룹니다(&lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h11m14s&quot;&gt;1:11:14&lt;/a&gt;). 미세 조정(SFT)을 한다면 학습 쌍이 두 종류 필요합니다. 하나는 &quot;질문 + 함수 설명 → 호출과 값&quot;, 다른 하나는 &quot;지금까지의 대화 전체(질문, 호출, 결과) → 최종 답&quot;입니다. 미세 조정 없이 프롬프트의 설명만으로도 할 수 있는데, 강의는 그 설명을 손으로 끝까지 쓰지 말라고 권합니다(&lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h17m39s&quot;&gt;1:17:39&lt;/a&gt;). 질문과 기대하는 호출을 짝지은 평가 묶음을 만들어 지금 설명을 채점하고, 점수를 추론 모델에게 주며 설명을 고치게 하라는 것입니다. 이 글 FAQ의 &quot;도구 설명은 어떻게 써야 하나요?&quot;에 대한 강의 쪽 답입니다.&lt;/p&gt;
&lt;p&gt;도구는 세 갈래로 나눕니다(&lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h20m36s&quot;&gt;1:20:36&lt;/a&gt;): 정보 찾기(학습 이후 뉴스, 날씨, 주가), 계산(질문을 코드로 바꿔 실행), 사용자 대신 행동하기(메일 쓰고 보내기). 그리고 한계 세 가지를 짚습니다(&lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h24m13s&quot;&gt;1:24:13&lt;/a&gt;). 혹시 몰라 도구를 많이 넣으면 일부가 문맥 속에 묻히고, 문맥 창에는 끝이 있고, 회사마다 도구를 정의하는 방식이 달라 표준이 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;같은 강의 &quot;Tool selection&quot;(&lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h26m22s&quot;&gt;1:26:22&lt;/a&gt;).&lt;/strong&gt; 도구가 많을 때의 해법으로 두 단계 &quot;도구 선택기&quot;를 소개합니다. 먼저 도구 이름과 한두 단어 설명만 담은 긴 목록을 주고 쓸 만한 것을 고르게 한 뒤, 고른 도구의 전체 설명만 문맥에 넣습니다. 라우터(router)라고도 부르며, 검색(RAG)으로 고를 수도 있지만 꼭 그래야 하는 건 아니라고 답합니다. 바로 이어지는 &quot;표준이 없다&quot;는 문제의 답이 MCP이고, 5화에서 다룹니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stanford Webinar &quot;Agentic AI&quot;(Insop Song) &lt;a href=&quot;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=26m47s&quot;&gt;26:47&lt;/a&gt;.&lt;/strong&gt; 언어 모델은 글을 받아 글을 내놓을 뿐이라 바깥 정보를 직접 가져오지 못한다는 데서 출발합니다. &quot;샌프란시스코 날씨&quot;를 예로, 날씨 질문이면 정해진 형식으로 출력하라고 프롬프트에 미리 알려 두면 그 출력을 소프트웨어가 읽어 날씨 API를 부르고, 결과를 모델에게 돌려줘 사람이 읽기 좋은 답을 만든다고 설명합니다. 모델이 코드를 만들고 바깥 샌드박스에서 실행하는 방식도 같은 틀로 소개합니다. (영상 설명란의 챕터는 16:30이지만, 자막 기준으로 도구 이야기는 26:47에 시작합니다.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;다음 화 예고.&lt;/strong&gt; 모델이 무엇을 부를지 &quot;결정&quot;하는 단계는 결국 모델에게 어떻게 말하느냐에 달려 있습니다. 3화에서는 모델이 더 잘 생각하게 만드는 프롬프트 기법을 다룹니다.&lt;/p&gt;
&lt;hr style=&quot;border:0;border-top:1px solid #dcdfe3;margin:36px 0;&quot; /&gt;
&lt;p&gt;원본: rohitg00/ai-engineering-from-scratch (MIT, © 2026 Rohit Ghumare). 이 글은 원문을 바탕으로 직접 정리하고 재구성했습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top:32px;&quot;&gt;출처&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 13-01 The Tool Interface: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/01-the-tool-interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 13-02 Function Calling Deep Dive: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/02-function-calling-deep-dive&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/13-tools-and-protocols/02-function-calling-deep-dive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Schick et al., Toolformer (arXiv 2302.04761): &lt;a href=&quot;https://arxiv.org/abs/2302.04761&quot;&gt;https://arxiv.org/abs/2302.04761&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Patil et al., Gorilla (arXiv 2305.15334): &lt;a href=&quot;https://arxiv.org/abs/2305.15334&quot;&gt;https://arxiv.org/abs/2305.15334&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude API 문서, Tool use with Claude: &lt;a href=&quot;https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview&quot;&gt;https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;openai/openai-agents-python (MIT): &lt;a href=&quot;https://github.com/openai/openai-agents-python&quot;&gt;https://github.com/openai/openai-agents-python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ShishirPatil/gorilla (Apache-2.0): &lt;a href=&quot;https://github.com/ShishirPatil/gorilla&quot;&gt;https://github.com/ShishirPatil/gorilla&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford CME295 Lecture 7 (Tool calling 59:28, Tool selection 1:26:22, 영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=59m28s&quot;&gt;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=59m28s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford Webinar, Agentic AI (Insop Song), 26:47 도구 사용 (영어 자막 확인): &lt;a href=&quot;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=26m47s&quot;&gt;https://www.youtube.com/watch?v=kJLiOGle3Lw&amp;amp;t=26m47s&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/8</guid>
      <comments>https://agentnote.tistory.com/8#entry8comment</comments>
      <pubDate>Thu, 8 Oct 2026 08:56:41 +0900</pubDate>
    </item>
    <item>
      <title>AI 에이전트는 왜 몇 번씩 다시 시도할까? ReAct 루프 쉽게 정리 (생각&amp;middot;행동&amp;middot;관찰)</title>
      <link>https://agentnote.tistory.com/7</link>
      <description>&lt;!-- 제목: AI 에이전트는 왜 몇 번씩 다시 시도할까? ReAct 루프 쉽게 정리 (생각·행동·관찰) | 태그: ReAct, AI 에이전트, 에이전트 루프, LLM, Claude Code, smolagents, 생성형 AI, AI 개발, ai-engineering-from-scratch --&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약.&lt;/b&gt; 에이전트가 몇 번씩 다시 시도하는 건 잘못 돌아가서가 아니라, 처음부터 그렇게 하도록 만들어졌기 때문입니다. 도구를 쓴 결과가 에러 메시지까지 그대로 언어 모델에 돌아오고, 모델은 그것을 읽고 다음 행동을 고칩니다. 생각과 행동을 이렇게 번갈아 하는 방식을 &lt;b&gt;ReAct&lt;/b&gt;라고 부릅니다. 끝없이 반복하지 않도록 멈춤 조건과 횟수 제한을 함께 둡니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;0화에서 이어지는 질문: 에이전트는 왜 같은 일을 또 할까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://agentnote.tistory.com/1&quot;&gt;0화 &quot;Claude Code는 어떻게 파일을 고칠까?&quot;&lt;/a&gt;에서는 AI 에이전트가 &quot;생각 &amp;rarr; 행동 &amp;rarr; 관찰&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;처음 보면 같은 자리를 맴도는 것처럼 보입니다. 하지만 이렇게 다시 시도하는 데는 이유가 있고, 이 방식을 부르는 이름도 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;ReAct란? 생각과 행동을 번갈아 하는 에이전트 방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유하면 간을 보며 요리하는 것과 같습니다. 레시피만 머릿속으로 따라가면 처음 넣은 소금이 틀려도 끝까지 모릅니다. 간을 보는 사람은 넣고, 맛보고, 다음에 무엇을 할지 다시 정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ReAct는 Reason(생각)과 Act(행동)를 합친 이름입니다. 2022년 &lt;a href=&quot;https://arxiv.org/abs/2210.03629&quot;&gt;ReAct 논문(Yao 외, arXiv 2210.03629)&lt;/a&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;생각(Thought)&lt;/b&gt;: 지금 무엇을 알고, 다음에 무엇을 할지 글로 적습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;행동(Action)&lt;/b&gt;: 검색, 계산, 파일 읽기 같은 도구를 부릅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;관찰(Observation)&lt;/b&gt;: 도구가 돌려준 결과입니다. 다음 생각의 재료가 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각만 하면 바깥을 확인하지 않아 틀린 사실이 끝까지 이어집니다. 행동만 하면 결과는 보지만 계획을 고치는 단계가 없습니다. ReAct는 둘을 번갈아 하게 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;740&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1T48h/dJMcablJIeD/uzww0hK0kYzXK7QckUvwsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1T48h/dJMcablJIeD/uzww0hK0kYzXK7QckUvwsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1T48h/dJMcablJIeD/uzww0hK0kYzXK7QckUvwsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1T48h%2FdJMcablJIeD%2Fuzww0hK0kYzXK7QckUvwsK%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;1200&quot; height=&quot;740&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;740&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 1. 생각만 하면 처음 실수가 끝까지 가고, ReAct는 관찰을 읽고 계획을 고칩니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;에이전트가 다시 시도하는 이유: 에러도 관찰이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 시도하는 이유는 관찰에 있습니다. 도구가 실패하면 프로그램이 멈추는 대신 에러 메시지가 관찰로 돌아옵니다. 모델은 그 메시지를 읽고 다음 행동을 고칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/01-the-agent-loop&quot;&gt;14-01 The Agent Loop&lt;/a&gt;도 같은 지점을 짚습니다. 레슨은 ReAct 논문을 따라, 생각을 글로 적는 단계가 세 가지 일을 한다고 정리합니다. 계획을 세우고, 단계마다 그 계획을 따라가고, 예상하지 못한 관찰이 돌아오면 대처하는 것입니다. 에러는 바로 이 &quot;예상하지 못한 관찰&quot;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레슨의 연습 문제 3번도 이 장면을 직접 만들어 보라고 합니다. 예제 모델이 가끔 잘못된 인자로 도구를 부르게 하고, 그때 에러를 관찰로 돌려줘 루프가 스스로 회복하게 만드는 과제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레슨에는 표준 라이브러리만 쓰는 177줄짜리 에이전트 루프 예제도 들어 있습니다. 여기에 &quot;직전 관찰을 읽고 다음 행동을 고르는&quot; 규칙을 하나 더해 실행한 기록이 그림 2입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;곱셈 기호를 &lt;code&gt;x&lt;/code&gt;로 넣자 에러가 돌아왔고, 다음 단계는 그 에러를 읽고 &lt;code&gt;*&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;1200&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blK90G/dJMcabFQd6i/RnccV6OLBPxBhkTT92pvQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blK90G/dJMcabFQd6i/RnccV6OLBPxBhkTT92pvQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blK90G/dJMcabFQd6i/RnccV6OLBPxBhkTT92pvQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblK90G%2FdJMcabFQd6i%2FRnccV6OLBPxBhkTT92pvQ0%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;1200&quot; height=&quot;836&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 2. 첫 행동은 실패했지만, 에러가 관찰로 돌아와 다음 행동을 바꿉니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://agentnote.tistory.com/1&quot;&gt;0화&lt;/a&gt;에서 본 Claude Code도 같은 구조입니다. &lt;a href=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot;&gt;공식 문서 &quot;How Claude Code works&quot;&lt;/a&gt;는 도구를 쓸 때마다 나온 정보가 루프로 돌아가 다음 결정을 정한다고 설명합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;다시 시도에도 끝이 있다: 멈춤 조건과 횟수 제한&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 에이전트는 성공할 때까지 계속 다시 할까요? 그렇지 않습니다. 같은 예제에서 관찰을 읽지 않고 같은 행동만 내는 규칙으로 바꾸면, 같은 에러를 세 번 받고도 같은 호출을 되풀이합니다. 최대 횟수를 3번으로 정해 두었기 때문에 &lt;code&gt;budget exhausted&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;1200&quot; data-origin-height=&quot;773&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HcMap/dJMcabFQd6x/YoWKDhTo5R6YVJuFpnhm5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HcMap/dJMcabFQd6x/YoWKDhTo5R6YVJuFpnhm5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HcMap/dJMcabFQd6x/YoWKDhTo5R6YVJuFpnhm5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHcMap%2FdJMcabFQd6x%2FYoWKDhTo5R6YVJuFpnhm5k%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;1200&quot; height=&quot;773&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;773&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 3. 관찰을 반영하지 않으면 다시 시도가 아니라 같은 실수의 반복이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 에이전트 루프에는 멈춤 조건이 있습니다. 모델이 &quot;끝났다&quot;고 답할 때, 더 부를 도구가 없을 때, 최대 횟수나 최대 토큰에 닿았을 때, 안전 규칙에 걸렸을 때 멈춥니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;ReAct 에이전트 루프의 다섯 가지 구성 요소&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/01-the-agent-loop&quot;&gt;14-01 The Agent Loop&lt;/a&gt;은 에이전트 루프에 꼭 필요한 것을 다섯 가지로 정리합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xiLzN/dJMcafVXDb3/vbhvWF8Z03miPD3NNfrOJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xiLzN/dJMcafVXDb3/vbhvWF8Z03miPD3NNfrOJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xiLzN/dJMcafVXDb3/vbhvWF8Z03miPD3NNfrOJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxiLzN%2FdJMcafVXDb3%2FvbhvWF8Z03miPD3NNfrOJ1%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;1200&quot; height=&quot;624&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 4. 다섯 번째인 관찰 변환 덕분에 에러가 프로그램을 멈추지 않고 글이 되어 돌아옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 시도와 직접 이어지는 것은 다섯 번째입니다. 에러를 예외로 터뜨리지 않고 모델이 읽을 글로 바꿔 돌려줘야, 다음 생각이 방향을 고칠 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;따라 해 보기: API 키 없이 에이전트 루프 돌려 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 레슨 &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/01-the-agent-loop&quot;&gt;14-01 The Agent Loop&lt;/a&gt;의 예제 코드(&lt;code&gt;code/main.py&lt;/code&gt;)는 API 키 없이 돌아갑니다. Python 3만 있으면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot; style=&quot;background: #1e2330; color: #e8eaf0; padding: 16px 18px; border-radius: 8px; overflow-x: auto; line-height: 1.6;&quot;&gt;&lt;code&gt;curl -sfLO https://raw.githubusercontent.com/rohitg00/ai-engineering-from-scratch/main/phases/14-agent-engineering/01-the-agent-loop/code/main.py
python3 main.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;thought&lt;/code&gt;와 &lt;code&gt;action&lt;/code&gt;, 화살표 뒤 결과가 번갈아 찍힙니다. 그다음 &lt;code&gt;main.py&lt;/code&gt;에서 &lt;code&gt;&quot;120 * 0.15&quot;&lt;/code&gt;를 &lt;code&gt;&quot;120 x 0.15&quot;&lt;/code&gt;로 바꿔 다시 돌려 보세요. 에러가 나도 프로그램이 멈추지 않고, 에러 문장이 관찰 자리에 들어가는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 레슨의 예제 모델은 미리 적어 둔 대본을 순서대로 읽기만 해서 에러를 보고 고치지는 않습니다. 고치는 판단은 실제 언어 모델의 몫입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. ReAct는 모델 이름인가요?&lt;/b&gt; 아닙니다. 언어 모델이 생각과 행동을 번갈아 내게 하는 방식의 이름입니다. 2022년 &lt;a href=&quot;https://arxiv.org/abs/2210.03629&quot;&gt;ReAct 논문&lt;/a&gt;의 ALFWorld&amp;middot;WebShop 실험에서는 프롬프트에 예시를 한두 개 넣는 것만으로 이 방식을 쓰게 했습니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 에이전트가 같은 에러를 계속 반복하면 어떻게 하나요?&lt;/b&gt; 그래서 횟수 제한을 둡니다. 예를 들어 Hugging Face의 오픈소스 에이전트 라이브러리 &lt;a href=&quot;https://github.com/huggingface/smolagents&quot;&gt;smolagents&lt;/a&gt;는 기본 20단계에서 멈춥니다. Claude Code는 작업 중에 사용자가 끼어들어 방향을 바꿀 수 있으니, 같은 실패가 반복되면 힌트를 주는 것도 방법입니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. Claude Code도 ReAct인가요?&lt;/b&gt; &lt;a href=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot;&gt;Claude Code 공식 문서 &quot;How Claude Code works&quot;&lt;/a&gt;는 Claude Code를 맥락 모으기, 행동하기, 결과 확인하기를 반복하는 루프로 설명합니다. 도구 결과가 다음 결정으로 돌아간다는 점에서 같은 모양이지만, 논문의 형식을 그대로 따르는지는 문서에 나와 있지 않습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;더 깊이: ReAct 논문, 강의, smolagents 코드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;논문.&lt;/b&gt; Yao 외, &quot;ReAct: Synergizing Reasoning and Acting in Language Models&quot;(&lt;a href=&quot;https://arxiv.org/abs/2210.03629&quot;&gt;arXiv 2210.03629&lt;/a&gt;, 2022년 10월 제출, ICLR 발표). 초록의 주장은 세 가지입니다.&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;질의응답(HotpotQA)과 사실 검증(Fever)에서 간단한 위키백과 API를 쓰며 답해, 연쇄적 사고(Chain-of-Thought)만 쓸 때 흔한 환각과 오류 전파를 극복합니다.&lt;/li&gt;
&lt;li&gt;상호작용 과제인 ALFWorld와 WebShop에서 모방 학습&amp;middot;강화 학습 방법보다 성공률이 절대값으로 각각 34%p, 10%p 높습니다. 프롬프트에 넣은 예시는 한두 개뿐입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;743&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bO6OfI/dJMcaaty48y/5DjgU4GlhheiqxWkcmlUok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bO6OfI/dJMcaaty48y/5DjgU4GlhheiqxWkcmlUok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bO6OfI/dJMcaaty48y/5DjgU4GlhheiqxWkcmlUok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbO6OfI%2FdJMcaaty48y%2F5DjgU4GlhheiqxWkcmlUok%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;1200&quot; height=&quot;743&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;743&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 5. ReAct 논문 초록에 나온 결과입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;smolagents 코드.&lt;/b&gt; Hugging Face의 오픈소스 에이전트 라이브러리 smolagents는 &lt;a href=&quot;https://huggingface.co/docs/smolagents/conceptual_guides/react&quot;&gt;공식 문서 &quot;How do multi-step agents work?&quot;&lt;/a&gt;에서 모든 에이전트가 ReAct를 추상화한 &lt;code&gt;MultiStepAgent&lt;/code&gt; 하나에서 나온다고 설명합니다. 단계에 에러가 나면 에러 내용 뒤에 &quot;Now let's retry: take care not to repeat previous errors! If you have retried several times, try a completely different approach.&quot;라는 문장을 붙여 모델에게 다시 보냅니다(&lt;code&gt;memory.py&lt;/code&gt;). 여러 번 실패하면 방법을 바꾸라는 지시까지 코드에 들어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;강의.&lt;/b&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h31m56s&quot;&gt;Stanford CME295 7강 1:31:56&lt;/a&gt;부터 ReAct 에이전트를 다룹니다. &lt;a href=&quot;https://www.youtube.com/watch?v=Lxh9RF5S-K0&quot;&gt;Stanford CS329A Part 4 &quot;Learning from Feedback with Tools&quot;&lt;/a&gt;도 ReAct를 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 화 예고.&lt;/b&gt; 이번 화에서 행동은 &quot;도구를 부른다&quot; 한 줄로 넘어갔습니다. 언어 모델은 글자만 내놓는데, 어떻게 계산기를 누르고 파일을 열까요? 2화 &quot;AI는 글자만 쓰는데, 어떻게 도구를 쓸까?&quot;에서 함수 호출을 다룹니다. &lt;/p&gt;
&lt;hr style=&quot;border: 0; border-top: 1px solid #dcdfe3; margin: 36px 0;&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본: rohitg00/ai-engineering-from-scratch (MIT, &amp;copy; 2026 Rohit Ghumare). 이 글은 원문을 바탕으로 직접 정리하고 재구성했습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;출처&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;rohitg00/ai-engineering-from-scratch, 14-01 The Agent Loop: &lt;a href=&quot;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/01-the-agent-loop&quot;&gt;https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/14-agent-engineering/01-the-agent-loop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Yao et al., ReAct (arXiv 2210.03629): &lt;a href=&quot;https://arxiv.org/abs/2210.03629&quot;&gt;https://arxiv.org/abs/2210.03629&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ReAct 프로젝트 사이트: &lt;a href=&quot;https://react-lm.github.io&quot;&gt;https://react-lm.github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;huggingface/smolagents (Apache-2.0): &lt;a href=&quot;https://github.com/huggingface/smolagents&quot;&gt;https://github.com/huggingface/smolagents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;smolagents 문서, How do multi-step agents work?: &lt;a href=&quot;https://huggingface.co/docs/smolagents/conceptual_guides/react&quot;&gt;https://huggingface.co/docs/smolagents/conceptual_guides/react&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude Code 문서, How Claude Code works: &lt;a href=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot;&gt;https://code.claude.com/docs/en/how-claude-code-works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford CME295 Lecture 7, 1:31:56: &lt;a href=&quot;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h31m56s&quot;&gt;https://www.youtube.com/watch?v=h-7S6HNq0Vg&amp;amp;t=1h31m56s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stanford CS329A Part 4: &lt;a href=&quot;https://www.youtube.com/watch?v=Lxh9RF5S-K0&quot;&gt;https://www.youtube.com/watch?v=Lxh9RF5S-K0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/Engineering</category>
      <category>AI 개발</category>
      <category>ai 에이전트</category>
      <category>ai-engineering-from-scratch</category>
      <category>claude code</category>
      <category>LLM</category>
      <category>React</category>
      <category>smolagents</category>
      <category>생성형 ai</category>
      <category>에이전트 루프</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/7</guid>
      <comments>https://agentnote.tistory.com/7#entry7comment</comments>
      <pubDate>Tue, 6 Oct 2026 11:14:54 +0900</pubDate>
    </item>
    <item>
      <title>Claude Code 팀 사용법 4편: 설계는 숫자로 고르고, 화면은 디자인 기준 파일로</title>
      <link>https://agentnote.tistory.com/5</link>
      <description>&lt;!-- 제목: Claude Code 팀 사용법 4편: 설계는 숫자로 고르고, 화면은 디자인 기준 파일로 | 태그: Claude Code, 클로드 코드, Claude Code 사용법, 설계 결정, 아키텍처 결정, impeccable, 대시보드 디자인, UI 디자인, AI 코딩, 팀 개발 --&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약.&lt;/b&gt; 저희 팀은 되돌리기 비싼 설계 결정을 느낌으로 하지 않습니다. Claude Code(클로드 코드)에게 대안을 같은 축의 표와 숫자로 비교하게 하고, &quot;무엇이 달라지면 다시 보나&quot;를 꼭 적게 합니다. 화면을 만들 때는 /impeccable 같은 디자인 스킬보다 디자인 기준 파일을 먼저 읽힙니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;이 글은 &quot;Claude Code 팀 사용법&quot; 4편 연재 중 마지막 4편입니다. 프론트엔드&amp;middot;백엔드가 있는 웹 시스템을 여러 명이 함께 개발하는 팀 기준입니다. 데이터 분석이나 문서 작업, 혼자 쓰는 작은 스크립트처럼 상황이 다르면 맞지 않는 규칙도 있습니다.&lt;/i&gt;&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;Claude Code로 설계 결정할 때 &quot;느낌&quot;으로 정하지 않는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사내 업무용 웹 대시보드를 만들며 구조를 정할 일이 자주 있었습니다. 근거가 느낌뿐이면 반년 뒤에 왜 그렇게 정했는지 아무도 모릅니다. 그래서 대안을 숫자로 견줘 놓고 고르기로 했습니다. 이때 부르는 스킬이 /jeffdean-mind입니다. 대안을 2개 이상 숫자로 비교하고, 10~20배로 늘었을 때와 결정이 뒤집히는 조건까지 적게 하는 스킬입니다. 실제로 이렇게 고른 기록이 네 건 남아 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&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;b&gt;선택지가 둘 이상이다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;되돌리기가 비싸다.&lt;/b&gt; 폴더 구조, DB 스키마, 배포 경로, 라이브러리 도입 같은 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;근거가 &quot;느낌&quot;밖에 없다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나라도 빠지면 그냥 만듭니다. 이미 방법이 정해진 일, 단순 버그 수정, 함수 하나 다듬기에는 부르지 않습니다. 표만 길어지고 결론은 안 바뀝니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnSS1l/dJMcai50MOR/a8lkEkuNwXwVAz14TDUTS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnSS1l/dJMcai50MOR/a8lkEkuNwXwVAz14TDUTS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnSS1l/dJMcai50MOR/a8lkEkuNwXwVAz14TDUTS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnSS1l%2FdJMcai50MOR%2Fa8lkEkuNwXwVAz14TDUTS0%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;1200&quot; height=&quot;734&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 1. 세 조건이 다 맞을 때만 숫자로 비교합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;비교 결과에 반드시 나와야 할 네 가지&lt;/h2&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;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;대안 2개 이상을 같은 축으로 비교한 표&lt;/td&gt;
&lt;td&gt;축이 다르면 비교가 아니라 나열입니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;숫자 (줄 수, KB, px, 일수, 건수)&lt;/td&gt;
&lt;td&gt;단위가 없으면 나중에 못 씁니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10~20배로 늘면&lt;/td&gt;
&lt;td&gt;지금 괜찮은 게 내년에도 괜찮은지는 다른 질문입니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;뒤집는 조건&lt;/td&gt;
&lt;td&gt;&quot;무엇이 달라지면 이 결정을 다시 봐야 하나.&quot; 이 줄이 진짜 산출물입니다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;실제로 숫자로 고른 네 건&lt;/h2&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;프론트를 한 번에 갈아탈까, 화면 단위로 갈까&lt;/td&gt;
&lt;td&gt;다시 써야 할 줄 수, 이주 기간 동안 얼려야 하는 커밋 수, 하루에 벌어지는 차이&lt;/td&gt;
&lt;td&gt;골격 먼저. 결정을 가른 건 일수가 아니라 &quot;깨지면 원인이 하나로 좁혀진다&quot;였다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;새 보드를 새 페이지로, 탭으로, 상단에 늘 보이는 띠로&lt;/td&gt;
&lt;td&gt;기존 파일 수정 줄 수, 화면 세로 점유, 필요한 가로 폭(작은 노트북에서 이미 스크롤)&lt;/td&gt;
&lt;td&gt;별도 페이지. 데이터 크기는 셋 다 무시할 수준이라 화면 공간이 갈랐다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;백엔드를 도메인별로 나눌까, 계층별로 나눌까&lt;/td&gt;
&lt;td&gt;import 문 변경 0 vs 수십 개 파일, 기존 테스트가 이미 도메인 단위로 부르고 있었음&lt;/td&gt;
&lt;td&gt;도메인 + 파사드. 기존 테스트가 이미 답을 갖고 있었다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB 이름 규칙: 전부 개명 / 충돌 몇 건만 / 규칙 문서만&lt;/td&gt;
&lt;td&gt;코드 수정 0 vs 수십 줄 vs 수천 줄, 전면 개명 시 업로드 기능 여러 곳이 조용히 열을 잃을 위험&lt;/td&gt;
&lt;td&gt;규칙 문서와 검사 먼저, 개명은 나중. 위험한 건 뒤로 미뤘다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; 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; 새 보드 건은 재 보니 데이터 크기가 세 안 모두 무시할 수준이었습니다. &quot;데이터 크기는 기준이 아니다&quot;를 알아낸 게 수확이었고, 그래서 축을 화면 공간으로 옮겼습니다. 재 보지 않았다면 엉뚱한 기준으로 논쟁했을 겁니다.&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;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;표 대신 직접 만들어 보고 정한 것: CSS 프레임워크 도입&lt;/h2&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;관찰&lt;/td&gt;
&lt;td&gt;CSS 한 파일이 수천 줄이었습니다. &quot;확장성이 막힌다&quot;는 느낌은 맞았습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;원인 후보 둘&lt;/td&gt;
&lt;td&gt;① 한 파일에 다 있다 ② 표준 어휘가 없다. 어느 쪽인지 모르는 게 문제였습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실제로 해 봄&lt;/td&gt;
&lt;td&gt;버리는 브랜치에서 전체 선언의 아주 일부(약 2%)를 Tailwind(클래스 이름을 조합해 스타일을 거는 CSS 프레임워크)로 옮겨 봤습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;측정 결과&lt;/td&gt;
&lt;td&gt;코드가 늘었습니다. 새로 쓴 유틸 상당수가 기본 눈금에 없는 임의값이었습니다(격자의 수가 눈금에 하나도 안 맞음). 번들 크기가 늘고, 검사 여러 건이 빨개졌고, 스타일 몇 개가 조용히 사라졌는데 자동으로 잡힌 건 0건이었습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;결정적이었던 것&lt;/td&gt;
&lt;td&gt;크기가 아니었습니다. CSS를 글자로 읽어서 규칙을 거는 검사를 수십 건 갖고 있는데, 이주하면 그걸 통째로 잃습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;결정&lt;/td&gt;
&lt;td&gt;도입하지 않았습니다. 대신 한 파일을 기능별로 쪼갰습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;뒤집는 조건&lt;/td&gt;
&lt;td&gt;① 조금씩 옮기는 걸 막는 기술 문제가 풀리고 ② 화면이 조용히 깨지는 걸 잡는 검출기가 생기면 다시 봅니다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;914&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCWpXw/dJMcabsnkmC/mK71XDkAWXYk4wk9bGeuyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCWpXw/dJMcabsnkmC/mK71XDkAWXYk4wk9bGeuyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCWpXw/dJMcabsnkmC/mK71XDkAWXYk4wk9bGeuyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCWpXw%2FdJMcabsnkmC%2FmK71XDkAWXYk4wk9bGeuyK%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;1200&quot; height=&quot;914&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;914&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 2. 느낌을 측정으로 바꾼 하루가 몇 주짜리 이주를 막았습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;대안 비교를 부르는 문장: 비교 기준은 직접 준다&lt;/h2&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 화면을 새 페이지로 뺄지, 기존 화면에 탭으로 붙일지 못 정했습니다. 두 안을 숫자로 비교해 주세요. 기존 파일을 몇 줄 고쳐야 하는지, 화면 세로&amp;middot;가로를 얼마나 먹는지(작은 노트북 기준), 지금 걸려 있는 검사 중 빨개지는 게 있는지. 그리고 어떤 조건이면 이 결정이 뒤집히는지도 적어 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;알아서 비교해 주세요&quot;라고만 하면 성능&amp;middot;확장성 같은 일반 항목으로 표를 만듭니다. 실제로 문제가 되는 건 화면 공간이나 검사 빨강처럼 구체적인 것들입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;Claude Code로 화면을 만들 때는 디자인 문맥 파일부터 읽힌다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스킬을 부르기 전에 디자인 문맥 파일(&lt;code&gt;.impeccable.md&lt;/code&gt;)부터 읽힙니다. 우리 화면을 누가&amp;middot;어디서&amp;middot;어떻게 쓰는지, 그래서 어떤 모양이어야 하는지 적은 파일입니다. 디자인 스킬(/impeccable, /critique 등)은 이 파일을 기준으로 판단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 필요한가.&lt;/b&gt; 설명 없이 &quot;화면 만들어 주세요&quot;라고 하면 카드와 그림자가 많고 도넛 차트와 게이지가 들어간, 흔히 보는 예쁜 대시보드가 나옵니다. 저희 대시보드에는 맞지 않았습니다. 숫자를 &lt;b&gt;보는&lt;/b&gt; 도구가 아니라 숫자를 &lt;b&gt;고치는&lt;/b&gt; 도구이기 때문입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;처음 만들 때: /impeccable teach&lt;/h2&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;Claude가 먼저 저장소를 훑습니다(README&amp;middot;문서, package.json, 기존 컴포넌트, CSS 토큰). 알 수 있는 건 스스로 채웁니다.&lt;/li&gt;
&lt;li&gt;코드로 알 수 없는 것만 선택지를 주고 묻습니다.&lt;/li&gt;
&lt;li&gt;누가 어떤 상황에서 쓰나, 이 화면으로 무슨 일을 끝내려 하나&lt;/li&gt;
&lt;li&gt;사용자가 어떤 느낌을 받아야 하나(확신&amp;middot;침착함&amp;middot;속도감 등)&lt;/li&gt;
&lt;li&gt;서비스 성격을 세 단어로 하면&lt;/li&gt;
&lt;li&gt;닮고 싶은 서비스와, 그 서비스의 어떤 점이 좋은지&lt;/li&gt;
&lt;li&gt;절대 이렇게 보이면 안 되는 모습&lt;/li&gt;
&lt;li&gt;라이트&amp;middot;다크, 꼭 쓰거나 피할 색&lt;/li&gt;
&lt;li&gt;접근성 요구(WCAG 등급, 색약, 애니메이션 줄이기)&lt;/li&gt;
&lt;li&gt;답을 모아 저장소 맨 위에 파일을 씁니다. 사용자, 성격, 디자인 방향, 원칙 3~5개.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트의 디자인 기준 파일을 만들고 싶습니다. /impeccable teach로 진행해 주세요. 코드에서 알 수 있는 건 먼저 확인하시고, 모르는 것만 물어봐 주세요. 참고로 이 화면은 매일 쓰는 실무자와, 주 1회 회의실 큰 화면으로 보는 참석자가 같이 씁니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답할 때 신경 쓸 것 셋입니다. ① &quot;깔끔하게&quot;보다 구체적으로(&quot;회의실 뒷줄에서 읽혀야 한다&quot;, &quot;적록색약 참석자가 있다&quot;). ② 레퍼런스는 이름만 말고 &quot;그 서비스의 무엇&quot;까지. ③ 피할 모습을 꼭 말합니다. 실제로 가장 많이 쓰이는 항목입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;디자인 문맥 파일에 적힌 것&lt;/h2&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;누가 쓰나&lt;/td&gt;
&lt;td&gt;두 부류가 같은 화면을 씁니다. ① 매일 자기 모니터로 값을 검토하고 조정하는 실무자 ② 주 1회 회의실 큰 화면으로 조정안을 같이 보고 그 자리에서 확정하는 참석자. 개인 모니터에 맞추면 뒷줄에서 안 보이고, 회의실에 맞추면 개인 작업 때 스크롤이 끝없이 길어집니다. 그래서 화면 밀도(글자&amp;middot;칸 크기)를 개인용과 회의용 사이에서 고르게 했습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;닮고 싶은 것&lt;/td&gt;
&lt;td&gt;조정 전&amp;middot;후를 차이(델타)로 보여 주는 방식 / Linear처럼 키보드만으로 일이 끝나고 누르면 바로 반응하는 것 / Figma처럼 누가 지금 무엇을 바꿨는지가 화면에 남는 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;피하고 싶은 것&lt;/td&gt;
&lt;td&gt;값 하나 고치려고 화면 세 개를 오가는 오래된 업무 시스템 / 도넛&amp;middot;게이지는 많은데 정작 숫자를 고칠 수 없는 일반 BI 대시보드&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;디자인 원칙 다섯 개와 실제로 적용한 곳&lt;/h2&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;① 숫자가 주인공&lt;/td&gt;
&lt;td&gt;카드&amp;middot;그림자&amp;middot;아이콘이 숫자보다 먼저 눈에 띄면 뺍니다. 꾸미기 전에 &quot;숫자가 더 잘 읽히나?&quot;를 묻습니다&lt;/td&gt;
&lt;td&gt;진단 설명을 문단으로 넣은 목업은 행이 전부 2~3줄로 늘어 표가 글처럼 됐습니다. 칸에는 한 줄, 긴 설명은 툴팁으로 옮겼습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;② 값보다 차이&lt;/td&gt;
&lt;td&gt;조정한 값만 보면 잘 고쳤는지 모릅니다. 전&amp;middot;후와 차이를 한 화면에 둡니다&lt;/td&gt;
&lt;td&gt;일괄 조정 화면에서 목표값 옆에 &quot;+1,200 (+8%)&quot;처럼 차이를 붙였습니다(예시 숫자)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③ 색은 보조&lt;/td&gt;
&lt;td&gt;증감을 색으로만 표시하지 않습니다. +/&amp;minus; 부호와 화살표가 먼저, 색은 거들 뿐입니다. 적록색약은 남성에게 드물지 않아서 참석자 중에 있을 수 있습니다&lt;/td&gt;
&lt;td&gt;증감에 부호를 항상 붙이고, 새 색 대신 기존 경고색을 다시 씁니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;④ 제자리에서 펼치기&lt;/td&gt;
&lt;td&gt;모달(팝업 창)이나 다른 페이지로 넘기지 않고 보던 자리에서 펼칩니다. 회의 중 화면이 바뀌면 모두 흐름을 놓칩니다&lt;/td&gt;
&lt;td&gt;값 편집 창을 격자 위에 작게 뜨는 칸으로 만들었습니다. &quot;진단 화면을 하나 더 만들자&quot;는 안도 이 원칙으로 기각했습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑤ 바로 반응하고, 저장은 뒤에서&lt;/td&gt;
&lt;td&gt;저장을 누르면 서버 응답을 기다리지 않고 화면부터 바꿉니다. 실패하면 원래 값으로 되돌리고 이유를 보여 줍니다&lt;/td&gt;
&lt;td&gt;처음엔 저장할 때마다 격자가 잠깐 비었다가 다시 나타났습니다. 입력하는 순간 값이 보이게 바꾸고 그 동작을 테스트로 고정했습니다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;코드 주석에도 원칙을 적는다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 문서는 보통 만들고 잊힙니다. 저희 것은 계획서와 코드 주석에서 그대로 인용됩니다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot; style=&quot;background: #1e2330; color: #e8eaf0; padding: 16px 18px; border-radius: 8px; overflow-x: auto; line-height: 1.6;&quot;&gt;&lt;code&gt;/** 색은 2차 신호다(원칙 3) &amp;mdash; 방향은 글자가 먼저 말한다. 적록색약은 증감 색을 못 가른다. */
// 제자리에서 편다. 모달 오버레이가 아니라 격자 위에 얹히는 팝오버다
// (원칙 4 &amp;mdash; 모달은 다른 수가 정말 없을 때만)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;왜 이렇게 만들었지?&quot;의 답이 코드 바로 옆에 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;화면 하나를 만드는 순서&lt;/h2&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;목업부터 만듭니다. HTML 목업으로 모양을 보고, docs/mockups/에 쌓습니다.&lt;/li&gt;
&lt;li&gt;목업 확인 뒤 구현합니다. 2편의 흐름을 그대로 탑니다.&lt;/li&gt;
&lt;li&gt;만든 화면을 평가받습니다. /critique에 우리 사용자 조건을 알려 줍니다.&lt;/li&gt;
&lt;li&gt;브라우저로 직접 봅니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표에 진단 열을 붙이려 합니다. 디자인 문맥 파일을 먼저 읽고, 제 아이디어 중 원칙에 어긋나는 게 있으면 만들기 전에 먼저 말씀해 주세요. 목업부터 만들고, 제가 보고 나서 구현으로 갑니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 요청했더니, 만들기 전에 &quot;설명을 문단으로 넣으면 칸이 길어져서 정작 숫자가 눈에 안 들어온다&quot;는 지적을 먼저 받았습니다. 평가를 맡길 때도 조건을 붙입니다.&lt;/p&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 화면 평가해 주세요. 회의실 큰 화면에서 뒷줄이 읽을 수 있느냐가 제일 중요하고, 적록색약인 분이 참석자에 있을 수 있습니다. 그 두 가지를 기준으로 봐 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건 없이 평가를 시키면 일반 UX 기준으로 봅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BtTDr/dJMcahlXKQ6/0CNj2KzEMQqzoHrQhq9P91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BtTDr/dJMcahlXKQ6/0CNj2KzEMQqzoHrQhq9P91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BtTDr/dJMcahlXKQ6/0CNj2KzEMQqzoHrQhq9P91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBtTDr%2FdJMcahlXKQ6%2F0CNj2KzEMQqzoHrQhq9P91%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;1200&quot; height=&quot;624&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 3. 기준 파일 &amp;rarr; 목업 &amp;rarr; 구현 &amp;rarr; 평가 &amp;rarr; 브라우저.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;화면과 문서를 만드는 스킬들&lt;/h2&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;화면&amp;middot;컴포넌트를 만든다&lt;/td&gt;
&lt;td&gt;/impeccable (목업 &amp;rarr; 구현)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;디자인 문맥을 처음 세운다&lt;/td&gt;
&lt;td&gt;/impeccable teach (한 번만)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;만든 화면을 평가한다&lt;/td&gt;
&lt;td&gt;/critique (시각 위계&amp;middot;인지 부하 점수)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;배치&amp;middot;여백이 어딘가 어색하다&lt;/td&gt;
&lt;td&gt;/layout (간격&amp;middot;정렬&amp;middot;리듬 교정)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;움직임을 더한다&lt;/td&gt;
&lt;td&gt;/animate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;아키텍처 도식이 필요하다&lt;/td&gt;
&lt;td&gt;아키텍처 도식 스킬&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이미 있는 HTML에 그림을 넣는다&lt;/td&gt;
&lt;td&gt;그림 넣는 스킬 (새 파일 없이 제자리 수정)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;차트&amp;middot;지표 타일을 만든다&lt;/td&gt;
&lt;td&gt;/dataviz (차트 코드 전에 읽는 색&amp;middot;축&amp;middot;범례 규칙)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;조사 결과를 보고서로&lt;/td&gt;
&lt;td&gt;보고서 스킬&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영 가이드&amp;middot;런북&lt;/td&gt;
&lt;td&gt;/guidify&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;회의 메모를 회의록으로&lt;/td&gt;
&lt;td&gt;/minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;글에서 AI 티를 걷어낸다&lt;/td&gt;
&lt;td&gt;/humanizer (현업 안내 메일&amp;middot;공지)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;왜 문서를 &quot;아티팩트&quot;(HTML 페이지)로 만드나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현업에는 엑셀이나 PPT 대신 링크 하나를 보냅니다. 받는 쪽은 열기만 하면 되고, git에 같이 있으니 나중에 찾을 수 있습니다. docs/에 수십 장 쌓여 있습니다. 설명 대본, 화면 목업, 속도 개선 실측, 현업 안내, 아키텍처 도식.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;따라 해 보기: 다음 구조 결정에 &quot;뒤집는 조건&quot; 받기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 되돌리기 비싼 결정을 할 때 이렇게 덧붙여 보세요. &quot;비교 기준은 A, B, C입니다. 숫자로 비교하고, 어떤 조건이면 이 결정이 뒤집히는지 적어 주세요.&quot; A, B, C는 실제로 걱정하는 것으로 채웁니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; 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;/p&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;background: #1e2330; color: #e8eaf0; padding: 16px 18px; border-radius: 8px; overflow-x: auto; line-height: 1.6;&quot;&gt;&lt;code&gt;## 결정: &amp;lt;무엇을 정했나&amp;gt;
### 비교표 (같은 축)
| 축 | 안 A | 안 B |
|---|---|---|
| 기존 파일 수정 (줄) | | |
| 화면 세로 점유 (px) | | |
| 빨개지는 검사 (건) | | |
### 10~20배로 늘면
### 뒤집는 조건
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;디자인 문맥 파일의 자리.&lt;/b&gt; /impeccable은 공개 저장소(pbakaus/impeccable, Apache-2.0)로 배포되는 디자인 스킬입니다. teach를 한 번 돌리면 저장소 맨 위에 &lt;code&gt;.impeccable.md&lt;/code&gt;가 생깁니다. 저장소에 들어 있어서 클론하면 팀원 모두에게 같은 기준이 따라옵니다(1편).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기준을 주는 이유.&lt;/b&gt; Claude Code의 스킬은 &lt;code&gt;SKILL.md&lt;/code&gt;에 절차를 적은 설명서입니다. 무엇을 기준으로 읽었느냐에 따라 결과가 갈립니다. 비교와 평가도 기준을 안 주면 가장 일반적인 기준을 고릅니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 모든 결정을 숫자로 비교시켜야 하나요?&lt;/b&gt; 아닙니다. 선택지가 둘 이상이고, 되돌리기가 비싸고, 근거가 느낌뿐일 때만 시킵니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 비교했는데 결론이 처음 생각과 같으면 시간 낭비 아닌가요?&lt;/b&gt; &quot;데이터 크기는 기준이 아니다&quot;를 알게 되어 엉뚱한 논쟁을 피했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연재는 여기까지입니다. 이제 다시 Engineering 본편으로 돌아갑니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;연재 목차: Claude Code 팀 사용법&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://agentnote.tistory.com/2&quot;&gt;1편: 첫날 세팅 30분과 꼭 지킬 규칙 8가지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://agentnote.tistory.com/3&quot;&gt;2편: 워크플로 9단계와 요청 프롬프트 10개&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://agentnote.tistory.com/4&quot;&gt;3편: 서브에이전트에게 맡기고 검증하는 법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;4편: 설계는 숫자로 고르고, 화면은 디자인 기준 파일로&lt;/b&gt; (지금 읽는 글)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;출처&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/impeccable (Apache-2.0): https://github.com/pbakaus/impeccable&lt;/li&gt;
&lt;li&gt;superpowers (MIT): https://github.com/obra/superpowers&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Skills: https://code.claude.com/docs/en/skills&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Memory(CLAUDE.md): https://code.claude.com/docs/en/memory&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/claude</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/5</guid>
      <comments>https://agentnote.tistory.com/5#entry5comment</comments>
      <pubDate>Sun, 4 Oct 2026 10:52:53 +0900</pubDate>
    </item>
    <item>
      <title>Claude Code 팀 사용법 3편: 서브에이전트에게 맡기고 검증하는 법</title>
      <link>https://agentnote.tistory.com/4</link>
      <description>&lt;!-- 제목: Claude Code 팀 사용법 3편: 서브에이전트에게 맡기고 검증하는 법 | 태그: Claude Code, 클로드 코드, Claude Code 서브에이전트, 서브에이전트, AI 에이전트, 멀티 에이전트, git, 배포 전 검사, AI 코딩, 팀 개발 --&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약.&lt;/b&gt; Claude Code(클로드 코드) 서브에이전트에게 일을 맡겼다면, 끝났는지는 &quot;다 했습니다&quot; 알림이 아니라 git 커밋으로 확인합니다. 30분이 지나도 커밋이 없으면 메인 에이전트가 직접 마무리합니다. 배포 전에는 검사 명령 하나로 여섯 단계를 정해진 순서대로 돌리고, 마지막 확인은 브라우저에서 눈으로 합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;이 글은 &quot;Claude Code 팀 사용법&quot; 4편 연재 중 3편입니다. 프론트엔드&amp;middot;백엔드가 있는 웹 시스템을 여러 명이 함께 개발하는 팀 기준입니다. 데이터 분석이나 문서 작업, 혼자 쓰는 작은 스크립트처럼 상황이 다르면 맞지 않는 규칙도 있습니다.&lt;/i&gt;&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;서브에이전트 작업 완료를 확인하는 규칙이 세 번 바뀐 이야기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편에서 소개한 여덟 가지 중 5번은 &quot;맡긴 일이 됐는지는 git으로 확인한다&quot;입니다. 이 규칙만 처음부터 이런 모양이 아니었습니다. 세 번 바뀌었고, 바뀔 때마다 시간을 크게 날린 뒤였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1차, 알림을 기다렸습니다.&lt;/b&gt; 일을 쪼개 에이전트에게 맡기고 &quot;다 했습니다&quot;가 오기를 기다렸습니다. 그런데 에이전트가 아무 말 없이 멈춘 채 몇 시간씩 있었습니다. 목록에는 계속 살아 있는 것으로 보이니 기다리는 쪽은 알 수가 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2차, 알림 대신 커밋을 봤습니다.&lt;/b&gt; 알림은 참고만 합니다. 커밋이 생겼으면 알림이 없어도 일은 된 것입니다. 에이전트가 일을 다 끝내고 커밋 직전에 죽은 적이 있었는데, 처음부터 커밋을 봤다면 바로 알았을 일이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3차, 커밋도 안 오면 메인 에이전트가 직접 마무리합니다.&lt;/b&gt; 기다리는 시간에 대략 30분이라는 상한을 뒀습니다. 그 시간을 넘으면 에이전트가 죽은 것으로 봅니다. 메인 에이전트가 남은 작업을 확인해 직접 커밋합니다. 이렇게 회수해서 잃은 작업은 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 지금 규칙은 이렇습니다. 알림은 참고용이고, 판단은 커밋으로 합니다. 30분이 지나도 커밋이 없으면 메인 에이전트가 마무리합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;597&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GurWq/dJMcaaNSDYg/SUIu7H237zasIIq78WZe40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GurWq/dJMcaaNSDYg/SUIu7H237zasIIq78WZe40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GurWq/dJMcaaNSDYg/SUIu7H237zasIIq78WZe40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGurWq%2FdJMcaaNSDYg%2FSUIu7H237zasIIq78WZe40%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;1200&quot; height=&quot;597&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;597&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 1. &quot;끝났다&quot;를 판단하는 기준은 알림 &amp;rarr; 커밋 &amp;rarr; 메인 에이전트 순으로 바뀌었습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;Claude Code 에이전트에게 일을 나눠 맡기는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 안내 문서에서 &quot;이 부분이 제일 중요하다&quot;고 적은 곳이 여기입니다. 일이 크면 에이전트를 여러 개 띄워 나눠 맡깁니다. 여기서 에이전트는 내 세션이 따로 띄운 Claude입니다. 자기 기억을 따로 갖고 한 가지 일만 합니다. 편한 만큼 위험해서, 가장 크게 데인 곳도 여기입니다.&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;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;규칙 1. &quot;다 했습니다&quot; 알림을 믿지 않는다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 두 번 있었던 일입니다. 에이전트가 일을 다 끝내고 커밋 직전에 죽었는데 알림이 오지 않았습니다. 죽은 줄 모르고 알림만 기다리며 몇 시간을 앉아 있었습니다. 그래서 판단 기준을 &quot;알림이 왔나&quot;에서 &quot;저장소가 움직였나&quot;로 바꿨습니다.&lt;/p&gt;
&lt;pre class=&quot;dsconfig&quot; style=&quot;background: #1e2330; color: #e8eaf0; padding: 16px 18px; border-radius: 8px; overflow-x: auto; line-height: 1.6;&quot;&gt;&lt;code&gt;git log --oneline -3   # 커밋이 생겼나
git status --short     # 안 끝낸 게 남아 있나
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋이 있으면 알림과 상관없이 다음으로 넘어갑니다. 커밋되지 않은 변경이 남아 있으면 그 에이전트는 죽은 것으로 봅니다. 되살리려고 씨름하지 않습니다. 메인 에이전트가 남은 변경을 확인해서 직접 커밋합니다. 실제로 그렇게 회수했고, 잃은 작업은 없었습니다. 대략 30분이 넘어가면 메인 에이전트가 반드시 직접 확인합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;규칙 2. 에이전트 목록은 &quot;살아 있다&quot;는 증거가 아니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰를 맡긴 에이전트 하나가 조용히 멈춘 적이 있습니다. 그런데 목록에는 계속 &quot;26분 전, 살아 있음&quot;으로 보였습니다. 그 표시만 믿고 밤새 기다렸습니다. 아침에 세어 보니 떠 있는 에이전트가 수십 개였고, 메모리를 수 GB 먹고 있었습니다. 대부분 전날 쓰고 남은 잔해였습니다. 그런데 그날 밤새 기다린 그 검증을 직접 해 보니 1초도 안 걸렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 규칙을 정했습니다. 리뷰는 보통 1~3분이면 끝납니다. 10분 안에 안 끝나면 &lt;b&gt;메인 에이전트&lt;/b&gt;(내가 직접 말을 거는 세션)가 확인합니다. 메인 에이전트가 리뷰 에이전트에게 한 번 재촉해 보되 답을 기다리지는 않습니다. 답이 안 오면 리뷰 에이전트를 중단시키고, 메인 에이전트가 그 검증을 직접 돌려 봅니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;규칙 3. 다 쓴 에이전트는 스스로 안 죽는다&lt;/h3&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;죽이기 전에 대상 개수를 꼭 셉니다. 1번을 건너뛰고 2번부터 하면 일하던 에이전트를 날립니다. tmux 서버 전체를 끄는 명령(&lt;code&gt;tmux kill-server&lt;/code&gt;)은 살아 있는 에이전트까지 죽이니 쓰지 않습니다. 끄는 명령은 환경마다 달라서 순서만 적습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSCQXX/dJMcaatya5r/asKw6SbKDlhuHbdcMFCi0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSCQXX/dJMcaatya5r/asKw6SbKDlhuHbdcMFCi0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSCQXX/dJMcaatya5r/asKw6SbKDlhuHbdcMFCi0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSCQXX%2FdJMcaatya5r%2FasKw6SbKDlhuHbdcMFCi0K%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 2. 정리는 &quot;세기 &amp;rarr; 남기기 &amp;rarr; 회수&quot; 순서입니다. 세기를 건너뛰면 일하던 에이전트를 날립니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;규칙 4. 여러 세션이 같은 폴더를 쓴다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희 팀은 여러 세션이 같은 폴더에서 동시에 일합니다. 그래서 커밋할 때는 경로를 지정합니다(&lt;code&gt;git commit -- &amp;lt;경로&amp;gt;&lt;/code&gt;). 경로 없이 커밋하면 옆 세션이 만든 파일이 같이 딸려 들어갑니다. 커밋 전에는 &lt;code&gt;git branch --show-current&lt;/code&gt;로 지금 브랜치를 확인합니다. 옆 세션이 브랜치를 바꿔 놨을 수 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 DB에 뭔가 쓰기 전에는 팀에 먼저 알립니다. 실제로 옆 세션이 관측하려고 준비해 둔 데이터를 지운 적이 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;배포 전 검사: 명령 하나, 여섯 단계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 전에 기억할 것은 검사 명령 하나입니다. 팀에서는 make 명령 하나로 묶었습니다. 내 컴퓨터에서 도는 검사와 서버(CI, 코드를 올릴 때마다 자동으로 검사하는 서버)에서 도는 검사가 같은 파일 하나를 씁니다. 그래서 &quot;제 로컬에선 됐는데요&quot;가 생길 자리가 없습니다. 검사는 여섯 단계를 정해진 순서로 돕니다.&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;① 마이그레이션 번호&lt;/td&gt;
&lt;td&gt;DB 변경 번호가 겹치는지&lt;/td&gt;
&lt;td&gt;겹치면 뒤 단계가 전부 무의미해진다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;② 구조 검사&lt;/td&gt;
&lt;td&gt;경로, API 목록, 없는 이름, 파일 크기&lt;/td&gt;
&lt;td&gt;제일 빠르고 제일 자주 깨진다. 먼저 돌려 빨리 실패하는 게 낫다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③ 스키마 올리기&lt;/td&gt;
&lt;td&gt;임시 DB에 표를 만든다&lt;/td&gt;
&lt;td&gt;④가 쓸 테이블을 먼저 만든다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;④ 동작 테스트&lt;/td&gt;
&lt;td&gt;계산, 화면 격자, 캐시, 업로드, 요약 같은 기능 묶음&lt;/td&gt;
&lt;td&gt;관련 테스트끼리 묶어 차례로 돌린다. 실패하면 어느 기능이 문제인지 바로 안다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑤ 프론트&lt;/td&gt;
&lt;td&gt;타입 검사 &amp;rarr; 단위 테스트&lt;/td&gt;
&lt;td&gt;타입 검사가 진짜 검사다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑥ API 응답 모양 확인&lt;/td&gt;
&lt;td&gt;서버를 실제로 띄워, 화면이 기대하는 응답 모양(필드 이름&amp;middot;자료형)과 맞는지&lt;/td&gt;
&lt;td&gt;⑤의 프론트 테스트는 가짜 응답을 써서, 서버가 필드 이름을 바꿔도 통과해 버린다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;일부러 검사에 안 넣은 것&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전 화면과 숫자를 대조하는 검사는 자동 검사에 넣지 않았습니다. 이 검사가 실패하면 &quot;집계 규칙이 바뀌었다&quot;는 뜻입니다. 그게 의도한 변경인지 실수인지는 사람이 판단해야 합니다. 그래서 집계 규칙을 건드렸을 때만 손으로 돌립니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;배포에서 조심할 것 세 가지&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;배포는 &quot;지금 폴더 내용&quot;을 빌드합니다.&lt;/b&gt; 푸시한 커밋이 아닙니다. 그래서 배포가 도는 동안에는 파일을 고치지 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;배포 명령에 파이프(&lt;code&gt;|&lt;/code&gt;)를 걸면 실패가 성공으로 보입니다.&lt;/b&gt; 파이프로 이으면 종료 코드(명령이 성공했는지 알려 주는 숫자)가 뒤쪽 명령의 것이 됩니다. 그래서 배포 명령에는 파이프를 걸지 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그만 보고 &quot;됐다&quot;고 했다가 화면이 그대로였던 적이 있습니다.&lt;/b&gt; 그래서 마지막 확인은 브라우저로, 눈으로 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhnHzf/dJMcad4J8rD/Y77fwtRAq7eAWUFWKWqM10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhnHzf/dJMcad4J8rD/Y77fwtRAq7eAWUFWKWqM10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhnHzf/dJMcad4J8rD/Y77fwtRAq7eAWUFWKWqM10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhnHzf%2FdJMcad4J8rD%2FY77fwtRAq7eAWUFWKWqM10%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;1200&quot; height=&quot;650&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;650&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 3. 세 가지 모두 &quot;됐다&quot;고 보이는데 실제로는 안 된 경우입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;자주 겪는 문제: 증상만 보면 원인을 잘못 짚는 것들&lt;/h2&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;&quot;반영했습니다&quot;라는데 안 돼 있다&lt;/td&gt;
&lt;td&gt;폴더만 보고 판단했는데 커밋엔 없었다&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git show HEAD:&amp;lt;파일&amp;gt;&lt;/code&gt;로 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB 변경 번호가 겹쳤다&lt;/td&gt;
&lt;td&gt;내 컴퓨터 기준으로만 봤다&lt;/td&gt;
&lt;td&gt;원격 기준으로 확인(&lt;code&gt;git ls-tree origin/main &amp;lt;폴더&amp;gt;&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;커밋에 남의 파일이 섞였다&lt;/td&gt;
&lt;td&gt;여러 세션이 같은 폴더를 쓴다&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git commit -- &amp;lt;경로&amp;gt;&lt;/code&gt;로 경로 지정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파일 크기 검사가 이유 없이 빨갛다&lt;/td&gt;
&lt;td&gt;검사가 세는 줄 수가 &lt;code&gt;wc -l&lt;/code&gt;보다 1 크다&lt;/td&gt;
&lt;td&gt;한도를 올리지 말고 주석을 줄인다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;타입 검사는 통과인데 실행하면 죽는다&lt;/td&gt;
&lt;td&gt;맥에서 파일명 대소문자 충돌(xyz.ts / Xyz.tsx). 타입 검사가 못 잡는다&lt;/td&gt;
&lt;td&gt;그런 파일명 짝을 아예 만들지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS를 고쳤는데 화면에서만 안 먹는다&lt;/td&gt;
&lt;td&gt;클래스 이름이 다른 데와 겹쳤다&lt;/td&gt;
&lt;td&gt;이름에 접두어를 붙이고 브라우저에서 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;브라우저로 잰 숫자가 이상하다&lt;/td&gt;
&lt;td&gt;탭이 뒤에 있으면 애니메이션이 안 돈다&lt;/td&gt;
&lt;td&gt;잴 때 &lt;code&gt;document.hidden&lt;/code&gt;부터 찍는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&quot;API 응답 모양 테스트가 있으니 괜찮겠지&quot;&lt;/td&gt;
&lt;td&gt;건너뛰도록 설정돼 있었고 개발 DB 데이터도 0건이라 실제로는 한 번도 안 돌았다&lt;/td&gt;
&lt;td&gt;테스트 &quot;이름&quot;을 증거로 읽지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;배포는 됐다는데 화면이 그대로다&lt;/td&gt;
&lt;td&gt;배포가 푸시한 커밋이 아니라 지금 폴더를 빌드했다&lt;/td&gt;
&lt;td&gt;배포 중에는 파일을 고치지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git이 403에 &quot;clock skew&quot;라고 한다&lt;/td&gt;
&lt;td&gt;시계가 아니라 키체인이 만료된 인증을 물고 있다&lt;/td&gt;
&lt;td&gt;그 호스트의 인증 정보만 초기화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;새로 만든 CSS가 화면에 안 나온다&lt;/td&gt;
&lt;td&gt;스타일 목록 파일에 한 줄(import)을 안 적었다&lt;/td&gt;
&lt;td&gt;조각을 만들면 목록에 한 줄 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;프론트 테스트가 이유 없이 빨갛다&lt;/td&gt;
&lt;td&gt;저장소 맨 위에서 돌렸다&lt;/td&gt;
&lt;td&gt;프론트 폴더로 이동해서 돌린다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저로 숫자를 재는 문제는 두 번이나 틀렸습니다. 그래서 지금은 재기 전에 &lt;code&gt;document.hidden&lt;/code&gt;(탭이 가려져 있는지 알려 주는 값)부터 찍습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;팀에서 안 하기로 한 것 10가지&lt;/h2&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;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;뭘 쓸지 정하기 전에 파일부터 열기&lt;/td&gt;
&lt;td&gt;스킬이 &quot;어떻게 찾아볼지&quot;까지 정해 줍니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;맡겨 놓고 알림만 기다리기&lt;/td&gt;
&lt;td&gt;git이 사실입니다. 30분 동안 커밋이 없으면 메인 에이전트가 직접 확인합니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;큰 파일을 통째로 읽히기&lt;/td&gt;
&lt;td&gt;컨텍스트가 찹니다. 필요한 부분만 짚어 줍니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;배포 명령에 파이프 걸기&lt;/td&gt;
&lt;td&gt;실패가 성공처럼 보입니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;빌드가 붙이는 버전 숫자(&lt;code&gt;?v=&lt;/code&gt;) 손으로 고치기&lt;/td&gt;
&lt;td&gt;빌드가 알아서 붙입니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파일 크기 한도 올리기&lt;/td&gt;
&lt;td&gt;대신 주석을 줄입니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테스트 &quot;이름&quot;을 증거로 읽기&lt;/td&gt;
&lt;td&gt;실제 출력을 봅니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;현업에 나갈 자료를 임시 폴더에 두기&lt;/td&gt;
&lt;td&gt;이틀 뒤에 못 찾습니다. &lt;code&gt;docs/&lt;/code&gt;에 둡니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;남의 &lt;code&gt;settings.local.json&lt;/code&gt; 복사하기&lt;/td&gt;
&lt;td&gt;개인 파일입니다. 필요한 권한은 쓰면서 쌓입니다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;개발 DB에 말없이 쓰기&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 에이전트에게 일을 맡기면, 알림 대신 30분쯤 뒤에 아래 두 줄을 쳐 보세요.&lt;/p&gt;
&lt;pre class=&quot;lua&quot; style=&quot;background: #1e2330; color: #e8eaf0; padding: 16px 18px; border-radius: 8px; overflow-x: auto; line-height: 1.6;&quot;&gt;&lt;code&gt;git log --oneline -3
git status --short
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; 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; Claude Code 공식 문서 Subagents는 서브에이전트가 메인 대화와 분리된 자기 컨텍스트에서 일한다고 설명합니다. 이 글에서 &quot;일 하나마다 새 에이전트에게 깨끗한 기억을 준다&quot;고 한 것이 이 구조 덕분입니다. 저희 팀은 결과를 알림이 아니라 저장소에 남은 커밋으로 읽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;절차를 스킬로 고정하기.&lt;/b&gt; 저희 팀은 절차를 superpowers 플러그인 하나로 통일했습니다. 이 플러그인의 skills 폴더에는 /subagent-driven-development, /dispatching-parallel-agents, /verification-before-completion, /finishing-a-development-branch 같은 스킬이 있습니다. 이름 그대로 계획을 에이전트에게 나눠 맡기는 절차와, &quot;됐습니다&quot;라고 말하기 전에 검증하는 절차입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사람에게 묻게 하는 일.&lt;/b&gt; 배포, &lt;code&gt;git push&lt;/code&gt;, &lt;code&gt;git reset&lt;/code&gt;, &lt;code&gt;git checkout&lt;/code&gt;은 매번 사람에게 묻도록 권한을 설정해 뒀습니다. 이 글의 규칙 4처럼 여러 세션이 같은 폴더를 쓰면 checkout 한 번이 옆 세션의 작업을 덮을 수 있기 때문입니다. 권한 설정은 공식 문서 Configure permissions에 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. Claude Code 에이전트가 끝났는지 어떻게 확인하나요?&lt;/b&gt; 알림 대신 저장소를 봅니다. &lt;code&gt;git log&lt;/code&gt;에 커밋이 생겼으면 끝난 것입니다. 30분이 지나도 커밋이 없고 변경만 남아 있으면 멈춘 것으로 보고 메인 에이전트가 마무리합니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 에이전트 목록에 &quot;살아 있음&quot;이라고 나오면 믿어도 되나요?&lt;/b&gt; 아닙니다. 멈춘 에이전트도 목록에는 살아 있는 것으로 보일 수 있습니다. 리뷰가 10분 안에 안 끝나면 메인 에이전트가 직접 확인합니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 테스트가 다 통과했는데 왜 브라우저로 또 보나요?&lt;/b&gt; 가짜 응답을 쓰는 테스트는 서버가 바뀌어도 통과합니다. 배포 로그가 성공이어도 화면이 그대로일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 4편은 &quot;숫자로 고르기와 화면 만들기&quot;입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;연재 목차: Claude Code 팀 사용법&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://agentnote.tistory.com/2&quot;&gt;1편: 첫날 세팅 30분과 꼭 지킬 규칙 8가지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://agentnote.tistory.com/3&quot;&gt;2편: 워크플로 9단계와 요청 프롬프트 10개&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편: 서브에이전트에게 맡기고 검증하는 법&lt;/b&gt; (지금 읽는 글)&lt;/li&gt;
&lt;li&gt;4편: 설계는 숫자로 고르고, 화면은 디자인 기준 파일로&lt;/li&gt;
&lt;/ul&gt;
&lt;hr style=&quot;border: 0; border-top: 1px solid #dcdfe3; margin: 36px 0;&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;출처&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude Code 문서, Subagents: https://code.claude.com/docs/en/sub-agents&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Configure permissions: https://code.claude.com/docs/en/permissions&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Settings: https://code.claude.com/docs/en/settings&lt;/li&gt;
&lt;li&gt;obra/superpowers (MIT): https://github.com/obra/superpowers&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/claude</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/4</guid>
      <comments>https://agentnote.tistory.com/4#entry4comment</comments>
      <pubDate>Sun, 4 Oct 2026 10:41:06 +0900</pubDate>
    </item>
    <item>
      <title>Claude Code 팀 사용법 2편: 워크플로 9단계와 요청 프롬프트 10개</title>
      <link>https://agentnote.tistory.com/3</link>
      <description>&lt;!-- 제목: Claude Code 팀 사용법 2편: 워크플로 9단계와 요청 프롬프트 10개 | 태그: Claude Code, 클로드 코드, Claude Code 사용법, Claude Code 프롬프트, superpowers, superpowers 스킬, 개발 워크플로, TDD, AI 코딩, 팀 개발 --&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약.&lt;/b&gt; 저희 팀은 Claude Code(클로드 코드)로 아이디어에서 배포까지 가는 과정을 9단계로 나누고, 단계마다 부르는 superpowers 스킬과 남는 파일을 정해 두었습니다. 요청 프롬프트는 표현보다 세 가지가 중요합니다. 지금 어느 단계인지, 건드리면 안 되는 자리, 끝났다는 증거로 무엇을 보여 달라고 할지입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;이 글은 &quot;Claude Code 팀 사용법&quot; 4편 연재 중 2편입니다. 프론트엔드&amp;middot;백엔드가 있는 웹 시스템을 여러 명이 함께 개발하는 팀 기준입니다. 데이터 분석이나 문서 작업, 혼자 쓰는 작은 스크립트처럼 상황이 다르면 맞지 않는 규칙도 있습니다.&lt;/i&gt;&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;Claude Code에 같은 요청을 해도 결과가 갈렸던 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혼자 쓸 때는 각자 방식이면 충분했습니다. 팀이 같은 저장소에서 Claude Code를 쓰기 시작하자 문제가 보였습니다. 같은 요청에도 누구는 계획부터 받고, 누구는 바로 코드를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금이 &quot;정하는 중&quot;인지 &quot;만드는 중&quot;인지 말하지 않으면 Claude가 짐작합니다. 짐작이 갈리니 결과도 갈렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 일의 순서를 9단계로 고정하고, 단계마다 실제로 쓰는 문장을 적어 두었습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;Claude Code 일의 흐름 9단계: 단계마다 스킬과 남는 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스킬은 &quot;이런 일은 이렇게 하라&quot;를 적어 둔 설명서입니다. 이름을 부르면 Claude가 그 절차대로 움직입니다. 아래 표의 영어 이름은 대부분 superpowers라는 공개 스킬 묶음에 들어 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baHFrq/dJMcadKqag0/0PtddFGABkEoYZqjXOtPkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baHFrq/dJMcadKqag0/0PtddFGABkEoYZqjXOtPkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baHFrq/dJMcadKqag0/0PtddFGABkEoYZqjXOtPkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaHFrq%2FdJMcadKqag0%2F0PtddFGABkEoYZqjXOtPkk%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;1200&quot; height=&quot;702&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 1. 흐름의 모양. 06과 07을 오가는 왕복이 대부분입니다.&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;th&gt;남는 것&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;01&lt;/td&gt;
&lt;td&gt;무엇을 왜 만드는지부터 정한다&lt;/td&gt;
&lt;td&gt;/brainstorming&lt;/td&gt;
&lt;td&gt;대화 (코드는 아직 안 씀)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;02&lt;/td&gt;
&lt;td&gt;방법이 둘 이상일 때 숫자로 고른다&lt;/td&gt;
&lt;td&gt;/jeffdean-mind, /grill-me&lt;/td&gt;
&lt;td&gt;결정과 &quot;뒤집히는 조건&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;03&lt;/td&gt;
&lt;td&gt;무엇이 맞는 동작인지 확정한다&lt;/td&gt;
&lt;td&gt;/to-spec&lt;/td&gt;
&lt;td&gt;명세 파일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;04&lt;/td&gt;
&lt;td&gt;작은 일로 쪼개고 각각의 &quot;끝&quot;을 정의한다&lt;/td&gt;
&lt;td&gt;/writing-plans&lt;/td&gt;
&lt;td&gt;계획 파일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05&lt;/td&gt;
&lt;td&gt;워크트리를 만들어 그 안에서만 작업한다&lt;/td&gt;
&lt;td&gt;/using-git-worktrees&lt;/td&gt;
&lt;td&gt;워크트리&amp;middot;브랜치&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;06&lt;/td&gt;
&lt;td&gt;하나씩 「실패 확인 &amp;rarr; 통과 &amp;rarr; 검증」&lt;/td&gt;
&lt;td&gt;/subagent-driven-development, /test-driven-development&lt;/td&gt;
&lt;td&gt;일 하나당 커밋 하나&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;막히면&lt;/td&gt;
&lt;td&gt;가설을 세우고 하나씩 지운다&lt;/td&gt;
&lt;td&gt;/systematic-debugging&lt;/td&gt;
&lt;td&gt;재현 절차&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;07&lt;/td&gt;
&lt;td&gt;리뷰를 요청하고, 지적은 근거를 확인한 뒤 고친다&lt;/td&gt;
&lt;td&gt;/requesting-code-review, /receiving-code-review&lt;/td&gt;
&lt;td&gt;리뷰 보고&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08&lt;/td&gt;
&lt;td&gt;끝났다고 말하기 전에 증거를 만든다&lt;/td&gt;
&lt;td&gt;/verification-before-completion&lt;/td&gt;
&lt;td&gt;검사 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09&lt;/td&gt;
&lt;td&gt;병합 &amp;rarr; 배포 &amp;rarr; 브라우저로 확인&lt;/td&gt;
&lt;td&gt;/finishing-a-development-branch&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;남는 것&quot; 칸이 중요합니다. 단계마다 파일이나 커밋이 쌓이니, 세션이 끊겨도 다음 사람이 그 파일만 읽고 이어받습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;06과 07은 일직선이 아니라 왕복입니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰(07)와 검사(08)는 한 번 통과하면 끝나는 관문이 아닙니다. 문제가 나오면 만들기(06)로 돌아갑니다. 그래서 실제로는 06과 07을 오가는 왕복이 대부분입니다. 열두 개로 쪼갠 계획이면 06&amp;ndash;07이 열두 번 돕니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;스킬 이름은 외우지 않아도 됩니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표의 스킬 이름을 외울 필요는 없습니다. &quot;코드는 아직 쓰지 말고 뭘 만들지부터 정리해 주세요&quot;라고만 해도 Claude가 알아서 그 스킬을 부릅니다. 중요한 건 이름이 아니라 지금이 어느 단계인지 말하는 것입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;Claude Code 요청 프롬프트에 들어갈 세 가지&lt;/h2&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;b&gt;지금 어느 단계인지&lt;/b&gt;: &quot;아직 정하는 중입니다&quot;, &quot;계획대로 만들어 주세요&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;건드리면 안 되는 자리&lt;/b&gt;: &quot;코드는 아직 건드리지 마세요&quot;, &quot;계획에 적힌 파일만&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;끝났다는 증거로 무엇을 보여 달라고 할지&lt;/b&gt;: &quot;검사 출력 마지막 줄을 그대로 붙여 주세요&quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;621&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by5KRj/dJMcaaUu35C/QltS8FZhmptV7oZ9RKJKKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by5KRj/dJMcaaUu35C/QltS8FZhmptV7oZ9RKJKKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by5KRj/dJMcaaUu35C/QltS8FZhmptV7oZ9RKJKKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby5KRj%2FdJMcaaUu35C%2FQltS8FZhmptV7oZ9RKJKKk%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;1200&quot; height=&quot;621&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;621&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 2. 표현보다 이 세 가지가 중요합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;단계별 요청 프롬프트 10개와 그렇게 쓰는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희 팀이 실제로 쓰는 문장입니다. 문장보다 &quot;왜&quot;를 가져가시면 됩니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;1. 뭘 만들지 정하기 (/brainstorming)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검토 화면에 「이번 주에 볼 것」 필터를 넣고 싶습니다. 코드는 아직 건드리지 마시고, 무엇을 만들지부터 같이 정리해 주세요. 지금 사용자가 이 화면에서 뭘 놓치고 있는지가 제일 궁금합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; &quot;만들어 주세요&quot;로 시작하면 바로 코드를 씁니다. &quot;아직 건드리지 마세요&quot; 한 줄이 이 단계를 지킵니다. 마지막 줄처럼 내가 무엇을 모르는지 말하면 Claude가 던지는 질문이 훨씬 좋아집니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;2. 방법 고르기 (/jeffdean-mind)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분류를 브라우저에서 할지 서버에서 할지 못 정했습니다. 두 안을 숫자로 비교해 주세요. 데이터는 ○○건, 사용자는 ○명, 주 ○회 씁니다. 10배로 늘면 어떻게 되는지, 어떤 조건이면 이 결정이 뒤집히는지도 같이 적어 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; ○○ 자리에는 실제 값을 넣습니다. 건수&amp;middot;인원&amp;middot;빈도 같은 숫자를 주지 않으면 추정에 근거가 없습니다. &quot;뒤집히는 조건&quot;은 꼭 요구합니다. 반년 뒤 이 결정을 다시 볼 때 그 한 줄이 제일 쓸모 있습니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;3. 명세로 확정하기&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 정한 걸 명세로 남겨 주세요. 아직 안 정해진 건 억지로 정하지 말고 「미정」이라고 표시해 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; 미정을 미정이라고 적어 두면 나중에 Claude가 마음대로 정하지 않습니다. 빈칸을 남기면 그럴듯하게 채우고, 그렇게 채워진 값이 제일 찾기 어려운 버그가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경로나 파일명은 말하지 않습니다. 저장 위치는 스킬에 이미 정해져 있어서 알아서 저장하고 커밋합니다. 스킬이 이미 하는 일을 굳이 지시하지 않습니다. 문장만 길어지고, 잘못 적으면 엉뚱한 자리에 저장됩니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;4. 계획 쓰기 (/writing-plans)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명세로 실행 계획을 써 주세요. 조건은 넷입니다. 일 하나는 한 세션에 끝나는 크기로 쪼개 주세요. 단계마다 실행할 명령과 「기대 출력」을 적어 주세요. 지켜야 할 기준(응답 시간&amp;middot;용량)은 숫자로 적어 주세요. 깨질 만한 자리를 미리 다섯 개 적어 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; 이 네 줄이 계획의 품질을 거의 다 결정합니다. 특히 &quot;기대 출력&quot;이 없으면 Claude가 자기가 끝났는지 스스로 판단하지 못합니다. &quot;테스트를 만든다&quot;가 아니라 &quot;이 명령을 돌리면 3개가 실패하고 메시지는 이것&quot;까지 적게 합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;5. 워크트리 만들기 (/using-git-worktrees)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 계획은 워크트리에서 작업하겠습니다. feat/&amp;lt;이름&amp;gt; 워크트리를 만들어 주세요. 그 안에서만 고치고, 원래 폴더는 건드리지 말아 주세요.&lt;/p&gt;
&lt;/div&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;main&lt;/code&gt;을 그대로 두고, &lt;code&gt;feat/필터&lt;/code&gt; 작업은 옆 폴더에서 합니다. 두 폴더는 같은 저장소(.git)를 공유하므로 커밋은 한곳에 쌓이지만, 작업 중인 파일은 서로 건드리지 않습니다. 브랜치를 갈아타려고 하던 일을 치우거나 stash할 필요도 없습니다. 작업이 끝나면 &lt;code&gt;git worktree remove&lt;/code&gt;로 폴더를 지웁니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background: #1e2330; color: #e8eaf0; padding: 16px 18px; border-radius: 8px; overflow-x: auto; line-height: 1.6;&quot;&gt;&lt;code&gt;git worktree add ../app-filter -b feat/filter   # 옆 폴더에 새 브랜치로 펼치기
git worktree list                                # 지금 펼쳐진 폴더 목록
git worktree remove ../app-filter                # 끝나면 정리
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;735&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tKbSa/dJMcaiZbQbo/Udvq3Unlw5LRACiWuxVC40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tKbSa/dJMcaiZbQbo/Udvq3Unlw5LRACiWuxVC40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tKbSa/dJMcaiZbQbo/Udvq3Unlw5LRACiWuxVC40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtKbSa%2FdJMcaiZbQbo%2FUdvq3Unlw5LRACiWuxVC40%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;1200&quot; height=&quot;735&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;735&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 3. 저장소는 하나, 작업 폴더는 둘. 세션마다 자기 폴더에서만 고칩니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;6. 만들기&amp;middot;맡기기 (/subagent-driven-development)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계획의 첫 번째 것부터 진행해 주세요. 일 하나당 에이전트 하나, 커밋 하나로 끊어 주세요. 계획에 적힌 파일만 고치고, 다른 파일이 필요해지면 고치지 말고 멈춰서 저한테 물어봐 주세요. 하나 끝날 때마다 해당 테스트만 돌려서 출력을 붙여 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 에이전트는 내 세션이 따로 띄운 Claude입니다. 자기 컨텍스트를 따로 갖고 한 가지 일만 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; &quot;계획에 적힌 파일만&quot;이 이 방식의 거의 전부입니다. 이 한 줄이 없으면 겸사겸사 옆 파일까지 정리하고, 그 정리가 다른 작업과 충돌합니다. 멈추고 묻게 하는 것도 같은 이유입니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;7. 막혔을 때 (/systematic-debugging)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 테스트가 왜 빨간지 모르겠습니다. 고치기 전에, 가설을 세 개 세우고 하나씩 지워 주세요. 먼저 재현하는 최소 절차부터 알려 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;빨갛다&quot;는 테스트가 실패했다는 뜻입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; 원인을 모른 채 고치면 증상만 옆으로 옮겨 갑니다. &quot;고치기 전에&quot;가 핵심입니다. 재현 절차를 먼저 받아 두면 같은 문제가 또 나도 5분이면 끝납니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;8. 리뷰 받기 (/requesting-code-review &amp;middot; /receiving-code-review)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰는 문장이 두 개입니다. 요청할 때와, 지적을 받았을 때입니다.&lt;/p&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 구현이 끝났습니다. 계획에 적어 둔 「깨질 만한 자리」 다섯 개를 기준으로 리뷰해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰 지적 중 2번은 저는 동의가 안 됩니다. 고치기 전에, 실제로 그런지 코드에서 확인하고 근거를 보여 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; 리뷰를 그대로 받아 적으면 없던 버그가 생깁니다. 두 번째 문장을 쓰지 않으면 &quot;네, 맞습니다&quot; 하고 잘못된 수정을 합니다. 지적이 맞는지 코드로 확인하게 하는 것이 그 문장의 역할입니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;9. 검사 (/verification-before-completion)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝났다고 말씀하시기 전에 검사를 끝까지 돌리고, 출력 마지막 줄을 그대로 붙여 주세요. 빨간 게 있으면 「무엇이」 빨간지부터 알려 주세요.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; &quot;통과했습니다&quot;는 주장이고, 출력이 증거입니다. 마지막 줄을 붙이게 하는 것만으로 &quot;돌렸다고 생각했는데 안 돌린&quot; 경우가 거의 사라집니다.&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;10. 배포 (/finishing-a-development-branch)&lt;/h3&gt;
&lt;div style=&quot;background: #f3f5f9; border-left: 4px solid #1f2a44; border-radius: 6px; padding: 18px 22px; margin: 8px 0 28px; line-height: 1.8;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;병합 전 정리를 해 주세요. 배포 전에 원격 기준으로 DB 변경(마이그레이션) 번호를 확인해 주시고, 배포 명령엔 파이프를 걸지 말아 주세요. 끝나면 제가 브라우저로 직접 봅니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜:&lt;/b&gt; 마이그레이션 번호는 내 컴퓨터가 아니라 원격 저장소를 봐야 합니다. 마이그레이션은 데이터베이스 구조를 바꾸는 변경 파일입니다. 배포 명령 뒤에 파이프(&lt;code&gt;|&lt;/code&gt;)로 다른 명령을 이으면 실패가 성공처럼 보입니다. 마지막 줄은 최종 확인은 사람이 한다는 선언입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;딱 하나만 가져간다면: 첫 줄에 &quot;지금 어느 단계인지&quot;&lt;/h2&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;로 시작하면 커밋이 돌아옵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ofP75/dJMcahsIl5E/eZDRz29U2UYoYsUU2pFQm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ofP75/dJMcahsIl5E/eZDRz29U2UYoYsUU2pFQm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ofP75/dJMcahsIl5E/eZDRz29U2UYoYsUU2pFQm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FofP75%2FdJMcahsIl5E%2FeZDRz29U2UYoYsUU2pFQm0%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;1200&quot; height=&quot;634&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 4. 첫 줄 하나가 돌아오는 결과의 종류를 바꿉니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;Claude Code 스킬이 겹칠 때 고르는 법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스킬은 내 컴퓨터 전체에 깔린 것(전역)과 저장소에 들어 있는 것, 두 군데서 옵니다. 전부 알 필요는 없습니다. 겹칠 때 무엇을 쓰는지만 알면 됩니다. 애매하면 저장소의 CLAUDE.md(세션마다 자동으로 읽는 팀 규칙 파일)에 적어 둔 표가 최종 답입니다.&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;b&gt;기본은 superpowers입니다.&lt;/b&gt; 계획&amp;middot;실행&amp;middot;테스트&amp;middot;디버깅&amp;middot;리뷰&amp;middot;검증이 다 여기 있습니다. 9단계 표의 영어 스킬 이름이 이 묶음의 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;superpowers에 없는 기능만 다른 스킬을 씁니다.&lt;/b&gt; 같은 일을 두 스킬이 다르게 시키면 사람마다 결과가 갈리기 때문입니다.&lt;/li&gt;
&lt;/ul&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;방법이 둘 이상이라 못 고르겠을 때&lt;/td&gt;
&lt;td&gt;/jeffdean-mind (대안을 숫자로 비교)&lt;/td&gt;
&lt;td&gt;전역 (4편)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;화면을 만들 때 (필수)&lt;/td&gt;
&lt;td&gt;/impeccable + 디자인 문맥 파일&lt;/td&gt;
&lt;td&gt;전역 + 저장소 (4편)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;내가 정한 걸 누가 되물어 줬으면 할 때&lt;/td&gt;
&lt;td&gt;/grill-me&lt;/td&gt;
&lt;td&gt;저장소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;대화를 명세&amp;middot;티켓으로 정리할 때&lt;/td&gt;
&lt;td&gt;/to-spec &amp;rarr; /to-tickets&lt;/td&gt;
&lt;td&gt;저장소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;모듈 경계를 설계할 때&lt;/td&gt;
&lt;td&gt;/codebase-design&lt;/td&gt;
&lt;td&gt;저장소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;병합 충돌이 났을 때&lt;/td&gt;
&lt;td&gt;/resolving-merge-conflicts&lt;/td&gt;
&lt;td&gt;저장소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;현업용 자료를 만들 때&lt;/td&gt;
&lt;td&gt;보고서&amp;middot;가이드 만드는 스킬, 글에서 AI 티를 걷어내는 스킬(/humanizer)&lt;/td&gt;
&lt;td&gt;전역&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;회의 메모를 회의록으로 바꿀 때&lt;/td&gt;
&lt;td&gt;회의록 스킬(/minutes)&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;/grill-me, /to-spec, /to-tickets, /codebase-design은 공개 저장소 mattpocock/skills(MIT)에 있는 스킬입니다. /jeffdean-mind는 대안을 숫자로 비교하게 하는 스킬로, 4편에서 자세히 다룹니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2RSlb/dJMcacx3geF/HuYfqJ3CWbLg3KwObWmUkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2RSlb/dJMcacx3geF/HuYfqJ3CWbLg3KwObWmUkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2RSlb/dJMcacx3geF/HuYfqJ3CWbLg3KwObWmUkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2RSlb%2FdJMcacx3geF%2FHuYfqJ3CWbLg3KwObWmUkK%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;1200&quot; height=&quot;828&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center; color: #5d6577; font-size: 14px; margin-top: 6px;&quot; data-ke-size=&quot;size16&quot;&gt;그림 5. 기본 하나, 빈 곳만 다른 스킬.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;따라 해 보기: 다음 요청의 첫 줄만 바꿔 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 Claude Code에 일을 맡길 때 첫 줄에 단계를 적어 보세요.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot; style=&quot;background: #1e2330; color: #e8eaf0; padding: 16px 18px; border-radius: 8px; overflow-x: auto; line-height: 1.6;&quot;&gt;&lt;code&gt;아직 정하는 중입니다. 코드는 아직 건드리지 마시고, 무엇을 만들지부터 같이 정리해 주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문이 먼저 돌아오는지, 코드가 먼저 돌아오는지만 보면 됩니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;더 깊이: 공개 문서로 보는 9단계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;superpowers 스킬 목록.&lt;/b&gt; 9단계 표의 영어 이름은 공개 저장소 obra/superpowers(MIT)의 skills 폴더에 있습니다. /brainstorming, /writing-plans, /using-git-worktrees, /subagent-driven-development, /test-driven-development, /systematic-debugging, /requesting-code-review, /receiving-code-review, /verification-before-completion, /finishing-a-development-branch가 모두 들어 있습니다(2026-10-02 확인).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스킬과 플러그인.&lt;/b&gt; 공식 문서에서 스킬은 필요할 때 불러 쓰는 절차이고, 여러 스킬을 한 번에 설치하는 단위가 플러그인입니다. superpowers도 플러그인으로 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;06단계의 에이전트.&lt;/b&gt; &quot;일 하나당 에이전트 하나&quot;의 에이전트는 공식 문서의 서브에이전트(Subagents)에 해당합니다. 서브에이전트는 메인 세션과 별도의 컨텍스트에서 일합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 9단계를 매번 다 거쳐야 하나요?&lt;/b&gt; 표는 전체 순서입니다. 핵심은 순서를 외우는 것이 아니라, 요청할 때 지금이 어느 단계인지 말하는 것입니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 스킬 이름을 정확히 불러야 하나요?&lt;/b&gt; 아닙니다. 단계를 말하면 알아서 맞는 스킬을 부릅니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q. 비슷한 스킬이 여러 개면 무엇을 쓰나요?&lt;/b&gt; 기본 묶음 하나로 통일하고, 거기 없는 기능만 다른 스킬을 씁니다. 애매하면 CLAUDE.md의 표를 따릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 3편은 &quot;에이전트에게 맡기고 검증하기&quot;입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin-top: 44px; padding-bottom: 8px; border-bottom: 2px solid #1f2a44;&quot; data-ke-size=&quot;size26&quot;&gt;연재 목차: Claude Code 팀 사용법&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://agentnote.tistory.com/2&quot;&gt;1편: 첫날 세팅 30분과 꼭 지킬 규칙 8가지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2편: 워크플로 9단계와 요청 프롬프트 10개&lt;/b&gt; (지금 읽는 글)&lt;/li&gt;
&lt;li&gt;3편: 서브에이전트에게 맡기고 검증하는 법&lt;/li&gt;
&lt;li&gt;4편: 설계는 숫자로 고르고, 화면은 디자인 기준 파일로&lt;/li&gt;
&lt;/ul&gt;
&lt;hr style=&quot;border: 0; border-top: 1px solid #dcdfe3; margin: 36px 0;&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;margin-top: 32px;&quot; data-ke-size=&quot;size23&quot;&gt;출처&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;obra/superpowers (MIT): https://github.com/obra/superpowers&lt;/li&gt;
&lt;li&gt;pbakaus/impeccable (Apache-2.0): https://github.com/pbakaus/impeccable&lt;/li&gt;
&lt;li&gt;mattpocock/skills (MIT): https://github.com/mattpocock/skills&lt;/li&gt;
&lt;li&gt;git 공식 문서, git-worktree: https://git-scm.com/docs/git-worktree&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Skills: https://code.claude.com/docs/en/skills&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Plugins: https://code.claude.com/docs/en/plugins&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Subagents: https://code.claude.com/docs/en/sub-agents&lt;/li&gt;
&lt;li&gt;Claude Code 문서, Memory(CLAUDE.md): https://code.claude.com/docs/en/memory&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI/claude</category>
      <author>agentnote</author>
      <guid isPermaLink="true">https://agentnote.tistory.com/3</guid>
      <comments>https://agentnote.tistory.com/3#entry3comment</comments>
      <pubDate>Fri, 2 Oct 2026 22:14:01 +0900</pubDate>
    </item>
  </channel>
</rss>