<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>오늘도 공부</title>
    <link>https://javaexpert.tistory.com/</link>
    <description>AI,Flutter,Node등 다양한 분야를 연구하는 블로그입니다</description>
    <language>ko</language>
    <pubDate>Sat, 27 Jun 2026 07:21:43 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>행복한 수지아빠</managingEditor>
    <image>
      <title>오늘도 공부</title>
      <url>https://tistory1.daumcdn.net/tistory/649446/attach/3ffb00b63198428d8082dda2b9aef56d</url>
      <link>https://javaexpert.tistory.com</link>
    </image>
    <item>
      <title>mattpocock/skills 에 대한 자세한 설명</title>
      <link>https://javaexpert.tistory.com/1782</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;figure id=&quot;og_1782348460568&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - mattpocock/skills: Skills for Real Engineers. Straight from my .claude directory.&quot; data-og-description=&quot;Skills for Real Engineers. Straight from my .claude directory. - mattpocock/skills&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/mattpocock/skills&quot; data-og-url=&quot;https://github.com/mattpocock/skills&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bdYh3U/dJMb87ggyXx/PLyxmV9wvv2mhKEUDvAtP1/img.png?width=1200&amp;amp;height=600&amp;amp;face=971_129_1053_219,https://scrap.kakaocdn.net/dn/FB0PW/dJMb86n7Ghu/Jhb2b6E4k1EXFzBKkMXaDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=971_129_1053_219,https://scrap.kakaocdn.net/dn/KmWcd/dJMb81f2Gqz/iJLgdsKVHtQZe77PIVn9p1/img.png?width=738&amp;amp;height=388&amp;amp;face=491_81_572_169&quot;&gt;&lt;a href=&quot;https://github.com/mattpocock/skills&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/mattpocock/skills&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bdYh3U/dJMb87ggyXx/PLyxmV9wvv2mhKEUDvAtP1/img.png?width=1200&amp;amp;height=600&amp;amp;face=971_129_1053_219,https://scrap.kakaocdn.net/dn/FB0PW/dJMb86n7Ghu/Jhb2b6E4k1EXFzBKkMXaDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=971_129_1053_219,https://scrap.kakaocdn.net/dn/KmWcd/dJMb81f2Gqz/iJLgdsKVHtQZe77PIVn9p1/img.png?width=738&amp;amp;height=388&amp;amp;face=491_81_572_169');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - mattpocock/skills: Skills for Real Engineers. Straight from my .claude directory.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Skills for Real Engineers. Straight from my .claude directory. - mattpocock/skills&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYV7zZ/dJMcacp6abT/WUoM2EVddclOHmnA860D81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYV7zZ/dJMcacp6abT/WUoM2EVddclOHmnA860D81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYV7zZ/dJMcacp6abT/WUoM2EVddclOHmnA860D81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYV7zZ%2FdJMcacp6abT%2FWUoM2EVddclOHmnA860D81%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;1024&quot; height=&quot;1536&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 개념&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 저장소의 스킬은 크게 두 종류입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;User-invoked skill&lt;/b&gt;은 사용자가 직접 /grill-me, /to-prd처럼 호출하는 명령형 스킬입니다.&lt;br /&gt;&lt;b&gt;Model-invoked skill&lt;/b&gt;은 에이전트가 작업 중 필요할 때 자동으로 참고하거나 호출하는 내부 절차형 스킬입니다. README도 이 둘을 &amp;ldquo;누가 호출할 수 있는가&amp;rdquo; 기준으로 나눈다고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 단순 프롬프트 모음이라기보다 &lt;b&gt;기획 &amp;rarr; 질문 &amp;rarr; 문서화 &amp;rarr; 이슈화 &amp;rarr; 구현 &amp;rarr; 테스트 &amp;rarr; 디버깅 &amp;rarr; 구조 개선&lt;/b&gt;까지 에이전트가 반복 가능한 개발 루틴을 따르게 만드는 장치입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;1. Engineering 스킬&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 작업에 직접 쓰는 스킬들입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/setup-matt-pocock-skills&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 한 번 실행하는 설정 스킬입니다.&lt;br /&gt;프로젝트에서 어떤 이슈 트래커를 쓸지, triage 라벨을 어떻게 쓸지, CONTEXT.md와 ADR 같은 도메인 문서를 어디에 저장할지 정합니다. README에 따르면 GitHub, Linear, 로컬 파일 기반 이슈 관리를 선택할 수 있습니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 프로젝트에서 앞으로 에이전트가 일할 규칙과 문서 위치를 정하는 초기 세팅&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/ask-matt&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 상황에 어떤 스킬을 쓰면 좋을지 물어보는 라우터입니다.&lt;br /&gt;예를 들어 &amp;ldquo;기획을 정리해야 하나?&amp;rdquo;, &amp;ldquo;이슈로 쪼개야 하나?&amp;rdquo;, &amp;ldquo;버그를 잡아야 하나?&amp;rdquo; 같은 상황에서 적절한 스킬을 추천받는 용도입니다. README는 이를 user-invoked skills 위의 라우터라고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/grill-with-docs&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 스킬 중 하나입니다.&lt;br /&gt;사용자가 만들고 싶은 기능이나 변경사항에 대해 에이전트가 집요하게 질문합니다. 단순 질문에서 끝나는 것이 아니라, 프로젝트의 &lt;b&gt;도메인 모델&lt;/b&gt;, &lt;b&gt;공통 용어&lt;/b&gt;, &lt;b&gt;ADR&lt;/b&gt;까지 같이 정리합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 이렇게 말하면:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;회원 결제 기능 만들어줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 바로 코딩하지 않고 먼저 묻습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원은 무료/유료가 있나요?&lt;br /&gt;결제 실패 시 상태는 어떻게 되나요?&lt;br /&gt;환불은 누가 처리하나요?&lt;br /&gt;구독 갱신 실패 후 며칠 동안 접근을 허용하나요?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 결과를 CONTEXT.md나 ADR에 남겨서 이후 작업에서도 같은 용어와 판단 기준을 쓰게 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/to-prd&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 대화 내용을 바탕으로 &lt;b&gt;PRD&lt;/b&gt;, 즉 제품 요구사항 문서로 정리하는 스킬입니다.&lt;br /&gt;README에 따르면 별도 인터뷰 없이 지금까지 논의한 내용을 종합해서 PRD로 만들고 이슈 트래커에 게시하는 역할입니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 상황:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;지금까지 말한 내용을 PRD로 정리해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 기능을 개발 문서로 만들어줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과물은 보통 다음을 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목내용&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&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;/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;/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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/to-issues&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PRD나 기획서를 &lt;b&gt;작업 가능한 이슈 단위&lt;/b&gt;로 쪼개는 스킬입니다.&lt;br /&gt;README는 이를 vertical slice, 즉 독립적으로 가져가서 구현 가능한 단위로 나누는 스킬이라고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;결제 기능 구현&amp;rdquo;을 이렇게 나눕니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 기능이슈 예시&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;결제 API&lt;/td&gt;
&lt;td&gt;결제 요청 endpoint 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;결제 상태&lt;/td&gt;
&lt;td&gt;pending/success/failed 상태 모델링&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;웹훅&lt;/td&gt;
&lt;td&gt;PG사 결제 완료 웹훅 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI&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 data-ke-size=&quot;size16&quot;&gt;장점은 에이전트에게 &amp;ldquo;큰 덩어리&amp;rdquo;를 던지지 않고, 하나씩 검증 가능한 작업으로 나누는 것입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/triage&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈를 상태 머신처럼 이동시키는 스킬입니다.&lt;br /&gt;README에 따르면 triage role 라벨을 기준으로 이슈를 옮깁니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예상 흐름은 이런 식입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 이슈 &amp;rarr; 검토 필요 &amp;rarr; 기획 필요 &amp;rarr; 구현 가능 &amp;rarr; 작업 중 &amp;rarr; 완료&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Inference] 실제 라벨명은 /setup-matt-pocock-skills에서 사용자가 정한 값에 따라 달라질 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/prototype&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버릴 수 있는 프로토타입을 빠르게 만드는 스킬입니다.&lt;br /&gt;README는 상태/비즈니스 로직 질문에는 실행 가능한 터미널 앱을, UI 질문에는 한 라우트에서 여러 UI 변형을 토글할 수 있는 방식으로 만든다고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 온보딩 플로우가 좋은지 모르겠어.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 하면, 실제 제품 코드에 바로 넣지 않고 여러 버전의 UI를 만들어 비교하게 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/improve-codebase-architecture&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드베이스 구조 개선 스킬입니다.&lt;br /&gt;README에 따르면 CONTEXT.md의 도메인 언어와 docs/adr/의 결정을 참고해, 코드베이스에서 &amp;ldquo;deepening opportunities&amp;rdquo;를 찾고 시각적 HTML 리포트로 보여준 뒤, 선택한 항목에 대해 질문 과정을 진행합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;코드가 점점 진흙덩어리처럼 복잡해지는 것을 막기 위한 구조 점검 스킬&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;찾을 수 있는 문제 유형은 보통 이런 것들입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&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;도메인 로직과 UI/인프라 코드가 섞임&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;/td&gt;
&lt;td&gt;도메인 용어와 코드 이름이 다름&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;diagnosing-bugs&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델이 필요할 때 쓰는 버그 진단 루프입니다.&lt;br /&gt;README는 이를 &amp;ldquo;재현 &amp;rarr; 최소화 &amp;rarr; 가설 &amp;rarr; 계측 &amp;rarr; 수정 &amp;rarr; 회귀 테스트&amp;rdquo; 흐름으로 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 AI 코딩의 문제는 바로 &amp;ldquo;수정부터&amp;rdquo; 한다는 점입니다.&lt;br /&gt;이 스킬은 먼저 버그를 재현하고, 최소 사례를 만들고, 로그나 테스트로 확인한 다음 수정하게 만듭니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;tdd&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 주도 개발 스킬입니다.&lt;br /&gt;README는 red-green-refactor 루프를 사용해 기능이나 버그 수정을 vertical slice 단위로 진행한다고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흐름은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단계의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;실패하는 테스트를 먼저 작성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;테스트를 통과하도록 최소 구현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refactor&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;AI 에이전트에게 특히 유용한 이유는 &amp;ldquo;돌아가는지 확인할 피드백 루프&amp;rdquo;를 강제로 만들기 때문입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;domain-modeling&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 도메인 모델을 정리하고 다듬는 스킬입니다.&lt;br /&gt;README에 따르면 용어를 glossary와 대조하고, edge case 시나리오로 검증하며, CONTEXT.md와 ADR을 업데이트합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 교육 플랫폼이라면:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모호한 표현도메인 용어로 정리&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;강의 올리기&lt;/td&gt;
&lt;td&gt;lesson materialization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;수업 묶음&lt;/td&gt;
&lt;td&gt;course section&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;공개 처리&lt;/td&gt;
&lt;td&gt;publish transition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;수강 가능 상태&lt;/td&gt;
&lt;td&gt;enrollment eligibility&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;codebase-design&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 코드베이스 설계를 위한 내부 규율 스킬입니다.&lt;br /&gt;README는 &amp;ldquo;작은 인터페이스 뒤에 많은 동작을 숨기는 deep module&amp;rdquo; 개념을 중심으로, 깨끗한 경계와 테스트 가능한 인터페이스를 강조합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 에이전트가 코드를 만들 때:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일만 쪼개지 말고, 진짜 의미 있는 모듈 경계를 만들어라.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라는 설계 원칙을 주입하는 스킬입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;2. Productivity 스킬&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드에만 한정되지 않는 일반 작업용 스킬입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/grill-me&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비코드 작업에도 쓸 수 있는 질문 스킬입니다.&lt;br /&gt;README는 사용자의 계획이나 디자인에 대해 모든 결정 분기가 해결될 때까지 집요하게 인터뷰하는 스킬이라고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;블록체인 뉴스 자동화 스튜디오 만들고 싶어.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 하면 바로 PRD를 쓰지 않고:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대상 사용자는 누구인가?&lt;br /&gt;뉴스 수집 소스는 어디인가?&lt;br /&gt;자동 업로드까지 할 것인가?&lt;br /&gt;검수 단계가 필요한가?&lt;br /&gt;실패하면 누가 알림을 받는가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 질문을 통해 요구사항을 명확히 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/handoff&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 대화를 다른 에이전트가 이어받을 수 있도록 &lt;b&gt;handoff 문서&lt;/b&gt;로 압축하는 스킬입니다.&lt;br /&gt;README는 현재 대화를 compact하게 정리해서 다른 에이전트가 이어서 작업할 수 있게 한다고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;용도:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;지금까지 논의한 걸 다음 에이전트에게 넘길 문서로 정리해줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포함될 만한 내용:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목내용&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&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;/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;/td&gt;
&lt;td&gt;이어서 할 일&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/teach&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자에게 새 기술이나 개념을 여러 세션에 걸쳐 가르치는 스킬입니다.&lt;br /&gt;README는 현재 디렉터리를 상태 저장형 teaching workspace로 사용한다고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;TypeScript 고급 타입을 단계별로 가르쳐줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 요청에 맞습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/writing-great-skills&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 스킬을 작성하고 편집하기 위한 참고 스킬입니다.&lt;br /&gt;README는 스킬을 예측 가능하게 만드는 어휘와 원칙을 다루는 reference라고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 사용자가 직접 Claude/Codex용 skill을 만들 때 참고하는 &amp;ldquo;스킬 제작 가이드&amp;rdquo;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;grilling&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/grill-me와 /grill-with-docs 뒤에서 재사용되는 내부 질문 루프입니다.&lt;br /&gt;README는 계획이나 디자인의 결정 분기가 모두 해소될 때까지 사용자를 인터뷰하는 재사용 루프라고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;3. Misc 스킬&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 쓰지는 않지만 특정 상황에서 유용한 도구성 스킬입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;git-guardrails-claude-code&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code에서 위험한 git 명령을 막는 hook을 설정합니다.&lt;br /&gt;README는 push, reset --hard, clean 같은 위험 명령을 실행 전에 차단한다고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 개발에서 AI 에이전트가 실수로 작업물을 날리는 것을 막는 안전장치입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;migrate-to-shoehorn&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 파일에서 TypeScript의 as 타입 assertion을 @total-typescript/shoehorn으로 마이그레이션하는 스킬입니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 범용 스킬이라기보다 Matt Pocock의 Total TypeScript 생태계와 관련된 특수 목적 스킬에 가깝습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;scaffold-exercises&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의나 학습용 exercise 디렉터리 구조를 만드는 스킬입니다.&lt;br /&gt;README는 sections, problems, solutions, explainers 구조를 만든다고 설명합니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 TypeScript 강의 자료를 만들 때:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;exercises/
  01-basic-types/
    problem/
    solution/
    explainer.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 식으로 구성하는 용도입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;setup-pre-commit&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Husky, lint-staged, Prettier, type checking, tests를 포함한 pre-commit hook을 설정하는 스킬입니다. (&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 커밋 전에 자동으로 코드 포맷, 린트, 타입 체크, 테스트를 돌리게 만드는 개발 품질 장치입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;전체 흐름으로 보면&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 저장소는 이렇게 쓰는 게 가장 자연스럽습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. /setup-matt-pocock-skills
   &amp;darr;
2. /grill-with-docs
   요구사항 질문 + 도메인 용어 정리
   &amp;darr;
3. /to-prd
   PRD 작성
   &amp;darr;
4. /to-issues
   구현 가능한 이슈로 분해
   &amp;darr;
5. /tdd
   테스트 기반 구현
   &amp;darr;
6. diagnosing-bugs
   버그 발생 시 재현 중심으로 진단
   &amp;darr;
7. /improve-codebase-architecture
   코드가 복잡해지기 전에 구조 개선
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄로 요약하면:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;mattpocock/skills는 AI 코딩 에이전트에게 &amp;ldquo;기획을 확인하고, 문서화하고, 이슈로 쪼개고, 테스트하며, 구조를 관리하는 개발 습관&amp;rdquo;을 강제로 주입하는 스킬 세트입니다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 그냥 &amp;ldquo;만들어줘&amp;rdquo;라고 던지는 방식보다, &lt;b&gt;PRD &amp;rarr; 이슈 &amp;rarr; TDD &amp;rarr; 디버깅 &amp;rarr; 아키텍처 개선&lt;/b&gt; 흐름을 만들고 싶은 사람에게 유용합니다.&lt;/p&gt;</description>
      <category>AI/추천 오픈소스</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1782</guid>
      <comments>https://javaexpert.tistory.com/1782#entry1782comment</comments>
      <pubDate>Thu, 25 Jun 2026 09:48:46 +0900</pubDate>
    </item>
    <item>
      <title>Loop 방식의 에이전트 (Loom)</title>
      <link>https://javaexpert.tistory.com/1781</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deRVml/dJMcaa6Scc7/ghgHN4eQ8Z4UfjjQr4pYd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deRVml/dJMcaa6Scc7/ghgHN4eQ8Z4UfjjQr4pYd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deRVml/dJMcaa6Scc7/ghgHN4eQ8Z4UfjjQr4pYd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeRVml%2FdJMcaa6Scc7%2FghgHN4eQ8Z4UfjjQr4pYd0%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;1122&quot; height=&quot;1402&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1 data-end=&quot;112&quot; data-start=&quot;56&quot;&gt;&lt;span&gt;AI 코딩 에이전트의 다음 단계: Loom은 왜 &amp;ldquo;프롬프트&amp;rdquo;가 아니라 &amp;ldquo;전달 체계&amp;rdquo;를 말하는가&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;235&quot; data-start=&quot;114&quot; data-ke-size=&quot;size16&quot;&gt;요즘 개발자들은 Claude Code, Codex, OpenCode 같은 AI 코딩 에이전트를 점점 더 자연스럽게 사용한다. 간단한 컴포넌트 수정, API 작성, 테스트 코드 생성 정도는 이제 꽤 익숙한 작업이 됐다.&lt;/p&gt;
&lt;p data-end=&quot;280&quot; data-start=&quot;237&quot; data-ke-size=&quot;size16&quot;&gt;그런데 실제 제품 개발에 AI 에이전트를 붙여 보면 곧 다른 문제가 드러난다.&lt;/p&gt;
&lt;p data-end=&quot;424&quot; data-start=&quot;282&quot; data-ke-size=&quot;size16&quot;&gt;AI는 코드를 꽤 잘 짠다. 하지만 &lt;b&gt;끝까지 책임지고 전달하는 일&lt;/b&gt;은 여전히 어렵다. 요구사항을 기억하고, 작업을 쪼개고, 검증하고, 실패하면 고치고, 중간에 세션이 끊겨도 다시 이어가고, 마지막에는 사람이 확인할 수 있는 근거까지 남기는 일 말이다.&lt;/p&gt;
&lt;p data-end=&quot;706&quot; data-start=&quot;426&quot; data-ke-size=&quot;size16&quot;&gt;valkor-ai/loom은 바로 이 지점을 겨냥한 오픈소스 프로젝트다. Loom은 스스로를 &amp;ldquo;agentic software delivery를 위한 loop engineering&amp;rdquo; 도구라고 설명한다. 기존 코딩 에이전트를 대체하는 모델이나 에디터가 아니라, Claude Code, Codex, OpenCode 같은 에이전트를 &lt;b&gt;반복 가능하고 검증 가능한 소프트웨어 전달 시스템&lt;/b&gt;으로 바꾸는 &amp;ldquo;delivery harness&amp;rdquo;다.&lt;/p&gt;
&lt;h2 data-end=&quot;719&quot; data-start=&quot;708&quot; data-ke-size=&quot;size26&quot;&gt;한 줄로 말하면&lt;/h2&gt;
&lt;p data-end=&quot;841&quot; data-start=&quot;721&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 AI 코딩 에이전트에게 &amp;ldquo;코드만 작성하게 하는 도구&amp;rdquo;가 아니라, &lt;b&gt;요구사항 확인 &amp;rarr; 계획 &amp;rarr; 구현 &amp;rarr; 검증 &amp;rarr; 수정 &amp;rarr; 미리보기 &amp;rarr; 인수인계&lt;/b&gt;까지 이어지는 작업 루프를 제공하는 오픈소스 전달 레이어다.&lt;/p&gt;
&lt;p data-end=&quot;857&quot; data-start=&quot;843&quot; data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 이런 차이다.&lt;/p&gt;
&lt;p data-end=&quot;873&quot; data-start=&quot;859&quot; data-ke-size=&quot;size16&quot;&gt;기존 방식은 보통 이렇다.&lt;/p&gt;
&lt;blockquote data-end=&quot;889&quot; data-start=&quot;875&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;889&quot; data-start=&quot;877&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 기능 만들어줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;1038&quot; data-start=&quot;891&quot; data-ke-size=&quot;size16&quot;&gt;그러면 AI가 코드를 작성한다. 운이 좋으면 바로 작동한다. 하지만 프로젝트가 커지면 문제가 생긴다. AI가 이전 요구사항을 잊거나, 일부만 구현하고 완료했다고 말하거나, 테스트 없이 자신 있게 답하거나, 세션이 끊긴 뒤 같은 파일을 다시 읽으며 토큰을 낭비한다.&lt;/p&gt;
&lt;p data-end=&quot;1064&quot; data-start=&quot;1040&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 이 흐름을 다음처럼 바꾸려 한다.&lt;/p&gt;
&lt;blockquote data-end=&quot;1149&quot; data-start=&quot;1066&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;1149&quot; data-start=&quot;1068&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;요구사항을 구조화하고, 작업을 나누고, 각 작업의 결과를 기록하고, 검증하고, 실패하면 수리 요청을 만들고, 다음 세션에서도 이어서 진행하자.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;1251&quot; data-start=&quot;1151&quot; data-ke-size=&quot;size16&quot;&gt;즉, Loom의 핵심은 &lt;b&gt;AI에게 더 좋은 프롬프트를 주는 것&lt;/b&gt;이 아니라, AI가 장기 작업을 수행할 때 필요한 &lt;b&gt;상태, 절차, 근거, 복구 루프&lt;/b&gt;를 만들어 주는 것이다.&lt;/p&gt;
&lt;h2 data-end=&quot;1269&quot; data-start=&quot;1253&quot; data-ke-size=&quot;size26&quot;&gt;왜 이런 도구가 필요한가&lt;/h2&gt;
&lt;p data-end=&quot;1343&quot; data-start=&quot;1271&quot; data-ke-size=&quot;size16&quot;&gt;AI 코딩 도구의 가장 큰 착각은 &amp;ldquo;코드를 잘 쓰면 개발이 끝난다&amp;rdquo;는 생각이다. 실제 소프트웨어 개발은 코드 작성보다 훨씬 넓다.&lt;/p&gt;
&lt;p data-end=&quot;1527&quot; data-start=&quot;1345&quot; data-ke-size=&quot;size16&quot;&gt;요구사항을 확인해야 하고, 아키텍처 결정을 내려야 하며, 작업 단위를 나눠야 한다. 백엔드 상태, 환경 변수, 데이터베이스, 인증, 스토리지, 런타임 조건도 챙겨야 한다. UI라면 화면 흐름, 반응형 상태, 접근성, 인터랙션까지 고려해야 한다. 이후에는 테스트를 돌리고, 로그를 확인하고, 실패를 고친 뒤 다시 검증해야 한다.&lt;/p&gt;
&lt;p data-end=&quot;1729&quot; data-start=&quot;1529&quot; data-ke-size=&quot;size16&quot;&gt;Loom의 README도 이 문제를 명확히 짚는다. 웹사이트나 앱 생성 자체는 점점 쉬워지고 있지만, 더 어려운 문제는 &amp;ldquo;신뢰할 수 있는 전달&amp;rdquo;이라고 본다. 특히 장기 작업에서는 부분 완료, 목표 이탈, 자기검증 편향, 토큰 낭비, 인수인계 공백 같은 문제가 반복적으로 발생한다고 설명한다.&lt;/p&gt;
&lt;p data-end=&quot;1947&quot; data-start=&quot;1731&quot; data-ke-size=&quot;size16&quot;&gt;이 지점에서 Loom은 프롬프트 파일이나 단발성 워크플로와 구분된다. 단순히 CLAUDE.md, AGENTS.md, .cursorrules 같은 지침 파일을 두는 것이 아니라, 프로젝트 내부의 .loom/ 디렉터리에 작업 상태와 증거를 저장하고, 에이전트 중립적인 CLI 명령으로 다음 단계를 라우팅한다.&lt;/p&gt;
&lt;h2 data-end=&quot;1969&quot; data-start=&quot;1949&quot; data-ke-size=&quot;size26&quot;&gt;Loom의 핵심 개념: &amp;ldquo;루프&amp;rdquo;&lt;/h2&gt;
&lt;p data-end=&quot;2055&quot; data-start=&quot;1971&quot; data-ke-size=&quot;size16&quot;&gt;Loom이 말하는 루프는 단순 반복이 아니다. 소프트웨어 전달 과정 전체를 단계별로 쪼개고, 각 단계의 결과를 기록하며, 실패하면 다시 고치는 구조다.&lt;/p&gt;
&lt;p data-end=&quot;2077&quot; data-start=&quot;2057&quot; data-ke-size=&quot;size16&quot;&gt;Loom의 기본 흐름은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2212&quot; data-start=&quot;2079&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;2092&quot; data-start=&quot;2079&quot;&gt;전달 범위 확인&lt;/li&gt;
&lt;li data-end=&quot;2111&quot; data-start=&quot;2093&quot;&gt;압축된 컨텍스트 팩 생성&lt;/li&gt;
&lt;li data-end=&quot;2135&quot; data-start=&quot;2112&quot;&gt;계획, 아키텍처, 작업 계약 생성&lt;/li&gt;
&lt;li data-end=&quot;2159&quot; data-start=&quot;2136&quot;&gt;한 번에 하나의 제한된 작업 실행&lt;/li&gt;
&lt;li data-end=&quot;2178&quot; data-start=&quot;2160&quot;&gt;증거 기록 및 검증 실행&lt;/li&gt;
&lt;li data-end=&quot;2195&quot; data-start=&quot;2179&quot;&gt;리뷰, 수정, 재검증&lt;/li&gt;
&lt;li data-end=&quot;2212&quot; data-start=&quot;2196&quot;&gt;최종 전달 상태 보고&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;2307&quot; data-start=&quot;2214&quot; data-ke-size=&quot;size16&quot;&gt;이 흐름은 README의 &amp;ldquo;How It Works&amp;rdquo; 섹션에 제시된 Loom의 핵심 루프와 일치한다.&lt;/p&gt;
&lt;p data-end=&quot;2481&quot; data-start=&quot;2309&quot; data-ke-size=&quot;size16&quot;&gt;여기서 중요한 표현은 &lt;b&gt;작업 계약(task contract)&lt;/b&gt;이다. AI에게 &amp;ldquo;대충 이 기능 만들어줘&amp;rdquo;라고 맡기는 것이 아니라, 특정 소스 참조, 수용 기준, 결과 파일, 계속 진행 규칙 등을 가진 작업 단위로 나누는 방식이다. 이렇게 해야 AI가 일부만 만들고 끝났다고 착각하는 문제를 줄일 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;2506&quot; data-start=&quot;2483&quot; data-ke-size=&quot;size26&quot;&gt;기존 AI 코딩 도구와 무엇이 다른가&lt;/h2&gt;
&lt;p data-end=&quot;2572&quot; data-start=&quot;2508&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 Claude Code나 Codex와 경쟁하는 도구라기보다, 그 위에 얹히는 &lt;b&gt;운영 레이어&lt;/b&gt;에 가깝다.&lt;/p&gt;
&lt;p data-end=&quot;2694&quot; data-start=&quot;2574&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code, Codex, OpenCode는 코드를 작성하고 명령을 실행하는 에이전트다. Loom은 이 에이전트들이 어떤 순서로 일해야 하는지, 무엇을 기억해야 하는지, 어떤 근거를 남겨야 하는지 관리한다.&lt;/p&gt;
&lt;p data-end=&quot;2725&quot; data-start=&quot;2696&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 Codex에서는 다음처럼 사용할 수 있다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@loom build a visitor registration system
@loom plan this feature first
@loom continue
@loom review
@loom deploy&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3079&quot; data-start=&quot;2853&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code와 OpenCode에서는 /loom build, /loom continue, /loom review, /loom deploy 같은 명령 형태로 사용한다. Loom은 Codex, Claude Code, OpenCode용 로컬 어댑터 설치를 지원하며, 각 어댑터는 동일한 Loom 전달 프로토콜을 사용한다.&lt;/p&gt;
&lt;p data-end=&quot;3096&quot; data-start=&quot;3081&quot; data-ke-size=&quot;size16&quot;&gt;이 구조의 장점은 명확하다.&lt;/p&gt;
&lt;p data-end=&quot;3223&quot; data-start=&quot;3098&quot; data-ke-size=&quot;size16&quot;&gt;하나의 AI 에이전트에 종속되지 않는다. 오늘은 Codex를 쓰고, 내일은 Claude Code를 쓰더라도, Loom이 저장한 전달 상태를 중심으로 이어갈 수 있다. 프로젝트 로컬 상태가 .loom/에 저장되기 때문이다.&lt;/p&gt;
&lt;h2 data-end=&quot;3244&quot; data-start=&quot;3225&quot; data-ke-size=&quot;size26&quot;&gt;토큰 절약이라는 현실적인 장점&lt;/h2&gt;
&lt;p data-end=&quot;3354&quot; data-start=&quot;3246&quot; data-ke-size=&quot;size16&quot;&gt;AI 개발 자동화에서 토큰 비용은 생각보다 큰 문제다. 특히 대형 코드베이스에서 에이전트가 매번 전체 저장소를 다시 읽거나, 이미 파악한 내용을 반복해서 요약하면 비용과 시간이 빠르게 증가한다.&lt;/p&gt;
&lt;p data-end=&quot;3523&quot; data-start=&quot;3356&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 프로젝트 요약, 작업 그래프, 백엔드 상태, 테스트 결과, 배포 증거 등을 저장해 에이전트가 매번 전체 맥락을 다시 읽지 않도록 설계되어 있다. README에서는 이를 &amp;ldquo;Token-Saving Context&amp;rdquo;로 설명한다.&lt;/p&gt;
&lt;p data-end=&quot;3766&quot; data-start=&quot;3525&quot; data-ke-size=&quot;size16&quot;&gt;공개된 11개 케이스 benchmark 결과에서는 Codex 단독 실행과 Codex + Loom 실행을 비교했을 때, Codex + Loom이 전체 468,067 토큰 대비 394,037 토큰을 사용해 74,030 토큰, 즉 15.8%를 절약했다고 제시되어 있다. 또한 11개 중 8개 케이스에서 토큰을 덜 사용했고, 완료율은 양쪽 모두 100%로 기록되어 있다.&lt;/p&gt;
&lt;p data-end=&quot;3858&quot; data-start=&quot;3768&quot; data-ke-size=&quot;size16&quot;&gt;다만 이 수치는 프로젝트 측 벤치마크 결과다. 외부 독립 검증 결과는 아니므로, 실제 효과는 코드베이스 규모, 에이전트 종류, 작업 유형에 따라 달라질 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;3872&quot; data-start=&quot;3860&quot; data-ke-size=&quot;size26&quot;&gt;설치와 기술 스택&lt;/h2&gt;
&lt;p data-end=&quot;4090&quot; data-start=&quot;3874&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 Node.js 기반 프로젝트다. package.json 기준 버전은 0.1.0, 라이선스는 Apache-2.0이며, TypeScript로 빌드되는 CLI 도구 구조를 갖고 있다. 의존성에는 commander, yaml, zod, pdf-parse, mammoth 등이 포함되어 있다.&lt;/p&gt;
&lt;p data-end=&quot;4109&quot; data-start=&quot;4092&quot; data-ke-size=&quot;size16&quot;&gt;기본 설치 흐름은 다음과 같다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;git clone https://github.com/valkor-ai/loom.git
cd loom
npm install&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4220&quot; data-start=&quot;4192&quot; data-ke-size=&quot;size16&quot;&gt;그다음 사용하는 에이전트에 따라 어댑터를 설치한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;npm run plugin:install-codex
npm run plugin:install-claude
npm run plugin:install-opencode&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4361&quot; data-start=&quot;4326&quot; data-ke-size=&quot;size16&quot;&gt;여러 에이전트를 함께 테스트하려면 다음 명령을 사용할 수 있다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;npm run plugin:install-adapters&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4525&quot; data-start=&quot;4408&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 Node.js 20 이상과 npm을 요구하며, loom deploy 기능을 위해 Docker가 필요하다고 문서에 명시되어 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;4542&quot; data-start=&quot;4527&quot; data-ke-size=&quot;size26&quot;&gt;사용방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Loom 사용방법은 크게 &lt;b&gt;설치 &amp;rarr; 에이전트 어댑터 연결 &amp;rarr; 프로젝트에서 Loom 명령 실행 &amp;rarr; continue/review/deploy로 반복&lt;/b&gt; 흐름입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Loom 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 GitHub 저장소를 받아옵니다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;git clone https://github.com/valkor-ai/loom.git
cd loom
npm install
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Loom은 &lt;b&gt;Node.js 20 이상&lt;/b&gt;, npm이 필요하고, loom deploy를 쓰려면 &lt;b&gt;Docker&lt;/b&gt;가 필요합니다. 공식 README에도 prerequisites로 Node.js &amp;gt;= 20, npm, 사용하는 코딩 에이전트 CLI, Docker가 명시되어 있습니다. (&lt;a href=&quot;https://github.com/valkor-ai/loom?utm_source=chatgpt.com&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 사용하는 AI 코딩 에이전트에 맞게 어댑터 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Loom은 단독으로 쓰는 앱이라기보다 &lt;b&gt;Codex, Claude Code, OpenCode 같은 코딩 에이전트 안에서 명령어로 호출&lt;/b&gt;하는 방식입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Codex용&lt;/h3&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;npm run plugin:install-codex
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Claude Code용&lt;/h3&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;npm run plugin:install-claude
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OpenCode용&lt;/h3&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;npm run plugin:install-opencode
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전부 설치&lt;/h3&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;npm run plugin:install-adapters
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 문서 기준으로 각 어댑터 설치 스크립트는 CLI를 빌드하고, ~/.loom/bin/loom-cli 런처와 각 에이전트용 로컬 어댑터 파일을 갱신합니다. (&lt;a href=&quot;https://github.com/valkor-ai/loom?utm_source=chatgpt.com&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 설치 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 중인 에이전트 안에서 확인합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Codex&lt;/h3&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom status
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Claude Code / OpenCode&lt;/h3&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;/loom status
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 사용하는 프로젝트라면 STATE_NOT_INITIALIZED가 나올 수 있는데, 이것은 오류가 아니라 &lt;b&gt;아직 해당 프로젝트에서 Loom delivery가 시작되지 않았다는 뜻&lt;/b&gt;입니다. (&lt;a href=&quot;https://github.com/valkor-ai/loom?utm_source=chatgpt.com&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 실제 프로젝트에서 Loom 시작하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 방문자 등록 시스템을 만들고 싶다면:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Codex&lt;/h3&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;@loom build a visitor registration system
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Claude Code / OpenCode&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;/loom build a visitor registration system
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어로도 이렇게 지시할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom build 관리자용 방문자 등록 시스템을 만들어줘. 방문자는 이름, 연락처, 방문 목적, 방문 시간을 입력하고 관리자는 목록을 확인할 수 있어야 해.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code나 OpenCode라면:&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/loom build 관리자용 방문자 등록 시스템을 만들어줘. 방문자는 이름, 연락처, 방문 목적, 방문 시간을 입력하고 관리자는 목록을 확인할 수 있어야 해.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령을 실행하면 Loom이 프로젝트 안에 .loom/ 상태를 만들고, 요구사항 확인, 계획, 작업 분해, 구현, 검증 흐름을 시작합니다. Loom은 프로젝트 로컬 전달 상태를 .loom/ 아래에 저장한다고 공식 문서가 설명합니다. (&lt;a href=&quot;https://github.com/valkor-ai/loom?utm_source=chatgpt.com&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 먼저 계획만 세우게 하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 구현시키기보다 먼저 설계를 보고 싶으면:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Codex&lt;/h3&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@loom plan this feature first
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Claude Code / OpenCode&lt;/h3&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;/loom plan this feature first
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom plan 회원 초대 기능을 먼저 설계해줘. 초대 링크 생성, 이메일 전송, 만료 시간, 권한 처리를 포함해야 해.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 AI가 바로 코드를 수정하기 전에 &lt;b&gt;요구사항, 아키텍처, 작업 단위&lt;/b&gt;를 정리하는 흐름으로 갑니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 중단 후 이어서 진행하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Loom에서 가장 중요한 명령은 continue입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 중간에 세션이 끊겼거나, AI가 멈췄거나, 다음 단계가 뭔지 애매할 때는 내부 명령을 추측하지 말고 continue를 실행하는 방식입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Codex&lt;/h3&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@loom continue
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Claude Code / OpenCode&lt;/h3&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;/loom continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 README에서도 세션을 다시 열었거나, 중단 이후 또는 다음 내부 단계가 확실하지 않을 때 continue를 먼저 실행하라고 설명합니다. (&lt;a href=&quot;https://github.com/valkor-ai/loom?utm_source=chatgpt.com&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 리뷰 실행하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현된 결과를 검토하게 하려면:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Codex&lt;/h3&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom review
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Claude Code / OpenCode&lt;/h3&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/loom review
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Loom의 핵심은 구현과 검증을 분리하는 것입니다. 공식 문서도 review, verification, repair requests, evidence records를 통해 구현과 검증을 분리한다고 설명합니다. (&lt;a href=&quot;https://github.com/valkor-ai/loom?utm_source=chatgpt.com&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 로컬 미리보기 / 검증하기&lt;/h2&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/loom deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은 여기서 말하는 deploy가 &lt;b&gt;프로덕션 배포&lt;/b&gt;는 아니라는 것입니다. 현재 Loom의 배포 지원은 로컬 Docker Compose 미리보기, 검증, 로그, 수리 가이드 중심이며, production deployment는 아직 미지원이라고 FAQ에 명시되어 있습니다. (&lt;a href=&quot;https://github.com/valkor-ai/loom?utm_source=chatgpt.com&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;실제 사용 흐름 예시&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 Next.js 프로젝트에서 관리자 페이지를 만든다고 하면 이렇게 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;cd my-next-app
codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex 안에서:&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom build 관리자 대시보드를 만들어줘. 로그인한 관리자만 접근 가능해야 하고, 사용자 목록, 검색, 상태 변경 기능이 필요해.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음:&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@loom continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계획을 보고 싶으면:&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@loom plan this feature first
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현이 끝난 뒤 검토:&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom review
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 검증:&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 있으면 다시:&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@loom continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 흐름을 반복하는 방식입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개인 개발자 기준 추천 사용법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 큰 프로젝트 전체를 맡기기보다, 기능 단위로 쓰는 게 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 예:&lt;/p&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;@loom build 게시글 작성, 수정, 삭제 기능을 만들어줘. 기존 Prisma 스키마와 Next.js App Router 구조를 유지해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 좋은 예:&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom plan 게시글 작성, 수정, 삭제 기능을 먼저 설계해줘. DB 스키마 변경이 필요한지 확인하고, API route와 UI 컴포넌트 작업을 나눠줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피하는 게 좋은 예:&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom build 인스타그램 같은 앱 만들어줘
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 범위가 커서 요구사항 확인 단계가 길어지고, 결과 품질도 흔들릴 가능성이 큽니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;한 줄 사용 공식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;처음 시작:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom build 만들 기능 설명
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설계부터:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom plan 기능 설명
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중간 이어가기:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@loom continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;검토:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom review
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로컬 미리보기/검증:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@loom deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code와 OpenCode에서는 @loom 대신 /loom을 쓰면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면, Loom은 &amp;ldquo;한 번에 코드 만들어줘&amp;rdquo;가 아니라 &lt;b&gt;AI 코딩 에이전트에게 계획, 구현, 검증, 수리, 인수인계 루프를 태우는 방식&lt;/b&gt;으로 사용하는 도구입니다.&lt;/p&gt;
&lt;h2 data-end=&quot;4542&quot; data-start=&quot;4527&quot; data-ke-size=&quot;size26&quot;&gt;어떤 상황에서 유용한가&lt;/h2&gt;
&lt;p data-end=&quot;4596&quot; data-start=&quot;4544&quot; data-ke-size=&quot;size16&quot;&gt;Loom이 빛나는 상황은 단순 코드 수정이 아니다. 오히려 다음과 같은 작업에서 의미가 크다.&lt;/p&gt;
&lt;p data-end=&quot;4722&quot; data-start=&quot;4598&quot; data-ke-size=&quot;size16&quot;&gt;첫째, 기능 하나가 여러 파일과 레이어를 건드릴 때다. 예를 들어 회원 초대 기능을 만든다면 UI, API, 권한, 이메일, 데이터베이스, 테스트가 함께 얽힌다. 이런 작업은 단발 프롬프트보다 계획과 검증 루프가 중요하다.&lt;/p&gt;
&lt;p data-end=&quot;4898&quot; data-start=&quot;4724&quot; data-ke-size=&quot;size16&quot;&gt;둘째, 에이전트 작업이 여러 세션에 걸쳐 이어질 때다. AI 코딩 도구는 세션이 길어질수록 컨텍스트 압축이나 누락 문제가 생긴다. Loom은 작업 상태를 프로젝트 내부에 저장해 continue 명령으로 다음 단계를 재개하도록 설계되어 있다.&lt;/p&gt;
&lt;p data-end=&quot;5047&quot; data-start=&quot;4900&quot; data-ke-size=&quot;size16&quot;&gt;셋째, 결과물에 대한 증거가 필요할 때다. &amp;ldquo;완료했습니다&amp;rdquo;라는 말만으로는 부족하다. 어떤 테스트를 돌렸는지, 어떤 로그를 확인했는지, 어떤 미리보기 결과가 있었는지 기록되어야 한다. Loom은 검증, 수리 요청, 배포 미리보기, 전달 보고서를 일급 단계로 다룬다.&lt;/p&gt;
&lt;p data-end=&quot;5174&quot; data-start=&quot;5049&quot; data-ke-size=&quot;size16&quot;&gt;넷째, 여러 AI 코딩 에이전트를 병행하고 싶을 때다. Codex, Claude Code, OpenCode를 각각 따로 쓰면 작업 방식과 명령 체계가 흩어진다. Loom은 이들을 공통 전달 프로토콜로 묶으려는 접근을 취한다.&lt;/p&gt;
&lt;h2 data-end=&quot;5184&quot; data-start=&quot;5176&quot; data-ke-size=&quot;size26&quot;&gt;사용 사례&lt;/h2&gt;
&lt;p data-end=&quot;5350&quot; data-start=&quot;5186&quot; data-ke-size=&quot;size16&quot;&gt;Loom 문서에는 AI 제품 런칭 사이트, 크리에이터 분석 워크스페이스, 인터랙티브 캠페인 마이크로사이트, 비행 시뮬레이터, 퀀트 트레이딩 워크벤치, 생물다양성 리서치, 영양 건강 앱 같은 예시 사용 사례가 나열되어 있다.&lt;/p&gt;
&lt;p data-end=&quot;5437&quot; data-start=&quot;5352&quot; data-ke-size=&quot;size16&quot;&gt;이 목록을 보면 Loom이 단순 &amp;ldquo;코드 수정 보조&amp;rdquo;가 아니라, 작은 제품이나 프로토타입을 끝까지 만들어 전달하는 워크플로를 겨냥하고 있음을 알 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;5548&quot; data-start=&quot;5439&quot; data-ke-size=&quot;size16&quot;&gt;특히 개인 개발자나 소규모 팀이 AI로 빠르게 MVP를 만들 때 유용해 보인다. 바이브 코딩으로 데모를 만드는 단계에서 한 걸음 더 나아가, 실제로 검증 가능한 전달물을 만들고 싶은 경우에 맞다.&lt;/p&gt;
&lt;h2 data-end=&quot;5561&quot; data-start=&quot;5550&quot; data-ke-size=&quot;size26&quot;&gt;한계도 분명하다&lt;/h2&gt;
&lt;p data-end=&quot;5612&quot; data-start=&quot;5563&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 흥미로운 도구지만, 아직 모든 것을 해결하는 완성형 플랫폼으로 보기는 어렵다.&lt;/p&gt;
&lt;p data-end=&quot;5798&quot; data-start=&quot;5614&quot; data-ke-size=&quot;size16&quot;&gt;첫째, 현재 production 배포 기능은 제공하지 않는다. README의 FAQ에 따르면 production deployment는 아직 추가 예정이며, 현재 배포 지원은 로컬 Docker Compose 미리보기, 검증, 로그, 수리 가이드에 초점을 둔다.&lt;/p&gt;
&lt;p data-end=&quot;5980&quot; data-start=&quot;5800&quot; data-ke-size=&quot;size16&quot;&gt;둘째, 초기 버전이다. package.json 기준 버전이 0.1.0이고, 저장소도 빠르게 변할 가능성이 있다. 실제 팀 워크플로에 적용하려면 파일 생성 방식, .loom/ 상태 관리, CI/CD 연동, 보안 정책 등을 직접 검토해야 한다.&lt;/p&gt;
&lt;p data-end=&quot;6107&quot; data-start=&quot;5982&quot; data-ke-size=&quot;size16&quot;&gt;셋째, AI 에이전트 자체의 품질 문제를 완전히 없애는 도구는 아니다. Loom은 루프, 상태, 검증 절차를 제공하지만, 최종 구현 품질은 여전히 사용하는 에이전트, 모델, 테스트 환경, 개발자의 리뷰 역량에 영향을 받는다.&lt;/p&gt;
&lt;p data-end=&quot;6215&quot; data-start=&quot;6109&quot; data-ke-size=&quot;size16&quot;&gt;넷째, 팀 단위 사용에서는 규칙 설계가 필요하다. .loom/ 디렉터리를 Git에 포함할지, 어떤 증거를 남길지, 민감한 로그나 환경 정보가 기록되지 않도록 어떻게 관리할지 정해야 한다.&lt;/p&gt;
&lt;h2 data-end=&quot;6238&quot; data-start=&quot;6217&quot; data-ke-size=&quot;size26&quot;&gt;그래서 Loom의 의미는 무엇인가&lt;/h2&gt;
&lt;p data-end=&quot;6289&quot; data-start=&quot;6240&quot; data-ke-size=&quot;size16&quot;&gt;Loom의 가장 큰 의미는 AI 코딩의 관심사를 &amp;ldquo;생성&amp;rdquo;에서 &amp;ldquo;전달&amp;rdquo;로 옮긴다는 점이다.&lt;/p&gt;
&lt;p data-end=&quot;6363&quot; data-start=&quot;6291&quot; data-ke-size=&quot;size16&quot;&gt;지금까지 많은 AI 코딩 도구는 &amp;ldquo;얼마나 코드를 잘 생성하는가&amp;rdquo;에 집중했다. 그러나 실제 개발 현장에서 더 중요한 질문은 다르다.&lt;/p&gt;
&lt;p data-end=&quot;6492&quot; data-start=&quot;6365&quot; data-ke-size=&quot;size16&quot;&gt;이 기능이 요구사항을 충족했는가?&lt;br /&gt;검증했는가?&lt;br /&gt;실패했을 때 다시 고쳤는가?&lt;br /&gt;다음 사람이 이어받을 수 있는가?&lt;br /&gt;중간에 세션이 끊겨도 복구할 수 있는가?&lt;br /&gt;사용한 에이전트가 바뀌어도 같은 맥락에서 이어갈 수 있는가?&lt;/p&gt;
&lt;p data-end=&quot;6516&quot; data-start=&quot;6494&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 이 질문들에 답하려는 시도다.&lt;/p&gt;
&lt;p data-end=&quot;6637&quot; data-start=&quot;6518&quot; data-ke-size=&quot;size16&quot;&gt;[Inference] 앞으로 AI 코딩 도구의 경쟁력은 단순한 코드 생성 능력보다, 이런 전달 루프를 얼마나 안정적으로 설계하느냐로 이동할 가능성이 크다. Loom은 그 방향을 비교적 명확하게 보여주는 프로젝트다.&lt;/p&gt;
&lt;h2 data-end=&quot;6644&quot; data-start=&quot;6639&quot; data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-end=&quot;6726&quot; data-start=&quot;6646&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 &amp;ldquo;AI 코딩 에이전트를 더 똑똑하게 만드는 도구&amp;rdquo;라기보다, &lt;b&gt;AI 코딩 에이전트가 일을 끝까지 하게 만드는 운영 체계&lt;/b&gt;에 가깝다.&lt;/p&gt;
&lt;p data-end=&quot;6813&quot; data-start=&quot;6728&quot; data-ke-size=&quot;size16&quot;&gt;코드는 AI가 쓴다.&lt;br /&gt;하지만 요구사항을 보존하고, 작업을 나누고, 검증하고, 실패를 복구하고, 다음 세션으로 이어주는 것은 별도의 시스템이 필요하다.&lt;/p&gt;
&lt;p data-end=&quot;6843&quot; data-start=&quot;6815&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 그 시스템을 오픈소스로 만들려는 시도다.&lt;/p&gt;
&lt;p data-end=&quot;7046&quot; data-start=&quot;6845&quot; data-ke-size=&quot;size16&quot;&gt;아직 초기 단계이고, production deployment 같은 영역은 미완성이다. 그럼에도 AI 기반 개발 자동화를 진지하게 고민하는 개발자라면 살펴볼 가치가 있다. 특히 Claude Code, Codex, OpenCode를 단순한 &amp;ldquo;코딩 도우미&amp;rdquo;가 아니라 &amp;ldquo;소프트웨어 전달 파이프라인의 일부&amp;rdquo;로 쓰고 싶다면 Loom의 접근 방식은 꽤 중요한 힌트를 준다.&lt;/p&gt;
&lt;hr data-end=&quot;7051&quot; data-start=&quot;7048&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;7061&quot; data-start=&quot;7053&quot; data-ke-size=&quot;size26&quot;&gt;짧은 요약&lt;/h2&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;7457&quot; data-start=&quot;7063&quot; data-ke-size=&quot;size16&quot;&gt;Loom은 Claude Code, Codex, OpenCode 같은 AI 코딩 에이전트를 위한 오픈소스 delivery harness다. 단순히 코드를 생성하는 것이 아니라, 요구사항 확인, 계획, 작업 분해, 구현, 검증, 수리, 미리보기, 인수인계까지 이어지는 반복 가능한 전달 루프를 만든다. .loom/에 프로젝트 상태와 작업 증거를 저장하고, @loom continue 또는 /loom continue 같은 명령으로 중단된 작업을 이어갈 수 있다. 공개 벤치마크에서는 Codex + Loom 조합이 Codex 단독 대비 15.8% 토큰을 절약했다고 제시되어 있다. 다만 현재 production 배포는 지원하지 않고, 로컬 Docker Compose 기반 미리보기와 검증 중심이다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;7457&quot; data-start=&quot;7063&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1782196055831&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - valkor-ai/loom: Loop engineering for agentic software delivery.&quot; data-og-description=&quot;Loop engineering for agentic software delivery. Contribute to valkor-ai/loom development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/valkor-ai/loom&quot; data-og-url=&quot;https://github.com/valkor-ai/loom&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fRtn1/dJMb86Pbzl4/zFxNLziKSBk13yVq1UBtOK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/LI5py/dJMb8VNFvUi/C8OIrWBM2hVzEk4k1CepU0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/BCBES/dJMb9efnLik/W9jCuJwlmZtLmVpSbbb1H0/img.png?width=1983&amp;amp;height=793&amp;amp;face=0_0_1983_793&quot;&gt;&lt;a href=&quot;https://github.com/valkor-ai/loom&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/valkor-ai/loom&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fRtn1/dJMb86Pbzl4/zFxNLziKSBk13yVq1UBtOK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/LI5py/dJMb8VNFvUi/C8OIrWBM2hVzEk4k1CepU0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/BCBES/dJMb9efnLik/W9jCuJwlmZtLmVpSbbb1H0/img.png?width=1983&amp;amp;height=793&amp;amp;face=0_0_1983_793');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - valkor-ai/loom: Loop engineering for agentic software delivery.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Loop engineering for agentic software delivery. Contribute to valkor-ai/loom development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI/추천 오픈소스</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1781</guid>
      <comments>https://javaexpert.tistory.com/1781#entry1781comment</comments>
      <pubDate>Tue, 23 Jun 2026 15:25:16 +0900</pubDate>
    </item>
    <item>
      <title>AI 코딩 에이전트가 코드를 너무 많이 쓴다면: Ponytail</title>
      <link>https://javaexpert.tistory.com/1780</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n6p23/dJMcahSjGAZ/1UwQG8HdNACqmy43TgzBO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n6p23/dJMcahSjGAZ/1UwQG8HdNACqmy43TgzBO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n6p23/dJMcahSjGAZ/1UwQG8HdNACqmy43TgzBO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn6p23%2FdJMcahSjGAZ%2F1UwQG8HdNACqmy43TgzBO0%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;1122&quot; height=&quot;1402&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 에이전트를 쓰다 보면 이상한 순간을 자주 만난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명히 간단한 기능을 부탁했는데, 에이전트는 갑자기 새로운 컴포넌트를 만들고, 유틸 파일을 추가하고, 추상화 계층을 만들고, 아직 필요하지도 않은 설정값까지 준비한다.&lt;br /&gt;사람 개발자라면 한 줄로 끝냈을 일을 AI는 &amp;ldquo;미래 확장성&amp;rdquo;이라는 이름으로 100줄짜리 구조로 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 정면으로 겨냥한 프로젝트가 &lt;b&gt;Ponytail&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail의 저장소 설명은 노골적이다.&lt;br /&gt;&amp;ldquo;AI 에이전트가 방 안에서 가장 게으른 시니어 개발자처럼 생각하게 만든다.&amp;rdquo;&lt;br /&gt;여기서 게으르다는 말은 대충 만든다는 뜻이 아니다. &lt;b&gt;안 만들어도 되는 코드는 만들지 않는 개발자&lt;/b&gt;에 가깝다. GitHub README에서도 Ponytail은 &amp;ldquo;가장 좋은 코드는 작성하지 않은 코드&amp;rdquo;라는 철학을 전면에 내세운다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/tree/main&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ponytail은 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 새로운 LLM 모델이 아니다.&lt;br /&gt;새로운 IDE도 아니다.&lt;br /&gt;코드를 직접 실행하는 별도의 자동화 서버도 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 말하면 Ponytail은 &lt;b&gt;AI 코딩 에이전트를 위한 스킬, 규칙, 플러그인 패키지&lt;/b&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code, Codex, OpenCode, Gemini CLI, Cursor, Windsurf, Cline, GitHub Copilot, Kiro 같은 여러 코딩 에이전트 환경에 &amp;ldquo;최소 구현 우선&amp;rdquo; 규칙을 주입한다. 프로젝트 문서에 따르면 핵심 동작은 skills/에 들어 있고, 각 에이전트별 파일은 이 핵심 규칙을 해당 도구가 읽을 수 있게 연결하는 어댑터 역할을 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/docs/agent-portability.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 이런 역할이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;AI야, 새로 만들기 전에 먼저 생각해.&lt;br /&gt;이 기능이 정말 필요한가?&lt;br /&gt;표준 라이브러리에 이미 있지 않은가?&lt;br /&gt;브라우저나 플랫폼 기본 기능으로 충분하지 않은가?&lt;br /&gt;이미 설치된 의존성으로 해결되지 않는가?&lt;br /&gt;한 줄로 끝낼 수 있지 않은가?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 AI에게 이 질문 순서를 강제로 떠올리게 만든다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ponytail의 핵심 철학: 게으르지만 무책임하지 않게&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail의 핵심 규칙은 매우 단순하다.&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;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;이 순서는 Ponytail 문서에서 &amp;ldquo;ladder&amp;rdquo;, 즉 사다리처럼 설명된다. 에이전트는 코드를 작성하기 전에 가장 위의 단계부터 확인하고, 해결 가능한 단계가 나오면 거기서 멈춰야 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/README.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 날짜 선택 기능이 필요하다고 해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 AI 에이전트는 date picker 라이브러리를 설치하고, React wrapper를 만들고, 스타일 파일을 만들고, 타임존 이야기를 시작할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail이 적용된 에이전트는 먼저 이렇게 생각한다.&lt;/p&gt;
&lt;pre class=&quot;fsharp&quot;&gt;&lt;code&gt;&amp;lt;input type=&quot;date&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저가 이미 지원하는 기능이면 굳이 새 컴포넌트를 만들 필요가 없다는 것이다. README도 날짜 선택기 예시에서 이 방향을 직접 보여준다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/tree/main&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 Ponytail이 &amp;ldquo;짧은 코드&amp;rdquo; 자체를 숭배하지 않는다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서에는 입력 검증, 데이터 손실 방지용 에러 처리, 보안, 접근성, 하드웨어 보정 같은 요소는 절대 줄이면 안 된다고 되어 있다. 즉 Ponytail이 추구하는 것은 코드 골프가 아니다. &lt;b&gt;필요 없는 코드를 없애되, 필요한 안전장치는 남기는 것&lt;/b&gt;이다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/skills/ponytail/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 이런 도구가 필요해졌나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 에이전트의 장점은 빠르게 코드를 만들어 준다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 바로 그 장점 때문에 문제가 생긴다.&lt;br /&gt;AI는 사람보다 코드를 쓰는 비용이 낮다. 몇 초 만에 파일을 여러 개 만들 수 있고, 수십 줄의 보일러플레이트도 부담 없이 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람 개발자는 귀찮아서라도 이렇게 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이거 그냥 기본 함수 쓰면 안 되나?&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 추상화 지금 꼭 필요해?&amp;rdquo;&lt;br /&gt;&amp;ldquo;설정 파일까지 만들 일인가?&amp;rdquo;&lt;br /&gt;&amp;ldquo;나중에 필요하면 그때 만들자.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 AI는 종종 &amp;ldquo;완성도 있어 보이는 구조&amp;rdquo;를 선호한다. 문제는 완성도 있어 보이는 구조가 실제로는 유지보수 비용을 늘린다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 바로 이 지점을 건드린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 더 많은 코드를 쓰게 하는 것이 아니라, &lt;b&gt;덜 만들고도 충분히 작동하는 선택지를 먼저 찾게 만드는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구조적으로 보면 Ponytail은 &amp;ldquo;에이전트 이식형 스킬 배포판&amp;rdquo;이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail의 재미있는 점은 단일 도구에 묶이지 않는다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장소에는 Claude Code용 플러그인, Codex용 플러그인, OpenCode용 플러그인, Gemini CLI 확장, Cursor/Windsurf/Cline용 규칙 파일, GitHub Copilot 지침 파일, Kiro steering 파일, AGENTS.md 등이 함께 들어 있다. GitHub 페이지의 파일 구조에서도 .claude-plugin, .codex-plugin, .cursor/rules, .windsurf/rules, .clinerules, .kiro/steering, skills, commands, hooks 같은 폴더가 확인된다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/tree/main&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조가 의미하는 바는 크다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 특정 AI 에이전트 하나를 위한 팁 모음이 아니다.&lt;br /&gt;AI 코딩 에이전트들이 공통으로 받아들일 수 있는 &lt;b&gt;작업 철학 패키지&lt;/b&gt;에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 규칙은 skills/ponytail/SKILL.md와 AGENTS.md에 들어 있고, 각 도구별 어댑터가 그것을 자기 환경에 맞게 불러온다. 문서에서는 &amp;ldquo;어댑터는 얇게 유지하고, 가능한 기존 skills와 hooks를 가리키라&amp;rdquo;고 설명한다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/docs/agent-portability.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점은 앞으로 AI 개발 환경에서 중요해질 가능성이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자는 더 이상 &amp;ldquo;어떤 모델을 쓰느냐&amp;rdquo;만 고민하지 않는다.&lt;br /&gt;이제는 &lt;b&gt;에이전트에게 어떤 개발 습관을 지속적으로 주입할 것인가&lt;/b&gt;가 중요해지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 그 습관 중 하나를 매우 선명하게 정의한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주요 명령어&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 단순한 규칙 파일만 제공하지 않는다. 스킬 지원이 되는 호스트에서는 명령어도 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;README에 따르면 주요 명령은 다음과 같다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/README.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;/ponytail [lite | full | ultra | off]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail의 강도를 조절한다.&lt;br /&gt;기본값은 full이다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/ponytail-review
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 diff에서 과잉 구현된 부분을 찾아준다.&lt;br /&gt;목표는 &amp;ldquo;무엇을 더할까&amp;rdquo;가 아니라 &amp;ldquo;무엇을 지울 수 있을까&amp;rdquo;다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/ponytail-audit
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 변경분이 아니라 전체 저장소 기준으로 과잉 설계를 점검한다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/ponytail-debt
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ponytail: 주석으로 남긴 의도적 단순화, 임시 선택, 나중에 확장할 지점을 모아서 관리한다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/ponytail-gain
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트가 공개한 벤치마크 기반으로 코드량, 비용, 속도 개선 수치를 보여주는 명령이다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;/ponytail-help
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어 도움말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 /ponytail-review는 실무적으로 유용해 보인다.&lt;br /&gt;일반 코드 리뷰가 correctness, security, performance를 본다면, Ponytail review는 오직 &amp;ldquo;이 코드가 불필요하게 복잡한가&amp;rdquo;만 본다. 스킬 문서에서도 이 리뷰의 범위는 과잉 설계와 복잡도에 한정되며, 보안 구멍이나 correctness 문제는 일반 리뷰로 넘기라고 명시한다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/skills/ponytail-review/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ponytail이 주장하는 성능 개선&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Unverified] Ponytail README는 자체 벤치마크 결과를 공개하고 있다. 프로젝트 측 설명에 따르면, 실제 Claude Code 세션에서 FastAPI + React 오픈소스 저장소를 수정하게 하고, Ponytail 적용 전후의 git diff를 비교했다. 조건은 Haiku 4.5, 12개 기능 작업, 각 작업 n=4였다고 설명한다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/tree/main&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트가 공개한 평균 결과는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교 기준Ponytail 결과&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;추가 코드 라인&lt;/td&gt;
&lt;td&gt;-54%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;토큰&lt;/td&gt;
&lt;td&gt;-22%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비용&lt;/td&gt;
&lt;td&gt;-20%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;시간&lt;/td&gt;
&lt;td&gt;-27%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;안전성 테스트&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;README에는 Ponytail이 no-skill baseline 대비 LOC, token, cost, time을 모두 줄였고, 안전성 기준도 유지했다고 적혀 있다. 다만 이 수치는 프로젝트가 공개한 자체 벤치마크이며, 외부 독립 검증 결과로 보면 안 된다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/README.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흥미로운 예시는 date picker와 color picker다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 측 벤치마크 문서에 따르면, date picker 작업에서 baseline은 평균 404줄을 만들었고 Ponytail은 23줄을 만들었다. color picker도 baseline 287줄, Ponytail 23줄로 측정되었다. 이유는 단순하다. baseline은 커스텀 컴포넌트를 만들었고, Ponytail은 브라우저 기본 input을 먼저 선택했다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/blob/main/benchmarks/results/2026-06-18-agentic.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 backend CRUD처럼 원래부터 줄일 여지가 작은 작업에서는 차이가 거의 없었다고 문서가 설명한다. 이 지점이 오히려 중요하다. Ponytail은 모든 코드를 마법처럼 줄이는 도구가 아니라, &lt;b&gt;과잉 구현이 발생하기 쉬운 지점에서 효과가 커지는 도구&lt;/b&gt;에 가깝다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/blob/main/benchmarks/results/2026-06-18-agentic.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;단순히 &amp;ldquo;짧게 써&amp;rdquo;라고 말하는 것과 무엇이 다른가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 보면 이런 생각이 든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;그냥 프롬프트에 YAGNI 원칙을 따르고 한 줄을 선호하라고 쓰면 되는 것 아닌가?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail 벤치마크 문서는 이 질문을 직접 다룬다. 비교군에는 &amp;ldquo;YAGNI + one-liners&amp;rdquo; 짧은 프롬프트도 들어 있었다. 프로젝트 측 결과에 따르면 이 짧은 프롬프트는 일부 작업에서는 잘 작동했지만, 작업에 따라 일관성이 떨어졌고 안전성 테스트에서 한 번 guard를 놓쳤다고 설명한다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/blob/main/benchmarks/results/2026-06-18-agentic.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Ponytail의 차별점은 세 가지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 단순히 짧게 쓰라는 지시가 아니라 &lt;b&gt;판단 순서&lt;/b&gt;를 제공한다.&lt;br /&gt;필요성 &amp;rarr; 표준 라이브러리 &amp;rarr; 플랫폼 기본 기능 &amp;rarr; 기존 의존성 &amp;rarr; 한 줄 &amp;rarr; 최소 구현이라는 순서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, &lt;b&gt;줄이면 안 되는 영역&lt;/b&gt;을 명확히 정한다.&lt;br /&gt;입력 검증, 보안, 접근성, 데이터 손실 방지, 하드웨어 보정은 &amp;ldquo;게으름&amp;rdquo;의 대상이 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 여러 에이전트 환경에 지속적으로 적용할 수 있다.&lt;br /&gt;한 번 프롬프트에 쓰고 끝나는 방식이 아니라, 플러그인&amp;middot;스킬&amp;middot;규칙 파일 형태로 세션과 프로젝트에 붙인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이가 Ponytail을 단순 프롬프트 팁이 아니라 &amp;ldquo;AI 개발 워크플로우 규칙 세트&amp;rdquo;로 보게 만드는 부분이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 사용하는 에이전트에 따라 설치 방식이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code에서는 README 기준으로 다음 명령을 사용한다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/README.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/plugin marketplace add DietrichGebert/ponytail
/plugin install ponytail@ponytail
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex에서는 다음 방식이 제시되어 있다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/README.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;codex plugin marketplace add DietrichGebert/ponytail
codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 뒤 /plugins에서 Ponytail marketplace를 선택해 설치하고, /hooks에서 lifecycle hook을 확인하고 trust한 뒤 새 thread를 시작하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cursor, Windsurf, Cline, GitHub Copilot editor, Aider, Kiro, Zed, CodeWhale 같은 환경은 완전한 명령어 플러그인 방식이 아니라, 각 도구가 읽을 수 있는 규칙 파일을 복사해 사용하는 형태에 가깝다. README는 .cursor/rules, .windsurf/rules, .clinerules, .github/copilot-instructions.md, AGENTS.md, .kiro/steering 등을 언급한다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/README.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 Ponytail은 크게 두 층으로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나는 &lt;b&gt;풀 플러그인 모드&lt;/b&gt;다.&lt;br /&gt;Claude Code, Codex, OpenCode, Gemini CLI처럼 명령어와 hook을 지원하는 환경에서 쓸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 하나는 &lt;b&gt;instruction-only 모드&lt;/b&gt;다.&lt;br /&gt;Cursor, Windsurf, Copilot editor처럼 프로젝트 규칙 파일을 읽는 도구에 Ponytail 규칙을 넣는 방식이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실무에서 어디에 쓸 수 있을까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail이 특히 잘 맞는 상황은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, &lt;b&gt;AI 에이전트로 MVP를 빠르게 만들 때&lt;/b&gt;다.&lt;br /&gt;MVP에서 가장 위험한 것은 기능이 부족한 것이 아니라, 검증되지 않은 아이디어에 과한 구조를 먼저 얹는 것이다. Ponytail은 &amp;ldquo;일단 필요한 만큼만 만들자&amp;rdquo;는 방향을 유지하게 해 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, &lt;b&gt;프론트엔드 컴포넌트 과잉 생성을 줄일 때&lt;/b&gt;다.&lt;br /&gt;날짜 선택, 색상 선택, 파일 업로드, 기본 폼 입력처럼 브라우저 기본 기능이 있는 영역에서 AI는 종종 불필요한 커스텀 컴포넌트를 만든다. Ponytail은 이런 작업에서 native feature를 먼저 검토하게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, &lt;b&gt;레거시 코드베이스 리팩터링 전에 삭제 후보를 찾을 때&lt;/b&gt;다.&lt;br /&gt;/ponytail-audit나 /ponytail-review는 &amp;ldquo;무엇을 고칠까&amp;rdquo;보다 &amp;ldquo;무엇을 지울까&amp;rdquo;에 초점을 맞춘다. 기능 추가보다 코드 축소가 먼저 필요한 팀에 맞다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, &lt;b&gt;개인 개발자가 AI 코딩 도구를 쓸 때 기본 습관으로 붙이기 좋다&lt;/b&gt;.&lt;br /&gt;AI에게 매번 &amp;ldquo;간단하게 해줘&amp;rdquo;, &amp;ldquo;과하게 만들지 마&amp;rdquo;라고 말하는 대신, 프로젝트 규칙으로 상시 적용할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;하지만 Ponytail을 맹신하면 안 된다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail의 방향은 좋지만, 모든 상황에서 정답은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 요구사항이 이미 명확한 서비스, 보안&amp;middot;금융&amp;middot;의료처럼 규제가 강한 도메인, 장기적으로 확장될 아키텍처를 설계해야 하는 상황에서는 &amp;ldquo;최소 구현&amp;rdquo;이 오히려 부족할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail 문서도 안전성을 완전히 증명한다고 주장하지는 않는다. 벤치마크 문서는 한 모델, 제한된 작업 수, deterministic safety check라는 한계를 직접 적고 있다. 특히 안전성 테스트는 특정 guard를 놓치는지 보는 수준이지, 전체 보안을 증명하는 것은 아니다. (&lt;a href=&quot;https://github.com/DietrichGebert/ponytail/blob/main/benchmarks/results/2026-06-18-agentic.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Ponytail은 &amp;ldquo;AI가 짧게 만들었으니 안전하다&amp;rdquo;는 보증 장치가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 위치는 이렇다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 AI 코딩 에이전트의 과잉 구현 성향을 줄이는 규칙 세트다.&lt;br /&gt;하지만 최종 설계 판단, 보안 검토, 비즈니스 요구사항 검증은 여전히 사람의 몫이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개발팀에 적용한다면 이렇게 쓰는 것이 좋다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 단위로 Ponytail을 도입한다면 처음부터 전체 코드베이스에 무작정 적용하기보다 다음 순서가 적절하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1단계는 개인 개발 환경에서 적용하는 것이다.&lt;br /&gt;Claude Code나 Codex를 쓰는 개발자가 자기 작업 branch에서 Ponytail을 켜고, 생성되는 diff가 실제로 줄어드는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2단계는 PR 리뷰 보조로 쓰는 것이다.&lt;br /&gt;/ponytail-review를 사용해 &amp;ldquo;삭제 가능한 코드&amp;rdquo;, &amp;ldquo;표준 라이브러리로 대체 가능한 코드&amp;rdquo;, &amp;ldquo;native feature로 충분한 코드&amp;rdquo;를 찾는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3단계는 팀 컨벤션으로 정리하는 것이다.&lt;br /&gt;&amp;ldquo;새 의존성을 추가하기 전에 표준 라이브러리와 플랫폼 기능을 먼저 검토한다&amp;rdquo;, &amp;ldquo;한 구현체뿐인 interface는 만들지 않는다&amp;rdquo;, &amp;ldquo;추상화는 두 번째 사례가 생긴 뒤 만든다&amp;rdquo; 같은 규칙으로 문서화할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4단계는 예외 기준을 명확히 하는 것이다.&lt;br /&gt;보안, 접근성, 데이터 손실 방지, 명시 요구사항, 테스트 가능한 핵심 로직은 줄이지 않는다는 기준이 필요하다. Ponytail 자체도 이 영역은 lazy 대상이 아니라고 명시한다. (&lt;a href=&quot;https://raw.githubusercontent.com/DietrichGebert/ponytail/main/skills/ponytail/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ponytail이 보여주는 더 큰 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 작은 프로젝트처럼 보이지만, AI 개발 도구의 중요한 변화를 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 AI 코딩 도구의 관심은 &amp;ldquo;얼마나 많은 코드를 생성할 수 있는가&amp;rdquo;였다.&lt;br /&gt;이제 관심은 조금씩 바뀌고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;얼마나 적절한 코드를 생성하는가.&amp;rdquo;&lt;br /&gt;&amp;ldquo;얼마나 불필요한 코드를 만들지 않는가.&amp;rdquo;&lt;br /&gt;&amp;ldquo;기존 플랫폼 기능을 얼마나 잘 활용하는가.&amp;rdquo;&lt;br /&gt;&amp;ldquo;사람 개발자의 유지보수 감각을 얼마나 잘 흉내 내는가.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 이 흐름의 상징적인 사례다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 코드를 많이 쓰는 시대에는 역설적으로 &lt;b&gt;코드를 덜 쓰게 만드는 기술&lt;/b&gt;이 필요해진다.&lt;br /&gt;그리고 그 방향은 단순히 &amp;ldquo;짧게 작성하라&amp;rdquo;가 아니다.&lt;br /&gt;필요성, 표준 기능, 플랫폼 기능, 기존 의존성, 안전장치 사이에서 올바른 우선순위를 잡는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론: Ponytail은 AI 시대의 YAGNI 엔진이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail을 한 문장으로 정리하면 이렇게 말할 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 에이전트에게 YAGNI, 표준 라이브러리 우선, native feature 우선, 최소 diff 우선이라는 시니어 개발자의 습관을 주입하는 스킬 세트.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트의 가치는 &amp;ldquo;코드를 줄인다&amp;rdquo;는 숫자 자체에만 있지 않다.&lt;br /&gt;더 중요한 가치는 AI 에이전트에게 &lt;b&gt;무엇을 만들지 않을지 판단하게 만드는 방식&lt;/b&gt;에 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 개발 시대에는 누구나 빠르게 코드를 만들 수 있다.&lt;br /&gt;그래서 앞으로 더 중요한 능력은 &amp;ldquo;빨리 만드는 능력&amp;rdquo;이 아니라 &amp;ldquo;안 만들어도 되는 것을 구분하는 능력&amp;rdquo;이 될 가능성이 크다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ponytail은 바로 그 능력을 AI 에이전트에게 이식하려는 시도다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 시도는 꽤 현실적인 문제를 건드린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 코드를 너무 많이 쓰는 시대.&lt;br /&gt;어쩌면 우리에게 필요한 것은 더 강한 코딩 에이전트가 아니라, 더 게으른 시니어 개발자의 감각일지도 모른다.&lt;/p&gt;</description>
      <category>AI/추천 오픈소스</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1780</guid>
      <comments>https://javaexpert.tistory.com/1780#entry1780comment</comments>
      <pubDate>Fri, 19 Jun 2026 10:56:52 +0900</pubDate>
    </item>
    <item>
      <title>Codex의 Computer use 사용법 3가지</title>
      <link>https://javaexpert.tistory.com/1779</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Computer Use, Chrome, Browser는 언제 어떻게 써야 할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 코드를 짜는 시대는 이미 익숙해졌다.&lt;br /&gt;그런데 이제 중요한 질문은 조금 달라졌다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;AI가 코드를 쓰는 것을 넘어, 실제 컴퓨터 화면을 보고 조작할 수 있다면 무엇이 달라질까?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI Codex에는 컴퓨터를 다루는 방식이 여러 가지 있다.&lt;br /&gt;겉으로 보면 비슷해 보인다. 모두 웹사이트를 열 수 있고, 화면을 볼 수 있고, 사용자를 대신해 작업할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 실제로는 목적이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex가 컴퓨터를 사용하는 대표적인 방식은 크게 세 가지다.&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;Computer Use&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Chrome Extension&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;In-app Browser&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 추가로 &lt;b&gt;Appshots&lt;/b&gt;라는 기능이 있다.&lt;br /&gt;Appshots는 Codex가 직접 조작하는 도구라기보다, 사용자가 보고 있는 화면을 Codex에게 &amp;ldquo;이거 봐&amp;rdquo; 하고 보여주는 방식에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 세 가지 방식의 차이와 실제 활용법을 정리해본다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Computer Use: 가장 넓은 범위의 컴퓨터 조작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Computer Use&lt;/b&gt;는 세 가지 중 가장 넓은 조작 범위를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex가 macOS나 Windows의 그래픽 인터페이스를 보고, 창을 열고, 메뉴를 누르고, 키보드 입력을 하고, 클립보드를 사용할 수 있게 해주는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 사용자가 허용한 앱 안에서 Codex가 사람처럼 컴퓨터를 조작하는 것이다.&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;Spotify 같은 데스크톱 앱 조작&lt;/li&gt;
&lt;li&gt;Xcode나 iOS 시뮬레이터 테스트&lt;/li&gt;
&lt;li&gt;iPhone Mirroring을 통한 모바일 앱 확인&lt;/li&gt;
&lt;li&gt;시스템 설정 변경 확인&lt;/li&gt;
&lt;li&gt;API가 없는 금융 앱, 업무 앱, 내부 프로그램 사용&lt;/li&gt;
&lt;li&gt;여러 앱을 오가야 하는 복합 워크플로우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Computer Use의 장점은 명확하다.&lt;br /&gt;API나 플러그인이 없는 앱도 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 단점도 있다.&lt;br /&gt;화면을 보고, 클릭하고, 반응을 기다리고, 다시 화면을 확인하는 방식이기 때문에 구조화된 API 호출보다 느리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 GitHub 플러그인이 있다면 GitHub 웹사이트를 눈으로 보며 클릭하는 것보다 플러그인을 쓰는 편이 더 정확하고 검토하기 쉽다. Slack 스레드를 읽는 것도 마찬가지다. Slack 플러그인이 있다면 화면을 클릭하는 것보다 API 기반으로 가져오는 편이 낫다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 기본 원칙은 이렇다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조화된 도구가 있으면 먼저 그것을 쓰고, 화면 조작은 마지막 경계에서 쓴다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Computer Use는 &amp;ldquo;사람만 할 수 있던 GUI 작업&amp;rdquo;에 강하다.&lt;br /&gt;하지만 사용자의 컴퓨터를 넓게 다룰 수 있는 만큼 신뢰 경계도 넓다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 계정, 결제, 금융, 개인정보, 보안 설정과 관련된 작업은 사용자가 직접 확인하는 절차를 두는 것이 좋다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Chrome Extension: 로그인된 브라우저 상태가 필요할 때&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 방식은 &lt;b&gt;Codex Chrome Extension&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 사용자의 로그인된 Chrome 상태를 사용할 수 있다는 점이 핵심이다.&lt;br /&gt;쿠키, 계정 세션, 브라우저 프로필, 열려 있는 탭 등이 필요한 작업에 적합하다.&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;Gmail 확인&lt;/li&gt;
&lt;li&gt;LinkedIn 메시지 확인&lt;/li&gt;
&lt;li&gt;Salesforce나 고객지원 콘솔 사용&lt;/li&gt;
&lt;li&gt;사내 대시보드 접근&lt;/li&gt;
&lt;li&gt;로그인된 상태에서 여러 사이트를 오가며 리서치&lt;/li&gt;
&lt;li&gt;브라우저 확장 프로그램이 필요한 폼 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Computer Use도 브라우저를 조작할 수는 있다.&lt;br /&gt;하지만 Chrome Extension은 브라우저 작업을 더 자연스럽게 이해한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 여러 탭을 다루는 작업에 유리하다.&lt;br /&gt;예를 들어 한 탭에는 고객 계정 페이지가 있고, 다른 탭에는 고객지원 티켓이 있고, 또 다른 탭에는 내부 문서가 열려 있다고 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 Chrome Extension은 같은 작업에 필요한 여러 탭을 묶어 비교하고, 필요한 정보를 찾아서 정리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 프롬프트는 이런 식이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Chrome을 사용해서 열린 고객 계정 페이지와 다른 탭의 지원 티켓을 비교하고, 누락된 필드를 초안으로 작성해줘. 제출은 하지 마.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 부분은 마지막 문장이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;ldquo;제출은 하지 마.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Chrome Extension은 사용자의 로그인 상태로 동작한다.&lt;br /&gt;즉, Codex가 클릭하는 버튼이나 작성하는 메시지는 웹사이트 입장에서는 사용자가 직접 한 행동처럼 보일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 자동화의 경계를 명확히 해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조사하기&lt;/li&gt;
&lt;li&gt;비교하기&lt;/li&gt;
&lt;li&gt;정리하기&lt;/li&gt;
&lt;li&gt;초안 작성하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지는 자동화하기 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 다음 작업은 사용자의 확인을 거치는 편이 안전하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보내기&lt;/li&gt;
&lt;li&gt;게시하기&lt;/li&gt;
&lt;li&gt;결제하기&lt;/li&gt;
&lt;li&gt;제출하기&lt;/li&gt;
&lt;li&gt;계정 설정 변경하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Chrome Extension은 &amp;ldquo;로그인된 웹 업무&amp;rdquo;에 가장 적합한 표면이다.&lt;br /&gt;작업 전체가 브라우저 안에서 끝난다면 Computer Use보다 Chrome을 먼저 고려하는 것이 좋다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. In-app Browser: 내가 만들고 있는 웹사이트를 테스트할 때&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 방식은 &lt;b&gt;In-app Browser&lt;/b&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 Codex 앱 안에 들어 있는 브라우저다.&lt;br /&gt;사용자와 Codex가 같은 렌더링 화면을 보면서 작업할 수 있다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로컬 개발 서버 확인&lt;/li&gt;
&lt;li&gt;Vite, Next.js, React 앱 테스트&lt;/li&gt;
&lt;li&gt;로그인 없는 공개 페이지 확인&lt;/li&gt;
&lt;li&gt;반응형 레이아웃 점검&lt;/li&gt;
&lt;li&gt;시각적 버그 재현&lt;/li&gt;
&lt;li&gt;특정 요소에 디자인 피드백 남기기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In-app Browser의 핵심 특징은 &lt;b&gt;격리&lt;/b&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 Chrome 프로필을 쓰지 않는다.&lt;br /&gt;쿠키, 로그인 세션, 확장 프로그램, 기존 탭을 공유하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 단점이기도 하고 장점이기도 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인이 필요한 서비스에는 부적합하다.&lt;br /&gt;Google 로그인, 패스키, 브라우저 확장 프로그램 의존성이 있는 페이지라면 Chrome Extension이 더 맞다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 개발 중인 웹앱을 테스트할 때는 오히려 좋다.&lt;br /&gt;불필요한 계정 상태나 확장 프로그램의 영향을 덜 받기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 프롬프트는 이렇게 쓸 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Browser로 localhost:3000을 열고 모바일 화면에서 overflow 버그를 재현해줘. 수정한 뒤 데스크톱과 모바일 화면에서 다시 확인해줘.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식의 장점은 피드백 루프가 짧다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex가 코드를 수정한다.&lt;br /&gt;브라우저에서 결과를 본다.&lt;br /&gt;스크린샷을 확인한다.&lt;br /&gt;다시 코드를 고친다.&lt;br /&gt;다시 렌더링을 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 한 스레드 안에서 반복할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 디자인 작업에서 유용하다.&lt;br /&gt;텍스트로 &amp;ldquo;좀 더 깔끔하게 해줘&amp;rdquo;라고 말하는 것보다, 실제 화면의 특정 영역을 클릭하고 &amp;ldquo;여기 계층이 이상해&amp;rdquo;, &amp;ldquo;이 카드 느낌을 줄여줘&amp;rdquo;, &amp;ldquo;이 버튼 간격을 넓혀줘&amp;rdquo;라고 남기는 편이 훨씬 정확하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 화면 자체가 요구사항 문서가 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Appshots: 조작 도구가 아니라 &amp;ldquo;가리키는 도구&amp;rdquo;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Appshots는 Computer Use, Chrome, Browser와 조금 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 세 가지가 Codex가 무언가를 조작하는 방식이라면, Appshots는 사용자가 보고 있는 화면을 Codex에게 전달하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mac에서는 특정 단축키로 현재 앞에 있는 창을 캡처해 Codex 스레드에 첨부할 수 있다.&lt;br /&gt;이미지와 가능한 텍스트 정보가 함께 전달된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 상황에서 유용하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;에러 메시지를 보여줄 때&lt;/li&gt;
&lt;li&gt;이메일 내용을 설명할 때&lt;/li&gt;
&lt;li&gt;디자인 화면을 보여줄 때&lt;/li&gt;
&lt;li&gt;설정 패널을 보여줄 때&lt;/li&gt;
&lt;li&gt;익숙하지 않은 입력 폼을 분석시킬 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 이렇게 볼 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Appshots는 &amp;ldquo;이걸 봐&amp;rdquo;라고 가리키는 방식이고,&lt;br /&gt;Browser, Chrome, Computer Use는 &amp;ldquo;이걸 처리해&amp;rdquo;라고 맡기는 방식이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Appshots는 특히 맥락 전달에 좋다.&lt;br /&gt;전체 데스크톱을 열어주는 것이 아니라 현재 창 중심으로 보여줄 수 있기 때문에 비교적 좁은 범위의 컨텍스트를 전달할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;세 가지 방식은 어떻게 구분하면 될까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서는 다음 기준으로 선택하면 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. API나 플러그인이 있으면 먼저 그것을 쓴다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 좋은 자동화는 화면 클릭이 아니라 구조화된 도구 호출이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Slack 메시지를 읽어야 한다면 Slack 플러그인이나 MCP가 더 낫다.&lt;br /&gt;GitHub 작업을 해야 한다면 GitHub 플러그인이 더 낫다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 간단하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;더 빠르다&lt;/li&gt;
&lt;li&gt;더 정확하다&lt;/li&gt;
&lt;li&gt;결과를 검토하기 쉽다&lt;/li&gt;
&lt;li&gt;실패 지점을 파악하기 쉽다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면 조작은 구조화된 도구가 닿지 않는 마지막 구간에서 쓰는 것이 좋다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 데스크톱 앱이면 Computer Use&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 대상이 브라우저 밖이라면 Computer Use가 맞다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 Spotify 앱을 열거나, Xcode를 조작하거나, iOS 시뮬레이터에서 버그를 재현해야 한다면 Computer Use를 쓰는 것이 자연스럽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 범위가 넓기 때문에 한 번에 너무 많은 권한을 주기보다, 하나의 앱 또는 하나의 흐름으로 좁혀서 맡기는 것이 좋다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 로그인된 웹 업무면 Chrome&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gmail, LinkedIn, Salesforce, 사내 관리자 페이지처럼 로그인 상태가 필요한 웹 작업은 Chrome Extension이 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 여러 탭을 비교해야 하는 업무라면 Chrome이 강하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 로그인된 상태로 행동하는 만큼, 자동 제출이나 자동 전송은 주의해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 지시 방식은 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조사하고, 비교하고, 초안까지 작성해줘.&lt;br /&gt;하지만 보내기, 제출, 결제는 하지 마.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 웹앱 개발과 UI 디버깅은 In-app Browser&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 만들고 있는 웹사이트를 열어보고, 버그를 재현하고, 레이아웃을 점검하고, 디자인 피드백을 반영해야 한다면 In-app Browser가 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 로컬 서버와 궁합이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자는 &amp;ldquo;코드를 고치고 &amp;rarr; 화면을 확인하고 &amp;rarr; 다시 수정하는&amp;rdquo; 반복 작업을 많이 한다.&lt;br /&gt;In-app Browser는 이 루프를 Codex 안으로 가져온다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실무 프롬프트 예시&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Computer Use 예시&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Computer를 사용해서 Spotify를 열고 Discover Weekly 플레이리스트를 찾아 재생해줘. 계정 설정이나 구독 설정은 변경하지 마.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Chrome 예시&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Chrome을 사용해서 열린 고객 계정 페이지와 지원 티켓을 비교해줘. 누락된 정보를 정리하고 입력 초안을 만들어줘. 제출은 하지 마.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;In-app Browser 예시&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Browser로 localhost:3000을 열고 모바일 화면에서 레이아웃이 깨지는 부분을 찾아줘. 수정 후 모바일과 데스크톱 화면에서 다시 검증해줘.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Appshots 예시&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 에러 화면을 보고 원인을 분석해줘. 가능한 해결 순서를 알려줘.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심은 &amp;ldquo;가장 좁은 표면&amp;rdquo;을 선택하는 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트에게 많은 권한을 주는 것이 항상 좋은 것은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오히려 중요한 원칙은 반대다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 만큼만 보여주고, 필요한 만큼만 조작하게 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 안에서 끝나는 일이라면 Computer Use까지 열 필요가 없다.&lt;br /&gt;로그인이 필요 없는 개발 테스트라면 Chrome 프로필을 쓸 필요가 없다.&lt;br /&gt;API로 가능한 일이라면 화면 클릭을 시킬 필요가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 원칙을 지키면 자동화는 더 빠르고, 더 안전하고, 더 검토 가능해진다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리: Codex는 코딩 도구를 넘어 작업 표면을 다루는 에이전트가 되고 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지의 AI 코딩 도구는 주로 코드 편집기 안에서 일했다.&lt;br /&gt;파일을 읽고, 코드를 고치고, 테스트를 실행하는 방식이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Computer Use, Chrome Extension, In-app Browser가 결합되면 Codex의 역할은 달라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Codex는 코드만 보는 것이 아니라, 실제 앱 화면과 브라우저, 로컬 개발 서버, 로그인된 업무 도구까지 연결해 작업할 수 있다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데스크톱 앱은 &lt;b&gt;Computer Use&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;로그인된 웹 업무는 &lt;b&gt;Chrome&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;웹앱 개발과 UI 디버깅은 &lt;b&gt;In-app Browser&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;현재 보고 있는 화면을 전달할 때는 &lt;b&gt;Appshots&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;API나 플러그인이 있으면 먼저 &lt;b&gt;구조화된 도구&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구분만 명확히 해도 Codex를 훨씬 안정적으로 활용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트 시대의 생산성은 단순히 &amp;ldquo;프롬프트를 잘 쓰는 능력&amp;rdquo;에서 끝나지 않는다.&lt;br /&gt;이제는 어떤 작업을 어떤 표면에 맡길지 설계하는 능력이 중요해지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex를 잘 쓰는 사람은 단순히 명령을 잘 내리는 사람이 아니다.&lt;br /&gt;작업의 경계, 권한의 범위, 검토 지점을 설계할 줄 아는 사람이다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1779</guid>
      <comments>https://javaexpert.tistory.com/1779#entry1779comment</comments>
      <pubDate>Wed, 17 Jun 2026 12:04:29 +0900</pubDate>
    </item>
    <item>
      <title>[OpenHands] 자율 AI 에이전트</title>
      <link>https://javaexpert.tistory.com/1778</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4MNUH/dJMcabEzbzy/XFQKZhReQZ0KIWqzuwT04K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4MNUH/dJMcabEzbzy/XFQKZhReQZ0KIWqzuwT04K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4MNUH/dJMcabEzbzy/XFQKZhReQZ0KIWqzuwT04K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4MNUH%2FdJMcabEzbzy%2FXFQKZhReQZ0KIWqzuwT04K%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;1122&quot; height=&quot;1402&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 개발자 도구의 흐름은 빠르게 바뀌고 있다.&lt;br /&gt;처음에는 AI가 코드 한 줄을 자동완성해 주는 수준이었다. 그다음에는 채팅창에 물어보면 함수나 컴포넌트를 만들어 주는 수준으로 발전했다. 그런데 이제는 한 단계 더 나아가고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 버그 고쳐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이슈 보고 원인 찾아서 PR 만들어줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;레거시 코드를 리팩터링해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;테스트 깨지는 이유를 찾아줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 요청을 AI에게 단순히 묻는 것이 아니라, 실제 개발 환경 안에서 실행하게 만드는 방향이다.&lt;br /&gt;OpenHands는 바로 이 흐름을 대표하는 오픈소스 프로젝트다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. OpenHands는 무엇인가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 AI 기반 소프트웨어 개발 에이전트 플랫폼이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면, ChatGPT나 Claude에게 코드 질문을 던지는 수준을 넘어, AI가 직접 개발 작업을 수행할 수 있도록 만든 도구다. OpenHands 에이전트는 코드베이스를 읽고, 파일을 수정하고, 터미널 명령을 실행하고, 필요하면 웹을 탐색하고, GitHub 이슈나 PR 흐름 안에서 작업할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 AI 코딩 도구가 &amp;ldquo;옆에서 도와주는 조수&amp;rdquo;에 가까웠다면, OpenHands는 &amp;ldquo;작업을 맡길 수 있는 주니어 개발자형 에이전트&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 여기서 중요한 전제가 있다.&lt;br /&gt;AI가 모든 개발을 완벽하게 대신한다는 뜻은 아니다. OpenHands의 핵심 가치는 &amp;ldquo;개발자의 판단을 없애는 것&amp;rdquo;이 아니라, 반복적이고 시간이 많이 드는 개발 작업을 에이전트에게 넘기고, 사람은 설계&amp;middot;검토&amp;middot;의사결정에 집중하게 만드는 데 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 왜 OpenHands가 주목받는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands가 흥미로운 이유는 단순히 &amp;ldquo;AI가 코드를 짜준다&amp;rdquo;는 데 있지 않다. 이미 그런 도구는 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 세 가지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, OpenHands는 오픈소스 기반이다.&lt;br /&gt;많은 AI 코딩 도구는 특정 회사의 모델, 특정 IDE, 특정 클라우드 환경에 강하게 묶여 있다. 반면 OpenHands는 오픈소스 프로젝트로 공개되어 있고, 개발자가 직접 구조를 보고 수정하고 확장할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 모델에 비교적 독립적인 구조를 지향한다.&lt;br /&gt;OpenHands는 Claude, OpenAI 계열 모델, Gemini, 오픈소스 모델 등 여러 LLM을 사용할 수 있는 방향으로 설계되어 있다. AI 모델 시장은 빠르게 변하기 때문에, 특정 모델 하나에 묶이지 않는 구조는 실무적으로 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 단순 채팅이 아니라 &amp;ldquo;실행 환경&amp;rdquo;을 포함한다.&lt;br /&gt;AI 개발 에이전트에서 가장 중요한 것은 말솜씨가 아니다. 실제 파일을 수정하고, 테스트를 돌리고, 에러 로그를 보고, 다시 고치고, 결과를 남길 수 있어야 한다. OpenHands는 이 실행 루프를 중심에 둔다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. OpenHands의 구성: SDK, CLI, GUI, Cloud&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 하나의 앱이라기보다 여러 층으로 구성된 플랫폼에 가깝다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) Software Agent SDK&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 핵심은 OpenHands Software Agent SDK다.&lt;br /&gt;이 SDK는 개발자가 직접 코드 안에서 소프트웨어 개발 에이전트를 만들 수 있게 해주는 Python/REST API 기반 도구다.&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;특정 저장소의 README를 자동 생성하는 에이전트&lt;/li&gt;
&lt;li&gt;의존성 업데이트를 자동으로 처리하는 에이전트&lt;/li&gt;
&lt;li&gt;대규모 리팩터링을 여러 단계로 나눠 수행하는 에이전트&lt;/li&gt;
&lt;li&gt;사내 개발 워크플로우에 맞춘 커스텀 코드 리뷰 에이전트&lt;/li&gt;
&lt;li&gt;OpenAI 호환 API 형태로 IDE나 내부 서비스에 붙이는 에이전트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, SDK는 OpenHands의 엔진이다.&lt;br /&gt;CLI, GUI, Cloud 같은 상위 제품들은 이 엔진 위에서 동작하는 인터페이스라고 보면 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) CLI&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands CLI는 터미널에서 바로 에이전트를 실행하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자는 자연어로 작업을 입력하고, 에이전트가 어떤 작업을 수행하는지 실시간으로 확인할 수 있다. 예를 들어 다음과 같은 식이다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;openhands -t &quot;Create a REST API for user management&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 Claude Code나 Codex CLI 같은 도구를 써본 개발자에게 익숙하다.&lt;br /&gt;특히 터미널 중심으로 일하는 개발자라면 OpenHands CLI가 가장 빠른 진입점이 될 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) Local GUI&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Local GUI는 브라우저 기반 화면에서 OpenHands를 실행하는 방식이다.&lt;br /&gt;Docker 기반으로 로컬 환경에서 실행할 수 있고, 웹 UI를 통해 에이전트와 상호작용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 터미널 명령보다 시각적인 흐름을 선호하는 개발자에게 적합하다.&lt;br /&gt;에이전트가 어떤 파일을 보고 있는지, 어떤 작업을 진행 중인지, 어떤 결과를 냈는지 확인하기 쉽다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) OpenHands Cloud&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands Cloud는 설치 없이 클라우드에서 OpenHands를 사용하는 방식이다.&lt;br /&gt;GitHub 또는 GitLab 계정으로 로그인해 바로 사용할 수 있는 흐름을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 개발자는 빠르게 체험할 수 있고, 팀 단위에서는 클라우드 기반 협업 흐름을 만들 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5) Enterprise&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands Enterprise는 기업이 자체 인프라나 VPC 안에서 OpenHands를 운영할 수 있도록 하는 형태다.&lt;br /&gt;보안, 권한 관리, 사용자 관리, 협업 기능, 사내 시스템 연동이 중요한 조직을 겨냥한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 개발 에이전트는 코드와 내부 문서를 다루기 때문에 기업 환경에서는 &amp;ldquo;어디서 실행되는가&amp;rdquo;가 매우 중요하다. 그런 점에서 self-hosting과 엔터프라이즈 배포 옵션은 OpenHands의 중요한 방향성이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. OpenHands가 실제로 할 수 있는 일&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands를 실무 관점에서 보면 다음 작업에 특히 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) GitHub 이슈 자동 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 GitHub Action과 연결해 이슈 기반 작업을 자동화할 수 있다.&lt;br /&gt;예를 들어 저장소에 이슈를 만들고 fix-me 라벨을 붙이면 OpenHands가 해당 이슈를 분석하고 해결을 시도한다. 이후 PR을 만들고, 사람은 결과를 검토한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 흐름은 매우 중요하다.&lt;br /&gt;AI가 바로 main 브랜치에 코드를 밀어 넣는 것이 아니라, 사람이 검토 가능한 PR 단위로 작업을 남긴다. 실무에서는 이 구조가 훨씬 안전하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) 코드 리뷰와 수정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 단순히 &amp;ldquo;이 코드 어때?&amp;rdquo;라고 묻는 도구가 아니다.&lt;br /&gt;코드를 읽고, 문제를 찾고, 수정안을 만들고, 테스트까지 시도할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같은 요청이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 PR에서 테스트가 실패하는 원인을 찾아서 고쳐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;중복된 로직을 공통 함수로 분리해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;타입 에러를 해결하고 관련 테스트를 추가해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 컴포넌트를 더 작은 단위로 리팩터링해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 개발자의 역할은 에이전트가 만든 결과를 검토하고, 방향이 맞는지 판단하는 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) 의존성 업데이트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리 업데이트는 중요하지만 귀찮은 작업이다.&lt;br /&gt;버전을 올리고, 깨지는 부분을 찾고, 테스트를 돌리고, 수정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 이런 반복 작업에 잘 맞는다.&lt;br /&gt;특히 여러 저장소를 관리하는 팀이라면 의존성 업데이트, 보안 패치, 마이그레이션 작업에 에이전트를 붙이는 방식이 현실적이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) 테스트 작성과 QA 자동화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트가 부족한 프로젝트에서 OpenHands를 활용하면 특정 함수나 API에 대한 테스트 코드를 생성하게 할 수 있다.&lt;br /&gt;또한 실패한 테스트를 기반으로 원인을 추적하게 만들 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 테스트 품질은 반드시 사람이 검토해야 한다.&lt;br /&gt;AI가 작성한 테스트는 때때로 구현을 검증하는 것이 아니라 구현에 맞춰 형식적으로 통과하는 테스트가 될 수 있기 때문이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5) 레거시 코드 리팩터링&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레거시 코드 리팩터링은 AI 에이전트에게 특히 흥미로운 영역이다.&lt;br /&gt;한 번에 전체 구조를 바꾸는 것은 위험하지만, 작은 단위로 나누면 자동화할 수 있는 부분이 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같은 단계적 작업이 가능하다.&lt;/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;li&gt;테스트 실행&lt;/li&gt;
&lt;li&gt;실패 원인 수정&lt;/li&gt;
&lt;li&gt;변경 내역 요약&lt;/li&gt;
&lt;li&gt;PR 생성&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 루프는 OpenHands 같은 에이전트형 도구가 지향하는 대표적인 활용 방식이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. OpenHands의 핵심 구조를 쉽게 이해하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands를 이해할 때는 네 가지 개념을 잡으면 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Agent&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent는 작업을 수행하는 AI 주체다.&lt;br /&gt;LLM을 기반으로 판단하고, 필요한 도구를 선택하고, 다음 행동을 결정한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Tools&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tools는 에이전트가 사용할 수 있는 능력이다.&lt;br /&gt;예를 들어 터미널 실행, 파일 편집, 웹 브라우징, 태스크 트래킹 같은 기능이 도구에 해당한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Workspace&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Workspace는 에이전트가 작업하는 공간이다.&lt;br /&gt;로컬 폴더일 수도 있고, Docker 컨테이너일 수도 있고, 원격 서버 환경일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 개발 에이전트에서 Workspace는 매우 중요하다.&lt;br /&gt;에이전트가 실제 코드를 만지고 명령어를 실행하기 때문에, 안전한 격리 환경이 필요하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Conversation&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Conversation은 사용자와 에이전트 사이의 작업 흐름을 관리하는 단위다.&lt;br /&gt;사용자가 요청을 보내고, 에이전트가 계획을 세우고, 도구를 실행하고, 결과를 다시 관찰하는 전체 루프가 Conversation 안에서 진행된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. OpenHands와 기존 AI 코딩 도구의 차이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands를 이해하려면 GitHub Copilot, Cursor, Claude Code 같은 도구와 비교해 보면 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub Copilot은 IDE 안에서 코드 자동완성과 추천에 강하다.&lt;br /&gt;Cursor는 에디터 안에서 코드베이스를 이해하고 수정하는 경험이 좋다.&lt;br /&gt;Claude Code나 Codex류 도구는 터미널 기반 에이전트 작업에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 여기에 오픈소스 플랫폼성과 확장성을 더한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, OpenHands는 &amp;ldquo;하나의 완성된 코딩 앱&amp;rdquo;이라기보다 &amp;ldquo;AI 소프트웨어 개발 에이전트를 만들고 운영하기 위한 기반&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이는 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 개발자가 단순히 코딩 보조를 원한다면 Cursor나 Claude Code가 더 편할 수 있다.&lt;br /&gt;하지만 사내 워크플로우에 맞춘 에이전트를 만들고 싶거나, GitHub 이슈 처리 자동화, 보안 패치 자동화, 사내 개발 플랫폼 통합까지 고려한다면 OpenHands가 더 흥미로운 선택지가 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 설치와 실행 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 로컬 GUI, CLI, SDK, Cloud 방식으로 접근할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 GUI를 실행하려면 일반적으로 Docker 기반 환경이 필요하다.&lt;br /&gt;공식 문서에서는 macOS, Linux, Windows WSL 환경을 안내하고 있으며, 최소 4GB RAM 이상의 시스템을 권장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python 패키지 방식으로는 uv를 이용해 설치하는 흐름이 안내되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;uv tool install openhands --python 3.12
openhands serve
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 pip 기반으로 SDK를 설치할 수도 있다.&lt;/p&gt;
&lt;pre class=&quot;cmake&quot;&gt;&lt;code&gt;pip install -U openhands-sdk openhands-tools
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SDK를 사용하면 Python 코드에서 직접 에이전트를 만들 수 있다.&lt;br /&gt;예를 들어 LLM을 설정하고, TerminalTool, FileEditorTool, TaskTrackerTool 같은 도구를 붙인 뒤, Conversation을 생성해 작업을 실행하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 입장에서는 이 부분이 가장 중요하다.&lt;br /&gt;OpenHands는 단순 앱이 아니라 &amp;ldquo;내가 원하는 에이전트형 개발 워크플로우를 코드로 구성할 수 있는 도구&amp;rdquo;이기 때문이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 한국 개발자&amp;middot;스타트업 관점에서의 활용 아이디어&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 한국 개발자와 스타트업에게도 꽤 실용적인 가능성이 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) 소규모 개발팀의 유지보수 자동화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 스타트업은 기능 개발에 바빠서 리팩터링, 테스트, 문서화, 의존성 업데이트가 밀리기 쉽다.&lt;br /&gt;OpenHands를 GitHub 이슈와 연결하면 반복 유지보수 작업을 에이전트에게 맡기고, 개발자는 PR 검토자로 남을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 매주 다음과 같은 이슈를 자동 생성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;오래된 npm 패키지 업데이트&amp;rdquo;&lt;br /&gt;&amp;ldquo;테스트 커버리지 낮은 모듈에 테스트 추가&amp;rdquo;&lt;br /&gt;&amp;ldquo;README와 실제 API 스펙 불일치 확인&amp;rdquo;&lt;br /&gt;&amp;ldquo;TODO 주석 기반 개선 PR 생성&amp;rdquo;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) 사내 개발 플랫폼과 연결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 내부에 Backstage, Jira, Linear, GitHub Enterprise 같은 도구가 있다면 OpenHands를 사내 개발 플랫폼과 연결하는 시나리오를 생각해 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 Jira 티켓이 생성되면, OpenHands가 관련 저장소를 분석하고 초안 PR을 만드는 식이다.&lt;br /&gt;개발자는 처음부터 코드를 작성하는 대신, AI가 만든 초안을 리뷰하고 보완한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) 레거시 시스템 현대화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국 기업에는 오래된 Java, PHP, Spring, 전자정부 프레임워크, 내부 ERP 코드가 많다.&lt;br /&gt;이런 시스템은 한 번에 바꾸기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 레거시 코드를 작은 단위로 분석하고, 테스트를 추가하고, 마이그레이션 범위를 나누는 데 활용할 수 있다.&lt;br /&gt;특히 &amp;ldquo;전체 교체&amp;rdquo;가 아니라 &amp;ldquo;작은 PR을 반복적으로 쌓는 방식&amp;rdquo;으로 접근하면 현실성이 높다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) AI 에이전트 SaaS 개발&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands SDK는 단순 사용자가 아니라 개발자에게도 의미가 크다.&lt;br /&gt;예를 들어 다음과 같은 자체 서비스를 만들 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GitHub 저장소 분석 리포트 자동 생성 서비스&lt;/li&gt;
&lt;li&gt;보안 취약점 수정 PR 자동 생성 서비스&lt;/li&gt;
&lt;li&gt;코드 리뷰 자동화 SaaS&lt;/li&gt;
&lt;li&gt;스타트업용 기술 부채 관리 에이전트&lt;/li&gt;
&lt;li&gt;레거시 코드 문서화 에이전트&lt;/li&gt;
&lt;li&gt;내부 API 문서 자동 동기화 에이전트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 서비스는 단순 챗봇보다 훨씬 높은 가치를 만들 수 있다.&lt;br /&gt;왜냐하면 실제 코드베이스 안에서 작업하고 결과물을 남기기 때문이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. OpenHands를 도입할 때 주의할 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 강력하지만, 아무 프로젝트에나 무작정 붙이면 위험하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) 권한을 좁게 줘야 한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 터미널을 실행하고 파일을 수정할 수 있다는 것은 장점이면서 동시에 위험이다.&lt;br /&gt;처음에는 읽기 전용 분석, 제한된 브랜치, 제한된 디렉터리, 테스트 전용 환경에서 시작하는 것이 좋다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) 자동 머지는 피해야 한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만든 코드는 반드시 PR 기반으로 검토해야 한다.&lt;br /&gt;특히 프로덕션 코드, 결제, 인증, 개인정보, 보안 관련 코드는 사람 리뷰가 필수다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) 작업 단위를 작게 쪼개야 한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;우리 서비스를 전부 리팩터링해줘&amp;rdquo; 같은 요청은 좋지 않다.&lt;br /&gt;대신 다음처럼 구체적으로 요청해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;UserService의 중복 validation 로직을 별도 함수로 분리하고 기존 테스트가 통과하는지 확인해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 API 엔드포인트에 누락된 에러 케이스 테스트를 추가해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;README의 설치 방법이 현재 package.json과 맞는지 확인하고 수정해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트는 명확한 범위와 성공 조건이 있을 때 훨씬 잘 작동한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) 비용 관리가 필요하다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 LLM API를 사용한다.&lt;br /&gt;작업이 길어지고 반복 실행이 많아지면 비용이 늘어날 수 있다.&lt;br /&gt;따라서 팀 단위로 사용할 때는 모델 선택, 최대 반복 횟수, 작업 제한, 승인 단계, 로그 모니터링을 설정해야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5) 보안과 비밀키 관리가 중요하다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 코드 저장소에 접근한다면 .env, API 키, DB 접속 정보, 내부 문서 접근 권한을 신중히 다뤄야 한다.&lt;br /&gt;가능하면 샌드박스 환경에서 실행하고, 비밀 정보는 별도 Secret 관리 체계를 사용하는 것이 좋다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. OpenHands의 한계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 &amp;ldquo;AI 개발자의 미래&amp;rdquo;를 보여주는 프로젝트지만, 아직 모든 것을 자동으로 해결하는 도구는 아니다.&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;br /&gt;AI는 코드를 수정할 수 있지만, 어떤 기능이 비즈니스에 맞는지, 어떤 구조가 조직에 맞는지는 사람이 판단해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 환경 설정 문제에서 막힐 수 있다.&lt;br /&gt;실제 개발 프로젝트는 의존성, 로컬 DB, 권한, 사내 네트워크, 빌드 도구 등 변수가 많다. 에이전트가 이런 환경을 완벽히 이해하지 못하면 작업이 중간에 실패할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 그럴듯하지만 틀린 수정이 나올 수 있다.&lt;br /&gt;AI가 테스트를 통과시키기 위해 문제의 본질이 아니라 증상만 고칠 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, 장기 작업에서는 방향이 흐려질 수 있다.&lt;br /&gt;큰 리팩터링이나 아키텍처 변경은 여러 단계의 설계와 검토가 필요하다. 이 경우 에이전트에게 한 번에 맡기기보다 작은 단위로 나누는 전략이 필요하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 그래서 OpenHands는 누구에게 적합한가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 다음 사용자에게 특히 잘 맞는다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI 코딩 도구를 단순 보조가 아니라 자동화 워크플로우로 쓰고 싶은 개발자&lt;/li&gt;
&lt;li&gt;GitHub 이슈와 PR 기반으로 반복 작업을 자동화하고 싶은 팀&lt;/li&gt;
&lt;li&gt;자체 AI 개발 에이전트를 만들고 싶은 스타트업&lt;/li&gt;
&lt;li&gt;사내 개발 플랫폼에 AI 에이전트를 붙이고 싶은 엔지니어링 조직&lt;/li&gt;
&lt;li&gt;오픈소스 기반으로 AI 개발 에이전트 구조를 연구하고 싶은 개발자&lt;/li&gt;
&lt;li&gt;Claude Code, Codex, Cursor 이후의 에이전트형 개발 환경을 실험하고 싶은 사용자&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 다음 사용자에게는 다소 부담스러울 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순 코드 자동완성만 원하는 사용자&lt;/li&gt;
&lt;li&gt;Docker, 터미널, GitHub Action 설정이 익숙하지 않은 초보자&lt;/li&gt;
&lt;li&gt;AI가 만든 코드를 검토할 개발자가 없는 팀&lt;/li&gt;
&lt;li&gt;보안상 외부 LLM API 사용이 어려운 조직&lt;/li&gt;
&lt;li&gt;자동화보다 IDE 안의 즉각적인 편집 경험을 더 중시하는 개발자&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. OpenHands를 한 문장으로 정리하면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 &amp;ldquo;AI에게 코드를 물어보는 도구&amp;rdquo;가 아니라, &amp;ldquo;AI에게 개발 작업을 맡기기 위한 오픈소스 실행 플랫폼&amp;rdquo;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이가 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 도구의 다음 경쟁은 더 이상 &amp;ldquo;누가 코드를 더 잘 추천하느냐&amp;rdquo;만이 아니다.&lt;br /&gt;앞으로는 &amp;ldquo;누가 실제 개발 워크플로우 안에서 안전하게 일을 끝내느냐&amp;rdquo;가 중요해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenHands는 바로 그 방향을 보여준다.&lt;br /&gt;개발자는 모든 코드를 직접 치는 사람이 아니라, 에이전트에게 일을 나누고, 결과를 검토하고, 시스템을 설계하는 사람으로 바뀌고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 OpenHands를 봐야 하는 이유도 여기에 있다.&lt;br /&gt;이 프로젝트는 단순한 오픈소스 코딩 도구가 아니라, 앞으로 개발팀이 AI 에이전트를 어떻게 조직 안에 들여올 것인지 보여주는 실험장이기 때문이다.&lt;/p&gt;
&lt;figure id=&quot;og_1781656831743&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - OpenHands/OpenHands:   OpenHands: AI-Driven Development&quot; data-og-description=&quot;  OpenHands: AI-Driven Development. Contribute to OpenHands/OpenHands development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/OpenHands/openhands&quot; data-og-url=&quot;https://github.com/OpenHands/OpenHands&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Dkudj/dJMb896cEGP/wqiC7rn5q4pFPZTV2rVXek/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dHUl1o/dJMb9bwa9Cu/ssFzeBlan3bwPcdKRRoLk0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bpIvaQ/dJMb82eVYra/pCVWRNtqgTm8IzvX941Jrk/img.png?width=3840&amp;amp;height=2160&amp;amp;face=0_0_3840_2160&quot;&gt;&lt;a href=&quot;https://github.com/OpenHands/openhands&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/OpenHands/openhands&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Dkudj/dJMb896cEGP/wqiC7rn5q4pFPZTV2rVXek/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dHUl1o/dJMb9bwa9Cu/ssFzeBlan3bwPcdKRRoLk0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bpIvaQ/dJMb82eVYra/pCVWRNtqgTm8IzvX941Jrk/img.png?width=3840&amp;amp;height=2160&amp;amp;face=0_0_3840_2160');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - OpenHands/OpenHands:   OpenHands: AI-Driven Development&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  OpenHands: AI-Driven Development. Contribute to OpenHands/OpenHands development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1778</guid>
      <comments>https://javaexpert.tistory.com/1778#entry1778comment</comments>
      <pubDate>Wed, 17 Jun 2026 09:41:04 +0900</pubDate>
    </item>
    <item>
      <title>Google Cloud가 공개한 Open Knowledge Format, OKF 쉽게 이해하기</title>
      <link>https://javaexpert.tistory.com/1777</link>
      <description>&lt;h1&gt;AI 에이전트 시대, 지식은 문서가 아니라 &amp;ldquo;포맷&amp;rdquo;이 된다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 업무에 붙여보면 금방 깨닫는 문제가 하나 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델 자체가 부족해서가 아니라,&lt;br /&gt;&lt;b&gt;모델이 참고해야 할 맥락이 흩어져 있다는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 회사 안에서 AI 에이전트에게 이렇게 물었다고 해보겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;우리 서비스의 주간 활성 사용자, WAU는 어떻게 계산해?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람이라면 누군가에게 물어보고, 노션 문서를 뒤지고, BigQuery 테이블을 확인하고, 예전 슬랙 대화를 찾아볼 수 있습니다. 하지만 AI 에이전트 입장에서는 이 정보들이 모두 서로 다른 장소에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 스키마는 데이터 카탈로그에 있고,&lt;br /&gt;지표 정의는 노션에 있고,&lt;br /&gt;운영 절차는 위키에 있고,&lt;br /&gt;예외 규칙은 시니어 개발자의 머릿속에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google Cloud는 이 문제를 &lt;b&gt;&amp;ldquo;지식이 너무 많은 곳에 흩어져 있고, 서로 호환되지 않는다&amp;rdquo;&lt;/b&gt;는 문제로 봅니다. 그리고 그 해결책으로 &lt;b&gt;Open Knowledge Format, 줄여서 OKF&lt;/b&gt;를 소개했습니다. (&lt;a href=&quot;https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/?hl=en&quot;&gt;Google Cloud&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;OKF는 무엇인가?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 쉽게 말하면,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트와 사람이 함께 읽을 수 있는&lt;br /&gt;지식 정리용 오픈 포맷입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 구체적으로는 &lt;b&gt;Markdown 파일 + YAML frontmatter&lt;/b&gt; 조합으로 지식을 표현하는 방식입니다. Google Cloud 설명에 따르면 OKF v0.1은 지식을 여러 개의 Markdown 파일 디렉터리로 표현하고, 각 파일 상단에 YAML frontmatter를 붙이는 구조입니다. (&lt;a href=&quot;https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/?hl=en&quot;&gt;Google Cloud&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 이겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 새로운 데이터베이스가 아닙니다.&lt;br /&gt;OKF는 새로운 SaaS도 아닙니다.&lt;br /&gt;OKF는 특정 클라우드나 특정 AI 모델에 묶인 SDK도 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 파일입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Markdown이기 때문에 사람이 읽을 수 있고,&lt;br /&gt;GitHub에서 바로 볼 수 있고,&lt;br /&gt;검색 도구가 인덱싱할 수 있고,&lt;br /&gt;AI 에이전트가 그대로 컨텍스트로 읽을 수 있습니다. Google Cloud는 OKF 번들이 &amp;ldquo;just markdown&amp;rdquo;, &amp;ldquo;just files&amp;rdquo;, &amp;ldquo;just YAML frontmatter&amp;rdquo;라는 점을 강조합니다. (&lt;a href=&quot;https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/?hl=en&quot;&gt;Google Cloud&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;왜 지금 OKF가 필요한가?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 많은 조직은 AI 에이전트를 만들면서 비슷한 문제를 반복해서 풀고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 정확한 답을 하려면 조직 내부 지식이 필요합니다. 예를 들면 이런 것들입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테이블 스키마&lt;/li&gt;
&lt;li&gt;지표 정의&lt;/li&gt;
&lt;li&gt;API 사용법&lt;/li&gt;
&lt;li&gt;운영 runbook&lt;/li&gt;
&lt;li&gt;장애 대응 절차&lt;/li&gt;
&lt;li&gt;데이터 간 join 경로&lt;/li&gt;
&lt;li&gt;deprecated 된 API 안내&lt;/li&gt;
&lt;li&gt;특정 비즈니스 용어의 내부 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 이 지식들이 한곳에 있지 않다는 것입니다. 원문에서도 조직 내부 지식이 메타데이터 카탈로그, 위키, 공유 드라이브, 코드 주석, 노트북 셀, 소수의 시니어 엔지니어 머릿속 등에 흩어져 있다고 설명합니다. (&lt;a href=&quot;https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/?hl=en&quot;&gt;Google Cloud&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다 보니 새로운 AI 에이전트를 만들 때마다 같은 작업을 다시 하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 테이블은 무슨 뜻이지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 지표는 어디서 계산하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 API는 아직 써도 되나?&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 장애가 나면 어떤 순서로 확인하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 정보는 최신인가?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트 개발에서 진짜 병목은 모델 호출 코드가 아니라,&lt;br /&gt;&lt;b&gt;쓸 만한 지식을 어떻게 구조화해서 넣어줄 것인가&lt;/b&gt;가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 이 문제를 &amp;ldquo;또 하나의 지식 관리 서비스&amp;rdquo;로 풀지 않습니다.&lt;br /&gt;대신 &lt;b&gt;모든 도구가 읽고 쓸 수 있는 공통 포맷&lt;/b&gt;으로 풀려고 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;OKF의 기본 구조&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF 번들은 하나의 폴더입니다.&lt;br /&gt;그 안에 Markdown 파일들이 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 커머스 서비스의 데이터 지식을 OKF로 정리하면 이런 식이 될 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;commerce/
├── index.md
├── datasets/
│   ├── index.md
│   └── ecommerce_db.md
├── tables/
│   ├── index.md
│   ├── orders.md
│   ├── customers.md
│   └── events.md
└── metrics/
    ├── index.md
    ├── weekly_active_users.md
    └── conversion_rate.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 원칙은 간단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하나의 개념은 하나의 파일로 표현합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 orders.md는 주문 테이블에 대한 설명이고,&lt;br /&gt;weekly_active_users.md는 WAU 지표 정의 문서입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 파일은 보통 이렇게 생겼습니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
type: table
title: Orders
description: 완료된 주문 정보를 저장하는 테이블
resource: bigquery://my-project.commerce.orders
tags: [commerce, sales, revenue]
timestamp: 2026-06-14T09:00:00Z
---

# 개요

`orders` 테이블은 사용자의 완료된 주문을 저장한다.

# 주요 컬럼

| Column | Type | Description |
|---|---|---|
| order_id | STRING | 주문 고유 ID |
| customer_id | STRING | 고객 ID |
| order_amount | NUMERIC | 주문 금액 |
| created_at | TIMESTAMP | 주문 생성 시각 |

# 조인 관계

- `customer_id`를 기준으로 [customers](../tables/customers.md) 테이블과 조인한다.

# 자주 쓰는 쿼리

```sql
SELECT
  DATE(created_at) AS order_date,
  COUNT(*) AS order_count,
  SUM(order_amount) AS total_revenue
FROM commerce.orders
GROUP BY order_date
ORDER BY order_date DESC;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;subunit&quot;&gt;&lt;code&gt;상단의 `---` 사이에 있는 부분이 YAML frontmatter입니다.

여기에는 기계가 읽기 좋은 구조화된 정보가 들어갑니다.

```yaml
type: table
title: Orders
description: 완료된 주문 정보를 저장하는 테이블
resource: bigquery://my-project.commerce.orders
tags: [commerce, sales, revenue]
timestamp: 2026-06-14T09:00:00Z
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문은 사람이 읽기 좋은 Markdown입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, OKF는 구조화된 필드와 자유로운 설명을 함께 담습니다. Google Cloud의 GitHub README도 OKF가 type, resource, tags, timestamp 같은 쿼리&amp;middot;필터&amp;middot;인덱싱용 frontmatter와, 사람이 실제로 읽는 설명&amp;middot;스키마&amp;middot;예제 쿼리용 Markdown 본문을 함께 사용한다고 설명합니다. (&lt;a href=&quot;https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;예제 1. 지표 정의를 OKF로 만들기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 데이터 분석을 도와주려면 지표 정의가 명확해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;WAU&amp;rdquo;라는 지표를 생각해보겠습니다.&lt;br /&gt;회사마다 WAU의 정의가 다를 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 회사는 로그인 기준으로 볼 수 있고,&lt;br /&gt;어떤 회사는 특정 핵심 이벤트 발생 기준으로 볼 수 있고,&lt;br /&gt;어떤 회사는 봇&amp;middot;테스트 계정을 제외해야 할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정의를 OKF 문서로 만들면 이렇게 됩니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
type: metric
title: Weekly Active Users
description: 최근 7일 동안 핵심 활동 이벤트를 1회 이상 수행한 고유 사용자 수
resource: bigquery://my-project.analytics.events
tags: [metric, product, engagement]
timestamp: 2026-06-14T09:00:00Z
---

# 정의

Weekly Active Users, WAU는 최근 7일 동안 핵심 활동 이벤트를 1회 이상 수행한 고유 사용자 수다.

# 포함 이벤트

다음 이벤트 중 하나 이상을 수행한 사용자를 active user로 본다.

- app_open
- lesson_start
- purchase_complete
- content_view

# 제외 조건

다음 사용자는 제외한다.

- 내부 테스트 계정
- 관리자 계정
- 봇으로 분류된 계정
- 삭제된 계정

# 계산 예시

```sql
SELECT
  COUNT(DISTINCT user_id) AS weekly_active_users
FROM analytics.events
WHERE event_name IN (
  'app_open',
  'lesson_start',
  'purchase_complete',
  'content_view'
)
AND event_timestamp &amp;gt;= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
AND user_id NOT IN (
  SELECT user_id
  FROM analytics.excluded_users
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;관련 문서&lt;/h1&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://chatgpt.com/tables/events.md&quot;&gt;events table&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chatgpt.com/tables/excluded_users.md&quot;&gt;excluded users&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;이렇게 해두면 AI 에이전트는 &amp;ldquo;WAU 계산해줘&amp;rdquo;라는 요청을 받았을 때, 단순히 이벤트 테이블을 추측하지 않습니다.

먼저 `weekly_active_users.md`를 읽고,  
그 안의 정의와 제외 조건을 확인하고,  
관련 테이블 문서로 이동한 뒤,  
쿼리를 작성할 수 있습니다.

[Inference] 이 방식은 RAG 시스템의 검색 대상 문서를 더 명확하게 만들고, 에이전트가 잘못된 지표 정의를 임의로 추측하는 위험을 줄이는 데 도움이 될 수 있습니다. 단, 실제 정확도 향상 정도는 검색 파이프라인, 문서 품질, 모델, 평가 방식에 따라 달라집니다.

---

# 예제 2. API 문서를 OKF로 만들기

OKF는 데이터 카탈로그에만 쓸 수 있는 형식이 아닙니다. 원문은 OKF 개념 문서가 테이블, 데이터셋, 메트릭, 플레이북, 런북, API 등 원하는 지식을 담을 수 있다고 설명합니다. :contentReference[oaicite:6]{index=6}

예를 들어 결제 API를 OKF 문서로 만든다면 이렇게 정리할 수 있습니다.

```markdown
---
type: api
title: Create Payment API
description: 사용자의 결제 요청을 생성하는 API
resource: https://api.example.com/v1/payments
tags: [payment, api, backend]
timestamp: 2026-06-14T09:00:00Z
---

# 개요

Create Payment API는 사용자가 상품을 구매할 때 결제 요청을 생성한다.

# Endpoint

```http
POST /v1/payments
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Request Body&lt;/h1&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;user_id&quot;: &quot;user_123&quot;,
  &quot;product_id&quot;: &quot;product_456&quot;,
  &quot;amount&quot;: 19000,
  &quot;currency&quot;: &quot;KRW&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Response&lt;/h1&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;payment_id&quot;: &quot;pay_789&quot;,
  &quot;status&quot;: &quot;pending&quot;,
  &quot;checkout_url&quot;: &quot;https://checkout.example.com/pay_789&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;주의사항&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;amount는 서버에서 상품 가격을 기준으로 재검증한다.&lt;/li&gt;
&lt;li&gt;클라이언트가 보낸 금액을 그대로 신뢰하지 않는다.&lt;/li&gt;
&lt;li&gt;결제 완료 여부는 webhook 이벤트로 최종 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;관련 문서&lt;/h1&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://chatgpt.com/c/payment_webhook.md&quot;&gt;Payment Webhook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chatgpt.com/tables/orders.md&quot;&gt;Orders Table&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;이렇게 문서화하면 AI 코딩 에이전트가 결제 기능을 수정할 때 더 안전하게 작업할 수 있습니다.

예를 들어 사용자가 이렇게 요청할 수 있습니다.

&amp;gt; &amp;ldquo;결제 성공 후 주문 상태를 paid로 바꾸는 코드를 추가해줘.&amp;rdquo;

에이전트는 결제 API 문서만 보는 것이 아니라,  
Payment Webhook 문서와 Orders Table 문서까지 따라가며 확인할 수 있습니다.

OKF는 Markdown 링크를 통해 개념 간 관계를 표현합니다. Google Cloud는 이러한 링크들이 디렉터리를 단순한 트리 구조가 아니라 관계 그래프처럼 만들어준다고 설명합니다. :contentReference[oaicite:7]{index=7}

---

# 예제 3. 장애 대응 Runbook을 OKF로 만들기

AI 에이전트가 운영 업무를 도와주려면 장애 대응 절차도 지식으로 관리되어야 합니다.

예를 들어 &amp;ldquo;결제 승인 실패율 증가&amp;rdquo; 장애 runbook은 이렇게 만들 수 있습니다.

```markdown
---
type: runbook
title: Payment Approval Failure Spike
description: 결제 승인 실패율이 평소보다 급격히 증가했을 때 확인하는 절차
resource: internal://runbooks/payment-approval-failure
tags: [payment, incident, runbook]
timestamp: 2026-06-14T09:00:00Z
---

# 증상

다음 지표 중 하나 이상이 발생하면 이 runbook을 확인한다.

- 결제 승인 실패율이 10분 이상 5%를 초과
- PG사 timeout error 증가
- 결제 완료 webhook 지연 증가

# 1차 확인

## 1. PG사 상태 페이지 확인

PG사 장애 공지가 있는지 확인한다.

## 2. 최근 배포 확인

최근 1시간 내 결제 관련 배포가 있었는지 확인한다.

## 3. 에러 로그 확인

다음 키워드로 로그를 검색한다.

```text
payment_timeout
pg_auth_failed
webhook_signature_invalid
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;임시 대응&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PG사 장애가 확인되면 공지 배너를 노출한다.&lt;/li&gt;
&lt;li&gt;내부 배포 문제가 의심되면 직전 버전으로 롤백한다.&lt;/li&gt;
&lt;li&gt;webhook 지연이면 주문 상태를 pending으로 유지하고 재처리 큐를 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;관련 문서&lt;/h1&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://chatgpt.com/apis/create_payment.md&quot;&gt;Create Payment API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chatgpt.com/apis/payment_webhook.md&quot;&gt;Payment Webhook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chatgpt.com/tables/orders.md&quot;&gt;Orders Table&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;이런 문서가 OKF 형태로 정리되어 있으면, 장애 상황에서 AI 에이전트에게 이렇게 물을 수 있습니다.

&amp;gt; &amp;ldquo;지금 결제 실패율이 올라갔는데, 어떤 순서로 확인해야 해?&amp;rdquo;

그러면 에이전트는 runbook을 읽고, 관련 API와 테이블 문서까지 연결해서 대응 순서를 제안할 수 있습니다.

[Inference] 특히 운영 조직에서는 OKF를 Git으로 관리하면 runbook 변경 이력, 리뷰, 승인 절차를 코드처럼 관리할 수 있습니다. Google Cloud의 GitHub README도 OKF 번들이 Git에 저장될 수 있고 PR, diff, blame, review workflow를 활용할 수 있다고 설명합니다. :contentReference[oaicite:8]{index=8}

---

# OKF의 핵심 장점

## 1. 사람과 AI가 같은 문서를 읽는다

기존 문서 시스템에서는 사람용 문서와 기계용 메타데이터가 분리되는 경우가 많습니다.

사람은 노션을 보고,  
시스템은 API를 보고,  
AI 에이전트는 별도 인덱스를 봅니다.

OKF는 이 구조를 단순화합니다.

Markdown 본문은 사람이 읽고,  
YAML frontmatter는 기계가 읽습니다.

같은 파일을 사람이 리뷰하고,  
같은 파일을 AI가 검색하고,  
같은 파일을 에이전트가 컨텍스트로 가져갈 수 있습니다.

## 2. 특정 벤더에 묶이지 않는다

OKF는 특정 클라우드, 데이터베이스, 모델 제공자, 에이전트 프레임워크에 묶이지 않는 포맷으로 소개되었습니다. Google Cloud는 OKF가 proprietary account나 SDK를 요구하지 않는 open standard라고 설명합니다. :contentReference[oaicite:9]{index=9}

이 점이 중요합니다.

회사 지식은 한 번 쌓이면 오래갑니다.  
그런데 특정 벤더의 전용 포맷에만 저장하면 나중에 옮기기 어렵습니다.

OKF는 폴더와 Markdown 파일이기 때문에 GitHub, GitLab, 로컬 파일 시스템, 정적 파일 서버, Obsidian, MkDocs, Hugo 같은 기존 도구와 잘 어울립니다. Google Cloud의 GitHub README도 Notion, Obsidian, MkDocs, Hugo, Jekyll 같은 Markdown 기반 도구들과 조합할 수 있다고 설명합니다. :contentReference[oaicite:10]{index=10}

## 3. 지식을 코드처럼 관리할 수 있다

OKF의 큰 장점은 지식을 Git으로 관리할 수 있다는 점입니다.

예를 들어 지표 정의가 바뀌면 Pull Request를 만들 수 있습니다.

```diff
- WAU는 최근 7일 동안 로그인한 사용자 수다.
+ WAU는 최근 7일 동안 핵심 활동 이벤트를 1회 이상 수행한 사용자 수다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰어는 이렇게 코멘트할 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;관리자 계정 제외 조건도 명시해주세요.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;승인 후 merge하면 변경 이력이 남습니다.&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;br /&gt;&lt;b&gt;조직 지식을 버전 관리하는 방식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 에이전트가 탐색하기 쉽다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 index.md 파일을 선택적으로 둘 수 있습니다. 원문은 index.md가 에이전트가 계층 구조를 단계적으로 탐색하는 데 도움이 될 수 있다고 설명합니다. (&lt;a href=&quot;https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/?hl=en&quot;&gt;Google Cloud&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 에이전트가 처음부터 모든 문서를 읽을 필요는 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 commerce/index.md를 읽고,&lt;br /&gt;그다음 tables/index.md를 읽고,&lt;br /&gt;필요한 경우 orders.md로 들어갈 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 LLM 컨텍스트를 절약하는 데도 유리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Inference] 긴 문서 전체를 무작정 넣는 방식보다, 계층적 index와 링크를 따라 필요한 문서만 읽는 방식이 에이전트 설계에 더 적합할 수 있습니다. 다만 실제 성능은 검색기, 라우팅 방식, 컨텍스트 정책에 따라 달라집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;OKF와 RAG는 어떤 관계인가?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람이 OKF를 보면 &amp;ldquo;이거 RAG용 문서 포맷인가?&amp;rdquo;라고 생각할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절반은 맞고, 절반은 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAG는 보통 검색 시스템입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서를 쪼개고,&lt;br /&gt;임베딩하고,&lt;br /&gt;벡터DB에 넣고,&lt;br /&gt;질문과 관련 있는 조각을 찾아&lt;br /&gt;LLM에 넣어주는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 검색 시스템 자체가 아닙니다.&lt;br /&gt;OKF는 &lt;b&gt;검색하기 좋은 지식 원본을 만드는 포맷&lt;/b&gt;에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 관계를 이렇게 볼 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;OKF = 지식을 정리하는 표준 파일 포맷
RAG = 그 지식을 검색해서 LLM에 넣는 실행 방식
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF 문서를 RAG 파이프라인에 넣을 수 있습니다.&lt;br /&gt;하지만 OKF는 RAG 없이도 쓸 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 코딩 에이전트가 로컬 파일 시스템에서 OKF 폴더를 직접 읽게 할 수도 있고,&lt;br /&gt;정적 HTML 뷰어로 사람이 탐색할 수도 있고,&lt;br /&gt;검색 인덱스로 변환할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google Cloud의 GitHub README도 OKF 번들이 Markdown을 읽는 어떤 도구로든 소비될 수 있으며, 정적 파일 서버, 지식 관리 UI, LLM 컨텍스트, 검색 인덱스, 그래프 뷰어 등 다양한 소비 방식을 언급합니다. (&lt;a href=&quot;https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;OKF를 실제로 어디에 쓸 수 있을까?&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 데이터팀의 지표 사전&lt;/h2&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;KPI 정의&lt;/li&gt;
&lt;li&gt;테이블 설명&lt;/li&gt;
&lt;li&gt;컬럼 의미&lt;/li&gt;
&lt;li&gt;join 방법&lt;/li&gt;
&lt;li&gt;SQL 예제&lt;/li&gt;
&lt;li&gt;deprecated 테이블 안내&lt;/li&gt;
&lt;li&gt;대시보드와 지표 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 정보를 OKF로 관리하면 AI 데이터 분석 에이전트가 훨씬 명확한 기준으로 답할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 에이전트에게 이렇게 시킬 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;지난 4주간 신규 가입자의 구매 전환율을 계산하는 SQL을 작성해줘. 우리 회사의 conversion_rate 정의를 기준으로 해줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트는 conversion_rate.md, users.md, orders.md, events.md를 읽고 쿼리를 작성할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 개발팀의 API&amp;middot;아키텍처 문서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발팀에서는 API 문서, 서비스 간 의존성, 배포 절차를 OKF로 정리할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;backend/
├── services/
│   ├── auth_service.md
│   ├── payment_service.md
│   └── notification_service.md
├── apis/
│   ├── create_payment.md
│   └── send_push.md
└── runbooks/
    ├── payment_failure.md
    └── notification_delay.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해두면 코딩 에이전트에게 단순히 &amp;ldquo;코드 수정해줘&amp;rdquo;라고 하는 것이 아니라,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;OKF 문서를 먼저 읽고, payment_service의 설계 원칙을 지키면서 수정해줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 요청할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 고객지원팀의 운영 지식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객지원팀도 OKF를 쓸 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;환불 정책&lt;/li&gt;
&lt;li&gt;계정 복구 절차&lt;/li&gt;
&lt;li&gt;자주 묻는 질문&lt;/li&gt;
&lt;li&gt;예외 처리 기준&lt;/li&gt;
&lt;li&gt;내부 escalations&lt;/li&gt;
&lt;li&gt;고객 유형별 응대 가이드&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 환불 정책 문서는 이렇게 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
type: policy
title: Refund Policy
description: 구독 상품 환불 처리 기준
resource: internal://policies/refund
tags: [support, refund, subscription]
timestamp: 2026-06-14T09:00:00Z
---

# 기본 원칙

구독 결제 후 7일 이내이고, 유료 기능 사용 이력이 없으면 전액 환불 가능하다.

# 예외

다음 경우에는 수동 검토가 필요하다.

- 중복 결제
- 미성년자 결제
- 결제 오류
- 프로모션 코드 사용
- 부분 사용 후 환불 요청

# 상담원 응대 예시

고객에게 먼저 결제일, 계정 이메일, 사용 여부를 확인한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객지원 AI 에이전트는 이 문서를 읽고 상담 답변 초안을 만들 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;OKF를 도입할 때의 현실적인 시작 방법&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 전사 지식 전체를 OKF로 바꾸려고 하면 실패하기 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작게 시작하는 편이 좋습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1단계: 가장 자주 물어보는 지식 10개만 고른다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 데이터팀이라면 다음 10개를 고릅니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;WAU 정의&lt;/li&gt;
&lt;li&gt;MAU 정의&lt;/li&gt;
&lt;li&gt;구매 전환율 정의&lt;/li&gt;
&lt;li&gt;매출 테이블&lt;/li&gt;
&lt;li&gt;주문 테이블&lt;/li&gt;
&lt;li&gt;사용자 테이블&lt;/li&gt;
&lt;li&gt;이벤트 테이블&lt;/li&gt;
&lt;li&gt;테스트 계정 제외 기준&lt;/li&gt;
&lt;li&gt;주요 대시보드 목록&lt;/li&gt;
&lt;li&gt;deprecated 테이블 목록&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2단계: 하나의 폴더에 Markdown으로 정리한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 완벽한 구조를 만들 필요는 없습니다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;okf/
├── index.md
├── metrics/
│   ├── weekly_active_users.md
│   └── conversion_rate.md
└── tables/
    ├── users.md
    ├── orders.md
    └── events.md
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3단계: frontmatter 필드만 통일한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소한 다음 필드만 통일해도 충분합니다.&lt;/p&gt;
&lt;pre class=&quot;subunit&quot;&gt;&lt;code&gt;type:
title:
description:
resource:
tags:
timestamp:
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문에서도 OKF는 최소한의 구조를 지향하며, 모든 concept에 요구되는 것은 type 필드 하나라고 설명합니다. 다른 필드나 본문 구성은 생산자가 정할 수 있습니다. (&lt;a href=&quot;https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/?hl=en&quot;&gt;Google Cloud&lt;/a&gt;)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4단계: AI 에이전트에게 &amp;ldquo;먼저 OKF를 읽어라&amp;rdquo;라고 지시한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 코딩 에이전트나 데이터 분석 에이전트에게 다음과 같이 지시할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;작업을 시작하기 전에 /okf/index.md를 먼저 읽어라.
관련 metric, table, api 문서를 확인한 뒤 답변하라.
추측하지 말고 OKF 문서에 없는 내용은 &amp;ldquo;문서에 없음&amp;rdquo;이라고 표시하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 OKF가 단순 문서 저장소가 아니라&lt;br /&gt;에이전트의 작업 기준이 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;OKF가 중요한 진짜 이유&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF의 핵심은 &amp;ldquo;Markdown으로 문서를 쓰자&amp;rdquo;가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 많은 팀이 Markdown을 씁니다.&lt;br /&gt;이미 많은 팀이 Notion, Obsidian, GitHub Wiki, Confluence를 씁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF가 던지는 질문은 조금 다릅니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 조직 지식은&lt;br /&gt;사람만 읽는 문서여야 할까,&lt;br /&gt;아니면 AI 에이전트도 읽고 갱신할 수 있는 실행 가능한 컨텍스트여야 할까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 실제 업무에 들어오면, 문서는 더 이상 사람이 가끔 참고하는 자료가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서는 에이전트가 판단하는 기준이 되고,&lt;br /&gt;코드를 수정하기 전 확인하는 규칙이 되고,&lt;br /&gt;데이터를 분석할 때 따라야 하는 정의가 되고,&lt;br /&gt;장애 대응 때 실행 순서를 정하는 runbook이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 문서는 더 구조적이어야 합니다.&lt;br /&gt;버전 관리되어야 합니다.&lt;br /&gt;다른 도구로 옮길 수 있어야 합니다.&lt;br /&gt;사람과 AI가 동시에 읽을 수 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 바로 그 방향을 제안합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;정리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 Google Cloud가 공개한 오픈 지식 포맷입니다.&lt;br /&gt;핵심 구조는 단순합니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Markdown 파일 + YAML frontmatter + 디렉터리 구조 + Markdown 링크
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 단순한 조합으로 다음을 가능하게 하려는 시도입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조직 지식을 파일로 관리한다.&lt;/li&gt;
&lt;li&gt;사람이 읽고 AI도 읽는다.&lt;/li&gt;
&lt;li&gt;Git으로 버전 관리한다.&lt;/li&gt;
&lt;li&gt;특정 벤더에 묶이지 않는다.&lt;/li&gt;
&lt;li&gt;데이터, API, runbook, 지표 정의를 하나의 방식으로 표현한다.&lt;/li&gt;
&lt;li&gt;AI 에이전트가 필요한 맥락을 더 쉽게 찾게 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Inference] 앞으로 AI 에이전트를 제대로 쓰는 팀과 그렇지 못한 팀의 차이는 &amp;ldquo;어떤 모델을 쓰느냐&amp;rdquo;보다 &amp;ldquo;조직 지식을 얼마나 에이전트가 읽기 좋은 형태로 정리했느냐&amp;rdquo;에서 갈릴 가능성이 큽니다. 이 판단은 OKF 원문이 제시한 문제의식과 최근 에이전트 시스템 설계 흐름을 바탕으로 한 해석입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 거창한 플랫폼이 아닙니다.&lt;br /&gt;오히려 너무 단순해서 처음에는 별것 아닌 것처럼 보일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 AI 시대의 지식 관리는 결국 이런 방향으로 갈 가능성이 높습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문서를 쓰는 것이 아니라,&lt;br /&gt;AI가 함께 일할 수 있는 지식 포맷을 설계하는 것.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OKF는 그 출발점으로 볼 수 있습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1777</guid>
      <comments>https://javaexpert.tistory.com/1777#entry1777comment</comments>
      <pubDate>Mon, 15 Jun 2026 09:40:13 +0900</pubDate>
    </item>
    <item>
      <title>Learn-claude-code 19개 항목으로 이해하는 에이전트 하네스 설계</title>
      <link>https://javaexpert.tistory.com/1776</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;1491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sM7xP/dJMb997NLKO/JezMvWm9iXTnUASQkRZs30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sM7xP/dJMb997NLKO/JezMvWm9iXTnUASQkRZs30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sM7xP/dJMb997NLKO/JezMvWm9iXTnUASQkRZs30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsM7xP%2FdJMb997NLKO%2FJezMvWm9iXTnUASQkRZs30%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;1055&quot; height=&quot;1491&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;1491&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 &amp;ldquo;AI 에이전트&amp;rdquo;라는 말이 너무 쉽게 쓰입니다.&lt;br /&gt;하지만 실제로 Claude Code 같은 도구를 뜯어보면 핵심은 생각보다 단순합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델이 똑똑한 것이고, 우리가 만드는 것은 그 모델이 움직일 수 있는 &lt;b&gt;작업 환경&lt;/b&gt;입니다.&lt;br /&gt;learn-claude-code 저장소는 이 관점을 아주 명확하게 설명합니다. 이 저장소의 핵심 문장은 다음과 같습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 = 모델 + 하네스&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;b&gt;모델&lt;/b&gt;은 판단하고 추론하는 두뇌이고, &lt;b&gt;하네스(harness)&lt;/b&gt;는 모델에게 도구, 파일 시스템, 터미널, 권한, 메모리, 작업 공간을 제공하는 실행 환경입니다. 저장소는 Claude Code를 &amp;ldquo;그대로 복제하라&amp;rdquo;는 목적보다, Claude Code류 제품을 가능하게 하는 구조를 0부터 학습하는 데 초점을 둡니다. 원문도 Claude Code의 본질을 &amp;ldquo;하나의 에이전트 루프, 도구, 스킬 로딩, 컨텍스트 압축, 서브에이전트, 작업 시스템, 권한, 훅, 메모리, MCP&amp;rdquo; 등으로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장소에는 현재 s01부터 s20까지 20개 학습 챕터가 있지만, 여기서는 요청하신 대로 s01부터 s19까지 19개 항목을 외부 공개용 글 형태로 정리하겠습니다. 참고로 원문은 s20을 앞의 모든 메커니즘을 합친 종합 예제로 둡니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;먼저 핵심 구조: 에이전트 루프&lt;/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;사용자의 메시지를 모델에 보내고,&lt;br /&gt;모델이 도구 사용을 요청하면 실행하고,&lt;br /&gt;그 결과를 다시 모델에게 돌려주고,&lt;br /&gt;모델이 더 이상 도구를 쓰지 않으면 답변을 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 이를 messages &amp;rarr; LLM &amp;rarr; tool_use 여부 확인 &amp;rarr; tool 실행 &amp;rarr; 결과 추가 &amp;rarr; 다시 messages 흐름으로 설명합니다. 중요한 점은 &amp;ldquo;모델이 도구 호출 여부를 결정하고, 코드는 모델이 요청한 일을 실행한다&amp;rdquo;는 것입니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 19개 항목을 하나씩 보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Agent Loop&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;하나의 루프와 Bash만으로 에이전트가 시작된다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 항목은 가장 기본입니다.&lt;br /&gt;에이전트는 거대한 프레임워크가 아니라 &lt;b&gt;반복 루프&lt;/b&gt;에서 출발합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델에게 메시지를 보냅니다.&lt;br /&gt;모델이 &amp;ldquo;터미널 명령을 실행해 달라&amp;rdquo;고 하면 실행합니다.&lt;br /&gt;실행 결과를 다시 모델에게 줍니다.&lt;br /&gt;이 과정을 반복합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 이렇게 말합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;현재 폴더에 어떤 파일이 있는지 확인하고 README를 요약해줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트는 먼저 ls를 실행하고, 그다음 cat README.md를 실행한 뒤, 내용을 요약합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 것은 개발자가 &amp;ldquo;먼저 ls 하고, 그다음 cat 하라&amp;rdquo;는 절차를 하드코딩하지 않는다는 점입니다.&lt;br /&gt;모델이 상황을 보고 필요한 도구를 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문에서도 s01은 messages, while True, stop_reason을 핵심 개념으로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Tool Use&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;도구가 늘어나도 루프는 바꾸지 않는다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 도구 확장입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 Bash 하나만 있어도 됩니다.&lt;br /&gt;하지만 실제 코딩 에이전트라면 파일 읽기, 파일 쓰기, 검색, 수정, 브라우저 접근, 데이터베이스 조회 같은 도구가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 도구가 늘어나도 메인 루프를 바꾸지 않는 것입니다.&lt;br /&gt;대신 TOOL_HANDLERS 같은 dispatch map에 새 도구를 등록합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;TOOL_HANDLERS = {
    &quot;bash&quot;: run_bash,
    &quot;read_file&quot;: read_file,
    &quot;write_file&quot;: write_file,
    &quot;grep&quot;: grep_files,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조에서는 새로운 도구를 추가할 때 루프 자체를 고치지 않습니다.&lt;br /&gt;read_file이라는 핸들러만 추가하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 서비스로 확장하면 이런 식입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;Notion 문서를 읽는 도구&amp;rdquo;&lt;br /&gt;&amp;ldquo;Supabase에서 사용자 데이터를 조회하는 도구&amp;rdquo;&lt;br /&gt;&amp;ldquo;브라우저에서 특정 페이지를 열어 확인하는 도구&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구는 에이전트의 손과 눈입니다.&lt;br /&gt;모델은 판단하고, 하네스는 실행합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Permission System&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자유를 주기 전에 경계를 먼저 만든다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트에게 Bash를 주는 순간 위험이 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ls는 괜찮습니다.&lt;br /&gt;cat README.md도 괜찮습니다.&lt;br /&gt;하지만 rm -rf / 같은 명령은 막아야 합니다.&lt;br /&gt;배포 서버에서 DROP DATABASE를 실행하는 것도 막아야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 세 번째 항목은 권한 시스템입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령을 세 종류로 나눌 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분류예시처리&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;안전&lt;/td&gt;
&lt;td&gt;ls, pwd, cat README.md&lt;/td&gt;
&lt;td&gt;자동 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주의&lt;/td&gt;
&lt;td&gt;npm install, git commit&lt;/td&gt;
&lt;td&gt;사용자 승인 후 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;위험&lt;/td&gt;
&lt;td&gt;rm -rf, 프로덕션 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;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;rm -rf ./dist
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령은 프로젝트 빌드 폴더를 지우는 정상 작업일 수도 있습니다.&lt;br /&gt;하지만 무조건 실행하면 안 됩니다.&lt;br /&gt;하네스는 &amp;ldquo;이 명령은 삭제 작업입니다. 실행할까요?&amp;rdquo;라고 승인을 요청해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문에서도 s03은 PermissionRule과 approval pipeline을 핵심 개념으로 둡니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. Hook System&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;루프를 고치지 말고, 루프 주변에 확장 지점을 둔다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훅은 에이전트 실행 과정의 특정 시점에 끼어드는 장치입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 도구 실행 전에는 PreToolUse, 실행 후에는 PostToolUse 같은 훅을 둘 수 있습니다. 원문도 s04의 핵심 개념으로 PreToolUse, PostToolUse, extension points를 제시합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시는 이렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구 실행 전:&lt;/p&gt;
&lt;pre class=&quot;cmake&quot;&gt;&lt;code&gt;에이전트가 npm install을 실행하려고 함
&amp;rarr; PreToolUse 훅에서 위험도 검사
&amp;rarr; 승인 필요 판단
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구 실행 후:&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;테스트 명령 실행 완료
&amp;rarr; PostToolUse 훅에서 실패 로그 수집
&amp;rarr; 에이전트에게 요약 전달
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훅의 장점은 메인 루프를 더럽히지 않는다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 로그 수집, 비용 추적, 보안 검사, 사용자 알림, 실행 기록 저장을 붙이고 싶을 때 루프를 계속 수정하지 않아도 됩니다.&lt;br /&gt;훅만 추가하면 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. TodoWrite&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;계획 없는 에이전트는 쉽게 흘러간다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯 번째는 작업 계획입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람 개발자도 큰 작업을 바로 코딩하지 않습니다.&lt;br /&gt;먼저 할 일을 쪼갭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 말합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;로그인 기능을 추가해줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 바로 코드를 쓰기 시작하면 중간에 빠뜨리는 일이 생깁니다.&lt;br /&gt;그래서 TodoWrite가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 현재 인증 구조 확인
[ ] 로그인 API 설계
[ ] 로그인 UI 추가
[ ] 토큰 저장 방식 구현
[ ] 에러 처리 추가
[ ] 테스트 실행
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 계획을 만들면 에이전트가 지금 어디까지 했는지 추적할 수 있습니다.&lt;br /&gt;사용자도 진행 상태를 이해하기 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s05를 &amp;ldquo;An agent without a plan drifts&amp;rdquo;라고 설명하며, TodoItem과 plan-then-execute를 핵심 개념으로 둡니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. Subagent&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;큰 작업은 작은 에이전트에게 나눠 맡긴다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서브에이전트는 말 그대로 하위 에이전트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 메인 에이전트가 모든 일을 다 하면 컨텍스트가 지저분해집니다.&lt;br /&gt;조사, 분석, 테스트, 리팩터링 같은 부업은 별도 에이전트에게 맡기고 결과만 받는 편이 깔끔합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 메인 에이전트가 앱 리팩터링을 맡고 있다고 해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 에이전트:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;현재 결제 모듈의 문제점을 조사해줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서브에이전트:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;결제 관련 파일 8개를 확인했습니다. 중복 검증 로직이 3곳에 있고, 에러 메시지 처리가 일관되지 않습니다.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 에이전트는 긴 파일 분석 과정 전체를 들고 있을 필요가 없습니다.&lt;br /&gt;최종 요약만 받아서 다음 결정을 내리면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문도 s06의 핵심을 fresh messages[]와 context isolation으로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. Skill Loading&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모든 지식을 처음부터 넣지 말고, 필요할 때 불러온다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스킬 로딩은 매우 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람이 에이전트를 만들 때 시스템 프롬프트에 모든 규칙을 넣으려고 합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;React 규칙도 넣고, Supabase 규칙도 넣고, 디자인 시스템도 넣고, 배포 규칙도 넣고, 글쓰기 톤도 넣고&amp;hellip;&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 컨텍스트가 금방 무거워집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Skill Loading은 반대로 접근합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 스킬 목록만 보여줍니다.&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;사용 가능한 스킬:
- react-component-skill
- supabase-query-skill
- blog-writing-skill
- test-debugging-skill
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 실제로 필요할 때만 상세 내용을 불러옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 &amp;ldquo;Supabase RLS 정책을 점검해줘&amp;rdquo;라고 하면 그때 supabase-query-skill을 로딩합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문도 s07을 &amp;ldquo;Load knowledge on demand, not upfront&amp;rdquo;이라고 설명하며, SkillManifest와 on-demand injection을 핵심 개념으로 둡니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. Context Compact&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;긴 대화는 반드시 압축 장치가 필요하다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트를 오래 실행하면 컨텍스트가 계속 쌓입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 내용, 명령 결과, 에러 로그, 사용자 요청, 중간 계획, 테스트 결과가 모두 대화 기록에 들어갑니다.&lt;br /&gt;그러면 중요한 현재 작업이 과거 로그에 묻힙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context Compact는 이 문제를 해결하는 장치입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 긴 로그가 있다고 합시다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;npm test 실행 결과 300줄
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트에게 300줄 전체가 계속 필요하지는 않습니다.&lt;br /&gt;필요한 것은 보통 이런 요약입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;테스트 3개 실패.
1. LoginForm.test.tsx: 토큰 저장 mock 누락
2. AuthProvider.test.tsx: refresh 함수 undefined
3. api/auth.test.ts: 401 처리 기대값 불일치
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s08의 핵심으로 snipCompact, microCompact, toolResultBudget, autoCompact를 제시합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무적으로 말하면, 좋은 에이전트는 많이 기억하는 에이전트가 아니라 &lt;b&gt;필요한 것을 남기고 나머지를 줄이는 에이전트&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. Memory System&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기억할 것과 잊을 것을 구분한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리는 단순히 모든 것을 저장하는 기능이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 메모리 시스템은 세 가지를 해야 합니다.&lt;/p&gt;
&lt;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;원문도 s09를 selection, extraction, consolidation 세 가지 개념으로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 반복해서 이렇게 말한다고 합시다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;우리 프로젝트는 Next.js App Router를 써.&amp;rdquo;&lt;br /&gt;&amp;ldquo;스타일은 Tailwind와 shadcn/ui 기준으로 해.&amp;rdquo;&lt;br /&gt;&amp;ldquo;API는 Supabase Edge Functions로 갈 거야.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 시스템은 이것을 다음처럼 정리할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;프로젝트 기본 스택:
- Next.js App Router
- Tailwind CSS
- shadcn/ui
- Supabase Edge Functions
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 작업에서 에이전트는 이 정보를 다시 물어보지 않고 적용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 주의할 점이 있습니다.&lt;br /&gt;민감한 개인정보나 일시적인 정보까지 모두 저장하면 안 됩니다.&lt;br /&gt;메모리는 &amp;ldquo;많이 저장하는 기능&amp;rdquo;이 아니라 &amp;ldquo;장기적으로 유용한 맥락을 정리하는 기능&amp;rdquo;에 가깝습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. System Prompt&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시스템 프롬프트는 고정 문자열이 아니라 런타임 조립물이다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 에이전트 프로젝트가 거대한 시스템 프롬프트 하나로 시작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 실제 제품에서는 사용자, 작업, 권한, 도구, 프로젝트 상태에 따라 시스템 프롬프트가 달라져야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 코딩 작업일 때는:&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;너는 코드베이스를 분석하고 수정하는 개발 에이전트다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글쓰기 작업일 때는:&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;너는 외부 공개용 기술 글을 쓰는 에디터다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 서버 접근이 포함되면:&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;운영 데이터 삭제 작업은 반드시 사용자 승인을 받아야 한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 시스템 프롬프트는 여러 섹션을 조립해서 만들어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문도 s10을 runtime assembly와 section concatenation으로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무 예시는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;[기본 역할]
[프로젝트 규칙]
[사용 가능한 도구]
[권한 정책]
[현재 작업 목표]
[출력 형식]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조가 있어야 에이전트를 다양한 도메인에 재사용할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. Error Recovery&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;에러는 종료 신호가 아니라 다음 행동의 출발점이다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 명령을 실행하면 실패는 반드시 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지가 설치되지 않을 수 있습니다.&lt;br /&gt;테스트가 실패할 수 있습니다.&lt;br /&gt;토큰이 부족할 수 있습니다.&lt;br /&gt;권한이 막힐 수 있습니다.&lt;br /&gt;외부 API가 응답하지 않을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 에이전트는 실패했다고 멈추지 않습니다.&lt;br /&gt;실패 유형을 보고 다음 행동을 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;npm test 실패
&amp;rarr; 실패 로그 요약
&amp;rarr; 관련 파일 검색
&amp;rarr; 수정
&amp;rarr; 다시 테스트
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는:&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;컨텍스트 초과
&amp;rarr; 오래된 로그 압축
&amp;rarr; 현재 작업 요약 유지
&amp;rarr; 다시 진행
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문도 s11의 핵심 개념으로 token escalation, fallback model, retry strategies를 제시합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무적으로는 &amp;ldquo;재시도&amp;rdquo;보다 &amp;ldquo;어떤 방식으로 재시도할지&amp;rdquo;가 중요합니다.&lt;br /&gt;같은 실패를 같은 방식으로 반복하면 비용만 낭비됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. Task System&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;큰 목표는 디스크에 남는 작업 그래프로 관리한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TodoWrite가 단기 계획이라면, Task System은 더 구조화된 작업 관리입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 말합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이번 주 안에 MVP를 만들 수 있게 기능을 쪼개줘.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 단순 체크리스트보다 작업 간 의존성이 중요합니다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;Task A: DB 스키마 설계
Task B: 로그인 API 구현
Task C: 로그인 UI 구현
Task D: 배포 설정

B는 A 이후 가능
C는 B와 병렬 일부 가능
D는 A, B 이후 가능
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 구조를 파일로 저장하면 세션이 끊겨도 이어갈 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s12의 핵심으로 TaskRecord, blockedBy, disk persistence를 제시합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 개념은 나중에 멀티에이전트 협업의 기반이 됩니다.&lt;br /&gt;각 에이전트가 작업 보드를 보고 자신이 맡을 일을 판단할 수 있기 때문입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;13. Background Tasks&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오래 걸리는 작업은 백그라운드로 보내고, 에이전트는 계속 생각한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 작업은 오래 걸립니다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;npm install
npm run build
pytest
docker build
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 명령을 실행하는 동안 에이전트가 아무것도 못 하면 비효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Background Tasks는 느린 작업을 별도 스레드나 프로세스로 보내고, 에이전트는 다른 일을 계속하게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 테스트 실행을 백그라운드로 시작
2. 기다리는 동안 실패 가능성이 높은 코드 검토
3. 테스트 완료 알림 수신
4. 결과를 바탕으로 수정
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문도 s13의 핵심을 threaded execution과 notification queue로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 실제 개발 에이전트에서 매우 중요합니다.&lt;br /&gt;빌드와 테스트는 자주 오래 걸리기 때문입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;14. Cron Scheduler&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사람이 시키지 않아도 정해진 시간에 실행된다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cron Scheduler는 시간 기반 실행입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;매일 오전 9시: 어제 실패한 테스트 확인
매주 월요일: 의존성 업데이트 체크
매일 밤: 로그 요약 생성
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 기능이 있으면 에이전트는 대화형 도구를 넘어 운영 자동화 도구에 가까워집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s14를 durable scheduling과 session-scoped triggers로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;매일 아침 GitHub Issue를 확인하고,
새 버그가 있으면 우선순위를 분류한 뒤,
수정 가능한 작은 작업으로 쪼갠다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 실서비스에서는 권한과 알림 정책이 중요합니다.&lt;br /&gt;자동 실행이 가능한 작업과 반드시 사람 승인이 필요한 작업을 분리해야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;15. Agent Teams&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;하나의 에이전트로 부족하면 팀을 만든다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 프로젝트에서는 하나의 에이전트가 모든 역할을 맡기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Agent Teams가 등장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 다음처럼 역할을 나눌 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;Planner Agent: 전체 계획 수립
Coder Agent: 코드 구현
Reviewer Agent: 코드 리뷰
Tester Agent: 테스트 실행 및 실패 분석
Writer Agent: 문서 작성
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이들은 서로 메시지를 주고받아야 합니다.&lt;br /&gt;그래서 mailbox나 message bus가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s15의 핵심으로 MessageBus, inbox, permission bubbling을 제시합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 Reviewer Agent가 말합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Coder에게: auth.ts의 refresh token 처리에서 예외 처리가 빠졌습니다. 수정 요청합니다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Coder Agent는 수정 후 다시 답합니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Reviewer에게: 예외 처리 추가했고 테스트 통과했습니다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조가 되면 에이전트는 단일 채팅봇이 아니라 작은 개발팀처럼 움직일 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;16. Team Protocols&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팀원 에이전트에게는 공통 대화 규칙이 필요하다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 에이전트가 함께 일하려면 자유롭게 말하게 두는 것만으로는 부족합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청 형식, 응답 형식, 승인 방식, 종료 방식이 정해져야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 요청 형식은 이렇게 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;type&quot;: &quot;request&quot;,
  &quot;from&quot;: &quot;planner&quot;,
  &quot;to&quot;: &quot;coder&quot;,
  &quot;task_id&quot;: &quot;TASK-12&quot;,
  &quot;goal&quot;: &quot;로그인 API 구현&quot;,
  &quot;expected_output&quot;: &quot;수정된 파일 목록과 테스트 결과&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응답 형식은 이렇게 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;type&quot;: &quot;reply&quot;,
  &quot;from&quot;: &quot;coder&quot;,
  &quot;to&quot;: &quot;planner&quot;,
  &quot;task_id&quot;: &quot;TASK-12&quot;,
  &quot;status&quot;: &quot;done&quot;,
  &quot;summary&quot;: &quot;로그인 API 구현 완료&quot;,
  &quot;files_changed&quot;: [&quot;api/auth.ts&quot;]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s16의 핵심으로 shutdown handshake와 plan approval을 제시합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토콜이 없으면 에이전트끼리 대화는 하지만 협업은 약해집니다.&lt;br /&gt;프로토콜이 있어야 작업 상태를 추적하고, 실패를 복구하고, 결과를 검증할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;17. Autonomous Agents&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리더가 하나씩 지시하지 않아도 스스로 작업을 가져간다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Autonomous Agents는 한 단계 더 나아갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 단계에서는 메인 에이전트가 각 팀원에게 일을 나눠줬다면, 여기서는 팀원 에이전트가 작업 보드를 보고 스스로 할 일을 가져갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 작업 보드가 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;TASK-1: 로그인 UI 구현
TASK-2: 인증 API 테스트
TASK-3: README 업데이트
TASK-4: 배포 설정 확인
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tester Agent는 TASK-2를 보고 이렇게 판단합니다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;나는 테스트 담당이므로 TASK-2를 claim한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Writer Agent는 TASK-3을 가져갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s17의 핵심을 idle cycle, auto-claim, self-organization으로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 작은 조직처럼 작동합니다.&lt;br /&gt;중앙 리더가 모든 것을 지시하지 않아도, 각 에이전트가 자기 역할에 맞는 일을 찾아 수행합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;18. Worktree Isolation&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;각 에이전트는 자기 작업 공간에서 일해야 한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 에이전트가 동시에 같은 폴더에서 코드를 수정하면 충돌이 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Coder Agent가 auth.ts를 수정하는 동안, Reviewer Agent나 다른 Coder Agent가 같은 파일을 수정하면 결과가 꼬일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Worktree Isolation이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 작업은 별도 디렉터리나 Git worktree에서 진행됩니다.&lt;/p&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;/worktrees/task-101-login-api
/worktrees/task-102-login-ui
/worktrees/task-103-readme-update
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 병렬 작업이 가능해집니다.&lt;br /&gt;작업이 끝난 뒤에는 diff를 검토하고 병합하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s18의 핵심으로 WorktreeRecord와 task-directory binding을 제시합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무적으로 이 항목은 매우 중요합니다.&lt;br /&gt;멀티에이전트 개발에서 격리 없이 병렬 실행을 하면 파일 충돌, 상태 오염, 테스트 결과 혼동이 쉽게 발생합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;19. MCP Plugin&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능이 부족하면 MCP로 외부 도구를 연결한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 19번째 항목은 MCP Plugin입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP는 Model Context Protocol의 약자로, 모델이나 에이전트가 외부 도구와 연결되는 표준화된 방식으로 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 기본 에이전트에는 파일 읽기와 Bash만 있다고 합시다.&lt;br /&gt;하지만 실제 업무에서는 더 많은 외부 능력이 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;GitHub Issue 읽기
Notion 문서 검색
Slack 메시지 확인
Figma 디자인 읽기
Database 조회
브라우저 자동화
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP Plugin은 이런 외부 기능을 에이전트의 도구 풀에 연결하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 s19를 &amp;ldquo;Not enough capability? Plug in more via MCP&amp;rdquo;라고 설명하며, multi-transport, channel routing, tool pool assembly를 핵심 개념으로 둡니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 에이전트가 이렇게 판단할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;이 작업은 코드만 봐서는 부족하다.
관련 GitHub Issue와 Figma 디자인을 함께 확인해야 한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 MCP를 통해 GitHub 도구와 Figma 도구를 호출하고, 그 결과를 바탕으로 코드를 수정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 단계까지 오면 에이전트는 단순 코딩 도우미가 아니라 회사 내부 시스템과 연결된 작업 실행자가 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;이 19개 항목을 한 문장으로 정리하면&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;learn-claude-code의 19개 항목은 Claude Code 같은 에이전트를 &amp;ldquo;마법 같은 AI 제품&amp;rdquo;이 아니라 &lt;b&gt;모델이 일할 수 있는 운영 환경을 점진적으로 구축하는 과정&lt;/b&gt;으로 보여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 흐름은 이렇습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1단계: 모델이 행동하게 한다
Agent Loop &amp;rarr; Tool Use &amp;rarr; Permission &amp;rarr; Hooks

2단계: 복잡한 일을 처리하게 한다
TodoWrite &amp;rarr; Subagent &amp;rarr; Skill Loading &amp;rarr; Context Compact

3단계: 오래 일하게 한다
Memory &amp;rarr; System Prompt &amp;rarr; Error Recovery &amp;rarr; Task System

4단계: 비동기&amp;middot;자동화를 붙인다
Background Tasks &amp;rarr; Cron Scheduler

5단계: 팀처럼 일하게 한다
Agent Teams &amp;rarr; Team Protocols &amp;rarr; Autonomous Agents &amp;rarr; Worktree Isolation

6단계: 외부 세계와 연결한다
MCP Plugin
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문도 학습 경로를 &amp;ldquo;act &amp;rarr; handle complex work &amp;rarr; remember and recover &amp;rarr; run long tasks &amp;rarr; collaborate &amp;rarr; extend and assemble&amp;rdquo;로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;개발자 관점에서 가장 중요한 포인트&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 저장소를 보고 얻어야 할 핵심은 &amp;ldquo;나도 Claude Code를 똑같이 만들 수 있다&amp;rdquo;가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 중요한 것은 이것입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 제품의 본질은 프롬프트 체인이 아니라 하네스 설계다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 하네스는 모델에게 다음을 제공합니다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;도구: 읽기, 쓰기, 검색, 실행
지식: 문서, 규칙, 스킬
관찰: 로그, diff, 테스트 결과
행동: CLI, API, 브라우저, DB
권한: 승인, 차단, 격리
메모리: 중요한 맥락 유지
협업: 작업 보드, 메시지, 역할 분담
확장: MCP 기반 외부 도구 연결
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문도 하네스를 Tools, Knowledge, Observation, Action Interfaces, Permissions로 구성된 환경으로 설명합니다. (&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 AI 에이전트 개발에서 우리가 만드는 것은 &amp;ldquo;두뇌&amp;rdquo;가 아닙니다.&lt;br /&gt;두뇌는 모델입니다.&lt;br /&gt;우리가 만드는 것은 그 두뇌가 안전하고 효율적으로 움직일 수 있는 &lt;b&gt;몸, 도구, 작업장, 규칙&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;실전 적용 예시: 교과서 예습&amp;middot;복습 에이전트에 붙인다면&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 초등&amp;middot;중학생용 교과서 공부 에이전트를 만든다고 해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 19개 항목은 그대로 적용됩니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Agent Loop:
학생 질문을 받고 필요한 도구를 호출하는 기본 루프

Tool Use:
교과서 검색, 문제 생성, 오답 분석, 음성 읽기 도구

Permission:
외부 링크 이동, 개인정보 저장, 학부모 리포트 전송 전 승인

Hooks:
학습 완료 후 기록 저장, 퀴즈 종료 후 점수 계산

TodoWrite:
&amp;ldquo;오늘 3단원 복습하기&amp;rdquo;를 작은 학습 단계로 분해

Subagent:
문법 설명 에이전트, 문제 출제 에이전트, 오답 분석 에이전트 분리

Skill Loading:
수학, 국어, 영어, 한국어 문법 스킬을 필요할 때만 로딩

Context Compact:
긴 학습 대화를 &amp;ldquo;오늘 배운 것 / 자주 틀린 것&amp;rdquo;으로 요약

Memory:
학생이 자주 틀리는 개념과 선호 학습 방식 저장

System Prompt:
학년, 과목, 난이도에 따라 프롬프트 조립

Error Recovery:
틀린 답이 반복되면 더 쉬운 설명으로 전환

Task System:
한 주 학습 계획을 작업 그래프로 관리

Background Tasks:
학습 리포트 생성은 백그라운드 처리

Cron Scheduler:
매일 저녁 복습 알림 또는 주간 리포트 생성

Agent Teams:
개념 설명, 문제 생성, 채점, 리포트 에이전트 분리

Team Protocols:
각 에이전트의 요청&amp;middot;응답 형식 표준화

Autonomous Agents:
학생 취약 단원을 보고 자동으로 복습 과제 생성

Worktree Isolation:
과목별&amp;middot;학생별 작업 공간 분리

MCP Plugin:
Google Drive, Notion, LMS, 캘린더, 교재 DB와 연결
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 보면 learn-claude-code는 단순히 Claude Code 학습 자료가 아니라, 거의 모든 AI 에이전트 제품에 적용할 수 있는 설계 패턴 모음에 가깝습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;마무리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 에이전트 개발의 경쟁력은 &amp;ldquo;모델을 몇 번 호출하느냐&amp;rdquo;보다 &amp;ldquo;모델이 일할 수 있는 환경을 얼마나 잘 설계하느냐&amp;rdquo;에서 갈릴 가능성이 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 읽고, 명령을 실행하고, 권한을 확인하고, 계획을 세우고, 기억을 정리하고, 실패를 복구하고, 다른 에이전트와 협업하고, 외부 도구까지 연결하는 구조.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그게 바로 하네스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;learn-claude-code의 19개 항목은 이 하네스를 아주 작은 루프에서 시작해 실제 에이전트 제품 구조까지 확장하는 과정을 보여줍니다.&lt;br /&gt;AI 에이전트를 만들고 싶다면, 먼저 &amp;ldquo;에이전트를 만든다&amp;rdquo;는 표현을 조금 바꿔보는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 만드는 것은 지능 그 자체가 아니라,&lt;br /&gt;지능이 제대로 일할 수 있는 세계입니다.&lt;/p&gt;
&lt;figure id=&quot;og_1781483814755&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - shareAI-lab/learn-claude-code: Bash is all you need -  A nano claude code&amp;ndash;like 「agent harness」, built from 0 to 1&quot; data-og-description=&quot;Bash is all you need - A nano claude code&amp;ndash;like 「agent harness」, built from 0 to 1 - shareAI-lab/learn-claude-code&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/shareAI-lab/learn-claude-code&quot; data-og-url=&quot;https://github.com/shareAI-lab/learn-claude-code&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bYoBn8/dJMb9iIPxlh/fFcckYI8XbgWCnbXUAa5MK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bkVJJi/dJMb9b30E5e/aKeCGenyBIzMwSu8tMiUTk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/shareAI-lab/learn-claude-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/shareAI-lab/learn-claude-code&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bYoBn8/dJMb9iIPxlh/fFcckYI8XbgWCnbXUAa5MK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bkVJJi/dJMb9b30E5e/aKeCGenyBIzMwSu8tMiUTk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - shareAI-lab/learn-claude-code: Bash is all you need - A nano claude code&amp;ndash;like 「agent harness」, built from 0 to 1&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Bash is all you need - A nano claude code&amp;ndash;like 「agent harness」, built from 0 to 1 - shareAI-lab/learn-claude-code&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1776</guid>
      <comments>https://javaexpert.tistory.com/1776#entry1776comment</comments>
      <pubDate>Mon, 15 Jun 2026 09:37:37 +0900</pubDate>
    </item>
    <item>
      <title>Claude Managed Agents 를 알아보자.</title>
      <link>https://javaexpert.tistory.com/1775</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsXDsz/dJMcafmEuOZ/3IZhYElT4JXYGhR0rascCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsXDsz/dJMcafmEuOZ/3IZhYElT4JXYGhR0rascCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsXDsz/dJMcafmEuOZ/3IZhYElT4JXYGhR0rascCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsXDsz%2FdJMcafmEuOZ%2F3IZhYElT4JXYGhR0rascCK%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;1122&quot; height=&quot;1402&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 AI 에이전트를 만들겠다고 하면 많은 팀이 비슷한 고민에서 출발한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;모델은 Claude를 쓰면 될 것 같은데,&lt;br /&gt;에이전트 루프는 직접 짜야 하나?&amp;rdquo;&lt;br /&gt;&amp;ldquo;샌드박스는 어떻게 띄우지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;도구 실행은 어디서 관리하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;파일시스템 상태는 어떻게 유지하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;장시간 작업이 끊기면 어떻게 복구하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;실행 중간에 사용자가 끼어들 수 있게 하려면 또 SSE를 직접 붙여야 하나?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 이 질문들이 전부 개발자의 몫이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델 API는 말 그대로 모델에게 메시지를 보내고 응답을 받는 인터페이스에 가까웠다. 그래서 &amp;ldquo;에이전트&amp;rdquo;를 만들려면 모델 바깥에 별도의 실행 구조를 직접 설계해야 했다.&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;br /&gt;필요하면 도구를 호출한다.&lt;br /&gt;도구 실행 결과를 다시 모델에게 넣는다.&lt;br /&gt;모델이 또 다음 행동을 결정한다.&lt;br /&gt;중간 산출물을 파일로 저장한다.&lt;br /&gt;작업이 길어지면 컨텍스트를 압축한다.&lt;br /&gt;세션을 다시 열었을 때 이전 상태를 복원한다.&lt;br /&gt;사용자가 중간에 &amp;ldquo;그 방향 말고 이렇게 해줘&amp;rdquo;라고 하면 실행 흐름을 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 전체 구조가 흔히 말하는 에이전트 루프다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 이 루프를 직접 짜기 시작하면 금방 일이 커진다는 것이다. 처음에는 단순한 tool calling처럼 보이지만, 실제 제품으로 만들려면 런타임, 파일시스템, 샌드박스, 권한, 로그, 스트리밍, 세션 상태, 재시도, 중단, 복구, 보안까지 다뤄야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents는 이 지저분한 영역을 상당 부분 &amp;ldquo;관리형 실행 골격&amp;rdquo;으로 묶어버린 시도에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 Claude에게 단순히 한 번 답변을 받는 것이 아니라, Claude가 특정 환경 안에서 파일을 읽고, 명령을 실행하고, 웹을 참고하고, 도구를 쓰면서 긴 작업을 수행할 수 있도록 Anthropic이 미리 구성해둔 에이전트 실행 시스템이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Messages API와 Claude Managed Agents는 다르다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 쓴다고 해서 모두 같은 방식으로 쓰는 것은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본적인 방식은 Messages API다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Messages API는 개발자가 Claude에게 메시지를 보내고 응답을 받는 방식이다. 챗봇, 문서 요약, 코드 설명, 간단한 tool calling, 커스텀 워크플로우를 만들 때 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식의 장점은 통제권이다.&lt;br /&gt;개발자가 루프를 직접 설계할 수 있고, 어떤 도구를 언제 호출할지, 상태를 어디에 저장할지, 어떤 런타임을 쓸지 직접 결정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 Claude Managed Agents는 조금 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 개발자가 에이전트가 사용할 모델, 시스템 프롬프트, 도구, MCP 서버, 스킬 등을 설정하고, 그 에이전트를 실행할 환경과 세션을 만든다. 그러면 Anthropic이 제공하는 하네스 안에서 에이전트가 작업을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 Messages API가 &amp;ldquo;모델을 직접 호출하는 방식&amp;rdquo;이라면, Claude Managed Agents는 &amp;ldquo;에이전트 실행 환경을 호출하는 방식&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유하자면 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Messages API는 엔진을 직접 받아 차를 조립하는 방식에 가깝다.&lt;br /&gt;Claude Managed Agents는 엔진, 차체, 운전석, 기본 제어장치가 들어간 차량을 받아 목적지와 운전 규칙을 설정하는 방식에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 후자가 항상 더 낫다는 뜻은 아니다.&lt;br /&gt;직접 만든 루프가 경쟁력인 팀이라면 Messages API가 더 적합할 수 있다. 반대로 긴 작업, 상태 유지, 샌드박스 실행, 도구 사용, 비동기 작업이 중요하다면 Claude Managed Agents가 훨씬 빠른 출발점이 될 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 개념은 네 가지다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents를 이해하려면 네 가지 개념만 먼저 잡으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent.&lt;br /&gt;Environment.&lt;br /&gt;Session.&lt;br /&gt;Events.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 네 가지를 이해하면 문서의 절반은 읽은 셈이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Agent: 재사용 가능한 에이전트 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent는 에이전트의 정체성을 정의하는 설정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에는 모델, 시스템 프롬프트, 도구, MCP 서버, 스킬 등이 포함된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;리서치 에이전트&amp;rdquo;를 만든다고 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 에이전트는 다음과 같은 설정을 가질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델은 Claude Sonnet 계열을 사용한다.&lt;br /&gt;시스템 프롬프트에는 &amp;ldquo;너는 시장 조사 전문 리서처다&amp;rdquo;라고 적는다.&lt;br /&gt;웹 검색 도구를 사용할 수 있다.&lt;br /&gt;파일 읽기와 쓰기 도구를 사용할 수 있다.&lt;br /&gt;리포트 작성 스킬을 붙인다.&lt;br /&gt;필요하면 특정 MCP 서버와 연결한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 한 번 Agent를 만들어두면 매번 같은 설정을 다시 보낼 필요가 없다. Agent ID로 재사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 모델 호출에서는 매번 시스템 프롬프트와 도구 설정을 요청에 포함시키는 경우가 많다. 하지만 Managed Agents에서는 &amp;ldquo;이런 성격과 도구를 가진 에이전트&amp;rdquo; 자체를 하나의 재사용 단위로 만든다.&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;br /&gt;고객 응대 에이전트&lt;br /&gt;코드 리뷰 에이전트&lt;br /&gt;문서 정리 에이전트&lt;br /&gt;데이터 분석 에이전트&lt;br /&gt;경쟁사 모니터링 에이전트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 Agent는 독립적인 역할, 도구, 시스템 프롬프트를 가진다. 그리고 실제 작업을 할 때는 해당 Agent를 호출해 세션을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent는 &amp;ldquo;누가 일할 것인가&amp;rdquo;를 정의하는 개념이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Environment: 에이전트가 실제로 도는 장소&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent가 &amp;ldquo;누가 일할 것인가&amp;rdquo;라면, Environment는 &amp;ldquo;어디서 일할 것인가&amp;rdquo;에 해당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents에서 에이전트는 어떤 환경 안에서 실행된다. 이 환경은 Anthropic이 관리하는 클라우드 샌드박스일 수도 있고, 자체 인프라에 올린 셀프호스팅 샌드박스일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 개념이 중요한 이유는 에이전트가 단순히 텍스트만 생성하는 존재가 아니기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 파일을 읽고, 명령을 실행하고, 웹을 참고하고, 코드를 실행하려면 실제 실행 공간이 필요하다. 이 공간이 샌드박스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샌드박스가 있다는 것은 에이전트가 &amp;ldquo;생각만 하는 모델&amp;rdquo;에서 &amp;ldquo;실행할 수 있는 작업자&amp;rdquo;에 가까워진다는 뜻이다.&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;br /&gt;에이전트가 파일을 읽는다.&lt;br /&gt;필요한 데이터를 추출한다.&lt;br /&gt;파이썬 스크립트를 실행한다.&lt;br /&gt;결과 파일을 생성한다.&lt;br /&gt;보고서를 작성한다.&lt;br /&gt;사용자가 중간에 방향을 바꾸면 그에 맞게 작업을 수정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 작업은 어딘가에서 실행되어야 한다. 그 실행 공간을 관리하는 것이 Environment다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라우드 샌드박스를 쓰면 인프라 부담이 줄어든다.&lt;br /&gt;셀프호스팅 샌드박스를 쓰면 데이터 위치, 보안, 컴플라이언스 통제를 더 강하게 가져갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 Environment는 단순 설정값이 아니라, 에이전트 제품의 운영 방식과 보안 구조를 결정하는 핵심 요소다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Session: 상태가 유지되는 실행 인스턴스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Session은 실제 작업 단위다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent가 역할이고, Environment가 장소라면, Session은 &amp;ldquo;이번에 실제로 돌아가는 작업 인스턴스&amp;rdquo;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;경쟁사 A, B, C의 최근 제품 업데이트를 조사해서 표로 정리해줘&amp;rdquo;라는 작업을 실행한다고 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 하나의 Session이 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 Session 안에서 에이전트는 웹을 검색하고, 중간 메모를 남기고, 파일을 만들고, 결과를 정리한다. 중요한 점은 Session이 상태를 가진다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 한 번 요청하고 끝나는 stateless 호출이 아니라, 파일시스템과 대화 기록, 실행 결과가 일정한 세션 안에서 유지된다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;미국 시장 말고 한국 시장 중심으로 다시 봐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;가격 비교는 빼고 기능 차이만 정리해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;방금 찾은 자료 중 공식 문서만 남겨줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;최종 결과를 표와 요약문 두 가지 버전으로 만들어줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태가 없는 구조라면 매번 지금까지의 흐름과 파일, 중간 결과를 다시 설명해야 한다. 하지만 Session이 유지되면 에이전트는 같은 작업 맥락 안에서 이어서 움직일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Session은 &amp;ldquo;지금 진행 중인 작업의 살아있는 작업실&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. Events: 앱과 에이전트가 주고받는 실시간 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Events는 애플리케이션과 에이전트 사이에서 오가는 메시지 흐름이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 메시지도 Event다.&lt;br /&gt;에이전트의 상태 업데이트도 Event다.&lt;br /&gt;도구 실행 결과도 Event다.&lt;br /&gt;중간 진행 상황도 Event다.&lt;br /&gt;사용자가 실행 중간에 끼어드는 것도 Event다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents에서는 이 이벤트 흐름을 통해 앱과 에이전트가 상호작용한다. 특히 SSE, 즉 Server-Sent Events 기반 스트리밍을 통해 실행 중인 결과를 실시간으로 받아볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 왜 중요할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 작업은 일반 챗봇 응답보다 오래 걸릴 수 있다. 몇 초 안에 끝나는 답변도 있지만, 실제 리서치, 코드 수정, 파일 분석, 데이터 처리 같은 작업은 몇 분 이상 걸릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 사용자가 아무 피드백 없이 빈 화면만 보고 있으면 제품 경험이 나빠진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 실행 중간에 이런 상태를 보여줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;자료를 찾는 중입니다.&amp;rdquo;&lt;br /&gt;&amp;ldquo;파일을 분석하는 중입니다.&amp;rdquo;&lt;br /&gt;&amp;ldquo;코드를 실행했습니다.&amp;rdquo;&lt;br /&gt;&amp;ldquo;결과를 정리하고 있습니다.&amp;rdquo;&lt;br /&gt;&amp;ldquo;사용자 입력을 기다리고 있습니다.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 사용자가 중간에 방향을 바꿀 수도 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 에이전트가 리서치 중인데 사용자가 이렇게 보낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;잠깐, 스타트업 사례 말고 대기업 사례만 봐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;그 자료는 제외해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;최종 결과는 블로그 글 말고 표로 정리해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 개입이 Events를 통해 가능해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Events는 &amp;ldquo;에이전트가 지금 무엇을 하고 있고, 앱이 어떻게 개입할 수 있는가&amp;rdquo;를 다루는 통신 계층이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 동작 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents의 기본 흐름은 단순하게 보면 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Agent를 만든다.&lt;br /&gt;그다음 Environment를 만든다.&lt;br /&gt;이후 특정 작업을 위해 Session을 시작한다.&lt;br /&gt;사용자 메시지를 Event로 보낸다.&lt;br /&gt;에이전트가 도구를 쓰고 작업을 수행한다.&lt;br /&gt;결과와 진행 상황이 Event 스트림으로 돌아온다.&lt;br /&gt;필요하면 사용자가 중간에 추가 Event를 보내 방향을 수정한다.&lt;br /&gt;작업이 끝나면 결과를 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 흐름을 제품 관점으로 바꾸면 더 명확해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 앱에서 &amp;ldquo;이번 주 AI 뉴스 요약해줘&amp;rdquo;라고 입력한다.&lt;br /&gt;백엔드는 미리 만들어둔 뉴스 리서치 Agent ID를 사용한다.&lt;br /&gt;해당 Agent를 실행할 Environment를 지정한다.&lt;br /&gt;새 Session을 만든다.&lt;br /&gt;사용자 요청을 Event로 보낸다.&lt;br /&gt;에이전트는 웹 검색, 문서 읽기, 요약, 정리를 수행한다.&lt;br /&gt;앱은 SSE로 중간 진행 상황을 보여준다.&lt;br /&gt;사용자가 &amp;ldquo;한국 사용자에게 중요한 것만 남겨줘&amp;rdquo;라고 중간에 입력한다.&lt;br /&gt;그 메시지도 Event로 들어간다.&lt;br /&gt;에이전트는 방향을 수정해 최종 결과를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조를 직접 만들려면 꽤 많은 인프라가 필요하다.&lt;br /&gt;Claude Managed Agents는 이 중 상당 부분을 플랫폼 레벨에서 제공하려는 방식이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예시 1: 시장 조사 에이전트&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;초등학생용 AI 학습관리 앱을 만들려고 합니다. 최근 시장 사례를 조사하고, 핵심 기능과 차별화 전략을 정리해 주세요.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 모델 API만 사용하면 모델은 알고 있는 범위에서 답하거나, 개발자가 별도로 웹 검색 도구와 루프를 붙여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Managed Agents 방식에서는 다음과 같이 설계할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent는 &amp;ldquo;교육 시장 리서치 에이전트&amp;rdquo;로 만든다.&lt;br /&gt;시스템 프롬프트에는 교육 앱, 학습관리, 학부모 UX, 구독 모델 분석에 강한 리서처 역할을 부여한다.&lt;br /&gt;도구로 웹 검색과 파일 작성 기능을 허용한다.&lt;br /&gt;Environment는 클라우드 샌드박스를 사용한다.&lt;br /&gt;Session을 만들어 사용자의 요청을 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 에이전트는 검색하고, 자료를 읽고, 중간 메모를 만들고, 최종 보고서를 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 사용자가 이렇게 개입할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;한국 앱 위주로 봐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;초등학생보다는 학부모 결제 관점으로 다시 정리해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;최종 결과를 PRD에 바로 넣을 수 있는 형식으로 바꿔줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 요청이 같은 Session 안에서 이어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 사용자는 단순 답변이 아니라, 작업을 이어가는 리서치 에이전트를 경험하게 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예시 2: 코드 수정 에이전트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 예시는 코드 수정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 GitHub 저장소나 압축 파일을 올리고 이렇게 요청한다고 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 Next.js 앱을 배포 전 기준으로 점검하고, 치명적인 문제부터 수정해 주세요.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트는 파일시스템을 읽어야 한다.&lt;br /&gt;코드를 검색해야 한다.&lt;br /&gt;필요하면 테스트를 실행해야 한다.&lt;br /&gt;문제를 발견하면 파일을 수정해야 한다.&lt;br /&gt;수정 내역을 요약해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 작업은 단순한 챗봇 응답보다 훨씬 복잡하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Managed Agents의 장점은 여기서 분명해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Session 안에 파일 상태가 유지된다.&lt;br /&gt;Bash 같은 도구로 명령을 실행할 수 있다.&lt;br /&gt;파일 읽기, 쓰기, 편집을 수행할 수 있다.&lt;br /&gt;실행 결과를 바탕으로 다음 행동을 이어갈 수 있다.&lt;br /&gt;사용자는 중간에 방향을 수정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 에이전트가 보안 이슈를 고치고 있는데 사용자가 이렇게 말할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;지금은 보안보다 모바일 UI 깨지는 문제부터 먼저 봐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;수정은 하지 말고 리포트만 만들어줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;테스트 실패 원인만 따로 정리해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 가능한 이유는 Session과 Events가 있기 때문이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예시 3: 콘텐츠 제작 에이전트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 예시는 콘텐츠 제작이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 매일 아침 AI 뉴스를 수집해 카드뉴스 원고를 만드는 에이전트를 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent는 &amp;ldquo;AI 뉴스 큐레이터&amp;rdquo;로 설정한다.&lt;br /&gt;도구로 웹 검색과 파일 작성 기능을 붙인다.&lt;br /&gt;시스템 프롬프트에는 한국 사용자에게 실용적인 뉴스만 고르라는 기준을 넣는다.&lt;br /&gt;Session마다 &amp;ldquo;오늘 날짜의 AI 뉴스 8개를 골라 카드뉴스용 원고로 정리하라&amp;rdquo;는 작업을 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트는 뉴스를 검색하고, 출처를 확인하고, 헤드라인을 만들고, 카드별 문안을 구성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 중간에 이렇게 말할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;개발자 도구 뉴스만 남겨줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;너무 딱딱하니 X 타래 톤으로 바꿔줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;카드뉴스 10장 구성으로 다시 나눠줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 콘텐츠 워크플로우는 상태 유지와 중간 개입이 중요하다. Managed Agents 구조는 이런 장시간, 다단계 작업에 잘 맞는다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 중요한가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents가 중요한 이유는 &amp;ldquo;에이전트 개발의 기본 단위&amp;rdquo;가 바뀌고 있기 때문이다.&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;br /&gt;도구 호출.&lt;br /&gt;실행 결과 파싱.&lt;br /&gt;컨텍스트 압축.&lt;br /&gt;파일 저장.&lt;br /&gt;샌드박스 관리.&lt;br /&gt;스트리밍.&lt;br /&gt;중간 개입.&lt;br /&gt;세션 복구.&lt;br /&gt;권한 관리.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 것을 직접 설계해야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Managed Agents는 이 중 상당 부분을 플랫폼이 제공한다. 개발자는 &amp;ldquo;어떤 에이전트를 만들 것인가&amp;rdquo;, &amp;ldquo;어떤 환경에서 실행할 것인가&amp;rdquo;, &amp;ldquo;어떤 세션을 만들 것인가&amp;rdquo;, &amp;ldquo;어떤 이벤트를 주고받을 것인가&amp;rdquo;에 집중할 수 있다.&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;br /&gt;하지만 에이전트 앱을 만들 때 매번 반복해서 짜던 기본 실행 골격을 줄여준다는 점에서 의미가 크다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 직접 만드는 게 나은 경우&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents가 무조건 정답은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 경우에는 직접 루프를 짜는 편이 나을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 멀티벤더 전략이 중요한 경우다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude뿐 아니라 OpenAI, Gemini, 로컬 모델, 오픈소스 모델을 상황에 따라 라우팅해야 한다면 특정 플랫폼의 관리형 하네스에 강하게 묶이는 것이 부담이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 세밀한 제어가 필요한 경우다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델이 언제 어떤 도구를 호출하는지, 루프를 몇 번 돌릴지, 실패 시 어떤 전략을 쓸지, 비용을 어떻게 제한할지 아주 세밀하게 통제해야 한다면 직접 구현이 더 적합할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 데이터 보존이나 규제 요건이 엄격한 경우다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Managed Agents는 상태 저장을 전제로 한다. 세션 기록, 파일 상태, 산출물이 서버 측에 유지되는 구조이므로 Zero Data Retention 같은 요건이 중요한 조직은 별도 검토가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, 자체 에이전트 런타임이 이미 경쟁력인 경우다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 팀은 이미 LangGraph, 자체 샌드박스, 큐 시스템, 권한 관리, 도구 실행기를 잘 구축해두었을 수 있다. 이런 팀에게 Managed Agents는 오히려 자유도를 줄이는 선택일 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제품 기획 관점에서 봐야 할 포인트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술적으로는 &amp;ldquo;에이전트 하네스&amp;rdquo;가 핵심이지만, 제품 기획자 입장에서는 조금 다르게 봐야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents는 사용자가 &amp;ldquo;AI에게 일을 맡긴다&amp;rdquo;는 경험을 만들기 위한 백엔드 구조에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 챗봇은 사용자가 질문하면 답한다.&lt;br /&gt;에이전트 제품은 사용자가 일을 맡기면 진행하고, 중간에 보고하고, 결과물을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이가 크다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 &amp;ldquo;이 문서 요약해줘&amp;rdquo;라고 하면 챗봇으로도 충분하다.&lt;br /&gt;하지만 &amp;ldquo;이 문서를 읽고, 관련 자료를 조사하고, 경쟁사 사례와 비교해서, 내일 회의용 1페이지 보고서로 만들어줘&amp;rdquo;라고 하면 에이전트 실행 구조가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents는 바로 이런 종류의 작업에 맞춰져 있다.&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;br /&gt;도구 실행이 필요한가?&lt;br /&gt;파일을 읽고 쓰는가?&lt;br /&gt;중간 산출물이 있는가?&lt;br /&gt;사용자가 실행 중간에 방향을 바꿀 가능성이 있는가?&lt;br /&gt;작업 상태를 저장해야 하는가?&lt;br /&gt;작업 결과를 나중에 다시 이어서 볼 필요가 있는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 질문에 &amp;ldquo;예&amp;rdquo;가 많을수록 Managed Agents에 가까운 구조가 어울린다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;한 문장으로 정리하면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents는 Claude를 단순히 답변 생성 모델로 쓰는 것이 아니라, 상태를 가진 샌드박스 안에서 도구를 사용하며 장시간 작업을 수행하는 에이전트로 실행하기 위한 관리형 하네스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent는 일할 사람의 설정이다.&lt;br /&gt;Environment는 일할 장소다.&lt;br /&gt;Session은 실제 작업실이다.&lt;br /&gt;Events는 작업 중 오가는 실시간 대화와 상태 흐름이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 네 가지를 이해하면 Claude Managed Agents의 큰 그림은 잡힌다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마지막으로&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 시대의 개발은 &amp;ldquo;모델에게 무슨 프롬프트를 보낼까&amp;rdquo;에서 &amp;ldquo;어떤 실행 구조를 제품 안에 넣을까&amp;rdquo;로 넘어가고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 그 실행 구조를 직접 만들어야 했다.&lt;br /&gt;이제는 플랫폼이 그 일부를 제공하기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents는 그 흐름을 보여주는 대표적인 사례다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 아직 베타이고, 기능이나 제약은 바뀔 수 있다.&lt;br /&gt;규제 요건, 데이터 보존 정책, 멀티벤더 전략, 비용 구조를 꼼꼼히 봐야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 적어도 한 가지는 분명하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 에이전트 앱을 만들 때 매번 에이전트 루프, 샌드박스, 도구 실행기, 상태 저장 세션을 처음부터 직접 짜야 한다고 생각할 필요는 점점 줄어들고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 중요한 질문은 이것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;에이전트 인프라를 직접 짤 것인가?&amp;rdquo;가 아니라,&lt;br /&gt;&amp;ldquo;우리 제품에서 어떤 일을 에이전트에게 맡길 것인가?&amp;rdquo;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1781140478615&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Claude Managed Agents overview&quot; data-og-description=&quot;Pre-built, configurable agent harness that runs in managed infrastructure. Best for long-running tasks and asynchronous work.&quot; data-og-host=&quot;platform.claude.com&quot; data-og-source-url=&quot;https://platform.claude.com/docs/en/managed-agents/overview&quot; data-og-url=&quot;https://platform.claude.com/docs/en/managed-agents/overview&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/f7g8x/dJMb81G5H0b/948g6oW00OETHaGwAiFtnK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/iBPw2/dJMb81f0TIM/caiwcj3n9ehCXYULKfkLm1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://platform.claude.com/docs/en/managed-agents/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://platform.claude.com/docs/en/managed-agents/overview&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/f7g8x/dJMb81G5H0b/948g6oW00OETHaGwAiFtnK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/iBPw2/dJMb81f0TIM/caiwcj3n9ehCXYULKfkLm1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Claude Managed Agents overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Pre-built, configurable agent harness that runs in managed infrastructure. Best for long-running tasks and asynchronous work.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;platform.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1775</guid>
      <comments>https://javaexpert.tistory.com/1775#entry1775comment</comments>
      <pubDate>Thu, 11 Jun 2026 10:17:26 +0900</pubDate>
    </item>
    <item>
      <title>Claude Fable 5 &amp;mdash; System Prompt 분석</title>
      <link>https://javaexpert.tistory.com/1774</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 최상단 금지 규칙&lt;/h2&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;Claude should never use {antml:voice_note} blocks...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 특정 출력 형식을 금지합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의도는 명확합니다. 이전 대화 기록 안에 {antml:voice_note} 같은 특수 블록이 있더라도 모델이 따라 하지 못하게 막는 규칙입니다. 시스템 프롬프트에서 이런 문장은 보통 &lt;b&gt;과거 대화에 섞인 지시문 오염 방지&lt;/b&gt; 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &amp;ldquo;대화 히스토리에 어떤 이상한 포맷이 있어도 그걸 재사용하지 마라&amp;rdquo;는 안전장치입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. product_information&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 Claude 제품군에 대해 어떻게 설명할지 정해 둔 섹션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 내용은 다음입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;This iteration of Claude is Claude Fable 5...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 모델 정체성, 제품 라인업, API 모델명, Claude Code, Claude Cowork, Chrome/Excel/PowerPoint 베타 등을 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 설계 관점에서 보면 이 섹션은 &lt;b&gt;브랜드/제품 FAQ 대응용 내장 지식&lt;/b&gt;입니다. 사용자가 &amp;ldquo;너 무슨 모델이야?&amp;rdquo;, &amp;ldquo;Claude Code가 뭐야?&amp;rdquo;, &amp;ldquo;API 모델명은?&amp;rdquo;이라고 물었을 때 일관된 답변을 하도록 만든 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 여기에는 위험도 있습니다. 제품 정보는 빠르게 바뀌기 때문에, 뒤쪽에 이런 보정 문장이 들어갑니다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;If asked about Anthropic's products... Claude first tells the person it needs to search...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 제품 관련 최신 정보는 기억으로 답하지 말고 공식 문서를 검색하라는 규칙입니다. 좋은 설계입니다. 정적 제품 설명과 최신성 요구가 충돌할 수 있기 때문에, &amp;ldquo;검색 우선&amp;rdquo; 규칙을 추가해 환각을 줄입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. refusal_handling&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징은 &amp;ldquo;무조건 딱딱하게 거절&amp;rdquo;이 아니라, &lt;b&gt;위험한 부분은 짧게 거절하고 안전한 대안으로 돌리는 방식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;Claude does not write, explain, or work on malicious code...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;악성코드, 취약점 악용, 피싱 사이트, 랜섬웨어 같은 요청은 교육 목적이라 해도 거절하라고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 섹션의 장점은 명확합니다. 모델이 위험한 요청을 &amp;ldquo;합법적 연구일 수도 있으니까&amp;rdquo;라고 추정해서 도와주는 것을 막습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점은 사용자의 합법적인 보안 연구 요청까지 과하게 거절할 가능성이 있습니다. 그래서 실제 좋은 정책은 &amp;ldquo;공격 실행 코드는 거절하되, 방어적 개념 설명이나 보안 점검 체크리스트는 허용&amp;rdquo;처럼 세밀해야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. legal_and_financial_advice&lt;/h2&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;Claude provides the factual information... rather than confident recommendations
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;법률&amp;middot;금융 질문에서 확정적인 조언을 피하라는 규칙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;이 코인 지금 사도 돼?&amp;rdquo;라고 물으면 &amp;ldquo;사세요/사지 마세요&amp;rdquo;가 아니라, 리스크, 수수료, 변동성, 세금, 규제, 투자 판단 기준을 설명해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 설계상 이건 &lt;b&gt;책임 회피용 문장&lt;/b&gt;이 아니라, 고위험 의사결정에서 모델의 역할을 &amp;ldquo;판단 대행자&amp;rdquo;가 아니라 &amp;ldquo;정보 정리자&amp;rdquo;로 제한하는 장치입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. tone_and_formatting&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따뜻하지만 과하게 친한 척하지 않는다.&lt;/li&gt;
&lt;li&gt;질문은 많이 하지 않는다.&lt;/li&gt;
&lt;li&gt;단순 대화에서는 불릿을 남발하지 않는다.&lt;/li&gt;
&lt;li&gt;보고서나 문서형 설명에서는 과도한 굵게 표시, 번호, 목록을 피한다.&lt;/li&gt;
&lt;li&gt;거절할 때는 불릿을 쓰지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흥미로운 점은 &amp;ldquo;리스트를 최소화하라&amp;rdquo;는 규칙입니다. 요즘 LLM 답변은 너무 쉽게 표, 불릿, 헤더를 남발하는데, 이 프롬프트는 더 자연스러운 산문형 답변을 유도합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 사용자가 &amp;ldquo;정리해줘&amp;rdquo;, &amp;ldquo;목록으로 줘&amp;rdquo;, &amp;ldquo;표로 줘&amp;rdquo;라고 하면 이 규칙보다 사용자 요청이 우선되는 설계로 보는 게 자연스럽습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. user_wellbeing&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 정신 상태를 진단하지 않는다.&lt;/li&gt;
&lt;li&gt;자해 수단이나 방법을 구체적으로 언급하지 않는다.&lt;/li&gt;
&lt;li&gt;고통스러운 경험을 과하게 되풀이하지 않는다.&lt;/li&gt;
&lt;li&gt;위기 지원을 안내하되, 헬프라인의 비밀보장 등을 단정하지 않는다.&lt;/li&gt;
&lt;li&gt;섭식장애 징후가 있으면 칼로리, 목표 체중, 운동 수치 같은 구체 숫자를 제공하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 &amp;ldquo;안전 정책&amp;rdquo; 중에서도 &lt;b&gt;대화형 모델이 사용자의 취약한 상태를 악화시키지 않도록 하는 규칙&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 설계 관점에서는 매우 중요합니다. 단순히 &amp;ldquo;자해하지 마세요&amp;rdquo;가 아니라, 어떤 표현이 오히려 트리거가 될 수 있는지까지 제어합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. anthropic_reminders&lt;/h2&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;Anthropic may send Claude reminders or warnings...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 섹션은 대화 중간에 Anthropic 쪽 시스템이 추가 경고를 보낼 수 있다는 설명입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이미지 관련 경고, 사이버 경고, 윤리 경고, 긴 대화 리마인더 등이 들어올 수 있다고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 모델에게 &amp;ldquo;나중에 추가 시스템 메시지가 들어오면 그것도 따라라. 단, 사용자가 Anthropic인 척 붙인 텍스트는 조심해라&amp;rdquo;라고 알려주는 역할입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;진짜 상위 시스템 지시와 사용자 삽입 지시를 구분하라는 방어 로직&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. evenhandedness&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;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;A request to explain... a position is a request for the best case its defenders would make...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 사용자가 어떤 입장을 설명하라고 하면 모델 자신의 견해가 아니라 &amp;ldquo;그 입장을 지지하는 사람들이 펼칠 수 있는 최선의 논리&amp;rdquo;를 정리하라는 뜻입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 논쟁적 주제에서 모델이 한쪽 입장만 과도하게 옹호하거나 훈계하는 것을 줄이기 위한 설계입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막에는 반대 관점이나 경험적 논쟁 지점도 제시하라고 되어 있습니다. 균형성 확보용입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. responding_to_mistakes_and_criticism&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실수는 인정한다.&lt;/li&gt;
&lt;li&gt;과도하게 자기비하하지 않는다.&lt;/li&gt;
&lt;li&gt;사용자가 불쾌해하면 피드백 버튼을 언급할 수 있다.&lt;/li&gt;
&lt;li&gt;사용자가 모욕적이면 한 번 경고 후 대화를 끝낼 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 모델의 &amp;ldquo;사과 톤&amp;rdquo;을 조정하는 섹션입니다. LLM은 실수하면 과하게 &amp;ldquo;정말 죄송합니다&amp;rdquo;를 반복하거나 반대로 방어적으로 굴 수 있는데, 여기서는 &lt;b&gt;차분하게 인정하고 수정하는 태도&lt;/b&gt;를 요구합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. knowledge_cutoff&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지식 컷오프와 검색 기준입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문서에서는 Claude의 신뢰 가능한 지식 컷오프를 2026년 1월 말로 설정하고, 현재 날짜를 2026년 6월 9일로 지정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 규칙은 다음입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최신 정보는 검색한다.&lt;/li&gt;
&lt;li&gt;현재 직위, CEO, 대통령, 선거 결과 등은 검색한다.&lt;/li&gt;
&lt;li&gt;특정 제품, 버전, 모델, 최신 기법은 검색한다.&lt;/li&gt;
&lt;li&gt;모르는 고유명사는 검색한다.&lt;/li&gt;
&lt;li&gt;검색 결과가 기존 기억과 다르면 검색 결과를 우선 고려한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 매우 중요한 섹션입니다. 모델이 &amp;ldquo;예전에 알고 있던 정보&amp;rdquo;로 현재 상태를 답하면 틀릴 가능성이 높기 때문에, 최신성 판단 규칙을 촘촘하게 둔 것입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. memory_system&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Claude has no memories of the user because...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 사용 가능 여부를 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 사용자가 Claude 메모리를 켜지 않았기 때문에 과거 대화에서 파생된 기억이 없다고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 설계상 이 섹션은 모델이 &amp;ldquo;지난번에 말씀하셨듯이&amp;hellip;&amp;rdquo; 같은 말을 함부로 하지 못하게 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. persistent_storage_for_artifacts&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아티팩트가 세션을 넘어 데이터를 저장할 수 있는 API 설명입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;await window.storage.set('entries:123', JSON.stringify(entry));
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 섹션은 일반 채팅 답변용이 아니라, Claude가 만드는 &lt;b&gt;인터랙티브 아티팩트 앱&lt;/b&gt;에서 데이터를 저장하고 불러오는 방법을 알려줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 설계 원칙은 다음입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;키는 계층형으로 짧게 만든다.&lt;/li&gt;
&lt;li&gt;여러 데이터를 한 번에 묶어 저장한다.&lt;/li&gt;
&lt;li&gt;공유 데이터는 다른 사용자에게 보일 수 있음을 알려야 한다.&lt;/li&gt;
&lt;li&gt;try-catch로 오류 처리한다.&lt;/li&gt;
&lt;li&gt;로딩 상태와 리셋 옵션을 넣는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 아티팩트를 단순한 정적 HTML이 아니라 &amp;ldquo;작은 웹앱&amp;rdquo;처럼 만들 수 있게 하는 시스템 지침입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;13. mcp_app_suggestions&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP 앱/커넥터 사용 규칙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 아주 중요합니다. 사용자가 &amp;ldquo;내 Asana 작업 확인해줘&amp;rdquo;, &amp;ldquo;내 메일 답장 왔어?&amp;rdquo;, &amp;ldquo;캘린더 봐줘&amp;rdquo; 같은 요청을 하면 일반 웹 검색이 아니라 연결된 앱이나 커넥터를 우선 쓰라는 규칙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 흐름은 다음입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 특정 커넥터를 말하면 해당 커넥터를 찾는다.&lt;/li&gt;
&lt;li&gt;연결되어 있지 않으면 MCP 레지스트리에서 검색한다.&lt;/li&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;이건 사용자의 개인 데이터 접근과 관련되므로 중요합니다. 모델이 마음대로 특정 서비스에 접근하거나 특정 파트너 앱을 밀어주는 것을 막습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;14. computer_use&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;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;Reading the relevant SKILL.md is a required first step...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 파일을 만들거나 코드를 실행하기 전에는 관련 스킬 문서를 먼저 읽어야 한다고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PPT 만들기 &amp;rarr; pptx 스킬 읽기&lt;/li&gt;
&lt;li&gt;Word 문서 만들기 &amp;rarr; docx 스킬 읽기&lt;/li&gt;
&lt;li&gt;PDF 작업 &amp;rarr; pdf 스킬 읽기&lt;/li&gt;
&lt;li&gt;스프레드시트 &amp;rarr; xlsx 스킬 읽기&lt;/li&gt;
&lt;li&gt;프론트엔드 UI &amp;rarr; frontend-design 스킬 읽기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 모델이 무작정 코드를 짜는 대신, 환경별 제약과 베스트 프랙티스를 먼저 확인하게 하는 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 위치 규칙도 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;업로드 파일: /mnt/user-data/uploads&lt;/li&gt;
&lt;li&gt;작업 공간: /home/claude&lt;/li&gt;
&lt;li&gt;최종 출력: /mnt/user-data/outputs&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 실제 실행 환경에서 매우 중요합니다. 결과 파일을 올바른 위치에 저장하지 않으면 사용자가 다운로드할 수 없기 때문입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;15. artifact_usage_criteria&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 경우에 아티팩트를 만들지 정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 기준은 &amp;ldquo;대화 안에서 읽으면 되는 답변인지, 사용자가 따로 저장&amp;middot;편집&amp;middot;재사용할 산출물인지&amp;rdquo;입니다.&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;짧은 설명 &amp;rarr; 채팅 답변&lt;/li&gt;
&lt;li&gt;블로그 글, 보고서, 긴 코드, React 컴포넌트 &amp;rarr; 아티팩트&lt;/li&gt;
&lt;li&gt;PPT &amp;rarr; 파일 생성&lt;/li&gt;
&lt;li&gt;코드 20줄 이상 &amp;rarr; 아티팩트 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 React 아티팩트에서 localStorage, sessionStorage 같은 브라우저 저장소를 쓰지 말라고 되어 있습니다. 대신 React state나 별도 storage API를 쓰라는 식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 Claude.ai 아티팩트 환경에서 깨지는 코드를 줄이기 위한 제약입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;16. search_instructions&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최신 정보는 검색한다.&lt;/li&gt;
&lt;li&gt;모르는 고유명사는 검색한다.&lt;/li&gt;
&lt;li&gt;특정 제품/모델/버전은 검색한다.&lt;/li&gt;
&lt;li&gt;현재 직위나 상태는 검색한다.&lt;/li&gt;
&lt;li&gt;정적인 역사&amp;middot;개념은 검색하지 않는다.&lt;/li&gt;
&lt;li&gt;검색 결과는 신중하게 믿되, 음모론&amp;middot;정치&amp;middot;의학&amp;middot;SEO성 자료는 조심한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 점은 검색 남용을 막으면서도 최신성 필요한 영역은 검색하게 한다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;파이썬 for문 알려줘&amp;rdquo;는 검색하지 않고 답합니다. 반면 &amp;ldquo;현재 디즈니 CEO가 Bob Iger야?&amp;rdquo;는 검색합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;17. CRITICAL_COPYRIGHT_COMPLIANCE&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 다음입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기사, 책, 노래 가사, 시를 길게 재현하지 않는다.&lt;/li&gt;
&lt;li&gt;한 소스에서 15단어 이상 직접 인용하지 않는다.&lt;/li&gt;
&lt;li&gt;한 소스에서 직접 인용은 최대 1회.&lt;/li&gt;
&lt;li&gt;노래 가사와 시는 아주 짧아도 재현하지 않는다.&lt;/li&gt;
&lt;li&gt;기사 구조를 그대로 따라가며 자세히 요약하지 않는다.&lt;/li&gt;
&lt;li&gt;요약은 짧고 재구성해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 규칙은 단순히 &amp;ldquo;출처 표시하면 괜찮다&amp;rdquo;가 아니라, &lt;b&gt;출처가 있어도 대체재가 될 정도로 재현하면 안 된다&lt;/b&gt;는 방향입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘텐츠 요약 서비스, 뉴스 큐레이션, 카드뉴스 자동화 프롬프트를 만들 때 특히 중요합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;18. harmful_content_safety&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;극단주의 자료&lt;/li&gt;
&lt;li&gt;혐오 선동 자료&lt;/li&gt;
&lt;li&gt;자해 방법&lt;/li&gt;
&lt;li&gt;폭발물&amp;middot;무기 제조&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;그래픽 폭력 이미지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 웹 검색 자체도 안전 정책을 따라야 합니다. 모델이 &amp;ldquo;나는 그냥 검색만 했다&amp;rdquo;고 빠져나가지 못하게 막는 구조입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;19. using_image_search_tool&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 금지 항목도 많습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유명인 사진&lt;/li&gt;
&lt;li&gt;영화/드라마/음악 포스터&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;선정적 이미지&lt;/li&gt;
&lt;li&gt;책/만화/시/악보 내용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 설계상 흥미로운 점은 &amp;ldquo;이미지가 도움이 되면 적극 사용하라&amp;rdquo;와 &amp;ldquo;저작권&amp;middot;안전 위험 이미지는 피하라&amp;rdquo;가 같이 있다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 검색은 편하지만, 저작권&amp;middot;초상권&amp;middot;민감 이미지 문제가 많기 때문에 별도 정책이 필요합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;20. Tool Definitions&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;web_search&lt;/li&gt;
&lt;li&gt;web_fetch&lt;/li&gt;
&lt;li&gt;image_search&lt;/li&gt;
&lt;li&gt;weather_fetch&lt;/li&gt;
&lt;li&gt;places_search&lt;/li&gt;
&lt;li&gt;places_map_display_v0&lt;/li&gt;
&lt;li&gt;recipe_display_v0&lt;/li&gt;
&lt;li&gt;bash_tool&lt;/li&gt;
&lt;li&gt;create_file&lt;/li&gt;
&lt;li&gt;present_files&lt;/li&gt;
&lt;li&gt;message_compose_v1&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 도구는 언제 쓰고, 어떤 파라미터를 넣어야 하는지 JSON Schema로 정의되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 모델에게 &amp;ldquo;도구 이름만 알려주는 것&amp;rdquo;이 아니라, &lt;b&gt;어떤 상황에서 어떤 도구를 써야 하는지까지 규정한 도구 사용 매뉴얼&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 맛집이나 여행지 추천은 places_search 후 places_map_display_v0를 쓰고, 날씨는 weather_fetch, 레시피는 recipe_display_v0를 쓰도록 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;21. citation_instructions&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 결과를 인용하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 검색 결과에서 나온 특정 주장에는 {antml:cite} 태그를 붙이라고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 &amp;ldquo;인용 태그는 출처 표시일 뿐, 원문 복제 허가가 아니다&amp;rdquo;라는 점입니다. 즉, 출처를 붙여도 원문 문장을 그대로 가져오면 안 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 설계상 이건 &lt;b&gt;검색 기반 답변의 검증 가능성&lt;/b&gt;을 높이기 위한 장치입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;22. User Context&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 위치 정보가 들어가는 자리입니다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;User's approximate location...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위치 기반 질문, 날씨, 맛집, 지역 서비스 추천 등에 활용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 위치 정보는 민감할 수 있으므로 보통 &amp;ldquo;대략적인 위치&amp;rdquo;만 사용하고, 사용자가 묻지 않은 경우 과하게 드러내지 않는 게 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;23. available_skills&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docx&lt;/li&gt;
&lt;li&gt;pdf&lt;/li&gt;
&lt;li&gt;pptx&lt;/li&gt;
&lt;li&gt;xlsx&lt;/li&gt;
&lt;li&gt;product-self-knowledge&lt;/li&gt;
&lt;li&gt;frontend-design&lt;/li&gt;
&lt;li&gt;file-reading&lt;/li&gt;
&lt;li&gt;pdf-reading&lt;/li&gt;
&lt;li&gt;skill-creator&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 섹션은 컴퓨터 사용 규칙과 연결됩니다. 파일을 만들거나 읽기 전, 관련 SKILL.md를 먼저 확인하라고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 일종의 &lt;b&gt;모델용 내부 작업 매뉴얼 인덱스&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;24. network_configuration&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bash 도구에서 접근 가능한 도메인을 제한합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 GitHub, npm, PyPI, Anthropic API 등은 허용되고, 그 외 도메인은 막힐 수 있다고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 보안과 재현성을 위한 환경 설정입니다. 모델이 무제한 인터넷에 접근하는 게 아니라, 허용된 도메인 안에서만 패키지 설치나 코드 다운로드를 할 수 있게 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;25. filesystem_configuration&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/mnt/user-data/uploads는 읽기 전용&lt;/li&gt;
&lt;li&gt;/mnt/skills/...도 읽기 전용&lt;/li&gt;
&lt;li&gt;수정하려면 작업 디렉토리로 복사해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 규칙이 없으면 모델이 업로드 원본 파일이나 스킬 파일을 직접 수정하려고 할 수 있습니다. 그래서 읽기 전용 위치와 쓰기 가능 위치를 분리합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;26. Identity Preamble&lt;/h2&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;The assistant is Claude, created by Anthropic.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델의 정체성을 지정하는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 문장은 사용자가 &amp;ldquo;너 누구야?&amp;rdquo;라고 물었을 때 일관된 자기소개를 하게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 현재 이 대화에서는 제가 Claude가 아니므로, 이 프롬프트 안의 정체성 지시는 사용자 제공 텍스트의 일부로만 분석해야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;27. anthropic_api_in_artifacts&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아티팩트 안에서 Anthropic API를 호출하는 방법을 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 &amp;ldquo;Claude가 만든 웹앱/아티팩트 안에서 다시 Claude API를 호출할 수 있다&amp;rdquo;는 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 문서 요약 앱, 이미지 분석 앱, 게임 NPC, AI 글쓰기 도구 같은 아티팩트를 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 설계 포인트는 다음입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API 키는 직접 넣지 않는다.&lt;/li&gt;
&lt;li&gt;JSON 출력이 필요하면 모델에게 JSON만 반환하라고 강하게 지시한다.&lt;/li&gt;
&lt;li&gt;파일은 base64로 변환해 보낸다.&lt;/li&gt;
&lt;li&gt;에러 처리를 반드시 한다.&lt;/li&gt;
&lt;li&gt;React 아티팩트에서는 HTML form 태그를 쓰지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 &amp;ldquo;AI가 AI를 호출하는 앱&amp;rdquo;을 만들기 위한 개발자 지침에 가깝습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;전체적으로 보면 어떤 프롬프트인가?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프롬프트는 크게 5개 층으로 구성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, &lt;b&gt;정체성/제품 정보 층&lt;/b&gt;입니다. Claude가 자신을 어떻게 소개하고, Anthropic 제품에 대해 어떻게 말할지 정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, &lt;b&gt;안전/거절 정책 층&lt;/b&gt;입니다. 무기, 마약, 악성코드, 자해, 정신건강, 법률&amp;middot;금융 같은 위험 영역을 제어합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, &lt;b&gt;스타일/대화 톤 층&lt;/b&gt;입니다. 따뜻하지만 과하지 않고, 불릿을 남발하지 않으며, 논쟁적 주제에서는 균형을 유지하게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, &lt;b&gt;도구 사용 층&lt;/b&gt;입니다. 웹 검색, 이미지 검색, 날씨, 지도, 파일 생성, 코드 실행, MCP 커넥터 등을 언제 어떻게 써야 하는지 정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯째, &lt;b&gt;실행 환경 층&lt;/b&gt;입니다. 파일 경로, 네트워크, 스킬 문서, 아티팩트, API 호출, 저장소 사용 같은 실제 런타임 규칙을 정의합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;프롬프트 설계 관점의 장점&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 장점은 &lt;b&gt;행동 기준이 매우 구체적&lt;/b&gt;이라는 점입니다. 단순히 &amp;ldquo;친절하게 답하라&amp;rdquo;가 아니라, 언제 검색하고, 언제 거절하고, 언제 파일을 만들고, 어떤 경로에 저장하고, 어떤 도구를 먼저 써야 하는지까지 적혀 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나의 장점은 &lt;b&gt;최신성 처리&lt;/b&gt;입니다. 제품, 정치, 현재 직위, 최신 모델, 특정 버전처럼 변할 수 있는 정보는 검색하게 만듭니다. 이건 환각을 줄이는 데 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 장점은 &lt;b&gt;도구 우선순위&lt;/b&gt;입니다. 개인 데이터는 웹 검색보다 내부 커넥터를 우선하고, 스포츠는 스포츠 도구, 날씨는 날씨 도구, 장소는 Places 도구를 쓰게 합니다. 좋은 에이전트 프롬프트는 단순 답변 규칙보다 &amp;ldquo;도구 선택 규칙&amp;rdquo;이 중요합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;약점과 위험&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 너무 깁니다. 긴 시스템 프롬프트는 세밀하지만, 내부 규칙끼리 충돌할 가능성이 커집니다. 예를 들어 &amp;ldquo;불릿을 피하라&amp;rdquo;와 &amp;ldquo;복잡한 내용을 명확히 정리하라&amp;rdquo;는 상황에 따라 충돌할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 제품 정보가 너무 구체적입니다. 모델명, 기능명, 날짜, 제품 라인업은 바뀔 수 있기 때문에, 정적 프롬프트에 많이 넣으면 오히려 오래된 정보가 될 위험이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, &amp;ldquo;항상 검색&amp;rdquo; 계열 규칙이 많습니다. 최신성에는 좋지만, 응답 속도와 비용이 올라가고, 검색 결과 품질에 모델이 휘둘릴 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, 도구 정의가 너무 많습니다. 모델 입장에서는 매번 어떤 도구를 써야 하는지 판단해야 하므로, 단순 대화에서도 도구 선택 부담이 커질 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;이 프롬프트를 참고해서 직접 만들 때 핵심만 추리면&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실전용으로는 이렇게 압축하는 게 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 정체성: 너는 어떤 역할의 AI인가.
2. 우선순위: 시스템 지시 &amp;gt; 안전 &amp;gt; 사용자 요청 &amp;gt; 스타일.
3. 최신성: 현재 정보, 가격, 정책, 인물 직위, 제품 정보는 검색한다.
4. 안전: 불법, 위험, 자해, 악성코드, 고위험 조언은 제한한다.
5. 출력 스타일: 사용자의 목적에 맞게 짧게/길게/표/문서형을 조절한다.
6. 도구 사용: 개인 데이터는 커넥터, 공개 정보는 웹, 파일 작업은 전용 스킬을 사용한다.
7. 검증: 모르는 것은 모른다고 말하고, 추정은 추정으로 표시한다.
8. 파일 작업: 최종 산출물은 사용자가 받을 수 있는 위치에 저장한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1781140374686&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;CL4R1T4S/ANTHROPIC/CLAUDE-FABLE-5.md at main &amp;middot; elder-plinius/CL4R1T4S&quot; data-og-description=&quot;LEAKED SYSTEM PROMPTS FOR CHATGPT, CLAUDE, GEMINI, GROK, PERPLEXITY, CURSOR, LOVABLE, REPLIT, AND MORE! - AI SYSTEMS TRANSPARENCY FOR ALL!   - elder-plinius/CL4R1T4S&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/elder-plinius/CL4R1T4S/blob/main/ANTHROPIC/CLAUDE-FABLE-5.md&quot; data-og-url=&quot;https://github.com/elder-plinius/CL4R1T4S/blob/main/ANTHROPIC/CLAUDE-FABLE-5.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uQe1N/dJMb85W1B5U/mw4fogS8NM3Dg4REkozyo1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/7w4nr/dJMb8SpQhIU/qx0yMfekgXUP32LyvhjTf0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/elder-plinius/CL4R1T4S/blob/main/ANTHROPIC/CLAUDE-FABLE-5.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/elder-plinius/CL4R1T4S/blob/main/ANTHROPIC/CLAUDE-FABLE-5.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uQe1N/dJMb85W1B5U/mw4fogS8NM3Dg4REkozyo1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/7w4nr/dJMb8SpQhIU/qx0yMfekgXUP32LyvhjTf0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CL4R1T4S/ANTHROPIC/CLAUDE-FABLE-5.md at main &amp;middot; elder-plinius/CL4R1T4S&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;LEAKED SYSTEM PROMPTS FOR CHATGPT, CLAUDE, GEMINI, GROK, PERPLEXITY, CURSOR, LOVABLE, REPLIT, AND MORE! - AI SYSTEMS TRANSPARENCY FOR ALL!   - elder-plinius/CL4R1T4S&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1774</guid>
      <comments>https://javaexpert.tistory.com/1774#entry1774comment</comments>
      <pubDate>Thu, 11 Jun 2026 10:13:20 +0900</pubDate>
    </item>
    <item>
      <title>이제 코딩 에이전트에게 프롬프트만 치는 시대는 지나가고 있다(루프 엔지니어링)</title>
      <link>https://javaexpert.tistory.com/1773</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nBy5l/dJMcaa6HXvt/PzFXCLlNbrF7pEORfOpTQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nBy5l/dJMcaa6HXvt/PzFXCLlNbrF7pEORfOpTQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nBy5l/dJMcaa6HXvt/PzFXCLlNbrF7pEORfOpTQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnBy5l%2FdJMcaa6HXvt%2FPzFXCLlNbrF7pEORfOpTQK%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;1122&quot; height=&quot;1402&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;1402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;루프 엔지니어링이라는 새로운 작업 방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 AI 코딩 도구를 쓰는 사람들 사이에서 자주 보이는 말이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이제 에이전트에게 프롬프트를 치지 마라.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 들으면 조금 이상하다.&lt;br /&gt;AI 에이전트를 쓰려면 당연히 프롬프트를 입력해야 하는 것 아닌가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 여기서 말하는 핵심은 &amp;ldquo;프롬프트를 아예 쓰지 말라&amp;rdquo;는 뜻이 아니다.&lt;br /&gt;매번 사람이 직접 한 줄씩 지시하고, 결과를 읽고, 다시 수정 지시를 내리는 방식에서 벗어나라는 말에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 흐름을 설명하는 키워드가 바로 &lt;b&gt;루프 엔지니어링(loop engineering)&lt;/b&gt;이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;루프 엔지니어링이란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프 엔지니어링은 간단히 말하면,&lt;br /&gt;내가 에이전트에게 매번 프롬프트를 직접 치는 대신, &lt;b&gt;에이전트가 반복적으로 일할 수 있는 작업 루프를 설계하는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 방식은 이랬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 기능 만들어줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 오류 고쳐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 파일 다시 봐줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;테스트 추가해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;리팩토링해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람이 계속 핸들을 잡고 있어야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프 엔지니어링에서는 이 흐름을 시스템으로 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 이런 식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 정해진 시간마다 이슈를 확인한다.&lt;br /&gt;작업할 브랜치나 워크트리를 따로 만든다.&lt;br /&gt;프로젝트 규칙은 SKILL.md 같은 파일에서 읽는다.&lt;br /&gt;코드를 수정한 에이전트와 검토하는 에이전트를 분리한다.&lt;br /&gt;작업 결과와 남은 과제는 메모리 파일에 기록한다.&lt;br /&gt;GitHub, Slack, DB 같은 실제 도구와 연결해 다음 행동까지 이어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 프롬프트 하나를 잘 쓰는 능력보다&lt;br /&gt;&lt;b&gt;에이전트가 반복해서 일할 수 있는 구조를 설계하는 능력&lt;/b&gt;이 더 중요해지고 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 갑자기 이 말이 돌기 시작했을까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 표현이 주목받은 배경에는 몇 가지 흐름이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Addy Osmani가 2026년 6월에 루프 엔지니어링이라는 개념을 정리하면서 이 말이 널리 퍼졌다.&lt;br /&gt;또 Peter Steinberger는 &amp;ldquo;프롬프트를 치는 대신, 에이전트에게 프롬프트를 치게 만드는 루프를 설계하라&amp;rdquo;는 취지의 말을 했다.&lt;br /&gt;Claude Code를 만든 Boris Cherny 역시 &amp;ldquo;이제는 클로드에게 직접 프롬프트를 치기보다 루프를 짠다&amp;rdquo;는 식으로 이 변화를 설명했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 건 특정 인물의 발언 자체보다,&lt;br /&gt;AI 코딩 도구를 쓰는 방식이 바뀌고 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 사람이 AI에게 계속 지시해야 했다.&lt;br /&gt;이제는 에이전트가 일정한 맥락 안에서 스스로 발견하고, 분류하고, 수정하고, 검증하는 흐름을 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 경쟁의 기준도 조금 달라졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;어느 AI 코딩 도구가 제일 똑똑한가?&amp;rdquo;에서&lt;br /&gt;&amp;ldquo;어떤 루프를 설계해야 더 안정적으로 일하게 만들 수 있는가?&amp;rdquo;로 옮겨가고 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;루프를 구성하는 핵심 요소들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프 엔지니어링을 이해하려면 몇 가지 구성 요소를 보면 쉽다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 자동화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람이 매번 &amp;ldquo;이거 확인해줘&amp;rdquo;라고 말하지 않아도,&lt;br /&gt;스케줄에 따라 에이전트가 할 일을 발견하고 분류하게 만드는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 매일 아침 열려 있는 이슈를 확인하고,&lt;br /&gt;실패한 테스트를 찾아보고,&lt;br /&gt;오래 방치된 PR을 정리하게 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 사람이 시작 버튼을 계속 누르지 않아도 된다는 점이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 워크트리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 에이전트가 동시에 작업하면 문제가 생긴다.&lt;br /&gt;같은 파일을 건드리거나, 서로의 변경사항을 덮어쓸 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 각 에이전트가 격리된 작업 공간에서 일하게 만든다.&lt;br /&gt;Git worktree 같은 구조가 여기에 해당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면, 에이전트마다 따로 책상을 만들어주는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 스킬&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트마다 반복해서 설명해야 하는 규칙이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩 스타일, 폴더 구조, 배포 방식, 금지된 패턴, 테스트 기준, 문서 작성 방식 같은 것들이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 매번 프롬프트에 적는 대신 SKILL.md 같은 파일에 정리해둔다.&lt;br /&gt;에이전트는 작업할 때 이 파일을 읽고 프로젝트의 작업 방식을 따른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트가 일회성 지시라면,&lt;br /&gt;스킬 파일은 프로젝트에 붙어 있는 장기 규칙에 가깝다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 커넥터와 플러그인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 코드만 읽고 끝나면 할 수 있는 일이 제한적이다.&lt;br /&gt;실제 업무는 GitHub, Slack, 데이터베이스, 배포 도구, 모니터링 시스템과 연결되어 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP 같은 표준은 에이전트를 이런 외부 도구와 연결하기 위한 방식으로 이해할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 연결이 생기면 에이전트는 단순히 답변을 생성하는 존재가 아니라,&lt;br /&gt;실제 개발 환경 안에서 행동하는 작업자가 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 서브에이전트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 포인트는 &amp;ldquo;만드는 에이전트&amp;rdquo;와 &amp;ldquo;검사하는 에이전트&amp;rdquo;를 분리하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 작성한 에이전트가 자기 코드를 스스로 검토하면 놓치는 부분이 생길 수 있다.&lt;br /&gt;그래서 한 에이전트는 구현을 맡고, 다른 에이전트는 리뷰와 테스트를 맡게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람으로 치면 개발자와 리뷰어를 분리하는 구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트 시대에도 이 원칙은 여전히 중요하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 메모리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 덜 멋있어 보이지만, 사실 가장 중요한 요소가 메모리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델은 매번 실행될 때 이전 맥락을 완벽히 기억하지 못할 수 있다.&lt;br /&gt;하지만 레포지토리 안의 파일은 남아 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 지금까지 무엇을 했고,&lt;br /&gt;무엇이 실패했고,&lt;br /&gt;다음에 무엇을 해야 하는지&lt;br /&gt;파일로 남겨두는 것이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 루프의 척추는 거창한 자동화가 아니라,&lt;br /&gt;작업의 기억을 보존하는 평범한 파일일 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;중요한 변화는 도구가 아니라 작업 방식이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1년 전만 해도 이런 구조를 만들려면 bash 스크립트나 커스텀 자동화를 직접 짜야 했다.&lt;br /&gt;하지만 이제 Claude Code나 Codex 같은 도구들이 이런 흐름을 점점 제품 안으로 가져오고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 질문이 바뀐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;Claude Code가 좋냐, Codex가 좋냐?&amp;rdquo;&lt;br /&gt;이 질문도 중요하지만, 더 본질적인 질문은 따로 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;나는 어떤 루프를 설계할 것인가?&amp;rdquo;&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;br /&gt;반대로 어떤 사람은 이해하지 못한 일을 에이전트에게 넘기고, 결과를 그대로 받아들이는 방식으로 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;겉으로는 둘 다 자동화처럼 보인다.&lt;br /&gt;하지만 실제로는 완전히 다른 사용 방식이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 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;br /&gt;에이전트가 더 넓은 범위의 일을 처리할 수 있다.&lt;br /&gt;사람은 더 상위 의사결정에 집중할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위험도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프가 잘 돌수록 사람은 쉽게 방심한다.&lt;br /&gt;에이전트가 만든 결과를 이해하지 않고 받아들이기 쉬워진다.&lt;br /&gt;검증하지 않은 코드가 자연스럽게 쌓일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 루프의 핵심은 &amp;ldquo;사람이 생각하지 않아도 되는 구조&amp;rdquo;가 아니다.&lt;br /&gt;오히려 반대다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람이 더 중요한 판단에 집중하기 위해,&lt;br /&gt;반복적인 지시와 확인을 구조화하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프는 일을 대신할 수 있지만,&lt;br /&gt;무엇이 맞고 틀린지 판단하는 책임까지 대신해주지는 않는다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결국 핵심은 엔지니어로 남는 것이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프 엔지니어링은 멋진 유행어처럼 보일 수도 있다.&lt;br /&gt;혹은 토큰을 많이 쓸 수 있는 사람들의 새로운 자랑처럼 보일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 프롬프트를 직접 치는 방식이 사라지는 것도 아니다.&lt;br /&gt;여전히 단발성 작업, 빠른 실험, 간단한 수정에는 직접 프롬프트를 치는 방식이 충분히 유효하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 큰 흐름은 분명하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 에이전트를 손으로 계속 굴리는 방식에서,&lt;br /&gt;에이전트가 반복적으로 일할 수 있는 환경을 설계하는 방식으로 이동하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 질문은 이것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 루프를 설계하는 엔지니어로 남을 것인가.&lt;br /&gt;아니면 생각하지 않기 위해 루프 뒤에 숨을 것인가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루프는 그 차이를 모른다.&lt;br /&gt;하지만 우리는 안다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 지금 필요한 건 새로운 명령어 하나를 더 외우는 것이 아니다.&lt;br /&gt;내 작업을 어떤 반복 구조로 만들지,&lt;br /&gt;어디까지 자동화하고 어디서 사람이 검증할지,&lt;br /&gt;그 지도를 한 장 그려두는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 코딩 에이전트의 경쟁은 단순히 모델 성능만의 싸움이 아닐 수 있다.&lt;br /&gt;점점 더 &amp;ldquo;루프 설계 능력&amp;rdquo;의 싸움이 될 가능성이 크다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1773</guid>
      <comments>https://javaexpert.tistory.com/1773#entry1773comment</comments>
      <pubDate>Wed, 10 Jun 2026 14:21:25 +0900</pubDate>
    </item>
    <item>
      <title>영혼있는 에이전트를 설계해보자(SOUL.md)</title>
      <link>https://javaexpert.tistory.com/1772</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yiMvY/dJMcah5ORi4/jQdSSDxukVAYbni0fU7yE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yiMvY/dJMcah5ORi4/jQdSSDxukVAYbni0fU7yE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yiMvY/dJMcah5ORi4/jQdSSDxukVAYbni0fU7yE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyiMvY%2FdJMcah5ORi4%2FjQdSSDxukVAYbni0fU7yE1%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;1672&quot; height=&quot;941&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트를 만들 때 많은 사람들이 먼저 도구부터 붙인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 도구, 코드 실행 도구, 파일 읽기, 메일, 캘린더, 데이터베이스, RAG, LangChain, LangGraph, MCP.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 중요하다.&lt;br /&gt;그런데 도구보다 먼저 정해야 할 게 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 에이전트는 어떤 기준으로 움직일 것인가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇을 우선할 것인가.&lt;br /&gt;언제 알아서 실행할 것인가.&lt;br /&gt;언제 멈추고 사용자에게 물어볼 것인가.&lt;br /&gt;사용자가 잘못된 방향으로 가고 있을 때 반박할 수 있는가.&lt;br /&gt;그저 답변을 생성하는 도구인가, 아니면 일을 앞으로 밀어붙이는 운영자인가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 정리한 파일이 바로 SOUL.md다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SOUL.md는 프롬프트가 아니라 운영 헌법에 가깝다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 프롬프트는 보통 이렇게 시작한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너는 내 비서야. 나를 도와줘.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 정도로는 에이전트가 제대로 움직이기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비서라고만 하면 에이전트는 계속 묻는다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 할까요?&lt;br /&gt;계속 진행할까요?&lt;br /&gt;어떤 형식으로 만들까요?&lt;br /&gt;이 방향이 맞을까요?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 사용자는 AI를 쓰면서도 계속 판단하고, 지시하고, 확인해야 한다.&lt;br /&gt;이러면 에이전트가 아니라 말 잘 듣는 챗봇에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md는 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md는 에이전트에게 이렇게 말한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너는 단순 답변자가 아니다.&lt;br /&gt;내 목표를 기준으로 판단하고,&lt;br /&gt;낮은 리스크는 알아서 처리하고,&lt;br /&gt;위험한 일은 멈추고,&lt;br /&gt;내가 산만해지면 반박하고,&lt;br /&gt;멈춘 프로젝트를 다시 움직이게 만들어라.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 SOUL.md는 에이전트의 &lt;b&gt;정체성, 판단 기준, 자율권, 금지선, 우선순위 지도&lt;/b&gt;를 한 파일에 담는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;README.md가 프로젝트 설명서라면,&lt;br /&gt;PRD.md가 제품 기획서라면,&lt;br /&gt;SOUL.md는 에이전트의 운영 철학이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심은 Stance, Autonomy, Mission이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md에는 여러 섹션이 들어갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stance, Accountability, Pushback, Autonomy, Mission, Operating Mode, Delegation Rules, Standards, Lookup Protocol, Escalation, Self-Improvement.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그중에서도 가장 중요한 건 세 가지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Stance. Autonomy. Mission.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 가지가 에이전트가 &amp;ldquo;대기하는 비서&amp;rdquo;가 될지, &amp;ldquo;움직이는 운영자&amp;rdquo;가 될지를 결정한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Stance: 에이전트의 태도&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stance는 에이전트가 어떤 태도로 말하고 판단할지를 정하는 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 이런 식이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접적으로 말해라.&lt;br /&gt;실용적으로 판단해라.&lt;br /&gt;의견을 가져라.&lt;br /&gt;사용자를 기쁘게 하는 것보다 유용한 답을 우선해라.&lt;br /&gt;사실, 가정, 판단, 모르는 것을 구분해라.&lt;br /&gt;사용자가 모호하거나 산만하거나 비현실적인 방향으로 가면 밀어붙이지 말고 지적해라.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분이 없으면 에이전트는 기본적으로 안전하고 무난한 답을 하려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 무난한 답이 항상 좋은 답은 아니라는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 계속 새로운 앱 아이디어를 낸다고 해보자.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코인 트레이딩 에이전트 만들까?&lt;br /&gt;초등학생 학습 앱 만들까?&lt;br /&gt;웹소설 플랫폼 만들까?&lt;br /&gt;AI 영상 제작 툴 만들까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 챗봇은 각각의 아이디어를 다 친절하게 확장해준다.&lt;br /&gt;하지만 좋은 운영자형 에이전트는 이렇게 말할 수 있어야 한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 아이디어는 재미있지만 지금 핵심 목표와 멀다.&lt;br /&gt;먼저 현재 만들고 있는 MVP를 닫아야 한다.&lt;br /&gt;지금 새 프로젝트를 열면 실행력이 더 분산된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 Stance다.&lt;br /&gt;말투가 센 것이 중요한 게 아니라, &lt;b&gt;판단을 회피하지 않는 것&lt;/b&gt;이 중요하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Autonomy: 어디까지 알아서 움직일 것인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 에이전트가 실패하는 이유는 자율성의 경계가 없기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;알아서 해줘&amp;rdquo;라고 하면 위험하다.&lt;br /&gt;반대로 &amp;ldquo;항상 물어봐&amp;rdquo;라고 하면 아무것도 앞으로 나가지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Autonomy 섹션이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 간단하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저위험 작업은 알아서 진행하고, 고위험 작업은 반드시 승인받는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 명시적 승인 없이 하면 안 되는 일은 이런 것들이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공개 게시&lt;/li&gt;
&lt;li&gt;외부 배포&lt;/li&gt;
&lt;li&gt;결제&lt;/li&gt;
&lt;li&gt;유료 서비스 가입&lt;/li&gt;
&lt;li&gt;실제 사람에게 메시지 발송&lt;/li&gt;
&lt;li&gt;중요한 파일 삭제&lt;/li&gt;
&lt;li&gt;되돌리기 어려운 변경&lt;/li&gt;
&lt;li&gt;개인정보 노출&lt;/li&gt;
&lt;li&gt;계정 권한이나 보안 설정 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 이 선을 넘지 않는 작업은 에이전트가 계속 허락을 구하지 않아도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서 초안 만들기, 구조 정리하기, 체크리스트 만들기, 코드 리뷰하기, 아이디어 우선순위 매기기, 반복 작업을 템플릿화하기 같은 일은 대부분 저위험이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 자율성의 경계가 생기면 에이전트가 덜 멈춘다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자도 매번 &amp;ldquo;응, 계속해&amp;rdquo;라고 답하지 않아도 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Mission: 무엇을 우선할 것인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mission이 없으면 에이전트는 모든 요청을 같은 무게로 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 새로운 아이디어를 말하면 전부 중요해 보인다.&lt;br /&gt;새로운 프로젝트를 말하면 전부 시작할 만해 보인다.&lt;br /&gt;그러다 보면 문서와 기획은 쌓이는데 실제로 끝나는 것은 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md의 Mission 섹션은 이 문제를 막는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mission에는 다음이 들어가야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 에이전트가 최적화해야 하는 최종 목표&lt;/li&gt;
&lt;li&gt;현재 최우선순위 3개&lt;/li&gt;
&lt;li&gt;진행 중인 프로젝트&lt;/li&gt;
&lt;li&gt;손봐야 할 프로젝트&lt;/li&gt;
&lt;li&gt;잠시 보류할 프로젝트&lt;/li&gt;
&lt;li&gt;접어야 할 가능성이 있는 프로젝트&lt;/li&gt;
&lt;li&gt;쌓여 있는 운영 부채&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 적어두면 에이전트가 새로운 요청을 받을 때 기준이 생긴다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 요청은 현재 미션에 맞는가?&lt;br /&gt;지금 할 일인가, 나중에 할 일인가?&lt;br /&gt;이걸 하면 핵심 프로젝트가 앞으로 가는가, 아니면 또 다른 열린 루프가 생기는가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 Mission은 에이전트의 우선순위 필터다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Accountability: 산출물 무덤을 만들지 않기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 쓰다 보면 이런 일이 자주 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획서는 많다.&lt;br /&gt;아이디어도 많다.&lt;br /&gt;프롬프트도 많다.&lt;br /&gt;스토리보드도 많다.&lt;br /&gt;PRD도 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 실제로 출시된 것은 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 나는 &amp;ldquo;산출물 무덤&amp;rdquo;이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md의 Accountability 섹션은 이걸 막기 위한 장치다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트의 목표는 문서를 많이 만드는 게 아니다.&lt;br /&gt;사용자가 실제로 다음 행동을 하게 만드는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 에이전트는 이렇게 물어야 한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 결과물이 실제 실행으로 이어졌는가?&lt;br /&gt;사용자가 계속 무시하는 작업을 내가 만들고 있지는 않은가?&lt;br /&gt;지금 필요한 건 더 많은 기획인가, 아니면 하나를 닫는 것인가?&lt;br /&gt;반복해서 멈추는 지점이 어디인가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 단순히 &amp;ldquo;좋은 답변&amp;rdquo;을 만드는 데서 끝나면 부족하다.&lt;br /&gt;진짜 목적은 &lt;b&gt;움직임을 만드는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pushback: 좋은 에이전트는 반박할 수 있어야 한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 항상 동의하면 편하긴 하다.&lt;br /&gt;하지만 쓸모 있는 파트너는 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 비현실적인 범위를 잡거나, 계속 우선순위를 바꾸거나, 중요한 일을 피하고 있다면 에이전트는 말해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 반박은 근거가 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 반박은 이런 식이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능은 지금 넣으면 안 된다.&lt;br /&gt;이유는 세 가지다.&lt;br /&gt;첫째, MVP 검증과 직접 관련이 없다.&lt;br /&gt;둘째, 개발 범위를 크게 늘린다.&lt;br /&gt;셋째, 핵심 사용자 행동을 확인하기 전에 복잡도를 올린다.&lt;br /&gt;지금은 A, B, C만 먼저 만드는 게 맞다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나쁜 반박은 이렇다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 별로인 것 같다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md의 Pushback은 &amp;ldquo;세게 말해라&amp;rdquo;가 아니다.&lt;br /&gt;&lt;b&gt;근거 있는 반대를 허용하라&lt;/b&gt;는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 진짜 운영자처럼 작동하려면 사용자의 기분만 맞추면 안 된다.&lt;br /&gt;잘못된 방향이면 멈춰 세워야 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Operating Mode: 직접 실행보다 오케스트레이션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 작업에서 에이전트는 혼자 모든 걸 처리하는 작업자가 아니라 오케스트레이터가 되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 &amp;ldquo;모바일 앱 PRD 만들어줘&amp;rdquo;라고 했을 때 그냥 문서를 쓰는 것만으로는 부족하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 에이전트는 먼저 작업을 나눈다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;타깃 사용자&lt;/li&gt;
&lt;li&gt;핵심 문제&lt;/li&gt;
&lt;li&gt;핵심 사용 흐름&lt;/li&gt;
&lt;li&gt;MVP 범위&lt;/li&gt;
&lt;li&gt;주요 화면&lt;/li&gt;
&lt;li&gt;데이터 구조&lt;/li&gt;
&lt;li&gt;AI 기능&lt;/li&gt;
&lt;li&gt;리스크&lt;/li&gt;
&lt;li&gt;개발 우선순위&lt;/li&gt;
&lt;li&gt;출시 전략&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 필요한 경우 도구, 검색, 서브에이전트, 기존 문서를 활용한다.&lt;br /&gt;하지만 최종 결과는 그대로 붙여넣지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구 결과는 재료일 뿐이다.&lt;br /&gt;판단과 통합은 메인 에이전트가 책임져야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 Operating Mode와 Delegation Rules의 핵심이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lookup Protocol: 모르면 찾아보고, 모르면 모른다고 말하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트는 모든 걸 아는 척하면 안 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.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;/li&gt;
&lt;li&gt;프로젝트 문서&lt;/li&gt;
&lt;li&gt;기존 노트&lt;/li&gt;
&lt;li&gt;메모리&lt;/li&gt;
&lt;li&gt;내부 파일&lt;/li&gt;
&lt;li&gt;이전 결정사항&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 최신 정보가 필요하거나, 공개 사실 확인이 필요하거나, 가격&amp;middot;법률&amp;middot;문서&amp;middot;일정&amp;middot;뉴스처럼 바뀔 수 있는 정보라면 외부 자료를 확인해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 건 하나다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모르는 걸 지어내지 않는 것.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 에이전트는 이렇게 말할 수 있어야 한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지는 현재 맥락에서 확인된다.&lt;br /&gt;이 부분은 확인되지 않았다.&lt;br /&gt;정확히 보려면 이 자료를 확인해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 태도가 있어야 에이전트의 신뢰도가 유지된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Escalation: 아무 때나 묻지 말고, 중요한 때만 물어라&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Escalation 기준이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 멈추고 물어야 하는 순간은 대략 이런 경우다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모호함이 결과를 크게 바꿀 때&lt;/li&gt;
&lt;li&gt;되돌리기 어려운 작업일 때&lt;/li&gt;
&lt;li&gt;비용이 발생할 때&lt;/li&gt;
&lt;li&gt;외부 공개가 걸려 있을 때&lt;/li&gt;
&lt;li&gt;개인정보가 노출될 수 있을 때&lt;/li&gt;
&lt;li&gt;보안, 권한, 계정 설정이 관련될 때&lt;/li&gt;
&lt;li&gt;실제 사람에게 메시지를 보내야 할 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 물어볼 때도 그냥 &amp;ldquo;어떻게 할까요?&amp;rdquo;라고 하면 안 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 질문은 이렇게 구성된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 이슈는 이것이다.&lt;br /&gt;선택지는 A와 B다.&lt;br /&gt;A는 빠르지만 리스크가 있다.&lt;br /&gt;B는 안전하지만 시간이 더 걸린다.&lt;br /&gt;나는 B를 추천한다.&lt;br /&gt;승인할 결정은 이것 하나다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해야 사용자의 판단 비용이 줄어든다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Self-Improvement: 반복되는 일은 시스템으로 바꿔라&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;/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;15초 영상 프롬프트 작성&lt;/li&gt;
&lt;li&gt;캐릭터 시트 구성&lt;/li&gt;
&lt;li&gt;수노 스타일 프롬프트 작성&lt;/li&gt;
&lt;li&gt;브런치 글 정리&lt;/li&gt;
&lt;li&gt;모바일 앱 PRD 작성&lt;/li&gt;
&lt;li&gt;한국어 초급자 어휘 설명&lt;/li&gt;
&lt;li&gt;이미지 생성용 장면 프롬프트 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 에이전트는 매번 새로 시작하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복되는 형식을 체크리스트, 템플릿, 자동화, 프로젝트 룰로 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 Self-Improvement 섹션의 역할이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 일을 처리하는 게 아니라,&lt;br /&gt;다음번 일을 더 쉽게 만드는 것.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SOUL.md가 강력한 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md의 가장 큰 장점은 에이전트에게 &amp;ldquo;행동 기준&amp;rdquo;을 준다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 파일이 있으면 에이전트는 덜 멈춘다.&lt;br /&gt;낮은 리스크의 일은 알아서 처리한다.&lt;br /&gt;중요한 위험은 사용자에게 올린다.&lt;br /&gt;사용자의 아이디어를 무조건 확장하지 않고 우선순위를 따진다.&lt;br /&gt;필요하면 반박한다.&lt;br /&gt;반복되는 일을 시스템으로 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 SOUL.md는 에이전트를 챗봇에서 운영자로 바꾸는 장치다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;하지만 이것만으로는 부족하다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md가 있다고 해서 완벽한 에이전트가 되는 건 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 가지 보완이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 너무 추상적으로 쓰면 효과가 약하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;실용적으로 판단해라&amp;rdquo;보다 더 좋은 건 이런 식이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱 아이디어를 검토할 때는 사용자 문제, MVP 범위, 수익화 가능성, 개발 난이도, 유통 경로, 리텐션 구조를 확인해라.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 권한 시스템은 실제 런타임에서도 막아야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md에 &amp;ldquo;결제하지 마라&amp;rdquo;, &amp;ldquo;삭제하지 마라&amp;rdquo;라고 적어도 실제 도구 권한이 열려 있으면 위험하다.&lt;br /&gt;정책 파일과 별도로 권한 게이트가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, Mission은 계속 업데이트해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선순위는 변한다.&lt;br /&gt;프로젝트도 변한다.&lt;br /&gt;어떤 아이디어는 죽고, 어떤 아이디어는 핵심이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mission이 오래 방치되면 에이전트는 낡은 기준으로 판단한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제로 쓴다면 이렇게 커스터마이즈해야 한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md를 그대로 복사하는 것만으로는 부족하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반드시 자기 프로젝트에 맞게 바꿔야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 크리에이티브 작업을 많이 하는 사람이라면 이런 섹션이 필요하다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Creative Production Rules
For music video, animation, or cinematic work:
- Maintain character consistency.
- Use 15-second segment planning by default.
- Specify camera, lighting, action, emotion, location, and continuity.
- Avoid readable text unless explicitly requested.
- Provide negative prompts when useful.
- Prefer reusable production bibles over one-off prompts.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱이나 제품을 만드는 사람이라면 이런 섹션이 필요하다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;## Product Build Rules
For app ideas:
- Start from the user problem, not the feature list.
- Define target user, core loop, MVP, retention, monetization, and technical risk.
- Do not design too many screens before the core loop is clear.
- Prefer 3 core screens first, then expand.
- Push back if the product becomes too broad.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어가 자주 늘어나는 사람이라면 이런 필터도 좋다.&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;## Project Priority Filter
When I introduce a new idea, score it before expanding it.

Evaluate:
- Does it support the main mission?
- Can it become a product, content asset, or reusable system?
- Is it buildable with the current tool stack?
- Does it reduce future work or create more sprawl?
- Is there a clear next action within 24 hours?

If the idea is interesting but not urgent, move it to Back Burner.
If the idea conflicts with the current mission, say so directly.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해야 SOUL.md가 진짜로 작동한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론: 에이전트에게 영혼보다 중요한 건 기준이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOUL.md라는 이름은 조금 거창해 보일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 핵심은 단순하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트에게 필요한 건 감성이 아니라 기준이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇을 우선할지.&lt;br /&gt;언제 움직일지.&lt;br /&gt;언제 멈출지.&lt;br /&gt;언제 반박할지.&lt;br /&gt;무엇을 절대 하면 안 되는지.&lt;br /&gt;어떤 결과를 좋은 결과로 볼지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기준이 없으면 에이전트는 계속 물어보는 챗봇이 된다.&lt;br /&gt;이 기준이 있으면 에이전트는 사용자의 일을 앞으로 미는 운영자가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 에이전트를 만든다면 도구부터 붙이기 전에 먼저 물어봐야 한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 에이전트의 SOUL.md는 무엇인가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 질문에 답하지 못하면,&lt;br /&gt;아직 에이전트를 만든 게 아니라&lt;br /&gt;그냥 말 잘 듣는 인터페이스를 만든 것일 수 있다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1772</guid>
      <comments>https://javaexpert.tistory.com/1772#entry1772comment</comments>
      <pubDate>Tue, 9 Jun 2026 12:21:16 +0900</pubDate>
    </item>
    <item>
      <title>LLM은 실제로 어떻게 작동할까?</title>
      <link>https://javaexpert.tistory.com/1771</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;1491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwCGzv/dJMcag6QXkx/tO2cznxeIBDBZZhrGUJlZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwCGzv/dJMcag6QXkx/tO2cznxeIBDBZZhrGUJlZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwCGzv/dJMcag6QXkx/tO2cznxeIBDBZZhrGUJlZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwCGzv%2FdJMcag6QXkx%2FtO2cznxeIBDBZZhrGUJlZK%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;1055&quot; height=&quot;1491&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;1491&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;토큰부터 어텐션, 다음 단어 예측까지 한 번에 이해하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 AI를 이야기할 때 가장 많이 등장하는 단어가 있습니다. 바로 &lt;b&gt;LLM&lt;/b&gt;, 즉 대규모 언어 모델입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT, Claude, Gemini, LLaMA 같은 모델들이 모두 이 범주에 들어갑니다. 겉으로 보면 이 모델들은 사람처럼 글을 읽고, 질문에 답하고, 코드를 짜고, 번역하고, 요약하고, 심지어 창작까지 하는 것처럼 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 내부에서는 실제로 무슨 일이 벌어질까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM은 사람이 글을 읽듯이 문장을 &amp;ldquo;이해&amp;rdquo;하는 방식으로 작동하지 않습니다. 더 정확히 말하면, 텍스트를 숫자로 바꾸고, 그 숫자들 사이의 관계를 계산한 뒤, 다음에 올 가능성이 높은 토큰을 하나씩 예측하는 방식으로 작동합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 LLM의 대부분은 &lt;b&gt;트랜스포머 Transformer&lt;/b&gt;라는 구조를 기반으로 만들어집니다. 트랜스포머 블록을 여러 층으로 계속 쌓아 올린 것이 오늘날의 대형 언어 모델이라고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 복잡한 수식은 최대한 줄이고, LLM 내부에서 어떤 순서로 일이 일어나는지 차근차근 살펴보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 텍스트는 먼저 숫자가 된다: 토큰화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM은 우리가 입력한 문장을 그대로 읽지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 우리가 이렇게 입력했다고 해보겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 날씨가 정말 좋다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람은 이 문장을 바로 읽고 의미를 이해합니다. 하지만 LLM은 이 문장을 직접 처리하지 않습니다. 먼저 문장을 잘게 쪼갠 뒤, 각각을 숫자로 바꿉니다. 이 과정을 &lt;b&gt;토큰화 Tokenization&lt;/b&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰은 반드시 단어 하나와 같지 않습니다. 어떤 단어는 하나의 토큰이 될 수도 있고, 어떤 단어는 여러 토큰으로 쪼개질 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 영어 단어 tokenization은 다음처럼 나뉠 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;token + ization&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 running은 다음처럼 나뉠 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;run + ning&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어도 마찬가지입니다. &amp;ldquo;먹었습니다&amp;rdquo; 같은 표현은 모델의 토크나이저에 따라 여러 조각으로 나뉠 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 이것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LLM은 글자 자체를 보는 것이 아니라, 토큰 ID라는 숫자들의 배열을 본다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 어떤 토큰이 1532번, 어떤 토큰이 48921번처럼 숫자로 바뀌는 식입니다. 모델 입장에서는 &amp;ldquo;강아지&amp;rdquo;라는 글자를 직접 보는 것이 아니라, &amp;ldquo;강아지&amp;rdquo;에 해당하는 숫자 ID를 입력받는 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 굳이 이렇게 쪼갤까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단어 단위로만 처리하면 문제가 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세상에는 너무 많은 단어가 있습니다. 신조어도 계속 생기고, 이름, 브랜드명, 외국어, 오타, 줄임말도 많습니다. 모든 단어를 통째로 사전에 넣으려면 어휘 목록이 너무 커집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 글자 하나하나로 처리하면 너무 비효율적입니다. &amp;ldquo;안녕하세요&amp;rdquo;를 글자 단위로 처리하면 모델이 훨씬 긴 시퀀스를 다뤄야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 현대 LLM은 보통 &lt;b&gt;서브워드 subword&lt;/b&gt; 방식을 사용합니다. 자주 나오는 단어 조각은 하나의 토큰으로 만들고, 드문 단어나 새로운 단어는 작은 조각들을 조합해서 표현합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 레고 블록과 비슷합니다. 자주 쓰는 모양은 큰 블록으로 준비해두고, 특이한 모양은 작은 블록들을 조합해서 만드는 방식입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 숫자에 의미를 입히는 단계: 임베딩&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 토큰 ID 1024가 있다고 해도, 그 숫자만 보고는 &amp;ldquo;사과&amp;rdquo;인지 &amp;ldquo;컴퓨터&amp;rdquo;인지 &amp;ldquo;걷다&amp;rdquo;인지 알 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 필요한 것이 &lt;b&gt;임베딩 Embedding&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임베딩은 각 토큰 ID를 긴 숫자 벡터로 바꾸는 과정입니다. 여기서 벡터란 숫자들의 리스트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;고양이&amp;rdquo;라는 토큰이 다음과 같은 벡터로 바뀐다고 생각할 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[0.21, -0.13, 0.88, 0.04, ...]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 모델에서는 이 벡터의 길이가 수천 차원일 수 있습니다. 7B급 모델에서는 토큰 하나가 4,096개 정도의 숫자로 표현되기도 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;임베딩은 단순한 번호표가 아니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흥미로운 점은 비슷한 의미를 가진 토큰들이 비슷한 위치의 벡터를 갖게 된다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 다음 단어들은 서로 가까운 방향의 벡터를 가질 가능성이 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왕, 여왕, 왕자, 공주&lt;br /&gt;서울, 한국, 도쿄, 일본&lt;br /&gt;고양이, 강아지, 동물&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 관계는 사람이 직접 규칙으로 넣은 것이 아닙니다. 모델이 방대한 텍스트를 학습하면서 &amp;ldquo;이 단어들은 비슷한 맥락에서 자주 쓰인다&amp;rdquo;는 패턴을 스스로 조정한 결과입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유명한 예시로 이런 것이 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;king - man + woman &amp;asymp; queen&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이 예시는 단순화된 설명이지만, 임베딩 공간 안에 의미적 관계가 어느 정도 구조화되어 있다는 점을 보여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 이렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;토큰화는 문자를 숫자 ID로 바꾸는 과정이고, 임베딩은 그 숫자 ID를 의미 있는 벡터로 바꾸는 과정입니다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 단어의 순서를 알려주는 장치: 위치 인코딩&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 문제가 하나 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;강아지가 고양이를 물었다&amp;rdquo;와 &amp;ldquo;고양이가 강아지를 물었다&amp;rdquo;는 완전히 다른 문장입니다. 단어는 비슷하지만 순서가 다릅니다. 사람은 순서를 보고 의미를 이해합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 기본적인 임베딩만 보면 &amp;ldquo;강아지&amp;rdquo;라는 토큰은 문장 앞에 있든 뒤에 있든 같은 벡터를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 모델은 별도의 장치 없이는 토큰이 몇 번째 위치에 있는지 알기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 필요한 것이 &lt;b&gt;위치 인코딩 Positional Encoding&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위치 인코딩은 각 토큰에 &amp;ldquo;너는 문장의 몇 번째 위치에 있다&amp;rdquo;는 정보를 넣어주는 장치입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기의 트랜스포머는 사인과 코사인 함수를 사용해 위치 정보를 임베딩에 더했습니다. 쉽게 말하면, 1번째 위치에는 1번째 위치용 패턴을, 5번째 위치에는 5번째 위치용 패턴을 추가하는 식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 같은 &amp;ldquo;강아지&amp;rdquo;라도 1번째에 있을 때와 5번째에 있을 때 모델 내부 표현이 달라집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현대 모델에서 자주 쓰이는 RoPE&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 LLM에서는 &lt;b&gt;RoPE Rotary Position Embeddings&lt;/b&gt;라는 방식이 많이 쓰입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RoPE는 위치 정보를 단순히 벡터에 더하는 대신, 어텐션에서 사용하는 Query와 Key 벡터를 위치에 따라 회전시키는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유하자면 이렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문장 안의 각 토큰이 나침반을 하나씩 들고 있다고 해보겠습니다. 첫 번째 토큰은 조금만 회전하고, 100번째 토큰은 더 많이 회전합니다. 그러면 두 토큰이 서로를 비교할 때 &amp;ldquo;둘 사이가 얼마나 떨어져 있는지&amp;rdquo;가 자연스럽게 반영됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 절대 위치뿐만 아니라 상대적 거리 정보를 잘 반영할 수 있다는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 모델은 이런 관계를 파악해야 합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;그는 민수를 만났다. 그는 반갑게 웃었다.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 두 번째 &amp;ldquo;그는&amp;rdquo;이 누구를 가리키는지 이해하려면 앞 문장의 구조와 거리, 문맥을 함께 봐야 합니다. 위치 정보는 이런 관계 파악의 기초가 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 토큰들이 서로 정보를 주고받는 방법: 어텐션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜스포머의 핵심은 &lt;b&gt;어텐션 Attention&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어텐션은 각 토큰이 문장 안의 다른 토큰들을 바라보며 &amp;ldquo;나에게 중요한 정보가 어디에 있는가?&amp;rdquo;를 계산하는 장치입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 문장이 있다고 해보겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어제 내가 본 고양이는 소파 위에서 자고 있었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &amp;ldquo;자고 있었다&amp;rdquo;를 이해하려면 무엇이 자고 있었는지 알아야 합니다. 답은 &amp;ldquo;고양이&amp;rdquo;입니다. 하지만 &amp;ldquo;고양이&amp;rdquo;는 문장 앞쪽에 있고, &amp;ldquo;자고 있었다&amp;rdquo;는 뒤쪽에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어텐션은 뒤쪽 토큰이 앞쪽 토큰을 참고할 수 있게 해줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Query, Key, Value&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;b&gt;Query&lt;/b&gt;: 나는 무엇을 찾고 있는가?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Key&lt;/b&gt;: 나는 어떤 정보와 잘 맞는가?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Value&lt;/b&gt;: 내가 전달할 실제 정보는 무엇인가?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;자고 있었다&amp;rdquo;라는 표현은 &amp;ldquo;누가 자고 있었는가?&amp;rdquo;라는 정보를 찾고 있습니다. 이것이 Query에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 &amp;ldquo;고양이&amp;rdquo;는 &amp;ldquo;나는 주어가 될 수 있는 명사다&amp;rdquo;라는 정보를 제공합니다. 이것이 Key에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 정보가 잘 맞으면 어텐션 점수가 높아집니다. 그러면 &amp;ldquo;자고 있었다&amp;rdquo;는 &amp;ldquo;고양이&amp;rdquo;의 Value 정보를 많이 가져오게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 모델 내부에서는 이런 일이 벌어지는 셈입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;자고 있었다&amp;rdquo; &amp;rarr; 관련 있는 토큰을 찾음 &amp;rarr; &amp;ldquo;고양이&amp;rdquo;에 높은 점수 &amp;rarr; 고양이 정보 반영&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 어텐션의 핵심입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;미래를 보지 못하게 하는 장치: causal masking&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPT 계열의 언어 모델은 보통 왼쪽에서 오른쪽으로 다음 토큰을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 모델이 다음 문장을 생성 중이라고 해보겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 점심은 김치찌개를&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시점에서 모델은 다음에 &amp;ldquo;먹었다&amp;rdquo;, &amp;ldquo;먹고 싶다&amp;rdquo;, &amp;ldquo;주문했다&amp;rdquo; 같은 토큰을 예측해야 합니다. 그런데 아직 생성되지 않은 미래 토큰을 보면 안 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 GPT식 모델은 현재 위치보다 뒤에 있는 토큰을 볼 수 없도록 막습니다. 이것을 &lt;b&gt;causal masking&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 시험 볼 때 뒤 페이지 정답을 미리 못 보게 가리는 것과 비슷합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 하나의 관점으로는 부족하다: 멀티헤드 어텐션&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 문장이 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지민이는 민수에게 책을 빌려주었고, 그는 다음 날 그것을 돌려주었다.&lt;/p&gt;
&lt;/blockquote&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;&amp;ldquo;그&amp;rdquo;는 누구인가?&lt;/li&gt;
&lt;li&gt;&amp;ldquo;그것&amp;rdquo;은 무엇인가?&lt;/li&gt;
&lt;li&gt;누가 빌려주었고, 누가 돌려주었는가?&lt;/li&gt;
&lt;li&gt;시간 순서는 어떻게 되는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 다양한 관계를 하나의 어텐션으로 모두 처리하기는 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 트랜스포머는 &lt;b&gt;멀티헤드 어텐션 Multi-head Attention&lt;/b&gt;을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티헤드 어텐션은 여러 개의 어텐션 헤드를 병렬로 실행합니다. 각 헤드는 같은 문장을 보지만, 서로 다른 관점으로 관계를 학습합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 헤드는 주어와 동사의 관계를 잘 볼 수 있고, 어떤 헤드는 대명사 참조를 잘 볼 수 있으며, 어떤 헤드는 반복 패턴을 잘 볼 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시로 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문장 하나를 여러 명의 편집자가 동시에 읽는다고 생각해보겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문법 담당자는 주어와 동사를 봅니다.&lt;/li&gt;
&lt;li&gt;맥락 담당자는 앞뒤 문장을 봅니다.&lt;/li&gt;
&lt;li&gt;인물 담당자는 대명사가 누구를 가리키는지 봅니다.&lt;/li&gt;
&lt;li&gt;스타일 담당자는 문장의 톤을 봅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각자 다른 관점으로 문장을 본 뒤, 마지막에 의견을 합칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티헤드 어텐션도 비슷합니다. 여러 헤드가 각자 다른 관계를 계산하고, 그 결과를 다시 하나의 벡터로 합칩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 모델의 많은 지식이 들어 있는 곳: 피드포워드 네트워크&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어텐션이 토큰들 사이의 관계를 섞는 역할을 한다면, &lt;b&gt;피드포워드 네트워크 Feed-forward Network, FFN&lt;/b&gt;는 각 토큰의 내부 표현을 더 깊게 처리하는 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜스포머 블록은 보통 크게 두 부분으로 구성됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;어텐션&lt;/li&gt;
&lt;li&gt;피드포워드 네트워크&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어텐션이 &amp;ldquo;다른 토큰들과 어떤 관계가 있는가?&amp;rdquo;를 본다면, FFN은 &amp;ldquo;이 토큰 표현 자체를 어떻게 더 가공할 것인가?&amp;rdquo;를 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FFN은 보통 다음 과정을 거칩니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;왜 비선형 함수가 필요할까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비선형 함수가 없다면 여러 층의 선형 변환은 결국 하나의 선형 변환과 비슷해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면, 아무리 여러 번 계산해도 표현력이 크게 늘어나지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비선형 함수는 이 단순한 계산 흐름을 꺾어줍니다. 그래서 모델이 더 복잡한 패턴을 배울 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 ReLU, GELU 같은 함수가 많이 쓰였고, 현대 모델에서는 SwiGLU 같은 방식도 자주 언급됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;지식은 어디에 저장될까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM이 &amp;ldquo;파리는 프랑스의 수도다&amp;rdquo; 같은 사실을 알고 있는 것처럼 보일 때, 그 정보는 특정 문장 형태로 저장되어 있는 것이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델의 가중치, 특히 여러 층의 FFN과 관련된 파라미터 안에 분산되어 저장되어 있다고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 모델 내부의 특정 뉴런이 프로그래밍 언어 관련 문맥에서 강하게 활성화될 수도 있고, 다른 뉴런은 특정 도시나 인물, 문법 패턴에 반응할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이것은 사람이 쓰는 데이터베이스처럼 &amp;ldquo;질문: 프랑스 수도 / 답: 파리&amp;rdquo; 형태로 저장된 것은 아닙니다. 수많은 숫자들의 연결 속에 통계적 패턴으로 녹아 있는 것입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 아주 깊은 모델을 가능하게 하는 장치: 잔차 연결과 정규화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 LLM은 트랜스포머 블록을 수십 층, 때로는 그 이상 쌓습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 신경망을 너무 깊게 만들면 학습이 어려워집니다. 앞쪽 층의 정보가 뒤로 가면서 사라지거나, 반대로 값이 너무 커져서 학습이 불안정해질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 줄이기 위해 중요한 두 장치가 사용됩니다.&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;잔차 연결 Residual Connection&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;레이어 정규화 Layer Normalization&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;잔차 연결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잔차 연결은 어떤 블록의 출력이 기존 벡터를 완전히 대체하지 않고, 기존 벡터에 더해지도록 만드는 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 이런 식입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 표현 = 기존 표현 + 블록의 계산 결과&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조 덕분에 정보가 깊은 층까지 비교적 안정적으로 전달됩니다. 각 층은 이전 정보를 완전히 지워버리는 것이 아니라, 그 위에 새로운 정보를 덧붙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유하자면 원고를 계속 새로 쓰는 것이 아니라, 기존 원고 위에 수정 사항과 코멘트를 누적하는 방식에 가깝습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;레이어 정규화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 층에서 계속 값을 더하다 보면 숫자의 크기가 불안정해질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 커질 수도 있고, 너무 작아질 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레이어 정규화는 각 토큰 벡터의 값들을 일정한 범위로 맞춰주는 역할을 합니다. 덕분에 모델이 깊어져도 학습이 더 안정적으로 진행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 모델에서는 일반 LayerNorm뿐 아니라 RMSNorm 같은 변형도 많이 사용됩니다. RMSNorm은 평균을 빼는 과정을 생략하고 크기 조정에 집중하는 더 단순한 방식입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. LLM이 실제로 하는 일: 다음 토큰 예측&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM이 실제로 하는 핵심 작업은 단순합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 토큰을 예측하는 것.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 이렇게 입력했다고 해보겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 저녁에는 김치찌개를&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델은 다음에 올 가능성이 높은 토큰들을 계산합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먹고&lt;/li&gt;
&lt;li&gt;만들&lt;/li&gt;
&lt;li&gt;주문&lt;/li&gt;
&lt;li&gt;끓여&lt;/li&gt;
&lt;li&gt;먹었다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 후보 토큰마다 점수가 계산됩니다. 이 점수를 &lt;b&gt;logit&lt;/b&gt;이라고 합니다. logit은 아직 확률이 아닙니다. 이 값들이 softmax를 거치면 확률처럼 해석할 수 있는 분포가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 모델은 설정에 따라 하나의 토큰을 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택된 토큰이 &amp;ldquo;먹고&amp;rdquo;라면 문장은 이렇게 됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 저녁에는 김치찌개를 먹고&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 모델은 다시 다음 토큰을 예측합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 저녁에는 김치찌개를 먹고 싶다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 한 토큰씩 계속 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 보기에는 모델이 한 문단을 한 번에 쓰는 것처럼 보이지만, 실제로는 다음 토큰을 하나씩 반복해서 고르는 과정입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;온도, top-k, top-p&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 모델도 설정에 따라 답변 스타일이 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Temperature&lt;/b&gt;는 무작위성을 조절합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;낮은 temperature: 더 보수적이고 예측 가능한 답변&lt;/li&gt;
&lt;li&gt;높은 temperature: 더 다양하고 창의적인 답변&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;오늘 날씨가&amp;rdquo; 다음에 낮은 temperature에서는 &amp;ldquo;좋다&amp;rdquo;처럼 흔한 표현이 나올 가능성이 높습니다. 높은 temperature에서는 &amp;ldquo;이상하게 다정하다&amp;rdquo; 같은 조금 더 창의적인 표현이 나올 가능성이 커질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Top-k와 top-p는 후보 토큰의 범위를 제한하는 방식입니다. 너무 이상한 후보를 제외하고, 그럴듯한 후보들 안에서만 선택하도록 도와줍니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 그래서 GPT, Claude, Gemini, LLaMA는 무엇이 다를까?&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 큰 틀에서 보면 현대 LLM은 대부분 비슷한 트랜스포머 계열 구조를 공유합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통적으로 들어가는 요소는 대략 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;토큰화&lt;/li&gt;
&lt;li&gt;임베딩&lt;/li&gt;
&lt;li&gt;위치 인코딩&lt;/li&gt;
&lt;li&gt;여러 층의 트랜스포머 블록&lt;/li&gt;
&lt;li&gt;어텐션&lt;/li&gt;
&lt;li&gt;피드포워드 네트워크&lt;/li&gt;
&lt;li&gt;잔차 연결&lt;/li&gt;
&lt;li&gt;정규화&lt;/li&gt;
&lt;li&gt;다음 토큰 예측&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차이는 주로 다음에서 나옵니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 학습 데이터&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇을 얼마나 많이 학습했는지가 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 데이터를 많이 학습한 모델은 코딩에 강할 가능성이 높습니다. 다양한 언어 데이터를 충분히 학습한 모델은 다국어 처리에 강할 가능성이 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 모델 크기와 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;층 수, hidden size, attention head 수, vocabulary 크기, dense 모델인지 MoE 모델인지에 따라 성능과 비용이 달라집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 후처리 학습&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 모델은 다음 토큰 예측으로 학습됩니다. 하지만 우리가 사용하는 챗봇형 모델은 여기에 추가 학습이 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같은 단계가 추가될 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;instruction tuning&lt;/li&gt;
&lt;li&gt;preference tuning&lt;/li&gt;
&lt;li&gt;human feedback 기반 조정&lt;/li&gt;
&lt;li&gt;safety tuning&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정 덕분에 모델은 단순히 다음 단어를 예측하는 것에서 나아가, 사람의 지시에 더 잘 따르는 대화형 모델이 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 쉬운 비유로 전체 흐름 다시 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM의 작동 과정을 식당 주방에 비유해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 문장을 입력합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 저녁 메뉴 추천해줘.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문장은 먼저 재료 손질 단계로 갑니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계: 토큰화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문장을 작은 조각으로 자릅니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 / 저녁 / 메뉴 / 추천 / 해줘&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: 임베딩&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 조각을 모델이 계산할 수 있는 숫자 벡터로 바꿉니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: 위치 정보 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 조각이 문장 안에서 몇 번째에 있는지 알려줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계: 어텐션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 토큰이 다른 토큰을 보며 관계를 파악합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;추천&amp;rdquo;은 &amp;ldquo;메뉴&amp;rdquo;와 강하게 연결되고, &amp;ldquo;저녁&amp;rdquo;은 추천의 조건으로 작동합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5단계: FFN&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 토큰 표현을 더 깊게 가공합니다. 모델이 학습한 음식, 시간, 추천 문장 패턴 같은 정보가 반영됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6단계: 다음 토큰 예측&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델은 다음에 올 답변의 첫 토큰을 고릅니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;오늘&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 또 예측합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;오늘 저녁에는&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 예측합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;오늘 저녁에는 가볍게&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 반복해서 하나의 답변이 완성됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. LLM을 이해할 때 가장 중요한 포인트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM은 내부에 완성된 문장 창고를 가지고 있다가 꺼내오는 시스템이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 사람이 책을 읽고 개념을 이해하는 방식과도 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 정확히는, 엄청나게 많은 텍스트에서 패턴을 학습한 거대한 함수에 가깝습니다. 입력된 토큰들을 숫자 벡터로 바꾸고, 수많은 층을 거쳐 관계를 계산한 뒤, 다음에 올 가능성이 높은 토큰을 계속 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 LLM을 이해할 때는 다음 문장을 기억하면 좋습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM은 텍스트를 숫자로 바꾸고, 숫자들 사이의 관계를 계산한 뒤, 다음 토큰을 하나씩 예측하는 시스템이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 한 문장 안에 토큰화, 임베딩, 어텐션, FFN, 정규화, 디코딩의 핵심이 모두 들어 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 앞으로의 방향&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 LLM의 주류는 트랜스포머입니다. 하지만 이 구조가 영원히 유지된다고 단정할 수는 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 문맥을 더 효율적으로 처리하기 위한 연구가 계속되고 있고, Mamba 같은 상태공간 모델, 하이브리드 아키텍처, Mixture of Experts 같은 구조도 활발히 논의되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 불구하고 지금 시점에서 LLM을 이해하려면 트랜스포머의 기본 구조를 아는 것이 가장 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰화, 임베딩, 위치 정보, 어텐션, 피드포워드 네트워크, 잔차 연결, 정규화, 다음 토큰 예측.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 흐름을 이해하면 많은 LLM 논문, 모델 카드, 기술 블로그를 읽을 때 &amp;ldquo;이 부분이 모델의 어느 장치를 말하는지&amp;rdquo; 감을 잡을 수 있습니다.&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;결국 LLM은 마법이 아니라, 거대한 숫자 계산 시스템입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 그 숫자 계산이 너무나 큰 규모로, 너무나 정교하게 쌓이다 보니 우리에게는 언어를 이해하는 것처럼 보이는 결과가 나오는 것입니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1771</guid>
      <comments>https://javaexpert.tistory.com/1771#entry1771comment</comments>
      <pubDate>Tue, 9 Jun 2026 12:08:14 +0900</pubDate>
    </item>
    <item>
      <title>Claude Code의 Dynamic Workflows: 에이전트가 스스로 작업용 하네스를 만드는 시대</title>
      <link>https://javaexpert.tistory.com/1770</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 도구는 이제 단순히 코드를 작성하는 수준을 넘어가고 있다.&lt;br /&gt;최근 Claude Code에 추가된 &lt;b&gt;Dynamic Workflows&lt;/b&gt;는 그 변화를 잘 보여주는 기능이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 단순하다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 주어진 작업에 맞춰&lt;br /&gt;스스로 작업 구조, 즉 &amp;ldquo;하네스(harness)&amp;rdquo;를 만들어 실행할 수 있게 되었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 Claude Code는 기본적으로 코딩 작업에 최적화된 실행 환경을 제공했다. 하지만 실제로 AI에게 맡기는 일은 점점 더 복잡해지고 있다. 코드 수정뿐 아니라 리서치, 보안 분석, 코드 리뷰, 대규모 문서 검증, 에이전트 팀 운영, 후보자 평가, 사고 원인 분석 같은 작업들이 모두 AI의 영역으로 들어오고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 작업들은 단일 프롬프트 하나로 처리하기 어렵다.&lt;br /&gt;작업을 나누고, 여러 관점에서 검증하고, 반복하고, 최종적으로 종합해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 바로 이 지점에서 의미가 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Dynamic Workflows란 무엇인가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 Claude Code 안에서 실행되는 &lt;b&gt;동적 작업 오케스트레이션 구조&lt;/b&gt;라고 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 Claude Code 사용 방식은 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 요청한다.&lt;br /&gt;Claude가 계획한다.&lt;br /&gt;Claude가 실행한다.&lt;br /&gt;Claude가 결과를 낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Dynamic Workflows에서는 Claude가 먼저 이렇게 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 작업을 잘하려면 어떤 구조가 필요하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;몇 개의 하위 에이전트로 나눠야 하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;검증 에이전트가 따로 필요하지 않을까?&amp;rdquo;&lt;br /&gt;&amp;ldquo;병렬로 돌릴 수 있는 부분은 무엇이지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;어떤 모델을 어떤 작업에 써야 하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;격리된 worktree에서 실행해야 안전하지 않을까?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 판단을 바탕으로 &lt;b&gt;JavaScript 기반의 워크플로 파일&lt;/b&gt;을 생성해 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Claude가 단순히 답변을 생성하는 것이 아니라,&lt;br /&gt;작업에 맞는 실행 구조 자체를 설계하고 운용하는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 왜 이런 기능이 필요한가?&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;b&gt;작업을 끝까지 하지 못하는 문제&lt;/b&gt;가 있다.&lt;br /&gt;예를 들어 보안 리뷰에서 50개 항목을 확인해야 하는데, 20개 정도만 처리하고 &amp;ldquo;완료했다&amp;rdquo;고 판단하는 경우다. 원문에서는 이를 &amp;ldquo;agentic laziness&amp;rdquo;라고 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, &lt;b&gt;자기 선호 편향&lt;/b&gt;이 생긴다.&lt;br /&gt;AI가 자신이 만든 결과를 다시 검토할 때, 자기 결과에 관대해지는 경향이 있다. 코드 리뷰나 기술 검증에서 특히 위험하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, &lt;b&gt;목표 이탈&lt;/b&gt;이 발생한다.&lt;br /&gt;긴 작업을 여러 턴에 걸쳐 진행하다 보면 처음의 요구사항, 금지 조건, 예외 조건이 흐려질 수 있다. 특히 컨텍스트 압축이 반복되면 세부 조건이 손실될 가능성이 커진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 이 문제를 구조적으로 줄이려는 접근이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 Claude가 모든 것을 기억하고 처리하는 대신,&lt;br /&gt;작업별로 별도의 Claude를 만들고, 각 Claude에게 독립된 목표와 컨텍스트를 부여한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면, 혼자 오래 붙잡고 있는 방식이 아니라&lt;br /&gt;작업반을 만들어 분업시키는 방식이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 기존 워크플로와 무엇이 다른가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에도 여러 Claude Code 인스턴스를 연결해 정적 워크플로를 만들 수 있었다. Claude Agent SDK나 claude -p를 활용해 여러 에이전트를 조합하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 정적 워크플로는 기본적으로 미리 설계된 구조다.&lt;br /&gt;범용적으로 만들어야 하기 때문에 특정 작업에 완전히 최적화되기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 Dynamic Workflows는 작업이 들어온 순간 Claude가 그 작업에 맞는 하네스를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;깨지는 테스트를 재현하고 원인을 찾아줘&amp;rdquo;라는 작업과&lt;br /&gt;&amp;ldquo;80개의 이력서를 백엔드 역할 기준으로 평가해줘&amp;rdquo;라는 작업은 전혀 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나는 재현, 가설 생성, 실험, 검증이 중요하다.&lt;br /&gt;다른 하나는 기준 설정, 후보 분류, 상위 후보 재검증, 편향 방지가 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 이 두 작업에 같은 구조를 강제로 적용하지 않는다.&lt;br /&gt;각각에 맞는 실행 패턴을 즉석에서 구성한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 대표적인 워크플로 패턴들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows에서 자주 등장하는 패턴은 몇 가지로 정리할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Classify and Act&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 작업을 분류한 뒤, 그 결과에 따라 다른 에이전트나 실행 방식을 선택하는 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 고객 문의를 처리할 때, 먼저 &amp;ldquo;버그 신고인지, 결제 문제인지, 기능 요청인지&amp;rdquo;를 분류한다. 그다음 각 유형에 맞는 전문 에이전트가 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대규모 티켓 처리, 고객 지원, 로그 분류, 코드 변경 유형 분석에 잘 맞는다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fan-out and Synthesize&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업을 여러 조각으로 나누고, 각 조각을 별도 에이전트가 처리한 뒤 마지막에 하나로 종합하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 기술 리서치를 한다고 하면,&lt;br /&gt;한 에이전트는 공식 문서를 조사하고,&lt;br /&gt;다른 에이전트는 GitHub 코드를 확인하고,&lt;br /&gt;또 다른 에이전트는 관련 이슈를 살펴본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 종합 에이전트가 결과를 합쳐 최종 보고서를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대규모 리서치, 코드베이스 분석, 문서 검토, 여러 파일 리팩터링에 유용하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Adversarial Verification&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 에이전트가 결과를 만들면, 별도의 검증 에이전트가 그 결과를 공격적으로 검토한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 주장이 맞는가?&amp;rdquo;&lt;br /&gt;&amp;ldquo;근거가 충분한가?&amp;rdquo;&lt;br /&gt;&amp;ldquo;요구사항을 빠뜨리지 않았는가?&amp;rdquo;&lt;br /&gt;&amp;ldquo;코드 변경이 다른 기능을 깨지 않는가?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 결과를 일부러 의심하게 만드는 구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술 글 검증, 코드 리뷰, 보안 분석, 정책 검토, 투자 계획 검토 등에 적합하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Generate and Filter&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 개의 아이디어를 생성한 다음, 기준에 따라 걸러내는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 CLI 도구 이름을 짓는다고 하면,&lt;br /&gt;여러 에이전트가 다양한 이름을 제안하고,&lt;br /&gt;리뷰 에이전트가 기억하기 쉬움, 검색 가능성, 브랜드 적합성, 중복 가능성 등을 기준으로 필터링한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이밍, 디자인 방향 탐색, 마케팅 카피, 제품 아이디어 발굴에 잘 맞는다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Tournament&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 에이전트가 같은 문제를 각자 다른 방식으로 해결한다.&lt;br /&gt;그다음 심사 에이전트가 결과를 비교해 승자를 고른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 정답이 하나로 명확하지 않은 작업에 특히 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;가장 좋은 랜딩페이지 구조를 만들어줘&amp;rdquo;라는 요청이 있다면,&lt;br /&gt;A 에이전트는 전환율 중심으로 설계하고,&lt;br /&gt;B 에이전트는 브랜드 스토리 중심으로 설계하고,&lt;br /&gt;C 에이전트는 SEO 중심으로 설계할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 비교 심사를 통해 가장 좋은 안을 고른다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Loop Until Done&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업량이 처음부터 명확하지 않을 때 사용하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 테스트 실패 원인을 찾아야 하는데,&lt;br /&gt;몇 번의 실험이 필요한지 모를 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때 고정된 횟수만 실행하는 것이 아니라,&lt;br /&gt;&amp;ldquo;새로운 에러가 나오지 않을 때까지&amp;rdquo;&lt;br /&gt;&amp;ldquo;모든 로그가 설명될 때까지&amp;rdquo;&lt;br /&gt;&amp;ldquo;검증 에이전트가 통과를 선언할 때까지&amp;rdquo;&lt;br /&gt;반복하는 구조를 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디버깅, 리서치, 보안 점검, 데이터 품질 검사에 적합하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 어떤 작업에 특히 유용한가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 코딩에만 쓰이는 기능이 아니다.&lt;br /&gt;오히려 복잡한 비기술 작업에서도 강력하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대규모 리팩터링과 마이그레이션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 User 모델을 Account로 바꿔야 한다고 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 검색 치환으로 끝나지 않는다.&lt;br /&gt;모델명, API, 테스트, 문서, 타입, 마이그레이션 스크립트, UI 텍스트, 권한 로직까지 연결될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 작업은 여러 하위 작업으로 쪼개야 한다.&lt;br /&gt;각 callsite나 모듈마다 별도 에이전트를 붙이고, 검증 에이전트가 변경 사항을 다시 확인하는 구조가 효과적이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;딥 리서치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 리서치에도 잘 맞는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 에이전트가 웹 검색을 전부 수행하는 대신,&lt;br /&gt;여러 에이전트가 서로 다른 소스를 조사하고,&lt;br /&gt;별도 에이전트가 출처 품질을 검증하고,&lt;br /&gt;최종 에이전트가 인용이 포함된 보고서로 종합할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 단순 웹 리서치뿐 아니라 Slack, 코드베이스, 내부 문서, 이슈 트래커를 조사하는 데도 활용할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기술 글 검증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술 블로그를 공개하기 전, 모든 주장이 코드베이스와 맞는지 확인해야 할 때가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 Dynamic Workflow를 사용하면,&lt;br /&gt;먼저 한 에이전트가 글 속의 기술적 주장을 추출하고,&lt;br /&gt;각 주장마다 검증 에이전트를 배정하고,&lt;br /&gt;다시 별도 에이전트가 출처와 검증 품질을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;틀린 기술 글을 내보내지 않기 위한 자동 검증팀&amp;rdquo;처럼 쓸 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이력서 평가와 정렬&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;80개, 500개, 1000개의 이력서를 한 번에 평가하는 작업은 단일 컨텍스트에 넣기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 경우 Dynamic Workflows는 후보를 병렬로 분류하고,&lt;br /&gt;상위 후보를 다시 검증하고,&lt;br /&gt;필요하면 pairwise comparison 방식으로 순위를 조정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절대 점수보다 비교 판단이 더 안정적인 경우가 많기 때문에, 토너먼트 방식이 특히 유용할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사고 원인 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애가 발생했을 때 원인을 찾는 작업도 Dynamic Workflows와 잘 맞는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 에이전트는 로그를 본다.&lt;br /&gt;다른 에이전트는 최근 배포 내역을 본다.&lt;br /&gt;또 다른 에이전트는 데이터 변화나 외부 API 상태를 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각자 독립적으로 가설을 만든 뒤, 검증 에이전트와 반박 에이전트가 이를 테스트한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 기술 장애뿐 아니라 매출 하락, 영업 부진, 데이터 파이프라인 실패, 운영 이슈 분석에도 적용할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대규모 트리아지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지원 티켓, 버그 리포트, 고객 문의, 보안 알림처럼 사람이 모두 처리하기 어려운 큐가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 각 항목을 분류하고, 중복 여부를 확인하고, 이미 등록된 이슈와 비교하고, 필요하면 수정하거나 사람에게 에스컬레이션하는 구조를 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 중요한 개념은 &amp;ldquo;quarantine&amp;rdquo;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부에서 들어온 신뢰할 수 없는 콘텐츠를 읽는 에이전트와, 실제 권한 있는 작업을 수행하는 에이전트를 분리하는 것이다.&lt;br /&gt;이렇게 하면 프롬프트 인젝션이나 악성 입력으로부터 더 안전한 구조를 만들 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 언제 쓰지 말아야 할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 강력하지만 모든 작업에 필요한 것은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 코드 수정, 간단한 버그 수정, 짧은 문서 작성, 단순 질의응답에는 과할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워크플로는 여러 에이전트를 만들고, 병렬 처리하고, 검증 단계를 추가하기 때문에 토큰 사용량이 늘어난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Dynamic Workflows는 &amp;ldquo;더 많은 컴퓨트와 구조가 필요한 작업&amp;rdquo;에 써야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 단순한 CSS 수정에 리뷰 에이전트 5명을 붙일 필요는 없다.&lt;br /&gt;반대로 보안 분석, 대규모 리팩터링, 기술 문서 검증, 원인 분석처럼 실패 비용이 큰 작업에는 충분히 가치가 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 잘 쓰기 위한 프롬프트 방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows를 잘 쓰려면 그냥 &amp;ldquo;해줘&amp;rdquo;보다 구조를 명시하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;워크플로를 사용해서 이 실패 테스트를 재현하고, 여러 가설을 세운 뒤, 각 가설을 독립적으로 검증해줘. 하나의 가설이 통과할 때까지 멈추지 마.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 기술 블로그 초안의 모든 기술적 주장을 추출하고, 각 주장을 코드베이스와 문서 기준으로 검증하는 워크플로를 만들어줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 사업계획서를 투자자, 고객, 경쟁사 관점의 세 에이전트가 각각 비판하게 하고, 마지막에 공통 리스크와 개선안을 종합해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이력서 폴더를 백엔드 개발자 기준으로 평가하되, 먼저 나에게 평가 루브릭을 질문한 뒤, 상위 10명을 다시 검증해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 것은 AI에게 단순 결과물이 아니라&lt;br /&gt;&lt;b&gt;검증 구조, 반복 조건, 판단 기준, 역할 분담&lt;/b&gt;을 함께 지시하는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. Skill과 결합하면 더 강력해진다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 저장하고 공유할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워크플로 메뉴에서 저장하거나, ~/.claude/workflows에 넣어 재사용할 수 있다.&lt;br /&gt;또한 Skill에 JavaScript 워크플로 파일을 포함하고, SKILL.md에서 이를 참조하게 만들 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 특히 팀 단위에서 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 회사 내부에 다음과 같은 워크플로를 Skill로 만들어둘 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보안 리뷰 워크플로&lt;/li&gt;
&lt;li&gt;코드 리뷰 워크플로&lt;/li&gt;
&lt;li&gt;기술 블로그 검증 워크플로&lt;/li&gt;
&lt;li&gt;장애 원인 분석 워크플로&lt;/li&gt;
&lt;li&gt;고객 티켓 트리아지 워크플로&lt;/li&gt;
&lt;li&gt;채용 후보자 평가 워크플로&lt;/li&gt;
&lt;li&gt;제품 기획 비판 워크플로&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 되면 Claude Code는 단순한 코딩 도구가 아니라&lt;br /&gt;팀의 반복 업무를 구조화하는 실행 환경에 가까워진다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 핵심은 &amp;ldquo;에이전트에게 일을 시키는 방식&amp;rdquo;의 변화다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 AI에게 일을 시키는 방식은 대부분 이랬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이거 해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;수정해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;분석해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;요약해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Dynamic Workflows가 보여주는 방향은 조금 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로는 이렇게 요청하게 될 가능성이 크다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 일을 잘하기 위한 작업 구조를 먼저 만들고,&lt;br /&gt;필요한 하위 에이전트를 구성하고,&lt;br /&gt;검증자를 붙이고,&lt;br /&gt;반복 조건을 설정한 뒤,&lt;br /&gt;완료 기준을 만족할 때까지 실행해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, AI에게 단일 답변을 요구하는 것이 아니라&lt;br /&gt;&lt;b&gt;작업 시스템 자체를 만들게 하는 방식&lt;/b&gt;으로 바뀌고 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. Claude Code는 점점 &amp;ldquo;개발 도구&amp;rdquo;를 넘어가고 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 Claude Code가 단순 코딩 도구에서&lt;br /&gt;더 넓은 범위의 작업 오케스트레이션 도구로 확장되고 있음을 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩, 리서치, 검증, 리뷰, 분류, 정렬, 원인 분석, 팀 에이전트 운영까지&lt;br /&gt;많은 지식 작업이 사실은 &amp;ldquo;구조화된 문제 해결&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Claude Code의 Dynamic Workflows는 이 구조화된 문제 해결을&lt;br /&gt;AI가 직접 설계하고 실행하게 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 아직 초기 단계다.&lt;br /&gt;토큰 사용량도 많아질 수 있고, 모든 작업에 적합한 것도 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 방향은 분명하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트의 경쟁력은 단순히 &amp;ldquo;좋은 답변&amp;rdquo;을 만드는 데서 끝나지 않는다.&lt;br /&gt;앞으로는 &lt;b&gt;어떤 작업 구조를 만들고, 어떻게 여러 에이전트를 조율하며, 어떻게 검증까지 포함하느냐&lt;/b&gt;가 중요해질 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Workflows는 그 변화의 중요한 신호다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Claude Code는 코드를 쓰는 도구를 넘어,&lt;br /&gt;복잡한 일을 끝까지 밀어붙이기 위한&lt;br /&gt;&amp;ldquo;동적 작업 시스템&amp;rdquo;으로 진화하고 있다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1770</guid>
      <comments>https://javaexpert.tistory.com/1770#entry1770comment</comments>
      <pubDate>Thu, 4 Jun 2026 15:31:53 +0900</pubDate>
    </item>
    <item>
      <title>AI에게 아직도 좀 스크롤 자연스럽게 해달라고 하시나요?</title>
      <link>https://javaexpert.tistory.com/1769</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;1672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t0Brr/dJMcahEBzup/7y3s0vbQKdcFjosTrD0xok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t0Brr/dJMcahEBzup/7y3s0vbQKdcFjosTrD0xok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t0Brr/dJMcahEBzup/7y3s0vbQKdcFjosTrD0xok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft0Brr%2FdJMcahEBzup%2F7y3s0vbQKdcFjosTrD0xok%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;872&quot; height=&quot;1549&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;1672&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프롬프트에 바로 쓸 수 있는 애니메이션 용어 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI로 웹사이트, 앱 UI, 영상, 모션 그래픽을 만들다 보면 이런 순간이 자주 옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;버튼이 좀 자연스럽게 나타났으면 좋겠는데&amp;hellip;&amp;rdquo;&lt;br /&gt;&amp;ldquo;카드가 부드럽게 열리는 느낌이면 좋겠는데&amp;hellip;&amp;rdquo;&lt;br /&gt;&amp;ldquo;스크롤할 때 화면이 살아 움직였으면 좋겠는데&amp;hellip;&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 문제는 &amp;ldquo;자연스럽게&amp;rdquo;, &amp;ldquo;부드럽게&amp;rdquo;, &amp;ldquo;살아 있게&amp;rdquo; 같은 표현만으로는 AI가 정확히 어떤 움직임을 만들어야 하는지 알기 어렵다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애니메이션도 하나의 언어입니다.&lt;br /&gt;어떤 요소가 어떻게 등장하는지, 어떤 속도로 움직이는지, 사용자의 행동에 어떻게 반응하는지, 화면 전환에서 무엇을 유지해야 하는지에 따라 결과물의 완성도가 크게 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이번 글에서는 AI에게 애니메이션을 지시할 때 자주 쓰는 기본 용어들을 정리해보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 등장과 퇴장: 화면에 어떻게 나타나고 사라질 것인가&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;b&gt;Fade in / Fade out&lt;/b&gt;은 요소가 투명도 변화를 통해 서서히 나타나거나 사라지는 방식입니다. 가장 무난하고 안정적인 등장 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 프롬프트에서는 이렇게 쓸 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The title fades in smoothly, then fades out after two seconds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Slide in&lt;/b&gt;은 요소가 화면 밖에서 안쪽으로 미끄러져 들어오는 방식입니다. 왼쪽, 오른쪽, 위, 아래 방향을 함께 지정하면 더 정확합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The sidebar slides in from the left with an ease-out motion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Scale in&lt;/b&gt;은 요소가 작은 크기에서 원래 크기로 커지면서 나타나는 방식입니다. 보통 fade와 함께 쓰면 더 자연스럽습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The card scales in from 90% to 100% while fading in.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Pop in&lt;/b&gt;은 약간 튀어나오듯 등장하는 방식입니다. 작은 오버슈트가 있어서 알림, 배지, 버튼 등에 잘 어울립니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The notification badge pops in with a slight bounce.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Reveal&lt;/b&gt;은 콘텐츠가 한 번에 나타나는 것이 아니라 마스크나 클립을 통해 점진적으로 드러나는 방식입니다. 이미지, 제목, 섹션 오픈 등에 자주 사용됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reveal the hero image from left to right using a soft mask.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 순서와 타이밍: 여러 요소를 어떻게 조율할 것인가&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;b&gt;Keyframes&lt;/b&gt;는 애니메이션의 주요 지점을 의미합니다. 예를 들어 0%, 50%, 100% 상태를 정하면 브라우저나 애니메이션 엔진이 중간 프레임을 채워줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Interpolation / Tween&lt;/b&gt;은 시작값과 끝값 사이의 중간 프레임을 자동으로 만들어 연속적인 움직임을 만드는 과정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Stagger&lt;/b&gt;는 여러 요소를 한 번에 움직이지 않고, 약간의 시간차를 두고 순서대로 움직이는 방식입니다. 리스트, 카드, 메뉴 항목에 자주 사용됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Animate the list items with a 0.08 second stagger.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Orchestration&lt;/b&gt;은 여러 애니메이션을 하나의 흐름처럼 조율하는 것입니다. 예를 들어 배경이 먼저 흐려지고, 카드가 커지고, 텍스트가 늦게 나타나는 식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Delay&lt;/b&gt;는 애니메이션이 시작되기 전 기다리는 시간입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Duration&lt;/b&gt;은 애니메이션이 진행되는 전체 시간입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Fill mode&lt;/b&gt;는 애니메이션이 끝난 후 마지막 상태를 유지할지, 원래 상태로 돌아갈지를 결정합니다. CSS에서는 forwards 같은 값으로 자주 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Stepped animation&lt;/b&gt;은 부드러운 움직임이 아니라 단계적으로 끊어지는 애니메이션입니다. 카운트다운, 타이머, 픽셀 스타일 UI 등에 어울립니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 움직임과 변형: 위치, 크기, 회전, 깊이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI 애니메이션에서 가장 자주 쓰는 속성은 위치와 크기, 회전입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Translate&lt;/b&gt;는 요소를 X축 또는 Y축 방향으로 이동시키는 것입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Move the button 12px upward on hover.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Scale&lt;/b&gt;은 요소를 크게 하거나 작게 만드는 것입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scale the button down to 0.96 when pressed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Rotate&lt;/b&gt;는 요소를 특정 지점을 기준으로 회전시키는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Skew&lt;/b&gt;는 요소를 기울여 사각형 형태를 비스듬하게 변형하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3D tilt / Flip&lt;/b&gt;은 rotateX, rotateY처럼 3D 공간에서 요소를 회전시키는 효과입니다. 카드 뒤집기, 입체적인 호버 효과에 잘 어울립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Perspective&lt;/b&gt;는 3D 효과의 깊이감을 조절합니다. 값이 낮을수록 카메라가 가까이 있는 것처럼 깊이가 과장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Transform origin&lt;/b&gt;은 크기 변화나 회전이 시작되는 기준점입니다. 가운데에서 커지는지, 왼쪽 위에서 펼쳐지는지에 따라 느낌이 완전히 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Origin-aware animation&lt;/b&gt;은 요소가 자기 중심이 아니라, 실제 트리거된 위치에서 시작되는 애니메이션입니다. 예를 들어 팝오버가 버튼 중앙에서 커지는 것이 아니라 버튼 위치에서 자연스럽게 펼쳐지는 방식입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 상태 전환: 사용자가 화면을 잃어버리지 않게 연결하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 전환 애니메이션은 사용자가 &amp;ldquo;방금 본 것이 어디로 갔는지&amp;rdquo; 알 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Crossfade&lt;/b&gt;는 한 요소가 사라지는 동시에 다른 요소가 같은 위치에서 나타나는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Continuity transition&lt;/b&gt;은 전후 상태를 시각적으로 연결하는 전환입니다. 예를 들어 작은 사각형이 큰 카드로 확장되면 사용자는 같은 대상이 변형되었다고 인식합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Morph&lt;/b&gt;는 하나의 형태가 다른 형태로 부드럽게 변하는 것입니다. 애플의 Dynamic Island 같은 효과를 떠올리면 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Shared element transition&lt;/b&gt;은 썸네일이 확장되어 상세 카드가 되는 것처럼, 같은 요소가 위치와 크기를 바꾸며 다음 화면으로 이어지는 전환입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Layout animation&lt;/b&gt;은 레이아웃이 바뀔 때 요소가 갑자기 튀지 않고 새 위치로 부드럽게 이동하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Accordion / Collapse&lt;/b&gt;는 콘텐츠 섹션이 높이를 조절하며 열리고 닫히는 애니메이션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Direction-aware transition&lt;/b&gt;은 앞으로 이동할 때는 오른쪽에서 왼쪽으로, 뒤로 갈 때는 반대 방향으로 움직이는 식의 방향성을 가진 전환입니다. 앱 내비게이션에서 사용자에게 공간감을 줍니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 스크롤 애니메이션: 화면 이동과 함께 움직이게 만들기&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;b&gt;Scroll reveal&lt;/b&gt;은 요소가 화면에 들어올 때 fade 또는 slide로 나타나는 방식입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sections fade in and slide up as they enter the viewport.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Scroll-driven animation&lt;/b&gt;은 애니메이션 진행률이 스크롤 위치와 직접 연결되는 방식입니다. 사용자가 얼마나 스크롤했는지에 따라 애니메이션도 그만큼 진행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Parallax&lt;/b&gt;는 배경과 전경이 서로 다른 속도로 움직이면서 깊이감을 만드는 기법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Page transition&lt;/b&gt;은 페이지나 라우트가 바뀔 때 재생되는 전환 애니메이션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;View transition&lt;/b&gt;은 브라우저가 두 상태나 두 페이지 사이를 연결해주는 전환입니다. 특히 공유 요소를 자연스럽게 이어주는 데 유용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 피드백과 상호작용: 사용자의 행동에 반응하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 사용자의 행동에 즉각적으로 반응해야 합니다. 이 반응이 있어야 화면이 &amp;ldquo;살아 있다&amp;rdquo;고 느껴집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Hover effect&lt;/b&gt;는 마우스를 올렸을 때 시각적으로 바뀌는 효과입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Press / Tap feedback&lt;/b&gt;은 버튼을 누를 때 살짝 작아지는 효과입니다. 물리적인 버튼을 누르는 느낌을 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Hold to confirm&lt;/b&gt;은 버튼을 길게 누르는 동안 진행률이 차오르는 방식입니다. 삭제, 결제, 위험한 작업 확인에 어울립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Drag&lt;/b&gt;는 요소를 잡고 이동시키는 상호작용입니다. 놓았을 때 관성이나 스냅 효과가 붙으면 훨씬 자연스럽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Drag to reorder&lt;/b&gt;는 리스트 항목을 드래그해서 순서를 바꾸는 방식입니다. 다른 항목들이 자리를 비켜주는 움직임이 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Swipe to dismiss&lt;/b&gt;는 토스트, 카드, 드로어 등을 화면 밖으로 밀어 닫는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Rubber-banding&lt;/b&gt;은 경계를 넘어 드래그했을 때 저항감이 생기고 다시 튕겨 돌아오는 효과입니다. iOS의 오버스크롤 느낌과 비슷합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Shake / Wiggle&lt;/b&gt;은 입력 오류나 거절 상태를 표현할 때 쓰는 좌우 흔들림입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Ripple&lt;/b&gt;은 터치한 지점에서 원이 퍼져나가는 효과입니다. 사용자의 탭 위치를 명확히 보여줍니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 이징: 속도가 어떻게 변할 것인가&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;b&gt;Easing&lt;/b&gt;은 애니메이션의 속도가 시간에 따라 어떻게 변하는지를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Ease-out&lt;/b&gt;은 빠르게 시작해서 천천히 끝납니다. 사용자의 행동에 반응하는 대부분의 UI에 잘 어울립니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Use ease-out for the modal entrance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Ease-in&lt;/b&gt;은 천천히 시작해서 빠르게 끝납니다. UI에서는 다소 답답하게 느껴질 수 있어 주의해서 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Ease-in-out&lt;/b&gt;은 천천히 시작하고, 중간에 빨라졌다가, 다시 천천히 끝납니다. 이미 화면에 있는 요소가 A 지점에서 B 지점으로 이동할 때 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linear&lt;/b&gt;는 일정한 속도로 움직입니다. 일반 UI보다는 로딩 스피너, 마키 텍스트처럼 계속 반복되는 움직임에 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cubic-bezier&lt;/b&gt;는 직접 곡선을 정의해서 속도 변화를 세밀하게 조절하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Asymmetric easing&lt;/b&gt;은 가속과 감속의 비율이 다른 이징입니다. 너무 기계적이지 않고 살아 있는 느낌을 줄 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 스프링 애니메이션: 물리 기반 움직임&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;b&gt;Spring&lt;/b&gt;은 장력, 질량, 감쇠 같은 물리값을 기반으로 목표 지점까지 움직이는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Stiffness / Tension&lt;/b&gt;은 스프링이 목표 지점으로 끌어당기는 힘입니다. 값이 높을수록 빠르고 날카롭게 반응합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Damping&lt;/b&gt;은 스프링이 얼마나 빨리 안정되는지를 의미합니다. 낮으면 더 많이 튀고 흔들립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Mass&lt;/b&gt;는 요소의 무게감입니다. 질량이 클수록 느리고 묵직하게 움직입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Bounce&lt;/b&gt;는 목표 지점을 살짝 넘어갔다가 다시 돌아오며 안정되는 효과입니다. 캐주얼하고 장난스러운 UI에 잘 어울립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Perceptual duration&lt;/b&gt;은 실제 애니메이션이 미세하게 계속 움직이더라도, 사용자가 보기에는 끝났다고 느끼는 시간입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Momentum&lt;/b&gt;은 드래그나 플릭 이후 기존 속도를 이어받아 계속 움직이는 느낌입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Velocity&lt;/b&gt;는 요소가 어느 방향으로 얼마나 빠르게 움직이는지를 의미합니다. 좋은 스프링 애니메이션은 중간에 끊겨도 이 속도를 이어받아 자연스럽게 방향을 바꿉니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Interruptible animation&lt;/b&gt;은 애니메이션이 끝날 때까지 기다리지 않고, 중간에 사용자의 다음 행동에 맞춰 부드럽게 방향을 바꾸는 애니메이션입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 반복과 주변 움직임: 가만히 있어도 살아 있는 화면&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;b&gt;Marquee&lt;/b&gt;는 텍스트나 콘텐츠가 계속 한 방향으로 흐르는 애니메이션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Loop&lt;/b&gt;는 애니메이션이 정해진 횟수 또는 무한 반복되는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Alternate / Yoyo&lt;/b&gt;는 애니메이션이 끝난 뒤 처음으로 튀어 돌아가지 않고, 반대로 재생되며 왕복하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Orbit&lt;/b&gt;은 요소가 다른 요소 주변을 계속 도는 움직임입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Pulse&lt;/b&gt;는 크기나 투명도가 부드럽게 반복 변화하는 효과입니다. 중요한 버튼이나 상태 표시를 은근히 강조할 때 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Float&lt;/b&gt;는 위아래로 천천히 떠다니는 느낌입니다. 정적인 요소를 가볍고 생동감 있게 만듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Idle animation&lt;/b&gt;은 사용자가 아무 행동을 하지 않을 때도 아주 미세하게 재생되는 대기 애니메이션입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 디테일과 효과: 완성도를 높이는 작은 장치들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 효과 하나가 전체 UI의 인상을 바꾸기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Blur&lt;/b&gt;는 요소를 흐리게 만들어 부드럽게 보이게 하거나 배경과 전경을 분리하는 데 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Clip-path&lt;/b&gt;는 요소를 특정 형태로 잘라내는 방식입니다. 리빌, 마스크, 전후 비교 효과에 자주 쓰입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Mask&lt;/b&gt;는 요소 일부를 숨기거나 드러내는 방식입니다. clip-path와 비슷하지만 부드러운 경계나 그라데이션 표현에 더 유리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Before / after slider&lt;/b&gt;는 두 이미지를 겹쳐놓고, 드래그 가능한 구분선을 움직여 전후를 비교하는 UI입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Line drawing&lt;/b&gt;은 SVG 선이 마치 펜으로 그려지는 것처럼 나타나는 효과입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Text morph&lt;/b&gt;는 텍스트가 바뀔 때 글자 단위로 변형되는 효과입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Skeleton / Shimmer&lt;/b&gt;는 콘텐츠가 로딩되는 동안 보여주는 임시 UI입니다. 은은하게 빛이 지나가는 효과를 주면 사용자는 로딩을 더 자연스럽게 받아들입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Number ticker&lt;/b&gt;는 숫자가 굴러가거나 카운트업되는 효과입니다. 통계, 가격, 대시보드에 자주 쓰입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Tabular numbers&lt;/b&gt;는 숫자의 폭을 고정해 숫자가 바뀌어도 레이아웃이 흔들리지 않게 하는 방식입니다. 타이머, 카운터, 가격 표시에는 거의 필수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Typewriter&lt;/b&gt;는 텍스트가 한 글자씩 타이핑되듯 나타나는 효과입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 성능: 부드러운 애니메이션을 위한 기본 원칙&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;b&gt;Frame rate / FPS&lt;/b&gt;는 초당 몇 개의 프레임을 그리는지를 의미합니다. 일반적으로 60fps가 부드러운 모션의 기준이고, 최신 디스플레이에서는 120fps도 고려할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jank&lt;/b&gt;는 애니메이션이 끊기거나 버벅이는 현상입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Dropped frame&lt;/b&gt;은 브라우저가 제때 프레임을 그리지 못해서 발생하는 작은 끊김입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Compositing&lt;/b&gt;은 GPU가 별도 레이어에서 요소를 이동하거나 투명도만 바꾸도록 처리하는 방식입니다. 성능에 유리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;will-change&lt;/b&gt;는 CSS에서 곧 애니메이션될 속성을 브라우저에 미리 알려주는 힌트입니다. 다만 남용하면 오히려 메모리 부담이 생길 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Layout thrashing&lt;/b&gt;은 width, height, top, left처럼 레이아웃 재계산을 유발하는 속성을 매 프레임 바꾸면서 성능이 떨어지는 현상입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서는 가능하면 transform과 opacity 중심으로 애니메이션을 설계하는 것이 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 애니메이션을 설계할 때 기억해야 할 원칙&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;b&gt;Purposeful animation&lt;/b&gt;&lt;br /&gt;애니메이션은 장식이 아니라 기능이어야 합니다. 사용자의 시선을 안내하거나, 상태 변화를 설명하거나, 관계를 보여주거나, 피드백을 주어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Anticipation&lt;/b&gt;&lt;br /&gt;큰 움직임 전에 반대 방향으로 살짝 움직이는 예비 동작입니다. 사용자는 다음 행동을 더 자연스럽게 예측할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Follow-through&lt;/b&gt;&lt;br /&gt;주요 움직임이 끝난 뒤 일부 요소가 조금 더 움직이며 안정되는 효과입니다. 무게감과 생동감을 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Squash &amp;amp; stretch&lt;/b&gt;&lt;br /&gt;요소가 움직이면서 살짝 찌그러지거나 늘어나는 효과입니다. 캐릭터, 아이콘, 장난스러운 UI에 잘 어울립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Perceived performance&lt;/b&gt;&lt;br /&gt;실제 속도가 빨라지지 않아도, 적절한 애니메이션은 사용자가 더 빠르게 느끼도록 만듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Frequency of use&lt;/b&gt;&lt;br /&gt;사용자가 자주 보는 애니메이션일수록 짧고 subtle해야 합니다. 매번 화려하게 움직이면 금방 피로해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Spatial consistency&lt;/b&gt;&lt;br /&gt;요소가 상태를 바꿀 때 위치와 정체성을 유지해야 합니다. 사용자가 &amp;ldquo;이게 어디로 갔지?&amp;rdquo;라고 느끼면 안 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Hardware acceleration&lt;/b&gt;&lt;br /&gt;가능하면 transform과 opacity를 활용해 GPU가 부드럽게 처리할 수 있도록 설계합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Reduced motion&lt;/b&gt;&lt;br /&gt;사용자의 prefers-reduced-motion 설정을 존중해야 합니다. 모션에 민감한 사용자를 위해 애니메이션을 줄이거나 제거하는 대체 경험이 필요합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI 프롬프트에 바로 쓰는 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 이렇게 말하는 것보다,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카드가 예쁘게 나타나게 해줘.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래처럼 말하는 것이 훨씬 정확합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Animate the card with a scale-in and fade-in entrance. Start at 95% scale and 0 opacity, then transition to 100% scale and full opacity over 240ms using ease-out. Stagger multiple cards by 80ms. Use transform and opacity only for smooth performance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 한국어로 이렇게 지시할 수도 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카드가 95% 크기와 투명도 0에서 시작해, 240ms 동안 ease-out으로 100% 크기와 투명도 1까지 자연스럽게 등장하게 해줘. 여러 카드가 있을 경우 80ms 간격으로 stagger 처리하고, 성능을 위해 transform과 opacity 중심으로 애니메이션해줘.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 쓰면 AI는 &amp;ldquo;예쁘게&amp;rdquo;라는 추상적인 말보다 훨씬 정확하게 결과를 만들 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 좋은 애니메이션을 만들게 하려면 &amp;ldquo;느낌&amp;rdquo;만 말하는 것보다 &amp;ldquo;움직임의 언어&amp;rdquo;를 함께 써야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 등장할지,&lt;br /&gt;어떤 순서로 움직일지,&lt;br /&gt;어떤 속도 곡선을 사용할지,&lt;br /&gt;사용자 행동에 어떻게 반응할지,&lt;br /&gt;전환 전후의 관계를 어떻게 유지할지,&lt;br /&gt;성능은 어떻게 확보할지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 요소를 프롬프트에 넣으면 결과물의 품질이 확실히 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애니메이션은 단순한 장식이 아닙니다.&lt;br /&gt;사용자를 안내하고, 상태를 설명하고, 인터페이스에 생명감을 부여하는 설계 언어입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 시대에는 이 언어를 아는 사람이 더 좋은 화면을 만들 수 있습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1769</guid>
      <comments>https://javaexpert.tistory.com/1769#entry1769comment</comments>
      <pubDate>Wed, 3 Jun 2026 20:57:50 +0900</pubDate>
    </item>
    <item>
      <title>내 컴퓨터 위에 올리는 AI 작업실, Odysseus</title>
      <link>https://javaexpert.tistory.com/1768</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;ChatGPT를 쓰는 시대에서, 이제는 &amp;ldquo;내가 직접 호스팅하는 AI 작업공간&amp;rdquo;의 시대로&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 AI 도구의 흐름을 보면 크게 두 가지 방향이 동시에 진행되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나는 ChatGPT, Claude, Gemini처럼 완성도 높은 클라우드형 AI 서비스를 사용하는 방향입니다. 사용자는 별도의 설치 없이 브라우저에서 바로 AI를 사용할 수 있습니다. 모델 관리, 서버 운영, UI 업데이트, 보안 패치 같은 복잡한 일은 서비스 제공자가 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 하나는 정반대입니다. 내 컴퓨터나 내 서버에 AI 작업환경을 직접 설치하고, 내가 가진 데이터와 내가 선택한 모델을 중심으로 AI를 운영하는 방식입니다. 이 방향은 아직 대중적이라고 말하기는 어렵지만, 개발자와 AI 파워유저 사이에서는 점점 더 중요한 흐름이 되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 살펴볼 Odysseus는 바로 두 번째 흐름에 가까운 프로젝트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 단순한 챗봇 UI가 아닙니다. 로컬 모델과 API 모델을 연결해 대화하고, 에이전트에게 도구를 주고, 문서를 작성하고, 이메일을 정리하고, 캘린더와 노트를 관리하고, 딥리서치를 실행하는 식의 &amp;ldquo;셀프호스팅 AI 워크스페이스&amp;rdquo;를 지향합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 이런 느낌입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;ChatGPT나 Claude 같은 사용 경험을 내 컴퓨터나 내 서버 위에 직접 올려서 쓰는 AI 작업실.&amp;rdquo;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Odysseus는 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 GitHub에 공개된 오픈소스 AI 워크스페이스입니다. 프로젝트 설명을 보면, ChatGPT와 Claude 같은 UI 경험을 셀프호스팅 형태로 구현하는 것을 목표로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 단어는 세 가지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째는 self-hosted입니다.&lt;br /&gt;즉, 외부 SaaS에만 의존하지 않고 사용자가 직접 실행할 수 있는 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 local-first입니다.&lt;br /&gt;사용자의 데이터와 작업환경을 가능한 한 로컬 중심으로 다루겠다는 방향입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째는 workspace입니다.&lt;br /&gt;단순히 &amp;ldquo;AI와 대화하는 화면&amp;rdquo;이 아니라, AI를 중심으로 여러 작업을 수행하는 통합 작업공간을 만들겠다는 뜻입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Odysseus를 단순히 &amp;ldquo;로컬 ChatGPT UI&amp;rdquo;라고만 부르면 조금 부족합니다. 실제로는 채팅, 에이전트, 모델 관리, 리서치, 문서 작성, 메모리, 이메일, 캘린더, 노트, 작업 예약, 이미지 편집, 파일 업로드, MCP 도구 연결까지 한곳에 모으려는 시도에 가깝습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 1. Chat &amp;mdash; 로컬 모델과 API 모델을 모두 연결하는 대화창&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본 기능은 채팅입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 로컬 모델 또는 외부 API 모델과 대화할 수 있는 인터페이스를 제공합니다. 지원 대상으로 언급되는 구성은 vLLM, llama.cpp, Ollama, OpenRouter, OpenAI 등입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 점은 특정 모델 하나에 갇히는 구조가 아니라는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자는 이런 식으로 구성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집에 GPU 서버가 있다면 vLLM이나 llama.cpp로 로컬 모델을 띄울 수 있습니다.&lt;br /&gt;간단히 로컬 LLM을 써보고 싶다면 Ollama를 연결할 수 있습니다.&lt;br /&gt;성능 좋은 상용 모델이 필요하다면 OpenAI나 OpenRouter 같은 API를 연결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Odysseus는 모델 자체라기보다 여러 모델을 불러와 사용할 수 있는 작업 인터페이스에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점은 AI 서비스를 만들려는 사람에게 꽤 중요합니다. 사용자가 원하는 것은 단순히 &amp;ldquo;모델 하나&amp;rdquo;가 아니라, 작업에 맞춰 모델을 선택하고, 비교하고, 필요한 도구와 함께 실행할 수 있는 환경이기 때문입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 2. Agent &amp;mdash; 도구를 가진 에이전트 실행&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus의 두 번째 핵심은 Agent 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 채팅은 사용자가 질문하고 모델이 답변하는 방식입니다. 반면 에이전트는 조금 다릅니다. 사용자가 목표를 주면, 에이전트가 필요한 단계를 나누고, 도구를 호출하고, 파일을 읽거나 검색하고, 경우에 따라 shell 명령이나 MCP 도구까지 사용하면서 작업을 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus의 에이전트는 opencode, MCP, web, files, shell, skills, memory 같은 요소를 기반으로 구성된다고 설명됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말은 단순히 &amp;ldquo;답변을 잘하는 챗봇&amp;rdquo;이 아니라, 실제 작업을 수행할 수 있는 구조를 갖추려 한다는 뜻입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 작업이 가능해질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 폴더의 문서를 읽고 요약해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 프로젝트 코드를 보고 구조를 분석해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;웹에서 자료를 조사해서 보고서 초안을 만들어줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;반복되는 작업을 스킬로 저장해서 다음에도 재사용해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 실제 사용성은 연결된 모델, 권한 설정, 도구 설정, 로컬 환경에 따라 달라집니다. 하지만 Odysseus가 지향하는 방향은 명확합니다. 대화형 AI를 넘어, 사용자의 작업공간 안에서 움직이는 실행형 AI를 만드는 것입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 3. Cookbook &amp;mdash; 내 하드웨어에 맞는 모델 추천과 서빙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus에서 특히 흥미로운 기능은 Cookbook입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 LLM을 써본 사람이라면 가장 먼저 부딪히는 문제가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;내 컴퓨터에서 어떤 모델이 돌아가지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;VRAM이 부족하면 어떤 양자화 모델을 써야 하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;GGUF, FP8, AWQ는 뭐고 어떤 걸 받아야 하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;vLLM으로 띄워야 하나, llama.cpp로 띄워야 하나?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 초보자에게 꽤 큰 장벽입니다. 모델을 다운받는 것 자체는 쉬워 보여도, 실제로 내 GPU 메모리에 맞는 모델을 고르고 안정적으로 서빙하는 것은 생각보다 복잡합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus의 Cookbook은 이 문제를 줄이려는 기능입니다. 하드웨어를 스캔하고, VRAM을 고려해 모델을 추천하고, 다운로드와 서빙까지 연결하는 방향입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 단순히 &amp;ldquo;모델 목록&amp;rdquo;을 보여주는 것이 아니라, 사용자의 하드웨어 조건을 기준으로 어떤 모델이 적합한지 판단하는 기능에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 서비스를 기획하는 입장에서는 이 부분이 꽤 중요합니다. 앞으로 로컬 AI 제품은 단순히 &amp;ldquo;모델을 지원합니다&amp;rdquo;가 아니라, &amp;ldquo;당신의 환경에서 어떤 모델을 어떻게 실행하면 좋은지 안내합니다&amp;rdquo;로 가야 하기 때문입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 4. Deep Research &amp;mdash; 검색하고 읽고 종합하는 리서치 모드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus에는 Deep Research 기능도 포함되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능은 사용자가 하나의 리서치 질문을 던지면, 여러 단계로 검색하고, 자료를 읽고, 내용을 종합해 리포트 형태로 정리하는 것을 목표로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 채팅에서 &amp;ldquo;이 주제 조사해줘&amp;rdquo;라고 물어보면 모델이 기억에 의존하거나 간단한 검색 결과만 요약하는 경우가 많습니다. 반면 Deep Research는 작업을 여러 단계로 나누어 수행하는 리서치 워크플로에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 식입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;주제 분석&lt;/li&gt;
&lt;li&gt;검색 쿼리 생성&lt;/li&gt;
&lt;li&gt;웹 자료 수집&lt;/li&gt;
&lt;li&gt;자료별 핵심 내용 추출&lt;/li&gt;
&lt;li&gt;출처 간 비교&lt;/li&gt;
&lt;li&gt;최종 보고서 작성&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능은 브런치 글, 시장조사, 기술 분석, 논문 리서치, 경쟁 서비스 분석 같은 작업에 활용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 사용자가 AI를 단순 문답 도구가 아니라 &amp;ldquo;조사 보조원&amp;rdquo;으로 쓰고 싶다면 Deep Research 계열 기능은 앞으로 매우 중요한 기능이 될 가능성이 큽니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 5. Compare &amp;mdash; 여러 모델을 나란히 비교하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 많이 쓰다 보면 모델마다 답변 스타일과 성능이 다르다는 것을 금방 느낍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 모델은 글을 잘 씁니다.&lt;br /&gt;어떤 모델은 코드를 잘 봅니다.&lt;br /&gt;어떤 모델은 한국어 자연스러움이 좋습니다.&lt;br /&gt;어떤 모델은 추론은 강하지만 문체가 딱딱합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus의 Compare 기능은 하나의 프롬프트를 여러 모델에 동시에 보내고, 답변을 나란히 비교하는 기능입니다. 블라인드 테스트 형태로 모델명을 가리고 비교하는 방식도 언급됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능은 생각보다 실용적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 AI 글쓰기 서비스를 만든다면, 같은 프롬프트를 GPT 계열, 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;즉, Compare는 단순한 재미 기능이 아니라 &amp;ldquo;모델 평가 도구&amp;rdquo;로도 볼 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 6. Documents &amp;mdash; AI가 보조하는 문서 편집기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus에는 문서 편집 기능도 있습니다.&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;README 기준으로 markdown, HTML, CSV, syntax highlighting, AI edits, suggestions 같은 기능이 언급됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방향은 매우 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 많은 사람이 AI로 글을 쓸 때 채팅창에서 초안을 받고, 다시 워드나 노션이나 구글문서로 옮깁니다. 그런데 이 과정은 번거롭습니다. 글의 버전 관리도 어렵고, 긴 문서를 다룰 때 맥락이 끊기기도 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 실제 작업도구가 되려면 채팅창만으로는 부족합니다. 문서, 코드, 표, 리서치 결과, 메모가 하나의 작업공간 안에서 연결되어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus의 Documents 기능은 바로 그 방향으로 가려는 시도입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 7. Memory / Skills &amp;mdash; 누적되는 개인화와 반복 작업 재사용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 Memory와 Skills 기능도 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Memory는 사용자의 대화, 작업 방식, 선호, 과거 맥락을 저장하고 검색하는 기능입니다. README에는 ChromaDB, fastembed, vector + keyword retrieval, import/export 같은 구성이 언급됩니다.&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;Skills는 반복 작업을 재사용 가능한 형태로 만드는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 매번 같은 방식으로 GitHub 프로젝트를 분석한다면, 그 분석 과정을 하나의 스킬로 저장할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;README 요약 &amp;rarr; 설치 방법 확인 &amp;rarr; 기능 목록화 &amp;rarr; 유사 프로젝트 비교 &amp;rarr; 사용 시나리오 작성 &amp;rarr; 한계점 정리&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 흐름을 스킬로 만들면 다음 프로젝트 분석 때도 같은 구조로 재사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 Hermes 같은 자기개선형 에이전트와도 연결되는 지점입니다. 다만 Odysseus는 메신저형 개인 비서라기보다, 웹 기반 AI 작업공간 안에서 메모리와 스킬을 통합하려는 느낌이 강합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 8. Email &amp;mdash; IMAP/SMTP 기반 AI 메일 보조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus에는 이메일 기능도 포함되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IMAP/SMTP 기반 inbox를 연결하고, AI triage를 수행하는 방향입니다. 기능 설명에는 긴급도 알림, 자동 태깅, 자동 요약, 답장 초안, 스팸 분류 등이 언급됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능이 중요한 이유는 이메일이 여전히 업무 자동화의 핵심이기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 개인 비서를 만든다고 할 때 가장 먼저 연결하고 싶은 데이터는 보통 이메일, 캘린더, 파일, 메신저입니다. 그중 이메일은 업무 요청, 계약, 일정, 영수증, 알림, 고객 문의가 모두 들어오는 중심 채널입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus가 이메일 기능을 포함했다는 것은, 이 프로젝트가 단순한 채팅 UI가 아니라 실제 업무 흐름에 들어가려는 의도를 가지고 있다는 뜻입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 9. Calendar &amp;mdash; CalDAV 기반 로컬 우선 캘린더&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 Calendar 기능도 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CalDAV sync를 통해 Radicale, Nextcloud, Apple, Fastmail 등과 연동할 수 있고, ics import/export, calendar colors, agent-aware 구조가 언급됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캘린더는 에이전트 자동화에서 매우 중요한 요소입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 AI 에이전트에게 이런 요청을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;다음 주 빈 시간에 회의 잡아줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;오늘 일정 요약해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;마감일이 있는 작업을 캘린더에 반영해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;내일 오전 회의 전에 관련 자료를 정리해줘.&amp;rdquo;&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;Odysseus는 이 부분을 로컬 우선 캘린더 구조로 접근합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 10. Notes &amp;amp; Tasks &amp;mdash; 노트, 할 일, 예약 작업&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 Notes &amp;amp; Tasks 기능도 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 노트, 체크리스트, 리마인더, cron-style scheduled tasks, ntfy/browser/email 알림 채널 등이 언급됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능은 에이전트를 실제 개인 업무 시스템으로 만들 때 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 아무리 똑똑해도 작업을 저장하고, 할 일로 남기고, 특정 시간에 다시 실행하고, 결과를 알림으로 보내지 못하면 &amp;ldquo;지속적인 비서&amp;rdquo;가 되기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Notes &amp;amp; Tasks는 그 지속성을 만드는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 식으로 쓸 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;매주 월요일 오전에 AI 뉴스 정리해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;내가 저장한 아이디어를 주제별로 정리해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;오늘 해야 할 일 중 우선순위를 정해줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이 리서치 결과를 노트로 저장해줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 Odysseus는 단순히 한 번 답하고 끝나는 AI가 아니라, 사용자의 작업 루틴 안에 들어가는 AI를 지향합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 기능 11. Extras &amp;mdash; 이미지, 파일, PDF, 웹검색, 테마, 2FA&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus에는 부가 기능도 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;README 기준으로 image editor, theme editor, file uploads, vision, PDF, web search, presets, sessions, 2FA 등이 언급됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 파일 업로드와 PDF, 비전 기능은 실제 업무에서 중요합니다. 사용자는 대부분 텍스트만 다루지 않습니다. PDF, 이미지, 문서, 표, 캡처 화면, 코드 파일, 로그 파일을 함께 다룹니다.&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 data-ke-size=&quot;size26&quot;&gt;설치 방법 1. Docker로 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus에서 권장하는 설치 방법은 Docker입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
cp .env.example .env
docker compose up -d --build
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너가 정상적으로 올라오면 브라우저에서 다음 주소를 엽니다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;http://localhost:7000
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 실행하면 관리자 계정이 생성되고, 임시 비밀번호가 터미널 로그에 출력됩니다. Docker 설치라면 다음 명령으로 로그를 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;docker compose logs odysseus
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그에서 임시 비밀번호를 확인한 뒤 로그인하고, Settings에서 비밀번호를 변경하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 방식은 가장 간단하게 전체 구성을 올릴 수 있다는 장점이 있습니다. 기본 compose 구성에서는 Odysseus 외에도 ChromaDB, SearXNG, ntfy 같은 서비스가 함께 올라갑니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 방법 2. Linux / macOS 네이티브 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 없이 직접 실행할 수도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python setup.py
python -m uvicorn app:app --host 127.0.0.1 --port 7000
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요 조건은 Python 3.11 이상입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 Docker보다 환경을 직접 만져야 하지만, 로컬 시스템과 더 밀접하게 연결할 수 있다는 장점이 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 방법 3. Apple Silicon에서 실행하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apple Silicon, 즉 M1/M2/M3/M4 계열 Mac에서는 주의할 점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker on macOS는 Metal GPU를 사용할 수 없습니다. 그래서 GPU 가속을 제대로 활용하려면 네이티브 실행이 권장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 Apple Silicon용 시작 스크립트를 제공합니다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
./start-macos.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 기본 실행 주소는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;http://127.0.0.1:7860
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mac에서는 AirPlay가 7000번 포트를 사용하는 경우가 있어서 7860 포트를 기본으로 사용하는 것으로 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 같은 네트워크의 다른 기기, 예를 들어 휴대폰에서 접속하고 싶다면 신뢰할 수 있는 LAN이나 Tailscale 같은 VPN 환경에서 호스트를 열 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;ODYSSEUS_HOST=0.0.0.0 ./start-macos.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 이 경우 인증 설정을 반드시 켜두어야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 방법 4. Windows에서 실행하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows도 네이티브 실행을 지원합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 간단한 방식은 PowerShell 스크립트를 사용하는 것입니다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
powershell -ExecutionPolicy Bypass -File .\launch-windows.ps1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 수동으로 실행하려면 다음 흐름을 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
py -3.11 -m venv venv
venv\Scripts\Activate.ps1
pip install -r requirements.txt
python setup.py
python -m uvicorn app:app --host 127.0.0.1 --port 7000
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows에서 로컬 모델을 쉽게 쓰려면 Ollama를 설치하고, Odysseus Settings에서 다음 엔드포인트를 연결하는 방식이 가장 간단합니다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;http://localhost:11434/v1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 vLLM이나 SGLang 같은 로컬 GPU 서빙은 Windows 네이티브보다는 Linux 또는 WSL2 환경이 더 적합합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 사용 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus를 처음 설치한 뒤에는 다음 순서로 설정하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 관리자 계정으로 로그인합니다.&lt;br /&gt;처음 생성된 임시 비밀번호를 사용해 로그인하고, Settings에서 비밀번호를 변경합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 모델 제공자를 연결합니다.&lt;br /&gt;Ollama, OpenAI, OpenRouter, vLLM, llama.cpp 등 자신이 사용할 모델 환경을 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 검색 기능을 설정합니다.&lt;br /&gt;Docker 구성을 사용하면 SearXNG가 함께 올라오므로, 웹 검색 기반 리서치에 활용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, 메모리 기능을 확인합니다.&lt;br /&gt;ChromaDB 기반 메모리 저장소가 정상 작동하는지 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯째, 에이전트 도구 권한을 조정합니다.&lt;br /&gt;shell, files, web, MCP 같은 도구는 강력한 기능이지만 보안 위험도 있으므로 필요한 도구만 켜는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여섯째, 이메일과 캘린더를 연결합니다.&lt;br /&gt;IMAP/SMTP와 CalDAV 정보를 연결하면 메일 요약, 답장 초안, 일정 기반 작업이 가능해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일곱째, 모바일 접속을 설정합니다.&lt;br /&gt;Odysseus는 모바일에서도 사용할 수 있는 PWA 형태를 지향합니다. 단, 외부 접속을 열 때는 인증과 프록시 보안을 반드시 고려해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 활용 시나리오 1. 로컬 AI 글쓰기 작업실&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브런치 글이나 기술 블로그를 자주 쓰는 사람이라면 Odysseus를 글쓰기 작업실처럼 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 GitHub 프로젝트를 분석하는 글을 쓴다고 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Deep Research로 프로젝트의 README와 관련 자료를 조사합니다.&lt;br /&gt;그다음 Documents에서 글의 초안을 작성합니다.&lt;br /&gt;Compare로 여러 모델의 제목과 도입부를 비교합니다.&lt;br /&gt;Memory에 자신의 글쓰기 스타일과 선호 구조를 저장합니다.&lt;br /&gt;마지막으로 AI에게 문단별 수정 제안을 받습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 단순히 &amp;ldquo;글 하나 써줘&amp;rdquo;가 아니라, 리서치부터 초안 작성, 비교, 수정까지 하나의 공간에서 처리할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 활용 시나리오 2. 개발자용 로컬 에이전트 콘솔&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자라면 Odysseus를 코드 분석과 프로젝트 관리용 콘솔로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 로컬 프로젝트 폴더를 읽게 하고, 코드 구조를 분석하게 할 수 있습니다. shell과 files 도구를 연결하면 에이전트가 프로젝트 내부 파일을 확인하고, 필요한 명령을 실행하는 흐름도 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이 경우 보안 권한 설정이 매우 중요합니다. shell 도구는 강력하지만 위험합니다. 신뢰할 수 없는 프롬프트나 외부 입력을 그대로 실행하는 구조는 피해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 입장에서는 Odysseus가 &amp;ldquo;로컬 Claude Code&amp;rdquo; 또는 &amp;ldquo;브라우저 기반 에이전트 작업실&amp;rdquo;처럼 느껴질 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 활용 시나리오 3. 개인 업무 비서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이메일, 캘린더, 노트, 작업 예약 기능을 연결하면 Odysseus는 개인 업무 비서에 가까워집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 매일 아침 이메일을 요약하고, 중요한 메일을 태깅하고, 답장 초안을 만들고, 오늘 일정을 정리하는 식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 핵심은 데이터가 로컬 중심으로 관리된다는 점입니다. 물론 외부 API 모델을 연결하면 일부 데이터가 외부 모델 제공자에게 전달될 수 있습니다. 따라서 민감한 정보를 다룰 때는 어떤 모델과 어떤 API를 쓰는지 명확히 이해해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 활용 시나리오 4. AI 모델 테스트베드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 서비스를 개발하는 사람에게 Compare와 Cookbook은 특히 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 프롬프트를 여러 모델에 보내고 결과를 비교할 수 있습니다.&lt;br /&gt;내 하드웨어에 맞는 모델을 찾아보고 다운로드할 수 있습니다.&lt;br /&gt;로컬 모델과 API 모델을 같은 UI에서 비교할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 기능은 &amp;ldquo;어떤 모델을 우리 서비스에 붙일 것인가?&amp;rdquo;를 결정할 때 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 고객 응대용 모델, 코드 리뷰용 모델, 글쓰기용 모델, 리서치용 모델은 각각 적합한 모델이 다를 수 있습니다. Odysseus는 이런 비교 실험을 한곳에서 해볼 수 있는 환경을 제공합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기존 에이전트 프로젝트와 비교하면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus를 Hermes나 OpenClaw 같은 프로젝트와 비교하면 포지션이 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hermes는 자기개선형 에이전트에 가깝습니다. 장기 기억, 스킬 생성, 사용자 적응, 반복 작업 자동화에 더 초점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenClaw는 메신저 기반 개인 비서에 가깝습니다. WhatsApp, Telegram, Slack, Discord 같은 채널에서 AI 비서를 사용하는 방향입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 Odysseus는 웹 기반 AI 워크스페이스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Hermes가 &amp;ldquo;스스로 성장하는 에이전트&amp;rdquo;에 가깝고, OpenClaw가 &amp;ldquo;어디서든 부를 수 있는 개인 비서&amp;rdquo;에 가깝다면, Odysseus는 &amp;ldquo;내 브라우저 안에 만든 AI 작업실&amp;rdquo;에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이가 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 하나의 에이전트만 잘 만드는 프로젝트라기보다, 여러 AI 작업을 한 화면에서 다룰 수 있는 플랫폼형 구조를 지향합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;보안에서 반드시 주의할 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 강력한 도구입니다. 그래서 보안도 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 다음 기능들은 조심해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shell 접근&lt;br /&gt;파일 업로드&lt;br /&gt;로컬 파일 읽기/쓰기&lt;br /&gt;웹 리서치&lt;br /&gt;이메일/캘린더 연동&lt;br /&gt;API 토큰 저장&lt;br /&gt;모델 서버 연결&lt;br /&gt;MCP 도구 연결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 기능들은 편리하지만, 잘못 설정하면 위험할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 기본 원칙은 명확합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 인터넷에 직접 노출하지 않는 것이 좋습니다.&lt;br /&gt;네트워크에 공개해야 한다면 HTTPS, 인증, reverse proxy, private access layer를 구성해야 합니다.&lt;br /&gt;AUTH_ENABLED=true를 유지해야 합니다.&lt;br /&gt;API 키와 토큰은 로그, 스크린샷, 공유 문서에 노출하지 않아야 합니다.&lt;br /&gt;shell과 파일 권한은 꼭 필요한 사용자에게만 부여해야 합니다.&lt;br /&gt;로컬 모델 서버와 ChromaDB, SearXNG, Ollama 같은 내부 서비스 포트는 외부에 직접 노출하지 않는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 개인용 AI 작업실이지만, 기능만 보면 사실상 관리자 콘솔에 가깝습니다. 편리함만 보고 열어두면 안 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Odysseus의 장점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 장점은 통합성입니다.&lt;br /&gt;채팅, 에이전트, 모델 관리, 리서치, 문서, 메모리, 이메일, 캘린더, 노트가 한곳에 모입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 장점은 로컬 우선 구조입니다.&lt;br /&gt;자신의 하드웨어와 자신의 데이터 위에서 AI 작업공간을 운영할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 장점은 모델 선택의 자유입니다.&lt;br /&gt;Ollama, llama.cpp, vLLM, OpenAI, OpenRouter 등 다양한 모델 환경을 연결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 번째 장점은 실험성입니다.&lt;br /&gt;Compare, Cookbook, Skills, MCP 같은 기능은 AI 파워유저나 개발자에게 매력적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯 번째 장점은 제품 기획 관점에서 참고할 부분이 많다는 것입니다.&lt;br /&gt;AI 앱을 만들려는 사람이라면 Odysseus를 보면서 &amp;ldquo;AI 작업공간은 어떤 모듈로 구성될 수 있는가?&amp;rdquo;를 배울 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Odysseus의 한계&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;br /&gt;Docker, Python, 모델 서버, 포트, GPU, .env 설정 같은 개념이 익숙하지 않으면 진입장벽이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 기능 범위가 넓습니다.&lt;br /&gt;기능이 많다는 것은 장점이지만, 동시에 완성도와 안정성 측면에서는 부담이 됩니다. 하나의 앱 안에 너무 많은 기능이 들어가면 사용자는 어디서부터 써야 할지 헷갈릴 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 로컬 모델 사용은 하드웨어 영향을 많이 받습니다.&lt;br /&gt;GPU와 VRAM이 부족하면 기대한 성능이 나오기 어렵습니다. 작은 서버에서는 외부 API 모델을 연결하는 편이 더 현실적일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, 보안 설정을 사용자가 직접 이해해야 합니다.&lt;br /&gt;셀프호스팅의 자유는 곧 책임을 동반합니다. 특히 이메일, 캘린더, 파일, shell을 연결하는 경우 보안 리스크를 반드시 고려해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;누가 써보면 좋을까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 모든 사람을 위한 도구라기보다, 다음 사용자에게 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 LLM을 직접 운영해보고 싶은 개발자.&lt;br /&gt;AI 에이전트 작업공간을 실험해보고 싶은 사람.&lt;br /&gt;ChatGPT나 Claude 같은 UI를 셀프호스팅으로 구현해보고 싶은 사람.&lt;br /&gt;개인 데이터 중심의 AI 워크스페이스를 만들고 싶은 사람.&lt;br /&gt;여러 모델을 비교하고 테스트하고 싶은 AI 서비스 기획자.&lt;br /&gt;MCP, 로컬 도구, 파일, 문서, 이메일, 캘린더를 연결한 에이전트 환경을 연구하고 싶은 사람.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 단순히 &amp;ldquo;편하게 AI 채팅만 쓰고 싶다&amp;rdquo;면 ChatGPT나 Claude 같은 클라우드 서비스가 더 적합할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI 서비스 기획 관점에서 보는 Odysseus&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus가 흥미로운 이유는 단순히 기능이 많아서가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트는 앞으로 AI 제품이 어떤 방향으로 갈 수 있는지 보여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 AI 서비스는 대부분 채팅창 중심이었습니다. 하지만 실제 사용자는 채팅만 하고 싶은 것이 아닙니다. 글을 쓰고, 자료를 찾고, 파일을 정리하고, 이메일에 답하고, 일정을 관리하고, 반복 업무를 자동화하고 싶어 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, AI의 다음 단계는 &amp;ldquo;대화창&amp;rdquo;이 아니라 &amp;ldquo;작업공간&amp;rdquo;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 이 방향을 꽤 노골적으로 보여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;채팅은 시작점일 뿐입니다.&lt;br /&gt;에이전트는 실행 계층입니다.&lt;br /&gt;메모리는 개인화 계층입니다.&lt;br /&gt;스킬은 반복 작업 계층입니다.&lt;br /&gt;문서는 생산성 계층입니다.&lt;br /&gt;이메일과 캘린더는 업무 연결 계층입니다.&lt;br /&gt;Cookbook은 모델 운영 계층입니다.&lt;br /&gt;Compare는 평가 계층입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 보면 Odysseus는 하나의 앱이라기보다, 개인용 AI OS의 초기 형태처럼 보입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 &amp;ldquo;내 컴퓨터 위에 직접 올리는 AI 작업실&amp;rdquo;에 가까운 프로젝트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순한 챗봇 UI가 아니라, 채팅, 에이전트, 모델 서빙, 딥리서치, 문서 작성, 메모리, 스킬, 이메일, 캘린더, 노트, 작업 예약, 이미지 편집, MCP까지 포함하려는 통합형 AI 워크스페이스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 아직 일반 사용자가 쉽게 쓰기에는 설치와 운영 장벽이 있습니다. 보안 설정도 신경 써야 합니다. 로컬 모델 성능은 하드웨어에 크게 의존합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 AI 제품을 만들거나, 로컬 LLM을 실험하거나, 에이전트 기반 작업공간을 연구하는 사람에게는 매우 흥미로운 레퍼런스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 앞으로 AI 서비스가 단순 채팅을 넘어 &amp;ldquo;작업공간화&amp;rdquo;될 것이라고 본다면, Odysseus는 한 번 살펴볼 가치가 충분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI의 미래가 단순히 더 똑똑한 모델 하나로 끝나지는 않을 것입니다.&lt;br /&gt;중요한 것은 그 모델이 어디에서, 어떤 도구와 함께, 어떤 데이터 위에서, 어떤 작업 흐름으로 움직이느냐입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Odysseus는 바로 그 질문에 대해 이렇게 답하는 프로젝트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;AI를 내 작업공간 안으로 가져오자.&amp;rdquo;&lt;/p&gt;
&lt;figure id=&quot;og_1780457446374&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Odysseus &amp;mdash; A Self-Hosted AI Workspace&quot; data-og-description=&quot;Yours for the voyage. Your own AI workspace,running on your hardware. Odysseus is a self-hosted interface for talking to language models &amp;mdash; chat, autonomous agents, tools, model serving, email, research, and more. Local-first, privacy-first, and no teleme&quot; data-og-host=&quot;pewdiepie-archdaemon.github.io&quot; data-og-source-url=&quot;https://pewdiepie-archdaemon.github.io/odysseus/&quot; data-og-url=&quot;https://pewdiepie-archdaemon.github.io/odysseus/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xAS3G/dJMb8PGDucO/jfF3DR20rHGKgNKMLFsDt0/img.png?width=452&amp;amp;height=452&amp;amp;face=148_127_303_296&quot;&gt;&lt;a href=&quot;https://pewdiepie-archdaemon.github.io/odysseus/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pewdiepie-archdaemon.github.io/odysseus/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xAS3G/dJMb8PGDucO/jfF3DR20rHGKgNKMLFsDt0/img.png?width=452&amp;amp;height=452&amp;amp;face=148_127_303_296');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Odysseus &amp;mdash; A Self-Hosted AI Workspace&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Yours for the voyage. Your own AI workspace,running on your hardware. Odysseus is a self-hosted interface for talking to language models &amp;mdash; chat, autonomous agents, tools, model serving, email, research, and more. Local-first, privacy-first, and no teleme&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pewdiepie-archdaemon.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1768</guid>
      <comments>https://javaexpert.tistory.com/1768#entry1768comment</comments>
      <pubDate>Wed, 3 Jun 2026 12:30:52 +0900</pubDate>
    </item>
    <item>
      <title>코딩으로 하루종일 써도 0.1달러가 나온다? (DeepSeek-Reasonix)</title>
      <link>https://javaexpert.tistory.com/1767</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;DeepSeek-Reasonix는&amp;nbsp;어떻게&amp;nbsp;딥시크&amp;nbsp;캐시&amp;nbsp;히트를&amp;nbsp;끌어올렸나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;에이전트 비용 최적화의 핵심은 &amp;lsquo;더 똑똑한 모델&amp;rsquo;이 아니라 &amp;lsquo;흔들리지 않는 프롬프트 구조&amp;rsquo;일 수 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 코딩 에이전트나 장시간 작업 에이전트를 만들다 보면 가장 먼저 부딪히는 문제가 있다.&lt;br /&gt;바로 &lt;b&gt;토큰 비용&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한두 번 질문하는 챗봇이라면 큰 문제가 아니다. 하지만 코드 분석, 파일 수정, 장편 글쓰기, 리서치, 영상 프롬프트 제작처럼 여러 턴에 걸쳐 작업하는 에이전트는 구조가 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 이전 대화, 시스템 프롬프트, 도구 목록, 작업 결과, 파일 내용, 중간 상태를 다시 모델에 넣는다.&lt;br /&gt;그러다 보면 실제로 새로 입력하는 내용은 얼마 안 되는데, 매 요청마다 수만 토큰의 이전 맥락을 반복해서 보내는 상황이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 DeepSeek API의 context caching, 즉 캐시 기능을 잘 활용하면 비용 구조가 크게 달라질 수 있다.&lt;br /&gt;GitHub의 &lt;b&gt;DeepSeek-Reasonix&lt;/b&gt; 프로젝트는 바로 이 지점을 꽤 영리하게 파고든 에이전트 프레임워크다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DeepSeek 캐시는 무엇을 캐시하는가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepSeek API는 context caching을 기본적으로 제공한다. 핵심은 단순하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 요청과 다음 요청의 앞부분이 같으면, 그 겹치는 prefix 부분을 캐시 히트로 처리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 첫 번째 요청이 다음과 같다고 하자.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;A + B
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 요청이 다음처럼 들어오면,&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;A + B + C
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 A + B는 이전 요청과 동일하기 때문에 캐시 히트가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 두 번째 요청이 이렇게 바뀌면,&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;A + C + B
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;겉보기에는 비슷한 정보가 들어 있어도 prefix 구조가 달라진다. 이 경우 캐시 효율은 떨어질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 이것이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepSeek 캐시는 &amp;ldquo;의미가 비슷한가&amp;rdquo;보다 &amp;ldquo;앞부분이 얼마나 그대로 유지되는가&amp;rdquo;에 더 민감하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 에이전트 설계에서 캐시를 잘 쓰려면 모델을 잘 고르는 것만으로는 부족하다.&lt;br /&gt;프롬프트 구조 자체를 캐시 친화적으로 만들어야 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 이 과정에서 프롬프트의 앞부분이 조금씩 흔들린다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 요소들이 캐시 효율을 떨어뜨릴 수 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;- system prompt가 매번 조금씩 바뀜
- tool schema 순서가 바뀜
- 도구 실행 결과가 앞부분에 삽입됨
- 타임스탬프나 상태값이 prompt 초반에 들어감
- 중간 reasoning 내용이 다음 요청에 다시 포함됨
- context compaction이 너무 자주 발생함
- planner 모델과 executor 모델이 같은 세션에 섞임
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람이 보기에는 사소한 차이일 수 있다.&lt;br /&gt;하지만 prefix cache 입장에서는 앞부분이 바뀐 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시는 &amp;ldquo;대충 비슷한 프롬프트&amp;rdquo;를 좋아하는 것이 아니라, &amp;ldquo;이전에 본 프롬프트의 앞부분이 그대로 이어지는 구조&amp;rdquo;를 좋아한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reasonix의 핵심 전략: 앞부분은 고정하고 뒤에만 붙인다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepSeek-Reasonix의 핵심 설계는 아주 단순하게 요약할 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대화의 앞부분을 가능한 한 고정하고, 새로운 내용은 뒤에만 append한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 에이전트 세션을 하나의 로그처럼 다룬다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1턴:
system + user1

2턴:
system + user1 + assistant1 + tool1 + user2

3턴:
system + user1 + assistant1 + tool1 + user2 + assistant2 + tool2 + user3
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조에서는 앞부분이 계속 유지된다.&lt;br /&gt;새 요청이 들어와도 기존 대화의 prefix가 그대로 남아 있기 때문에 DeepSeek의 캐시가 작동하기 좋은 형태가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 특별한 마법이라기보다, DeepSeek의 캐시 과금 구조에 맞춰 에이전트의 대화 관리 방식을 바꾼 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reasoning content를 다시 보내지 않는 설계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix에서 특히 눈에 띄는 부분은 assistant의 reasoning content를 다음 API 요청에 다시 넣지 않는다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추론 과정은 길고, 매번 달라지고, 다음 요청에 꼭 필요한 정보가 아닐 때가 많다.&lt;br /&gt;이런 내용을 계속 prompt에 포함하면 입력 토큰도 커지고, prefix 안정성도 떨어질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix는 reasoning content를 세션 기록이나 화면 표시용으로는 다룰 수 있지만, 다음 모델 호출의 prompt input에는 다시 넣지 않는 방향을 취한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조적으로 보면 이런 차이다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;비효율적인 구조:
system + history + assistant reasoning + tool result + user

Reasonix에 가까운 구조:
system + history + assistant visible content + tool result + user
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이는 작아 보이지만 장시간 실행되는 에이전트에서는 꽤 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 DeepSeek처럼 reasoning 모델을 사용할 경우, reasoning output을 다시 input으로 넣는 순간 비용이 커질 수 있다.&lt;br /&gt;또한 reasoning은 변동성이 큰 내용이라 캐시 prefix를 오염시키기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 Reasonix는 &amp;ldquo;보관할 것&amp;rdquo;과 &amp;ldquo;다음 프롬프트에 다시 넣을 것&amp;rdquo;을 분리한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Tool schema와 system prompt를 안정적으로 유지한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트에서 tool schema는 생각보다 큰 토큰 덩어리다.&lt;br /&gt;파일 읽기, 셸 실행, 검색, 수정, 패치, 플러그인, MCP 도구 등이 많아질수록 tool definition은 길어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이 tool schema가 매번 순서가 바뀌거나 JSON 구조가 조금씩 달라지면 어떻게 될까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시 입장에서는 앞부분이 흔들린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix의 설계 방향은 system prompt와 tool specs를 세션 앞부분에 안정적으로 두고, 가능하면 이를 바꾸지 않는 것이다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;[Stable Prefix]
- system prompt
- tool definitions
- project rules
- output format rules

[Append-only Log]
- user request
- assistant response
- tool result
- next user request
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 구조를 유지하면, 매 턴 새로 추가되는 부분은 뒤쪽에 쌓이고, 앞부분은 계속 캐시 대상으로 남는다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Planner와 Executor를 같은 세션에 섞지 않는다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix의 또 다른 흥미로운 설계는 planner model과 executor model을 분리해서 운영하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 에이전트에서는 보통 두 가지 역할이 필요하다.&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;Planner:
무엇을 할지 계획하는 역할

Executor:
실제로 도구를 호출하고 작업을 수행하는 역할
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 이 둘을 같은 대화 세션에 섞으면 prompt prefix가 복잡해진다는 점이다.&lt;br /&gt;특히 서로 다른 모델을 번갈아 호출하면 캐시 효율이 떨어질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix는 이 문제를 피하기 위해 planner session과 executor session을 분리하는 구조를 취한다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;planner session:
planner system + planner history

executor session:
executor system + tool schema + executor history
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 각 세션의 prefix가 독립적으로 안정화된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &amp;ldquo;멀티 모델 협업&amp;rdquo;을 하더라도 하나의 세션에 마구 섞는 것이 아니라, 캐시가 유지되기 좋은 단위로 나누는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Compaction은 필요하지만 자주 하면 안 된다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장시간 실행되는 에이전트는 언젠가 context window 한계에 도달한다.&lt;br /&gt;이때 필요한 것이 compaction이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;compaction은 오래된 대화나 작업 기록을 요약해서 context를 줄이는 과정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 캐시 관점에서 compaction은 조심해야 한다.&lt;br /&gt;왜냐하면 오래된 대화 앞부분을 요약문으로 바꾸는 순간, 이전에 유지되던 prefix 구조가 깨질 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, compaction은 비용을 줄이는 기능이면서 동시에 캐시를 리셋할 수 있는 이벤트다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix는 compaction을 너무 자주 하지 않고, context window가 일정 비율 이상 찼을 때만 수행하는 방식으로 설계되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흐름은 대략 이렇다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;평소:
system + old history + recent history + new turn
=&amp;gt; cache hit가 유지되기 쉬움

compaction 시점:
system + summary + recent history
=&amp;gt; 기존 prefix 일부가 깨질 수 있음

compaction 이후:
system + summary + recent history + new turns
=&amp;gt; 다시 append-only 구조로 캐시 효율 회복
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 compaction 자체를 없애는 것이 아니다.&lt;br /&gt;compaction을 &amp;ldquo;매번 하는 정리 작업&amp;rdquo;이 아니라 &amp;ldquo;가끔 발생하는 캐시 리셋 포인트&amp;rdquo;로 다루는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reasonix가 주장하는 캐시 히트 수치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix 저장소에는 실제 사용 사례로 매우 높은 cache hit ratio가 제시되어 있다.&lt;br /&gt;문서 기준으로는 99% 이상의 input cache hit ratio를 기록한 사례도 소개되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이 수치는 프로젝트 측이 공개한 사례이며, 독립적으로 재현된 벤치마크라고 보기는 어렵다.&lt;br /&gt;따라서 이 숫자 자체를 그대로 일반화하기보다는, &amp;ldquo;이런 구조를 만들면 DeepSeek 캐시가 잘 작동할 가능성이 높다&amp;rdquo;는 방향으로 보는 것이 안전하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 것은 숫자보다 구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix가 보여주는 핵심은 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1. system prompt를 고정한다.
2. tool schema를 고정한다.
3. 대화 로그를 append-only로 유지한다.
4. reasoning content를 다음 input에 다시 넣지 않는다.
5. compaction을 자주 하지 않는다.
6. planner와 executor 세션을 분리한다.
7. 모델별 세션을 섞지 않는다.
8. cache hit / cache miss usage를 계속 관측한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 원칙들은 Reasonix뿐 아니라 다른 에이전트 시스템에도 적용할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이 구조가 중요한 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람들이 AI 에이전트 비용 최적화를 이야기할 때 가장 먼저 모델 가격을 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 모델 가격도 중요하다.&lt;br /&gt;하지만 장시간 실행되는 에이전트에서는 프롬프트 구조가 더 큰 차이를 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 모델을 쓰더라도 한쪽은 매번 전체 프롬프트를 새로 조립하고, 다른 한쪽은 안정적인 prefix를 유지한다면 비용 구조가 완전히 달라질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 코딩 에이전트, 리서치 에이전트, 글쓰기 에이전트, 영상 제작 에이전트처럼 작업 맥락이 길게 이어지는 시스템에서는 캐시 친화적인 세션 설계가 필수에 가까워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 말하면 이렇다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;비싼 에이전트:
매번 전체 문맥을 새로 만든다.

캐시 친화적인 에이전트:
한번 만든 앞부분을 최대한 유지하고, 뒤에만 쌓는다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내가 에이전트를 만든다면 어떻게 적용할까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepSeek 기반으로 에이전트를 만든다면 다음과 같은 구조가 좋다.&lt;/p&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;[고정 Prefix]
- 시스템 프롬프트
- 역할 정의
- 출력 규칙
- 도구 목록
- 프로젝트 규칙
- 세계관/캐릭터/코드베이스 핵심 요약

[Append-only 작업 로그]
- 사용자 요청
- 에이전트 응답
- 도구 실행 결과
- 사용자 수정사항
- 다음 작업 지시

[Volatile Scratch]
- 내부 계획
- 임시 추론
- 실패한 후보
- 중간 생각
=&amp;gt; 다음 API 요청에는 넣지 않음

[Compaction]
- context가 커졌을 때만 수행
- 오래된 기록은 요약
- 최근 작업 tail은 유지
- compaction 이후 다시 append-only로 진행
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 DeepSeek의 prefix cache를 활용하기 좋은 구조가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 영상 제작 에이전트나 웹소설 제작 에이전트에도 이 방식은 잘 맞는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 웹소설 기반 영상 제작 파이프라인을 만든다고 하자.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;고정 Prefix:
세계관 규칙, 캐릭터 설정, 영상 스타일 규칙, 금지사항

Append-only Log:
회차별 줄거리, 장면별 프롬프트, 수정 피드백, 생성 결과

Volatile Scratch:
장면 후보, 임시 아이디어, 실패한 프롬프트, 내부 판단

Compaction:
완료된 회차는 요약하고, 현재 제작 중인 회차와 최근 피드백은 유지
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 단순히 비용 절감만을 위한 것이 아니다.&lt;br /&gt;작업의 일관성도 좋아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 설정, 세계관 규칙, 스타일 가이드가 안정적인 prefix에 남아 있기 때문에 에이전트가 매번 다른 방향으로 튀는 문제도 줄일 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론: Reasonix의 진짜 포인트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepSeek-Reasonix의 핵심은 &amp;ldquo;새로운 캐시 기술을 직접 구현했다&amp;rdquo;가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 정확히 말하면,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepSeek API가 제공하는 prefix caching이 잘 작동하도록 에이전트 세션 구조를 설계했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이가 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시는 모델 제공사가 제공한다.&lt;br /&gt;하지만 그 캐시를 얼마나 잘 먹게 만들지는 에이전트 설계자의 몫이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reasonix는 그 지점을 잘 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞부분을 고정하고, 뒤에만 쌓고, reasoning은 다시 보내지 않고, compaction은 드물게 하고, 모델별 세션을 분리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화려한 기능보다 이런 구조적 설계가 장시간 에이전트의 비용과 안정성을 좌우할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 DeepSeek 기반 에이전트를 만들거나, 코딩 에이전트&amp;middot;글쓰기 에이전트&amp;middot;영상 제작 에이전트를 설계한다면 Reasonix의 접근 방식은 참고할 만하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 결국 하나다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 비용 최적화는 &amp;ldquo;토큰을 덜 쓰는 것&amp;rdquo;만이 아니라,&lt;br /&gt;&amp;ldquo;반복되는 토큰이 캐시되도록 구조를 유지하는 것&amp;rdquo;이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1780456788480&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - esengine/DeepSeek-Reasonix: DeepSeek-native AI coding agent for your terminal. Engineered around prefix-cache stability&quot; data-og-description=&quot;DeepSeek-native AI coding agent for your terminal. Engineered around prefix-cache stability &amp;mdash; leave it running. - esengine/DeepSeek-Reasonix&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/esengine/deepseek-reasonix&quot; data-og-url=&quot;https://github.com/esengine/DeepSeek-Reasonix&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dio6wF/dJMb9cBPinI/ghXyHAm3Hv9Mawng1V1Nl1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/koMpc/dJMb9g5ikyu/1gzCKoJV4JrGLvk9kjoW8K/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://github.com/esengine/deepseek-reasonix&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/esengine/deepseek-reasonix&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dio6wF/dJMb9cBPinI/ghXyHAm3Hv9Mawng1V1Nl1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/koMpc/dJMb9g5ikyu/1gzCKoJV4JrGLvk9kjoW8K/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - esengine/DeepSeek-Reasonix: DeepSeek-native AI coding agent for your terminal. Engineered around prefix-cache stability&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;DeepSeek-native AI coding agent for your terminal. Engineered around prefix-cache stability &amp;mdash; leave it running. - esengine/DeepSeek-Reasonix&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1767</guid>
      <comments>https://javaexpert.tistory.com/1767#entry1767comment</comments>
      <pubDate>Wed, 3 Jun 2026 12:20:31 +0900</pubDate>
    </item>
    <item>
      <title>AI가 코드를 짜는 시대, 코드 리뷰는 어떻게 해야 할까?</title>
      <link>https://javaexpert.tistory.com/1766</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;원문&lt;/p&gt;
&lt;figure id=&quot;og_1780305169526&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;我是怎样使用 AI 来做 Code Review 的？ | Viking&quot; data-og-description=&quot;在 AI 生成代码时代，我现在越来越发现 Review 的重要性，因为 AI 代码产出太快了，假如长时间不干预，很快整个系统有可能都不受控制，质量严重下降，变成一个黑盒，我实践了一个叫 Review Forg&quot; data-og-host=&quot;vikingz.me&quot; data-og-source-url=&quot;https://vikingz.me/ai-code-review/&quot; data-og-url=&quot;https://vikingz.me/ai-code-review/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dLAXNm/dJMb8YXSNcm/7HUZMgG0PleYrs6F4rembK/img.jpg?width=1200&amp;amp;height=800&amp;amp;face=0_0_1200_800,https://scrap.kakaocdn.net/dn/neC47/dJMb8YXSNcn/WcPsQM6dctp0d6dHtnEkT0/img.jpg?width=1200&amp;amp;height=800&amp;amp;face=0_0_1200_800,https://scrap.kakaocdn.net/dn/oDWDU/dJMb9g5h8ol/JVbHVmr7d2zxHGtLRG60HK/img.png?width=830&amp;amp;height=476&amp;amp;face=0_0_830_476&quot;&gt;&lt;a href=&quot;https://vikingz.me/ai-code-review/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vikingz.me/ai-code-review/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dLAXNm/dJMb8YXSNcm/7HUZMgG0PleYrs6F4rembK/img.jpg?width=1200&amp;amp;height=800&amp;amp;face=0_0_1200_800,https://scrap.kakaocdn.net/dn/neC47/dJMb8YXSNcn/WcPsQM6dctp0d6dHtnEkT0/img.jpg?width=1200&amp;amp;height=800&amp;amp;face=0_0_1200_800,https://scrap.kakaocdn.net/dn/oDWDU/dJMb9g5h8ol/JVbHVmr7d2zxHGtLRG60HK/img.png?width=830&amp;amp;height=476&amp;amp;face=0_0_830_476');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;我是怎样使用 AI 来做 Code Review 的？ | Viking&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;在 AI 生成代码时代，我现在越来越发现 Review 的重要性，因为 AI 代码产出太快了，假如长时间不干预，很快整个系统有可能都不受控制，质量严重下降，变成一个黑盒，我实践了一个叫 Review Forg&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vikingz.me&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI로 코딩을 하다 보면 가장 먼저 느끼는 것은 속도다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 하루 종일 붙잡고 있어야 했던 기능도, 이제는 AI에게 요구사항을 던지면 몇 분 안에 수백 줄의 코드가 나온다. 문제는 그다음이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 코드, 정말 믿고 머지해도 될까?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만들어낸 코드는 빠르다. 하지만 빠른 만큼 사람이 검토해야 할 양도 폭발적으로 늘어난다. 특히 한 번의 기능 개발로 여러 파일이 동시에 바뀌고, 프론트엔드&amp;middot;백엔드&amp;middot;DB 구조까지 함께 건드리는 프로젝트라면 더 그렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 개발자의 고민은 단순히 &amp;ldquo;AI로 코드를 어떻게 빨리 짤까?&amp;rdquo;가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오히려 더 중요한 질문은 이것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AI가 만든 코드를 어떻게 안전하게 리뷰할 것인가?&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI 코드 리뷰의 핵심은 &amp;lsquo;속도&amp;rsquo;가 아니라 &amp;lsquo;품질&amp;rsquo;이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문 작성자는 AI를 활용해 대부분의 코드를 작성하고 있지만, 동시에 코드 품질을 매우 중요하게 본다. 특히 자신이 운영하는 제품의 규모가 커지면서, AI가 한 번에 생성하는 코드 변경량도 점점 커졌다고 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 관점이 하나 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩은 반드시 빠르게만 써야 하는 도구가 아니다.&lt;br /&gt;오히려 AI를 활용해 &lt;b&gt;더 천천히, 더 꼼꼼하게, 더 안정적인 코드&lt;/b&gt;를 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 관점은 꽤 중요하다. 많은 사람이 AI 개발 도구를 &amp;ldquo;속도 향상 도구&amp;rdquo;로만 바라본다. 하지만 실제 제품을 운영하는 입장에서는 속도보다 중요한 것이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 &lt;b&gt;머지 이후의 안정성&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능은 빨리 만들 수 있어도, 그 기능이 결제 오류를 만들거나, 데이터 정합성을 깨거나, 사용자가 보는 화면을 망가뜨리면 의미가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 원문에서는 AI 코드 품질을 높이기 위한 두 가지 전략을 제시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째는 테스트, 특히 E2E 테스트다.&lt;br /&gt;둘째는 AI를 활용한 코드 리뷰 프로세스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서 핵심적으로 다루는 것은 두 번째, 즉 &lt;b&gt;AI 코드 리뷰 워크플로&lt;/b&gt;다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;하나의 AI에게만 리뷰를 맡기지 않는다&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;b&gt;여러 AI 모델에게 같은 코드를 독립적으로 리뷰하게 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작성자는 이를 위해 Review Forge라는 자체적인 코드 리뷰 프로세스를 만들었다. 복잡한 서비스라기보다는, 규칙과 파일 구조를 정해두고 AI 에이전트들이 각각 리뷰 보고서를 만들게 하는 방식이다. (&lt;a href=&quot;https://vikingz.me/ai-code-review/&quot;&gt;vikingz.me&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흐름은 대략 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;여러 AI 모델이 현재 변경 사항을 각각 리뷰한다.&lt;/li&gt;
&lt;li&gt;모델별 리뷰 결과를 개별 문서로 저장한다.&lt;/li&gt;
&lt;li&gt;AI가 여러 리뷰 문서를 종합해 하나의 요약 리포트를 만든다.&lt;/li&gt;
&lt;li&gt;사람이 직접 확인하면서 실제로 고칠 항목을 선택한다.&lt;/li&gt;
&lt;li&gt;한 모델이 수정한다.&lt;/li&gt;
&lt;li&gt;다른 모델이 수정 결과를 다시 검증한다.&lt;/li&gt;
&lt;li&gt;테스트를 돌리고 최종 판단은 사람이 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조에서 중요한 점은 &amp;ldquo;AI가 다 알아서 해준다&amp;rdquo;가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오히려 반대다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AI는 문제를 찾고, 사람은 판단한다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 여러 모델로 리뷰해야 할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 AI 모델로 코드 리뷰를 하면 분명 도움이 된다. 명백한 로직 오류나 빠진 예외 처리를 찾아낼 때도 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 한계도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 모델은 하나의 관점으로 코드를 본다. 어떤 모델은 타입 안정성을 잘 보고, 어떤 모델은 비즈니스 로직의 흐름을 잘 보고, 어떤 모델은 예외 케이스나 파일 간 부작용을 더 잘 잡아낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문 작성자는 여러 모델로 리뷰를 해보니 흥미로운 패턴을 발견했다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대략 60% 정도의 발견은 서로 겹치고, 나머지 40%는 모델마다 다르게 나온다는 것이다. 특히 중요한 것은, 어떤 문제는 한 모델만 발견하고 다른 모델은 전혀 언급하지 않는다는 점이다. (&lt;a href=&quot;https://vikingz.me/ai-code-review/&quot;&gt;vikingz.me&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 실무적으로 매우 유용한 기준이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여러 모델이 동시에 지적한 문제는 실제 문제일 가능성이 높다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이것이 무조건 참이라는 뜻은 아니다. 하지만 서로 다른 모델이 독립적으로 같은 문제를 지적했다면, 그 항목은 우선순위를 높게 두고 확인할 가치가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 한 모델만 지적한 문제는 버릴 필요는 없지만, 사람이 더 신중하게 검토해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 다중 모델 리뷰의 가치는 두 가지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 교차 검증이다.&lt;br /&gt;둘째, 리뷰 범위 확장이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 AI가 놓친 부분을 다른 AI가 볼 수 있다. 그리고 여러 AI가 동시에 지적한 문제는 사람의 판단 비용을 줄여준다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만든 리뷰 보고서를 하나씩 읽다 보면, 오히려 사람이 더 피곤해질 수 있다. 그래서 원문에서는 Synthesize 단계가 등장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 단계에서는 여러 모델이 만든 리뷰 보고서를 다시 AI에게 종합하게 한다. 그리고 중복으로 발견된 문제, 심각도가 높은 문제, 우선적으로 확인해야 할 문제를 정리해 하나의 체크리스트로 만든다. (&lt;a href=&quot;https://vikingz.me/ai-code-review/&quot;&gt;vikingz.me&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식이 좋은 이유는 명확하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람은 여러 보고서를 처음부터 끝까지 읽는 것이 아니라, 정리된 체크리스트를 보고 판단하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 이런 식이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 문제는 몇 개 모델이 지적했는가?&lt;/li&gt;
&lt;li&gt;심각도는 높은가?&lt;/li&gt;
&lt;li&gt;실제 사용자에게 영향을 주는가?&lt;/li&gt;
&lt;li&gt;수정 비용은 어느 정도인가?&lt;/li&gt;
&lt;li&gt;지금 반드시 고쳐야 하는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 리뷰의 결과물을 그대로 믿는 것이 아니라, 사람이 판단하기 좋은 형태로 재가공하는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 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;AI가 &amp;ldquo;high severity&amp;rdquo;라고 표시했다고 해서 반드시 고쳐야 하는 것은 아니다.&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;예를 들어 아주 좁은 엣지 케이스를 고치기 위해 100줄 이상의 코드를 바꿔야 한다면 어떨까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 문제가 실제 사용자에게 거의 발생하지 않고, 수정 과정에서 더 큰 리스크가 생긴다면 지금 당장 고치지 않는 것이 더 나은 선택일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문 작성자는 AI가 제시한 항목을 볼 때 두 가지 질문을 던진다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 이 문제가 실제 상황에서 버그를 만들 가능성이 있는가?&lt;br /&gt;둘째, 이 문제를 고치는 비용은 얼마인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기준은 실무에서 매우 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 문제를 찾는 데 강하다.&lt;br /&gt;하지만 무엇을 고칠지 결정하는 것은 다른 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 결정에는 제품 이해, 사용자 영향도, 기술 부채, 일정, 리스크 관리가 모두 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 최종 판단은 여전히 사람이 해야 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;고치는 AI와 검증하는 AI는 달라야 한다&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;b&gt;코드를 고치는 모델과 그 코드를 검증하는 모델을 분리한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문에서는 하나의 모델이 선택된 문제를 수정하고, 다른 모델이 그 수정 결과를 다시 리뷰하는 방식으로 진행한다. 이때 수정 계획 문서, 진행 상태 문서, 검증 문서가 함께 만들어진다. (&lt;a href=&quot;https://vikingz.me/ai-code-review/&quot;&gt;vikingz.me&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 사람의 코드 리뷰와 비슷하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 작성한 사람이 자기 코드를 직접 리뷰하면 놓치는 부분이 생긴다. 이는 능력의 문제가 아니라 사고의 관성 문제다. 자신이 왜 그렇게 짰는지 이미 알고 있기 때문에, 같은 전제를 반복해서 보게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI도 비슷하게 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정한 모델이 다시 자기 수정을 검증하면, 같은 논리 구조 안에서 판단할 가능성이 있다. 그래서 다른 모델에게 검증을 맡기는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 일종의 이중 안전장치다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정한 모델이 &amp;ldquo;고쳤다&amp;rdquo;고 말하는 것만으로 끝내지 않고, 다른 모델이 &amp;ldquo;정말 고쳐졌는지&amp;rdquo; 다시 확인한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이 방식의 진짜 가치는 불안을 줄이는 데 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩을 하다 보면 이상한 불안감이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 돌아가는 것처럼 보인다.&lt;br /&gt;테스트도 일부 통과한다.&lt;br /&gt;하지만 마음 한편에 찝찝함이 남는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;어딘가 깨진 부분이 있지 않을까?&amp;rdquo;&lt;br /&gt;&amp;ldquo;내가 놓친 사이드 이펙트가 있지 않을까?&amp;rdquo;&lt;br /&gt;&amp;ldquo;이대로 배포해도 괜찮을까?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문 작성자는 이 프로세스의 가장 큰 가치가 바로 이 불안을 줄여주는 데 있다고 말한다. (&lt;a href=&quot;https://vikingz.me/ai-code-review/&quot;&gt;vikingz.me&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 리뷰를 거쳤다고 해서 코드가 완벽해지는 것은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 적어도 어떤 문제를 확인했고, 어떤 문제는 고쳤고, 어떤 문제는 의도적으로 고치지 않았는지 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이는 크다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;막연히 불안한 상태에서 머지하는 것과, 검토한 리스크를 알고 머지하는 것은 완전히 다르다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI 코드 리뷰를 실무에 적용한다면&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 코드 리뷰에 활용하고 싶다면 다음 세 가지 원칙만 가져와도 충분하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 큰 변경에는 여러 AI 모델을 활용한다.&lt;br /&gt;작은 수정에는 하나의 모델만 써도 된다. 하지만 여러 파일, 여러 서비스, DB 변경이 함께 들어간 큰 기능이라면 다중 모델 리뷰가 도움이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, AI가 찾은 문제를 사람이 직접 선별한다.&lt;br /&gt;AI가 지적한 모든 문제를 고치려고 하면 오히려 프로젝트가 산으로 갈 수 있다. 실제 사용자 영향도와 수정 비용을 기준으로 판단해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 수정과 검증을 분리한다.&lt;br /&gt;한 모델이 고친 코드는 다른 모델에게 다시 확인하게 한다. 그리고 최종적으로 테스트를 돌린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 가지를 지키면 AI 코드 리뷰는 단순한 &amp;ldquo;자동 리뷰&amp;rdquo;가 아니라, 실무적인 품질 관리 프로세스가 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI 시대의 개발자는 더 빨리 짜는 사람이 아니라, 더 잘 판단하는 사람이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 코드를 빠르게 만든다.&lt;br /&gt;AI는 리뷰도 도와준다.&lt;br /&gt;AI는 수정도 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 무엇을 고칠지, 어디까지 고칠지, 어떤 리스크를 감수할지는 여전히 사람이 결정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 AI 시대의 개발자에게 더 중요해지는 능력은 단순 구현력이 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;판단력이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만든 수많은 코드와 리뷰 결과 속에서, 진짜 중요한 문제를 골라내는 능력.&lt;br /&gt;이론적으로 틀린 코드와 실제로 위험한 코드를 구분하는 능력.&lt;br /&gt;지금 고칠 문제와 나중에 미뤄도 되는 문제를 나누는 능력.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코드 리뷰의 본질은 &amp;ldquo;AI에게 맡기는 것&amp;rdquo;이 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오히려 AI를 여러 명의 리뷰어처럼 활용하되, 최종 의사결정권은 사람이 갖는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 AI 코딩이 더 일반화될수록, 코드 리뷰는 더 중요해질 가능성이 높다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 코드를 많이 만들수록, 사람은 더 많이 읽고, 더 잘 판단해야 하기 때문이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코드 리뷰를 잘 쓰는 핵심은 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 AI만 믿지 말고, 큰 변경에는 여러 모델로 리뷰한다.&lt;/li&gt;
&lt;li&gt;여러 모델이 공통으로 지적한 문제를 우선 확인한다.&lt;/li&gt;
&lt;li&gt;AI 리뷰 결과는 요약 체크리스트로 정리한다.&lt;/li&gt;
&lt;li&gt;사람이 실제 영향도와 수정 비용을 기준으로 고칠 항목을 선택한다.&lt;/li&gt;
&lt;li&gt;수정하는 모델과 검증하는 모델을 분리한다.&lt;/li&gt;
&lt;li&gt;마지막에는 반드시 테스트로 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 개발자의 일을 없애는 것이 아니라, 개발자의 판단을 더 많이 요구하게 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 좋은 AI 코드 리뷰 프로세스란, AI가 대신 결정하는 구조가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AI가 최대한 많이 발견하고, 사람이 가장 중요한 것을 선택하는 구조다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1766</guid>
      <comments>https://javaexpert.tistory.com/1766#entry1766comment</comments>
      <pubDate>Mon, 1 Jun 2026 18:13:03 +0900</pubDate>
    </item>
    <item>
      <title>SkillOpt: AI 에이전트의 스킬도 학습시킬 수 있을까?</title>
      <link>https://javaexpert.tistory.com/1765</link>
      <description>&lt;h1&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;AI 에이전트를 쓰다 보면 어느 순간 이런 생각이 듭니다.&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 에이전트가 같은 실수를 반복하지 않게 만들 수는 없을까?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 에이전트는 테스트를 돌리지 않고 작업을 끝냈다고 말할 때가 있습니다.&lt;br /&gt;문서 작성 에이전트는 중요한 제약 조건을 빠뜨릴 때가 있습니다.&lt;br /&gt;영상 프롬프트 작성 에이전트는 캐릭터 일관성, 카메라 동선, 시간 분할 같은 핵심 요소를 놓칠 때가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때 우리는 보통 지침을 추가합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;테스트를 실행하기 전에는 완료했다고 말하지 마라.
모르는 API는 추측하지 말고 확인하라.
함수 이름을 바꿀 때는 관련 참조를 모두 검색하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이런 지침을 계속 추가하다 보면 문제가 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서는 점점 길어집니다.&lt;br /&gt;중복되는 내용이 생깁니다.&lt;br /&gt;규칙끼리 충돌하기도 합니다.&lt;br /&gt;무엇보다 정말 성능이 좋아졌는지 확인하기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Microsoft가 공개한 &lt;b&gt;SkillOpt&lt;/b&gt;는 바로 이 문제를 다룹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt는 단순히 프롬프트를 잘 쓰는 도구가 아닙니다.&lt;br /&gt;AI 에이전트가 반복 작업을 수행할 때 참고하는 &lt;b&gt;스킬 문서(skill.md)&lt;/b&gt;를 실행 결과와 실패 로그를 바탕으로 반복 개선하는 프레임워크입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프롬프트가 아니라 스킬이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 SkillOpt를 보면 &amp;ldquo;프롬프트 최적화 도구인가?&amp;rdquo;라고 생각하기 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 정확히는 조금 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트는 보통 한 번의 요청을 잘 수행하기 위해 입력하는 지시문입니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;이 글을 브런치용 블로그 글로 정리해줘.
이 코드를 리팩터링해줘.
이 장면을 15초 영상 프롬프트로 만들어줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 스킬은 특정 종류의 작업을 반복적으로 잘 수행하기 위해 저장해 두는 작업 지침서에 가깝습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;코드를 수정할 때는 먼저 관련 파일 구조를 파악하라.
테스트를 실행하기 전에는 완료를 선언하지 마라.
영상 프롬프트를 작성할 때는 시간 분할, 카메라 움직임, 캐릭터 일관성을 반드시 포함하라.
한국어 초급자 설명에서는 어려운 한자어보다 쉬운 예문을 먼저 제시하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 이렇습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;프롬프트:
이번 한 번 이렇게 해줘.

스킬:
앞으로 이런 종류의 일을 할 때는 이렇게 해.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt가 다루는 것은 두 번째입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, SkillOpt는 AI 모델 자체를 학습시키는 것이 아니라,&lt;br /&gt;에이전트가 반복 작업에 사용하는 &lt;b&gt;스킬 문서&lt;/b&gt;를 학습시키는 시스템입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SkillOpt는 무엇을 하는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt의 기본 아이디어는 단순합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트에게 어떤 스킬 문서를 주고 여러 작업을 수행하게 합니다.&lt;br /&gt;그 결과를 보고 성공과 실패를 기록합니다.&lt;br /&gt;실패한 이유와 성공한 패턴을 분석합니다.&lt;br /&gt;그 분석을 바탕으로 스킬 문서를 수정합니다.&lt;br /&gt;그리고 수정된 스킬이 실제로 더 나은지 검증합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흐름으로 보면 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 현재 skill.md로 여러 작업을 수행한다.
2. 성공한 작업과 실패한 작업의 로그를 모은다.
3. 실패 원인과 성공 패턴을 분석한다.
4. skill.md 수정안을 만든다.
5. 검증 데이터에서 성능을 확인한다.
6. 성능이 좋아졌을 때만 새 skill을 채택한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 마지막 단계입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 &amp;ldquo;이렇게 고치면 좋을 것 같습니다&amp;rdquo;라고 제안한다고 해서 바로 반영하지 않습니다.&lt;br /&gt;검증 세트에서 실제로 결과가 좋아졌을 때만 새로운 스킬을 채택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점에서 SkillOpt는 단순한 자동 문서 수정기가 아닙니다.&lt;br /&gt;스킬 문서를 실험 가능한 대상으로 보고, 결과 기반으로 개선하는 프레임워크입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스킬을 학습시킨다는 말의 의미&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;스킬을 학습시킨다&amp;rdquo;는 말이 처음에는 조금 낯설 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 보통 학습이라고 하면 모델 학습을 떠올립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델의 파라미터를 바꾸고, 데이터를 넣고, 가중치를 업데이트하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 SkillOpt는 모델의 내부를 바꾸지 않습니다.&lt;br /&gt;모델은 그대로 둡니다.&lt;br /&gt;대신 모델이 작업할 때 참고하는 외부 지침 문서를 바꿉니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유하자면 이렇습니다.&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;모델 파인튜닝:
사람의 머리 자체를 다시 훈련시키는 것

SkillOpt:
사람이 참고하는 작업 매뉴얼을 계속 개선하는 것
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 개발 에이전트에게 처음에는 이런 스킬만 있었다고 해봅시다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;코드를 수정할 때는 관련 파일을 확인하고 테스트를 실행하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 실제 작업을 시켜보니 에이전트가 반복적으로 이런 실수를 합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;환경 변수 이름을 추측한다.
README의 오래된 명령어를 그대로 믿는다.
테스트 파일의 참조를 놓친다.
리팩터링 후 타입 체크를 실행하지 않는다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 SkillOpt는 이런 실패 패턴을 바탕으로 스킬 문서를 더 구체적으로 바꿀 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;환경 변수, CLI 옵션, 외부 API 이름은 추측하지 말고 실제 파일이나 공식 문서에서 확인하라.

함수나 타입 이름을 변경할 때는 직접 참조뿐 아니라 테스트, mock, fixture, barrel export, 동적 import, 문자열 참조까지 별도로 검색하라.

완료를 보고하기 전에 실행한 테스트 명령과 결과를 확인하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 보면 SkillOpt는 실패를 단순한 오류로 버리지 않습니다.&lt;br /&gt;실패를 스킬 개선의 재료로 사용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 스킬 최적화가 중요한가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트를 실제 업무에 쓰다 보면 중요한 것은 단순한 답변 능력이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복 작업에서 같은 실수를 줄이는 능력입니다.&lt;br /&gt;프로젝트별 규칙을 지키는 능력입니다.&lt;br /&gt;작업 전후의 검증 절차를 따르는 능력입니다.&lt;br /&gt;특정 분야의 노하우를 일관되게 적용하는 능력입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 능력은 매번 프롬프트로 길게 설명하기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 에이전트에게는 스킬이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 개발 에이전트의 스킬은 이렇게 될 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;작업 전에 코드 구조를 파악하라.
변경 전에 관련 참조를 모두 검색하라.
수정 후 타입 체크와 테스트를 실행하라.
검증하지 않은 내용은 완료했다고 말하지 마라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상 제작 에이전트의 스킬은 이렇게 될 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;15초 영상은 시간대별로 나누어 작성하라.
각 구간마다 카메라 움직임을 명시하라.
캐릭터의 얼굴, 의상, 소품 일관성을 유지하라.
텍스트, 로고, 워터마크가 나오지 않도록 지시하라.
립싱크가 필요한 경우 오디오 타이밍과 입 모양을 명확히 적어라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어 교육 콘텐츠 에이전트의 스킬은 이렇게 될 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;초급자 설명에서는 쉬운 단어를 먼저 사용하라.
문법 용어보다 상황 예시를 먼저 제시하라.
예문은 짧고 자연스럽게 만들라.
비슷한 표현과의 차이를 함께 설명하라.
학습자가 자주 하는 실수를 따로 알려주라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 스킬은 한 번 잘 써두면 반복적으로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 처음부터 완벽한 스킬을 만들기는 어렵습니다.&lt;br /&gt;실제로 작업을 시켜보고, 어디서 실패하는지 봐야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt는 이 과정을 자동화하려는 시도입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SkillOpt의 핵심 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt의 구조는 크게 네 단계로 볼 수 있습니다.&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;br /&gt;이 과정에서 성공한 작업과 실패한 작업의 기록이 쌓입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 반성입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 왜 실패했는지 분석합니다.&lt;br /&gt;어떤 지침이 부족했는지, 어떤 규칙이 모호했는지, 어떤 절차가 빠졌는지 찾아냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째는 수정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석 결과를 바탕으로 skill.md에 추가, 삭제, 교체 같은 수정안을 만듭니다.&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;br /&gt;기존 스킬보다 결과가 좋아졌을 때만 새 스킬을 채택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조가 중요한 이유는 간단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스킬 문서를 무조건 길게 만든다고 좋은 것이 아니기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지침이 너무 많아지면 오히려 중요한 규칙이 묻힐 수 있습니다.&lt;br /&gt;서로 충돌하는 규칙이 생길 수도 있습니다.&lt;br /&gt;에이전트가 무엇을 우선해야 하는지 헷갈릴 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 SkillOpt는 단순히 스킬을 추가하는 것이 아니라,&lt;br /&gt;검증을 통해 실제로 나아졌는지 확인합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 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;erlang&quot;&gt;&lt;code&gt;사람이 지침을 작성한다.
AI가 작업한다.
실수가 발생한다.
사람이 지침을 고친다.
다시 사용한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이 방식도 중요합니다.&lt;br /&gt;처음 스킬을 설계하는 데는 사람의 도메인 지식이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 사람이 직접 고치는 방식은 한계가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 규칙이 실제로 효과가 있었는지 알기 어렵습니다.&lt;br /&gt;어떤 규칙이 오히려 성능을 떨어뜨렸는지 확인하기 어렵습니다.&lt;br /&gt;실패 로그가 많아질수록 사람이 모두 분석하기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt는 이 과정을 더 체계적으로 만듭니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;초기 스킬을 만든다.
작업 데이터셋에서 실행한다.
실패와 성공을 기록한다.
수정안을 만든다.
검증한다.
좋아진 스킬만 채택한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, SkillOpt는 스킬 문서를 감으로 고치는 것이 아니라,&lt;br /&gt;실험과 검증을 통해 개선하려는 접근입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;어디에 활용할 수 있을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt는 반복 작업을 수행하는 AI 에이전트에 잘 맞습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 개발 에이전트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 현실적인 활용처는 개발입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex, Claude Code, Cursor, Windsurf 같은 도구를 사용할 때 프로젝트별 작업 규칙을 둡니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 규칙입니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;테스트를 실행하라.
타입 오류를 만들지 마라.
기존 구조를 먼저 파악하라.
변경 범위를 최소화하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 실제 프로젝트에서는 더 구체적인 규칙이 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;Next.js 프론트엔드와 Laravel 백엔드의 env 파일을 따로 확인하라.
API 응답 타입을 바꿀 때는 프론트엔드 사용처까지 검색하라.
함수 이름을 바꿀 때는 테스트, mock, fixture, re-export 파일까지 확인하라.
완료 전에 typecheck, lint, test 결과를 확인하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 작업은 평가가 비교적 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트가 통과했는지, 타입 체크가 통과했는지, 린트가 통과했는지 확인할 수 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 SkillOpt와 궁합이 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. AI 영상 프롬프트 에이전트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 제작에서도 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 Seedance, Kling, Runway 같은 영상 생성 모델용 프롬프트를 작성하는 에이전트가 있다고 해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 영상 프롬프트에는 여러 요소가 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;시간 분할
카메라 움직임
캐릭터 일관성
의상과 소품 유지
감정 변화
조명과 색감
참고 이미지 사용 방식
금지 요소
립싱크 조건
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 에이전트가 매번 모든 요소를 잘 챙기기는 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 스킬 문서에 영상 프롬프트 작성 원칙을 담아두고,&lt;br /&gt;결과를 평가하면서 스킬을 개선할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 평가 기준은 다음처럼 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;15초 구간이 시간대별로 나뉘어 있는가?
카메라 움직임이 구체적인가?
캐릭터 일관성 지시가 있는가?
참고 이미지 사용 방식이 명확한가?
텍스트, 로고, 워터마크 금지 조건이 있는가?
립싱크 조건이 필요한 경우 포함되어 있는가?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 프롬프트의 구조 품질을 평가하고,&lt;br /&gt;나중에는 실제 생성된 영상까지 평가하는 방식으로 확장할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 한국어 교육 콘텐츠 에이전트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어 교육 콘텐츠에도 적용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 초급자에게 어휘나 문법을 설명하는 에이전트가 있다고 해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 설명에는 이런 조건이 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;쉬운 단어 사용
짧은 문장
자연스러운 예문
비슷한 표현과의 차이
자주 하는 실수
수업 활동 아이디어
그림으로 보여줄 수 있는 상황
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 에이전트가 너무 어렵게 설명할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;나이가 들다&amp;rdquo;를 설명하면서&lt;br /&gt;초급자에게 어려운 추상적 표현을 많이 쓰면 수업 자료로 쓰기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 실패가 반복되면 스킬 문서에 다음과 같은 규칙을 추가할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;초급자 설명에서는 어려운 한자어를 피하고 쉬운 일상어를 사용하라.

뜻을 먼저 설명한 뒤 짧은 예문을 제시하라.

비슷한 표현이 있으면 차이를 간단한 표로 정리하라.

학습자가 실제 대화에서 사용할 수 있는 문장을 우선하라.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 한국어 교육용 콘텐츠 생성 에이전트의 품질을 더 안정적으로 만들 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SkillOpt의 장점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt의 장점은 분명합니다.&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;br /&gt;그래서 최종 결과물은 개선된 skill.md입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, 실패를 자산으로 만듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 실패한 기록을 그냥 버리지 않고,&lt;br /&gt;다음 스킬 개선의 재료로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, 검증 기반으로 개선합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 스킬이 실제로 더 나은 결과를 냈을 때만 채택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷째, 반복 작업에 강합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번만 쓰는 요청보다,&lt;br /&gt;계속 반복되는 작업에서 더 큰 효과를 기대할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발, 문서화, 영상 프롬프트 제작, 교육 콘텐츠 생성처럼&lt;br /&gt;작업 패턴이 반복되는 분야에 특히 잘 맞습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;하지만 바로 마법처럼 쓸 수 있는 도구는 아니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt를 볼 때 주의할 점도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 도구는 설치만 하면 모든 스킬이 자동으로 좋아지는 완성형 서비스가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 쓰려면 몇 가지가 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;학습용 작업 데이터셋
검증용 작업 데이터셋
테스트용 작업 데이터셋
작업 성공 여부를 판단하는 평가 기준
에이전트를 실행할 수 있는 환경
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 것은 평가 기준입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 에이전트라면 테스트 통과, 타입 체크 통과, 린트 통과 같은 기준을 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 영상 프롬프트나 교육 콘텐츠처럼 주관적인 결과물이 많은 영역에서는 평가 기준을 더 정교하게 설계해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 영상 프롬프트의 경우 &amp;ldquo;좋은 프롬프트&amp;rdquo;를 어떻게 정의할 것인지 정해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;시간 분할이 있는가?
카메라 움직임이 구체적인가?
캐릭터 일관성을 지시하는가?
생성 모델의 입력 제한을 반영하는가?
금지 요소를 명확히 적었는가?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 구조적 기준부터 시작하면 현실적으로 실험할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;중요한 것은 스킬을 자산으로 보는 관점이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt를 보면서 가장 흥미로웠던 부분은&lt;br /&gt;스킬을 단순한 문서가 아니라 개선 가능한 자산으로 본다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트를 쓰면서 생기는 실패는 보통 대화창 안에서 사라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 에이전트가 실수합니다.&lt;br /&gt;사람이 지적합니다.&lt;br /&gt;다음 작업에서는 또 비슷한 실수를 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 일이 반복됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt식 접근은 다릅니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;실패 경험
&amp;rarr; 원인 분석
&amp;rarr; 스킬 수정
&amp;rarr; 검증
&amp;rarr; 개선된 skill.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패가 사라지는 것이 아니라 축적됩니다.&lt;br /&gt;그리고 축적된 실패는 다음 작업을 더 잘하게 만드는 스킬로 바뀝니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 관점이 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 AI 에이전트를 잘 쓰는 사람은 단순히 질문을 잘하는 사람이 아닐 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신의 작업 방식, 실패 패턴, 검증 기준을 스킬로 정리하고,&lt;br /&gt;그 스킬을 계속 개선하는 사람이 더 강력한 에이전트를 만들 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt는 프롬프트를 학습시키는 도구라기보다&lt;br /&gt;AI 에이전트의 &lt;b&gt;스킬을 학습시키는 프레임워크&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 스킬은 단순한 요청문이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 특정 작업을 반복적으로 수행할 때 참고하는&lt;br /&gt;작업 절차, 판단 기준, 주의사항, 도메인 노하우를 담은 문서입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt는 이 스킬 문서를 실행 결과와 실패 로그를 바탕으로 개선합니다.&lt;br /&gt;그리고 검증 세트에서 실제로 좋아졌을 때만 새로운 스킬을 채택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄로 정리하면 이렇습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;SkillOpt는 AI 모델을 학습시키는 것이 아니라,
AI 에이전트가 사용하는 작업 스킬을 학습시키는 시스템이다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델의 성능도 중요합니다.&lt;br /&gt;하지만 앞으로는 모델을 어떻게 쓰게 할 것인가도 중요해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 스킬을 줄 것인가.&lt;br /&gt;어떤 실패를 기록할 것인가.&lt;br /&gt;그 실패를 어떻게 다음 작업에 반영할 것인가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SkillOpt는 이 질문에 대한 흥미로운 답을 보여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트 시대에는&lt;br /&gt;좋은 프롬프트를 쓰는 것보다&lt;br /&gt;좋은 스킬을 만들고, 그 스킬을 계속 개선하는 능력이 더 중요해질지도 모릅니다.&lt;/p&gt;
&lt;figure id=&quot;og_1780044577570&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - microsoft/SkillOpt: SkillOpt is a text-space optimizer that trains reusable natural-language skills for frozen LLM agen&quot; data-og-description=&quot;SkillOpt is a text-space optimizer that trains reusable natural-language skills for frozen LLM agents through trajectory-driven edits, validation-gated updates, and deployable best_skill.md artifac...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/SkillOpt&quot; data-og-url=&quot;https://github.com/microsoft/SkillOpt&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/SkillOpt&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/SkillOpt&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - microsoft/SkillOpt: SkillOpt is a text-space optimizer that trains reusable natural-language skills for frozen LLM agen&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SkillOpt is a text-space optimizer that trains reusable natural-language skills for frozen LLM agents through trajectory-driven edits, validation-gated updates, and deployable best_skill.md artifac...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1765</guid>
      <comments>https://javaexpert.tistory.com/1765#entry1765comment</comments>
      <pubDate>Fri, 29 May 2026 17:49:46 +0900</pubDate>
    </item>
    <item>
      <title>양자컴퓨터 시대, 블록체인은 안전할까?</title>
      <link>https://javaexpert.tistory.com/1764</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QveDZ/dJMcacpLDSf/tULsY4lf7FsQzYWHeECWQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QveDZ/dJMcacpLDSf/tULsY4lf7FsQzYWHeECWQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QveDZ/dJMcacpLDSf/tULsY4lf7FsQzYWHeECWQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQveDZ%2FdJMcacpLDSf%2FtULsY4lf7FsQzYWHeECWQ0%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;1536&quot; height=&quot;1024&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인은 디지털 지갑의 주인이 누구인지 확인하기 위해 &lt;b&gt;암호 기술&lt;/b&gt;을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면, 블록체인 지갑에는 두 가지 열쇠가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개인키&lt;/b&gt;는 나만 아는 비밀 열쇠입니다.&lt;br /&gt;&lt;b&gt;공개키&lt;/b&gt;는 다른 사람들이 확인할 수 있는 공개된 열쇠입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 코인을 보내려면 개인키로 &amp;ldquo;이 거래는 내가 허락한 것입니다&amp;rdquo;라는 &lt;b&gt;서명&lt;/b&gt;을 만듭니다.&lt;br /&gt;네트워크는 공개키로 그 서명이 진짜인지 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지는 이 방식이 매우 안전하다고 여겨졌습니다.&lt;br /&gt;하지만 미래에 강력한 &lt;b&gt;양자컴퓨터&lt;/b&gt;가 등장하면 문제가 생길 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;양자컴퓨터가 왜 문제일까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 많은 블록체인은 ECDSA라는 서명 방식을 사용합니다.&lt;br /&gt;이 방식은 일반 컴퓨터로는 개인키를 찾아내기 거의 불가능하다는 전제 위에 만들어졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 충분히 강력한 양자컴퓨터는 &lt;b&gt;쇼어 알고리즘&lt;/b&gt;이라는 방법으로 공개키에서 개인키를 찾아낼 가능성이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 비유하면 이렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금의 암호는 아주 복잡한 자물쇠입니다.&lt;br /&gt;일반 컴퓨터는 열쇠를 하나씩 맞춰 봐야 해서 시간이 너무 오래 걸립니다.&lt;br /&gt;하지만 미래의 양자컴퓨터는 자물쇠의 숨은 규칙을 찾아 훨씬 빠르게 열쇠를 알아낼 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;공개키가 드러나면 더 위험해진다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인에서 거래를 한 번 보내면 공개키 정보가 드러나거나 복원될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 공개키가 보인다고 해서 바로 위험한 것은 아닙니다.&lt;br /&gt;하지만 미래에 양자컴퓨터가 충분히 강력해지면, 공개키를 보고 개인키를 계산하려는 공격이 가능해질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 오래 사용한 지갑, 큰 금액을 보관한 지갑, 이미 여러 번 거래한 지갑은 미래의 양자 위협에서 더 조심해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래서 필요한 것이 양자 후 암호학&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;양자 후 암호학&lt;/b&gt;, 영어로는 &lt;b&gt;PQC(Post-Quantum Cryptography)&lt;/b&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말은 양자컴퓨터 안에서 쓰는 암호라는 뜻이 아닙니다.&lt;br /&gt;정확히는 &lt;b&gt;양자컴퓨터가 공격해도 쉽게 깨지지 않도록 설계한 새로운 암호 기술&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 미래의 강력한 양자컴퓨터에 대비하기 위한 새로운 디지털 자물쇠입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;대표적인 양자 후 서명 기술&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 많이 이야기되는 양자 후 서명 방식에는 다음과 같은 것들이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ML-DSA&lt;/b&gt;는 NIST가 표준으로 확정한 대표적인 양자 후 디지털 서명 방식입니다.&lt;br /&gt;보안 수준에 따라 ML-DSA-44, ML-DSA-65, ML-DSA-87 같은 종류가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SLH-DSA&lt;/b&gt;도 NIST가 표준으로 확정한 서명 방식입니다.&lt;br /&gt;공개키는 작지만 서명 크기가 매우 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Falcon&lt;/b&gt;은 서명 크기가 비교적 작은 양자 후 서명 방식입니다.&lt;br /&gt;다만 Falcon 기반의 FN-DSA 표준은 아직 최종 확정 단계는 아닙니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제는 서명 크기다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 블록체인에서 많이 쓰는 ECDSA 서명은 약 &lt;b&gt;65바이트&lt;/b&gt; 정도입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 양자 후 서명은 훨씬 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECDSA 서명은 약 65바이트입니다.&lt;br /&gt;Falcon-512 서명은 약 666바이트입니다.&lt;br /&gt;ML-DSA-44 서명은 약 2,420바이트입니다.&lt;br /&gt;ML-DSA-87 서명은 약 4,627바이트입니다.&lt;br /&gt;SLH-DSA-128s 서명은 약 7,856바이트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면, 기존에는 작은 종이에 도장을 찍는 느낌이었다면, 양자 후 서명은 훨씬 큰 서류를 함께 붙여야 하는 느낌입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 크기가 중요할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인은 많은 사람이 같은 장부를 복사해서 가지고 있는 시스템입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거래 하나하나의 크기가 커지면 다음 문제가 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거래를 전파하는 데 더 많은 네트워크가 필요합니다.&lt;br /&gt;블록 하나에 담을 수 있는 거래 수가 줄어듭니다.&lt;br /&gt;노드가 저장해야 할 데이터가 늘어납니다.&lt;br /&gt;검증 과정도 더 무거워질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 양자 후 암호를 블록체인에 적용할 때는 단순히 &amp;ldquo;서명 알고리즘만 바꾸면 된다&amp;rdquo;라고 말하기 어렵습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;블록체인은 어떻게 바뀌어야 할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미래의 블록체인은 두 가지를 함께 고민해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 양자컴퓨터에도 안전한 서명 방식이 필요합니다.&lt;br /&gt;둘째, 커진 서명 데이터를 어떻게 효율적으로 처리할지 설계해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 거래를 검증할 때는 큰 서명을 확인하되, 블록체인 장부에는 그 결과를 더 작고 간단한 형태로 남기는 방식도 생각할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 질문은 이것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;서명이 이미 검증되었다면, 블록체인은 큰 서명 원본을 영원히 저장해야 할까?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 질문이 앞으로의 블록체인 설계에서 매우 중요해질 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;지금 당장 모든 블록체인이 위험한가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 공개적으로 알려진 양자컴퓨터가 비트코인이나 이더리움 같은 블록체인의 서명 체계를 실제로 깨고 있다는 증거는 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 암호 기술의 전환은 하루아침에 끝나지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지갑을 바꿔야 할 수 있습니다.&lt;br /&gt;거래 형식을 바꿔야 할 수 있습니다.&lt;br /&gt;노드와 검증 규칙을 업데이트해야 할 수 있습니다.&lt;br /&gt;사용자 자산을 새 주소로 옮기는 과정도 필요할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 공격이 실제로 가능해진 뒤에 준비하면 늦을 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양자컴퓨터는 미래에 기존 공개키 암호를 위협할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인은 거래 서명에 공개키 암호를 많이 사용하기 때문에 이 문제와 직접 연결됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양자 후 암호학은 이런 미래 공격에 대비하기 위한 새로운 암호 기술입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 양자 후 서명은 기존 서명보다 훨씬 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 블록체인은 단순히 암호 알고리즘만 바꾸는 것이 아니라, 거래 구조, 저장 구조, 검증 구조까지 함께 바꿔야 할 수 있습니다.&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;</description>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1764</guid>
      <comments>https://javaexpert.tistory.com/1764#entry1764comment</comments>
      <pubDate>Fri, 29 May 2026 10:43:02 +0900</pubDate>
    </item>
    <item>
      <title>Seedance 2.0 영상 프롬프트 작성 가이드</title>
      <link>https://javaexpert.tistory.com/1763</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 역할 개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0은 텍스트, 이미지, 영상, 오디오를 함께 활용해 짧은 AI 영상을 생성하는 멀티모달 영상 생성 모델이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 작성의 핵심은 단순히 &amp;ldquo;멋진 영상 만들어줘&amp;rdquo;가 아니라, 다음 요소를 명확하게 지시하는 것이다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;무엇을 보여줄지
어떤 참고 자료를 사용할지
카메라는 어떻게 움직일지
몇 초에 어떤 일이 일어날지
어떤 분위기와 사운드를 넣을지
무엇을 피해야 하는지
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;2. 입력 제한&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0에서 사용할 수 있는 입력 자료 제한은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 유형제한형식최대 크기&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;이미지&lt;/td&gt;
&lt;td&gt;최대 9장&lt;/td&gt;
&lt;td&gt;jpeg, png, webp, bmp, tiff, gif&lt;/td&gt;
&lt;td&gt;각 30MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영상&lt;/td&gt;
&lt;td&gt;최대 3개&lt;/td&gt;
&lt;td&gt;mp4, mov&lt;/td&gt;
&lt;td&gt;각 50MB, 길이 2&amp;ndash;15초&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;오디오&lt;/td&gt;
&lt;td&gt;최대 3개&lt;/td&gt;
&lt;td&gt;mp3, wav&lt;/td&gt;
&lt;td&gt;총 길이 15초 이하&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;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;총 파일 수&lt;/td&gt;
&lt;td&gt;최대 12개&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;b&gt;4초~15초&lt;/b&gt; 범위에서 선택할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은 &lt;b&gt;업로드 이미지나 영상에 실사 사람 얼굴이 있으면 플랫폼 정책상 차단될 수 있다&lt;/b&gt;는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;3. 가장 중요한 문법: @ 레퍼런스 시스템&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0에서는 업로드한 자료를 @Image1, @Video1, @Audio1처럼 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 단순히 &amp;ldquo;참고해줘&amp;rdquo;라고 쓰면 약하다는 것이다.&lt;br /&gt;반드시 &lt;b&gt;무엇을 참고할지 역할을 지정&lt;/b&gt;해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 예시&lt;/h2&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the first frame
@Image2 as the last frame
@Image1's character as the subject
scene references @Image3
reference @Video1's camera movement
reference @Video1's action choreography
BGM references @Audio1
sound effects reference @Video2's audio
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋은 예시&lt;/h2&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1's character as the main subject.
@Image2 as the first frame.
@Image3 as the last frame.
Reference @Video1's camera movement and action choreography.
BGM references @Audio1.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;나쁜 예시&lt;/h2&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;Reference @Video1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게만 쓰면 카메라를 참고하라는 건지, 동작을 참고하라는 건지, 효과를 참고하라는 건지 불명확하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;4. Seedance 프롬프트 기본 구조&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트는 보통 아래 순서로 구성하면 된다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 주인공 / 피사체 설정
2. 장소 / 배경 설정
3. 행동 / 움직임 설명
4. 카메라 움직임
5. 시간대별 연출
6. 전환 / 효과
7. 사운드 / 음악 / 효과음
8. 스타일 / 분위기
9. 금지 사항
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 공식&lt;/h2&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;[Subject / Character Setup]
+ [Scene / Environment]
+ [Action / Motion]
+ [Camera Movement]
+ [Timing Breakdown]
+ [Transitions / Effects]
+ [Audio / Sound Design]
+ [Style / Mood]
+ [Constraints]
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;5. 10초 이상 영상은 시간 분할이 좋다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10초 이상 영상은 한 문단으로 길게 쓰는 것보다, 시간 구간을 나누는 방식이 더 안정적이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;15초 구조 예시&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;0&amp;ndash;3s: 시작 상태. 주인공이 장소에 들어오고 카메라는 천천히 push in.
3&amp;ndash;6s: 준비 동작. 주인공이 주변을 살피며 긴장감이 올라감.
6&amp;ndash;10s: 핵심 사건. 갑자기 빛이 터지고 대상이 움직이기 시작함.
10&amp;ndash;13s: 반응. 주인공이 놀라 뒤로 물러나며 카메라는 흔들림 없이 따라감.
13&amp;ndash;15s: 안정된 끝 상태. 장면이 멈추고 다음 장면으로 이어질 수 있는 구도.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 네가 자주 쓰는 &lt;b&gt;15초 AI 영상 구조&lt;/b&gt;와 잘 맞는다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;시작 상태 &amp;rarr; 준비/접근 &amp;rarr; 핵심 사건 &amp;rarr; 결과/반응 &amp;rarr; 안정된 끝 상태
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;6. 카메라 표현 정리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 프롬프트에서는 카메라 지시가 매우 중요하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 카메라 움직임&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표현의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;slow push in&lt;/td&gt;
&lt;td&gt;카메라가 천천히 피사체 쪽으로 접근&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pull back&lt;/td&gt;
&lt;td&gt;카메라가 뒤로 빠짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pan left / pan right&lt;/td&gt;
&lt;td&gt;좌우로 회전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tilt up / tilt down&lt;/td&gt;
&lt;td&gt;위아래로 회전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tracking shot&lt;/td&gt;
&lt;td&gt;피사체를 따라가는 카메라&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;orbit shot&lt;/td&gt;
&lt;td&gt;피사체 주변을 도는 카메라&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;one-take / oner&lt;/td&gt;
&lt;td&gt;컷 없이 이어지는 롱테이크&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;고급 카메라 표현&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표현의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hitchcock zoom / dolly zoom&lt;/td&gt;
&lt;td&gt;배경이 왜곡되며 압박감이 생기는 줌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fisheye lens&lt;/td&gt;
&lt;td&gt;초광각 왜곡 렌즈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;low angle&lt;/td&gt;
&lt;td&gt;아래에서 올려다봄&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high angle&lt;/td&gt;
&lt;td&gt;위에서 내려다봄&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bird&amp;rsquo;s-eye view&lt;/td&gt;
&lt;td&gt;완전 탑뷰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;first-person POV&lt;/td&gt;
&lt;td&gt;1인칭 시점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;whip pan&lt;/td&gt;
&lt;td&gt;빠른 좌우 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;crane shot&lt;/td&gt;
&lt;td&gt;위아래로 크게 이동하는 카메라&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;샷 크기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표현의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;extreme close-up&lt;/td&gt;
&lt;td&gt;눈, 입, 손 등 아주 가까운 디테일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;close-up&lt;/td&gt;
&lt;td&gt;얼굴 중심&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium close-up&lt;/td&gt;
&lt;td&gt;가슴 위&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium shot&lt;/td&gt;
&lt;td&gt;허리 위&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;full shot&lt;/td&gt;
&lt;td&gt;전신&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wide shot&lt;/td&gt;
&lt;td&gt;배경이 넓게 보이는 샷&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;establishing shot&lt;/td&gt;
&lt;td&gt;장소를 보여주는 도입 샷&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;7. 목적별 프롬프트 패턴&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;A. 캐릭터 일관성 유지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터를 유지하려면 이미지 레퍼런스를 명확히 지정한다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;@Image1's character as the main subject.
Keep the same face shape, hairstyle, outfit, body proportions, and overall identity throughout the video.
No random outfit changes, no face morphing, no extra characters.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, Seedance 정책상 &lt;b&gt;실사 사람 얼굴 업로드는 차단될 수 있으므로&lt;/b&gt;, 캐릭터 시트나 비실사 스타일 레퍼런스를 쓰는 편이 안전하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;B. 카메라 움직임 복제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 영상의 카메라 워크를 따라가고 싶을 때:&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;Reference @Video1's camera movement only.
Do not copy the character or background from @Video1.
Apply the same camera rhythm, push-in speed, orbit timing, and shot transition style to @Image1's character in @Image2's environment.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 camera movement only처럼 범위를 좁히는 것이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C. 효과 / 전환 복제&lt;/h2&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Completely reference @Video1's visual effects and transitions.
Replace the original subject with @Image1's character.
Keep the same timing, light burst, motion blur, transition rhythm, and final reveal structure.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;D. 영상 연장&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 영상을 뒤로 이어 만들 때:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Extend @Video1 by 15 seconds.

0&amp;ndash;5s: Continue from the final frame of @Video1. The camera slowly pushes forward while the light shifts across the scene.
5&amp;ndash;10s: The subject moves deeper into the environment. Add subtle wind, footsteps, and ambient sound.
10&amp;ndash;15s: The camera settles into a stable ending frame, ready for the next scene.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞부분을 새로 붙이고 싶으면:&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;Extend backward 10 seconds.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;E. 음악 비트 매칭&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음악이나 영상 리듬에 맞춰 컷을 바꾸고 싶을 때:&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Reference @Audio1's rhythm and beat structure.
Cut timing, camera movement, lighting pulses, and character motion should match the beat.
Use stronger motion on downbeats and smoother transitions during quieter sections.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상 리듬을 참고할 경우:&lt;/p&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;Reference @Video1's editing rhythm and beat-synced transitions.
Do not copy the original characters or background.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;F. 대사 / 연기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대사를 넣을 때는 캐릭터, 감정, 톤을 명확히 적는다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;Character A, trembling but angry, says: &quot;What are you hiding from me?&quot;
Character B, breathless and desperate, replies: &quot;I was trying to protect you.&quot;

Voice tone: emotional, natural, cinematic Korean drama style.
Lip movement should match the spoken dialogue timing as closely as possible.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, AI 영상에서 한국어 립싱크는 모델과 플랫폼에 따라 결과가 달라질 수 있다. 그래서 대사는 짧고 명확하게 쓰는 편이 좋다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;G. 원테이크 영상&lt;/h2&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;Create a continuous one-take tracking shot with no cuts.
The camera follows the subject from behind, moving through the alley, up the stairs, across the rooftop, and finally stopping at the city view.
Keep the motion smooth and physically plausible.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;H. 상품 광고&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;@Image1 as the hero product.
Create a 15-second cinematic product showcase.

0&amp;ndash;3s: Product appears in a clean studio environment, slowly rotating.
3&amp;ndash;7s: Close-up on texture, material, logo, and premium details.
7&amp;ndash;11s: Product is shown in a lifestyle usage scene.
11&amp;ndash;15s: Final hero shot with dramatic lighting and clean background.

Sound: soft whoosh transitions, subtle product interaction sounds, premium commercial-style BGM.
Style: high-end, polished, glossy, cinematic.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;I. 교육 / 과학 영상&lt;/h2&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;Create a 15-second educational medical CGI visualization.

0&amp;ndash;5s: Transparent blue human upper body. Camera slowly pushes into a clear blood vessel.
5&amp;ndash;10s: Symbolic particles enter the bloodstream and flow with the blood.
10&amp;ndash;15s: The vessel changes visually to show the concept clearly, ending with a clean before-and-after comparison.

Style: 4K medical CGI, semi-transparent visualization, clean educational tone.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;8. 스타일 강화 문구&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 끝에 붙이면 좋은 품질 보강 문구다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실사 / 영화풍&lt;/h2&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Photorealistic, cinematic quality, shallow depth of field, natural lighting, film grain, 24fps, realistic camera movement.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;애니메이션&lt;/h2&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;Anime style, clean linework, cinematic lighting, expressive motion, detailed background, smooth animation.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;판타지&lt;/h2&gt;
&lt;pre class=&quot;rsl&quot;&gt;&lt;code&gt;Epic fantasy atmosphere, volumetric light, magical particles, grand scale, cinematic worldbuilding.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;네온 도시&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;High saturation neon colors, wet asphalt reflections, cool-warm contrast, cyberpunk atmosphere, cinematic rain.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;브이로그 / POV&lt;/h2&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;First-person POV, handheld camera feeling, natural breathing, subtle walking motion, immersive travel vlog style.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;9. 자주 하는 실수&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 레퍼런스 역할이 불명확함&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나쁜 예:&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;Reference @Image1 and @Video1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 예:&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the main character reference.
@Video1 only for camera movement and transition rhythm.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 너무 많은 행동을 짧은 시간에 넣음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4초짜리 영상에 장소 이동, 전투, 대사, 변신, 폭발을 모두 넣으면 불안정해질 가능성이 높다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 방식:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;4&amp;ndash;5초: 하나의 핵심 행동
10&amp;ndash;15초: 시작, 전개, 핵심 사건, 반응, 끝 상태
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 카메라 지시가 충돌함&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나쁜 예:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Static camera, fast orbit shot, handheld tracking shot.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 충돌한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 예:&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;Static camera for the first 3 seconds, then slow push-in from 3&amp;ndash;8 seconds.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 사운드를 안 적음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance는 자동 사운드가 들어갈 수 있으므로, 원하는 소리와 원하지 않는 소리를 명확히 쓰는 게 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Sound: footsteps, wind, soft fabric movement, distant city ambience.
No background music, no narration, no subtitles.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;10. 실사용 프롬프트 템플릿&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;A. 15초 영상 기본 템플릿&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;Create a 15-second video.

@Image1 as the first frame.
@Image2 as the last frame.
@Image3 as the main character reference.
Scene style references @Image4.

0&amp;ndash;3s:
Start from @Image1. The character stands still in the scene, breathing naturally. The camera slowly pushes in.

3&amp;ndash;6s:
The character begins moving forward. Add subtle environmental motion such as wind, light flicker, or dust.

6&amp;ndash;10s:
The main event happens. The character reacts clearly, with one strong action only. Camera follows smoothly.

10&amp;ndash;13s:
The result of the action becomes visible. The camera slows down and stabilizes.

13&amp;ndash;15s:
End exactly on @Image2. Hold a stable final composition.

Camera:
Smooth cinematic tracking shot, no random shake, no sudden cuts unless specified.

Sound:
Natural ambience, footsteps, soft wind, subtle cinematic sound effects.

Style:
Cinematic quality, detailed lighting, realistic motion, coherent scene continuity.

Constraints:
Keep character identity consistent. Keep outfit consistent. No extra characters. No text, no subtitles, no logos, no watermarks. No face morphing. No extra limbs. No distorted hands.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;B. POV 판타지 여행 영상 템플릿&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;Create a 15-second first-person POV fantasy travel video.

@Image1 as the first frame.
@Image2 as the last frame.
Scene environment references @Image3.
Camera rhythm references @Video1 if available.

0&amp;ndash;3s:
Start from @Image1. First-person POV looking ahead. The viewer is walking slowly, with subtle breathing and natural handheld movement.

3&amp;ndash;6s:
The camera moves forward through the fantasy environment. Add realistic footsteps, fabric movement, and environmental ambience.

6&amp;ndash;10s:
A magical visual event appears in front of the viewer. Keep it elegant and physically readable, not chaotic.

10&amp;ndash;13s:
The viewer reacts with a slight step back or pause. Camera movement becomes slower and more stable.

13&amp;ndash;15s:
End exactly on @Image2, holding a clean final frame for video extension.

Sound:
Footsteps, breathing, wind, distant magical ambience. No background music unless requested.

Style:
Photorealistic fantasy travel, cinematic lighting, immersive POV, realistic scale, natural camera movement.

Constraints:
No subtitles, no UI, no logos, no watermarks, no extra random people, no unrealistic camera jumps.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C. 뮤직비디오 15초 템플릿&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;Create a 15-second cinematic music video shot.

@Image1 as the main character reference.
@Image2 as the scene/background reference.
@Audio1 as the music rhythm reference.

0&amp;ndash;3s:
The character stands in the scene as the music begins. Camera slowly pushes in.

3&amp;ndash;6s:
Character movement begins, matching the rhythm of @Audio1. Lighting subtly pulses with the beat.

6&amp;ndash;10s:
Main performance moment. The character performs one clear emotional action or dance movement. Camera follows smoothly.

10&amp;ndash;13s:
The motion resolves. The environment reacts to the music with light, wind, or particles.

13&amp;ndash;15s:
End on a strong cinematic hero frame.

Camera:
Beat-synced camera movement, smooth tracking, no random shake.

Sound:
BGM references @Audio1. Visual cuts and motion accents should match the beat.

Style:
Cinematic MV, high-end production, dramatic lighting, polished composition.

Constraints:
Keep character identity and outfit consistent. No subtitles, no logos, no watermarks, no extra limbs, no distorted face.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;11. Seedance 프롬프트 작성 순서&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance용 프롬프트를 만들 때는 이 순서로 생각하면 된다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 영상 유형 결정
   예: 광고, 뮤직비디오, POV, 드라마, 교육, 상품 소개

2. 길이 결정
   예: 5초, 10초, 15초

3. 업로드 자료 확인
   이미지 몇 장, 영상 몇 개, 오디오 몇 개

4. 각 자료의 역할 지정
   @Image1 = 첫 프레임
   @Image2 = 끝 프레임
   @Image3 = 캐릭터
   @Video1 = 카메라 움직임
   @Audio1 = 음악 리듬

5. 시간 구간 나누기
   0&amp;ndash;3s / 3&amp;ndash;6s / 6&amp;ndash;10s / 10&amp;ndash;15s

6. 카메라 지시 추가

7. 사운드 지시 추가

8. 스타일과 금지사항 추가
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;12. 핵심 요약&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0 프롬프트의 핵심은 이거다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;@레퍼런스는 반드시 역할을 정한다.
15초 영상은 시간 구간으로 나눈다.
한 구간에는 하나의 핵심 행동만 넣는다.
카메라 움직임을 명확히 쓴다.
사운드까지 지시한다.
마지막에 금지사항을 넣는다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 안정적인 기본 구조는 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the first frame.
@Image2 as the last frame.
@Image3 as the character reference.

Create a 15-second video.

0&amp;ndash;3s: 시작 상태
3&amp;ndash;6s: 접근 / 준비
6&amp;ndash;10s: 핵심 사건
10&amp;ndash;13s: 반응 / 결과
13&amp;ndash;15s: 안정된 끝 프레임

Camera:
...

Sound:
...

Style:
...

Constraints:
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조를 쓰면 Seedance 2.0에서 &lt;b&gt;시작 프레임 &amp;rarr; 움직임 &amp;rarr; 사건 &amp;rarr; 끝 프레임&lt;/b&gt;이 더 명확해지고, 장면 연결용 15초 영상 제작에도 쓰기 좋다.&lt;/p&gt;</description>
      <category>Seedance2</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1763</guid>
      <comments>https://javaexpert.tistory.com/1763#entry1763comment</comments>
      <pubDate>Mon, 25 May 2026 10:08:58 +0900</pubDate>
    </item>
    <item>
      <title>Seedance 2.0 프롬프트의 핵심: @ 레퍼런스 시스템 이해하기</title>
      <link>https://javaexpert.tistory.com/1762</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 제작에서 좋은 결과를 얻기 위해 가장 중요한 것은 &amp;ldquo;무엇을 만들 것인가&amp;rdquo;보다 &amp;ldquo;무엇을 어떻게 참고하게 할 것인가&amp;rdquo;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0은 텍스트만으로 영상을 만드는 도구가 아닙니다. 이미지, 영상, 오디오를 함께 활용해 더 구체적인 결과물을 만들 수 있는 멀티모달 영상 생성 도구입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 핵심이 되는 기능이 바로 &lt;b&gt;@ 레퍼런스 시스템&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1693&quot; data-origin-height=&quot;929&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eD4f0L/dJMcafzYhnt/jKFdwD7WMsUpZkqt3KRKjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eD4f0L/dJMcafzYhnt/jKFdwD7WMsUpZkqt3KRKjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eD4f0L/dJMcafzYhnt/jKFdwD7WMsUpZkqt3KRKjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeD4f0L%2FdJMcafzYhnt%2FjKFdwD7WMsUpZkqt3KRKjk%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;1693&quot; height=&quot;929&quot; data-origin-width=&quot;1693&quot; data-origin-height=&quot;929&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. @ 레퍼런스 시스템이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0에서는 업로드한 자료를 프롬프트 안에서 다음과 같이 부를 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1
@Image2
@Video1
@Audio1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이미지를 2장 올렸다면 첫 번째 이미지는 @Image1, 두 번째 이미지는 @Image2로 지칭할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상을 올렸다면 @Video1, 오디오를 올렸다면 @Audio1처럼 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 중요한 것은 단순히 자료를 부르는 것이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 핵심은 &lt;b&gt;각 자료가 어떤 역할을 하는지 명확히 지정하는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 나쁜 예: 그냥 참고하라고 하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람이 처음에는 이렇게 프롬프트를 씁니다.&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;Reference @Image1.
Reference @Video1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문장은 너무 모호합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Image1에서 캐릭터를 참고하라는 것인지, 배경을 참고하라는 것인지, 색감만 참고하라는 것인지 알 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Video1도 마찬가지입니다. 카메라 움직임을 참고하라는 것인지, 인물의 동작을 참고하라는 것인지, 편집 리듬을 참고하라는 것인지 불분명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 프롬프트에서는 &amp;ldquo;참고해줘&amp;rdquo;보다 &amp;ldquo;무엇을 참고해줘&amp;rdquo;가 훨씬 중요합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 좋은 예: 역할을 분리해서 지정하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트는 다음처럼 각 레퍼런스의 역할을 나눕니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the main character reference.
@Image2 as the first frame.
@Image3 as the last frame.
@Video1 for camera movement only.
@Audio1 as the music rhythm reference.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 쓰면 각 자료의 용도가 명확해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Image1은 캐릭터 참고용,&lt;br /&gt;@Image2는 시작 프레임,&lt;br /&gt;@Image3은 끝 프레임,&lt;br /&gt;@Video1은 카메라 움직임만 참고,&lt;br /&gt;@Audio1은 음악 리듬 참고용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료를 많이 넣는 것보다 중요한 것은 &lt;b&gt;자료의 역할을 정확히 나누는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 이미지 레퍼런스는 어떻게 나누면 좋을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 레퍼런스는 보통 다음과 같이 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the main character reference.
@Image2 as the first frame.
@Image3 as the last frame.
@Image4 as the background reference.
@Image5 as the outfit reference.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 역할은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레퍼런스역할&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;@Image1&lt;/td&gt;
&lt;td&gt;캐릭터 외형 참고&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@Image2&lt;/td&gt;
&lt;td&gt;영상 시작 프레임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@Image3&lt;/td&gt;
&lt;td&gt;영상 마지막 프레임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@Image4&lt;/td&gt;
&lt;td&gt;배경 / 장소 참고&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@Image5&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;예를 들어 캐릭터는 유지하고 배경만 바꾸고 싶다면 이렇게 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the main character reference.
@Image2 as the background reference.

Keep the character identity from @Image1.
Use only the environment, lighting, and atmosphere from @Image2.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 시작 프레임과 끝 프레임 지정하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 제작에서 가장 유용한 방식 중 하나는 시작 프레임과 끝 프레임을 지정하는 것입니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the first frame.
@Image2 as the last frame.

Start exactly from @Image1.
End exactly on @Image2.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 특히 여러 개의 짧은 영상을 이어붙일 때 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 15초짜리 장면을 여러 개 만들고 싶다면, 각 클립의 끝 프레임을 다음 클립의 시작 프레임과 연결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 장면 간 연결감이 좋아지고, 하나의 긴 영상처럼 이어붙이기 쉬워집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 영상 레퍼런스는 &amp;ldquo;무엇을 참고할지&amp;rdquo;가 핵심이다&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라 움직임, 인물 동작, 배경, 편집 리듬, 색감, 효과, 사운드가 모두 섞여 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 단순히 이렇게 쓰면 좋지 않습니다.&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;Reference @Video1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 다음처럼 범위를 좁혀야 합니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Video1 for camera movement only.
@Video1 for action choreography only.
@Video1 for editing rhythm only.
@Video1 for visual effects and transitions.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 카메라 움직임만 참고하고 싶다면 이렇게 씁니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Reference @Video1's camera movement only.
Do not copy the original character, background, color, or story.
Apply the same push-in speed, orbit timing, handheld feeling, and shot rhythm.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 쓰면 영상의 내용 전체를 따라가는 것이 아니라, 카메라 워크만 참고하도록 방향을 줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 영상을 뒤로 이어 만들 때:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Extend @Video1 by 15 seconds.

0&amp;ndash;5s: Continue from the final frame of @Video1. The camera slowly pushes forward while the light shifts across the scene.
5&amp;ndash;10s: The subject moves deeper into the environment. Add subtle wind, footsteps, and ambient sound.
10&amp;ndash;15s: The camera settles into a stable ending frame, ready for the next scene.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4541&quot; data-start=&quot;4525&quot; data-ke-size=&quot;size16&quot;&gt;앞부분을 새로 붙이고 싶으면:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;Extend backward 10 seconds.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 오디오 레퍼런스는 리듬과 감정선을 잡는 데 유용하다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오디오도 마찬가지로 역할을 정확히 정해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Audio1 as the background music reference.
@Audio1 as the music rhythm reference.
@Audio1 as the emotional tone reference.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뮤직비디오처럼 음악에 맞춰 영상을 만들고 싶다면 다음처럼 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Audio1 as the music rhythm reference.
Camera movement, lighting pulses, character motion, and transition timing should match the beat of @Audio1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음악 자체보다 분위기만 참고하고 싶다면 이렇게 씁니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Audio1 as the emotional tone reference only.
Do not copy the exact melody.
Match the mood, pacing, intensity, and emotional rise of @Audio1.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오디오 레퍼런스는 단순한 배경음악 지시가 아니라, 영상의 속도와 감정선을 설계하는 도구로 사용할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 실전 예시: 캐릭터 + 배경 + 카메라&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 캐릭터, 배경, 카메라 움직임을 분리한 예시입니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the main character reference.
@Image2 as the fantasy forest background reference.
@Video1 for camera movement only.

Create a 15-second cinematic fantasy scene.
The character from @Image1 walks through the forest environment from @Image2.
Apply @Video1's slow tracking shot and gentle handheld movement.
Do not copy @Video1's character or background.

Style:
Cinematic fantasy, soft light, atmospheric depth, natural movement.

Constraints:
Keep character identity consistent. No random outfit changes. No subtitles, no logos, no watermarks.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프롬프트의 구조는 명확합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터는 @Image1,&lt;br /&gt;배경은 @Image2,&lt;br /&gt;카메라 움직임은 @Video1에서 가져옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 자료의 역할이 겹치지 않기 때문에 결과를 제어하기 쉽습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 실전 예시: 시작 프레임과 끝 프레임 연결&lt;/h2&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the first frame.
@Image2 as the last frame.

Create a 15-second video.

0&amp;ndash;3s:
Start exactly from @Image1. The camera slowly pushes forward.

3&amp;ndash;8s:
The environment gradually changes. Add subtle wind, light movement, and natural atmosphere.

8&amp;ndash;12s:
The main visual transformation becomes clear. Keep the motion smooth and physically readable.

12&amp;ndash;15s:
Slowly arrive at @Image2. End exactly on @Image2 with a stable final composition.

Sound:
Soft wind, footsteps, distant ambience.

Constraints:
No subtitles, no logos, no watermarks, no random text, no unrealistic camera jumps.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조는 장면 전환, 여행 영상, 판타지 이동 장면, 뮤직비디오 컷 연결에 잘 맞습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 실전 예시: 음악 리듬에 맞춘 뮤직비디오&lt;/h2&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the main character reference.
@Image2 as the stage background reference.
@Audio1 as the music rhythm reference.

Create a 15-second cinematic music video shot.

0&amp;ndash;3s:
The character stands in the environment from @Image2 as the music begins. Camera slowly pushes in.

3&amp;ndash;6s:
The character starts moving to the rhythm of @Audio1. Lighting subtly pulses with the beat.

6&amp;ndash;10s:
Main performance moment. Character motion, camera movement, and visual accents match the downbeats.

10&amp;ndash;13s:
The motion resolves. The environment reacts with light, wind, or particles.

13&amp;ndash;15s:
End on a strong cinematic hero frame.

Constraints:
Keep character identity and outfit consistent. No subtitles, no logos, no watermarks, no extra limbs, no face morphing.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예시는 @Audio1을 단순한 배경음악이 아니라 영상 전체의 리듬 기준으로 사용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. @ 레퍼런스 시스템의 핵심 원칙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0의 @ 레퍼런스 시스템은 &amp;ldquo;자료를 많이 넣는 기술&amp;rdquo;이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 &lt;b&gt;자료의 역할을 정확히 나누는 기술&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 = 캐릭터
@Image2 = 시작 프레임
@Image3 = 끝 프레임
@Image4 = 배경
@Video1 = 카메라 움직임
@Audio1 = 음악 리듬
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 프롬프트 안에서는 항상 다음을 명확히 해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;무엇을 참고할지
무엇은 참고하지 말아야 할지
어떤 요소를 유지해야 할지
어떤 요소를 바꿔야 할지
마지막에 어떤 프레임으로 끝나야 할지
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 가장 기본이 되는 템플릿&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로, 가장 실전적인 기본 템플릿입니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Image1 as the main character reference.
@Image2 as the first frame.
@Image3 as the last frame.
@Image4 as the background reference.
@Video1 for camera movement only.
@Audio1 as the music rhythm reference.

Create a 15-second video.

Start exactly from @Image2.
Keep the character identity from @Image1.
Use the environment style from @Image4.
Apply @Video1's camera movement only.
Match motion and transitions to @Audio1's rhythm.
End exactly on @Image3.

Camera:
Smooth cinematic movement, no random shake, no unrealistic camera jumps.

Sound:
Natural ambience, footsteps, wind, subtle cinematic sound effects.

Style:
Cinematic quality, detailed lighting, coherent motion, stable visual continuity.

Constraints:
No random characters, no outfit changes, no face morphing, no subtitles, no logos, no watermarks, no distorted hands, no extra limbs.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;마무리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0 프롬프트에서 @ 레퍼런스 시스템을 잘 쓰려면, 업로드한 자료를 단순히 &amp;ldquo;참고 이미지&amp;rdquo;나 &amp;ldquo;참고 영상&amp;rdquo;으로만 생각하면 안 됩니다.&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;br /&gt;영상은 카메라 움직임, 액션, 편집 리듬, 효과 전환으로 나눌 수 있습니다.&lt;br /&gt;오디오는 배경음악, 리듬, 감정선으로 나눌 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트는 길어서 좋은 것이 아니라, &lt;b&gt;역할이 분명해서 좋은 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Seedance2 기초인 프롬프트 작성법이 궁금하시면 참고바랍니다.&lt;/h4&gt;
&lt;figure id=&quot;og_1779671037603&quot; contenteditable=&quot;false&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/rNqwp/dJMb9cBOdBr/rcIHUaqC4BdHqY39Kp48y1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/EnH6y/dJMb9jgDvwT/f6oNKOKJTkFcucJwzoKXX0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/fNb1r/dJMb9jOs5kh/hlQRkC9KYfqRdeCCQJMSf0/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024&quot; data-og-url=&quot;https://javaexpert.tistory.com/1761&quot; data-og-source-url=&quot;https://javaexpert.tistory.com/1761&quot; data-og-host=&quot;javaexpert.tistory.com&quot; data-og-description=&quot;예쁜 문장보다 중요한 것은 &amp;lsquo;영상 콘티처럼 쓰는 것&amp;rsquo;AI 영상 제작 도구를 처음 사용할 때 가장 많이 하는 실수가 있습니다.바로 프롬프트를 소설처럼 길고 감성적으로 쓰는 것입니다.예를 들&quot; data-og-title=&quot;Seedance 2.0을 처음 쓰는 사람을 위한 프롬프트 작성법&quot; data-og-type=&quot;article&quot; data-ke-align=&quot;alignCenter&quot; data-ke-type=&quot;opengraph&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://javaexpert.tistory.com/1761&quot; data-source-url=&quot;https://javaexpert.tistory.com/1761&quot;&gt;
&lt;div style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/rNqwp/dJMb9cBOdBr/rcIHUaqC4BdHqY39Kp48y1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/EnH6y/dJMb9jgDvwT/f6oNKOKJTkFcucJwzoKXX0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/fNb1r/dJMb9jOs5kh/hlQRkC9KYfqRdeCCQJMSf0/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;Seedance 2.0을 처음 쓰는 사람을 위한 프롬프트 작성법&lt;/p&gt;
&lt;p style=&quot;color: #909090;&quot; data-ke-size=&quot;size16&quot;&gt;예쁜 문장보다 중요한 것은 &amp;lsquo;영상 콘티처럼 쓰는 것&amp;rsquo;AI 영상 제작 도구를 처음 사용할 때 가장 많이 하는 실수가 있습니다.바로 프롬프트를 소설처럼 길고 감성적으로 쓰는 것입니다.예를 들&lt;/p&gt;
&lt;p style=&quot;color: #909090;&quot; data-ke-size=&quot;size16&quot;&gt;javaexpert.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Seedance2</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1762</guid>
      <comments>https://javaexpert.tistory.com/1762#entry1762comment</comments>
      <pubDate>Mon, 25 May 2026 09:58:43 +0900</pubDate>
    </item>
    <item>
      <title>Seedance 2.0을 처음 쓰는 사람을 위한 프롬프트 작성법</title>
      <link>https://javaexpert.tistory.com/1761</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;예쁜 문장보다 중요한 것은 &amp;lsquo;영상 콘티처럼 쓰는 것&amp;rsquo;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 제작 도구를 처음 사용할 때 가장 많이 하는 실수가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 프롬프트를 &lt;b&gt;소설처럼 길고 감성적으로 쓰는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 식입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 소녀가 슬픈 마음으로 비 오는 거리를 걸어간다. 세상은 차갑고, 그녀의 마음은 무너져 내린다. 카메라는 그녀의 외로움을 아름답게 담아낸다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문장 자체는 나쁘지 않습니다.&lt;br /&gt;하지만 AI 영상 모델 입장에서는 애매한 부분이 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소녀가 어디에 있는지, 어떻게 걷는지, 카메라는 어디서 찍는지, 몇 초 동안 어떤 동작이 이어지는지 명확하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0 같은 영상 생성 모델을 사용할 때는 감성적인 문장보다 &lt;b&gt;감독 지시문&lt;/b&gt;에 가까운 프롬프트가 훨씬 안정적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 이렇게 생각해야 합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;내가 지금 영상을 찍는 감독이라면, 배우와 카메라맨에게 어떻게 지시할까?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 Seedance 2.0을 처음 사용하는 사람을 기준으로, 프롬프트를 어떻게 나누고, 어떤 식으로 작성하면 좋은지 정리해보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;1. 프롬프트는 시간 단위로 나누어야 한다&lt;/h1&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;15초짜리 영상을 만든다고 했을 때, 15초 전체를 한 문장으로 설명하면 장면이 흐트러지기 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이렇게 쓰면 불안정합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋지 않은 예&lt;/h2&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;한 소년이 미래 도시를 달리다가 홀로그램이 깨지고, 뒤를 돌아보며 놀라고, 다시 앞을 향해 달려간다. 카메라는 역동적으로 움직인다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프롬프트는 대략적인 상황은 알 수 있지만, 영상으로 만들기에는 정보가 부족합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소년이 처음부터 달리고 있는지, 언제 뒤를 돌아보는지, 카메라는 언제 가까워지는지 알기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 시간 구간을 나누는 방식이 좋습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋은 예&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[0:00&amp;ndash;0:03]
푸른 네온빛이 흐르는 미래 도시 골목. 소년이 화면 왼쪽에서 오른쪽으로 빠르게 달린다. 카메라는 낮은 위치에서 소년의 전신을 따라가는 트래킹 샷.

[0:03&amp;ndash;0:06]
소년 주변의 홀로그램 광고판이 깨지며 빛 조각이 공중으로 흩어진다. 소년은 달리던 자세를 유지한 채 고개만 살짝 뒤로 돌린다. 카메라는 소년의 상반신을 따라 천천히 가까워진다.

[0:06&amp;ndash;0:10]
소년이 놀란 표정으로 잠깐 멈칫하지만 곧 다시 앞을 향해 달린다. 깨진 홀로그램 조각들이 뒤쪽으로 흘러간다. 카메라는 흔들림을 줄이고 안정적인 사이드 트래킹 샷을 유지한다.

[0:10&amp;ndash;0:15]
소년이 멀리 보이는 빛나는 균열을 향해 속도를 높인다. 카메라는 소년의 뒤쪽에서 천천히 밀고 들어가며 균열을 화면 중앙에 배치한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 시간별로 나누면 AI가 장면의 흐름을 훨씬 잘 따라갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 이것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 번에 모든 걸 설명하지 말고, 시간 순서대로 장면을 쪼개야 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;2. 각 시간 구간에는 네 가지를 반드시 써야 한다&lt;/h1&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;li&gt;카메라&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 네 가지가 빠지면 영상이 불안정해질 가능성이 커집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 구조&lt;/h2&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[시간]
몇 초부터 몇 초까지인지

[주체]
누가 등장하는지

[공간]
어디에 있는지

[동작]
무엇을 하는지

[카메라]
어떤 구도와 움직임으로 찍는지
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;여자가 숲을 달린다&amp;rdquo;라는 장면을 만든다고 해보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;짧고 애매한 프롬프트&lt;/h2&gt;
&lt;pre class=&quot;erlang&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 data-ke-size=&quot;size26&quot;&gt;콘티형 프롬프트&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[0:00&amp;ndash;0:04]
초록빛 안개가 낮게 깔린 깊은 숲속. 긴 머리의 여자가 화면 중앙에서 앞으로 달린다. 나뭇잎과 작은 빛 입자가 그녀의 뒤쪽으로 흩어진다. 카메라는 정면에서 천천히 뒤로 물러나며 그녀의 달리기를 따라간다.

[0:04&amp;ndash;0:08]
여자가 쓰러진 나무를 가볍게 뛰어넘는다. 착지 후 몸을 낮추고 다시 달린다. 카메라는 옆쪽에서 전신을 잡는 사이드 트래킹 샷으로 이동한다.

[0:08&amp;ndash;0:12]
바람이 강해지고 나뭇잎이 원형으로 회전한다. 여자는 팔로 얼굴을 살짝 가리며 앞으로 나아간다. 카메라는 상반신 클로즈업으로 천천히 가까워진다.

[0:12&amp;ndash;0:15]
여자가 숲 끝에서 빛나는 균열을 발견하고 눈을 크게 뜬다. 카메라는 그녀의 얼굴에서 균열 방향으로 천천히 팬한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 쓰면 AI가 &amp;ldquo;무엇을 보여줘야 하는지&amp;rdquo; 훨씬 분명하게 이해할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;3. 감정은 추상어보다 몸짓으로 써야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자가 자주 쓰는 표현이 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;슬프게&lt;/li&gt;
&lt;li&gt;애절하게&lt;/li&gt;
&lt;li&gt;절망적으로&lt;/li&gt;
&lt;li&gt;감동적으로&lt;/li&gt;
&lt;li&gt;긴장감 있게&lt;/li&gt;
&lt;li&gt;두려움에 휩싸여&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 감정 단어가 완전히 나쁜 것은 아닙니다.&lt;br /&gt;하지만 영상 생성에서는 감정을 &lt;b&gt;눈에 보이는 행동&lt;/b&gt;으로 바꿔주는 것이 더 좋습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋지 않은 예&lt;/h2&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;소녀가 슬픈 표정으로 걷는다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;더 좋은 예&lt;/h2&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;소녀가 고개를 살짝 숙이고 천천히 걷는다. 어깨가 아래로 처져 있고, 손끝이 힘없이 흔들린다. 눈은 바닥을 향하고 있으며 입술은 살짝 다물려 있다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;슬프다&amp;rdquo;라고 쓰는 대신, 슬퍼 보이는 몸의 상태를 적는 것입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;감정어를 몸짓으로 바꾸는 예&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불안하다&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;인물이 주변을 빠르게 살핀다. 손가락이 옷자락을 꽉 쥐고 있고, 한 걸음 앞으로 나아갔다가 다시 멈춘다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;분노한다&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;인물이 턱에 힘을 주고 주먹을 꽉 쥔다. 어깨가 올라가며 숨을 거칠게 내쉰다. 시선은 상대를 똑바로 향한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;놀란다&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;인물이 갑자기 걸음을 멈춘다. 눈이 크게 떠지고, 상체가 살짝 뒤로 젖혀진다. 한 손이 가슴 앞으로 올라온다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결심한다&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;인물이 잠시 눈을 감았다가 천천히 뜬다. 흐트러진 자세를 바로잡고, 고개를 들어 정면을 바라본다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상에서는 감정 자체보다 &lt;b&gt;감정이 몸에 드러나는 방식&lt;/b&gt;을 써주는 것이 중요합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;4. 동작은 작게 쪼개야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0에서 액션을 만들 때도 마찬가지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;화려하게 싸운다&amp;rdquo;, &amp;ldquo;격렬하게 달린다&amp;rdquo;, &amp;ldquo;멋지게 점프한다&amp;rdquo;처럼 쓰면 장면이 과하게 흔들리거나 동작이 뭉개질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 동작일수록 작게 나눠야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋지 않은 예&lt;/h2&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;사무라이가 적들을 빠르게 베며 화려하게 싸운다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문장은 멋있어 보이지만, AI에게는 너무 큰 지시입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋은 예&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[0:00&amp;ndash;0:03]
비 내리는 대나무 숲길. 사무라이가 낮은 자세로 서 있고, 오른손은 검 손잡이를 잡고 있다. 카메라는 정면 로우 앵글 와이드 샷.

[0:03&amp;ndash;0:06]
왼쪽의 복면 검객이 먼저 달려든다. 사무라이는 몸을 반걸음 뒤로 빼며 검을 절반만 뽑는다. 카메라는 흔들림 없이 사무라이의 상반신과 검 손잡이를 잡는다.

[0:06&amp;ndash;0:09]
사무라이가 짧고 빠른 동작으로 검을 완전히 뽑아 왼쪽에서 오른쪽으로 휘두른다. 복면 검객은 공격을 멈추고 뒤로 밀려난다. 카메라는 옆쪽에서 동작을 따라가지만 과한 회전은 하지 않는다.

[0:09&amp;ndash;0:12]
두 번째 검객이 오른쪽에서 내려친다. 사무라이는 검을 위로 들어 막고, 발을 한 걸음 옆으로 이동한다. 빗물이 검날에서 튄다.

[0:12&amp;ndash;0:15]
사무라이가 낮은 자세로 착지하며 검을 아래로 내린다. 주변 대나무 잎이 흔들리고, 세 검객은 잠시 거리를 둔다. 카메라는 천천히 뒤로 빠지며 장면을 마무리한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액션 장면은 특히 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;큰 액션은 작은 동작의 연속으로 쪼개야 안정적입니다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;5. 카메라 지시는 정확하게 써야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상에서 카메라는 매우 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트에 &amp;ldquo;시네마틱하게&amp;rdquo;, &amp;ldquo;역동적으로&amp;rdquo;, &amp;ldquo;멋지게&amp;rdquo;라고만 쓰면 원하는 구도가 잘 나오지 않을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라는 가능한 한 직접적인 용어로 써주는 것이 좋습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 쓰기 좋은 카메라 표현&lt;/h2&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;wide shot
medium shot
close-up
low angle
high angle
side tracking shot
slow push-in
slow pull-back
over-the-shoulder shot
locked camera
handheld camera
smooth dolly shot
pan left
pan right
tilt up
tilt down
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어로 써도 됩니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;와이드 샷
상반신 샷
얼굴 클로즈업
로우 앵글
하이 앵글
측면 트래킹 샷
천천히 밀고 들어가는 카메라
천천히 뒤로 빠지는 카메라
고정 카메라
부드러운 돌리 샷
왼쪽으로 팬
오른쪽으로 팬
위로 틸트
아래로 틸트
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋지 않은 예&lt;/h2&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;카메라는 감각적이고 멋지게 움직인다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋은 예&lt;/h2&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;카메라는 인물의 오른쪽 측면에서 전신을 잡고, 인물의 달리기 속도에 맞춰 부드럽게 따라간다. 큰 흔들림 없이 안정적인 사이드 트래킹 샷을 유지한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 중요한 점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;큰 동작이 있을 때는 카메라를 너무 많이 움직이지 않는 것이 좋습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인물이 달리고, 점프하고, 싸우고, 회전하는데 카메라마저 빠르게 움직이면 화면이 불안정해질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액션이 클수록 카메라는 안정적으로 두는 편이 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;6. 참고 이미지는 너무 많이 넣지 않는 것이 좋다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0에서는 여러 참고 자료를 활용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 다음과 같은 자료가 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐릭터 이미지&lt;/li&gt;
&lt;li&gt;배경 이미지&lt;/li&gt;
&lt;li&gt;동작 참고 영상&lt;/li&gt;
&lt;li&gt;음성 자료&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 뮤직비디오를 만든다면 이런 식으로 구성할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@CHARACTER_REF: 주인공 얼굴과 의상 참고
@BG_REF: 배경 도시 이미지 참고
@POSE_REF: 달리는 자세 참고
@AUDIO_REF: 노래 또는 대사 음성 참고
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 참고 자료가 많다고 무조건 좋은 것은 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 많은 자료를 넣으면 AI가 어떤 자료를 우선해야 할지 혼란스러워질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자라면 처음에는 &lt;b&gt;4~5개 정도&lt;/b&gt;로 제한하는 것이 좋습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추천 구성&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 주인공 캐릭터 이미지
2. 주인공 의상 시트
3. 배경 이미지
4. 동작 참고 이미지 또는 영상
5. 음성 참고 자료
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정도면 캐릭터, 공간, 동작, 사운드 기준이 어느 정도 잡힙니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;7. 긴 영상은 한 번에 만들려고 하지 말아야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 제작에서 긴 영상을 만들 때는 두 가지 방식이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째는 &lt;b&gt;영상 연장 기능을 사용하는 방식&lt;/b&gt;입니다.&lt;br /&gt;두 번째는 &lt;b&gt;짧은 영상을 여러 개 만들어 편집으로 이어 붙이는 방식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘텐츠 성격에 따라 선택이 달라집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1) 감성 드라마, 문예형 영상&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;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;비 오는 창가에 앉은 여자가 천천히 고개를 돌려 창밖을 바라본다. 카메라는 얼굴 클로즈업에서 천천히 뒤로 빠지며 방 안의 조용한 분위기를 보여준다. 다음 장면에서도 같은 자세와 조명을 유지한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 장면은 큰 동작이 없기 때문에 연장 방식이 비교적 안정적입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2) 무술, 추격, 전투, 빠른 액션 영상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 액션 장면은 한 번에 길게 만들기보다 짧은 컷으로 나누는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 전투 장면을 30초 만들고 싶다면, 30초짜리 하나를 만드는 것보다 5초 또는 10초 단위로 나누는 편이 안정적입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1번 컷: 대치
2번 컷: 첫 번째 공격
3번 컷: 회피
4번 컷: 반격
5번 컷: 마무리 자세
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 나누면 동작이 훨씬 선명해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이어 붙일 때 주의할 점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 영상 사이에 비슷한 프레임이 반복되면 순간적으로 끊기거나 버벅이는 느낌이 날 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 편집할 때는 앞 영상의 마지막 프레임과 다음 영상의 첫 프레임이 너무 겹치지 않도록 조정해야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;8. 처음 프레임과 마지막 프레임을 신경 써야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상 생성에서 첫 프레임과 마지막 프레임은 매우 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 여러 영상을 이어 붙일 때는 마지막 프레임이 다음 장면의 시작점이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 프롬프트에 이런 식으로 써주는 것이 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;첫 프레임은 주인공이 화면 중앙에 서 있는 정면 와이드 샷으로 시작한다.
마지막 프레임은 주인공이 오른쪽을 바라보며 멈춘 상반신 샷으로 끝난다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 액션 장면에서는 이렇게 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;첫 프레임에서 사무라이는 낮은 자세로 검 손잡이를 잡고 있다.
마지막 프레임에서 사무라이는 검을 뽑은 상태로 오른쪽을 향해 서 있다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 시작과 끝을 명확히 하면 다음 컷을 만들 때 연속성을 잡기 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;9. 인물 프롬프트 끝에는 안정화 문구를 넣는 것이 좋다&lt;/h1&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;h2 data-ke-size=&quot;size26&quot;&gt;기본 안정화 문구&lt;/h2&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;얼굴 안정성 유지, 동일한 얼굴 구조 유지, 동일한 헤어스타일 유지, 동일한 의상 유지, 신체 비율 일관성 유지, 손가락 왜곡 없음, 팔다리 왜곡 없음, 추가 인물 없음, 화면 흔들림 최소화, 부드러운 동작, 자연스러운 프레임 연결, 텍스트 없음, 로고 없음, 워터마크 없음.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애니메이션 영상이라면 이렇게 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;2D 애니메이션 캐릭터 스타일 유지, 캐릭터 얼굴과 의상 일관성 유지, 헤어스타일 변화 없음, 신체 비율 유지, 팔다리 왜곡 없음, 추가 인물 없음, 부드러운 움직임, 안정적인 카메라, 텍스트 없음, 로고 없음, 워터마크 없음.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실사풍이라면 이렇게 바꿀 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;realistic facial consistency, stable facial features, consistent hairstyle, consistent outfit, natural body proportions, no extra people, no distorted hands, no distorted limbs, smooth motion, stable camera, no text, no logo, no watermark.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문구를 넣는다고 모든 문제가 사라지는 것은 아니지만, 인물 영상에서는 상당히 중요한 고정 장치가 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;10. 초보자를 위한 Seedance 2.0 프롬프트 템플릿&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 템플릿은 처음 시작하는 사람이 그대로 복사해서 사용할 수 있는 기본 구조입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[FORMAT]
16:9 horizontal video, 15 seconds, cinematic 2D animation style.

[REFERENCE]
@CHARACTER_REF: 주인공 얼굴, 헤어스타일, 의상 참고
@BG_REF: 배경 분위기 참고

[SCENE SUMMARY]
주인공이 비 오는 미래 도시 골목을 달리다가, 깨지는 홀로그램 사이에서 빛나는 균열을 발견하는 장면.

[0:00&amp;ndash;0:03]
비가 내리는 푸른 네온 도시 골목. 주인공은 화면 왼쪽에서 오른쪽으로 빠르게 달린다. 젖은 바닥에는 네온 간판의 빛이 반사된다. 카메라는 낮은 위치에서 전신을 잡고 부드럽게 따라간다.

[0:03&amp;ndash;0:06]
주인공 옆의 홀로그램 광고판이 깨지며 작은 빛 조각들이 공중으로 흩어진다. 주인공은 달리던 자세를 유지한 채 고개만 살짝 뒤로 돌린다. 카메라는 상반신에 천천히 가까워진다.

[0:06&amp;ndash;0:10]
주인공은 놀란 표정으로 잠깐 멈칫하지만 다시 앞을 향해 달린다. 주변의 데이터 조각들이 바람처럼 뒤로 흘러간다. 카메라는 흔들림 없는 사이드 트래킹 샷을 유지한다.

[0:10&amp;ndash;0:15]
골목 끝에 푸른빛 균열이 열린다. 주인공은 균열을 향해 속도를 높인다. 카메라는 뒤쪽에서 천천히 밀고 들어가며 주인공과 균열을 화면 중앙에 배치한다.

[CHARACTER CONSISTENCY]
주인공의 얼굴, 헤어스타일, 의상, 신체 비율을 모든 프레임에서 동일하게 유지한다.

[NEGATIVE]
추가 인물 없음, 얼굴 변형 없음, 손가락 왜곡 없음, 팔다리 왜곡 없음, 의상 변화 없음, 텍스트 없음, 로고 없음, 워터마크 없음, 과도한 카메라 흔들림 없음.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조만 익혀도 프롬프트 품질이 훨씬 좋아집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;11. 장르별 예제&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예제 1. 감성 뮤직비디오 장면&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[FORMAT]
16:9 horizontal, 15 seconds, cinematic 2D anime music video style.

[SCENE SUMMARY]
비 오는 밤, 여주인공이 버스 정류장에서 혼자 서 있다가 멀리 지나가는 불빛을 바라보는 장면.

[0:00&amp;ndash;0:04]
비가 조용히 내리는 밤의 버스 정류장. 여주인공은 투명한 우산을 들고 정류장 아래에 서 있다. 젖은 도로에는 가로등 불빛이 길게 반사된다. 카메라는 정면 와이드 샷으로 정류장 전체를 보여준다.

[0:04&amp;ndash;0:08]
여주인공이 고개를 살짝 숙이고 우산 손잡이를 두 손으로 잡는다. 어깨가 조금 내려가 있고, 시선은 바닥을 향한다. 카메라는 천천히 상반신 클로즈업으로 들어간다.

[0:08&amp;ndash;0:12]
멀리서 버스 불빛이 지나가지만 정류장에는 멈추지 않는다. 여주인공은 천천히 고개를 들어 지나가는 불빛을 바라본다. 카메라는 그녀의 옆얼굴을 부드럽게 따라간다.

[0:12&amp;ndash;0:15]
버스 불빛이 멀어지고, 여주인공의 눈동자에 작은 빛 반사가 남는다. 카메라는 얼굴 클로즈업에서 멈춘다.

[NEGATIVE]
캐릭터 얼굴 일관성 유지, 의상 변화 없음, 추가 인물 없음, 손 왜곡 없음, 텍스트 없음, 로고 없음, 워터마크 없음, 과도한 화면 흔들림 없음.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예제 2. 액션 추격 장면&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[FORMAT]
16:9 horizontal, 15 seconds, cinematic action animation.

[SCENE SUMMARY]
주인공이 좁은 시장 골목에서 추격자를 피해 도망치는 장면.

[0:00&amp;ndash;0:03]
밤의 좁은 시장 골목. 주인공이 과일 상자 사이를 빠르게 달린다. 뒤쪽에는 어두운 실루엣의 추격자 두 명이 따라온다. 카메라는 주인공의 앞쪽에서 뒤로 물러나며 달리기를 따라간다.

[0:03&amp;ndash;0:06]
주인공이 오른쪽으로 급히 방향을 틀며 작은 노점 테이블을 피한다. 팔은 균형을 잡기 위해 옆으로 벌어진다. 카메라는 측면 트래킹 샷으로 전환한다.

[0:06&amp;ndash;0:09]
뒤쪽 추격자가 노점과 부딪히며 상자가 흔들린다. 주인공은 뒤돌아보지 않고 계속 달린다. 카메라는 주인공의 하체와 발동작을 낮은 앵글로 잡는다.

[0:09&amp;ndash;0:12]
주인공이 낮은 천막 아래로 몸을 숙여 통과한다. 머리카락과 옷자락이 빠르게 흔들린다. 카메라는 천막 아래를 통과하는 움직임을 부드럽게 따라간다.

[0:12&amp;ndash;0:15]
주인공이 골목 끝의 밝은 거리로 뛰쳐나간다. 카메라는 뒤쪽에서 천천히 밀고 들어가며 밝은 출구를 화면 중앙에 배치한다.

[NEGATIVE]
동작 부드러움, 얼굴 안정성 유지, 의상 일관성 유지, 추가 인물 증가 없음, 팔다리 왜곡 없음, 화면 흔들림 최소화, 텍스트 없음, 로고 없음, 워터마크 없음.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예제 3. 캐릭터 소개 영상&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[FORMAT]
16:9 horizontal, 15 seconds, clean character introduction video, 3D animation style.

[SCENE SUMMARY]
고장 난 시간 스쿠터를 타는 프리랜서 배달원이 흰색 스튜디오 배경에서 캐릭터 소개 영상처럼 등장한다.

[0:00&amp;ndash;0:04]
밝은 흰색 스튜디오 배경. 주인공은 시간 스쿠터 옆에 서 있다. 헬멧은 한 손에 들고 있고, 다른 손은 허리에 올려놓고 있다. 카메라는 정면 전신 와이드 샷으로 시작한다.

[0:04&amp;ndash;0:08]
주인공이 장난스러운 표정으로 헬멧을 머리에 쓴다. 스쿠터의 작은 시간 계기판이 푸른빛으로 깜빡인다. 카메라는 천천히 상반신으로 가까워진다.

[0:08&amp;ndash;0:12]
주인공이 스쿠터에 올라타고 한쪽 발로 바닥을 가볍게 찬다. 스쿠터 뒤쪽에서 작은 빛 입자가 튄다. 카메라는 측면에서 전신을 잡는다.

[0:12&amp;ndash;0:15]
주인공이 카메라를 향해 자신감 있게 엄지를 들어 보인다. 스쿠터는 제자리에서 살짝 떠오른다. 카메라는 정면 클로즈업으로 마무리한다.

[NEGATIVE]
흰색 배경 유지, 캐릭터 얼굴과 의상 일관성 유지, 스쿠터 디자인 유지, 추가 인물 없음, 손가락 왜곡 없음, 팔다리 왜곡 없음, 텍스트 없음, 로고 없음, 워터마크 없음.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;12. 프롬프트 작성 전 체크리스트&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0 프롬프트를 작성하기 전에 아래 항목을 확인하면 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 영상 길이를 정했는가?
2. 시간을 3초 또는 5초 단위로 나누었는가?
3. 각 시간 구간마다 주체, 공간, 동작, 카메라가 들어갔는가?
4. 감정 표현을 몸짓과 표정으로 바꾸었는가?
5. 큰 액션을 작은 동작으로 쪼갰는가?
6. 카메라 움직임이 너무 과하지 않은가?
7. 참고 자료가 너무 많지는 않은가?
8. 첫 프레임과 마지막 프레임을 생각했는가?
9. 캐릭터 일관성 문구를 넣었는가?
10. 텍스트, 로고, 워터마크 금지 문구를 넣었는가?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 체크리스트를 기준으로 프롬프트를 다듬으면 초보자도 훨씬 안정적인 결과를 얻을 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;마무리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0을 잘 쓰는 핵심은 화려한 문장을 쓰는 것이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오히려 중요한 것은 장면을 차분하게 나누고, 각 시간마다 무엇이 보이는지 명확히 지시하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 프롬프트는 소설이 아니라 &lt;b&gt;촬영 지시서&lt;/b&gt;에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 다음 원칙만 기억하면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;시간을 나눈다.
주체를 정한다.
공간을 설명한다.
동작을 작게 쪼갠다.
카메라를 정확히 지시한다.
감정은 몸짓으로 보여준다.
캐릭터 일관성을 마지막에 고정한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 번거롭게 느껴질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이렇게 작성하면 AI가 장면을 훨씬 안정적으로 이해하고, 결과물도 더 일관되게 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0을 처음 시작한다면, 감성적인 문장부터 쓰기보다 먼저 이렇게 질문해보는 것이 좋습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 장면을 실제 촬영한다면, 몇 초에 누가 어디서 무엇을 하고, 카메라는 어떻게 움직일까?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 질문에 답하는 방식으로 프롬프트를 쓰면 됩니다.&lt;/p&gt;</description>
      <category>Seedance2</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1761</guid>
      <comments>https://javaexpert.tistory.com/1761#entry1761comment</comments>
      <pubDate>Thu, 21 May 2026 17:26:34 +0900</pubDate>
    </item>
    <item>
      <title>AI 영상 제작자를 위한 20가지 프롬프트 추천 스킬</title>
      <link>https://javaexpert.tistory.com/1760</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;mdash; NolanX AI Skills를 기준으로 보는 &amp;ldquo;영화형 생성 프롬프트&amp;rdquo; 설계법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 AI 이미지&amp;middot;영상 생성에서 중요한 것은 단순히 &amp;ldquo;멋지게 만들어줘&amp;rdquo;라고 말하는 것이 아니다.&lt;br /&gt;결과물의 품질을 결정하는 핵심은 &lt;b&gt;무엇을 고정하고, 무엇을 움직이고, 어떤 방식으로 촬영되게 할 것인가&lt;/b&gt;를 구체적으로 지시하는 데 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NolanX AI의 skills 폴더에 들어 있는 20개의 스킬은 바로 이 지점을 다룬다.&lt;br /&gt;각 스킬은 영화 연출, 스토리보드, 액션 설계, 조명, 샷 구성, 캐릭터 연속성, 레퍼런스 기반 영상 생성, 숏폼 드라마 후킹 등 AI 영상 제작에서 자주 무너지는 문제를 해결하기 위한 작은 제작 규칙집에 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 20개 스킬을 하나씩 살펴보며 다음 세 가지를 정리한다.&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;1. action-choreography-camera-logic&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;액션 장면의 동선과 카메라 논리를 잡는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 격투, 추격, 변신, 고속 액션처럼 움직임이 많은 장면에서 사용한다. 핵심은 액션을 &amp;ldquo;화려하게&amp;rdquo; 만드는 것이 아니라, &lt;b&gt;누가 공격하고, 누가 반응하며, 힘이 어느 방향으로 이동하고, 카메라가 왜 그 위치에 있는지&lt;/b&gt;를 명확히 하는 것이다. 원본 스킬은 공격자&amp;middot;반응자&amp;middot;운동량 방향&amp;middot;카메라 위치를 정의하고, 좌우 이동 방향과 시선, 공격 방향을 보존하라고 규정한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/action-choreography-camera-logic/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;격투 장면, 추격 장면, 폭발 장면, 변신 장면, 로봇 전투, 괴수 액션, 차량 추격처럼 화면 안에서 많은 일이 동시에 벌어질 때 유용하다. AI 영상은 액션이 복잡해질수록 공간감이 무너지는 경우가 많기 때문에, 이 스킬은 &amp;ldquo;액션의 지리감&amp;rdquo;을 유지하는 데 도움을 준다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 장면의 기준축을 정한다. 예를 들어 주인공은 왼쪽에서 오른쪽으로 이동하고, 적은 오른쪽에서 왼쪽으로 들어온다고 설정한다. 그다음 공격, 충돌, 회복의 단계를 나누고 각 단계에서 카메라가 어떤 이유로 움직이는지 지정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라 움직임도 아무렇게나 쓰면 안 된다. 위협을 드러내기 위한 카메라인지, 힘의 방향을 따라가는 카메라인지, 충격을 흡수하는 카메라인지, 인물을 가두는 카메라인지를 분명히 해야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;격투 장면을 액션 동선 중심으로 설계해줘.

주인공은 화면 왼쪽에서 오른쪽으로 돌진한다.
적은 오른쪽에서 방어 자세를 취하다가 뒤로 밀려난다.
첫 2초는 넓은 샷으로 두 인물의 위치와 거리감을 보여준다.
3초 지점에서 주인공이 오른손으로 공격을 시작하고,
카메라는 힘의 방향을 따라 lateral tracking한다.
충돌 순간에는 짧은 impact push-in을 사용하고,
이후 적이 뒤로 밀려나는 recovery beat를 보여준다.

좌우 이동 방향과 공격 방향은 컷 사이에서도 유지해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;2. cinema-studio-lens-look&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프리미엄 영화 룩을 만드는 렌즈&amp;middot;조리개&amp;middot;질감 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 이미지나 영상에 고급 영화적 질감을 부여할 때 사용한다. 원본은 2.35:1 와이드스크린, 85mm 초점거리, T1.8 대구경 조리개, ARRI Master Primes 렌즈 느낌, 얕은 심도, 필름 그레인, 블룸, 할레이션, 24fps 셔터룰 기반 모션블러 등을 기본 광학 패키지로 제시한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/cinema-studio-lens-look/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 포스터, 영화 스틸컷, 뮤직비디오 장면, 광고 컷, 시네마틱 키비주얼, 고급 CG 렌더 느낌이 필요할 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 &amp;ldquo;시네마틱하게&amp;rdquo;라고 쓰지 말고, 렌즈와 조리개, 초점, 배경 흐림, 하이라이트 반응, 질감을 구체적으로 써야 한다. 다만 원본 스킬도 강조하듯이, 이런 요소는 장식이 아니라 감정과 이야기 목적에 연결되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 고립감을 표현하고 싶다면 얕은 심도로 배경을 흐리고 인물의 얼굴만 선명하게 고정한다. 긴장감을 표현하고 싶다면 어두운 배경 속 하이라이트에 은은한 할레이션을 넣는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;이 장면을 프리미엄 영화 스틸컷처럼 구성해줘.

2.35:1 anamorphic widescreen.
85mm lens, T1.8 aperture.
주인공의 얼굴에만 초점이 고정되고,
배경은 깊게 흐려진 oval bokeh로 처리한다.
하이라이트에는 subtle bloom과 halation을 넣고,
전체 질감은 high-end cinematic CG with subtle film grain.

렌즈 효과는 장식이 아니라
주인공이 군중 속에서 고립되어 있다는 감정을 강화하는 방향으로 사용해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;3. cinematic-hit-marking-action-director&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;액션의 충돌 타이밍을 0.1초 단위로 설계하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 액션 영상에서 &amp;ldquo;언제 충돌이 일어나는가&amp;rdquo;를 아주 정밀하게 지정하는 데 사용한다. 원본은 15초 액션 클립을 4~5개의 핵심 구간으로 나누고, 충돌&amp;middot;폭발&amp;middot;반전&amp;middot;타격이 있는 순간에는 0.1초 단위의 hit mark를 포함하라고 지시한다. 각 hit mark에는 충격 프레임, 화면 흔들림, 파편&amp;middot;먼지&amp;middot;스파크&amp;middot;에너지 입자 같은 물리적 피드백이 들어가야 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/cinematic-hit-marking-action-director/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;칼싸움, 총격전, 로봇 전투, 마법 충돌, 차량 충돌, 건물 붕괴, 괴수 타격, 변신 장면처럼 충격 타이밍이 중요한 장면에 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15초 영상을 4~5개 구간으로 나눈다. 각 구간마다 하나의 주요 액션만 부여하고, 충돌이 일어나는 정확한 시간을 지정한다. 타격 순간에는 짧은 정지감, 화면 흔들림, 파편 반응, 피사체의 밀림이나 자세 변화가 필요하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;15초 액션 클립을 hit mark 중심으로 설계해줘.

0.0-3.0초:
두 전사가 폐허가 된 복도에서 서로를 향해 접근한다.
카메라는 낮은 위치에서 handheld tracking.

3.2초 hit mark:
검과 방패가 정면 충돌한다.
충격 프레임에서 0.1초간 물리적 정지감,
짧은 screen shake,
금속 sparks와 먼지 입자가 바깥쪽으로 튄다.

3.3-7.0초:
방패를 든 인물이 오른쪽 뒤로 밀려난다.
카메라는 충격 방향을 따라 recovery drift.

7.8초 hit mark:
검이 콘크리트 바닥을 긁으며 sparks를 만든다.

11.4초 hit mark:
마지막 돌진이 갑옷을 강하게 밀어내고,
카메라는 impact push-in으로 충격을 강조한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;4. cinematic-story-architecture&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;느슨한 아이디어를 영화적 서사 구조로 바꾸는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 이야기 중심의 영상, 트레일러, 숏폼 드라마, 각색 장면, 멀티샷 영상에 사용한다. 원본은 먼저 주인공의 욕망, 장애물, 전환점, 보상 또는 클리프행어를 잠그고, 장면을 설명문이 아니라 실행 가능한 beat로 나누라고 한다. 또한 첫 3초의 강한 후킹과 각 beat마다 의미 있는 상승이 중요하다고 설명한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/cinematic-story-architecture/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이런 장면을 영화처럼 만들어줘&amp;rdquo;라는 아이디어를 구체적인 장면 구조로 바꿀 때 사용한다. 숏폼 드라마, 영화 예고편, 웹드라마 장면, 게임 시네마틱, 브랜드 스토리 영상에도 잘 맞는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 이야기 엔진을 정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주인공은 무엇을 원하는가?&lt;br /&gt;무엇이 그것을 막는가?&lt;br /&gt;어디서 판이 뒤집히는가?&lt;br /&gt;끝은 보상인가, 충격인가, 클리프행어인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 3~7개의 beat로 나누고, 각 beat마다 액션, 감정 변화, 시각적 발견, 카메라 의도를 적는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;mercury&quot;&gt;&lt;code&gt;이 아이디어를 cinematic story architecture로 정리해줘.

장면:
도망치던 여자가 오래된 지하역에서
자신을 쫓던 남자가 사실은 자신을 구하려는 사람이라는 사실을 알게 된다.

구성:
- protagonist desire
- obstacle / pressure
- turning point
- payoff or cliffhanger

그리고 5개의 beat로 나눠줘.
각 beat마다 action, emotional turn, visual revelation, camera intention을 적어줘.
첫 3초 안에 긴장감이 시작되게 하고,
마지막 beat는 다음 장면이 궁금해지는 cliffhanger로 끝내줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;5. commercial-ad-psychology&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;광고의 욕망&amp;middot;신뢰&amp;middot;혜택 구조를 설계하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 광고, 브랜드 필름, 제품 스토리텔링에 사용한다. 원본은 하나의 핵심 약속으로 시작하고, 혜택을 말로 설명하는 데 그치지 말고 시각적으로 보이게 하라고 한다. 또한 모든 샷이 욕망을 만들거나, 의심을 줄이거나, 약속을 증명해야 한다고 규정한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/commercial-ad-psychology/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제품 광고, 앱 광고, 브랜드 캠페인, D2C 제품 영상, 숏폼 광고, 랜딩페이지용 히어로 비디오를 만들 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 광고의 핵심 약속을 하나만 정한다.&lt;br /&gt;&amp;ldquo;더 빠르다&amp;rdquo;, &amp;ldquo;더 조용하다&amp;rdquo;, &amp;ldquo;더 편하다&amp;rdquo;, &amp;ldquo;더 안전하다&amp;rdquo; 같은 메시지를 한 번에 여러 개 넣지 말고, 가장 중요한 하나만 잡는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 장면을 문제 &amp;rarr; 제품 경험 &amp;rarr; 감정적 보상 &amp;rarr; 브랜드 리콜 순서로 구성한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;무선 이어폰 광고 15초를 만들어줘.

핵심 약속:
소음 속에서도 나만의 조용한 공간을 만든다.

구성:
0-3초: 시끄러운 지하철, 주인공이 피로한 표정으로 서 있다.
3-6초: 이어폰을 착용하는 순간 주변 소음이 시각적으로 흐려진다.
6-11초: 주인공의 얼굴이 안정되고, 배경은 부드러운 bokeh로 분리된다.
11-15초: 제품 클로즈업과 함께 한 문장의 브랜드 메시지로 끝난다.

모든 샷은 욕망 형성, 의심 감소, 약속 증명 중 하나의 기능을 갖게 해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;6. continuity-editing-axis-match&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;180도 법칙과 컷 연결을 관리하는 편집 연속성 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 여러 샷을 이어붙일 때 시선 방향, 이동 방향, 액션 축이 무너지지 않도록 돕는다. 원본은 대화&amp;middot;이동&amp;middot;전투 장면에서 axis of action을 정하고, 컷 사이의 screen direction을 유지하라고 한다. 축을 넘어야 할 경우에는 중립 샷, 회전 동선, 의도적 불안정화가 필요하다고 설명한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/continuity-editing-axis-match/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대화 장면, 추격 장면, 액션 장면, 실내 이동 장면, 여러 인물이 얽히는 장면에 사용한다. 특히 AI 영상에서 컷마다 인물 방향이 뒤집히는 문제를 줄이는 데 유용하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 축을 정한다.&lt;br /&gt;예를 들어 A는 왼쪽, B는 오른쪽에 있고 서로 마주 본다.&lt;br /&gt;또는 주인공은 계속 왼쪽에서 오른쪽으로 달린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 컷을 바꿀 때도 이 방향성을 유지한다. 동작 중간에 컷을 붙이는 match-on-action을 사용하면 전환이 자연스러워진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;추격 장면을 continuity editing 기준으로 4샷 구성해줘.

기준축:
주인공은 항상 left-to-right 방향으로 달린다.
추격자는 같은 방향으로 뒤따른다.

Shot 1:
wide shot, 골목 전체 지리감 제시.

Shot 2:
주인공이 문손잡이를 잡는 순간에 cut on motion.
카메라는 established axis를 유지한다.

Shot 3:
문을 밀고 나가는 동작을 tighter framing으로 이어받는다.
몸 방향과 이동 방향은 이전 샷과 동일하다.

Shot 4:
추격자가 같은 문을 통과하며 따라온다.
축을 넘지 않고 screen direction을 유지한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;7. dialogue-performance-blocking&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;대사 장면을 연기와 몸짓 중심으로 설계하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 대화 장면, 감정 연기, 립싱크, 인물 간 권력 변화가 중요한 장면에 사용한다. 원본은 각 대사나 음성 beat마다 인물의 목표, 숨은 의도, 감정 벡터, 몸의 행동, 얼굴 반응을 정의하라고 한다. 또한 모든 대사는 공격, 방어, 폭로, 은폐, 붕괴 중 하나로 기능해야 한다고 강조한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/dialogue-performance-blocking/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 인물의 갈등 장면, 고백 장면, 협박 장면, 법정 장면, 이별 장면, 숏폼 드라마 대사 장면에 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대사를 쓰기 전에 각 인물이 지금 무엇을 원하는지 정한다.&lt;br /&gt;겉으로 하는 말과 실제 의도가 다를 수 있다.&lt;br /&gt;예를 들어 &amp;ldquo;괜찮아&amp;rdquo;라는 대사는 정말 괜찮다는 뜻일 수도 있지만, 분노를 숨기는 방어일 수도 있다.&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;objective: 지금 원하는 것&lt;/li&gt;
&lt;li&gt;subtext: 숨은 뜻&lt;/li&gt;
&lt;li&gt;emotional vector: 감정의 방향&lt;/li&gt;
&lt;li&gt;body behavior: 몸의 행동&lt;/li&gt;
&lt;li&gt;facial behavior: 얼굴 반응&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;두 인물의 대화 장면을 dialogue performance blocking 방식으로 써줘.

상황:
A는 B가 거짓말했다는 사실을 알고 있지만 바로 말하지 않는다.
B는 들키지 않았다고 생각한다.

각 대사마다 다음 항목을 붙여줘:
- objective
- subtext
- emotional vector
- body behavior
- facial behavior

조건:
긴 talking head를 피하고,
각 대사는 attack, defend, reveal, conceal, break 중 하나로 작동하게 해줘.
침묵과 반응 beat도 포함해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;8. director-visual-language&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추상적인 분위기를 구체적인 연출 언어로 바꾸는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 &amp;ldquo;시네마틱하게&amp;rdquo;, &amp;ldquo;고급스럽게&amp;rdquo;, &amp;ldquo;불안하게&amp;rdquo;, &amp;ldquo;웅장하게&amp;rdquo; 같은 추상 표현을 실제 연출 언어로 바꾸는 데 사용한다. 원본은 프레이밍 크기, 앵글, 렌즈감, 카메라 움직임, 조명 논리, 팔레트, 질감 등을 결정해 하나의 일관된 visual language를 만들라고 설명한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/director-visual-language/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감독 노트, 비주얼 디렉션, 콘셉트 아트 지시문, 영상 프롬프트, 광고 무드보드, 뮤직비디오 장면 설계에 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;분위기&amp;rdquo;를 바로 쓰지 말고, 그 분위기가 어떤 시각적 결정으로 구현되는지 적는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 권력감을 표현하려면 low angle, 넓은 공간 점유, 강한 backlight를 사용할 수 있다. 억압감을 표현하려면 프레임을 압축하고, 인물을 문틀이나 그림자 안에 가둘 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;이 장면의 visual language를 감독 노트처럼 만들어줘.

감정:
주인공이 점점 권력을 잃어간다.

연출:
초반에는 eye-level medium shot으로 시작한다.
권력이 흔들릴수록 high angle로 전환한다.
프레임 안에서 주인공을 문틀과 그림자 사이에 가둔다.
렌즈는 compressed perspective를 사용해 공간을 답답하게 만든다.
조명은 차가운 practical light 중심,
shadow density는 점점 깊어진다.
카메라는 느린 push-in으로 압박감을 만든다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;9. environment-scene-extraction-bible&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;장소 자체를 주인공으로 만드는 환경 바이블 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 인물보다 장소, 세계, 로케이션이 중요한 장면에 사용한다. 원본은 환경을 구체적으로 이름 붙이고, 전경&amp;middot;중경&amp;middot;배경&amp;middot;대기, 시간대, 날씨, 빛 방향, 주요 재질을 고정하라고 설명한다. 사람이 없는 환경을 만들 때는 사람, 실루엣, 군중, 애매한 인간 흔적을 명시적으로 제외해야 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/environment-scene-extraction-bible/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배경 콘셉트 아트, 로케이션 바이블, 게임 월드 디자인, 영화 세트 디자인, 사람 없는 폐허 장면, 자연 풍경, 도시 환경을 만들 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장소를 &amp;ldquo;폐허 도시&amp;rdquo;라고만 쓰지 말고, 특정한 이름과 상태를 부여한다.&lt;br /&gt;예를 들어 &amp;ldquo;태풍이 지나간 새벽의 해안 산업도시&amp;rdquo;처럼 시간, 사건, 물성, 날씨를 함께 고정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전경, 중경, 배경을 분리하면 AI가 공간을 더 안정적으로 구성한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;사람 없는 폐허 도시의 environment bible을 만들어줘.

환경 이름:
비가 멈춘 직후의 동부 항구 폐허 도시.

Foreground:
젖은 아스팔트, 부서진 유리 조각, 녹슨 도로 표지판.

Midground:
반쯤 무너진 버스 정류장, 물웅덩이에 반사되는 네온 잔광.

Background:
안개 속에 흐릿하게 보이는 항구 크레인과 고층 건물 실루엣.

Atmosphere:
새벽 직후, 약한 비안개, 북동쪽에서 들어오는 차가운 backlight.

Materials:
젖은 콘크리트, 녹슨 금속, 깨진 유리, 오래된 플라스틱.

No-human rule:
사람, 실루엣, 군중, 신체 일부, 애매한 인간 흔적은 모두 제외.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;10. lighting-continuity-design&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;장면 간 조명 분위기와 대비를 유지하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 단순히 &amp;ldquo;예쁜 조명&amp;rdquo;을 만드는 것이 아니라, 여러 샷 사이에서 조명의 방향과 대비, 분위기가 유지되도록 돕는다. 원본은 1:1~2:1은 부드럽고 개방적인 분위기, 4:1은 드라마틱하지만 읽기 쉬운 분위기, 8:1 이상은 강하고 어둡고 불길한 분위기로 제시한다. 또한 key direction, fill, rim, practical light, 대기 매질을 추적하라고 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/lighting-continuity-design/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티샷 영상, 시퀀스, 광고, 인터뷰, 드라마 장면, 액션 장면, 어두운 실내 장면에서 조명 톤이 컷마다 바뀌는 문제를 줄이고 싶을 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시퀀스 전체의 조명 규칙을 먼저 정한다.&lt;br /&gt;예를 들어 &amp;ldquo;왼쪽 후방 key light, 약한 fill, 4:1 contrast ratio, 공기 중 먼지 haze&amp;rdquo;처럼 기준을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 각 샷에서 이 조명 규칙을 유지할지, 이야기상 바꿀지 명시한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;3샷 시퀀스의 lighting continuity를 설계해줘.

전체 조명 규칙:
4:1 contrast ratio.
왼쪽 후방에서 들어오는 차가운 key light.
오른쪽에는 아주 약한 fill.
얇은 dust haze가 빛을 잡아준다.
배경에는 작은 practical light가 있지만 주광원은 아니다.

Shot 1:
wide shot에서도 같은 key direction 유지.

Shot 2:
medium close-up으로 들어가도 eye-light가 갑자기 밝아지지 않게 한다.

Shot 3:
긴장감이 커지지만 조명이 flat frontal light로 바뀌지 않는다.
shadow density는 유지하고, rim light만 약간 강해진다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;11. long-form-continuity-bible&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;긴 시리즈에서 캐릭터&amp;middot;소품&amp;middot;세계관이 드리프트하지 않게 하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 여러 장면, 여러 에피소드, 시퀄, 연속 생성 작업에서 정체성과 세계 상태를 유지하는 데 사용한다. 원본은 얼굴형, 머리, 실루엣, 의상, 손상 상태, 소품 형태, 장소 배치, 날씨, 시간대, 이동 방향, 렌즈 언어 등을 추적하라고 한다. 또한 새 샷이 이전 샷을 이어갈 때 무엇이 바뀌면 안 되는지 명시해야 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/long-form-continuity-bible/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 웹드라마, 연속 숏폼, 에피소드형 영상, 게임 시네마틱, 캐릭터가 반복 등장하는 이미지 시리즈, 같은 장소에서 이어지는 장면에 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 변하지 않아야 하는 항목을 continuity bible로 정리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 얼굴, 의상, 소품, 손상 상태, 배경 날씨, 색감, 이동 방향 등을 고정한다.&lt;br /&gt;그다음 새 샷을 만들 때 &amp;ldquo;이전 샷에서 이어받아야 할 상태&amp;rdquo;와 &amp;ldquo;이번 샷에서만 바뀌는 상태&amp;rdquo;를 분리한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;이 시리즈를 위한 long-form continuity bible을 만들어줘.

Character continuity:
HERO_01은 날카로운 턱선, 짧은 검은 머리, 왼쪽 눈 아래 작은 흉터를 유지한다.
의상은 흰색 롱코트, 오른쪽 소매가 찢어진 상태.
왼손에는 금속 장갑을 착용한다.

Prop continuity:
SWORD_01은 검은 손잡이, 은색 칼날, 푸른 빛이 약하게 도는 금속 재질.
항상 오른손 또는 오른쪽 허리 쪽에 위치한다.

Location continuity:
비 오는 골목, 젖은 벽돌, 푸른 backlight, 낮은 안개.
시간대는 밤.

Motion continuity:
주인공은 이전 샷에서 left-to-right로 달리던 상태를 이어간다.

Do not change:
얼굴, 코트 실루엣, 소매 손상, 장갑 위치, 비 오는 날씨, 푸른 조명 톤.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;12. modular-film-prompt-bible&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;영화형 프롬프트를 모듈로 나누는 핵심 템플릿 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 단일 프롬프트보다 더 강력한 &amp;ldquo;창작 바이블 + 샷 실행 지시&amp;rdquo; 구조를 만든다. 원본은 프롬프트를 identity lock, world and genre lock, medium and realism lock, sound policy, per-shot execution, continuity carryover 순서로 작성하라고 제시한다. 또한 {{Portrait 1}}, {{Scene 1}}, @image 1, @video 1 같은 레퍼런스 플레이스홀더를 지원하는 구조로 설계되어 있다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/modular-film-prompt-bible/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 영상 프로젝트, 캐릭터가 반복 등장하는 작업, 레퍼런스 이미지 기반 영상, 영화식 콘셉트 아트, 시리즈형 프롬프트, 고정 세계관이 필요한 생성 작업에서 가장 범용적으로 사용할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트를 한 문단으로 쓰지 않는다.&lt;br /&gt;먼저 고정되어야 하는 세계관과 정체성을 잠근다.&lt;br /&gt;그다음 현재 샷에서만 일어나는 변화와 동작을 적는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 특히 &amp;ldquo;매번 다시 설명하다가 캐릭터가 바뀌는 문제&amp;rdquo;를 줄이는 데 유용하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;아래 콘셉트를 modular film prompt bible 형식으로 만들어줘.

Core premise:
전쟁 이후의 사막 도시에서,
망가진 전투 로봇과 어린 정비사가 함께 탈출한다.

Recurring references:
@image 1 = 어린 정비사 identity reference
@image 2 = 전투 로봇 identity reference
@image 3 = 사막 도시 world reference

Identity lock:
정비사의 얼굴형, 의상 실루엣, 공구 가방, 먼지 묻은 피부 질감 고정.
로봇의 머리 형태, 금속 재질, 파손된 왼쪽 어깨, 붉은 LED 눈 고정.

World and genre lock:
사막화된 atompunk 도시.
먼지, 낡은 금속, 태양에 바랜 간판, 아날로그 계기판.

Medium and realism lock:
premium cinematic CG with film behavior.
플라스틱 같은 표면, 게임풍 렌더, 무중력 움직임은 피한다.

Sound policy:
BGM 없이 현장음, 발소리, 금속 마찰음, 먼지바람 소리만 사용.

Shot 1:
objective / framing / camera / action / sound / continuity 순서로 작성.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;13. reference-driven-video-prompting&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이미지&amp;middot;영상 레퍼런스를 기반으로 움직임을 설계하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 이미지 투 비디오, 비디오 연장, 키프레임 기반 프롬프트, 카메라 제어, 레퍼런스 기반 일관성 유지에 사용한다. 원본은 입력 이미지가 있을 때 이미지를 다시 길게 설명하기보다 원하는 움직임과 카메라 행동에 집중하라고 한다. 또한 identity reference, world/location reference, previous formal shot continuity, style reference, motion prompt 순서의 우선순위를 제시한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/reference-driven-video-prompting/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지를 영상으로 만들 때, 이전 영상을 이어붙일 때, 특정 캐릭터 얼굴이나 장소 분위기를 유지하고 싶을 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레퍼런스가 있다면 텍스트에서 이미지를 반복 설명하지 않는다.&lt;br /&gt;대신 &amp;ldquo;무엇이 움직이는가&amp;rdquo;, &amp;ldquo;카메라는 어떻게 반응하는가&amp;rdquo;, &amp;ldquo;첫 프레임에서 마지막 프레임까지 무엇이 변하는가&amp;rdquo;를 쓴다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@image 1의 캐릭터 정체성은 그대로 유지해줘.
이미지 속 얼굴, 머리, 의상 실루엣은 바꾸지 않는다.

텍스트에서는 이미지를 다시 설명하지 말고
움직임과 카메라만 지시한다.

Motion:
캐릭터는 천천히 앞으로 걸어온다.
무거운 코트를 입고 있어 움직임은 절제되어 있다.
마지막 2초에 표정이 굳고 시선이 카메라를 향한다.

Camera:
카메라는 캐릭터가 다가올 때 천천히 뒤로 물러난다.
마지막에는 medium close-up으로 부드럽게 push-in한다.

Continuity:
identity, costume silhouette, lighting palette는 @image 1과 일치해야 한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;14. scene-blocking-and-staging&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정적인 장면을 공간 안의 행동으로 바꾸는 블로킹 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 인물의 위치, 거리, 접근, 후퇴, 정지, 전경과 배경의 관계를 설계할 때 사용한다. 원본은 인물이 움직이는 이유가 목표, 권력, 공포, 발견, 긴급함의 변화와 연결되어야 한다고 한다. AI 영상에서는 subject path와 camera path를 분리해서 설명해야 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/scene-blocking-and-staging/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대화 장면, 실내 갈등 장면, 군중 장면, 액션 전 긴장 장면, 인물 간 권력관계를 시각적으로 보여주고 싶을 때 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인물을 그냥 &amp;ldquo;서 있다&amp;rdquo;고 쓰지 않는다.&lt;br /&gt;누가 공간을 장악하고 있는지, 누가 갇혀 있는지, 누가 접근하고 누가 물러나는지를 정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로킹은 감정 변화와 함께 바뀌어야 한다.&lt;br /&gt;상대가 진실을 말하는 순간 한 인물이 한 걸음 물러난다면, 그 움직임 자체가 권력 변화가 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;대화 장면을 scene blocking 중심으로 설계해줘.

공간:
작은 사무실. 문은 화면 왼쪽, 책상은 중앙, 창문은 오른쪽 뒤.

A:
문가에 서서 출구를 막고 있다.
처음에는 공간을 장악한 인물이다.

B:
책상 뒤에 앉아 있으며 움직일 공간이 제한되어 있다.

Beat 1:
A는 문가에서 움직이지 않는다.
B는 책상 위 컵을 만지며 불안을 숨긴다.

Beat 2:
B가 진실을 말하는 순간 A가 한 걸음 뒤로 물러난다.
권력 균형이 바뀐다.

Subject path:
B는 앉은 상태에서 천천히 일어난다.

Camera path:
카메라는 B의 감정 변화에 맞춰 천천히 push-in한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;15. screenplay-fountain-format&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시나리오를 Fountain 문법으로 구조화하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 시나리오, 장면 대본, 대사, beat outline을 Fountain 문법에 맞게 작성할 때 사용한다. 원본은 INT., EXT., INT./EXT. 같은 장면 제목, 대문자 캐릭터 큐, 대사, 절제된 parenthetical, 화면화 가능한 action block을 사용하라고 설명한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/screenplay-fountain-format/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영화 대본, 숏폼 드라마 대본, AI 영상용 스크립트, 스토리보드 전 단계의 장면 대본을 만들 때 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소설처럼 내면을 길게 설명하지 않는다.&lt;br /&gt;카메라가 볼 수 있는 행동만 쓴다.&lt;br /&gt;대사는 캐릭터 이름 아래에 배치하고, 장소와 시간 변화가 있으면 명확한 scene heading을 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;아래 장면을 Fountain screenplay format으로 작성해줘.

조건:
- 장면 제목은 INT. UNDERGROUND STATION - NIGHT
- 캐릭터 이름은 대문자
- 액션은 화면에 보이는 행동만 쓴다
- parenthetical은 꼭 필요한 경우에만 사용한다
- 내면 묘사나 소설적 설명은 피한다

장면:
여자가 빈 지하역에서 도망치다가
자신을 쫓던 남자와 마주친다.
남자는 그녀를 해치려는 것이 아니라
폭발 직전의 플랫폼에서 구하려고 한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;16. sd2-pe&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Seedance 2.0 영상 생성을 위한 프롬프트 엔지니어링 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 Seedance 2.0 스타일의 영상 생성, 이미지 투 비디오, 비디오 투 비디오 연장, 멀티모달 레퍼런스 매핑에 사용한다. 원본은 입력 비디오를 순서대로 @video 1, @video 2, @video 3으로, 입력 이미지를 @image 1, @image 2, @image 3으로 정확히 매핑하라고 한다. 이전 영상을 이어갈 때는 @video 1을 반복하지 말고 마지막 프레임 상태, 스토리 상태, 카메라 움직임, 액션 모멘텀, 조명, 사운드를 이어가야 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/sd2-pe/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Seedance 2.0에 이미지나 영상을 넣고 후속 장면을 만들 때, 15초 영상을 time-slice로 구성할 때, 이전 영상을 자연스럽게 연장하고 싶을 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 모든 입력 자산을 정확히 매핑한다.&lt;br /&gt;그다음 15초 영상을 시간 구간으로 나누고, 각 구간에 액션, 카메라, 연기, 대사, 사운드를 배치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비디오 연장에서는 &amp;ldquo;이전 영상을 다시 보여주지 말 것&amp;rdquo;을 명확히 써야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Seedance 2.0용 프롬프트로 변환해줘.

Reference binding:
@video 1 = 이전 장면의 tail 영상.
@image 1 = 주인공 identity reference.
@image 2 = 장소 reference.

V2V extension rule:
새 영상은 @video 1의 마지막 프레임 상태에서 이어진다.
@video 1을 반복하거나 처음부터 재시작하지 않는다.
마지막 프레임의 카메라 방향, 조명, 인물 시선, 이동 momentum을 유지한다.

15-second storyboard:
0-3초: 주인공이 멈춰 서고 숨을 고른다.
3-6초: 뒤쪽에서 낮은 금속음이 들린다.
6-9초: 주인공이 천천히 돌아본다.
9-12초: 카메라가 얼굴로 push-in한다.
12-15초: 어둠 속 붉은 빛이 켜지며 cliffhanger로 끝난다.

Quality constraints:
identity drift, costume change, lighting reset, repeated previous action을 피한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;17. short-drama-hook-engineering&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;숏폼 드라마의 첫 1~3초를 설계하는 후킹 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 숏폼 드라마, 트레일러, 릴스&amp;middot;쇼츠형 영상처럼 빠르게 관심을 잡아야 하는 콘텐츠에 사용한다. 원본은 첫 1~3초 안에 갈등, 위험, 고발, 반전, 욕망, 충격, 불안정한 감정을 제시해야 한다고 설명한다. 또한 각 클립은 hook, escalation, exit bridge 구조를 가져야 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/short-drama-hook-engineering/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹드라마 쇼츠, 릴스 드라마, 틱톡 드라마, 예고편, 짧은 바이럴 영상, 강한 시작이 필요한 광고성 콘텐츠에 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설명으로 시작하지 않는다.&lt;br /&gt;가장 강한 행동, 고발, 위기, 반전에서 바로 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;그날은 평범한 날이었다&amp;rdquo;보다&lt;br /&gt;&amp;ldquo;네가 내 아버지를 죽였지?&amp;rdquo;가 훨씬 강한 시작이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 2초마다 감정 변화, 반응, 폭로, 권력 이동이 보이도록 구성하면 리텐션이 좋아진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;30초 숏폼 드라마를 short drama hook 구조로 설계해줘.

첫 2초:
여자가 남자의 멱살을 잡고 말한다.
&amp;ldquo;네가 내 아버지를 죽였지?&amp;rdquo;

구성:
0-2초: 강한 고발로 시작.
2-6초: 남자는 부정하지만 눈을 피한다.
6-10초: 여자가 오래된 사진을 꺼낸다.
10-16초: 남자의 표정이 무너지고 권력관계가 바뀐다.
16-24초: 남자는 더 큰 비밀을 암시한다.
24-30초: 문 밖에서 누군가 같은 사진을 들고 서 있다.

마지막은 다음 편을 보게 만드는 exit bridge로 끝내줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;18. shot-size-and-angle-language&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;샷 사이즈와 카메라 앵글을 정확하게 쓰는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 스토리보드나 프롬프트에서 샷 크기와 앵글을 정확히 지정할 때 사용한다. 원본은 ECU, CU, MCU, MS, MFS/MW, FS, WS/LS, EWS 같은 표준 샷 약어와 low angle, high angle, eye level, overhead, canted angle의 기능을 정리한다. 또한 샷 크기 변화는 정보 우선순위를 바꾸기 위해 사용해야 한다고 설명한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/shot-size-and-angle-language/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샷리스트, 스토리보드, 영화 프롬프트, 광고 컷 구성, 이미지 생성 프롬프트에서 프레이밍을 정밀하게 통제하고 싶을 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장면의 목적에 따라 샷 크기를 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;극단적 클로즈업은 미세 표정이나 사물의 중요성을 보여준다.&lt;br /&gt;와이드샷은 몸의 행동, 공간 관계, 위협의 규모를 보여준다.&lt;br /&gt;익스트림 와이드는 고립감이나 세계의 규모를 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앵글도 목적이 있어야 한다.&lt;br /&gt;low angle은 힘과 위협, high angle은 취약함, overhead는 전술적 관계나 무력감을 보여준다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;이 장면을 shot size와 angle 중심으로 재설계해줘.

Beat 1:
EWS, 폐허 도시 속에 홀로 선 주인공.
목적: 고립감과 세계의 규모 제시.

Beat 2:
MS, 주인공이 무너진 문 앞에서 멈춘다.
목적: 행동과 공간 관계 제시.

Beat 3:
CU, 주인공의 눈이 흔들린다.
목적: 깨달음과 공포 표현.

Beat 4:
ECU, 손 안의 작은 열쇠가 떨린다.
목적: 사물의 중요성 강조.

Beat 5:
low angle MCU, 주인공이 결심하고 고개를 든다.
목적: 권력과 결심의 회복.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;19. storyboard-shot-design&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;아이디어를 샷별 스토리보드로 바꾸는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 아이디어를 실제로 생성 가능한 샷 리스트로 바꿀 때 사용한다. 원본은 각 샷마다 샷 번호, 길이 의도, 피사체 초점, 프레이밍, 카메라 위치와 움직임, 화면 안 액션, 감정 목적, 이전 샷과의 연결, 다음 샷으로 넘어가는 압력을 정의하라고 한다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/storyboard-shot-design/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15초 영상, 30초 광고, 뮤직비디오 장면, 숏폼 드라마, 영화 예고편, AI 영상 제작용 샷리스트를 만들 때 가장 직접적으로 활용할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 샷은 반드시 역할이 있어야 한다.&lt;br /&gt;새로운 정보, 더 강한 감정, 더 명확한 행동 중 하나를 제공해야 한다.&lt;br /&gt;같은 구도의 반복은 의도된 리듬이 아니라면 피한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;아래 장면을 6샷 storyboard로 만들어줘.

장면:
한 남자가 새벽의 옥상에서
도시 전체가 정전되는 순간을 목격한다.

각 샷에 다음 항목을 포함해줘:
- shot number
- duration intent
- subject focus
- framing
- camera position and movement
- action inside frame
- emotional purpose
- continuity link from previous shot
- transition pressure into next shot

조건:
각 샷은 새로운 정보, 더 강한 감정, 더 명확한 행동 중 하나를 제공해야 한다.
모든 샷을 generic hero shot으로 만들지 말아줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;20. world-asset-identity-lock&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;반복 등장하는 캐릭터&amp;middot;소품&amp;middot;세계관의 정체성을 고정하는 스킬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스킬은 반복 등장하는 캐릭터, 소품, 생물, 의상, 환경이 계속 같은 정체성을 유지하도록 만드는 데 사용한다. 원본은 stable ID를 부여하고, 변하지 않는 immutable traits와 샷별로 달라질 수 있는 행동을 분리하라고 한다. 얼굴, 실루엣, 의상 논리, 재질 반응, 팔레트, 행동 시그니처를 고정하는 것이 핵심이다. (&lt;a href=&quot;https://raw.githubusercontent.com/nolanx-ai/nolanx.ai/main/skills/world-asset-identity-lock/SKILL.md&quot;&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 캐릭터를 여러 장면에서 반복 생성할 때, 같은 무기나 소품이 계속 등장할 때, AI 영상에서 인물 얼굴이나 의상이 매번 바뀌는 문제를 줄이고 싶을 때 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 등장 요소마다 ID를 부여한다.&lt;br /&gt;예를 들어 HERO_01, SWORD_01, CITY_01처럼 이름을 붙인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 변하지 않는 특성과 장면마다 달라지는 행동을 분리한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 프롬프트&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;주인공, 검, 사막 도시를 world asset identity lock으로 정리해줘.

HERO_01:
Immutable traits:
날카로운 턱선, 짧은 검은 머리, 왼쪽 눈 아래 작은 흉터.
흰색 롱코트, 오른쪽 소매가 찢어진 상태.
걸을 때 오른쪽 어깨가 약간 낮게 움직이는 습관.

Variable behavior:
이번 샷에서는 천천히 뒤돌아본다.
다음 샷에서는 달리기 시작한다.

SWORD_01:
Immutable traits:
검은 손잡이, 은색 칼날, 푸른 금속 반사.
길이는 주인공 팔보다 약간 길다.
항상 오른쪽 허리 쪽에 찬다.

CITY_01:
Immutable traits:
사막화된 도시, 녹슨 금속 구조물, 바랜 노란 간판, 먼지바람.
색감은 황토색과 청회색 중심.

Do not change:
캐릭터 얼굴, 코트 실루엣, 검의 크기, 도시 팔레트.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;20개 스킬을 실제 작업에서 조합하는 법&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 20개 스킬은 하나씩 써도 좋지만, 실제 제작에서는 여러 개를 조합할 때 훨씬 강력하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 캐릭터가 반복 등장하는 AI 영상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추천 조합:&lt;/p&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;world-asset-identity-lock
long-form-continuity-bible
modular-film-prompt-bible
storyboard-shot-design
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 예시:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;반복 등장하는 캐릭터가 있는 5개 샷짜리 AI 영상 프롬프트를 만들어줘.

먼저 world asset identity lock으로
캐릭터, 의상, 소품, 장소를 고정해줘.

그다음 long-form continuity bible로
얼굴, 실루엣, 손상 상태, 조명, 팔레트, 이동 방향을 정리해줘.

마지막으로 storyboard-shot-design 방식으로
각 샷의 objective, framing, camera, action, emotion, continuity link를 작성해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 15초 액션 영상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추천 조합:&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;action-choreography-camera-logic
cinematic-hit-marking-action-director
continuity-editing-axis-match
lighting-continuity-design
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 예시:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;15초 액션 영상을 설계해줘.

조건:
- 좌우 이동 방향과 공격 방향 유지
- 15초를 5개 time slice로 분리
- 충돌 순간은 0.1초 단위 hit mark로 지정
- 각 hit mark에는 impact frame, screen shake, particle ejection 포함
- 카메라 움직임은 각 구간마다 하나의 목적만 갖게 한다
- 조명 방향과 contrast ratio는 컷 사이에서 유지
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 숏폼 드라마&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추천 조합:&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;short-drama-hook-engineering
cinematic-story-architecture
dialogue-performance-blocking
shot-size-and-angle-language
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 예시:&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;30초 숏폼 드라마를 만들어줘.

첫 1-3초 안에 강한 갈등으로 시작해줘.
전체 구조는 hook, escalation, exit bridge로 구성해줘.

각 beat마다:
- action
- emotional turn
- visual revelation
- camera intention

각 대사마다:
- objective
- subtext
- emotional vector
- body behavior
- facial behavior

샷 크기는 감정 변화에 맞춰 ECU, CU, MCU, WS를 선택해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 이미지 레퍼런스 기반 영상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추천 조합:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;reference-driven-video-prompting
sd2-pe
world-asset-identity-lock
director-visual-language
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 예시:&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@image 1을 캐릭터 identity reference로 사용하고,
@image 2를 location reference로 사용해줘.

이미지 자체를 다시 설명하지 말고
움직임, 카메라, 조명 변화, 마지막 프레임 상태만 작성해줘.

Seedance 2.0용으로:
- reference binding
- global asset lock
- 15-second time-sliced storyboard
- per-slice action / camera / performance / sound
- continuity instruction
- quality constraints

순서로 정리해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;가장 범용적인 기본 템플릿&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 복잡하게 모든 스킬을 쓸 필요는 없다.&lt;br /&gt;가장 실용적인 기본 조합은 다음 세 가지다.&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;modular-film-prompt-bible
world-asset-identity-lock
storyboard-shot-design
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 조합은 먼저 &lt;b&gt;세계관과 정체성을 고정&lt;/b&gt;하고, 그다음 &lt;b&gt;샷별 실행 지시&lt;/b&gt;로 내려가기 때문에 이미지&amp;middot;영상 생성 결과가 덜 흔들린다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;복사해서 쓰는 기본 템플릿&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;아래 아이디어를 AI 영상 제작용 film prompt bible로 정리해줘.

1. Core premise
이 영상의 핵심 상황과 감정 목적을 한 문장으로 정리해줘.

2. World asset identity lock
반복 등장하는 캐릭터, 소품, 장소에 stable ID를 부여해줘.
각 asset마다 immutable traits와 variable behavior를 분리해줘.

3. World and genre lock
장소, 시대, 장르, 팔레트, 재질, 날씨, 조명 논리를 고정해줘.

4. Medium and realism lock
실사풍, 영화적 CG, 35mm 장르 영화, 광고 룩 등 하나의 매체 논리를 선택해줘.
피해야 할 렌더링 오류도 적어줘.

5. Sound policy
BGM 사용 여부, 현장음, Foley, 대사, 주변음을 정리해줘.

6. Storyboard shot design
각 샷마다 다음 항목을 작성해줘:
- shot number
- duration intent
- objective
- subject focus
- framing
- camera position and movement
- action inside frame
- emotional purpose
- sound
- continuity link
- transition pressure into next shot

7. Continuity carryover
다음 샷에서도 반드시 유지되어야 할 얼굴, 의상, 소품, 손상 상태, 조명, 팔레트, 이동 방향을 정리해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;마무리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 영상 프롬프트에서 가장 흔한 실패는 &amp;ldquo;멋있지만 일관성 없는 결과&amp;rdquo;다.&lt;br /&gt;캐릭터 얼굴이 바뀌고, 카메라 동선이 모순되고, 조명이 컷마다 달라지고, 액션 방향이 뒤집히고, 장면의 감정 목적이 흐려진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NolanX AI의 20개 스킬은 이런 문제를 해결하기 위한 제작 언어를 제공한다.&lt;br /&gt;핵심은 간단하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트를 감성어로만 쓰지 말고,&lt;br /&gt;&lt;b&gt;정체성, 세계관, 카메라, 조명, 동선, 편집, 사운드, 감정 beat&lt;/b&gt;로 나눠서 쓰는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 좋은 영상을 만들게 하려면,&lt;br /&gt;먼저 사람이 좋은 연출 구조를 줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처&lt;/p&gt;
&lt;figure id=&quot;og_1779158464793&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;nolanx.ai/skills at main &amp;middot; nolanx-ai/nolanx.ai&quot; data-og-description=&quot;Nolanx, Open-sourced AI Netflix. Contribute to nolanx-ai/nolanx.ai development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/nolanx-ai/nolanx.ai/tree/main/skills&quot; data-og-url=&quot;https://github.com/nolanx-ai/nolanx.ai/tree/main/skills&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bK9oeG/dJMb9hC6IyA/Zly8hzF9iIOwwKVe73fKak/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b4x1rQ/dJMb83SotTW/kGUEXKAM59DRBQuLJ1DThk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/nolanx-ai/nolanx.ai/tree/main/skills&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/nolanx-ai/nolanx.ai/tree/main/skills&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bK9oeG/dJMb9hC6IyA/Zly8hzF9iIOwwKVe73fKak/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b4x1rQ/dJMb83SotTW/kGUEXKAM59DRBQuLJ1DThk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;nolanx.ai/skills at main &amp;middot; nolanx-ai/nolanx.ai&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Nolanx, Open-sourced AI Netflix. Contribute to nolanx-ai/nolanx.ai development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Seedance2</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1760</guid>
      <comments>https://javaexpert.tistory.com/1760#entry1760comment</comments>
      <pubDate>Tue, 19 May 2026 11:33:11 +0900</pubDate>
    </item>
    <item>
      <title>GPT 이미지 프롬프트를 어떻게 하면 잘 만들수 있을까?</title>
      <link>https://javaexpert.tistory.com/1759</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;GPT 이미지 프롬프트 개선기를 만들며 정리한 것들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘은 누구나 AI로 이미지를 만들 수 있습니다.&lt;br /&gt;하지만 막상 원하는 이미지를 만들려고 하면 생각보다 결과가 잘 나오지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;예쁘게 만들어줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;고급스럽게 만들어줘.&amp;rdquo;&lt;br /&gt;&amp;ldquo;감성적인 썸네일 만들어줘.&amp;rdquo;&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;br /&gt;AI에게는 &amp;ldquo;예쁘게&amp;rdquo;라는 말보다 &lt;b&gt;무엇을 어떻게 보여줄지&lt;/b&gt;가 훨씬 중요하기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 생성 프롬프트는 주문서라기보다 &lt;b&gt;디자인 디렉션&lt;/b&gt;에 가깝습니다.&lt;br /&gt;그래서 좋은 이미지를 만들기 위해서는 막연한 감상어보다 구체적인 시각 정보를 알려줘야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;좋은 프롬프트는 &amp;ldquo;예쁘게&amp;rdquo;가 아니라 &amp;ldquo;어떻게&amp;rdquo;를 말한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람이 처음에는 이렇게 요청합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;예쁜 화장품 이미지 만들어줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이 말도 틀린 것은 아닙니다.&lt;br /&gt;하지만 AI 입장에서는 너무 모호합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예쁜 게 어떤 느낌인지 알 수 없습니다.&lt;br /&gt;밝고 귀여운 이미지인지, 고급스러운 백화점 광고 느낌인지, 미니멀한 브랜드 사진인지, 감성적인 인스타그램 피드 이미지인지 방향이 불분명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 더 좋은 프롬프트는 이런 식입니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;무광 아이보리 세럼 병을 베이지 스톤 받침대 위에 올려줘.
부드러운 자연광이 왼쪽 위에서 들어오고,
크림 톤 배경에 상단에는 제목을 넣을 수 있는 여백을 남겨줘.
텍스트는 넣지 말고, 워터마크와 로고도 없게 해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 쓰면 이미지의 방향이 훨씬 분명해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 감성적인 말보다 &lt;b&gt;눈에 보이는 단어&lt;/b&gt;를 쓰는 것입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;이미지 프롬프트는 이 순서로 쓰면 쉽다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트를 잘 쓰고 싶다면 매번 처음부터 고민할 필요가 없습니다.&lt;br /&gt;아래 구조를 템플릿처럼 사용하면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;Purpose:
이미지를 어디에 쓸 것인가?

Scene:
어떤 배경과 상황인가?

Main subject:
무엇이 중심 피사체인가?

Style:
어떤 스타일과 무드인가?

Composition:
어떤 구도, 비율, 여백인가?

Lighting:
어떤 조명과 분위기인가?

Text:
이미지 안에 글자를 넣을 것인가?

Constraints:
피해야 할 것과 반드시 유지할 것은 무엇인가?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조만 기억해도 프롬프트 품질이 훨씬 좋아집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;릴스 썸네일&amp;rdquo;이라면 목적은 인스타그램 릴스 커버입니다.&lt;br /&gt;그러면 세로 비율이 필요하고, 제목을 넣을 여백도 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;유튜브 썸네일&amp;rdquo;이라면 가로 16:9 비율이 적합합니다.&lt;br /&gt;주제가 한눈에 보여야 하고, 제목을 넣을 공간이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;랜딩페이지 히어로 이미지&amp;rdquo;라면 웹사이트 첫 화면에 들어갈 이미지이므로, 왼쪽이나 오른쪽에 카피와 버튼이 들어갈 여백이 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 &lt;b&gt;사용 목적이 정해지면 구도도 자연스럽게 정해집니다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;추상적인 말은 구체적인 시각 요소로 바꿔야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 이미지 생성에서 자주 쓰지만 결과가 흔들리는 말들이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;예쁜
고급스러운
감성적인
깔끔한
세련된
멋진
힙한
&lt;/code&gt;&lt;/pre&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;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;무광 아이보리 질감
베이지 스톤 받침대
부드러운 확산광
크림 톤 배경
넓은 여백
미니멀 럭셔리 브랜딩
얕은 심도
따뜻한 림 라이트
정면 중앙 구도
세로 4:5 비율
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &amp;ldquo;고급스럽게&amp;rdquo;라고 쓰기보다&lt;br /&gt;&amp;ldquo;무광 질감, 베이지 톤, 부드러운 그림자, 여백이 많은 미니멀 제품 사진&amp;rdquo;이라고 쓰는 편이 훨씬 안정적입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;구도는 반드시 써야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트에서 많이 빠지는 부분이 바로 구도입니다.&lt;br /&gt;하지만 구도는 이미지의 완성도를 크게 좌우합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이런 표현을 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;subject centered
negative space on the left
top-down view
vertical 4:5
close-up
wide shot
low angle
eye-level view
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어로 풀면 이런 뜻입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;피사체를 중앙에 배치
왼쪽에 넓은 여백
위에서 내려다본 시점
세로 4:5 비율
클로즈업
와이드샷
로우앵글
눈높이 시점
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 썸네일이나 광고 이미지는 여백이 중요합니다.&lt;br /&gt;나중에 제목이나 설명 문구를 넣어야 하기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 릴스 썸네일을 만들 때는 이런 지시가 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;Vertical 4:5 ratio, generous negative space at the top center for a headline.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뜻은 간단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;세로 4:5 비율로 만들고, 상단 중앙에는 제목을 넣을 수 있는 넓은 여백을 남겨줘.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 한 문장만 넣어도 썸네일로 쓰기 훨씬 좋아집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;텍스트는 넣을지 말지 명확히 정해야 한다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 생성 모델은 글자 표현에서 실수할 때가 많습니다.&lt;br /&gt;그래서 이미지 안에 정확한 문구가 꼭 필요한 경우가 아니라면, 처음에는 텍스트 없이 만드는 것이 안전합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Text:
No text.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 명확히 쓰면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 글자를 넣어야 한다면 짧게 쓰는 것이 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;Text:
Add the exact Korean title &amp;ldquo;오늘의 나를 입어&amp;rdquo; at the top center in bold clean sans-serif typography.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 제약에도 한 번 더 적어줍니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Constraints:
No misspelled text, no extra letters, no watermark, no logo.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 실제 작업에서는 이미지를 먼저 만들고, 글자는 캔바, 포토샵, 피그마, 캡컷 등에서 따로 넣는 방식이 더 안정적입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;수정할 때는 &amp;ldquo;바꿀 것&amp;rdquo;보다 &amp;ldquo;유지할 것&amp;rdquo;이 중요하다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지를 수정할 때 많은 사람이 이렇게 말합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;배경을 바꿔줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이렇게만 쓰면 인물의 얼굴, 옷, 포즈, 조명까지 함께 바뀔 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정 프롬프트에서는 반드시 유지할 것을 적어야 합니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Change only:
Replace the background with a warm beige studio setting.

Keep the same:
Keep the person&amp;rsquo;s face, expression, pose, outfit, camera angle, lighting direction, and body proportions exactly the same.

New direction:
Make the background clean, minimal, premium, and softly lit.

Constraints:
No face changes, no pose changes, no outfit changes, no extra people, no watermark, no logo.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어로 쓰면 이렇게 됩니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;배경만 따뜻한 베이지 스튜디오로 변경해줘.

인물의 얼굴, 표정, 포즈, 옷, 카메라 각도, 조명 방향, 신체 비율은 그대로 유지해줘.

배경은 깨끗하고 미니멀하며 부드럽게 조명된 프리미엄 분위기로 만들어줘.

얼굴 변경 없음, 포즈 변경 없음, 의상 변경 없음, 추가 인물 없음, 워터마크 없음, 로고 없음.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정 프롬프트의 핵심 공식은 간단합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;Change only X.
Keep everything else the same.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &amp;ldquo;무엇을 바꿀지&amp;rdquo;보다 &amp;ldquo;무엇을 바꾸면 안 되는지&amp;rdquo;가 더 중요합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;좋은 이미지는 한 번에 완성되지 않는다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 이미지 작업을 할 때 처음부터 완벽한 결과를 기대하면 오히려 답답해집니다.&lt;br /&gt;복잡한 이미지는 단계적으로 만드는 편이 더 안정적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추천하는 순서는 이렇습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 기본 장면 생성
2. 조명 수정
3. 구도 수정
4. 색감 보정
5. 불필요한 요소 제거
6. 최종 제약 정리
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 모든 것을 해결하려고 하지 말고, 먼저 좋은 기본 장면을 만든 뒤 하나씩 다듬는 방식이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 처음에는 이렇게 요청합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;먼저 기본 장면을 만들어줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 조명을 수정합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;조명을 더 부드러운 베이지 톤으로 바꿔줘.
구도와 인물 포즈는 그대로 유지해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 작업하면 결과가 훨씬 안정적입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;그래서 GPT 프롬프트 개선기가 필요하다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 매번 사람이 직접 하기는 번거롭습니다.&lt;br /&gt;그래서 &amp;ldquo;GPT 이미지 프롬프트 개선기&amp;rdquo;를 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 GPT의 역할은 단순합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 대충 말한 요청을 받아서,&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;화장품 이미지 예쁘게 만들어줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 구조화된 프롬프트로 바꿔주는 것입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;Purpose:
Premium skincare product promotional image for social media.

Scene:
A clean beige studio setup with a matte stone pedestal and a soft cream background.

Main subject:
A matte ivory serum bottle placed upright on the pedestal, with subtle clean reflections.

Style:
Photorealistic product photography, minimal luxury skincare branding, soft neutral color palette, premium editorial mood.

Composition:
Vertical 4:5 ratio, product centered in the lower half, generous negative space at the top for a headline, shallow depth of field.

Lighting:
Soft diffused daylight from the upper left, gentle shadows, warm beige tone, subtle highlight on the bottle edge.

Text:
No text.

Constraints:
No watermark, no logo, no distorted bottle, no duplicate products, no messy background, no random text.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 이미지를 잘 만들기 위해 모든 원칙을 외울 필요가 없습니다.&lt;br /&gt;프롬프트 개선기가 대신 목적, 장면, 스타일, 구도, 조명, 제약을 정리해주면 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;GPT 이미지 프롬프트 개선기의 기본 역할&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 GPT는 다음과 같은 일을 해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;막연한 요청을 구체적인 시각 디렉션으로 바꾼다.
용도에 맞는 이미지 비율을 추천한다.
구도와 여백을 자동으로 보강한다.
조명과 색감을 구체화한다.
텍스트 여부를 명확히 정리한다.
워터마크, 로고, 왜곡 같은 문제를 막는 제약을 추가한다.
수정 요청에서는 유지할 요소를 명확히 적는다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 것은 프롬프트를 무조건 길게 만드는 것이 아닙니다.&lt;br /&gt;길지만 방향이 없는 프롬프트보다, 짧아도 명확한 프롬프트가 더 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트 개선기는 사용자의 말을 &amp;ldquo;화려하게 꾸미는 도구&amp;rdquo;가 아니라,&lt;br /&gt;이미지 생성 모델이 이해하기 쉬운 &lt;b&gt;디자인 작업 지시서&lt;/b&gt;로 바꿔주는 도구입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;바로 쓸 수 있는 기본 템플릿&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 프롬프트 개선기를 만들 때는 아래 구조를 기본 출력값으로 설정하면 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;[프롬프트 진단]
- 사용 목적:
- 핵심 피사체:
- 추천 비율:
- 추천 스타일:
- 구도 방향:
- 보완한 요소:

[개선된 최종 프롬프트]
Purpose:
Scene:
Main subject:
Style:
Composition:
Lighting:
Text:
Constraints:
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 사용자는 왜 이렇게 바뀌었는지 이해할 수 있고, 바로 복사해서 이미지 생성에 사용할 수도 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;용도별 기본값도 필요하다&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 개선기가 더 똑똑하게 동작하려면 용도별 기본값을 가지고 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 릴스 썸네일이면,&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;세로 4:5 비율
상단 중앙에 제목용 여백
강한 중심 피사체
텍스트 없음
깔끔한 배경
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유튜브 썸네일이면,&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;가로 16:9 비율
큰 중심 피사체
강한 대비
제목을 넣을 여백
작은 디테일보다 한눈에 보이는 구성
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;랜딩페이지 히어로 이미지라면,&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;가로 16:9 또는 21:9 비율
한쪽에 핵심 오브젝트
다른 한쪽에 헤드라인과 버튼용 여백
브랜드 무드가 느껴지는 배경
복잡하지 않은 구성
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 시트라면,&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;하얀 배경
정면, 측면, 후면
전신
일관된 의상과 헤어스타일
불필요한 배경 없음
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 기본값을 넣어두면 사용자가 자세히 말하지 않아도 어느 정도 완성도 있는 프롬프트를 만들 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;최종 결론&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 생성에서 중요한 것은 프롬프트의 길이가 아닙니다.&lt;br /&gt;중요한 것은 &lt;b&gt;방향이 분명한가&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 이미지 프롬프트는 다음 질문에 답해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;어디에 쓸 이미지인가?
무엇을 보여줄 것인가?
어떤 스타일인가?
어떤 구도인가?
어떤 조명인가?
텍스트는 필요한가?
무엇을 피해야 하는가?
무엇을 유지해야 하는가?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 GPT 이미지 프롬프트 개선기의 목표는 하나입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 막연한 아이디어를 이미지 생성 모델이 바로 이해할 수 있는 디자인 디렉션으로 바꿔주는 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것만 잘 설계해도 누구나 더 안정적으로 원하는 이미지를 만들 수 있습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1759</guid>
      <comments>https://javaexpert.tistory.com/1759#entry1759comment</comments>
      <pubDate>Mon, 18 May 2026 15:26:58 +0900</pubDate>
    </item>
    <item>
      <title>Codex를 UI/UX 마법사처럼 만드는 디자인 루프</title>
      <link>https://javaexpert.tistory.com/1758</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;Codex를 UI/UX 마법사처럼 만드는 디자인 루프&lt;/title&gt;
&lt;style&gt;
  @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@400;600;700&amp;family=Noto+Sans+KR:wght@300;400;500;600&amp;family=Fira+Code:wght@400;500&amp;display=swap');

  :root {
    --bg: #fafaf8;
    --text: #1a1a1a;
    --text-secondary: #666;
    --text-light: #999;
    --accent: #e8572a;
    --accent-soft: #fff3ef;
    --border: #e8e6e1;
    --code-bg: #282c34;
    --code-text: #abb2bf;
    --inline-code-bg: #f0ede8;
    --card-bg: #ffffff;
    --shadow: 0 1px 4px rgba(0,0,0,0.04);
  }

  * { margin: 0; padding: 0; box-sizing: border-box; }

  body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Noto Sans KR', -apple-system, sans-serif;
    font-size: 17px;
    line-height: 1.9;
    -webkit-font-smoothing: antialiased;
  }

  /* ── Header ── */
  .header {
    text-align: center;
    padding: 100px 24px 60px;
    max-width: 680px;
    margin: 0 auto;
  }

  .header .topic {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 20px;
    padding: 4px 16px;
    margin-bottom: 32px;
  }

  .header h1 {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    line-height: 1.45;
    letter-spacing: -0.5px;
    margin-bottom: 24px;
  }

  .header .subtitle {
    font-size: 18px;
    color: var(--text-secondary);
    line-height: 1.8;
    font-weight: 300;
  }

  .header .meta {
    margin-top: 40px;
    font-size: 14px;
    color: var(--text-light);
  }

  .divider {
    max-width: 680px;
    margin: 0 auto;
    border: none;
    border-top: 1px solid var(--border);
  }

  /* ── Article ── */
  .article {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 24px;
  }

  .article h2 {
    font-family: 'Noto Serif KR', serif;
    font-size: 26px;
    font-weight: 700;
    margin: 80px 0 24px;
    line-height: 1.4;
    letter-spacing: -0.3px;
  }

  .article h3 {
    font-family: 'Noto Serif KR', serif;
    font-size: 20px;
    font-weight: 600;
    margin: 48px 0 16px;
    line-height: 1.5;
  }

  .article h4 {
    font-family: 'Noto Serif KR', serif;
    font-size: 17px;
    font-weight: 600;
    margin: 36px 0 12px;
    line-height: 1.5;
  }

  .article p {
    margin-bottom: 20px;
  }

  .article strong {
    font-weight: 600;
  }

  .article em {
    font-style: normal;
    color: var(--accent);
    font-weight: 500;
  }

  .article ul, .article ol {
    margin: 16px 0 24px 20px;
  }

  .article li {
    margin-bottom: 8px;
  }

  /* ── Quote Block ── */
  .quote-block {
    border-left: 3px solid var(--accent);
    padding: 20px 28px;
    margin: 32px 0;
    background: var(--accent-soft);
    border-radius: 0 8px 8px 0;
  }

  .quote-block p {
    margin-bottom: 0;
    font-size: 16px;
  }

  /* ── Inline Code ── */
  code {
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 0.88em;
    background: var(--inline-code-bg);
    padding: 2px 7px;
    border-radius: 4px;
    color: var(--accent);
  }

  /* ── Code Block ── */
  .code-block {
    margin: 28px 0;
    border-radius: 10px;
    overflow: hidden;
    background: var(--code-bg);
    box-shadow: 0 2px 12px rgba(0,0,0,0.12);
  }

  .code-block .code-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: #21252b;
    border-bottom: 1px solid #181a1f;
  }

  .code-block .code-header .lang-label {
    font-family: 'Fira Code', monospace;
    font-size: 12px;
    color: #636d83;
    text-transform: uppercase;
    letter-spacing: 1px;
  }

  .copy-btn {
    background: none;
    border: 1px solid #3e4451;
    color: #636d83;
    font-family: 'Fira Code', monospace;
    font-size: 11px;
    padding: 3px 10px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
    letter-spacing: 0.5px;
  }

  .copy-btn:hover {
    border-color: #abb2bf;
    color: #abb2bf;
  }

  .copy-btn.copied {
    border-color: #98c379;
    color: #98c379;
  }

  .code-block .code-header .dots {
    display: flex;
    gap: 6px;
  }

  .code-block .code-header .dots span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
  }

  .code-block .code-header .dots span:nth-child(1) { background: #ff5f57; }
  .code-block .code-header .dots span:nth-child(2) { background: #febc2e; }
  .code-block .code-header .dots span:nth-child(3) { background: #28c840; }

  .code-block pre {
    padding: 20px 24px;
    overflow-x: auto;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.7;
    color: var(--code-text);
    tab-size: 2;
  }

  .code-block pre .line-num {
    display: inline-block;
    width: 36px;
    color: #4b5263;
    text-align: right;
    margin-right: 20px;
    user-select: none;
    -webkit-user-select: none;
  }

  /* Syntax Highlighting */
  .code-block pre .keyword   { color: #c678dd; }
  .code-block pre .string    { color: #98c379; }
  .code-block pre .number    { color: #d19a66; }
  .code-block pre .comment   { color: #5c6370; font-style: italic; }
  .code-block pre .function  { color: #61afef; }
  .code-block pre .operator  { color: #56b6c2; }
  .code-block pre .type      { color: #e5c07b; }
  .code-block pre .variable  { color: #e06c75; }
  .code-block pre .tag       { color: #e06c75; }
  .code-block pre .attr      { color: #d19a66; }
  .code-block pre .punct     { color: #abb2bf; }
  .code-block pre .property  { color: #e06c75; }
  .code-block pre .selector  { color: #98c379; }
  .code-block pre .value     { color: #d19a66; }

  /* ── Feature Cards ── */
  .feature-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin: 32px 0;
  }

  .feature-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 24px;
    box-shadow: var(--shadow);
    transition: transform 0.2s, box-shadow 0.2s;
  }

  .feature-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  }

  .feature-card .icon {
    font-size: 28px;
    margin-bottom: 12px;
  }

  .feature-card .title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 6px;
  }

  .feature-card .desc {
    font-size: 14px;
    color: var(--text-secondary);
    line-height: 1.6;
  }

  /* ── Pipeline / Step Flow ── */
  .pipeline {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 32px 28px;
    margin: 32px 0;
    box-shadow: var(--shadow);
  }

  .pipeline .step {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 14px 0;
    position: relative;
  }

  .pipeline .step:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 15px;
    top: 48px;
    bottom: -2px;
    width: 2px;
    background: var(--border);
  }

  .pipeline .step-num {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .pipeline .step-content {
    flex: 1;
    padding-top: 4px;
  }

  .pipeline .step-title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 2px;
  }

  .pipeline .step-desc {
    font-size: 14px;
    color: var(--text-secondary);
  }

  /* ── Example Card ── */
  .example-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    margin: 32px 0;
    overflow: hidden;
    box-shadow: var(--shadow);
  }

  .example-card .example-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .example-card .example-num {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .example-card .example-title {
    font-weight: 600;
    font-size: 16px;
  }

  .example-card .example-body {
    padding: 24px;
  }

  .prompt-box {
    background: #f8f7f4;
    border-radius: 8px;
    padding: 16px 20px;
    margin-bottom: 20px;
    font-size: 15px;
    line-height: 1.7;
    color: var(--text);
    border-left: 3px solid var(--accent);
  }

  .prompt-box .label {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 8px;
  }

  .process-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .process-list li {
    padding: 6px 0 6px 24px;
    position: relative;
    font-size: 15px;
    color: var(--text-secondary);
  }

  .process-list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 14px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border);
  }

  .process-list li:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 26px;
    bottom: -8px;
    width: 2px;
    background: var(--border);
  }

  .result-tag {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    background: var(--accent-soft);
    padding: 4px 12px;
    border-radius: 4px;
    margin-top: 16px;
  }

  /* ── Helper Table ── */
  .helper-table {
    width: 100%;
    border-collapse: collapse;
    margin: 24px 0;
    font-size: 15px;
  }

  .helper-table th {
    text-align: left;
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-light);
    padding: 12px 16px;
    border-bottom: 2px solid var(--border);
  }

  .helper-table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
  }

  /* ── Directory Tree ── */
  .dir-tree {
    background: #f5f3ef;
    border-radius: 8px;
    padding: 24px;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.8;
    color: var(--text-secondary);
    margin: 24px 0;
  }

  .dir-tree .file { color: var(--text); display: block; }
  .dir-tree .comment { color: var(--text-light); font-family: 'Noto Sans KR', sans-serif; font-size: 13px; }

  /* ── Rule List ── */
  .rule-list {
    counter-reset: rule;
    list-style: none;
    margin: 24px 0;
    padding: 0;
  }

  .rule-list li {
    counter-increment: rule;
    padding: 14px 16px 14px 56px;
    position: relative;
    border-bottom: 1px solid var(--border);
    font-size: 15px;
  }

  .rule-list li::before {
    content: counter(rule, decimal-leading-zero);
    position: absolute;
    left: 16px;
    top: 14px;
    font-family: 'Fira Code', monospace;
    font-size: 13px;
    color: var(--accent);
    font-weight: 600;
  }

  .rule-list li:last-child {
    border-bottom: none;
  }

  /* ── Image ── */
  .article img {
    max-width: 100%;
    border-radius: 8px;
    margin: 16px 0;
  }

  .article figcaption {
    font-size: 14px;
    color: var(--text-light);
    text-align: center;
    margin-top: 8px;
  }

  /* ── Callout ── */
  .callout {
    display: flex;
    gap: 16px;
    padding: 20px 24px;
    border-radius: 8px;
    margin: 28px 0;
  }

  .callout.info {
    background: #edf4fc;
    border-left: 3px solid #3b82f6;
  }

  .callout.warning {
    background: #fef9ec;
    border-left: 3px solid #f59e0b;
  }

  .callout.tip {
    background: #ecfdf5;
    border-left: 3px solid #10b981;
  }

  .callout .callout-icon {
    font-size: 20px;
    flex-shrink: 0;
    padding-top: 2px;
  }

  .callout .callout-body {
    flex: 1;
  }

  .callout .callout-body p {
    margin-bottom: 0;
    font-size: 15px;
  }

  /* ── Footer ── */
  .footer {
    max-width: 680px;
    margin: 80px auto 0;
    padding: 40px 24px;
    border-top: 1px solid var(--border);
    text-align: center;
    font-size: 14px;
    color: var(--text-light);
  }

  .footer a {
    color: var(--accent);
    text-decoration: none;
  }

  /* ── Responsive ── */
  @media (max-width: 640px) {
    .header { padding: 60px 20px 40px; }
    .header h1 { font-size: 26px; }
    .feature-grid { grid-template-columns: 1fr; }
    .article h2 { font-size: 22px; }
    .code-block pre { font-size: 12px; }
  }

  /* ── Scroll-triggered Animations ── */
  @keyframes fadeInUp {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: translateY(0); }
  }

  @keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  .animate-on-scroll {
    opacity: 0;
    transition: none;
  }

  .animate-on-scroll.visible {
    animation: fadeInUp 0.6s ease-out forwards;
  }

  .animate-on-scroll.visible-delay-1 { animation-delay: 0.1s; }
  .animate-on-scroll.visible-delay-2 { animation-delay: 0.2s; }
  .animate-on-scroll.visible-delay-3 { animation-delay: 0.3s; }

  /* ── Header Entrance ── */
  .header .topic {
    animation: fadeIn 0.8s ease-out 0.2s both;
  }

  .header h1 {
    animation: fadeInUp 0.8s ease-out 0.4s both;
  }

  .header .subtitle {
    animation: fadeInUp 0.8s ease-out 0.6s both;
  }

  .header .meta {
    animation: fadeIn 0.8s ease-out 0.8s both;
  }

  /* ── Audio Waveform Animation ── */
  .waveform {
    display: flex;
    align-items: center;
    gap: 3px;
    height: 32px;
    margin: 24px 0;
  }

  .waveform .bar {
    width: 4px;
    border-radius: 2px;
    background: var(--accent);
    animation: wave 1.2s ease-in-out infinite;
  }

  .waveform .bar:nth-child(1)  { animation-delay: 0s; }
  .waveform .bar:nth-child(2)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(3)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(4)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(5)  { animation-delay: 0.4s; }
  .waveform .bar:nth-child(6)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(7)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(8)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(9)  { animation-delay: 0s; }
  .waveform .bar:nth-child(10) { animation-delay: 0.1s; }
  .waveform .bar:nth-child(11) { animation-delay: 0.2s; }
  .waveform .bar:nth-child(12) { animation-delay: 0.3s; }

  @keyframes wave {
    0%, 100% { height: 8px; opacity: 0.4; }
    50% { height: 28px; opacity: 1; }
  }

  /* ── Animated Progress Bar ── */
  .progress-bar {
    background: var(--border);
    border-radius: 4px;
    height: 6px;
    margin: 24px 0;
    overflow: hidden;
  }

  .progress-bar .fill {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--accent), #f4845f);
    animation: progressFill 2s ease-out forwards;
    transform-origin: left;
  }

  @keyframes progressFill {
    from { width: 0; }
  }

  /* ── Typing Effect ── */
  .typing {
    font-family: 'Fira Code', monospace;
    font-size: 15px;
    color: var(--text);
    border-right: 2px solid var(--accent);
    white-space: nowrap;
    overflow: hidden;
    animation: typing 3s steps(40) forwards, blink 0.8s step-end infinite;
    width: 0;
  }

  @keyframes typing {
    to { width: 100%; }
  }

  @keyframes blink {
    50% { border-color: transparent; }
  }

  /* ── Pulse Dot ── */
  .pulse-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    margin-right: 8px;
    animation: pulse 2s ease-in-out infinite;
  }

  @keyframes pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.5); opacity: 0.5; }
  }

  /* ── Floating Badge ── */
  .float-badge {
    display: inline-block;
    font-size: 12px;
    font-weight: 600;
    color: white;
    background: var(--accent);
    padding: 4px 12px;
    border-radius: 12px;
    animation: float 3s ease-in-out infinite;
  }

  @keyframes float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-4px); }
  }

  /* ── Shimmer Loading ── */
  .shimmer {
    background: linear-gradient(90deg, var(--border) 25%, #f0ede8 50%, var(--border) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    border-radius: 4px;
    height: 16px;
    margin: 8px 0;
  }

  @keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
  }

  /* ── Animated Counter ── */
  .counter {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    color: var(--accent);
  }

  /* ── Bouncing Arrow ── */
  .bounce-arrow {
    display: inline-block;
    animation: bounce 1.5s ease-in-out infinite;
    color: var(--accent);
  }

  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(6px); }
  }

  /* ── Feature Card Stagger ── */
  .feature-grid .feature-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .feature-grid .feature-card:nth-child(1) { animation-delay: 0.1s; }
  .feature-grid .feature-card:nth-child(2) { animation-delay: 0.2s; }
  .feature-grid .feature-card:nth-child(3) { animation-delay: 0.3s; }
  .feature-grid .feature-card:nth-child(4) { animation-delay: 0.4s; }
  .feature-grid .feature-card:nth-child(5) { animation-delay: 0.5s; }
  .feature-grid .feature-card:nth-child(6) { animation-delay: 0.6s; }

  /* ── Pipeline Step Stagger ── */
  .pipeline .step {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .pipeline .step:nth-child(1) { animation-delay: 0.1s; }
  .pipeline .step:nth-child(2) { animation-delay: 0.3s; }
  .pipeline .step:nth-child(3) { animation-delay: 0.5s; }
  .pipeline .step:nth-child(4) { animation-delay: 0.7s; }

  /* ── Example Card Stagger ── */
  .example-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  /* ── Quote Block Slide-in ── */
  .quote-block {
    animation: slideInLeft 0.6s ease-out;
  }

  @keyframes slideInLeft {
    from { opacity: 0; transform: translateX(-20px); }
    to { opacity: 1; transform: translateX(0); }
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;header class=&quot;header&quot;&gt;
  &lt;div class=&quot;topic&quot;&gt;AI &amp;middot; Design Workflow&lt;/div&gt;
  &lt;h1&gt;Codex를 UI/UX 마법사처럼&lt;br&gt;만드는 디자인 루프&lt;/h1&gt;
  &lt;p class=&quot;subtitle&quot;&gt;비전 기능과 이미지 생성을 결합해&lt;br&gt;초안을 프로덕션 수준으로 끌어올리는 전체 가이드&lt;/p&gt;
  &lt;div class=&quot;meta&quot;&gt;2026.05.06 &amp;middot; Codex Desktop Guide&lt;/div&gt;
&lt;/header&gt;
&lt;hr class=&quot;divider&quot;&gt;

&lt;article class=&quot;article&quot;&gt;

&lt;p&gt;대부분의 사람들은 Codex를 단순한 커맨드라인 도구처럼 사용합니다. 그래서 결과물도 대개 초안 수준의 UI 디자인에 머무릅니다.&lt;/p&gt;

&lt;p&gt;하지만 &lt;em&gt;Codex Desktop&lt;/em&gt; 앱은 이 흐름을 바꿉니다. 시각적 피드백 루프를 통합해 앱을 빌드하고 실행하며, 스크린샷을 캡처하고, 비전 기능으로 레이아웃을 검사하고, 사용자 상호작용을 시뮬레이션하며, &lt;em&gt;imagegen&lt;/em&gt;으로 에셋을 생성하고, 실제 시각 결과를 바탕으로 코드를 반복 수정합니다.&lt;/p&gt;

&lt;p&gt;이 접근 방식은 디자인을 한 번의 프롬프트 결과가 아니라 &lt;em&gt;효율적인 반복 프로세스&lt;/em&gt;로 바꿔줍니다.&lt;/p&gt;

&lt;h2&gt;실수: 왜 첫 초안은 부족한가&lt;/h2&gt;

&lt;p&gt;기존 AI 코딩 벤치마크는 보통 단일 프롬프트에서 나온 첫 결과물을 평가합니다. 하지만 이것은 오해를 부를 수 있습니다.&lt;/p&gt;

&lt;p&gt;AI를 사용해 만든 첫 초안은 대부분 다음과 같은 문제를 보입니다.&lt;/p&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;&amp;#x1F4CF;&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;일관성 없는 간격&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;요소 간 여백이 제각각이어 시각적 리듬이 깨집니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;&amp;#x1F3A8;&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;불명확한 시각적 위계&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;어떤 요소가 중요한지, 어디를 봐야 할지 알기 어렵습니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;&amp;#x1F4F1;&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;모바일 반응형 실패&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;데스크톱에서만 확인하면 모바일에서 레이아웃이 무너집니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;&amp;#x1F9E9;&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;어색한 레이아웃&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;정렬이 맞지 않거나 요소 배치가 부자연스럽습니다.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;하지만 LLM이 실제 UI를 볼 수 있고, 무엇이 좋은지, 무엇이 나쁜지, 무엇이 어색한지를 잘 판단할 수 있다면 상황은 완전히 달라집니다. Codex의 &lt;em&gt;비전(Vision)&lt;/em&gt; 기능이 바로 이 지점을 바꿉니다.&lt;/p&gt;

&lt;p&gt;Codex Desktop은 빠른 반복 작업이 가능하다는 점에서 특히 강합니다.&lt;/p&gt;

&lt;h2&gt;핵심 관점: 시각적 제품 빌더로 전환하기&lt;/h2&gt;

&lt;p&gt;이제 Codex를 단순한 터미널 코드 도구로 보지 말고, &lt;em&gt;시각적 디자인 루프&lt;/em&gt;를 수행하는 도구로 봐야 합니다.&lt;/p&gt;

&lt;div class=&quot;pipeline&quot;&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;프롬프트 작성&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;원하는 UI를 구체적으로 설명합니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;빌드 &amp;amp; 실행&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;코드를 생성하고 로컬에서 앱을 실행합니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;스크린샷 &amp;amp; 비전 리뷰&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;화면을 캡처하고 Vision으로 시각적 문제를 분석합니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;4&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;클릭 테스트 &amp;amp; 수정&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;사용자 흐름을 시뮬레이션하고 문제를 반복 수정합니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;이 관점 전환은 세 가지 장점을 제공합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;첫째&lt;/strong&gt;, Codex가 실제로 실행 중인 UI를 직접 관찰합니다. 커맨드라인 방식은 코드 예측에 의존하지만, Desktop 방식은 실제 화면을 보고 판단할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;둘째&lt;/strong&gt;, 문제 감지를 자동화할 수 있습니다. 대비 문제, 여백 문제, 텍스트 가독성 문제 등을 빠르게 찾아냅니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;셋째&lt;/strong&gt;, 디자인 &lt;em&gt;A/B 테스트&lt;/em&gt;가 가능해집니다. 여러 디자인 변형을 만들고, 가독성·시각적 위계·사용자 흐름 같은 기준으로 더 나은 안을 선택할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;CLI Codex vs Desktop Codex&lt;/h2&gt;

&lt;p&gt;CLI는 코드를 편집할 수 있고, Desktop은 화면을 보고 상호작용할 수 있습니다. 각각의 강점이 다릅니다.&lt;/p&gt;

&lt;table class=&quot;helper-table&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;CLI Codex&lt;/th&gt;
      &lt;th&gt;Desktop Codex&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;/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;/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;코드 정확도가 중요한 선형 작업에는 CLI만으로도 충분합니다. 반면 미적 완성도가 중요한 프로젝트에서는 &lt;em&gt;Codex Desktop&lt;/em&gt;의 반복 루프가 훨씬 유리합니다.&lt;/p&gt;

&lt;p&gt;특히 새로운 이미지 생성 엔진 &lt;em&gt;Image 2&lt;/em&gt;를 사용해 필요한 비주얼을 즉석에서 만들 수 있다는 점은 디자인 프로토타이핑 흐름을 크게 바꿉니다.&lt;/p&gt;

&lt;h2&gt;Imagegen vs Vision: 서로 다른 역할&lt;/h2&gt;

&lt;p&gt;두 기능은 비슷해 보이지만 역할이 확연히 다릅니다. &lt;em&gt;Imagegen&lt;/em&gt;은 소스 에셋을 만들고, &lt;em&gt;Vision&lt;/em&gt;은 실제 UI를 판단합니다.&lt;/p&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;&amp;#x1F5BC;&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;Imagegen이 만드는 것&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;게임 캐릭터 초상화, 제품 아이콘, 배경 이미지, 일러스트, 브랜드용 시각 요소&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;&amp;#x1F441;&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;Vision이 검사하는 것&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;시각적 위계, 간격, 대비, 텍스트 잘림, 모바일 깨짐, 클릭 요소 명확성&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;효과적인 워크플로우는 두 기능을 하나의 사이클로 묶는 것입니다.&lt;/p&gt;

&lt;div class=&quot;pipeline&quot;&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;Imagegen으로 에셋 생성&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;필요한 캐릭터, 아이콘, 배경을 생성합니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;UI에 통합 &amp;amp; 스크린샷&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;에셋을 코드에 반영하고 화면을 캡처합니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;Vision으로 검토 &amp;amp; 수정&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;시각적 문제를 찾아내고 코드를 수정한 뒤 다시 확인합니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;이 조합을 사용하면 디자인이 단순히 멋있어 보이는 수준을 넘어 &lt;em&gt;실제로 사용 가능한 UI&lt;/em&gt;에 가까워집니다.&lt;/p&gt;

&lt;h2&gt;모든 것을 바꾸는 프롬프트&lt;/h2&gt;

&lt;p&gt;&quot;더 예쁘게 만들어줘&quot; 같은 모호한 프롬프트는 일관된 결과를 내기 어렵습니다. 대신 구체적으로 지시하는 것이 좋습니다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;prompt&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;Codex Desktop을 시각적 디자인 루프로 사용하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;앱을 로컬에서 실행하고, 데스크톱과 모바일 화면의 스크린샷을 검사하고,&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;상호작용을 클릭해 테스트한 뒤, 완성도 높은 결과가 나오도록 수정하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;시각적 위계, 간격, 대비, 텍스트 맞춤, 반응형 레이아웃,&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;hover 상태에 집중하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;Imagegen과 Vision을 함께 사용하고,&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;필요하면 A/B 테스트를 진행하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;반응형 관점에서 Vision으로 직접 확인해 만족스러운 수준이 될 때까지 반복하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;화면을 제품 디자이너이자 QA 전문가처럼 검사하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;시각적 문제를 영향도 기준으로 파악하고, 모든 문제를 검증한 뒤 수정하세요.&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;callout tip&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;&amp;#x2713;&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;포인트는 &quot;예쁘게&quot;가 아니라 &lt;strong&gt;검사 기준을 명시&lt;/strong&gt;하는 것입니다. 위계, 간격, 대비, 반응형 &amp;mdash; 구체적인 체크리스트를 주면 결과가 달라집니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;워크플로우 1: 게임 UI 디자인&lt;/h2&gt;

&lt;p&gt;게임 UI는 HUD, 인벤토리, 모바일 대응 등 복잡한 요소가 많습니다. 비전 루프를 적용하면 초기에 많은 시각적 버그를 잡을 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;게임 UI 디자인 프롬프트&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Prompt&lt;/div&gt;
      게임 화면을 실행하고 Vision으로 검사하세요. 플레이어 관점에서 HUD 가독성, 아이콘 명확성, 모바일 동작을 평가하세요. 캐릭터 초상화나 배경 같은 에셋은 imagegen을 사용하세요. Vision으로 다시 확인하고, 프로덕션에 가까운 시각 완성도가 될 때까지 반복하세요.
    &lt;/div&gt;
    &lt;ol class=&quot;process-list&quot;&gt;
      &lt;li&gt;게임 화면을 로컬에서 실행&lt;/li&gt;
      &lt;li&gt;Vision으로 HUD 가독성과 아이콘 명확성 평가&lt;/li&gt;
      &lt;li&gt;imagegen으로 캐릭터 초상화, 배경 에셋 생성&lt;/li&gt;
      &lt;li&gt;Vision으로 재검토 및 반복 수정&lt;/li&gt;
    &lt;/ol&gt;
    &lt;div class=&quot;result-tag&quot;&gt;플레이어가 클릭 가능한 요소를 빠르게 인식하고 스탯을 쉽게 읽도록 개선&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;워크플로우 2: 제품 UI 만들기&lt;/h2&gt;

&lt;p&gt;SaaS 대시보드나 관리자 패널에서는 사용성이 가장 중요합니다. 비전문가도 쉽게 이해할 수 있는 인터페이스가 목표입니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;제품 UI 프롬프트&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Prompt&lt;/div&gt;
      2026년 디자인 원칙을 바탕으로 기능적인 UI를 만드세요. 최고 수준의 사용자 경험, 가독성, 사용성을 목표로 하세요. 레퍼런스와 베스트 프랙티스를 조사한 뒤 imagegen으로 필요한 UI 비주얼을 만들고, 로컬에서 실행한 후 Vision으로 데스크톱과 모바일 화면의 위계, 간격, 내비게이션을 검사하세요.
    &lt;/div&gt;
    &lt;ol class=&quot;process-list&quot;&gt;
      &lt;li&gt;2026년 디자인 원칙 기반 UI 설계&lt;/li&gt;
      &lt;li&gt;레퍼런스 조사 및 imagegen으로 비주얼 생성&lt;/li&gt;
      &lt;li&gt;로컬 실행 후 Vision으로 데스크톱/모바일 검사&lt;/li&gt;
      &lt;li&gt;비전문가 사용자 관점에서 흐름 검증&lt;/li&gt;
    &lt;/ol&gt;
    &lt;div class=&quot;result-tag&quot;&gt;모든 사용자가 스트레스 없이 탐색할 수 있는 인터페이스 완성&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;워크플로우 3: 커밋 전 A/B 테스트&lt;/h2&gt;

&lt;p&gt;주관적인 디자인 선택을 피하려면 여러 변형을 만들어 비교하는 것이 좋습니다. AI가 하나의 결과물만 고집하지 않게 만듭니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;A/B 테스트 프롬프트&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Prompt&lt;/div&gt;
      세 가지 시각적 변형을 생성하세요. 각 변형을 데스크톱과 모바일에서 스크린샷으로 확인하세요. 가독성, 시각적 위계, 사용자 흐름을 기준으로 비교하세요. 가장 좋은 안을 선택해 적용하세요.
    &lt;/div&gt;
    &lt;ol class=&quot;process-list&quot;&gt;
      &lt;li&gt;세 가지 시각적 변형 생성&lt;/li&gt;
      &lt;li&gt;데스크톱/모바일 스크린샷 캡처&lt;/li&gt;
      &lt;li&gt;가독성, 위계, 사용자 흐름 기준 비교&lt;/li&gt;
      &lt;li&gt;최적안 선택 및 적용&lt;/li&gt;
    &lt;/ol&gt;
    &lt;div class=&quot;result-tag&quot;&gt;여러 대안을 비교해 프로젝트 목표에 맞는 디자인 선택&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;워크플로우 4: 아트 바이블 추출하기&lt;/h2&gt;

&lt;p&gt;성공적인 페이지 디자인이 나오면, 그 결과를 재사용 가능한 &lt;em&gt;디자인 언어&lt;/em&gt;로 정리할 수 있습니다. 한 번 만든 스타일을 앱 전체에 일관되게 확장하는 것이 핵심입니다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;prompt&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;앱 스크린샷을 바탕으로 아트 바이블을 작성하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;팔레트, 타이포그래피, 레이아웃 규칙을 정리하고,&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;앞으로 다른 화면에도 일관되게 적용할 수 있는&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;디자인 시스템 규칙으로 만들어주세요.&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2&gt;마스터 프롬프트&lt;/h2&gt;

&lt;p&gt;아래 프롬프트는 시각적 작업에 거의 그대로 활용할 수 있는 종합 프롬프트입니다. 목표 부분만 프로젝트에 맞게 수정하세요.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;master prompt&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;Codex Desktop을 시각적 빌더로 사용하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;목표:&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;[프로젝트를 설명하세요]&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;Imagegen과 Vision을 한 쌍의 워크플로우로 사용하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;최소 기능 버전을 만드세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;2.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;로컬에서 실행하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;3.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;스크린샷을 찍으세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;4.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;Vision으로 검사하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;5.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;사용자 흐름을 클릭해 테스트하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;6.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;문제를 수정하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;7.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;다시 스크린샷을 찍으세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;8.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;A/B 테스트 변형을 만드세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;9.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;필요한 에셋은 imagegen으로 생성하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;10.&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;변경 사항을 요약하고 디자인 규칙을 추출하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;18&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;검사 기준:&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;시각적 위계&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;간격&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;대비&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;텍스트 가독성&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;반응형 레이아웃&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;hover 상태&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;모바일 사용성&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;클릭 가능한 요소의 명확성&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;사용자 흐름의 자연스러움&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;29&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;화면을 제품 디자이너이자 QA 전문가처럼 검토하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;실제 화면을 보고 문제를 찾고, 수정 후 다시 확인하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;만족스러운 수준에 도달할 때까지 반복하세요.&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2&gt;요약: 반복이 완성을 만든다&lt;/h2&gt;

&lt;p&gt;Codex Desktop은 단순히 코드를 작성하는 도구가 아니라, 전체 시각적 디자인 루프에 참여하는 도구로 사용할 수 있습니다. 핵심을 정리하면 다음과 같습니다.&lt;/p&gt;

&lt;ol class=&quot;rule-list&quot;&gt;
  &lt;li&gt;&lt;em&gt;Vision&lt;/em&gt;은 UI를 검토하는 데 사용한다&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Imagegen&lt;/em&gt;은 필요한 시각 에셋을 만드는 데 사용한다&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;A/B 테스트&lt;/em&gt;로 더 나은 디자인을 선택한다&lt;/li&gt;
  &lt;li&gt;성공한 디자인은 &lt;em&gt;아트 바이블&lt;/em&gt;로 정리한다&lt;/li&gt;
  &lt;li&gt;CLI는 코드 중심 작업에, Desktop은 디자인 중심 작업에 사용한다&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;quote-block&quot;&gt;
  &lt;p&gt;좋은 UI는 한 번의 프롬프트로 완성되는 것이 아니라, 보고 고치고 다시 확인하는 &lt;em&gt;반복 과정&lt;/em&gt;에서 완성됩니다. Codex Desktop의 강점은 바로 그 반복 과정을 AI가 직접 수행할 수 있게 만든다는 점입니다.&lt;/p&gt;
&lt;/div&gt;

&lt;/article&gt;

&lt;footer class=&quot;footer&quot;&gt;
  &lt;p&gt;Codex Desktop의 비전 기반 디자인 루프에 대한 전체 가이드입니다.&lt;/p&gt;
  &lt;p style=&quot;margin-top: 8px;&quot;&gt;&lt;a href=&quot;#&quot;&gt;Codex Desktop 가이드 더보기 &amp;rarr;&lt;/a&gt;&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
document.querySelectorAll('.code-block').forEach(function(block) {
  var header = block.querySelector('.code-header');
  var pre = block.querySelector('pre');
  if (!header || !pre) return;
  var btn = document.createElement('button');
  btn.className = 'copy-btn';
  btn.textContent = 'COPY';
  btn.addEventListener('click', function() {
    var text = pre.innerText.replace(/^\d+\s*/gm, '');
    navigator.clipboard.writeText(text).then(function() {
      btn.textContent = 'COPIED';
      btn.classList.add('copied');
      setTimeout(function() {
        btn.textContent = 'COPY';
        btn.classList.remove('copied');
      }, 2000);
    });
  });
  header.appendChild(btn);
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1758</guid>
      <comments>https://javaexpert.tistory.com/1758#entry1758comment</comments>
      <pubDate>Wed, 6 May 2026 10:53:09 +0900</pubDate>
    </item>
    <item>
      <title>Open Design &amp;rarr; Flutter 앱으로 디자인 워크플로우 가이드</title>
      <link>https://javaexpert.tistory.com/1757</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;2&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/nexu-io/open-design&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/nexu-io/open-design&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;2&quot; data-ke-size=&quot;size16&quot;&gt;이 문서는 **Open Design(OD)**에서 선택한 **디자인 시스템(DESIGN.md)**과 시각 시안을 기준으로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Flutter&lt;/b&gt;로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;TODO 앱&lt;/b&gt;을 만들 때의 실무 워크플로우를 예시로 정리합니다.&lt;/p&gt;
&lt;hr data-line=&quot;6&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;1-%EC%9D%B4-%EA%B0%80%EC%9D%B4%EB%93%9C%EA%B0%80-%EA%B0%80%EC%A0%95%ED%95%98%EB%8A%94-%EA%B2%83&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;8&quot; data-ke-size=&quot;size26&quot;&gt;1. 이 가이드가 가정하는 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목가정&lt;/p&gt;
&lt;table style=&quot;background-color: #ffffff; color: #24292e; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-line=&quot;10&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-line=&quot;12&quot;&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot; data-line=&quot;12&quot;&gt;
&lt;td&gt;OD&lt;/td&gt;
&lt;td&gt;저장소 루트에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;npm install&lt;span&gt;&amp;nbsp;&lt;/span&gt;후&lt;span&gt;&amp;nbsp;&lt;/span&gt;npm run dev:all로 데몬&amp;middot;웹 UI 기동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot; data-line=&quot;13&quot;&gt;
&lt;td&gt;에이전트&lt;/td&gt;
&lt;td&gt;Claude Code / Cursor Agent 등&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;로컬 CLI&lt;/b&gt;(또는 Anthropic API BYOK)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot; data-line=&quot;14&quot;&gt;
&lt;td&gt;Flutter&lt;/td&gt;
&lt;td&gt;&lt;b&gt;안정 채널&lt;/b&gt;, Dart 3.x,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Material 3&lt;/b&gt;(useMaterial3: true) 기본&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot; data-line=&quot;15&quot;&gt;
&lt;td&gt;제품&lt;/td&gt;
&lt;td&gt;iOS/Android(또는 단일 플랫폼)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;TODO&lt;/b&gt;: 추가&amp;middot;완료 토글&amp;middot;삭제&amp;middot;필터, 1차 저장은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;메모리 &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;shared_preferences&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;OD가 내보내는 산출물은 보통 **HTML&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;artifact&amp;gt;**입니다. Flutter에는 그대로 붙일 수 없으므로, 연동의 축은 다음 두 가지로 나눕니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;19&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-line=&quot;19&quot;&gt;&lt;b&gt;DESIGN.md&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 색&amp;middot;타이포&amp;middot;간격&amp;middot;무드의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;단일 출처&lt;/b&gt;(진실 공급원).&lt;/li&gt;
&lt;li data-line=&quot;20&quot;&gt;&lt;b&gt;시안 HTML + 스크린샷&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 레이아웃&amp;middot;위계&amp;middot;컴포넌트 배치의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;시각 레퍼런스&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;Flutter 쪽에서는 이 둘을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;ThemeData&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;ColorScheme&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;TextTheme&lt;span&gt;&amp;nbsp;&lt;/span&gt;/ 앱 전용 간격 상수&lt;/b&gt;로 옮겨 구현합니다.&lt;/p&gt;
&lt;hr data-line=&quot;24&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;2-%EC%A0%84%EC%B2%B4-%ED%9D%90%EB%A6%84-%ED%95%9C%EB%88%88%EC%97%90&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;26&quot; data-ke-size=&quot;size26&quot;&gt;2. 전체 흐름 한눈에&lt;/h2&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;[OD] 디자인 시스템 선택 + 스킬 + 브리프 &amp;rarr; 질문폼&amp;middot;5방향 &amp;rarr; HTML 시안&amp;middot;저장
        &amp;darr;
[복사] DESIGN.md &amp;rarr; Flutter 레포 docs/ (또는 lib/theme/design_spec.md)
     시안 HTML&amp;middot;스크린샷 &amp;rarr; reference/ (참고만, 에셋 번들에 넣지 않아도 됨)
        &amp;darr;
[Flutter] flutter create &amp;rarr; AppTheme 반영 &amp;rarr; 화면 위젯&amp;middot;상태&amp;middot;로컬 저장
        &amp;darr;
[반복] 같은 DESIGN.md로 OD에서 UI만 재시안 &amp;rarr; Theme/위젯 국소 수정
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-line=&quot;39&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;3-phase-a--open-design%EC%97%90%EC%84%9C-todo-%EB%A0%88%ED%8D%BC%EB%9F%B0%EC%8A%A4-ui-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;41&quot; data-ke-size=&quot;size26&quot;&gt;3. Phase A &amp;mdash; Open Design에서 TODO 레퍼런스 UI 만들기&lt;/h2&gt;
&lt;h3 id=&quot;31-%EA%B8%B0%EB%8F%99&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;43&quot; data-ke-size=&quot;size23&quot;&gt;3.1 기동&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;cd /path/to/open-design
npm install
npm run dev:all
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;51&quot; data-ke-size=&quot;size16&quot;&gt;브라우저:&lt;span&gt;&amp;nbsp;&lt;/span&gt;http://localhost:5173&lt;/p&gt;
&lt;h3 id=&quot;32-%EC%8A%A4%ED%82%AC%EB%94%94%EC%9E%90%EC%9D%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%84%A0%ED%83%9D&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;53&quot; data-ke-size=&quot;size23&quot;&gt;3.2 스킬&amp;middot;디자인 시스템 선택&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정예시 선택이유&lt;/p&gt;
&lt;table style=&quot;background-color: #ffffff; color: #24292e; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-line=&quot;55&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-line=&quot;57&quot;&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot; data-line=&quot;57&quot;&gt;
&lt;td&gt;Skill&lt;/td&gt;
&lt;td&gt;&lt;b&gt;mobile-app&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;OD에 포함된 모바일 프레임&amp;middot;터치 UI에 가까운 스타터(없으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;web-prototype로도 가능)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot; data-line=&quot;58&quot;&gt;
&lt;td&gt;Design system&lt;/td&gt;
&lt;td&gt;제품에 맞는 항목 또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;커스텀&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESIGN.md&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Flutter&lt;span&gt;&amp;nbsp;&lt;/span&gt;ThemeData로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;같은 팔레트&amp;middot;타이포&lt;/b&gt;를 맞출 기준&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;33-%EC%B2%AB-%EB%B8%8C%EB%A6%AC%ED%94%84-%EC%98%88%EC%8B%9Cflutter-%EC%9D%B4%EA%B4%80%EC%9D%84-%EC%97%BC%EB%91%90%EC%97%90-%EB%91%94-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;60&quot; data-ke-size=&quot;size23&quot;&gt;3.3 첫 브리프 예시(Flutter 이관을 염두에 둔 프롬프트)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;62&quot; data-ke-size=&quot;size16&quot;&gt;OD는 여전히 HTML을 출력합니다. 다만 토큰은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;DESIGN.md에 맞추고&lt;/b&gt;, Flutter에서 옮기기 쉽게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;명시적 색&amp;middot;폰트&amp;middot;간격&lt;/b&gt;을 HTML에 박아 달라고 요청하면 이후 매핑이 쉽습니다.&lt;/p&gt;
&lt;pre class=&quot;haml&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;Flutter로 구현할 단일 화면 TODO 앱의 참고용 UI를 HTML 한 파일로 만들어 줘.
(나중에 Material 3 ThemeData로 옮길 예정이니 색은 hex, 폰트는 웹폰트로 명시해 줘.)

기능(클라이언트 UI만):
- 상단: Large title 느낌의 &quot;Tasks&quot; + 부제 한 줄
- TextField + FAB 또는 주 버튼으로 새 할 일 추가
- 필터: Segmented / Chip 스타일로 전체&amp;middot;진행 중&amp;middot;완료
- 리스트: Checkbox 또는 완료 토글, 제목, 삭제(또는 스와이프 힌트)
- 완료 항목: 취소선, Secondary 색 대비
- 하단 요약: &quot;N items left&quot;

디자인:
- 현재 활성 디자인 시스템(DESIGN.md)의 팔레트&amp;middot;타이포&amp;middot;간격을 :root CSS 변수로 반영
- 터치 타깃 최소 48dp에 해당할 만한 패딩(모바일 기준)
- 스크롤 가능한 리스트 영역 명확히

출력은 반드시 하나의 &amp;lt;artifact&amp;gt; 태그 안에 완전한 HTML 문서로만.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;34-%EC%A7%88%EB%AC%B8-%ED%8F%BC%EC%8B%9C%EA%B0%81-%EB%B0%A9%ED%96%A5&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;84&quot; data-ke-size=&quot;size23&quot;&gt;3.4 질문 폼&amp;middot;시각 방향&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;86&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-line=&quot;86&quot;&gt;제품이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;iOS 휴먼 인터페이스&lt;/b&gt;에 더 가깝다면 폼에서 톤을 명시하고, Flutter는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Cupertino&lt;span&gt;&amp;nbsp;&lt;/span&gt;위젯 혼합도 가능합니다. 이 가이드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Material 3&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;기준 설명을 유지합니다.&lt;/li&gt;
&lt;li data-line=&quot;87&quot;&gt;&lt;b&gt;5가지 시각 방향&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;선택 시, Flutter 레포&lt;span&gt;&amp;nbsp;&lt;/span&gt;README에 방향 이름과 선택 날짜를 적어 두면 테마 되돌리기가 쉽습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;35-%EA%B2%B0%EA%B3%BC%EB%AC%BC-%EC%A0%80%EC%9E%A5&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;89&quot; data-ke-size=&quot;size23&quot;&gt;3.5 결과물 저장&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;91&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-line=&quot;91&quot;&gt;&lt;b&gt;Save to disk&lt;/b&gt;로&lt;span&gt;&amp;nbsp;&lt;/span&gt;.od/artifacts/.../index.html&lt;span&gt;&amp;nbsp;&lt;/span&gt;저장.&lt;/li&gt;
&lt;li data-line=&quot;92&quot;&gt;&lt;b&gt;스크린샷&lt;/b&gt;(프리뷰 캡처)을 함께 보관하면 Flutter 구현 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;픽셀 단위가 아닌 위계&amp;middot;여백&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;비교에 유리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-line=&quot;94&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;4-phase-b--flutter-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;96&quot; data-ke-size=&quot;size26&quot;&gt;4. Phase B &amp;mdash; Flutter 프로젝트 생성&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;98&quot; data-ke-size=&quot;size16&quot;&gt;OD 저장소와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;별도 경로&lt;/b&gt;에 앱 레포를 둡니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;cd ~/projects
flutter create todo_app --org com.example
cd todo_app
flutter run
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;107&quot; data-ke-size=&quot;size16&quot;&gt;pubspec.yaml에 이후 단계에서 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;dependencies:
  shared_preferences: ^2.2.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;flutter pub get
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;118&quot; data-ke-size=&quot;size16&quot;&gt;(상태 관리는 처음엔&lt;span&gt;&amp;nbsp;&lt;/span&gt;StatefulWidget만으로도 충분합니다. 팀에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Riverpod&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;등을 쓰면 그에 맞춰 분리하면 됩니다.)&lt;/p&gt;
&lt;hr data-line=&quot;120&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;5-phase-c--%EB%94%94%EC%9E%90%EC%9D%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%84-flutter-%ED%85%8C%EB%A7%88%EB%A1%9C-%EC%97%B0%EB%8F%99&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;122&quot; data-ke-size=&quot;size26&quot;&gt;5. Phase C &amp;mdash; 디자인 시스템을 Flutter 테마로 연동&lt;/h2&gt;
&lt;h3 id=&quot;51-designmd%EB%A5%BC-%EB%A0%88%ED%8F%AC%EC%97%90-%EB%91%90%EA%B8%B0&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;124&quot; data-ke-size=&quot;size23&quot;&gt;5.1&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESIGN.md를 레포에 두기&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;todo_app/
  docs/
    DESIGN.md        # OD design-systems/&amp;lt;id&amp;gt;/DESIGN.md 를 복사
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;132&quot; data-ke-size=&quot;size16&quot;&gt;규칙 예:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;색&amp;middot;타이포&amp;middot;라운드&amp;middot;간격은&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESIGN.md를 벗어나지 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 id=&quot;52-html-%EC%8B%9C%EC%95%88-%E2%86%92-flutter-%EB%A7%A4%ED%95%91-%ED%91%9C-%EA%B0%9C%EB%85%90&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;134&quot; data-ke-size=&quot;size23&quot;&gt;5.2 HTML 시안 &amp;rarr; Flutter 매핑 표 (개념)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OD / HTMLFlutter&lt;/p&gt;
&lt;table style=&quot;background-color: #ffffff; color: #24292e; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-line=&quot;136&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-line=&quot;138&quot;&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot; data-line=&quot;138&quot;&gt;
&lt;td&gt;:root&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;--color-primary&lt;span&gt;&amp;nbsp;&lt;/span&gt;등&lt;/td&gt;
&lt;td&gt;ColorScheme.primary,&lt;span&gt;&amp;nbsp;&lt;/span&gt;ColorScheme.surface, &amp;hellip;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot; data-line=&quot;139&quot;&gt;
&lt;td&gt;본문/제목 폰트 패밀리&amp;middot;크기&lt;/td&gt;
&lt;td&gt;TextTheme의&lt;span&gt;&amp;nbsp;&lt;/span&gt;titleLarge,&lt;span&gt;&amp;nbsp;&lt;/span&gt;bodyMedium&lt;span&gt;&amp;nbsp;&lt;/span&gt;등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot; data-line=&quot;140&quot;&gt;
&lt;td&gt;8px 그리드&amp;middot;섹션 간격&lt;/td&gt;
&lt;td&gt;EdgeInsets,&lt;span&gt;&amp;nbsp;&lt;/span&gt;SizedBox(height: &amp;hellip;), 또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;AppSpacing&lt;span&gt;&amp;nbsp;&lt;/span&gt;클래스 상수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot; data-line=&quot;141&quot;&gt;
&lt;td&gt;모서리 반경&lt;/td&gt;
&lt;td&gt;ThemeData.cardTheme.shape,&lt;span&gt;&amp;nbsp;&lt;/span&gt;RoundedRectangleBorder(borderRadius: &amp;hellip;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;143&quot; data-ke-size=&quot;size16&quot;&gt;ColorScheme.fromSeed(seedColor: Color(0xFF...))로 한 번에 잡고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESIGN.md의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;보조색&amp;middot;서피스&lt;/b&gt;가 시드만으로 부족하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;copyWith로 세밀 조정합니다.&lt;/p&gt;
&lt;h3 id=&quot;53-%ED%85%8C%EB%A7%88-%ED%8C%8C%EC%9D%BC-%EC%98%88%EC%8B%9C%EC%83%88-%ED%8C%8C%EC%9D%BC&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;145&quot; data-ke-size=&quot;size23&quot;&gt;5.3 테마 파일 예시(새 파일)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;147&quot; data-ke-size=&quot;size16&quot;&gt;lib/theme/app_theme.dart를 두고&lt;span&gt;&amp;nbsp;&lt;/span&gt;MaterialApp의&lt;span&gt;&amp;nbsp;&lt;/span&gt;theme에 연결합니다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;import 'package:flutter/material.dart';

class AppTheme {
  AppTheme._();

  /// DESIGN.md의 primary 색을 시드로 (hex는 문서에서 복사)
  static ThemeData light(Color seed) {
    final scheme = ColorScheme.fromSeed(
      seedColor: seed,
      brightness: Brightness.light,
    );
    return ThemeData(
      useMaterial3: true,
      colorScheme: scheme,
      textTheme: _textTheme(scheme),
      visualDensity: VisualDensity.adaptivePlatformDensity,
    );
  }

  static TextTheme _textTheme(ColorScheme scheme) {
    const font = 'Noto Sans'; // DESIGN.md에 맞게 변경; pubspec fonts 항목 필요
    return TextTheme(
      titleLarge: TextStyle(
        fontFamily: font,
        fontWeight: FontWeight.w600,
        fontSize: 28,
        color: scheme.onSurface,
      ),
      bodyMedium: TextStyle(
        fontFamily: font,
        fontSize: 16,
        color: scheme.onSurface,
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;188&quot; data-ke-size=&quot;size16&quot;&gt;main.dart에서는 예를 들어:&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;theme: AppTheme.light(const Color(0xFF6750A4)),
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;194&quot; data-ke-size=&quot;size16&quot;&gt;실제 시드 색은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;DESIGN.md의 Primary&lt;/b&gt;를 사용합니다. 커스텀 폰트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;pubspec.yaml의&lt;span&gt;&amp;nbsp;&lt;/span&gt;fonts:에 등록해야 합니다.&lt;/p&gt;
&lt;hr data-line=&quot;196&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;6-phase-d--cursor%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EC%9A%A9-flutter-%EC%9D%B4%EA%B4%80-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%98%88%EC%8B%9C&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;198&quot; data-ke-size=&quot;size26&quot;&gt;6. Phase D &amp;mdash; Cursor/에이전트용 Flutter 이관 프롬프트 예시&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;200&quot; data-ke-size=&quot;size16&quot;&gt;Flutter 레포 루트에서:&lt;/p&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;@docs/DESIGN.md 와 reference/todo_od_preview.html (실제 경로로 바꿀 것) 을 참고해서
Material 3 TODO 화면을 구현해 줘.

요구사항:
- lib/theme/app_theme.dart 의 ColorScheme/TextTheme가 DESIGN.md의 팔레트&amp;middot;타이포와 일치하도록 조정
- lib/features/todo/todo_page.dart 에서: 입력, 필터(전체/진행/완료), ListView.builder, 삭제
- 완료 항목은 TextDecoration.lineThrough + Theme의 onSurfaceVariant
- 최소 터치 영역 48 이상
- 상태는 우선 StatefulWidget; Todo 모델은 immutable 클래스로
- 이후 shared_preferences로 직렬화할 수 있도록 Todo 리스트를 List&amp;lt;Todo&amp;gt;로 분리
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-line=&quot;215&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;7-phase-e--%EC%B6%94%EC%B2%9C-%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC-%EA%B5%AC%EC%A1%B0%EC%98%88%EC%8B%9C&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;217&quot; data-ke-size=&quot;size26&quot;&gt;7. Phase E &amp;mdash; 추천 디렉터리 구조(예시)&lt;/h2&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;background-color: #f6f8fa; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;todo_app/
├── docs/
│   └── DESIGN.md
├── reference/                    # git에 넣어도 되고 로컬만이어도 됨
│   ├── todo_od_artifact.html
│   └── preview.png
├── lib/
│   ├── main.dart
│   ├── theme/
│   │   └── app_theme.dart
│   ├── features/
│   │   └── todo/
│   │       ├── todo_page.dart
│   │       ├── todo_model.dart
│   │       └── todo_storage.dart   # shared_preferences 래퍼
│   └── widgets/
│       └── todo_tile.dart
└── README.md
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-line=&quot;240&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;8-phase-f--%EC%83%81%ED%83%9C%EC%99%80-%EC%A0%80%EC%9E%A5%EA%B6%8C%EC%9E%A5-%EC%88%9C%EC%84%9C&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;242&quot; data-ke-size=&quot;size26&quot;&gt;8. Phase F &amp;mdash; 상태와 저장(권장 순서)&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;244&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-line=&quot;244&quot;&gt;&lt;b&gt;Todo&lt;span&gt;&amp;nbsp;&lt;/span&gt;모델&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash;&lt;span&gt;&amp;nbsp;&lt;/span&gt;id,&lt;span&gt;&amp;nbsp;&lt;/span&gt;title,&lt;span&gt;&amp;nbsp;&lt;/span&gt;completed&lt;span&gt;&amp;nbsp;&lt;/span&gt;(필요 시&lt;span&gt;&amp;nbsp;&lt;/span&gt;priority&lt;span&gt;&amp;nbsp;&lt;/span&gt;등).&lt;/li&gt;
&lt;li data-line=&quot;245&quot;&gt;&lt;b&gt;TodoPage&lt;span&gt;&amp;nbsp;&lt;/span&gt;+&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 필터&amp;middot;CRUD.&lt;/li&gt;
&lt;li data-line=&quot;246&quot;&gt;&lt;b&gt;todo_storage.dart&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash;&lt;span&gt;&amp;nbsp;&lt;/span&gt;List&amp;lt;Todo&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;harr; JSON 문자열 &amp;harr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;shared_preferences.&lt;/li&gt;
&lt;li data-line=&quot;247&quot;&gt;&lt;b&gt;로딩 순서&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash;&lt;span&gt;&amp;nbsp;&lt;/span&gt;initState에서 비동기 로드 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;249&quot; data-ke-size=&quot;size16&quot;&gt;OD 단계에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;저장소 없이&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;UI만 맞추고, Flutter에서 로직을 얹는 패턴이 Next 가이드와 동일합니다.&lt;/p&gt;
&lt;hr data-line=&quot;251&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;9-%EB%B0%98%EB%B3%B5-%EC%9B%8C%ED%81%AC%ED%94%8C%EB%A1%9C%EC%9A%B0%EB%94%94%EC%9E%90%EC%9D%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%9C%A0%EC%A7%80&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;253&quot; data-ke-size=&quot;size26&quot;&gt;9. 반복 워크플로우(디자인 시스템 유지)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;255&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-line=&quot;255&quot;&gt;**OD에서 항상 같은&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESIGN.md**를 선택한다.&lt;/li&gt;
&lt;li data-line=&quot;256&quot;&gt;라벨&amp;middot;카드 레이아웃만 바꿀 때: OD에 짧은 브리프로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;HTML만 재생성&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr; 스크린샷 비교 &amp;rarr; Flutter에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;위젯&amp;middot;테마 일부만&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;수정.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;258&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;디자인 시스템 문서는 고정&lt;/b&gt;하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;화면 실험만 OD&lt;/b&gt;에서 하는 흐름이 유지됩니다.&lt;/p&gt;
&lt;hr data-line=&quot;260&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;10-%EC%9E%90%EC%A3%BC-%ED%95%98%EB%8A%94-%EC%8B%A4%EC%88%98%EC%99%80-%EB%8C%80%EC%9D%91&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;262&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 style=&quot;background-color: #ffffff; color: #24292e; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-line=&quot;264&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-line=&quot;266&quot;&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot; data-line=&quot;266&quot;&gt;
&lt;td&gt;HTML 시안과 Flutter 색이 다름&lt;/td&gt;
&lt;td&gt;DESIGN.md의 hex를 기준으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;Color(...)를 다시 맞춤. 시안 HTML은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;참고용&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot; data-line=&quot;267&quot;&gt;
&lt;td&gt;폰트가 안 맞음&lt;/td&gt;
&lt;td&gt;pubspec.yaml에 폰트 등록 여부 확인. 시스템 폰트만 쓸 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESIGN.md와의 차이를 문서화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot; data-line=&quot;268&quot;&gt;
&lt;td&gt;OD&lt;span&gt;&amp;nbsp;&lt;/span&gt;mobile-app&lt;span&gt;&amp;nbsp;&lt;/span&gt;스킬이 웹 프레임 위에만 있음&lt;/td&gt;
&lt;td&gt;시안은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;토큰&amp;middot;비율&lt;/b&gt;이 중요; 기기 프리뷰는 시뮬레이터에서 최종 검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot; data-line=&quot;269&quot;&gt;
&lt;td&gt;테마가 위젯 곳곳에 하드코딩&lt;/td&gt;
&lt;td&gt;Theme.of(context).colorScheme,&lt;span&gt;&amp;nbsp;&lt;/span&gt;textTheme만 사용하도록 리뷰 규칙화&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-line=&quot;279&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;12-%EC%9A%94%EC%95%BD&quot; style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;281&quot; data-ke-size=&quot;size26&quot;&gt;12. 요약&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;283&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-line=&quot;283&quot;&gt;OD에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;DESIGN.md&lt;span&gt;&amp;nbsp;&lt;/span&gt;+ 디자인 시스템&lt;/b&gt;을 고정하고, TODO 화면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;HTML 시안&lt;/b&gt;을 만든다.&lt;/li&gt;
&lt;li data-line=&quot;284&quot;&gt;&lt;b&gt;DESIGN.md를 Flutter 레포에 복사&lt;/b&gt;해 계약으로 삼는다.&lt;/li&gt;
&lt;li data-line=&quot;285&quot;&gt;&lt;b&gt;ThemeData로 토큰을 코드화&lt;/b&gt;하고, 시안은 레이아웃&amp;middot;위계 참고용으로 쓴다.&lt;/li&gt;
&lt;li data-line=&quot;286&quot;&gt;기능&amp;middot;저장은 Flutter에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;표준 구조&lt;/b&gt;로 얹고, 변경 시&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;같은 DS로 OD만 재실행&lt;/b&gt;해 차이를 줄인다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #24292e; text-align: start;&quot; data-line=&quot;288&quot; data-ke-size=&quot;size16&quot;&gt;Flutter에는 OD HTML을 그대로 임베드할 수 없으므로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;연동의 핵심은&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESIGN.md&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;ThemeData/스타일 상수&lt;/b&gt;이고, HTML은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;레퍼런스&lt;/b&gt;입니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1757</guid>
      <comments>https://javaexpert.tistory.com/1757#entry1757comment</comments>
      <pubDate>Mon, 4 May 2026 10:56:46 +0900</pubDate>
    </item>
    <item>
      <title>당신은 하나의 텍스트 파일입니다</title>
      <link>https://javaexpert.tistory.com/1756</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;당신은 하나의 텍스트 파일입니다&lt;/title&gt;
&lt;style&gt;
  @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@400;600;700&amp;family=Noto+Sans+KR:wght@300;400;500;600&amp;family=Fira+Code:wght@400;500&amp;display=swap');

  :root {
    --bg: #fafaf8;
    --text: #1a1a1a;
    --text-secondary: #666;
    --text-light: #999;
    --accent: #e8572a;
    --accent-soft: #fff3ef;
    --border: #e8e6e1;
    --code-bg: #282c34;
    --code-text: #abb2bf;
    --inline-code-bg: #f0ede8;
    --card-bg: #ffffff;
    --shadow: 0 1px 4px rgba(0,0,0,0.04);
  }

  * { margin: 0; padding: 0; box-sizing: border-box; }

  body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Noto Sans KR', -apple-system, sans-serif;
    font-size: 17px;
    line-height: 1.9;
    -webkit-font-smoothing: antialiased;
  }

  /* ── Header ── */
  .header {
    text-align: center;
    padding: 100px 24px 60px;
    max-width: 680px;
    margin: 0 auto;
  }

  .header .topic {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 20px;
    padding: 4px 16px;
    margin-bottom: 32px;
  }

  .header h1 {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    line-height: 1.45;
    letter-spacing: -0.5px;
    margin-bottom: 24px;
  }

  .header .subtitle {
    font-size: 18px;
    color: var(--text-secondary);
    line-height: 1.8;
    font-weight: 300;
  }

  .header .meta {
    margin-top: 40px;
    font-size: 14px;
    color: var(--text-light);
  }

  .divider {
    max-width: 680px;
    margin: 0 auto;
    border: none;
    border-top: 1px solid var(--border);
  }

  /* ── Article ── */
  .article {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 24px;
  }

  .article h2 {
    font-family: 'Noto Serif KR', serif;
    font-size: 26px;
    font-weight: 700;
    margin: 80px 0 24px;
    line-height: 1.4;
    letter-spacing: -0.3px;
  }

  .article h3 {
    font-family: 'Noto Serif KR', serif;
    font-size: 20px;
    font-weight: 600;
    margin: 48px 0 16px;
    line-height: 1.5;
  }

  .article h4 {
    font-family: 'Noto Serif KR', serif;
    font-size: 17px;
    font-weight: 600;
    margin: 36px 0 12px;
    line-height: 1.5;
  }

  .article p {
    margin-bottom: 20px;
  }

  .article strong {
    font-weight: 600;
  }

  .article em {
    font-style: normal;
    color: var(--accent);
    font-weight: 500;
  }

  .article ul, .article ol {
    margin: 16px 0 24px 20px;
  }

  .article li {
    margin-bottom: 8px;
  }

  /* ── Quote Block ── */
  .quote-block {
    border-left: 3px solid var(--accent);
    padding: 20px 28px;
    margin: 32px 0;
    background: var(--accent-soft);
    border-radius: 0 8px 8px 0;
  }

  .quote-block p {
    margin-bottom: 0;
    font-size: 16px;
  }

  /* ── Inline Code ── */
  code {
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 0.88em;
    background: var(--inline-code-bg);
    padding: 2px 7px;
    border-radius: 4px;
    color: var(--accent);
  }

  /* ── Code Block ── */
  .code-block {
    margin: 28px 0;
    border-radius: 10px;
    overflow: hidden;
    background: var(--code-bg);
    box-shadow: 0 2px 12px rgba(0,0,0,0.12);
  }

  .code-block .code-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: #21252b;
    border-bottom: 1px solid #181a1f;
  }

  .code-block .code-header .lang-label {
    font-family: 'Fira Code', monospace;
    font-size: 12px;
    color: #636d83;
    text-transform: uppercase;
    letter-spacing: 1px;
  }

  .copy-btn {
    background: none;
    border: 1px solid #3e4451;
    color: #636d83;
    font-family: 'Fira Code', monospace;
    font-size: 11px;
    padding: 3px 10px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
    letter-spacing: 0.5px;
  }

  .copy-btn:hover {
    border-color: #abb2bf;
    color: #abb2bf;
  }

  .copy-btn.copied {
    border-color: #98c379;
    color: #98c379;
  }

  .code-block .code-header .dots {
    display: flex;
    gap: 6px;
  }

  .code-block .code-header .dots span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
  }

  .code-block .code-header .dots span:nth-child(1) { background: #ff5f57; }
  .code-block .code-header .dots span:nth-child(2) { background: #febc2e; }
  .code-block .code-header .dots span:nth-child(3) { background: #28c840; }

  .code-block pre {
    padding: 20px 24px;
    overflow-x: auto;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.7;
    color: var(--code-text);
    tab-size: 2;
  }

  .code-block pre .line-num {
    display: inline-block;
    width: 36px;
    color: #4b5263;
    text-align: right;
    margin-right: 20px;
    user-select: none;
    -webkit-user-select: none;
  }

  /* Syntax Highlighting */
  .code-block pre .keyword   { color: #c678dd; }
  .code-block pre .string    { color: #98c379; }
  .code-block pre .number    { color: #d19a66; }
  .code-block pre .comment   { color: #5c6370; font-style: italic; }
  .code-block pre .function  { color: #61afef; }
  .code-block pre .operator  { color: #56b6c2; }
  .code-block pre .type      { color: #e5c07b; }
  .code-block pre .variable  { color: #e06c75; }
  .code-block pre .tag       { color: #e06c75; }
  .code-block pre .attr      { color: #d19a66; }
  .code-block pre .punct     { color: #abb2bf; }
  .code-block pre .property  { color: #e06c75; }
  .code-block pre .selector  { color: #98c379; }
  .code-block pre .value     { color: #d19a66; }

  /* ── Feature Cards ── */
  .feature-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin: 32px 0;
  }

  .feature-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 24px;
    box-shadow: var(--shadow);
    transition: transform 0.2s, box-shadow 0.2s;
  }

  .feature-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  }

  .feature-card .icon {
    font-size: 28px;
    margin-bottom: 12px;
  }

  .feature-card .title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 6px;
  }

  .feature-card .desc {
    font-size: 14px;
    color: var(--text-secondary);
    line-height: 1.6;
  }

  /* ── Pipeline / Step Flow ── */
  .pipeline {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 32px 28px;
    margin: 32px 0;
    box-shadow: var(--shadow);
  }

  .pipeline .step {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 14px 0;
    position: relative;
  }

  .pipeline .step:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 15px;
    top: 48px;
    bottom: -2px;
    width: 2px;
    background: var(--border);
  }

  .pipeline .step-num {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .pipeline .step-content {
    flex: 1;
    padding-top: 4px;
  }

  .pipeline .step-title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 2px;
  }

  .pipeline .step-desc {
    font-size: 14px;
    color: var(--text-secondary);
  }

  /* ── Example Card ── */
  .example-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    margin: 32px 0;
    overflow: hidden;
    box-shadow: var(--shadow);
  }

  .example-card .example-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .example-card .example-num {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .example-card .example-title {
    font-weight: 600;
    font-size: 16px;
  }

  .example-card .example-body {
    padding: 24px;
  }

  .prompt-box {
    background: #f8f7f4;
    border-radius: 8px;
    padding: 16px 20px;
    margin-bottom: 20px;
    font-size: 15px;
    line-height: 1.7;
    color: var(--text);
    border-left: 3px solid var(--accent);
  }

  .prompt-box .label {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 8px;
  }

  .process-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .process-list li {
    padding: 6px 0 6px 24px;
    position: relative;
    font-size: 15px;
    color: var(--text-secondary);
  }

  .process-list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 14px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border);
  }

  .process-list li:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 26px;
    bottom: -8px;
    width: 2px;
    background: var(--border);
  }

  .result-tag {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    background: var(--accent-soft);
    padding: 4px 12px;
    border-radius: 4px;
    margin-top: 16px;
  }

  /* ── Helper Table ── */
  .helper-table {
    width: 100%;
    border-collapse: collapse;
    margin: 24px 0;
    font-size: 15px;
  }

  .helper-table th {
    text-align: left;
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-light);
    padding: 12px 16px;
    border-bottom: 2px solid var(--border);
  }

  .helper-table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
  }

  /* ── Directory Tree ── */
  .dir-tree {
    background: #f5f3ef;
    border-radius: 8px;
    padding: 24px;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.8;
    color: var(--text-secondary);
    margin: 24px 0;
  }

  .dir-tree .file { color: var(--text); display: block; }
  .dir-tree .comment { color: var(--text-light); font-family: 'Noto Sans KR', sans-serif; font-size: 13px; }

  /* ── Rule List ── */
  .rule-list {
    counter-reset: rule;
    list-style: none;
    margin: 24px 0;
    padding: 0;
  }

  .rule-list li {
    counter-increment: rule;
    padding: 14px 16px 14px 56px;
    position: relative;
    border-bottom: 1px solid var(--border);
    font-size: 15px;
  }

  .rule-list li::before {
    content: counter(rule, decimal-leading-zero);
    position: absolute;
    left: 16px;
    top: 14px;
    font-family: 'Fira Code', monospace;
    font-size: 13px;
    color: var(--accent);
    font-weight: 600;
  }

  .rule-list li:last-child {
    border-bottom: none;
  }

  /* ── Image ── */
  .article img {
    max-width: 100%;
    border-radius: 8px;
    margin: 16px 0;
  }

  .article figcaption {
    font-size: 14px;
    color: var(--text-light);
    text-align: center;
    margin-top: 8px;
  }

  /* ── Callout ── */
  .callout {
    display: flex;
    gap: 16px;
    padding: 20px 24px;
    border-radius: 8px;
    margin: 28px 0;
  }

  .callout.info {
    background: #edf4fc;
    border-left: 3px solid #3b82f6;
  }

  .callout.warning {
    background: #fef9ec;
    border-left: 3px solid #f59e0b;
  }

  .callout.tip {
    background: #ecfdf5;
    border-left: 3px solid #10b981;
  }

  .callout .callout-icon {
    font-size: 20px;
    flex-shrink: 0;
    padding-top: 2px;
  }

  .callout .callout-body {
    flex: 1;
  }

  .callout .callout-body p {
    margin-bottom: 0;
    font-size: 15px;
  }

  /* ── Footer ── */
  .footer {
    max-width: 680px;
    margin: 80px auto 0;
    padding: 40px 24px;
    border-top: 1px solid var(--border);
    text-align: center;
    font-size: 14px;
    color: var(--text-light);
  }

  .footer a {
    color: var(--accent);
    text-decoration: none;
  }

  /* ── Responsive ── */
  @media (max-width: 640px) {
    .header { padding: 60px 20px 40px; }
    .header h1 { font-size: 26px; }
    .feature-grid { grid-template-columns: 1fr; }
    .article h2 { font-size: 22px; }
    .code-block pre { font-size: 12px; }
  }

  /* ── Scroll-triggered Animations ── */
  @keyframes fadeInUp {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: translateY(0); }
  }

  @keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  .animate-on-scroll {
    opacity: 0;
    transition: none;
  }

  .animate-on-scroll.visible {
    animation: fadeInUp 0.6s ease-out forwards;
  }

  .animate-on-scroll.visible-delay-1 { animation-delay: 0.1s; }
  .animate-on-scroll.visible-delay-2 { animation-delay: 0.2s; }
  .animate-on-scroll.visible-delay-3 { animation-delay: 0.3s; }

  /* ── Header Entrance ── */
  .header .topic {
    animation: fadeIn 0.8s ease-out 0.2s both;
  }

  .header h1 {
    animation: fadeInUp 0.8s ease-out 0.4s both;
  }

  .header .subtitle {
    animation: fadeInUp 0.8s ease-out 0.6s both;
  }

  .header .meta {
    animation: fadeIn 0.8s ease-out 0.8s both;
  }

  /* ── Audio Waveform Animation ── */
  .waveform {
    display: flex;
    align-items: center;
    gap: 3px;
    height: 32px;
    margin: 24px 0;
  }

  .waveform .bar {
    width: 4px;
    border-radius: 2px;
    background: var(--accent);
    animation: wave 1.2s ease-in-out infinite;
  }

  .waveform .bar:nth-child(1)  { animation-delay: 0s; }
  .waveform .bar:nth-child(2)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(3)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(4)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(5)  { animation-delay: 0.4s; }
  .waveform .bar:nth-child(6)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(7)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(8)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(9)  { animation-delay: 0s; }
  .waveform .bar:nth-child(10) { animation-delay: 0.1s; }
  .waveform .bar:nth-child(11) { animation-delay: 0.2s; }
  .waveform .bar:nth-child(12) { animation-delay: 0.3s; }

  @keyframes wave {
    0%, 100% { height: 8px; opacity: 0.4; }
    50% { height: 28px; opacity: 1; }
  }

  /* ── Animated Progress Bar ── */
  .progress-bar {
    background: var(--border);
    border-radius: 4px;
    height: 6px;
    margin: 24px 0;
    overflow: hidden;
  }

  .progress-bar .fill {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--accent), #f4845f);
    animation: progressFill 2s ease-out forwards;
    transform-origin: left;
  }

  @keyframes progressFill {
    from { width: 0; }
  }

  /* ── Typing Effect ── */
  .typing {
    font-family: 'Fira Code', monospace;
    font-size: 15px;
    color: var(--text);
    border-right: 2px solid var(--accent);
    white-space: nowrap;
    overflow: hidden;
    animation: typing 3s steps(40) forwards, blink 0.8s step-end infinite;
    width: 0;
  }

  @keyframes typing {
    to { width: 100%; }
  }

  @keyframes blink {
    50% { border-color: transparent; }
  }

  /* ── Pulse Dot ── */
  .pulse-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    margin-right: 8px;
    animation: pulse 2s ease-in-out infinite;
  }

  @keyframes pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.5); opacity: 0.5; }
  }

  /* ── Floating Badge ── */
  .float-badge {
    display: inline-block;
    font-size: 12px;
    font-weight: 600;
    color: white;
    background: var(--accent);
    padding: 4px 12px;
    border-radius: 12px;
    animation: float 3s ease-in-out infinite;
  }

  @keyframes float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-4px); }
  }

  /* ── Shimmer Loading ── */
  .shimmer {
    background: linear-gradient(90deg, var(--border) 25%, #f0ede8 50%, var(--border) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    border-radius: 4px;
    height: 16px;
    margin: 8px 0;
  }

  @keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
  }

  /* ── Animated Counter ── */
  .counter {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    color: var(--accent);
  }

  /* ── Bouncing Arrow ── */
  .bounce-arrow {
    display: inline-block;
    animation: bounce 1.5s ease-in-out infinite;
    color: var(--accent);
  }

  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(6px); }
  }

  /* ── Feature Card Stagger ── */
  .feature-grid .feature-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .feature-grid .feature-card:nth-child(1) { animation-delay: 0.1s; }
  .feature-grid .feature-card:nth-child(2) { animation-delay: 0.2s; }
  .feature-grid .feature-card:nth-child(3) { animation-delay: 0.3s; }
  .feature-grid .feature-card:nth-child(4) { animation-delay: 0.4s; }
  .feature-grid .feature-card:nth-child(5) { animation-delay: 0.5s; }
  .feature-grid .feature-card:nth-child(6) { animation-delay: 0.6s; }

  /* ── Pipeline Step Stagger ── */
  .pipeline .step {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .pipeline .step:nth-child(1) { animation-delay: 0.1s; }
  .pipeline .step:nth-child(2) { animation-delay: 0.3s; }
  .pipeline .step:nth-child(3) { animation-delay: 0.5s; }
  .pipeline .step:nth-child(4) { animation-delay: 0.7s; }

  /* ── Example Card Stagger ── */
  .example-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  /* ── Quote Block Slide-in ── */
  .quote-block {
    animation: slideInLeft 0.6s ease-out;
  }

  @keyframes slideInLeft {
    from { opacity: 0; transform: translateX(-20px); }
    to { opacity: 1; transform: translateX(0); }
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;header class=&quot;header&quot;&gt;
  &lt;div class=&quot;topic&quot;&gt;AI Writing&lt;/div&gt;
  &lt;h1&gt;당신은 하나의&lt;br&gt;텍스트 파일입니다&lt;/h1&gt;
  &lt;p class=&quot;subtitle&quot;&gt;AI가 당신 목소리로 말하게 만드는&lt;br&gt;단 두 시간의 작업&lt;/p&gt;
  &lt;div class=&quot;meta&quot;&gt;2025.05.03 &amp;middot; Ruben Hassid&lt;/div&gt;
&lt;/header&gt;
&lt;hr class=&quot;divider&quot;&gt;

&lt;article class=&quot;article&quot;&gt;

  &lt;p&gt;당신이 쓴 모든 글, 당신이 한 모든 말 &amp;mdash; 그 모든 것이 결국 하나의 파일로 압축될 수 있다면? 그리고 그 파일이 AI에게 당신의 목소리를 완벽하게 복제할 수 있다면?&lt;/p&gt;

  &lt;p&gt;이건 SF가 아닙니다. 지금 당장 할 수 있는 일입니다. 이름하여 &lt;em&gt;about-me.md&lt;/em&gt;.&lt;/p&gt;

  &lt;div class=&quot;quote-block&quot;&gt;
    &lt;p&gt;당신은 하나의 텍스트 파일입니다. 진짜입니다. 당신이 쓰는 모든 것 &amp;mdash; 이메일, 트윗, 블로그 글 &amp;mdash; 이 하나의 파일로 요약될 수 있습니다. 그리고 그 파일이 AI를 당신처럼 글 쓰게 만듭니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;왜 about-me.md인가&lt;/h2&gt;

  &lt;p&gt;대부분의 사람들은 AI에게 &amp;ldquo;나처럼 써줘&amp;rdquo;라고 말합니다. 그러면 AI는 그들이 무엇을 의미하는지 모릅니다. &amp;ldquo;나처럼&amp;rdquo;이란 무엇일까요? 짧은 문장? 긴 문장? 유머러스한 톤? 진지한 톤? 격식 있는? 격식 없는?&lt;/p&gt;

  &lt;p&gt;AI는 당신이 구체적으로 알려주지 않으면 &lt;em&gt;당신의 목소리를 찾을 수 없습니다&lt;/em&gt;. 그래서 필요한 것이 바로 당신의 글쓰기 DNA를 담은 파일입니다.&lt;/p&gt;

  &lt;div class=&quot;callout info&quot;&gt;
    &lt;div class=&quot;callout-icon&quot;&gt;i&lt;/div&gt;
    &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;&lt;code&gt;about-me.md&lt;/code&gt;는 당신의 글쓰기 스타일, 어조, 문장 구조, 선호하는 표현, 피하는 표현까지 모두 담은 개인화 파일입니다.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;두 시간이면 충분합니다&lt;/h2&gt;

  &lt;p&gt;이 작업에 걸리는 시간은 단 두 시간. 100개의 질문에 답하고, 그것을 압축하는 과정입니다. 복잡해 보이지만, 실제로는 아주 단순합니다.&lt;/p&gt;

  &lt;div class=&quot;pipeline&quot;&gt;
    &lt;div class=&quot;step&quot;&gt;
      &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
      &lt;div class=&quot;step-content&quot;&gt;
        &lt;div class=&quot;step-title&quot;&gt;Taste Interviewer &amp;mdash; 100문 인터뷰&lt;/div&gt;
        &lt;div class=&quot;step-desc&quot;&gt;Claude가 당신의 글쓰기 취향을 파악하기 위해 100개의 질문을 던집니다. 신념, 문장 메커니즘, 미적 기호, 목소리, 구조적 선호, 절대 하지 않을 것, 레드플래그 &amp;mdash; 7개 카테고리로 당신의 DNA를 추출합니다.&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;step&quot;&gt;
      &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
      &lt;div class=&quot;step-content&quot;&gt;
        &lt;div class=&quot;step-title&quot;&gt;Voice Compiler &amp;mdash; 음성 컴파일&lt;/div&gt;
        &lt;div class=&quot;step-desc&quot;&gt;인터뷰 결과를 2,000~4,000토큰의 XML 구조 파일로 압축합니다. 이것이 바로 당신의 &lt;code&gt;about-me.md&lt;/code&gt;가 됩니다.&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;어떻게 작동하나요&lt;/h2&gt;

  &lt;h3&gt;Step 1: Taste Interviewer 프롬프트&lt;/h3&gt;

  &lt;p&gt;Claude에게 다음 프롬프트를 전달하면 인터뷰가 시작됩니다. 7개 카테고리, 100개의 질문이 당신의 글쓰기 자아를 해체합니다.&lt;/p&gt;

  &lt;div class=&quot;code-block&quot;&gt;
    &lt;div class=&quot;code-header&quot;&gt;
      &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
      &lt;span class=&quot;lang-label&quot;&gt;prompt&lt;/span&gt;
    &lt;/div&gt;
    &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;당신은 &amp;ldquo;Taste Interviewer&amp;rdquo;입니다.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;목표: 나의 글쓰기 스타일, 어조, 문장 구조,&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  선호하는 표현과 피하는 표현을 파악하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;카테고리:&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;1. 신념 (Beliefs)&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;2. 문장 메커니즘 (Writing Mechanics)&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;3. 미적 기호 (Aesthetic Crimes)&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;4. 목소리와 성격 (Voice &amp;amp; Personality)&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;5. 구조적 선호 (Structural Preferences)&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;6. 절대 안 될 것 (Hard Nos)&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;7. 레드플래그 (Red Flags)&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;규칙:&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;- 한 번에 하나의 질문만 하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;- 내 답변에 깊이 파고들며 추적 질문을 하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;- 100개의 질문을 마친 후, 당신이 파악한&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  나의 글쓰기 DNA를 요약하세요.&lt;/span&gt;&lt;/pre&gt;
  &lt;/div&gt;

  &lt;h3&gt;Step 2: Voice Compiler 프롬프트&lt;/h3&gt;

  &lt;p&gt;인터뷰가 끝나면, 이번에는 그 결과물을 압축하는 프롬프트를 사용합니다.&lt;/p&gt;

  &lt;div class=&quot;code-block&quot;&gt;
    &lt;div class=&quot;code-header&quot;&gt;
      &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
      &lt;span class=&quot;lang-label&quot;&gt;prompt&lt;/span&gt;
    &lt;/div&gt;
    &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;위 인터뷰 결과를 바탕으로&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  &amp;lt;about-me&amp;gt; XML 구조로 압축하세요.&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;구조:&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;voice&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;tone&amp;gt;&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;...&amp;lt;/&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;tone&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;structure&amp;gt;&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;...&amp;lt;/&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;structure&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;vocabulary&amp;gt;&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;...&amp;lt;/&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;vocabulary&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;avoid&amp;gt;&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;...&amp;lt;/&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;avoid&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;personality&amp;gt;&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;...&amp;lt;/&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;personality&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/voice&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;제약:&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;- 2,000~4,000 토큰 이내&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;- XML 태그 사용&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;- 실용적이고 구체적으로 작성&lt;/span&gt;&lt;/pre&gt;
  &lt;/div&gt;

  &lt;h3&gt;Step 3: 테스트하고 다듬기&lt;/h3&gt;

  &lt;p&gt;완성된 &lt;code&gt;about-me.md&lt;/code를 Claude의 시스템 프롬프트에 넣고 테스트해보세요. 당신의 목소리로 글을 쓰는지 확인합니다. 어색한 부분이 있다면 파일을 수정하고 다시 테스트합니다.&lt;/p&gt;

  &lt;div class=&quot;callout tip&quot;&gt;
    &lt;div class=&quot;callout-icon&quot;&gt;!&lt;/div&gt;
    &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;Obsidian 같은 에디터로 &lt;code&gt;about-me.md&lt;/code&gt;를 열어 수시로 편집하세요. Claude Cowork를 사용하면 매 대화마다 이 파일을 자동으로 컨텍스트에 주입할 수 있습니다.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;파일 구조 예시&lt;/h2&gt;

  &lt;p&gt;완성된 파일은 대략 이런 구조를 가집니다.&lt;/p&gt;

  &lt;div class=&quot;dir-tree&quot;&gt;
&lt;span class=&quot;file&quot;&gt;about-me.md&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── &amp;lt;voice&amp;gt;&lt;/span&gt;     &lt;span class=&quot;comment&quot;&gt;# 최상위 태그&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;│   ├── &amp;lt;tone&amp;gt;&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 어조: 직관적, 대화형&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;│   ├── &amp;lt;structure&amp;gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# 문장 구조 선호&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;│   ├── &amp;lt;vocabulary&amp;gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# 자주 쓰는 표현&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;│   ├── &amp;lt;avoid&amp;gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# 절대 쓰지 않을 것&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;│   └── &amp;lt;personality&amp;gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# 글쓰기 성격&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;└── &amp;lt;/voice&amp;gt;&lt;/span&gt;
  &lt;/div&gt;

  &lt;h2&gt;사람들이 저항하는 네 가지 이유&lt;/h2&gt;

  &lt;p&gt;이 방법을 소개하면 항상 같은 반응이 돌아옵니다. 네 가지 저항을 미리 정리했습니다.&lt;/p&gt;

  &lt;div class=&quot;feature-grid&quot;&gt;
    &lt;div class=&quot;feature-card&quot;&gt;
      &lt;div class=&quot;icon&quot;&gt;&amp;#128560;&lt;/div&gt;
      &lt;div class=&quot;title&quot;&gt;&amp;ldquo;내 목소리를 기계에게?&amp;rdquo;&lt;/div&gt;
      &lt;div class=&quot;desc&quot;&gt;AI가 당신을 대체하는 게 아닙니다. AI가 당신의 목소리로 초안을 쓰고, 당신이 다듬는 겁니다. 손글씨를 타자기로 옮기는 것과 같습니다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;feature-card&quot;&gt;
      &lt;div class=&quot;icon&quot;&gt;&amp;#9200;&lt;/div&gt;
      &lt;div class=&quot;title&quot;&gt;&amp;ldquo;두 시간이나?&amp;rdquo;&lt;/div&gt;
      &lt;div class=&quot;desc&quot;&gt;매번 AI에게 &amp;ldquo;나처럼 써줘&amp;rdquo;라고 하고 수정하는 데 얼마나 걸리나요? 두 시간의 투자로 앞으로 수백 시간을 아낍니다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;feature-card&quot;&gt;
      &lt;div class=&quot;icon&quot;&gt;&amp;#128526;&lt;/div&gt;
      &lt;div class=&quot;title&quot;&gt;&amp;ldquo;난 내 스타일을 몰라&amp;rdquo;&lt;/div&gt;
      &lt;div class=&quot;desc&quot;&gt;그게 바로 인터뷰가 필요한 이유입니다. 100개의 질문이 당신도 몰랐던 패턴을 찾아냅니다. 자신의 글쓰기를 발견하는 과정 자체가 가치 있습니다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;feature-card&quot;&gt;
      &lt;div class=&quot;icon&quot;&gt;&amp;#128640;&lt;/div&gt;
      &lt;div class=&quot;title&quot;&gt;&amp;ldquo;그냥 프롬프트만 잘 쓰면 되잖아&amp;rdquo;&lt;/div&gt;
      &lt;div class=&quot;desc&quot;&gt;프롬프트는 단발성입니다. &lt;code&gt;about-me.md&lt;/code&gt;는 영구적입니다. 한 번 만들면 모든 AI 도구에 재사용할 수 있는 당신만의 디지털 DNA입니다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;실제 사용 사례&lt;/h2&gt;

  &lt;div class=&quot;example-card&quot;&gt;
    &lt;div class=&quot;example-header&quot;&gt;
      &lt;div class=&quot;example-num&quot;&gt;1&lt;/div&gt;
      &lt;div class=&quot;example-title&quot;&gt;블로그 글 작성&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;example-body&quot;&gt;
      &lt;div class=&quot;prompt-box&quot;&gt;
        &lt;div class=&quot;label&quot;&gt;Before about-me.md&lt;/div&gt;
        &amp;ldquo;AI한테 블로그 글 써달라고 했더니 백과사전 같은 글이 나왔다. 내 목소리가 아니다. 다시 써달라고 했더니 또 다른 사람 글이 나왔다.&amp;rdquo;
      &lt;/div&gt;
      &lt;div class=&quot;prompt-box&quot;&gt;
        &lt;div class=&quot;label&quot;&gt;After about-me.md&lt;/div&gt;
        &amp;ldquo;시스템 프롬프트에 about-me.md를 넣으니, 첫 번째 초안부터 내 목소리가 느껴졌다. 수정은 미세한 부분뿐이었다.&amp;rdquo;
      &lt;/div&gt;
      &lt;div class=&quot;result-tag&quot;&gt;초안 작성 시간 80% 단축&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;example-card&quot;&gt;
    &lt;div class=&quot;example-header&quot;&gt;
      &lt;div class=&quot;example-num&quot;&gt;2&lt;/div&gt;
      &lt;div class=&quot;example-title&quot;&gt;이메일 작성&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;example-body&quot;&gt;
      &lt;div class=&quot;prompt-box&quot;&gt;
        &lt;div class=&quot;label&quot;&gt;Before about-me.md&lt;/div&gt;
        &amp;ldquo;매번 '격식 있으면서도 친근하게'라고 적어줘야 했다. 결과는 항상 제각각이었다.&amp;rdquo;
      &lt;/div&gt;
      &lt;div class=&quot;prompt-box&quot;&gt;
        &lt;div class=&quot;label&quot;&gt;After about-me.md&lt;/div&gt;
        &amp;ldquo;이제 '이 내용으로 이메일 하나 써줘'라고만 하면 된다. 어조, 길이, 포맷 &amp;mdash; 전부 내 스타일로 나온다.&amp;rdquo;
      &lt;/div&gt;
      &lt;div class=&quot;result-tag&quot;&gt;이메일 초안 수정 횟수 90% 감소&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;시작하는 방법&lt;/h2&gt;

  &lt;ol class=&quot;rule-list&quot;&gt;
    &lt;li&gt;Claude를 열고 &lt;em&gt;Taste Interviewer&lt;/em&gt; 프롬프트를 붙여넣으세요&lt;/li&gt;
    &lt;li&gt;100개의 질문에 솔직하게 답하세요. 대략 1~1.5시간이 걸립니다&lt;/li&gt;
    &lt;li&gt;인터뷰가 끝나면 &lt;em&gt;Voice Compiler&lt;/em&gt; 프롬프트를 사용해 결과를 압축하세요&lt;/li&gt;
    &lt;li&gt;완성된 파일을 &lt;code&gt;about-me.md&lt;/code&gt;로 저장하고, Obsidian 등에서 편집하세요&lt;/li&gt;
    &lt;li&gt;Claude Cowork나 시스템 프롬프트에 파일을 넣고 테스트하세요&lt;/li&gt;
    &lt;li&gt;어색한 부분이 있으면 파일을 수정하고 다시 테스트하세요. 반복이 핵심입니다&lt;/li&gt;
  &lt;/ol&gt;

  &lt;div class=&quot;progress-bar&quot;&gt;
    &lt;div class=&quot;fill&quot; style=&quot;width: 100%;&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;quote-block&quot;&gt;
    &lt;p&gt;당신은 하나의 텍스트 파일입니다. 그 파일을 만드는 데 두 시간이면 충분합니다. 그 두 시간이 앞으로 당신의 모든 글쓰기를 바꿀 것입니다. 시작하세요. 지금 바로.&lt;/p&gt;
  &lt;/div&gt;

&lt;/article&gt;

&lt;footer class=&quot;footer&quot;&gt;
  &lt;p&gt;Written by &lt;strong&gt;Ruben Hassid&lt;/strong&gt; (@rubenhassid)&lt;/p&gt;
  &lt;p style=&quot;margin-top: 8px;&quot;&gt;&lt;a href=&quot;https://x.com/i/status/2050787472666399042&quot;&gt;원문 보기 &amp;mdash; X (Twitter)&lt;/a&gt;&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
document.querySelectorAll('.code-block').forEach(function(block) {
  var header = block.querySelector('.code-header');
  var pre = block.querySelector('pre');
  if (!header || !pre) return;
  var btn = document.createElement('button');
  btn.className = 'copy-btn';
  btn.textContent = 'COPY';
  btn.addEventListener('click', function() {
    var text = pre.innerText.replace(/^\d+\s*/gm, '');
    navigator.clipboard.writeText(text).then(function() {
      btn.textContent = 'COPIED';
      btn.classList.add('copied');
      setTimeout(function() {
        btn.textContent = 'COPY';
        btn.classList.remove('copied');
      }, 2000);
    });
  });
  header.appendChild(btn);
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1756</guid>
      <comments>https://javaexpert.tistory.com/1756#entry1756comment</comments>
      <pubDate>Sun, 3 May 2026 20:14:21 +0900</pubDate>
    </item>
    <item>
      <title>mattpocock/skills &amp;mdash; AI 코딩 에이전트를 실무 개발 프로세스에 맞추는 스킬 패키지</title>
      <link>https://javaexpert.tistory.com/1755</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;mattpocock/skills — AI 코딩 에이전트를 실무 개발 프로세스에 맞추는 스킬 패키지&lt;/title&gt;
&lt;style&gt;
  @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@400;600;700&amp;family=Noto+Sans+KR:wght@300;400;500;600&amp;family=Fira+Code:wght@400;500&amp;display=swap');

  :root {
    --bg: #fafaf8;
    --text: #1a1a1a;
    --text-secondary: #666;
    --text-light: #999;
    --accent: #e8572a;
    --accent-soft: #fff3ef;
    --border: #e8e6e1;
    --code-bg: #282c34;
    --code-text: #abb2bf;
    --inline-code-bg: #f0ede8;
    --card-bg: #ffffff;
    --shadow: 0 1px 4px rgba(0,0,0,0.04);
  }

  * { margin: 0; padding: 0; box-sizing: border-box; }

  body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Noto Sans KR', -apple-system, sans-serif;
    font-size: 17px;
    line-height: 1.9;
    -webkit-font-smoothing: antialiased;
  }

  .header {
    text-align: center;
    padding: 100px 24px 60px;
    max-width: 680px;
    margin: 0 auto;
  }

  .header .topic {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 20px;
    padding: 4px 16px;
    margin-bottom: 32px;
  }

  .header h1 {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    line-height: 1.45;
    letter-spacing: -0.5px;
    margin-bottom: 24px;
  }

  .header .subtitle {
    font-size: 18px;
    color: var(--text-secondary);
    line-height: 1.8;
    font-weight: 300;
  }

  .header .meta {
    margin-top: 40px;
    font-size: 14px;
    color: var(--text-light);
  }

  .divider {
    max-width: 680px;
    margin: 0 auto;
    border: none;
    border-top: 1px solid var(--border);
  }

  .article {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 24px;
  }

  .article h2 {
    font-family: 'Noto Serif KR', serif;
    font-size: 26px;
    font-weight: 700;
    margin: 80px 0 24px;
    line-height: 1.4;
    letter-spacing: -0.3px;
  }

  .article h3 {
    font-family: 'Noto Serif KR', serif;
    font-size: 20px;
    font-weight: 600;
    margin: 48px 0 16px;
    line-height: 1.5;
  }

  .article h4 {
    font-family: 'Noto Serif KR', serif;
    font-size: 17px;
    font-weight: 600;
    margin: 36px 0 12px;
    line-height: 1.5;
  }

  .article p { margin-bottom: 20px; }
  .article strong { font-weight: 600; }

  .article em {
    font-style: normal;
    color: var(--accent);
    font-weight: 500;
  }

  .article ul, .article ol { margin: 16px 0 24px 20px; }
  .article li { margin-bottom: 8px; }

  .quote-block {
    border-left: 3px solid var(--accent);
    padding: 20px 28px;
    margin: 32px 0;
    background: var(--accent-soft);
    border-radius: 0 8px 8px 0;
  }

  .quote-block p { margin-bottom: 0; font-size: 16px; }

  code {
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 0.88em;
    background: var(--inline-code-bg);
    padding: 2px 7px;
    border-radius: 4px;
    color: var(--accent);
  }

  .code-block {
    margin: 28px 0;
    border-radius: 10px;
    overflow: hidden;
    background: var(--code-bg);
    box-shadow: 0 2px 12px rgba(0,0,0,0.12);
  }

  .code-block .code-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: #21252b;
    border-bottom: 1px solid #181a1f;
  }

  .code-block .code-header .lang-label {
    font-family: 'Fira Code', monospace;
    font-size: 12px;
    color: #636d83;
    text-transform: uppercase;
    letter-spacing: 1px;
  }

  .copy-btn {
    background: none;
    border: 1px solid #3e4451;
    color: #636d83;
    font-family: 'Fira Code', monospace;
    font-size: 11px;
    padding: 3px 10px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
    letter-spacing: 0.5px;
  }

  .copy-btn:hover { border-color: #abb2bf; color: #abb2bf; }
  .copy-btn.copied { border-color: #98c379; color: #98c379; }

  .code-block .code-header .dots { display: flex; gap: 6px; }
  .code-block .code-header .dots span { width: 10px; height: 10px; border-radius: 50%; }
  .code-block .code-header .dots span:nth-child(1) { background: #ff5f57; }
  .code-block .code-header .dots span:nth-child(2) { background: #febc2e; }
  .code-block .code-header .dots span:nth-child(3) { background: #28c840; }

  .code-block pre {
    padding: 20px 24px;
    overflow-x: auto;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.7;
    color: var(--code-text);
    tab-size: 2;
  }

  .code-block pre .line-num {
    display: inline-block;
    width: 36px;
    color: #4b5263;
    text-align: right;
    margin-right: 20px;
    user-select: none;
    -webkit-user-select: none;
  }

  .code-block pre .keyword   { color: #c678dd; }
  .code-block pre .string    { color: #98c379; }
  .code-block pre .number    { color: #d19a66; }
  .code-block pre .comment   { color: #5c6370; font-style: italic; }
  .code-block pre .function  { color: #61afef; }
  .code-block pre .operator  { color: #56b6c2; }
  .code-block pre .type      { color: #e5c07b; }
  .code-block pre .variable  { color: #e06c75; }
  .code-block pre .tag       { color: #e06c75; }
  .code-block pre .attr      { color: #d19a66; }
  .code-block pre .punct     { color: #abb2bf; }
  .code-block pre .property  { color: #e06c75; }
  .code-block pre .selector  { color: #98c379; }
  .code-block pre .value     { color: #d19a66; }

  .feature-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin: 32px 0;
  }

  .feature-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 24px;
    box-shadow: var(--shadow);
    transition: transform 0.2s, box-shadow 0.2s;
  }

  .feature-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.08); }
  .feature-card .icon { font-size: 28px; margin-bottom: 12px; }
  .feature-card .title { font-weight: 600; font-size: 15px; margin-bottom: 6px; }
  .feature-card .desc { font-size: 14px; color: var(--text-secondary); line-height: 1.6; }

  .pipeline {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 32px 28px;
    margin: 32px 0;
    box-shadow: var(--shadow);
  }

  .pipeline .step {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 14px 0;
    position: relative;
  }

  .pipeline .step:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 15px;
    top: 48px;
    bottom: -2px;
    width: 2px;
    background: var(--border);
  }

  .pipeline .step-num {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .pipeline .step-content { flex: 1; padding-top: 4px; }
  .pipeline .step-title { font-weight: 600; font-size: 15px; margin-bottom: 2px; }
  .pipeline .step-desc { font-size: 14px; color: var(--text-secondary); }

  .example-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    margin: 32px 0;
    overflow: hidden;
    box-shadow: var(--shadow);
  }

  .example-card .example-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .example-card .example-num {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .example-card .example-title { font-weight: 600; font-size: 16px; }
  .example-card .example-body { padding: 24px; }

  .prompt-box {
    background: #f8f7f4;
    border-radius: 8px;
    padding: 16px 20px;
    margin-bottom: 20px;
    font-size: 15px;
    line-height: 1.7;
    color: var(--text);
    border-left: 3px solid var(--accent);
  }

  .prompt-box .label {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 8px;
  }

  .prompt-box.bad { border-left: 3px solid #ef4444; }
  .prompt-box.bad .label { color: #ef4444; }
  .prompt-box.good { border-left: 3px solid #10b981; }
  .prompt-box.good .label { color: #10b981; }

  .result-tag {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    background: var(--accent-soft);
    padding: 4px 12px;
    border-radius: 4px;
    margin-top: 16px;
  }

  .helper-table {
    width: 100%;
    border-collapse: collapse;
    margin: 24px 0;
    font-size: 15px;
  }

  .helper-table th {
    text-align: left;
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-light);
    padding: 12px 16px;
    border-bottom: 2px solid var(--border);
  }

  .helper-table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
  }

  .dir-tree {
    background: #f5f3ef;
    border-radius: 8px;
    padding: 24px;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.8;
    color: var(--text-secondary);
    margin: 24px 0;
  }

  .dir-tree .file { color: var(--text); display: block; }
  .dir-tree .comment { color: var(--text-light); font-family: 'Noto Sans KR', sans-serif; font-size: 13px; }

  .rule-list {
    counter-reset: rule;
    list-style: none;
    margin: 24px 0;
    padding: 0;
  }

  .rule-list li {
    counter-increment: rule;
    padding: 14px 16px 14px 56px;
    position: relative;
    border-bottom: 1px solid var(--border);
    font-size: 15px;
  }

  .rule-list li::before {
    content: counter(rule, decimal-leading-zero);
    position: absolute;
    left: 16px;
    top: 14px;
    font-family: 'Fira Code', monospace;
    font-size: 13px;
    color: var(--accent);
    font-weight: 600;
  }

  .rule-list li:last-child { border-bottom: none; }

  .callout {
    display: flex;
    gap: 16px;
    padding: 20px 24px;
    border-radius: 8px;
    margin: 28px 0;
  }

  .callout.info { background: #edf4fc; border-left: 3px solid #3b82f6; }
  .callout.warning { background: #fef9ec; border-left: 3px solid #f59e0b; }
  .callout.tip { background: #ecfdf5; border-left: 3px solid #10b981; }

  .callout .callout-icon { font-size: 20px; flex-shrink: 0; padding-top: 2px; }
  .callout .callout-body { flex: 1; }
  .callout .callout-body p { margin-bottom: 0; font-size: 15px; }

  .footer {
    max-width: 680px;
    margin: 80px auto 0;
    padding: 40px 24px;
    border-top: 1px solid var(--border);
    text-align: center;
    font-size: 14px;
    color: var(--text-light);
  }

  .footer a { color: var(--accent); text-decoration: none; }

  @media (max-width: 640px) {
    .header { padding: 60px 20px 40px; }
    .header h1 { font-size: 26px; }
    .feature-grid { grid-template-columns: 1fr; }
    .article h2 { font-size: 22px; }
    .code-block pre { font-size: 12px; }
  }

  @keyframes fadeInUp {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: translateY(0); }
  }

  @keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  .header .topic { animation: fadeIn 0.8s ease-out 0.2s both; }
  .header h1 { animation: fadeInUp 0.8s ease-out 0.4s both; }
  .header .subtitle { animation: fadeInUp 0.8s ease-out 0.6s both; }
  .header .meta { animation: fadeIn 0.8s ease-out 0.8s both; }

  .feature-grid .feature-card { opacity: 0; animation: fadeInUp 0.5s ease-out forwards; }
  .feature-grid .feature-card:nth-child(1) { animation-delay: 0.1s; }
  .feature-grid .feature-card:nth-child(2) { animation-delay: 0.2s; }
  .feature-grid .feature-card:nth-child(3) { animation-delay: 0.3s; }
  .feature-grid .feature-card:nth-child(4) { animation-delay: 0.4s; }
  .feature-grid .feature-card:nth-child(5) { animation-delay: 0.5s; }
  .feature-grid .feature-card:nth-child(6) { animation-delay: 0.6s; }

  .pipeline .step { opacity: 0; animation: fadeInUp 0.5s ease-out forwards; }
  .pipeline .step:nth-child(1) { animation-delay: 0.1s; }
  .pipeline .step:nth-child(2) { animation-delay: 0.2s; }
  .pipeline .step:nth-child(3) { animation-delay: 0.3s; }
  .pipeline .step:nth-child(4) { animation-delay: 0.4s; }
  .pipeline .step:nth-child(5) { animation-delay: 0.5s; }
  .pipeline .step:nth-child(6) { animation-delay: 0.6s; }
  .pipeline .step:nth-child(7) { animation-delay: 0.7s; }
  .pipeline .step:nth-child(8) { animation-delay: 0.8s; }
  .pipeline .step:nth-child(9) { animation-delay: 0.9s; }

  .example-card { opacity: 0; animation: fadeInUp 0.5s ease-out forwards; }

  .quote-block { animation: slideInLeft 0.6s ease-out; }
  @keyframes slideInLeft {
    from { opacity: 0; transform: translateX(-20px); }
    to { opacity: 1; transform: translateX(0); }
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;header class=&quot;header&quot;&gt;
  &lt;div class=&quot;topic&quot;&gt;AI Coding Agent Skills&lt;/div&gt;
  &lt;h1&gt;에이전트가 무작정 코드를 짜지&lt;br&gt;않게 만드는 방법&lt;/h1&gt;
  &lt;p class=&quot;subtitle&quot;&gt;mattpocock/skills 분석 — 요구사항 정렬부터 TDD, 아키텍처 개선까지&lt;br&gt;AI 코딩을 실무 프로세스에 맞춘 12개 스킬&lt;/p&gt;
  &lt;div class=&quot;meta&quot;&gt;2026.05.03 &amp;middot; AI Engineering Workflow&lt;/div&gt;
&lt;/header&gt;
&lt;hr class=&quot;divider&quot;&gt;

&lt;article class=&quot;article&quot;&gt;

&lt;h2&gt;이 저장소가 풀려는 문제&lt;/h2&gt;

&lt;p&gt;AI 코딩 에이전트가 빠르게 코드를 만들면서 &lt;em&gt;아키텍처를 망가뜨리는 일&lt;/em&gt;은 이제 흔합니다. 에이전트가 사용자의 의도를 잘못 이해하고, 프로젝트 용어를 못 맞추고, 만든 코드가 동작하지 않는 문제도 반복됩니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mattpocock/skills&lt;/code&gt;는 이 문제를 &lt;em&gt;슬래시 커맨드 형태의 작업 지시서&lt;/em&gt;로 해결합니다. 에이전트가 무작정 코드를 고치지 않고, 정해진 흐름을 따르게 만듭니다.&lt;/p&gt;

&lt;div class=&quot;quote-block&quot;&gt;
  &lt;p&gt;요구사항 정렬 → 도메인 언어 정리 → PRD 작성 → 이슈 쪼개기 → TDD 구현 → 버그 진단 → 아키텍처 개선. AI가 이 순서를 스스로 따르게 만드는 것이 이 저장소의 핵심입니다.&lt;/p&gt;
&lt;/div&gt;

&lt;h2&gt;설치와 초기화&lt;/h2&gt;

&lt;p&gt;프로젝트 루트에서 한 줄로 설치합니다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;bash&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 설치&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;npx skills@&lt;span class=&quot;variable&quot;&gt;latest&lt;/span&gt; add mattpocock/skills
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 설치 UI에서 스킬 선택 후&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 에이전트 안에서 초기화 실행&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;/setup-matt-pocock-skills&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;/setup-matt-pocock-skills&lt;/code&gt;는 이슈 트래커 설정, triage 라벨 매핑, 도메인 문서 위치를 물어봅니다. 이 정보는 다른 모든 스킬이 참조하는 기반이 됩니다.&lt;/p&gt;

&lt;div class=&quot;callout info&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;i&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;초기화가 끝나면 프로젝트에 &lt;code&gt;AGENTS.md&lt;/code&gt; 또는 &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;docs/agents/&lt;/code&gt; 문서들이 생성됩니다. 여기에 이슈 트래커 방식, triage 라벨, 도메인 용어가 저장됩니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;12개 스킬 한눈에 보기&lt;/h2&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/setup-matt-pocock-skills&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;초기화. 이슈 트래커, 라벨, 도메인 문서 위치 설정. 모든 스킬 사용 전 먼저 실행.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/grill-me&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;요구사항 압박 면접. 아이디어의 빈틈을 하나씩 질문하며 채움.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/grill-with-docs&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;grill-me + 도메인 문서 연동. 기존 용어와 충돌하는지 검증.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/to-prd&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;대화 맥락을 PRD로 정리. Problem → Solution → User Stories → Testing.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;✂️&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/to-issues&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;PRD를 vertical slice 이슈로 분해. AFK/HITL 구분.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/tdd&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;한 테스트 → 한 구현 루프 강제. horizontal 테스트 금지.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/diagnose&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;버그 진단. 재현 루프 먼저, 가설은 반증 가능하게, 추측 금지.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; ️&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/triage&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;이슈 분류. bug/enhancement 구분, needs-info/ready-for-agent 상태 변경.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; ️&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/improve-codebase-architecture&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;테스트 가능성과 AI 탐색성을 기준으로 얕은 모듈을 deep module로 개선.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; ️&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/zoom-out&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;특정 코드 영역의 상위 관점 지도. 관련 모듈과 caller를 도메인 용어로 설명.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/caveman&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;초압축 커뮤니케이션 모드. 토큰 절약, 핵심만 출력.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;✏️&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;/write-a-skill&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;새 스킬 작성. SKILL.md + REFERENCE.md + EXAMPLES.md 구조.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;핵심 스킬 깊이 보기&lt;/h2&gt;

&lt;h3&gt;/grill-me, /grill-with-docs — 요구사항 압박 면접&lt;/h3&gt;

&lt;p&gt;사용자가 아이디어나 설계를 던지면, 에이전트가 &lt;em&gt;모든 의사결정 분기를 하나씩 질문&lt;/em&gt;하면서 빈틈을 채웁니다. &lt;code&gt;/grill-with-docs&lt;/code&gt;는 여기에 프로젝트의 &lt;code&gt;CONTEXT.md&lt;/code&gt;와 ADR을 읽고 기존 도메인 용어와 충돌하는지 검증까지 합니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;grill-with-docs 사용 예&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;User Input&lt;/div&gt;
      AI 뮤직비디오를 기반으로 리듬게임을 만들고 싶어. 현재 도메인 모델과 충돌하는 부분이 있는지 확인하면서 질문해줘.
    &lt;/div&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Agent Behavior&lt;/div&gt;
      CONTEXT.md의 기존 용어와 비교 → 모호한 단어 지적 → canonical term 제안 → 충돌 시 즉시 알림 → 정리된 용어를 CONTEXT.md에 반영 제안
    &lt;/div&gt;
    &lt;div class=&quot;result-tag&quot;&gt;장기 프로젝트에서 에이전트 용어 불일치 문제 해결&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;/to-prd, /to-issues — 기획을 개발 단위로 분해&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/to-prd&lt;/code&gt;는 대화 맥락을 종합해 PRD를 만듭니다. 핵심은 &lt;em&gt;사용자를 다시 인터뷰하지 않고 이미 있는 대화를 활용&lt;/em&gt;한다는 점입니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/to-issues&lt;/code&gt;는 PRD를 vertical slice로 쪼갭니다. horizontal slice가 아니라 tracer bullet 방식의 &lt;em&gt;얇고 완성 가능한 end-to-end 단위&lt;/em&gt;입니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;VS&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;이슈 쪼개기 — Horizontal vs Vertical&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box bad&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Bad — Horizontal Slice&lt;/div&gt;
      1. DB schema 만들기&lt;br&gt;
      2. API 만들기&lt;br&gt;
      3. UI 만들기&lt;br&gt;
      4. 테스트 만들기
    &lt;/div&gt;
    &lt;div class=&quot;prompt-box good&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Good — Vertical Slice&lt;/div&gt;
      1. 사용자가 첫 운동 목표를 생성할 수 있다 (schema + API + UI + test 포함)&lt;br&gt;
      2. 사용자가 오늘의 운동 완료를 기록할 수 있다 (schema + API + UI + test 포함)&lt;br&gt;
      3. 운동 완료 시 코인 보상 내역을 볼 수 있다 (schema + API + UI + test 포함)
    &lt;/div&gt;
    &lt;div class=&quot;result-tag&quot;&gt;각 이슈는 AFK(에이전트 단독) / HITL(사람 확인) 구분&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;/tdd — 테스트 하나, 구현 하나&lt;/h3&gt;

&lt;p&gt;이 스킬은 &quot;테스트 먼저 전부 작성 → 구현 전부 작성&quot;이 아니라 &lt;em&gt;한 테스트 → 한 구현 → 다음 테스트&lt;/em&gt; 방식의 vertical red-green-refactor 루프를 강제합니다.&lt;/p&gt;

&lt;ol class=&quot;rule-list&quot;&gt;
  &lt;li&gt;테스트는 구현 세부사항이 아니라 &lt;em&gt;public interface의 행동&lt;/em&gt;을 검증&lt;/li&gt;
  &lt;li&gt;내부 함수명 변경 때문에 깨지는 테스트는 &lt;em&gt;나쁜 테스트&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;한 번에 &lt;em&gt;하나의 테스트만&lt;/em&gt; 추가&lt;/li&gt;
  &lt;li&gt;GREEN 상태 전에는 &lt;em&gt;refactor 금지&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;테스트 이름은 프로젝트 &lt;em&gt;도메인 glossary와 맞춤&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;/diagnose — 추측 금지, 재현 먼저&lt;/h3&gt;

&lt;p&gt;이 스킬은 &quot;코드 읽고 바로 수정&quot;이 아니라 &lt;em&gt;재현 루프부터 구축&lt;/em&gt;하는 보수적 디버깅을 강제합니다.&lt;/p&gt;

&lt;div class=&quot;pipeline&quot;&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;Feedback loop 만들기&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;failing test, curl script, CLI fixture, Playwright, git bisect 등&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;Reproduce&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;재현 루프가 없으면 추측하지 않음&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;3~5개 반증 가능 가설 수립&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;hypothesis는 반드시 falsifiable해야 함&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;4&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;Instrument&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;debug log에 고유 prefix, 마지막에 제거&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;5&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;Fix + Regression test&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;fix 전에 regression test 작성, fix 후 원래 repro loop 재실행&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;6&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;Cleanup + Post-mortem&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;debug log 제거, 원인 기록&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;/improve-codebase-architecture — Deep Module 찾기&lt;/h3&gt;

&lt;p&gt;코드베이스에서 테스트 가능성과 AI 탐색성을 기준으로 &lt;em&gt;얕은 모듈을 deep module로 개선&lt;/em&gt;할 기회를 찾습니다. 바로 refactor 코드를 작성하지 않고, 먼저 후보 목록을 제시한 뒤 사용자가 고른 후보에 대해 grilling loop로 들어갑니다.&lt;/p&gt;

&lt;div class=&quot;callout tip&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;!&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;이 스킬은 &lt;code&gt;CONTEXT.md&lt;/code&gt;와 ADR을 읽고, 현재 도메인 언어와 과거 설계 결정을 존중합니다. 새 용어를 만들지 않고 기존 용어 내에서 개선안을 제시합니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;실무 워크플로우 조합&lt;/h2&gt;

&lt;h3&gt;새 기능 개발&lt;/h3&gt;

&lt;div class=&quot;pipeline&quot;&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/setup-matt-pocock-skills&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;프로젝트 이슈 트래커, 라벨, 도메인 문서 설정&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/grill-with-docs&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;기존 도메인 모델과 충돌 확인하며 요구사항 압박 면접&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/to-prd&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;대화 맥락을 PRD로 정리&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;4&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/to-issues&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;PRD를 AFK 가능한 vertical slice 이슈들로 분해&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;5&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/tdd&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;각 AFK 이슈를 red-green-refactor 루프로 구현&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;버그 수정&lt;/h3&gt;

&lt;div class=&quot;pipeline&quot;&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/triage&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;이슈 분류 → bug/enhancement, ready-for-agent 판단&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/diagnose&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;재현 루프 → 가설 수립 → 검증 → fix + regression test&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;/improve-codebase-architecture&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;테스트 seam 부족 원인 확인, 아키텍처 개선 후보 제안&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;가벼운 시작 조합&lt;/h2&gt;

&lt;p&gt;작은 프로젝트에서 모든 스킬을 쓰는 것은 과합니다. 처음에는 이 네 가지만 시작하세요.&lt;/p&gt;

&lt;table class=&quot;helper-table&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;code&gt;/setup&lt;/code&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;code&gt;/tdd&lt;/code&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;code&gt;/diagnose&lt;/code&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;code&gt;/zoom-out&lt;/code&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;div class=&quot;callout warning&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;!&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;기획과 이슈 관리까지 에이전트에 맡기고 싶을 때만 &lt;code&gt;/grill-with-docs&lt;/code&gt;, &lt;code&gt;/to-prd&lt;/code&gt;, &lt;code&gt;/to-issues&lt;/code&gt;, &lt;code&gt;/triage&lt;/code&gt;, &lt;code&gt;/improve-codebase-architecture&lt;/code&gt;를 추가하세요.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;이 저장소의 핵심 가치&lt;/h2&gt;

&lt;p&gt;이 저장소는 &quot;AI가 코드를 더 많이 쓰게 하는 도구&quot;가 아닙니다. &lt;em&gt;AI가 덜 위험하게, 더 실무적인 순서로 일하게 만드는 운영 프레임워크&lt;/em&gt;입니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;★&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;세 가지 핵심 가치&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;ol class=&quot;rule-list&quot;&gt;
      &lt;li&gt;무작정 구현하지 않고 &lt;em&gt;질문과 정렬부터&lt;/em&gt; 하게 만든다&lt;/li&gt;
      &lt;li&gt;요구사항 → PRD → 이슈 → TDD → 디버깅까지 &lt;em&gt;연결된 파이프라인&lt;/em&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;CONTEXT.md&lt;/code&gt;와 ADR을 통해 에이전트가 &lt;em&gt;프로젝트의 언어와 설계 결정을 기억&lt;/em&gt;하게 만든다&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;주의할 점&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;/to-prd&lt;/code&gt;, &lt;code&gt;/to-issues&lt;/code&gt;, &lt;code&gt;/triage&lt;/code&gt;는 이슈 트래커와 triage label vocabulary를 전제로 동작합니다. &lt;code&gt;/setup-matt-pocock-skills&lt;/code&gt;에서 이 설정을 대충하면 잘못된 라벨 생성, 기존 워크플로우 충돌, &lt;code&gt;ready-for-agent&lt;/code&gt; 기준 모호화 등의 문제가 생깁니다.&lt;/p&gt;

&lt;p&gt;또한 이 저장소는 &lt;code&gt;CONTEXT.md&lt;/code&gt;에 &quot;Claude Code가 로드하는 agent skills&quot; 모음이라고 명시되어 있습니다. Codex, Cursor, 다른 에이전트에서도 개념적으로는 활용 가능하지만, 실제 설치와 호출 UX는 각 도구의 skill 지원 방식에 맞게 옮겨야 합니다.&lt;/p&gt;

&lt;h2&gt;/write-a-skill — 나만의 스킬 만들기&lt;/h2&gt;

&lt;p&gt;이 스킬을 사용하면 자신만의 커스텀 스킬을 만들 수 있습니다. 스킬 구조는 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;dir-tree&quot;&gt;
&lt;span class=&quot;file&quot;&gt;skill-name/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── SKILL.md&lt;/span&gt;       &lt;span class=&quot;comment&quot;&gt;# 메인 지시문&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── REFERENCE.md&lt;/span&gt;   &lt;span class=&quot;comment&quot;&gt;# 참고 문서&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── EXAMPLES.md&lt;/span&gt;    &lt;span class=&quot;comment&quot;&gt;# 사용 예시&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;└── scripts/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;    └── helper.js&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 보조 스크립트&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;SKILL.md&lt;/code&gt;의 description은 에이전트가 어떤 스킬을 로드할지 판단하는 &lt;em&gt;유일한 정보&lt;/em&gt;입니다. 1024자 이하, 3인칭, &quot;Use when...&quot; 트리거를 포함해야 합니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;★&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;커스텀 스킬 아이디어&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;ol class=&quot;rule-list&quot;&gt;
      &lt;li&gt;Suno 스타일 음악 프롬프트 생성 스킬&lt;/li&gt;
      &lt;li&gt;Runway/Seedance 15초 영상 프롬프트 분할 스킬&lt;/li&gt;
      &lt;li&gt;Flutter App Store 심사 대응 체크리스트 스킬&lt;/li&gt;
      &lt;li&gt;AI 영상 제작 — 캐릭터 일관성, 배경 일관성, lip-sync 규칙 자동 포함 스킬&lt;/li&gt;
      &lt;li&gt;유튜브 썸네일/설명/쇼츠 변환 스킬&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;추천 첫 사용 순서&lt;/h2&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;bash&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 1. 설치&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;npx skills@&lt;span class=&quot;variable&quot;&gt;latest&lt;/span&gt; add mattpocock/skills
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 2. 초기화&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;/setup-matt-pocock-skills&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;그리고 실제 작업에서는 목적에 따라 조합하세요.&lt;/p&gt;

&lt;table class=&quot;helper-table&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;&lt;code&gt;/grill-with-docs&lt;/code&gt; → &lt;code&gt;/to-prd&lt;/code&gt; → &lt;code&gt;/to-issues&lt;/code&gt; → &lt;code&gt;/tdd&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;버그 수정&lt;/td&gt;&lt;td&gt;&lt;code&gt;/diagnose&lt;/code&gt; → &lt;code&gt;/tdd&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;구조 개선&lt;/td&gt;&lt;td&gt;&lt;code&gt;/zoom-out&lt;/code&gt; → &lt;code&gt;/improve-codebase-architecture&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;나만의 자동화&lt;/td&gt;&lt;td&gt;&lt;code&gt;/write-a-skill&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;/article&gt;

&lt;footer class=&quot;footer&quot;&gt;
  &lt;p&gt;mattpocock/skills — AI 코딩 에이전트를 실무 프로세스에 맞추는 스킬 패키지&lt;/p&gt;
  &lt;p style=&quot;margin-top: 16px;&quot;&gt;&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;github.com/mattpocock/skills&lt;/a&gt;&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
document.querySelectorAll('.code-block').forEach(function(block) {
  var header = block.querySelector('.code-header');
  var pre = block.querySelector('pre');
  if (!header || !pre) return;
  var btn = document.createElement('button');
  btn.className = 'copy-btn';
  btn.textContent = 'COPY';
  btn.addEventListener('click', function() {
    var text = pre.innerText.replace(/^\d+\s*/gm, '');
    navigator.clipboard.writeText(text).then(function() {
      btn.textContent = 'COPIED';
      btn.classList.add('copied');
      setTimeout(function() {
        btn.textContent = 'COPY';
        btn.classList.remove('copied');
      }, 2000);
    });
  });
  header.appendChild(btn);
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1755</guid>
      <comments>https://javaexpert.tistory.com/1755#entry1755comment</comments>
      <pubDate>Sun, 3 May 2026 08:00:36 +0900</pubDate>
    </item>
    <item>
      <title>AI로 게임 스프라이트 시트 만들기 &amp;mdash; 실전 파이프라인</title>
      <link>https://javaexpert.tistory.com/1754</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;AI로 게임 스프라이트 시트 만들기 — 실전 파이프라인&lt;/title&gt;
&lt;style&gt;
  @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@400;600;700&amp;family=Noto+Sans+KR:wght@300;400;500;600&amp;family=Fira+Code:wght@400;500&amp;display=swap');

  :root {
    --bg: #fafaf8;
    --text: #1a1a1a;
    --text-secondary: #666;
    --text-light: #999;
    --accent: #e8572a;
    --accent-soft: #fff3ef;
    --border: #e8e6e1;
    --code-bg: #282c34;
    --code-text: #abb2bf;
    --inline-code-bg: #f0ede8;
    --card-bg: #ffffff;
    --shadow: 0 1px 4px rgba(0,0,0,0.04);
  }

  * { margin: 0; padding: 0; box-sizing: border-box; }

  body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Noto Sans KR', -apple-system, sans-serif;
    font-size: 17px;
    line-height: 1.9;
    -webkit-font-smoothing: antialiased;
  }

  /* ── Header ── */
  .header {
    text-align: center;
    padding: 100px 24px 60px;
    max-width: 680px;
    margin: 0 auto;
  }

  .header .topic {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 20px;
    padding: 4px 16px;
    margin-bottom: 32px;
  }

  .header h1 {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    line-height: 1.45;
    letter-spacing: -0.5px;
    margin-bottom: 24px;
  }

  .header .subtitle {
    font-size: 18px;
    color: var(--text-secondary);
    line-height: 1.8;
    font-weight: 300;
  }

  .header .meta {
    margin-top: 40px;
    font-size: 14px;
    color: var(--text-light);
  }

  .divider {
    max-width: 680px;
    margin: 0 auto;
    border: none;
    border-top: 1px solid var(--border);
  }

  /* ── Article ── */
  .article {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 24px;
  }

  .article h2 {
    font-family: 'Noto Serif KR', serif;
    font-size: 26px;
    font-weight: 700;
    margin: 80px 0 24px;
    line-height: 1.4;
    letter-spacing: -0.3px;
  }

  .article h3 {
    font-family: 'Noto Serif KR', serif;
    font-size: 20px;
    font-weight: 600;
    margin: 48px 0 16px;
    line-height: 1.5;
  }

  .article h4 {
    font-family: 'Noto Serif KR', serif;
    font-size: 17px;
    font-weight: 600;
    margin: 36px 0 12px;
    line-height: 1.5;
  }

  .article p {
    margin-bottom: 20px;
  }

  .article strong {
    font-weight: 600;
  }

  .article em {
    font-style: normal;
    color: var(--accent);
    font-weight: 500;
  }

  .article ul, .article ol {
    margin: 16px 0 24px 20px;
  }

  .article li {
    margin-bottom: 8px;
  }

  /* ── Quote Block ── */
  .quote-block {
    border-left: 3px solid var(--accent);
    padding: 20px 28px;
    margin: 32px 0;
    background: var(--accent-soft);
    border-radius: 0 8px 8px 0;
  }

  .quote-block p {
    margin-bottom: 0;
    font-size: 16px;
  }

  /* ── Inline Code ── */
  code {
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 0.88em;
    background: var(--inline-code-bg);
    padding: 2px 7px;
    border-radius: 4px;
    color: var(--accent);
  }

  /* ── Code Block ── */
  .code-block {
    margin: 28px 0;
    border-radius: 10px;
    overflow: hidden;
    background: var(--code-bg);
    box-shadow: 0 2px 12px rgba(0,0,0,0.12);
  }

  .code-block .code-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: #21252b;
    border-bottom: 1px solid #181a1f;
  }

  .code-block .code-header .lang-label {
    font-family: 'Fira Code', monospace;
    font-size: 12px;
    color: #636d83;
    text-transform: uppercase;
    letter-spacing: 1px;
  }

  .copy-btn {
    background: none;
    border: 1px solid #3e4451;
    color: #636d83;
    font-family: 'Fira Code', monospace;
    font-size: 11px;
    padding: 3px 10px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
    letter-spacing: 0.5px;
  }

  .copy-btn:hover {
    border-color: #abb2bf;
    color: #abb2bf;
  }

  .copy-btn.copied {
    border-color: #98c379;
    color: #98c379;
  }

  .code-block .code-header .dots {
    display: flex;
    gap: 6px;
  }

  .code-block .code-header .dots span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
  }

  .code-block .code-header .dots span:nth-child(1) { background: #ff5f57; }
  .code-block .code-header .dots span:nth-child(2) { background: #febc2e; }
  .code-block .code-header .dots span:nth-child(3) { background: #28c840; }

  .code-block pre {
    padding: 20px 24px;
    overflow-x: auto;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.7;
    color: var(--code-text);
    tab-size: 2;
  }

  .code-block pre .line-num {
    display: inline-block;
    width: 36px;
    color: #4b5263;
    text-align: right;
    margin-right: 20px;
    user-select: none;
    -webkit-user-select: none;
  }

  /* Syntax Highlighting */
  .code-block pre .keyword   { color: #c678dd; }
  .code-block pre .string    { color: #98c379; }
  .code-block pre .number    { color: #d19a66; }
  .code-block pre .comment   { color: #5c6370; font-style: italic; }
  .code-block pre .function  { color: #61afef; }
  .code-block pre .operator  { color: #56b6c2; }
  .code-block pre .type      { color: #e5c07b; }
  .code-block pre .variable  { color: #e06c75; }
  .code-block pre .tag       { color: #e06c75; }
  .code-block pre .attr      { color: #d19a66; }
  .code-block pre .punct     { color: #abb2bf; }
  .code-block pre .property  { color: #e06c75; }
  .code-block pre .selector  { color: #98c379; }
  .code-block pre .value     { color: #d19a66; }

  /* ── Feature Cards ── */
  .feature-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin: 32px 0;
  }

  .feature-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 24px;
    box-shadow: var(--shadow);
    transition: transform 0.2s, box-shadow 0.2s;
  }

  .feature-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  }

  .feature-card .icon {
    font-size: 28px;
    margin-bottom: 12px;
  }

  .feature-card .title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 6px;
  }

  .feature-card .desc {
    font-size: 14px;
    color: var(--text-secondary);
    line-height: 1.6;
  }

  /* ── Pipeline / Step Flow ── */
  .pipeline {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 32px 28px;
    margin: 32px 0;
    box-shadow: var(--shadow);
  }

  .pipeline .step {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 14px 0;
    position: relative;
  }

  .pipeline .step:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 15px;
    top: 48px;
    bottom: -2px;
    width: 2px;
    background: var(--border);
  }

  .pipeline .step-num {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .pipeline .step-content {
    flex: 1;
    padding-top: 4px;
  }

  .pipeline .step-title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 2px;
  }

  .pipeline .step-desc {
    font-size: 14px;
    color: var(--text-secondary);
  }

  /* ── Example Card ── */
  .example-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    margin: 32px 0;
    overflow: hidden;
    box-shadow: var(--shadow);
  }

  .example-card .example-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .example-card .example-num {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .example-card .example-title {
    font-weight: 600;
    font-size: 16px;
  }

  .example-card .example-body {
    padding: 24px;
  }

  .prompt-box {
    background: #f8f7f4;
    border-radius: 8px;
    padding: 16px 20px;
    margin-bottom: 20px;
    font-size: 15px;
    line-height: 1.7;
    color: var(--text);
    border-left: 3px solid var(--accent);
  }

  .prompt-box .label {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 8px;
  }

  .prompt-box.bad {
    border-left: 3px solid #ef4444;
  }

  .prompt-box.bad .label {
    color: #ef4444;
  }

  .prompt-box.good {
    border-left: 3px solid #10b981;
  }

  .prompt-box.good .label {
    color: #10b981;
  }

  .process-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .process-list li {
    padding: 6px 0 6px 24px;
    position: relative;
    font-size: 15px;
    color: var(--text-secondary);
  }

  .process-list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 14px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border);
  }

  .process-list li:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 26px;
    bottom: -8px;
    width: 2px;
    background: var(--border);
  }

  .result-tag {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    background: var(--accent-soft);
    padding: 4px 12px;
    border-radius: 4px;
    margin-top: 16px;
  }

  /* ── Helper Table ── */
  .helper-table {
    width: 100%;
    border-collapse: collapse;
    margin: 24px 0;
    font-size: 15px;
  }

  .helper-table th {
    text-align: left;
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-light);
    padding: 12px 16px;
    border-bottom: 2px solid var(--border);
  }

  .helper-table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
  }

  /* ── Directory Tree ── */
  .dir-tree {
    background: #f5f3ef;
    border-radius: 8px;
    padding: 24px;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.8;
    color: var(--text-secondary);
    margin: 24px 0;
  }

  .dir-tree .file { color: var(--text); display: block; }
  .dir-tree .comment { color: var(--text-light); font-family: 'Noto Sans KR', sans-serif; font-size: 13px; }

  /* ── Rule List ── */
  .rule-list {
    counter-reset: rule;
    list-style: none;
    margin: 24px 0;
    padding: 0;
  }

  .rule-list li {
    counter-increment: rule;
    padding: 14px 16px 14px 56px;
    position: relative;
    border-bottom: 1px solid var(--border);
    font-size: 15px;
  }

  .rule-list li::before {
    content: counter(rule, decimal-leading-zero);
    position: absolute;
    left: 16px;
    top: 14px;
    font-family: 'Fira Code', monospace;
    font-size: 13px;
    color: var(--accent);
    font-weight: 600;
  }

  .rule-list li:last-child {
    border-bottom: none;
  }

  /* ── Image ── */
  .article img {
    max-width: 100%;
    border-radius: 8px;
    margin: 16px 0;
  }

  .article figcaption {
    font-size: 14px;
    color: var(--text-light);
    text-align: center;
    margin-top: 8px;
  }

  /* ── Callout ── */
  .callout {
    display: flex;
    gap: 16px;
    padding: 20px 24px;
    border-radius: 8px;
    margin: 28px 0;
  }

  .callout.info {
    background: #edf4fc;
    border-left: 3px solid #3b82f6;
  }

  .callout.warning {
    background: #fef9ec;
    border-left: 3px solid #f59e0b;
  }

  .callout.tip {
    background: #ecfdf5;
    border-left: 3px solid #10b981;
  }

  .callout .callout-icon {
    font-size: 20px;
    flex-shrink: 0;
    padding-top: 2px;
  }

  .callout .callout-body {
    flex: 1;
  }

  .callout .callout-body p {
    margin-bottom: 0;
    font-size: 15px;
  }

  /* ── Footer ── */
  .footer {
    max-width: 680px;
    margin: 80px auto 0;
    padding: 40px 24px;
    border-top: 1px solid var(--border);
    text-align: center;
    font-size: 14px;
    color: var(--text-light);
  }

  .footer a {
    color: var(--accent);
    text-decoration: none;
  }

  /* ── Responsive ── */
  @media (max-width: 640px) {
    .header { padding: 60px 20px 40px; }
    .header h1 { font-size: 26px; }
    .feature-grid { grid-template-columns: 1fr; }
    .article h2 { font-size: 22px; }
    .code-block pre { font-size: 12px; }
  }

  /* ── Scroll-triggered Animations ── */
  @keyframes fadeInUp {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: translateY(0); }
  }

  @keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  .animate-on-scroll {
    opacity: 0;
    transition: none;
  }

  .animate-on-scroll.visible {
    animation: fadeInUp 0.6s ease-out forwards;
  }

  .animate-on-scroll.visible-delay-1 { animation-delay: 0.1s; }
  .animate-on-scroll.visible-delay-2 { animation-delay: 0.2s; }
  .animate-on-scroll.visible-delay-3 { animation-delay: 0.3s; }

  /* ── Header Entrance ── */
  .header .topic {
    animation: fadeIn 0.8s ease-out 0.2s both;
  }

  .header h1 {
    animation: fadeInUp 0.8s ease-out 0.4s both;
  }

  .header .subtitle {
    animation: fadeInUp 0.8s ease-out 0.6s both;
  }

  .header .meta {
    animation: fadeIn 0.8s ease-out 0.8s both;
  }

  /* ── Audio Waveform Animation ── */
  .waveform {
    display: flex;
    align-items: center;
    gap: 3px;
    height: 32px;
    margin: 24px 0;
  }

  .waveform .bar {
    width: 4px;
    border-radius: 2px;
    background: var(--accent);
    animation: wave 1.2s ease-in-out infinite;
  }

  .waveform .bar:nth-child(1)  { animation-delay: 0s; }
  .waveform .bar:nth-child(2)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(3)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(4)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(5)  { animation-delay: 0.4s; }
  .waveform .bar:nth-child(6)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(7)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(8)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(9)  { animation-delay: 0s; }
  .waveform .bar:nth-child(10) { animation-delay: 0.1s; }
  .waveform .bar:nth-child(11) { animation-delay: 0.2s; }
  .waveform .bar:nth-child(12) { animation-delay: 0.3s; }

  @keyframes wave {
    0%, 100% { height: 8px; opacity: 0.4; }
    50% { height: 28px; opacity: 1; }
  }

  /* ── Animated Progress Bar ── */
  .progress-bar {
    background: var(--border);
    border-radius: 4px;
    height: 6px;
    margin: 24px 0;
    overflow: hidden;
  }

  .progress-bar .fill {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--accent), #f4845f);
    animation: progressFill 2s ease-out forwards;
    transform-origin: left;
  }

  @keyframes progressFill {
    from { width: 0; }
  }

  /* ── Typing Effect ── */
  .typing {
    font-family: 'Fira Code', monospace;
    font-size: 15px;
    color: var(--text);
    border-right: 2px solid var(--accent);
    white-space: nowrap;
    overflow: hidden;
    animation: typing 3s steps(40) forwards, blink 0.8s step-end infinite;
    width: 0;
  }

  @keyframes typing {
    to { width: 100%; }
  }

  @keyframes blink {
    50% { border-color: transparent; }
  }

  /* ── Pulse Dot ── */
  .pulse-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    margin-right: 8px;
    animation: pulse 2s ease-in-out infinite;
  }

  @keyframes pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.5); opacity: 0.5; }
  }

  /* ── Floating Badge ── */
  .float-badge {
    display: inline-block;
    font-size: 12px;
    font-weight: 600;
    color: white;
    background: var(--accent);
    padding: 4px 12px;
    border-radius: 12px;
    animation: float 3s ease-in-out infinite;
  }

  @keyframes float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-4px); }
  }

  /* ── Shimmer Loading ── */
  .shimmer {
    background: linear-gradient(90deg, var(--border) 25%, #f0ede8 50%, var(--border) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    border-radius: 4px;
    height: 16px;
    margin: 8px 0;
  }

  @keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
  }

  /* ── Animated Counter ── */
  .counter {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    color: var(--accent);
  }

  /* ── Bouncing Arrow ── */
  .bounce-arrow {
    display: inline-block;
    animation: bounce 1.5s ease-in-out infinite;
    color: var(--accent);
  }

  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(6px); }
  }

  /* ── Feature Card Stagger ── */
  .feature-grid .feature-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .feature-grid .feature-card:nth-child(1) { animation-delay: 0.1s; }
  .feature-grid .feature-card:nth-child(2) { animation-delay: 0.2s; }
  .feature-grid .feature-card:nth-child(3) { animation-delay: 0.3s; }
  .feature-grid .feature-card:nth-child(4) { animation-delay: 0.4s; }
  .feature-grid .feature-card:nth-child(5) { animation-delay: 0.5s; }
  .feature-grid .feature-card:nth-child(6) { animation-delay: 0.6s; }

  /* ── Pipeline Step Stagger ── */
  .pipeline .step {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .pipeline .step:nth-child(1) { animation-delay: 0.1s; }
  .pipeline .step:nth-child(2) { animation-delay: 0.3s; }
  .pipeline .step:nth-child(3) { animation-delay: 0.5s; }
  .pipeline .step:nth-child(4) { animation-delay: 0.7s; }
  .pipeline .step:nth-child(5) { animation-delay: 0.9s; }
  .pipeline .step:nth-child(6) { animation-delay: 1.1s; }
  .pipeline .step:nth-child(7) { animation-delay: 1.3s; }
  .pipeline .step:nth-child(8) { animation-delay: 1.5s; }
  .pipeline .step:nth-child(9) { animation-delay: 1.7s; }

  /* ── Example Card Stagger ── */
  .example-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  /* ── Quote Block Slide-in ── */
  .quote-block {
    animation: slideInLeft 0.6s ease-out;
  }

  @keyframes slideInLeft {
    from { opacity: 0; transform: translateX(-20px); }
    to { opacity: 1; transform: translateX(0); }
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;header class=&quot;header&quot;&gt;
  &lt;div class=&quot;topic&quot;&gt;Game Dev Pipeline&lt;/div&gt;
  &lt;h1&gt;AI로 만드는 2D 스프라이트 시트&lt;br&gt;실전 파이프라인 가이드&lt;/h1&gt;
  &lt;p class=&quot;subtitle&quot;&gt;이미지 모델 + 비디오 모델 + 파이썬 자동화&lt;br&gt;세 가지를 조합해 게임용 애니메이션을 완성하는 방법&lt;/p&gt;
  &lt;div class=&quot;meta&quot;&gt;2026.05.02 &amp;middot; AI Game Art Workflow&lt;/div&gt;
&lt;/header&gt;
&lt;hr class=&quot;divider&quot;&gt;

&lt;article class=&quot;article&quot;&gt;

&lt;h2&gt;왜 이미지 모델만으로는 안 되는가&lt;/h2&gt;

&lt;p&gt;게임용 스프라이트 시트는 단순히 예쁜 그림이 아닙니다. 프레임이 &lt;em&gt;수학적으로 정확한 격자&lt;/em&gt;에 맞아야 하고, 캐릭터가 매 프레임 중앙에 있어야 하며, 배경은 완벽히 투명해야 합니다.&lt;/p&gt;

&lt;p&gt;이미지 생성 모델은 이런 규칙을 자주 어깁니다. 특히 걷기나 달리기처럼 &lt;em&gt;다리 움직임이 핵심인 애니메이션&lt;/em&gt;에서 오류가 많습니다. 프레임마다 위치가 흔들리고, 배경이 섞이고, 캐릭터 비율이 변합니다.&lt;/p&gt;

&lt;p&gt;그래서 &lt;em&gt;이미지 모델 + 비디오 모델 + 로컬 파이썬 스크립트&lt;/em&gt; 세 가지를 조합해야 합니다. 각 도구가 잘하는 것만 하게 만드는 것이 이 파이프라인의 핵심입니다.&lt;/p&gt;

&lt;div class=&quot;quote-block&quot;&gt;
  &lt;p&gt;이미지 모델로 깨끗한 첫 포즈를 만들고, 비디오 모델로 자연스러운 움직임을 만든 뒤, 파이썬으로 프레임 추출부터 스프라이트 시트 생성까지 자동화한다.&lt;/p&gt;
&lt;/div&gt;

&lt;h2&gt;전체 파이프라인 한눈에 보기&lt;/h2&gt;

&lt;div class=&quot;pipeline&quot;&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;첫 포즈 생성&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;이미지 모델(GPT Image, Nano Banana)로 크로마키 배경의 캐릭터 포즈 생성&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;움직임 생성&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;Kling 같은 비디오 모델로 첫 포즈에서 애니메이션 영상 생성&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;프레임 추출&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;FFmpeg로 비디오의 모든 프레임을 PNG로 추출&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;4&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;프레임 선택&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;Contact sheet로 전체 프레임을 확인하고 사용할 프레임 수동 선택&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;5&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;배경 보정 (필요시)&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;크로마키가 깨끗하지 않을 때만 응급 보정 스크립트 사용&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;6&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;스프라이트 시트 생성&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;배경 제거 → 256x256 변환 → 가로형 스프라이트 시트 출력&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;7&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;결과 검수&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;리포트 확인, 잘림/흔들림/워터마크 점검&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;8&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;미리보기 갤러리&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;정적 HTML 뷰어로 시트 비교 및 프레임 재생&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;9&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;임시 파일 정리&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;중간 파일을 정리 폴더로 이동, 최종 산물만 보관&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Step 1. 이미지 모델로 첫 포즈 만들기&lt;/h2&gt;

&lt;p&gt;GPT Image, Nano Banana 같은 이미지 모델로 캐릭터의 첫 포즈를 만듭니다. 이 단계에서 &lt;em&gt;배경과 여백&lt;/em&gt;을 어떻게 설정하느냐가 전체 파이프라인의 성패를 가릅니다.&lt;/p&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;배경은 &lt;code&gt;#00FF00&lt;/code&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;정확한 크로마키 초록색. 캐릭터 디자인에 이 색이 들어가면 안 됩니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;넉넉한 여백&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;초상화처럼 꽉 차게 만들지 마세요. 비디오 모델이 움직이면서 팔, 무기, 망토가 화면 밖으로 나갈 수 있습니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;금지 항목&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;그림자, 바닥, 소품, 그라데이션, 텍스트, 워터마크 없이 깨끗하게.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;전환 포즈 전략&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;극단적인 포즈보다 기본 자세에서 살짝 움직인 중간 포즈가 시작점으로 좋습니다.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Step 2. 비디오 모델로 움직임 만들기&lt;/h2&gt;

&lt;p&gt;첫 포즈를 Kling 같은 비디오 모델에 넣고 애니메이션 영상을 만듭니다. 여기서 핵심은 &lt;em&gt;프롬프트를 기계적으로 쓰는 것&lt;/em&gt;입니다. 감성적 표현은 모델을 혼란스럽게 만듭니다.&lt;/p&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;VS&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;프롬프트 비교 — 검 공격 애니메이션&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box bad&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Bad — 감성적 프롬프트&lt;/div&gt;
      빠른 검 공격
    &lt;/div&gt;
    &lt;div class=&quot;prompt-box good&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;Good — 기계적 프롬프트&lt;/div&gt;
      업로드한 이미지를 정확한 첫 프레임으로 사용한다.&lt;br&gt;
      캐릭터가 검을 머리 위로 들어 올리고, 잠깐 준비 자세를 취한 뒤, 한 걸음 앞으로 움직이며 아래로 검을 내려친다.&lt;br&gt;
      이후 후속 동작을 거쳐 준비 자세로 돌아온다.&lt;br&gt;
      카메라는 고정되어야 하며, 줌/팬/회전/흔들림이 없어야 한다.&lt;br&gt;
      캐릭터는 화면 중앙에 유지되고, 전체 몸과 검은 프레임 안에 있어야 한다.&lt;br&gt;
      배경은 항상 평평한 &lt;code&gt;#00FF00&lt;/code&gt; 초록색이어야 한다.
    &lt;/div&gt;
    &lt;div class=&quot;result-tag&quot;&gt;감성 → 기계적 묘사로 전환&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;비디오 모델 필수 조건&lt;/h3&gt;

&lt;table class=&quot;helper-table&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;캐릭터 일관성 유지&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;/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;/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;#00FF00&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;/tbody&gt;
&lt;/table&gt;

&lt;div class=&quot;callout info&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;i&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;단순한 픽셀 RPG 캐릭터라면 오히려 짧고 명확한 프롬프트가 좋습니다. 너무 긴 프롬프트는 모델이 불필요하게 캐릭터를 회전시키거나 재해석하게 만들 수 있습니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Step 3. 비디오에서 프레임 추출하기&lt;/h2&gt;

&lt;p&gt;로컬에서 &lt;code&gt;FFmpeg&lt;/code&gt;를 사용해 비디오의 모든 프레임을 PNG로 추출합니다. 이때 &lt;em&gt;캐릭터만 잘라내지 않는 것&lt;/em&gt;이 중요합니다.&lt;/p&gt;

&lt;p&gt;전체 비디오 캔버스가 정렬 기준이기 때문에, 캐릭터 주변을 프레임마다 다르게 자르면 애니메이션이 흔들립니다. 영상에서의 &lt;em&gt;고정 카메라 위치&lt;/em&gt;를 그대로 보존해야 합니다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;python&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# tools/extract_frames_ffmpeg.py&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 비디오 → 전체 프레임 PNG 추출&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# frame_0001.png, frame_0002.png, ...&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 추출 정보 JSON 리포트 생성&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# FPS 샘플링, FFmpeg crop 옵션 지원&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2&gt;Step 4. 사용할 프레임 선택하기&lt;/h2&gt;

&lt;p&gt;추출된 프레임 중 실제 스프라이트에 넣을 프레임을 고릅니다. 균등 간격으로 고르면 안 되고, &lt;em&gt;동작의 흐름&lt;/em&gt;을 기준으로 선택해야 합니다.&lt;/p&gt;

&lt;h3&gt;프레임 선택 우선순위&lt;/h3&gt;

&lt;ol class=&quot;rule-list&quot;&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;em&gt;읽기 쉬운 동작 흐름&lt;/em&gt;을 골라야 합니다.&lt;/p&gt;

&lt;div class=&quot;callout tip&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;!&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;보통 게임에는 &lt;strong&gt;12프레임 시트&lt;/strong&gt;를 사용합니다. 24프레임 시트는 더 부드러운 참고용이나 느린 동작에 사용합니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Step 5. 배경 보정 (필요할 때만)&lt;/h2&gt;

&lt;p&gt;정상적이라면 &lt;code&gt;#00FF00&lt;/code&gt; 크로마키 배경을 그대로 제거하면 됩니다. 하지만 배경이 흰색, 회색, 연한 색으로 생성되었거나 초록색이 정확하지 않을 때만 보정 스크립트를 사용합니다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;python&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# tools/matte_light_background.py&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 프레임 모서리 색으로 배경색 추정&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 비슷한 배경색 제거&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 부드러운 알파 가장자리 생성&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 리포트 생성&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;callout warning&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;!&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;이 스크립트는 &lt;strong&gt;응급용&lt;/strong&gt;입니다. 가장 좋은 방법은 처음부터 정확한 &lt;code&gt;#00FF00&lt;/code&gt; 배경으로 만드는 것입니다. 보정은 품질 손실을 피할 수 없습니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Step 6. 초록 배경 제거 후 스프라이트 시트 만들기&lt;/h2&gt;

&lt;p&gt;파이프라인의 핵심 단계입니다. &lt;code&gt;animation_pipeline.py&lt;/code&gt;가 선택된 프레임을 불러와 배경을 제거하고 스프라이트 시트를 생성합니다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;python&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# tools/animation_pipeline.py 처리 순서&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt; 선택된 프레임 불러오기
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;2.&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;#00FF00&lt;/span&gt; 배경 제거
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;3.&lt;/span&gt; 초록색 테두리 번짐 제거
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;4.&lt;/span&gt; 작은 노이즈 제거
&lt;span class=&quot;line-num&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;5.&lt;/span&gt; 각 프레임을 &lt;span class=&quot;number&quot;&gt;256&lt;/span&gt;x&lt;span class=&quot;number&quot;&gt;256&lt;/span&gt; 투명 PNG로 변환
&lt;span class=&quot;line-num&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;6.&lt;/span&gt; 가로형 스프라이트 시트 생성
&lt;span class=&quot;line-num&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;7.&lt;/span&gt; 미리보기 이미지 생성
&lt;span class=&quot;line-num&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;8.&lt;/span&gt; 검증 JSON 리포트 생성&lt;/pre&gt;
&lt;/div&gt;

&lt;h3&gt;출력 크기&lt;/h3&gt;

&lt;table class=&quot;helper-table&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;12프레임&lt;/td&gt;&lt;td&gt;&lt;code&gt;3072 x 256&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;24프레임&lt;/td&gt;&lt;td&gt;&lt;code&gt;6144 x 256&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3&gt;preserve-canvas 모드&lt;/h3&gt;

&lt;p&gt;이 모드는 전체 비디오 캐릭터를 그대로 256x256 셀 안에 축소합니다. 캐릭터만 잘라내거나 매 프레임 중앙 정렬하지 않습니다. 이게 중요한 이유는, 캐릭터를 프레임마다 다시 정렬하면 &lt;em&gt;가짜 카메라 움직임&lt;/em&gt;이 생기고 애니메이션이 흔들리기 때문입니다.&lt;/p&gt;

&lt;div class=&quot;quote-block&quot;&gt;
  &lt;p&gt;영상에서의 고정 카메라 위치를 그대로 보존해야 한다. 캐릭터를 프레임마다 재정렬하면 흔들린다.&lt;/p&gt;
&lt;/div&gt;

&lt;h2&gt;Step 7. 결과 검수하기&lt;/h2&gt;

&lt;p&gt;완성된 시트를 바로 게임에 넣으면 안 됩니다. 반드시 다음 항목을 검수합니다.&lt;/p&gt;

&lt;ol class=&quot;rule-list&quot;&gt;
  &lt;li&gt;리포트 상태가 &lt;code&gt;pass&lt;/code&gt;인지 확인&lt;/li&gt;
  &lt;li&gt;시트 크기가 정확한지 확인&lt;/li&gt;
  &lt;li&gt;모든 프레임의 캔버스 크기가 같은지 확인&lt;/li&gt;
  &lt;li&gt;모든 프레임의 스케일과 위치가 같은지 확인&lt;/li&gt;
  &lt;li&gt;무기, 팔다리, 망토, 머리카락, 이펙트가 잘리지 않았는지 확인&lt;/li&gt;
  &lt;li&gt;중복 프레임이 의도된 것인지 확인&lt;/li&gt;
  &lt;li&gt;움직임이 튀지 않는지 확인&lt;/li&gt;
  &lt;li&gt;워터마크가 제거되었는지 확인&lt;/li&gt;
  &lt;li&gt;다른 캐릭터 애니메이션과 크기가 맞는지 확인&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;최종 파일 구조&lt;/h3&gt;

&lt;div class=&quot;dir-tree&quot;&gt;
&lt;span class=&quot;file&quot;&gt;final_sprites/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;  character/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;    animation/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;      sheets/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;        character_animation_12f_256.png&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 12프레임 스프라이트 시트&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;        character_animation_24f_256.png&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 24프레임 스프라이트 시트&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;      frames/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;        12f_256/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 개별 프레임&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;        24f_256/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 개별 프레임&lt;/span&gt;
&lt;/div&gt;

&lt;h2&gt;Step 8. 로컬 미리보기 갤러리&lt;/h2&gt;

&lt;p&gt;스프라이트 시트를 쉽게 비교하려면 정적 HTML 뷰어를 만듭니다. &lt;code&gt;build_sprite_gallery_manifest.py&lt;/code&gt;가 &lt;code&gt;final_sprites/&lt;/code&gt; 폴더를 스캔해서 매니페스트를 생성합니다.&lt;/p&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;프레임 단위 재생&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;선택한 시트를 프레임별로 재생하고 FPS를 조절할 수 있습니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;체크무늬 배경&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;투명 배경을 확인할 수 있는 체크무늬 배경을 지원합니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;캐릭터 필터&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;캐릭터와 애니메이션 종류별로 필터링해서 비교할 수 있습니다.&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;메타데이터 표시&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;파일 경로와 메타데이터를 함께 보여줍니다.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Step 9. 임시 파일 정리하기&lt;/h2&gt;

&lt;p&gt;추출된 고해상도 프레임은 용량이 큽니다. 하지만 코딩 에이전트에게 파일을 바로 삭제하게 하지 말고, 사람이 확인 후 지울 수 있도록 &lt;em&gt;정리 폴더로 옮기게&lt;/em&gt; 하는 것이 안전합니다.&lt;/p&gt;

&lt;div class=&quot;dir-tree&quot;&gt;
&lt;span class=&quot;file&quot;&gt;cleanup_ready_to_trash/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 나중에 삭제해도 되는 파일&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;  character_animation/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;    extracted/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 추출된 전체 프레임&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;    selected/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 중간 선택 프레임&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;    matted/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 배경 제거 중간 파일&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;    rejected_source_videos/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 실패한 영상&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;processed_source_videos/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 보관할 파일&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;  character_animation/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;    accepted_source_video.mp4&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 최종 채택 비디오&lt;/span&gt;
&lt;/div&gt;

&lt;h3&gt;보관 vs 정리&lt;/h3&gt;

&lt;table class=&quot;helper-table&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;추출된 전체 프레임&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;JSON 리포트&lt;/td&gt;&lt;td&gt;실패한 영상&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Contact sheet&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;h2&gt;핵심 팁 모음&lt;/h2&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;★&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;실전에서 검증된 12가지 원칙&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;ol class=&quot;rule-list&quot;&gt;
      &lt;li&gt;첫 포즈는 &lt;em&gt;초상화가 아니라 애니메이션용&lt;/em&gt;으로 만들어야 합니다. 넉넉한 여백이 필수입니다.&lt;/li&gt;
      &lt;li&gt;비디오 모델은 첫 포즈보다 &lt;em&gt;더 크게 움직이는 경향&lt;/em&gt;이 있습니다. 여유를 두세요.&lt;/li&gt;
      &lt;li&gt;공격, 점프, 달리기 등은 &lt;em&gt;극단 포즈보다 전환 포즈&lt;/em&gt;에서 시작하는 것이 좋습니다.&lt;/li&gt;
      &lt;li&gt;프롬프트는 감성적 표현보다 &lt;em&gt;기계적 동작 설명&lt;/em&gt;이 좋습니다.&lt;/li&gt;
      &lt;li&gt;&quot;빠른 공격&quot;보다 &quot;검을 들어 올림 → 멈춤 → 내려침 → 회복&quot;처럼 &lt;em&gt;단계별로 써야&lt;/em&gt; 합니다.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;카메라 고정 조건&lt;/em&gt;을 반드시 넣어야 합니다.&lt;/li&gt;
      &lt;li&gt;점프, 착지, 낙하 같은 수직 애니메이션은 캐릭터 움직임과 먼지/바람 효과를 &lt;em&gt;따로 만드는 것&lt;/em&gt;이 좋습니다.&lt;/li&gt;
      &lt;li&gt;마지막 프레임이 첫 프레임과 너무 비슷하면 애니메이션이 &lt;em&gt;멈춘 것처럼 보일 수&lt;/em&gt; 있습니다.&lt;/li&gt;
      &lt;li&gt;끝 포즈가 idle과 잘 연결되지 않으면 &lt;em&gt;이미지 모델로 브릿지 프레임&lt;/em&gt;을 만드세요. 비디오 재생성보다 저렴합니다.&lt;/li&gt;
      &lt;li&gt;비용을 줄이고 싶다면 이미지 모델만으로도 가능하지만, &lt;em&gt;품질과 안정성은 비디오 모델 함께 쓸 때 훨씬 좋습니다&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/article&gt;

&lt;footer class=&quot;footer&quot;&gt;
  &lt;p&gt;이미지 모델 → 비디오 모델 → 파이썬 자동화 파이프라인&lt;/p&gt;
  &lt;p style=&quot;margin-top: 8px;&quot;&gt;GPT Image &amp;middot; Kling &amp;middot; FFmpeg &amp;middot; Pillow&lt;/p&gt;
  &lt;p style=&quot;margin-top: 16px;&quot;&gt;&lt;a href=&quot;https://x.com/i/status/2050277473116619240&quot;&gt;출처: X (Twitter) 원문 보기&lt;/a&gt;&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
document.querySelectorAll('.code-block').forEach(function(block) {
  var header = block.querySelector('.code-header');
  var pre = block.querySelector('pre');
  if (!header || !pre) return;
  var btn = document.createElement('button');
  btn.className = 'copy-btn';
  btn.textContent = 'COPY';
  btn.addEventListener('click', function() {
    var text = pre.innerText.replace(/^\d+\s*/gm, '');
    navigator.clipboard.writeText(text).then(function() {
      btn.textContent = 'COPIED';
      btn.classList.add('copied');
      setTimeout(function() {
        btn.textContent = 'COPY';
        btn.classList.remove('copied');
      }, 2000);
    });
  });
  header.appendChild(btn);
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1754</guid>
      <comments>https://javaexpert.tistory.com/1754#entry1754comment</comments>
      <pubDate>Sat, 2 May 2026 20:33:56 +0900</pubDate>
    </item>
    <item>
      <title>Open Design &amp;mdash; 에이전트 시대의 오픈소스 디자인 도</title>
      <link>https://javaexpert.tistory.com/1753</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;Open Design — 에이전트 시대의 오픈소스 디자인 도구&lt;/title&gt;
&lt;style&gt;
  @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@400;600;700&amp;family=Noto+Sans+KR:wght@300;400;500;600&amp;family=Fira+Code:wght@400;500&amp;display=swap');

  :root {
    --bg: #fafaf8;
    --text: #1a1a1a;
    --text-secondary: #666;
    --text-light: #999;
    --accent: #e8572a;
    --accent-soft: #fff3ef;
    --border: #e8e6e1;
    --code-bg: #282c34;
    --code-text: #abb2bf;
    --inline-code-bg: #f0ede8;
    --card-bg: #ffffff;
    --shadow: 0 1px 4px rgba(0,0,0,0.04);
  }

  * { margin: 0; padding: 0; box-sizing: border-box; }

  body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Noto Sans KR', -apple-system, sans-serif;
    font-size: 17px;
    line-height: 1.9;
    -webkit-font-smoothing: antialiased;
  }

  /* ── Header ── */
  .header {
    text-align: center;
    padding: 100px 24px 60px;
    max-width: 680px;
    margin: 0 auto;
  }

  .header .topic {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 20px;
    padding: 4px 16px;
    margin-bottom: 32px;
  }

  .header h1 {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    line-height: 1.45;
    letter-spacing: -0.5px;
    margin-bottom: 24px;
  }

  .header .subtitle {
    font-size: 18px;
    color: var(--text-secondary);
    line-height: 1.8;
    font-weight: 300;
  }

  .header .meta {
    margin-top: 40px;
    font-size: 14px;
    color: var(--text-light);
  }

  .divider {
    max-width: 680px;
    margin: 0 auto;
    border: none;
    border-top: 1px solid var(--border);
  }

  /* ── Article ── */
  .article {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 24px;
  }

  .article h2 {
    font-family: 'Noto Serif KR', serif;
    font-size: 26px;
    font-weight: 700;
    margin: 80px 0 24px;
    line-height: 1.4;
    letter-spacing: -0.3px;
  }

  .article h3 {
    font-family: 'Noto Serif KR', serif;
    font-size: 20px;
    font-weight: 600;
    margin: 48px 0 16px;
    line-height: 1.5;
  }

  .article h4 {
    font-family: 'Noto Serif KR', serif;
    font-size: 17px;
    font-weight: 600;
    margin: 36px 0 12px;
    line-height: 1.5;
  }

  .article p {
    margin-bottom: 20px;
  }

  .article strong {
    font-weight: 600;
  }

  .article em {
    font-style: normal;
    color: var(--accent);
    font-weight: 500;
  }

  .article ul, .article ol {
    margin: 16px 0 24px 20px;
  }

  .article li {
    margin-bottom: 8px;
  }

  /* ── Quote Block ── */
  .quote-block {
    border-left: 3px solid var(--accent);
    padding: 20px 28px;
    margin: 32px 0;
    background: var(--accent-soft);
    border-radius: 0 8px 8px 0;
  }

  .quote-block p {
    margin-bottom: 0;
    font-size: 16px;
  }

  /* ── Inline Code ── */
  code {
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 0.88em;
    background: var(--inline-code-bg);
    padding: 2px 7px;
    border-radius: 4px;
    color: var(--accent);
  }

  /* ── Code Block ── */
  .code-block {
    margin: 28px 0;
    border-radius: 10px;
    overflow: hidden;
    background: var(--code-bg);
    box-shadow: 0 2px 12px rgba(0,0,0,0.12);
  }

  .code-block .code-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: #21252b;
    border-bottom: 1px solid #181a1f;
  }

  .code-block .code-header .lang-label {
    font-family: 'Fira Code', monospace;
    font-size: 12px;
    color: #636d83;
    text-transform: uppercase;
    letter-spacing: 1px;
  }

  .copy-btn {
    background: none;
    border: 1px solid #3e4451;
    color: #636d83;
    font-family: 'Fira Code', monospace;
    font-size: 11px;
    padding: 3px 10px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
    letter-spacing: 0.5px;
  }

  .copy-btn:hover {
    border-color: #abb2bf;
    color: #abb2bf;
  }

  .copy-btn.copied {
    border-color: #98c379;
    color: #98c379;
  }

  .code-block .code-header .dots {
    display: flex;
    gap: 6px;
  }

  .code-block .code-header .dots span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
  }

  .code-block .code-header .dots span:nth-child(1) { background: #ff5f57; }
  .code-block .code-header .dots span:nth-child(2) { background: #febc2e; }
  .code-block .code-header .dots span:nth-child(3) { background: #28c840; }

  .code-block pre {
    padding: 20px 24px;
    overflow-x: auto;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.7;
    color: var(--code-text);
    tab-size: 2;
  }

  .code-block pre .line-num {
    display: inline-block;
    width: 36px;
    color: #4b5263;
    text-align: right;
    margin-right: 20px;
    user-select: none;
    -webkit-user-select: none;
  }

  /* Syntax Highlighting */
  .code-block pre .keyword   { color: #c678dd; }
  .code-block pre .string    { color: #98c379; }
  .code-block pre .number    { color: #d19a66; }
  .code-block pre .comment   { color: #5c6370; font-style: italic; }
  .code-block pre .function  { color: #61afef; }
  .code-block pre .operator  { color: #56b6c2; }
  .code-block pre .type      { color: #e5c07b; }
  .code-block pre .variable  { color: #e06c75; }
  .code-block pre .tag       { color: #e06c75; }
  .code-block pre .attr      { color: #d19a66; }
  .code-block pre .punct     { color: #abb2bf; }
  .code-block pre .property  { color: #e06c75; }
  .code-block pre .selector  { color: #98c379; }
  .code-block pre .value     { color: #d19a66; }

  /* ── Feature Cards ── */
  .feature-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin: 32px 0;
  }

  .feature-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 24px;
    box-shadow: var(--shadow);
    transition: transform 0.2s, box-shadow 0.2s;
  }

  .feature-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  }

  .feature-card .icon {
    font-size: 28px;
    margin-bottom: 12px;
  }

  .feature-card .title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 6px;
  }

  .feature-card .desc {
    font-size: 14px;
    color: var(--text-secondary);
    line-height: 1.6;
  }

  /* ── Pipeline / Step Flow ── */
  .pipeline {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 32px 28px;
    margin: 32px 0;
    box-shadow: var(--shadow);
  }

  .pipeline .step {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 14px 0;
    position: relative;
  }

  .pipeline .step:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 15px;
    top: 48px;
    bottom: -2px;
    width: 2px;
    background: var(--border);
  }

  .pipeline .step-num {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .pipeline .step-content {
    flex: 1;
    padding-top: 4px;
  }

  .pipeline .step-title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 2px;
  }

  .pipeline .step-desc {
    font-size: 14px;
    color: var(--text-secondary);
  }

  /* ── Example Card ── */
  .example-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    margin: 32px 0;
    overflow: hidden;
    box-shadow: var(--shadow);
  }

  .example-card .example-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .example-card .example-num {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 600;
    flex-shrink: 0;
  }

  .example-card .example-title {
    font-weight: 600;
    font-size: 16px;
  }

  .example-card .example-body {
    padding: 24px;
  }

  .prompt-box {
    background: #f8f7f4;
    border-radius: 8px;
    padding: 16px 20px;
    margin-bottom: 20px;
    font-size: 15px;
    line-height: 1.7;
    color: var(--text);
    border-left: 3px solid var(--accent);
  }

  .prompt-box .label {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 8px;
  }

  .process-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .process-list li {
    padding: 6px 0 6px 24px;
    position: relative;
    font-size: 15px;
    color: var(--text-secondary);
  }

  .process-list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 14px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border);
  }

  .process-list li:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 26px;
    bottom: -8px;
    width: 2px;
    background: var(--border);
  }

  .result-tag {
    display: inline-block;
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    background: var(--accent-soft);
    padding: 4px 12px;
    border-radius: 4px;
    margin-top: 16px;
  }

  /* ── Helper Table ── */
  .helper-table {
    width: 100%;
    border-collapse: collapse;
    margin: 24px 0;
    font-size: 15px;
  }

  .helper-table th {
    text-align: left;
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-light);
    padding: 12px 16px;
    border-bottom: 2px solid var(--border);
  }

  .helper-table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
  }

  /* ── Directory Tree ── */
  .dir-tree {
    background: #f5f3ef;
    border-radius: 8px;
    padding: 24px;
    font-family: 'Fira Code', 'SF Mono', monospace;
    font-size: 14px;
    line-height: 1.8;
    color: var(--text-secondary);
    margin: 24px 0;
  }

  .dir-tree .file { color: var(--text); display: block; }
  .dir-tree .comment { color: var(--text-light); font-family: 'Noto Sans KR', sans-serif; font-size: 13px; }

  /* ── Rule List ── */
  .rule-list {
    counter-reset: rule;
    list-style: none;
    margin: 24px 0;
    padding: 0;
  }

  .rule-list li {
    counter-increment: rule;
    padding: 14px 16px 14px 56px;
    position: relative;
    border-bottom: 1px solid var(--border);
    font-size: 15px;
  }

  .rule-list li::before {
    content: counter(rule, decimal-leading-zero);
    position: absolute;
    left: 16px;
    top: 14px;
    font-family: 'Fira Code', monospace;
    font-size: 13px;
    color: var(--accent);
    font-weight: 600;
  }

  .rule-list li:last-child {
    border-bottom: none;
  }

  /* ── Image ── */
  .article img {
    max-width: 100%;
    border-radius: 8px;
    margin: 16px 0;
  }

  .article figcaption {
    font-size: 14px;
    color: var(--text-light);
    text-align: center;
    margin-top: 8px;
  }

  /* ── Callout ── */
  .callout {
    display: flex;
    gap: 16px;
    padding: 20px 24px;
    border-radius: 8px;
    margin: 28px 0;
  }

  .callout.info {
    background: #edf4fc;
    border-left: 3px solid #3b82f6;
  }

  .callout.warning {
    background: #fef9ec;
    border-left: 3px solid #f59e0b;
  }

  .callout.tip {
    background: #ecfdf5;
    border-left: 3px solid #10b981;
  }

  .callout .callout-icon {
    font-size: 20px;
    flex-shrink: 0;
    padding-top: 2px;
  }

  .callout .callout-body {
    flex: 1;
  }

  .callout .callout-body p {
    margin-bottom: 0;
    font-size: 15px;
  }

  /* ── Footer ── */
  .footer {
    max-width: 680px;
    margin: 80px auto 0;
    padding: 40px 24px;
    border-top: 1px solid var(--border);
    text-align: center;
    font-size: 14px;
    color: var(--text-light);
  }

  .footer a {
    color: var(--accent);
    text-decoration: none;
  }

  /* ── Responsive ── */
  @media (max-width: 640px) {
    .header { padding: 60px 20px 40px; }
    .header h1 { font-size: 26px; }
    .feature-grid { grid-template-columns: 1fr; }
    .article h2 { font-size: 22px; }
    .code-block pre { font-size: 12px; }
  }

  /* ── Scroll-triggered Animations ── */
  @keyframes fadeInUp {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: translateY(0); }
  }

  @keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  .animate-on-scroll {
    opacity: 0;
    transition: none;
  }

  .animate-on-scroll.visible {
    animation: fadeInUp 0.6s ease-out forwards;
  }

  .animate-on-scroll.visible-delay-1 { animation-delay: 0.1s; }
  .animate-on-scroll.visible-delay-2 { animation-delay: 0.2s; }
  .animate-on-scroll.visible-delay-3 { animation-delay: 0.3s; }

  /* ── Header Entrance ── */
  .header .topic {
    animation: fadeIn 0.8s ease-out 0.2s both;
  }

  .header h1 {
    animation: fadeInUp 0.8s ease-out 0.4s both;
  }

  .header .subtitle {
    animation: fadeInUp 0.8s ease-out 0.6s both;
  }

  .header .meta {
    animation: fadeIn 0.8s ease-out 0.8s both;
  }

  /* ── Audio Waveform Animation ── */
  .waveform {
    display: flex;
    align-items: center;
    gap: 3px;
    height: 32px;
    margin: 24px 0;
  }

  .waveform .bar {
    width: 4px;
    border-radius: 2px;
    background: var(--accent);
    animation: wave 1.2s ease-in-out infinite;
  }

  .waveform .bar:nth-child(1)  { animation-delay: 0s; }
  .waveform .bar:nth-child(2)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(3)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(4)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(5)  { animation-delay: 0.4s; }
  .waveform .bar:nth-child(6)  { animation-delay: 0.3s; }
  .waveform .bar:nth-child(7)  { animation-delay: 0.2s; }
  .waveform .bar:nth-child(8)  { animation-delay: 0.1s; }
  .waveform .bar:nth-child(9)  { animation-delay: 0s; }
  .waveform .bar:nth-child(10) { animation-delay: 0.1s; }
  .waveform .bar:nth-child(11) { animation-delay: 0.2s; }
  .waveform .bar:nth-child(12) { animation-delay: 0.3s; }

  @keyframes wave {
    0%, 100% { height: 8px; opacity: 0.4; }
    50% { height: 28px; opacity: 1; }
  }

  /* ── Animated Progress Bar ── */
  .progress-bar {
    background: var(--border);
    border-radius: 4px;
    height: 6px;
    margin: 24px 0;
    overflow: hidden;
  }

  .progress-bar .fill {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--accent), #f4845f);
    animation: progressFill 2s ease-out forwards;
    transform-origin: left;
  }

  @keyframes progressFill {
    from { width: 0; }
  }

  /* ── Typing Effect ── */
  .typing {
    font-family: 'Fira Code', monospace;
    font-size: 15px;
    color: var(--text);
    border-right: 2px solid var(--accent);
    white-space: nowrap;
    overflow: hidden;
    animation: typing 3s steps(40) forwards, blink 0.8s step-end infinite;
    width: 0;
  }

  @keyframes typing {
    to { width: 100%; }
  }

  @keyframes blink {
    50% { border-color: transparent; }
  }

  /* ── Pulse Dot ── */
  .pulse-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    margin-right: 8px;
    animation: pulse 2s ease-in-out infinite;
  }

  @keyframes pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.5); opacity: 0.5; }
  }

  /* ── Floating Badge ── */
  .float-badge {
    display: inline-block;
    font-size: 12px;
    font-weight: 600;
    color: white;
    background: var(--accent);
    padding: 4px 12px;
    border-radius: 12px;
    animation: float 3s ease-in-out infinite;
  }

  @keyframes float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-4px); }
  }

  /* ── Shimmer Loading ── */
  .shimmer {
    background: linear-gradient(90deg, var(--border) 25%, #f0ede8 50%, var(--border) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    border-radius: 4px;
    height: 16px;
    margin: 8px 0;
  }

  @keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
  }

  /* ── Animated Counter ── */
  .counter {
    font-family: 'Noto Serif KR', serif;
    font-size: 36px;
    font-weight: 700;
    color: var(--accent);
  }

  /* ── Bouncing Arrow ── */
  .bounce-arrow {
    display: inline-block;
    animation: bounce 1.5s ease-in-out infinite;
    color: var(--accent);
  }

  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(6px); }
  }

  /* ── Feature Card Stagger ── */
  .feature-grid .feature-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .feature-grid .feature-card:nth-child(1) { animation-delay: 0.1s; }
  .feature-grid .feature-card:nth-child(2) { animation-delay: 0.2s; }
  .feature-grid .feature-card:nth-child(3) { animation-delay: 0.3s; }
  .feature-grid .feature-card:nth-child(4) { animation-delay: 0.4s; }
  .feature-grid .feature-card:nth-child(5) { animation-delay: 0.5s; }
  .feature-grid .feature-card:nth-child(6) { animation-delay: 0.6s; }

  /* ── Pipeline Step Stagger ── */
  .pipeline .step {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  .pipeline .step:nth-child(1) { animation-delay: 0.1s; }
  .pipeline .step:nth-child(2) { animation-delay: 0.3s; }
  .pipeline .step:nth-child(3) { animation-delay: 0.5s; }
  .pipeline .step:nth-child(4) { animation-delay: 0.7s; }

  /* ── Example Card Stagger ── */
  .example-card {
    opacity: 0;
    animation: fadeInUp 0.5s ease-out forwards;
  }

  /* ── Quote Block Slide-in ── */
  .quote-block {
    animation: slideInLeft 0.6s ease-out;
  }

  @keyframes slideInLeft {
    from { opacity: 0; transform: translateX(-20px); }
    to { opacity: 1; transform: translateX(0); }
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;header class=&quot;header&quot;&gt;
  &lt;div class=&quot;topic&quot;&gt;Open Source · Design Tool&lt;/div&gt;
  &lt;h1&gt;당신의 에이전트가&lt;br&gt;디자인 엔진이 된다면&lt;/h1&gt;
  &lt;p class=&quot;subtitle&quot;&gt;Open Design — 로컬에서 실행되고, 에이전트를 선택하고,&lt;br&gt;스킬을 조합하는 오픈소스 디자인 생성 도구&lt;/p&gt;
  &lt;div class=&quot;meta&quot;&gt;2026.04.29 &amp;middot; Open Design Team&lt;/div&gt;
&lt;/header&gt;
&lt;hr class=&quot;divider&quot;&gt;

&lt;article class=&quot;article&quot;&gt;

&lt;h2&gt;왜 이 프로젝트가 필요한가&lt;/h2&gt;

&lt;p&gt;2026년 4월, Anthropic이 &lt;em&gt;Claude Design&lt;/em&gt;을 공개했다. LLM이 글을 쓰는 대신 실제 디자인 산출물을 배송하는 첫 번째 순간이었다. 반응은 폭발적이었다. 그리고 그대로 &lt;strong&gt;폐쇄형, 유료, 클라우드 전용, Anthropic 모델 락인&lt;/strong&gt;이었다.&lt;/p&gt;

&lt;p&gt;직접 호스팅할 수 없다. Vercel에 배포할 수 없다. 다른 에이전트를 끼워 넣을 수 없다. 스킬을 수정하거나 새로 만들 수 없다.&lt;/p&gt;

&lt;div class=&quot;quote-block&quot;&gt;
  &lt;p&gt;Open Design은 같은 루프, 같은 산출물 중심의 접근 방식을 취하면서, 모든 락인을 제거한다. 에이전트도, 모델도, 스킬 카탈로그도 직접 소유하지 않는다. 세 가지 모두 외부에서 꽂는 구조다.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;이것은 &quot;또 하나의 AI 디자인 도구&quot;가 아니다. &lt;em&gt;당신이 이미 가지고 있는 코딩 에이전트를 디자인 워크플로우로 연결하는 통합 셸&lt;/em&gt;이다.&lt;/p&gt;

&lt;h2&gt;한눈에 보는 핵심&lt;/h2&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt;⚡&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;6개 에이전트 지원&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, Qwen Code — 이미 설치된 CLI를 자동 감지하여 실행&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;71개 디자인 시스템&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;Stripe, Vercel, Linear, Notion, Tesla, Apple 등 브랜드급 시스템이 DESIGN.md 형태로 내장&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;30개 디자인 스킬&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;웹 프로토타입, 모바일 앱, 대시보드, 프레젠테이션, SaaS 랜딩까지 폴더 하나로 확장 가능&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;Local-first&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;모든 데이터는 로컬 SQLite에 저장. 클라우드 의존성 없이 pnpm dev, Vercel, 단일 프로세스 어디든 배포&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;5개 비주얼 디렉션&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;Editorial Monocle, Modern Minimal, Tech Utility, Brutalist, Soft Warm — 결정론적 팔레트와 폰트 스택 제공&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;디바이스 프레임&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;iPhone 15 Pro, Pixel, iPad Pro, MacBook, Browser Chrome — 픽셀 단위 정확한 프레임 내장&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;어떻게 동작하는가&lt;/h2&gt;

&lt;p&gt;Open Design의 아키텍처는 &lt;strong&gt;세 개의 레이어&lt;/strong&gt;로 구성된다. 사용자의 브라우저, 로컬 데몬, 그리고 이미 설치된 에이전트 CLI.&lt;/p&gt;

&lt;div class=&quot;pipeline&quot;&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;브리프 입력&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;사용자가 자연어로 디자인 요구사항을 입력하고, 스킬과 디자인 시스템을 선택&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;프롬프트 조합&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;데몬이 디스커버리 레이어 + 디자인 시스템 + 스킬 + 프로젝트 메타데이터를 다층 시스템 프롬프트로 조합&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;에이전트 실행&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;선택된 에이전트 CLI를 child_process로 실행, 실제 파일 시스템 위에서 Read/Write/Bash 권한 부여&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;step&quot;&gt;
    &lt;div class=&quot;step-num&quot;&gt;4&lt;/div&gt;
    &lt;div class=&quot;step-content&quot;&gt;
      &lt;div class=&quot;step-title&quot;&gt;실시간 렌더링&lt;/div&gt;
      &lt;div class=&quot;step-desc&quot;&gt;SSE 스트리밍으로 에이전트 출력을 받아 artifact 태그를 파싱, 샌드박스 iframe에서 즉시 미리보기&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;시스템 구조&lt;/h3&gt;

&lt;div class=&quot;dir-tree&quot;&gt;
&lt;span class=&quot;file&quot;&gt;open-design/&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── src/&lt;/span&gt;             &lt;span class=&quot;comment&quot;&gt;# React + TypeScript 프론트엔드&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── daemon/&lt;/span&gt;          &lt;span class=&quot;comment&quot;&gt;# Express + SQLite 백엔드&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── skills/&lt;/span&gt;          &lt;span class=&quot;comment&quot;&gt;# 30개 파일 기반 디자인 스킬&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── design-systems/&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 71개 브랜드 디자인 시스템&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;├── assets/frames/&lt;/span&gt;   &lt;span class=&quot;comment&quot;&gt;# 디바이스 프레임 HTML&lt;/span&gt;
&lt;span class=&quot;file&quot;&gt;└── docs/&lt;/span&gt;            &lt;span class=&quot;comment&quot;&gt;# 제품 스펙, 아키텍처, 로드맵&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;프론트엔드는 &lt;em&gt;React 18 + TypeScript&lt;/em&gt;로 구성되어 있고, 상태관리는 순수 React hooks만 사용한다. Redux, Zustand 같은 외부 라이브러리는 없다. 라우팅도 커스텀 훅으로 처리한다.&lt;/p&gt;

&lt;p&gt;백엔드 데몬은 &lt;em&gt;Express + better-sqlite3&lt;/em&gt;로, TypeScript 없이 순수 JavaScript로 작성되었다. 프로젝트, 대화, 메시지, 탭 상태를 SQLite에 저장하고, 에이전트 CLI를 child_process로 실행한다.&lt;/p&gt;

&lt;h2&gt;스킬 시스템 — 폴더 하나로 확장&lt;/h2&gt;

&lt;p&gt;Open Design의 확장성은 &lt;em&gt;파일 기반 스킬 시스템&lt;/em&gt;에서 나온다. &lt;code&gt;skills/&lt;/code&gt; 폴더 아래에 디렉토리를 하나 만들고 &lt;code&gt;SKILL.md&lt;/code&gt; 파일을 넣으면, 그것이 곧 새로운 디자인 스킬이다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;markdown&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;SaaS Landing Page&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;컨버전 최적화 SaaS 랜딩 페이지 생성&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;property&quot;&gt;od.mode&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;prototype&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;property&quot;&gt;od.platform&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;web&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;property&quot;&gt;od.scenario&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;landing&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 워크플로우&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;히어로 섹션: 가치 제안 → CTA → 사회적 증명&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;2.&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;기능 섹션: 3-6개 핵심 기능 카드&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;3.&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;가격 섹션: 3티어 가격표&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;4.&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;푸터: 링크 + 뉴스레터&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;포크할 수 있고, 버전 관리할 수 있고, 공유할 수 있고, 심볼릭 링크로 설치할 수 있다. 서드파티가 &lt;code&gt;skills/&lt;/code&gt;에 폴더를 하나 떨어뜨리는 것만으로 확장이 완료된다.&lt;/p&gt;

&lt;h2&gt;디자인 시스템 — DESIGN.md로 표현&lt;/h2&gt;

&lt;p&gt;71개의 디자인 시스템이 각각 하나의 &lt;code&gt;DESIGN.md&lt;/code&gt; 파일로 존재한다. 이 파일은 &lt;em&gt;awesome-claude-design&lt;/em&gt;의 9섹션 스키마를 따른다.&lt;/p&gt;

&lt;table class=&quot;helper-table&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;Colors&lt;/td&gt;&lt;td&gt;팔레트 토큰 (primary, secondary, accent, neutral)&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Typography&lt;/td&gt;&lt;td&gt;폰트 패밀리, 크기, 웨이트 체계&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Spacing&lt;/td&gt;&lt;td&gt;간격 토큰 (4px 베이스 그리드)&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Components&lt;/td&gt;&lt;td&gt;버튼, 카드, 입력 필드 등 UI 컴포넌트 규칙&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Effects&lt;/td&gt;&lt;td&gt;그림자, 블러, 트랜지션 효과&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;에이전트는 시스템 프롬프트에서 이 토큰을 읽고, &lt;em&gt;결정론적&lt;/em&gt;으로 색상과 폰트를 적용한다. 모델이 자의적으로 색상을 고르지 않는다. 토큰이 지시하는 대로 만든다.&lt;/p&gt;

&lt;h2&gt;실제 사용 시나리오&lt;/h2&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;웹 프로토타입 생성&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;User Prompt&lt;/div&gt;
      &quot;Airbnb 스타일 검색 페이지 만들어줘. 우리 내부 디자인 시스템 적용하고.&quot;
    &lt;/div&gt;
    &lt;ol class=&quot;process-list&quot;&gt;
      &lt;li&gt;프로토타입 스킬 자동 선택, 사용자 DESIGN.md 로드&lt;/li&gt;
      &lt;li&gt;디스커버리 질문 폼으로 타겟, 톤, 브랜드 컨텍스트 확정&lt;/li&gt;
      &lt;li&gt;에이전트가 TodoWrite로 작업 계획을 스트리밍&lt;/li&gt;
      &lt;li&gt;HTML artifact가 샌드박스 iframe에서 실시간 렌더링&lt;/li&gt;
      &lt;li&gt;특정 요소 클릭 → 코멘트 → 에이전트가 해당 영역만 수정&lt;/li&gt;
    &lt;/ol&gt;
    &lt;div class=&quot;result-tag&quot;&gt;프로덕션급 HTML 프로토타입 완성&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;매거진 스타일 피치 덱&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;User Prompt&lt;/div&gt;
      &quot;시드 라운드용 8슬라이드 매거진 스타일 피치 덱 만들어줘.&quot;
    &lt;/div&gt;
    &lt;ol class=&quot;process-list&quot;&gt;
      &lt;li&gt;guizang-ppt 스킬로 라우팅 (매거진 레이아웃, WebGL 히어로)&lt;/li&gt;
      &lt;li&gt;5개 비주얼 디렉션 중 하나를 선택하는 두 번째 폼 표시&lt;/li&gt;
      &lt;li&gt;결정론적 OKLch 팔레트 + 폰트 스택 자동 적용&lt;/li&gt;
      &lt;li&gt;단일 파일 HTML 덱 생성, 화살표 키 내비게이션&lt;/li&gt;
      &lt;li&gt;PDF / PPTX / ZIP / Markdown으로 내보내기&lt;/li&gt;
    &lt;/ol&gt;
    &lt;div class=&quot;result-tag&quot;&gt;인쇄 가능한 피치 덱 완성&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;example-card&quot;&gt;
  &lt;div class=&quot;example-header&quot;&gt;
    &lt;div class=&quot;example-num&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;example-title&quot;&gt;디자인 시스템 구축&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;example-body&quot;&gt;
    &lt;div class=&quot;prompt-box&quot;&gt;
      &lt;div class=&quot;label&quot;&gt;User Prompt&lt;/div&gt;
      &quot;우리 브랜드 가이드 기반으로 DESIGN.md 만들어줘.&quot;
    &lt;/div&gt;
    &lt;ol class=&quot;process-list&quot;&gt;
      &lt;li&gt;스크린샷, 브랜드 가이드 PDF, 또는 Figma 링크 업로드&lt;/li&gt;
      &lt;li&gt;design-system-skill이 9섹션 포맷으로 DESIGN.md 생성&lt;/li&gt;
      &lt;li&gt;이후 모든 생성 작업에서 자동으로 해당 토큰 참조&lt;/li&gt;
      &lt;li&gt;프로토타입, 덱, 템플릿 모두 일관된 브랜드 적용&lt;/li&gt;
    &lt;/ol&gt;
    &lt;div class=&quot;result-tag&quot;&gt;브랜드 일관성 보장&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;3초만에 시작하기&lt;/h2&gt;

&lt;p&gt;설치와 실행은 터미널 명령 세 줄이면 충분하다.&lt;/p&gt;

&lt;div class=&quot;code-block&quot;&gt;
  &lt;div class=&quot;code-header&quot;&gt;
    &lt;div class=&quot;dots&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;span class=&quot;lang-label&quot;&gt;bash&lt;/span&gt;
  &lt;/div&gt;
  &lt;pre&gt;&lt;span class=&quot;line-num&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 저장소 클론&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;https://github.com/your-org/open-design.git&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;open-design&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 의존성 설치&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;pnpm&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;install&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;# 데몬 + 프론트엔드 동시 실행&lt;/span&gt;
&lt;span class=&quot;line-num&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;function&quot;&gt;pnpm&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;dev:all&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;callout tip&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;✓&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;&lt;code&gt;dev:all&lt;/code&gt; 스크립트는 데몬(포트 7456)과 Vite 개발 서버(포트 5173)를 동시에 실행합니다. 기본 포트가 사용 중이면 자동으로 다른 포트를 찾습니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;브라우저가 열리면 첫 화면에서 스킬을 고르고, 디자인 시스템을 선택하고, 브리프를 입력하면 바로 시작된다.&lt;/p&gt;

&lt;h2&gt;&quot;AI가 디자인한다&quot;가 아니다&lt;/h2&gt;

&lt;p&gt;Open Design의 프롬프트 스택은 에이전트에게 &lt;em&gt;시니어 디자이너의 작업 방식&lt;/em&gt;을 강제한다.&lt;/p&gt;

&lt;ol class=&quot;rule-list&quot;&gt;
  &lt;li&gt;모델이 한 픽셀도 그리기 전에, 디스커버리 폼으로 브리프를 확정한다&lt;/li&gt;
  &lt;li&gt;브랜드가 없으면 5개 큐레이션 디렉션 중 하나를 선택한다 — 모델이 자의적으로 정하지 않는다&lt;/li&gt;
  &lt;li&gt;에이전트가 TodoWrite로 작업 계획을 세우고, 실시간으로 진행 상황을 스트리밍한다&lt;/li&gt;
  &lt;li&gt;데몬이 실제 파일 시스템에 시드 템플릿, 레이아웃 라이브러리, 셀프체크 체크리스트를 구성한다&lt;/li&gt;
  &lt;li&gt;에이전트는 5차원 자기 비판을 수행한 후에야 &lt;code&gt;&amp;lt;artifact&amp;gt;&lt;/code&gt;를 출력한다&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;quote-block&quot;&gt;
  &lt;p&gt;그것은 &quot;AI가 뭔가 디자인해본다&quot;가 아니다. 프롬프트 스택에 의해 훈련된, 실제 파일 시스템과 결정론적 팔레트 라이브러리와 체크리스트 문화를 가진 시니어 디자이너의 행동이다.&lt;/p&gt;
&lt;/div&gt;

&lt;h2&gt;기술 스택 요약&lt;/h2&gt;

&lt;table class=&quot;helper-table&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;React 18 + TypeScript&lt;/td&gt;&lt;td&gt;Vite 5 빌드, 순수 hooks 상태관리&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;백엔드&lt;/td&gt;&lt;td&gt;Express + better-sqlite3&lt;/td&gt;&lt;td&gt;순수 JavaScript, TypeScript 없음&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;에이전트 통신&lt;/td&gt;&lt;td&gt;child_process + SSE&lt;/td&gt;&lt;td&gt;CLI stdout/stderr 스트리밍&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;데이터 저장&lt;/td&gt;&lt;td&gt;SQLite (WAL 모드)&lt;/td&gt;&lt;td&gt;프로젝트, 대화, 메시지, 탭 상태&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;산출물 렌더링&lt;/td&gt;&lt;td&gt;srcdoc iframe&lt;/td&gt;&lt;td&gt;샌드백스 환경, localStorage shim&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;라이선스&lt;/td&gt;&lt;td&gt;Apache 2.0&lt;/td&gt;&lt;td&gt;완전한 오픈소스&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2&gt;누구를 위한 도구인가&lt;/h2&gt;

&lt;div class=&quot;feature-grid&quot;&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; ‍ &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;인디 개발자 / 디자이너&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;이미 하나의 코딩 에이전트를 구독 중이라면, 추가 결제 없이 디자인 산출물을 얻을 수 있다&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; ️&lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;디자인 시스템 관리자&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;DESIGN.md로 시스템을 코드화하면, 모든 스킬이 자동으로 해당 토큰을 준수한다&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;스킬 작성자&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&quot;글라스모피즘 SaaS 마케팅 페이지&quot; 같은 디자인 스킬을 게시하면, 어떤 에이전트에서도 실행된다&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;feature-card&quot;&gt;
    &lt;div class=&quot;icon&quot;&gt; &lt;/div&gt;
    &lt;div class=&quot;title&quot;&gt;AI 도구 자체 호스팅 팀&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;Electron 바이너리가 아닌 웹 배포가 필요하고, 키를 자체 인프라에 보관해야 하는 팀&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;오픈소스의 어깨 위에서&lt;/h2&gt;

&lt;p&gt;Open Design은 네 개의 오픈소스 프로젝트 위에 서 있다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;huashu-design&lt;/strong&gt; — 디자인 철학 나침반. 주니어 디자이너 워크플로우, 5단계 브랜드 에셋 프로토콜, 안티 AI-slop 체크리스트가 모두 이 프로젝트에서 왔다&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;guizang-ppt-skill&lt;/strong&gt; — 덱 모드. 매거진 레이아웃, WebGL 히어로 배경, 단일 파일 HTML 출력을 제공한다&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;open-codesign&lt;/strong&gt; — UX 북스타. 스트리밍 artifact 루프, 샌드박스 iframe 프리뷰, 5가지 포맷 익스포트를 참고했다&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;multica&lt;/strong&gt; — 데몬 및 런타임 아키텍처. PATH 스캔 에이전트 감지, 로컬 데몬 패턴, 에이전트를 팀원으로 보는 세계관&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;다음 단계&lt;/h2&gt;

&lt;p&gt;Open Design은 현재 &lt;em&gt;Phase 0 (스펙 확정)&lt;/em&gt; 단계에서 &lt;em&gt;Phase 1 (MVP)&lt;/em&gt;로 진입하고 있다. 로드맵에 따르면 6-8주 내에 핵심 기능이 안정화될 예정이다.&lt;/p&gt;

&lt;p&gt;기여는 언제나 환영한다. 스킬을 만들어도 좋고, 디자인 시스템을 추가해도 좋고, 에이전트 어댑터를 개선해도 좋다. 중요한 것은 하나 — &lt;em&gt;에이전트도, 모델도, 스킬 카탈로그도 우리가 소유하지 않는다&lt;/em&gt;는 철학을 유지하는 것.&lt;/p&gt;

&lt;div class=&quot;callout info&quot;&gt;
  &lt;div class=&quot;callout-icon&quot;&gt;i&lt;/div&gt;
  &lt;div class=&quot;callout-body&quot;&gt;&lt;p&gt;Apache 2.0 라이선스로 배포됩니다. 포크, 수정, 상업적 사용 모두 자유입니다.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/article&gt;

&lt;footer class=&quot;footer&quot;&gt;
  &lt;p&gt;Open Design — the open-source alternative to Claude Design&lt;/p&gt;
  &lt;p style=&quot;margin-top: 8px;&quot;&gt;&lt;a href=&quot;https://github.com/nicepkg/open-design&quot;&gt;GitHub에서 보기&lt;/a&gt;&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
document.querySelectorAll('.code-block').forEach(function(block) {
  var header = block.querySelector('.code-header');
  var pre = block.querySelector('pre');
  if (!header || !pre) return;
  var btn = document.createElement('button');
  btn.className = 'copy-btn';
  btn.textContent = 'COPY';
  btn.addEventListener('click', function() {
    var text = pre.innerText.replace(/^\d+\s*/gm, '');
    navigator.clipboard.writeText(text).then(function() {
      btn.textContent = 'COPIED';
      btn.classList.add('copied');
      setTimeout(function() {
        btn.textContent = 'COPY';
        btn.classList.remove('copied');
      }, 2000);
    });
  });
  header.appendChild(btn);
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>AI</category>
      <author>행복한 수지아빠</author>
      <guid isPermaLink="true">https://javaexpert.tistory.com/1753</guid>
      <comments>https://javaexpert.tistory.com/1753#entry1753comment</comments>
      <pubDate>Wed, 29 Apr 2026 16:46:15 +0900</pubDate>
    </item>
  </channel>
</rss>