{"componentChunkName":"component---src-templates-blog-post-js","path":"/2026-04-21/","result":{"data":{"site":{"siteMetadata":{"title":"FE Factory"}},"markdownRemark":{"id":"e4213c43-9657-5389-925b-4894d6ecbce9","excerpt":"요즘 AI 에이전트랑 하루종일 같이 일한다. 회사 일도, 사이드 도 대부분 Claude Code 를 옆에 띄워두고 같이 진행한다. 코드 생성에만 쓰는건 아니다. PR…","html":"<p>요즘 AI 에이전트랑 하루종일 같이 일한다.<br>\n회사 일도, 사이드 도 대부분 Claude Code 를 옆에 띄워두고 같이 진행한다.</p>\n<p>코드 생성에만 쓰는건 아니다.<br>\nPR 리뷰, 디버깅, 리팩토링, 문서 정리까지 웬만한건 다 같이 한다.<br>\n편하긴 정말 편한데, 그냥 풀어놓으면 큰 화를 면치 못할것이다.\n타입 에러를 고치라니 <code class=\"language-text\">any</code> 로 때려버리고,(요즘엔 거의 없다..)<br>\n실패하는 테스트를 고치라니 테스트 자체를 지워버리고,<br>\n리팩토링을 하라니 멀쩡한 로직을 잘라먹고.</p>\n<p>최근에는 모델들이 다을 우수해서인지 이제 기초적인 실수는 안하긴 한다.</p>\n<p>요즘은 프롬프트만 열심히 짜는 게 아니라,<br>\n이 녀석들이 일하는 환경 자체를 설계하는 데 더 많은 시간을 더 써야 하는건<br>\n누구나 알 것이다.</p>\n<p>흔히 말하는 하네스 엔지니어링(Harness Engineering) 이다.</p>\n<h2>하네스 엔지니어링은 짧게</h2>\n<p>개념 자체는 단순하다.<br>\nAI 에이전트가 보는 컨텍스트, 쓸 수 있는 도구, 권한, 실행 흐름 같은<br>\nAI 주변의 런타임 전체를 설계하는 일이다.<br>\n프롬프트가 <code class=\"language-text\">무엇을 시킬지</code> 라면, 하네스는 <code class=\"language-text\">어디서 어떻게 일하게 할지</code> 에 가깝다.</p>\n<p>개념 설명보다 내가 실제로 뭘 해보고 어떻게 좋아졌는지가 더 쓸모 있을 것 같다.<br>\n최근 작업 중인 사이드 프로젝트에서 이렇게 세팅했더니 체감이 꽤 좋았다.</p>\n<h3><code class=\"language-text\">docs/</code> 와 <code class=\"language-text\">.agent/</code> 를 연결하기</h3>\n<p>프로젝트 루트에 문서와 에이전트 설정을 따로 두었다.</p>\n<ul>\n<li><code class=\"language-text\">docs/</code> — 기능별 명세, 가이드라인, 테스트 전략 등 사람이 읽는 문서</li>\n<li><code class=\"language-text\">docs/HARNESS.md</code> — 기능 ↔ 문서 ↔ 코드 매핑표 (진입점)</li>\n<li><code class=\"language-text\">docs/features/*.md</code> — 기능별 상세 (관련 파일, DB 스키마, 로직, 테스트)</li>\n<li><code class=\"language-text\">.agent/</code> — 에이전트 전용 지침 (rules, skills, workflows, pipeline)</li>\n<li><code class=\"language-text\">.claude/</code> — Claude Code 전용 설정 (rules, skills)</li>\n<li><code class=\"language-text\">CLAUDE.md</code> — 루트 진입점. 위 문서들로 가는 포인터만 얕게 둔다</li>\n</ul>\n<p>핵심은 <code class=\"language-text\">CLAUDE.md 를 얕게 유지</code> 하는 부분이다.<br>\n<code class=\"language-text\">기능 작업 전 반드시 docs/features/&lt;feature>.md 를 먼저 읽어라</code> 정도의 라우팅 지침만 넣고,<br>\n실제 도메인 지식은 <code class=\"language-text\">docs/features/</code> 쪽에 분산시켜 두었다.<br>\n처음부터 모든 문서를 컨텍스트에 박지 않고, 필요할 때 해당 문서만 읽어오게 하는 방식이다.</p>\n<p>이건 Anthropic 이 말하는<br>\n<a href=\"https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents\" target=\"_blank\">Just-in-time context loading</a> 과 같은 개념인데,<br>\n직접 해보니 컨텍스트 낭비가 확연히 줄기는 줄어든 것 같다.<br>\n아마도…🤔</p>\n<h3>Skill / Subagent 로 역할 분리</h3>\n<p>전역 CLAUDE.md 에 모든 규칙을 다 때려넣는 대신,<br>\n역할이 명확한 작업은 슬래시 커맨드(<code class=\"language-text\">.claude/skills/</code>) 로 분리했다.</p>\n<table>\n<thead>\n<tr>\n<th>Skill</th>\n<th>용도</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"language-text\">/git-push</code></td>\n<td>커밋 컨벤션 + 푸시 절차</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">/i18n</code></td>\n<td>다국어 (ko.json / en.json 동시 업데이트)</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">/tdd</code></td>\n<td>테스트 주도 개발 루프</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">/pipeline</code></td>\n<td>Plan → Execute → Verify 3-Agent 자동화</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">/pr-analyzer</code></td>\n<td>PR 리뷰 체크리스트</td>\n</tr>\n</tbody>\n</table>\n<p>이 외에 추가적인 많은 기능들 등등.</p>\n<p>이렇게 분리해두면 해당 작업을 할 때만 관련 지침이 컨텍스트에 로드된다.<br>\ni18n 작업 중에 DB 마이그레이션 규칙을 컨텍스트에 들고 있을 이유가 없기 때문이다</p>\n<h3>Hook 으로 자동 검증</h3>\n<p>커밋 직전과 세션 종료 시 자동으로<br>\n<code class=\"language-text\">tsc --noEmit</code>, <code class=\"language-text\">eslint</code>, <code class=\"language-text\">test</code> 를 돌리도록 hook 을 걸어두었다.<br>\nAI 가 <code class=\"language-text\">테스트 통과했습니다</code> 라고 말하는 걸 곧이곧대로 믿지 않기 위함이다.<br>\n<code class=\"language-text\">통과했다</code> 는 주장과 실제 통과 여부가 꽤 자주 어긋난다.\n요즘들어 더 심해진듯? 🤔</p>\n<p>이렇게 세팅한 뒤로, 세션 하나에 매번 반복해서 넣어야 하는 맥락이 확실히 줄었다.<br>\n내가 같은 주의사항을 말해주는 일도 줄었고,<br>\n<code class=\"language-text\">이 기능 건드릴때 어떤 파일 봐야 해?</code> 같은 예비 질문도 거의 사라졌다.</p>\n<h2>컨텍스트가 8할이다</h2>\n<p>하네스를 아무리 잘 설계해도 결국 AI 가 보는 건 컨텍스트다.<br>\n여기가 망가지면 다른건 의미가 없다.</p>\n<p>처음엔 Claude 의 윈도우가 200k, 1M 까지 나왔으니<br>\n웬만하면 꽉 채워 써도 괜찮을 거라고 생각했다.<br>\n현실은 정반대였다.</p>\n<h3>왜 길어질수록 품질이 떨어지는가</h3>\n<p>Stanford 의 <a href=\"https://arxiv.org/abs/2307.03172\" target=\"_blank\">Lost in the Middle (Liu et al., 2023)</a> 은<br>\n20개 문서(약 4,000 토큰) 만 넣어도 답변 정확도가<br>\n70~75% 에서 55~60% 로 떨어진다는 걸 실험으로 보였다.<br>\n생각보다 훅 떨어진다. 🙃<br>\n정답이 컨텍스트 맨 앞이나 맨 뒤에 있을 때 정확도가 가장 높고,<br>\n중간으로 갈수록 놓치는 <code class=\"language-text\">U 자 커브</code> 가 관찰된다.</p>\n<p>원인은 단순히 <code class=\"language-text\">토큰 수 초과</code> 가 아니다.<br>\nAttention 가중치가 전체 컨텍스트에 분산되기 때문에,<br>\n입력이 길어질수록 특정 위치의 정보에 집중하기 어려워진다.<br>\n용량의 문제가 아니라 구조적인 한계에 가깝다.<br>\n결국 얘네도 집중력 총량이 정해져 있는 셈이다.<br>\n사람이랑 똑같네…</p>\n<p>Chroma 의 2025년 <a href=\"https://www.trychroma.com/research/context-rot\" target=\"_blank\">Context Rot</a> 연구는 이걸 더 넓게 보여준다.<br>\nGPT-4.1, Claude 4, Gemini 2.5, Qwen3 등 18개 프런티어 모델을 테스트했는데,<br>\n단순 retrieval 이나 텍스트 복제 같은 기초 과제에서도<br>\n입력 토큰이 길어질수록 예외 없이 성능이 떨어졌다.<br>\n잘난 모델들 다 모아놨는데 하나같이 긴 컨텍스트 앞에서는 헤매더라는 얘기. 🤡<br>\n쿼리와 정답의 의미적 유사도가 낮을수록 하락 속도가 더 가팔라진다.</p>\n<p>요약하면, 긴 컨텍스트 윈도우가 있다는 것과<br>\n그 길이만큼 품질이 유지된다는건 다른 얘기다.<br>\n실제 제품에서는 한참 전에 품질이 깎여 나가기 시작한다.<br>\n머리는 좋은데 건망증이 심한 친구랄까? 🙃 좀 이상한데..</p>\n<h3>내 기준선</h3>\n<p>Claude Code 에서는 대략 이렇게 쓰고 있다.</p>\n<ul>\n<li>Opus 4.7 (기본 200k) — 컨텍스트 <code class=\"language-text\">20 ~ 30%</code> 사이에서 <code class=\"language-text\">/clear</code></li>\n<li>Opus 4.7 1M — <code class=\"language-text\">10%</code> 넘기기 전에 <code class=\"language-text\">/clear</code></li>\n</ul>\n<p>숫자 자체보다 중요한 건 <code class=\"language-text\">꽉 차기 전에 비운다</code> 쪽이다.<br>\n위 연구들이 시사하는 건 <code class=\"language-text\">한계치 근처에서 버티면 품질이 이미 깎이고 있다</code> 이기 때문에<br>\n여유있게 끊어주는게 결과적으로 더 낫다.</p>\n<p>클리어 하기 직전에는 중요한 결정이나 맥락을<br>\n<code class=\"language-text\">CLAUDE.md</code>, memory, handoff 파일로 내려두고,<br>\n다음 세션에서 필요한 것만 다시 읽게 한다.<br>\nAnthropic 공식 가이드도<br>\n<code class=\"language-text\">unrelated task 사이에는 공격적으로 /clear 를 써라</code> 를 권장한다.<br>\n한 세션에 무관한 주제 여러개를 이어가면 누적된 오해가 이후 판단을 흐리게 된다.</p>\n<h2>기능은 잘게 쪼개서 시키자</h2>\n<p>이건 사람한테 일 시킬 때랑 똑같은 얘기다.<br>\n한번에 10개를 다 해달라고 하면 반드시 어딘가는 부실하다.</p>\n<p>나는 보통 이런 단위로 쪼개서 세션을 구분한다.</p>\n<ol>\n<li>도메인 모델 / 타입</li>\n<li>데이터 레이어 (DB, API, Resolver)</li>\n<li>비즈니스 로직 / Service</li>\n<li>UI 컴포넌트</li>\n<li>테스트</li>\n</ol>\n<p>한 세션 한 관심사 정도로 유지하면 컨텍스트도 가볍고,<br>\n중간에 방향이 틀어졌을 때 되돌리기도 쉽다.<br>\n덤으로 내가 뇌를 비우고 🤡 AI 에 끌려다니는 것도 방지된다.</p>\n<h2>여러 AI 로 크로스 체크</h2>\n<p>Claude 하나에만 의존하지 않는 것도 같은 맥락이다.<br>\n설계, 리뷰, 리팩토링은 Claude 위주로 쓰고,<br>\n최신 문서나 레퍼런스 조사는 Gemini, 다른 관점이 필요할때는 ChatGPT 를 섞는다.</p>\n<p>이게 왜 효과가 있는지도 최근 연구들이 설명해준다.</p>\n<p><code class=\"language-text\">Self-consistency</code> 는 같은 모델의 여러 샘플을 모아 다수결을 내는 기법인데,<br>\n<a href=\"https://openreview.net/forum?id=lOoRJo8xWy\" target=\"_blank\">Complementing Self-Consistency with Cross-Model Disagreement</a> 는<br>\n이 방식의 한계를 지적한다.</p>\n<p>모델이 틀린 답에 과도한 확신을 가지는 경우,<br>\n같은 모델을 여러 번 샘플링해도 똑같이 틀린 답이 반복된다.<br>\n자기 의심이 없는 모델의 다수결은 틀린 방향을 강화할 뿐이다.<br>\n목소리 큰 애들 여럿 모아봐야 틀린건 여전히 틀리다는 얘기다. 🤡</p>\n<p>반면 서로 다른 학습 데이터와 구조를 가진 모델들에게 같은 질문을 던지면,<br>\n한쪽이 overconfident 하게 틀리는 경우에도 다른 쪽이 불일치를 보일 가능성이 높다.</p>\n<p>이 cross-model disagreement 가 <code class=\"language-text\">여기 뭔가 이상하다</code> 는 신호가 된다.<br>\n불확실성을 정량화하는 지표로도 self-consistency 단독보다 더 잘 작동한다는게 해당 연구의 요지다.</p>\n<p>실제로 써보면 서로의 약점을 신기할 정도로 잘 잡아낸다.<br>\nClaude 가 놓친 엣지 케이스를 Gemini 가 짚어주고,<br>\nGemini 가 어색하게 쓴 타입 정의를 Claude 가 다듬는 식이다.\n은근히 싸움 붙여놓는 재미도 있다. 🤔</p>\n<p>한 모델의 편향을 덜 받는 것만으로도 의사 결정 품질이 눈에 띄게 올라간다.</p>\n<p>중요한 설계 결정이나 보안 판단은 한 녀석에게만 맡기지 않는 쪽이 안전하다.</p>\n<h2>세션을 역할별로 나누기 — Plan / Execute / Verify</h2>\n<p>크로스 체크와 비슷한 아이디어를 한 모델 안에서 적용한 게<br>\n요즘 쓰고 있는 3-Agent 파이프라인이다.</p>\n<ul>\n<li>Plan Agent — 요구사항 분석, 코드베이스 조사, 계획 수립. 코드 수정 금지</li>\n<li>Execute Agent — <code class=\"language-text\">plan.md</code> 에 적힌 대로만 구현. 계획에 없는건 하지 않음</li>\n<li>Verify Agent — 테스트, 타입체크, 린트, 리뷰. 코드 수정 금지</li>\n</ul>\n<p>세 에이전트는 각각 다른 세션(채팅) 에서 돌고,<br>\n<code class=\"language-text\">handoff/</code> 폴더의 파일을 통해서만 소통한다.<br>\n내 프로젝트에서는 이런 식으로 배치돼 있다.</p>\n<deckgo-highlight-code   >\n          <code slot=\"code\">.claude/skills/pipeline/\n├── SKILL.md\n├── agents/\n│   ├── planner.md\n│   ├── executor.md\n│   └── verifier.md\n└── handoff/\n    ├── plan.md\n    ├── execution-log.md\n    └── verification.md</code>\n        </deckgo-highlight-code>\n<p>각 에이전트 지침에는 역할 제한을 명확히 박아둔다.</p>\n<deckgo-highlight-code language=\"markdown\"  >\n          <code slot=\"code\">## 역할 제한 (Plan Agent Boundaries)\n\n- 코드 수정 금지: `.ts`, `.tsx`, `.css`, `.json` 등\n- 상태를 변경하는 명령 실행 금지 (`pnpm`, `git commit` 등)\n- 허용: 파일 읽기, 디렉토리 탐색, 웹 검색, handoff 파일 작성</code>\n        </deckgo-highlight-code>\n<p>Verify 쪽도 비슷하게 <code class=\"language-text\">문제를 발견해도 코드를 고치지 말고 verification 파일에만 적어라</code> 를 강제한다.<br>\n재시도 루프가 돌 때 Plan 이 이 verification 파일을 읽고 계획을 새로 세운다.</p>\n<h3>장점</h3>\n<ul>\n<li>관심사가 분리된다. Plan 이 계획만 세우다 신나서 구현까지 해버리는 사고가 안 생긴다.</li>\n<li>검증이 독립적이다. 같은 AI 가 짜고 검증하면 자기 코드에 관대해진다.<br>\n세션이 분리되면 컨텍스트가 깨끗한 상태에서 리뷰하게 된다.<br>\n앞서 말한 cross-model disagreement 의 단일 모델 버전이라고 봐도 된다.</li>\n<li>컨텍스트가 작게 유지된다. 각 세션은 자기 역할에 필요한 handoff 파일만 로드한다.</li>\n<li>재시도 루프가 깔끔하다. Verify 가 FAIL 이면 해당 <code class=\"language-text\">verification.md</code> 를 들고 Plan 을 다시 세우면 된다.</li>\n</ul>\n<h3>단점</h3>\n<ul>\n<li>오버헤드가 크다. 세션을 여러 개 띄워야 하고, handoff 파일 관리가 필요하다.</li>\n<li>작은 작업엔 과하다. 오타 하나 고치려고 Plan / Execute / Verify 를 다 돌릴 이유는 없다.</li>\n<li>핸드오프 품질이 곧 결과 품질이다. <code class=\"language-text\">plan.md</code> 가 부실하면 Execute 가 엉뚱한 걸 만든다.<br>\n결국 <code class=\"language-text\">문서로 정확히 소통하는 능력</code> 이 이 방식의 병목이다.</li>\n<li>완전 자동은 아니다. Plan 승인, Verify 결과 판단은 결국 사람이 한다.</li>\n</ul>\n<p>설계 결정이 중요한 작업, 리팩토링, 기능 추가처럼<br>\n적당히 큰 단위에서 이 방식이 빛을 발한다.<br>\n버그 픽스나 스타일 수정 같은 단발성 작업은 한 세션에서 처리하는 편이 빠르다.</p>\n<h2>정리</h2>\n<p>정리하면 요즘 지키려는 규칙은 이렇다.</p>\n<ul>\n<li>프롬프트 만큼 하네스(문서 배치, skill 분리, hook) 에도 시간을 쓴다</li>\n<li>CLAUDE.md 는 얕게, 실제 지식은 <code class=\"language-text\">docs/features/</code> 로 밀어내 필요할때만 로드한다</li>\n<li>컨텍스트는 꽉 채우지 않는다. <code class=\"language-text\">/clear</code> 에 인색하지 말자</li>\n<li>기능은 잘게 쪼개고, 한 세션 한 관심사로 유지한다</li>\n<li>같은 질문을 여러 모델에게 던져 cross-model disagreement 를 신호로 쓴다</li>\n<li>큰 작업은 Plan / Execute / Verify 로 세션을 분리하고 handoff 파일로 묶는다</li>\n</ul>\n<p>완벽한 방법은 당연히 아니다.<br>\n계속 써보고 바꾸고 있다.<br>\n결과물이 눈에 띄게 안정적인건 확실하다.</p>\n<p>애초에 개발자라면 바이브 코딩을 하면 할수록 이거 <code class=\"language-text\">해줘</code> 만으로는<br>\n어림도 없다는걸 알게 된다.<br>\n초기에도 그랬고 현재까지도 그렇다.</p>\n<p>미래는 모르겠다.<br>\nAnthropic 의 Mythos? 어마 무시해서 일반인에게 공개를 안한다고 하는데<br>\n저런 공포 마케팅을 너무 많이 봐서 아직은 믿음이 안간다..<br>\nAnthropic IPO 가 얼마 안남기도 했고. 🤡</p>\n<p>쨌든 AI 를 잘 쓰는 일이 결국 AI 를 어떻게 가둬둘 것인가의 문제라는게<br>\n써볼수록 점점 더 명확해진다. 🥹</p>","frontmatter":{"title":"AI 랑 잘 일하기 위한 몇가지","date":"April 21, 2026","description":"80~90s 스타일로 교육하자"}}},"pageContext":{"slug":"/2026-04-21/","previous":{"fields":{"slug":"/2026-01-17/"},"frontmatter":{"title":"AI Agent, 엄마와 캥거루족 사이"}},"next":null}},"staticQueryHashes":["2841359383","3490846071"]}