요즘 클로드 코드를 사용해서 개발을 하고 있지만, 어떻게 하면 AI 에이전트를 더 잘 활용할 수 있을까 늘 고민을 합니다.
그런데 개발하시는 분들은 알겠지만 프롬프트의 양과 질에 따라 결과물의 퀄리티가 꽤 차이납니다. 그럴 때마다 모델도 바꿔보고, 프롬프트도 좀 더 상세하게 작성해 보기도 했지만 여전히 2% 부족한 느낌이 들었습니다.
그러던 차에 이 책, 황민호 저자의 「하네스 엔지니어링 with 클로드 코드」를 읽게 됐습니다. 이 책은 "AI 코딩의 병목은 모델이 아니라 그 모델을 둘러싼 구조"라는 관점에서 출발해, 그 구조를 어떻게 설계하는지를 하나의 프레임으로 풀어냅니다. 관점이 달라지고 배운 내용이 꽤 좋아 제 나름대로 정리한 내용과 직접 하네스를 만들어 본 경험을 함께 공유해보려 합니다.

하네스 엔지니어링 주요 내용
1. 병목은 능력이 아니라 구조다
책의 출발점은 명확합니다. "모델을 그대로 둔 채, 둘러싼 환경만 바꾸면 결과가 어떻게 달라지는가?"
저자는 동일한 모델(Claude Sonnet)에서도 프로젝트 구성(.claude/), 편집 인터페이스(Hashline), 미들웨어와 에이전트 구조만 개선했을 때 성공률과 벤치마크 점수가 극적으로 반등한 다양한 사례들을 제시합니다.
그 사례들이 관통하는 핵심은 AI 에이전트의 성패를 가른 결정적 요인은 모델 자체의 능력이 아니라 모델이 일하는 환경과 구조였다는 것입니다.
이 관점은 소프트웨어 공학의 역사와 맞닿아 있습니다.
개발의 역사가 하위 계층으로 작업을 위임해 온 과정이었듯, AI 에이전트 역시 위임의 연속선상에 있습니다.
위임은 책임을 사라지게 하지 않는다. 책임이 놓이는 층을 바꿀 뿐이다.
다만 이전의 시스템과 다른 점이 있다면 AI 에이전트는 확률론적(비결정론적) 으로 동작한다는 것입니다. 따라서 엔지니어의 핵심 역할은 프롬프트 문장 하나를 매만지는 것에 머무르지 않고, 확률론적으로 답을 내는 모델의 바깥 가장자리를 견고한 결정론적 규칙과 검증 환경으로 감싸는 구조를 설계하는 일이 됩니다.
결국 AI 코딩의 병목은 모델의 지능 한계가 아니라, 모델이 제 역량을 발휘하도록 돕는 '하네스(구조)'의 부재에 있다라는 것입니다.
하네스란 무엇인가
그렇다면 하네스는 무엇일까요?
사전적인 harness의 의미는 '마구(馬具)'입니다. 말에 씌우는 각종 장비, 안장이나 굴레 따위를 뜻하죠. 마구는 말의 힘을 제어하고 방향을 잡고 짐을 실을 수 있게 돕습니다.
AI 에이전트를 "말(馬)" 로써 비유하자면 하네스란 AI 모델의 가중치를 바꾸지 않고도 제 힘을 온전히 발휘할 수 있도록 권한·도구·검증·상태·관측을 설계하는 것입니다.
좋은 프롬프트와 좋은 컨텍스트는 하네스 안에서도 그대로 쓰이고, 그 위에 권한 경계와 검증 루프, 상태 영속화, 관측 파이프라인이 더해지는 구조라는 것을 고려하면 하네스는 프롬프트 엔지니어링, 컨텍스트 엔지니어링 보다 좀 더 넓은 범주의 개념이라고 생각할 수 있습니다.
프롬프트 엔지니어링 ⊆ 컨텍스트 엔지니어링 ⊆ 하네스 엔지니어링
또 책은 하네스에 대한 세 가지 흔한 오해를 짚는데, 이 부분이 개념을 잡는 데 가장 도움이 됐습니다.
첫째, 하네스는 프롬프트 엔지니어링의 확장판이 아닙니다. 프롬프트는 지시이지 강제가 아니라서, 확률적 시스템에서는 그 지시가 확률적으로만 지켜집니다. 저자의 표현을 빌리면 프롬프트는 설득에 의존하고, 하네스는 기계적 강제에 의존합니다.
둘째, 하네스는 LangChain 같은 에이전트 프레임워크가 아닙니다. 프레임워크는 하네스를 짓는 데 쓰는 재료이지 하네스 그 자체가 아니라는 것이죠. 어떤 에이전트에게 어떤 권한을 주고, 언제 검증이 끼어들며, 상태를 어떻게 영속화할지는 그 뼈대 위에 개발자가 얹는 설계입니다. 프레임워크는 결과가 아니라 출발선인 셈입니다.
셋째, 하네스는 IDE나 플러그인이 아닙니다.
Cursor나 Claude Code는 에이전트 런타임 제품이고, 하네스는 그 위에 개발자가 더 얹는 설계입니다.
런타임을 바꿔도 리포지터리에 심어둔 .claude/agents/*.md 같은 포인터는 그대로 남는다는 점이 둘을 가르는 기준입니다.
그리고 이 장 전체를 관통하는 문장이 하나 있습니다.
파일이 없으면 존재하지 않는다.
에이전트는 반드시 .claude/agents/{name}.md로, 스킬은 .claude/skills/{name}/SKILL.md로 존재해야 합니다.
에이전트 도구의 프롬프트 인자에 역할을 직접 써넣는 방식은 그 세션에서만 유효합니다.
저자는 이걸 새로 채용한 직원에게 첫날 구두로만 업무를 알려주는 것에 비유합니다.
다음 날 그 직원은 대부분 잊어버리고 출근하고, 에이전트도 세션이 끝나면 아무것도 기억하지 못합니다.
결국 팀이 커질수록 살아남는 건 파일에 적힌 계약뿐이라는 이야기입니다.
누가·어떻게·언제 — 책임을 셋으로 나눈다
저자는 하네스를 세 가지 책임으로 분해합니다.
하네스는 누가(Agent), 어떻게(Skill), 언제·누구와(Orchestrator)라는 세 요소로 나뉘며, 이들은 독립적으로 설계되고 실행 시점에만 맞물린다.
Agent는 "누가"에 해당합니다.
저자는 에이전트 정의 파일을 설정 파일이 아니라 역할 계약서로 부르라고 말합니다.
설정 파일은 값을 저장하지만 계약서는 약속을 저장하기 때문입니다.
description 한 줄이 이 에이전트가 언제 호출될지를 바꾸고, tools 한 줄이 이 에이전트가 일으킬 수 있는 부작용의 범위를 바꿉니다.
에이전트는 세션 간 재사용되는 역할 자산인 셈이죠.
Skill은 "어떻게"입니다. 워크플로우, 트리거, 절차적 지식이 스킬의 영역입니다. 에이전트가 세션 간 재사용되는 역할 자산이라면, 스킬은 세션 간 재사용되는 절차 자산이라고 저자는 구분합니다.
Orchestrator는 "언제·누구와"입니다. 팀 구성, 작업 의존성, 단계 전환이 여기 속합니다. 앞의 둘과 다른 점은, 오케스트레이터는 영속 파일 하나로 고정되지 않는다는 것입니다. 규칙은 스킬 본문이나 CLAUDE.md에 적힐 수 있지만, 그 실행자는 사용자 요청이 들어왔을 때 팀을 구성하고 단계를 전환하고 팀을 해체하는 런타임의 메인 루프입니다. 저자는 오케스트레이터를 지시자가 아니라 지휘자라고 표현합니다. 팀원 각자가 자신의 악기를 연주하도록 맡기는 역할이라는 것이죠.
그렇다면 왜 이 셋을 굳이 나눠야 할까요. 저자는 커밋 메시지를 만드는 2인 팀을 예로 들어, author와 reviewer를 하나의 에이전트로 합쳤을 때 깨지는 것을 아래 네 가지로 정리합니다.
- 재사용 불가
- 커밋 형식 체크 로직을 PR 리뷰용 에이전트에서도 쓰고 싶다면 복사-붙여넣기밖에 없고, 한쪽을 고치면 다른 쪽도 고쳐야 함
- 병렬 불가
- 생성과 검증이 한 에이전트 안에 있으면 두 작업을 동시에 돌릴 수 없음
- 누락 반복
- 단일 에이전트가 처음에 놓친 가정을 검증 단계에서도 다시 놓치는 실패 모드가 그대로 남음
- 컨텍스트 폭발
- 역할 설명, 판정 기준, 형식 지식, 호출 순서, 에러 정책이 한 파일에 쌓이면서 어느새 수백 줄짜리 파일이 되어버림
한 가지 흥미로웠던 건, 저자가 Task를 독립 요소로 두지 않고 오케스트레이터 내부 도구로 재배치했다는 점입니다.
Claude Code 원문은 에이전트·스킬·작업을 세 시스템으로 보지만, 이 책은 Task가 조율의 수단이지 독립된 관심사가 아니라고 봅니다.
TaskCreate 같은 도구는 오케스트레이터가 "A에게 이걸 시키고 B는 그다음"이라고 기록하는 수단일 뿐이라는 것이죠.
저자는 이걸 원문이 틀렸다고 말하지 않고 관점의 차이라고 설명합니다.
Claude Code의 정의는 실행 관점이고, 이 책은 책임 관점으로 나눴다는 겁니다.
이 장을 읽으면서 저는 그동안 제가 만든 에이전트 파일들을 곱씹어보게 됐습니다. 한 파일에 역할과 판정 기준과 절차 지식을 다 욱여넣고 있었던 것은 아닌지 말입니다.
생성-검증, 가장 작은 팀
책이 반복해서 돌아오는 최소 단위는 생성-검증 패턴입니다.
author 에이전트가 _workspace/에 초안을 쓰면, reviewer 에이전트가 그 파일을 읽고 PASS 또는 REDO를 판정합니다.
여기서 핵심은 두 에이전트가 대화가 아니라 파일로 소통한다는 점입니다.
한쪽이 놓친 문제를 다른 쪽의 기준에서 걸러낼 가능성을 높이는, 혼자 쓴 PR을 혼자 머지하지 않는 구조입니다.
저자는 이 패턴이 작동하려면 reviewer 파일에 반드시 두 가지 규칙이 있어야 한다고 말합니다.
- 객관적인 판정 기준
- "형식을 어긴 경우"와 "사실과 다른 내용이 있는 경우"에만 REDO를 내리도록 못박아두지 않으면, 모델이 매번 다른 판단을 내림
- 재시도 상한
- 종료 조건이 없으면 생성-검증은 무한 루프에 빠짐
- 그래서 실무에서는 "2회 재생성 후에도 REDO면 경고와 함께 PASS 처리"처럼 상한을 명시하고, 아예 PASS/FIX/REDO 3단계로 중간 판정을 하나 더 두기도 함
그리고 이 대목에서 제가 자주 범했던 실수가 등장합니다. 바로 자연어로 쓴 금지사항은 안전장치가 아니라는 것.
에이전트 본문에 "절대 이 파일을 수정하지 마"라고 마크다운으로 써두는 건 프롬프트일 뿐, 에이전트의 행동을 원천적으로 막지는 못합니다.
그래서 AI 에이전트를 통한 작업의 안전을 책임지는 가드레일의 1순위는 프론트매터의 tools 필드가 됩니다.
만약 "검토 역할" 전문 에이전트에 Edit 권한이 남아 있으면, 검토자가 지적하는 대신 직접 코드를 고쳐버리면서 검증 루프가 통째로 무너집니다.
도구는 적을수록 좋다는 근거로 저자는 Vercel의 실험을 인용합니다. 에이전트에게 준 도구를 15개에서 2개로 줄였더니 정확도가 80%에서 100%로 올랐다고 합니다. 선택지가 너무 많으면 오히려 판단이 흐려지는 "토큰 마비"가 생긴다는 것이죠.
스킬, 그 중 description은 Pushy하게, 즉 공격적으로 써야 한다고 강조합니다.
이유는 스킬은 자연어 요청으로 발동하기 때문에 설명이 모호하면 아예 호출되지 않기 때문입니다.
저자는 이걸 세 단계로 정리합니다. 스킬이 실제로 하는 동작을 동사로 나열하고, "사용자가 ~을 언급하면 이 스킬을 쓸 것"처럼 트리거 상황을 직접 조건문으로 넣고, 적합하지 않은 경우까지 경계 조건으로 적는 것입니다.
본문은 반대로 Why-First로 씁니다. 명령형 규칙만 나열하면 LLM에는 역효과가 나기 쉽고, 이유를 함께 심어두면 규칙에 딱 들어맞지 않는 엣지 케이스에서도 스스로 판단할 여지가 생깁니다. 사람용 매뉴얼은 자의적 판단을 배제하려고 규칙을 쓰지만, LLM용 지시서는 반대로 생각을 이어갈 수 있도록 이유를 남긴다는 설명이 인상적이었습니다.
6단계로 팀을 구축한다
책의 3부에서 저자는 이 모든 걸 자동화하는 메타 하네스 스킬을 소개합니다. 보통의 스킬이 "어떤 작업을 어떻게 하는가"를 담는다면, 메타 스킬은 "어떤 에이전트와 스킬을 만들어야 하는가"를 담습니다. 결과물이 새 에이전트 파일과 스킬 파일인, 한 층 위의 스킬입니다.
이 메타 스킬이 여는 파이프라인은 여섯 단계입니다.
- 도메인 분석
- 답을 만드는 게 아니라 질문을 정제하는 단계
- 도메인 유형, 기존
.claude/현황, 코드베이스의 모듈 경계, 사용자 숙련도, 기존 구성과의 충돌·중복을 파악
- 팀 아키텍처 설계
- "작업들이 서로 기다려야 하는가, 동시에 할 수 있는가"에서 출발
- 실행 모드(에이전트 팀 / 서브에이전트 / 하이브리드)와 아키텍처 패턴을 정함
- 에이전트 정의
- 설계도를 실제 파일로 옮기며 "누가 일하는가"를 확정
- 스킬 생성
- 반복되는 절차를 스킬로 분리해 "어떻게 일하는가"를 확정
- 오케스트레이션
- 만든 에이전트와 스킬을 워크플로로 묶음
- 리더는 모니터이지 중계자가 아니라는 원칙이 핵심
- 검증
- 같은 테스트 프롬프트를 With/Without 두 조건에 던져 결과를 나란히 놓고 비교
6단계 검증에서 저자가 강조하는 건, 스킬이 있다는 사실만으로 품질이 올랐다고 추정하면 확증 편향에 빠지기 쉽다는 점입니다. 스킬 없이도 같은 결과가 나온다면 그 스킬은 불필요한 것이죠.
그리고 이 여섯 단계는 Phase 0(현황 감사)과 Phase 7(운영 루프)로 감싸여 순환합니다. 6단계를 완주했다고 파이프라인이 끝나는 게 아니라, 실행하며 얻은 피드백을 결과물 품질 문제면 스킬로, 역할 혼동이면 에이전트 파일로, 순서 문제면 오케스트레이터로 되돌려 반영합니다.
팀의 모양을 고를 때 쓰는 여섯 가지 아키텍처 패턴은 다음과 같이 정리됩니다.
| 패턴 | 구조 | 이 패턴을 고르는 신호 |
|---|---|---|
| 파이프라인 | 앞 단계의 출력이 다음 단계의 입력으로 이어짐 | 앞 결과 없이는 다음 에이전트가 시작할 수 없는 강한 순서 의존이 있을 때 |
| 팬아웃·팬인 | 같은 입력을 여러 에이전트가 동시에 보고 리더가 통합 | 한 팀원의 발견이 다른 팀원의 방향을 실시간으로 바꿔야 할 때 |
| 전문가 풀* | 라우터가 입력 유형을 분류해 전문가 한 명에게만 넘김 | 입력 유형이 몇 가지로 뚜렷이 나뉘고 유형별 전문성이 겹치지 않을 때 |
| 생성-검증 | 만들고, 검사하고, 실패하면 다시 만든다 | 산출물 품질 보장이 중요하고 검증 기준이 명확할 때 |
| 감독자* | 감독자가 작업 큐를 관리하고 워커가 스스로 다음 일을 가져감 | 작업 수가 실행 전에 정해지지 않고 실제로 스캔해봐야 알 때 |
| 계층적 위임* | 총괄 → 팀장 → 실무자로 영역을 쪼개 하위 팀에 위임 | 문제가 독립된 하위 영역으로 자연스럽게 나뉘고 각 영역이 충분히 복잡할 때 |
표에 \*를 붙인 세 가지는 조금 더 짚을 부분이 있습니다.
전문가 풀의 성패는 라우터의 분류 정확도에 달려 있습니다. 오분류가 나면 한 번의 실패로 끝나지 않고, 잘못된 영역에 잘못된 변경을 남겨 되돌리기 어려운 부작용을 만듭니다.
감독자에서 핵심은 워커가 작업을 "가져가는(claim)" 동작입니다. 감독자가 일일이 지시하는 게 아니라, 워커가 공유 큐에서 남은 작업을 능동적으로 선점하고 완료를 보고합니다.
계층적 위임에서 가장 중요한 제약은 깊이입니다. 2단계를 넘기면 안 됩니다. 3단계부터는 지연과 컨텍스트 손실이 기하급수적으로 커진다고 저자는 못박습니다.
저자가 반복하는 원칙은 패턴을 먼저 고르고 문제를 끼워 맞추지 말라는 것입니다.
문제의 구조를 정확히 파악하면 패턴은 자연스럽게 따라오고, 실전에서는 Phase마다 다른 패턴을 쓰고 그 경계를 _workspace/ 파일로 잇는 복합 패턴이 기본값이라고 합니다.
하네스는 진화하는 생명체다
위 여섯 단계를 완주해 팀을 만들었다고 해서 하네스가 100% 완성된 건 아닙니다. 저자는 하네스를 스냅샷으로 두지 않고 지속 가능한, 진화하는 시스템이 되어야 한다고 강조합니다. 새 세션에서 자동으로 다시 호출되어야 비로소 운영 시스템이 되고, 한 번에 하나씩 바꾸고 즉시 기록해야 진화하는 것이죠.
첫 번째 포인트, 등록
아무리 잘 만든 스킬도 CLAUDE.md에 "여기에 하네스가 있다"고 알려주는 포인터가 없으면 새 세션에서 한 번도 호출되지 않을 수 있습니다. Claude Code의 하네스 계층에서 CLAUDE.md는 제0계층이자 유일하게 항상 활성화되어 있는 층입니다. 그래서 포인터의 정식 위치도 개인 스코프가 아니라 프로젝트 스코프입니다. 팀 전체가 하네스를 공유하는 인프라로 쓰기 위해서죠. 포인터 자체는 상세 규칙을 담는 백과사전이 아니라 상세 파일로 연결하는 짧은 안내여야 하고, 하네스 위치·목표·트리거·변경 이력 정도로만 유지합니다.
두 번째 포인트, 진화
저자는 하네스가 현실과 어긋나기 시작하는 걸 알아채는 세 가지 신호를 듭니다.
반복되는 피드백, 반복되는 실패, 그리고 가장 결정적인 신호로 우회 관찰입니다.
사용자가 하네스를 부르지 않고 직접 편집기를 연다면, 그건 하네스가 제 기능을 못 하고 있다는 가장 직접적인 증거라는 겁니다.
이때 에이전트에게 하네스를 쓰라고 독려할 게 아니라, 왜 쓰지 않는지를 물어 description이나 워크플로를 고쳐야 한다고 말합니다.
그리고 변경할 때는 CLAUDE.md의 변경 이력 테이블에 날짜·내용·대상·사유를 남기는데, 저자는 이 중 마지막 "사유" 칼럼이 특히 중요하다고 강조합니다.
단순한 로그가 아니라, 나중에 그 사유를 근거로 어떤 규칙을 지워도 되는지 판단하게 해주는 장치이기 때문입니다.
이 대목을 읽으면서, 저는 그동안 설정 파일을 고칠 때 왜 고쳤는지를 거의 남기지 않았다는 걸 떠올렸습니다.
적용해보기
이 책의 핵심을 요약하면 이렇습니다.
AI 코딩의 병목은 모델 능력이 아니라 구조이고, 하네스는 모델을 둘러싼 환경을 설계하는 일이며, 그 환경은 누가·어떻게·언제라는 세 책임으로 나뉜다는 것.
가장 작은 팀은 생성-검증 쌍이고, 팀을 만드는 절차는 여섯 단계로 정형화할 수 있으며, 하네스는 한 번 만들고 끝나는 게 아니라 계속 고쳐 쓰는 생명체라는 것.
책의 이론과 원리를 직접 이해하기 위해 이 블로그에도 직접 "tech 포스트를 쓰는 팀" 하네스를 하나 만들어 봤습니다.
소스코드 참고: github 링크
구조는 이렇습니다.
tech-post-writer에이전트가 "누가"를 담당합니다.- 오케스트레이터 스킬이 만들어준 브리프(
_workspace/tech-post-brief.md)를 받아,style-guide.md와 코퍼스를 정독한 뒤 초안을_workspace/tech-post-draft.mdx에 씁니다. - 판정·검증은 하지 않습니다. 쓰는 것만 합니다.
- 오케스트레이터 스킬이 만들어준 브리프(
tech-post-style-reviewer에이전트가 이를 검증합니다.- 초안을 화법·전개·사고·서식·메타데이터·스니펫 밀도 여섯 축으로 채점하고,
_workspace/tech-post-review.md에 PASS 또는 REDO를 기록합니다. - 글을 대신 고쳐 쓰지 않고, writer가 바로 적용할 수 있는 수정 지시만 남깁니다.
- 초안을 화법·전개·사고·서식·메타데이터·스니펫 밀도 여섯 축으로 채점하고,
- 두 에이전트를 Phase 0부터 Phase 6까지 순서대로 조율하는 것이
write-tech-post오케스트레이터 스킬입니다.- 브리프를 작성하고, writer를 부르고, reviewer가 REDO를 내리면 수정 지시를 붙여 writer를 재호출하고, PASS가 나면 사용자 확인을 거쳐
apps/web/content/posts/ko/에 파일을 최종 저장합니다.
- 브리프를 작성하고, writer를 부르고, reviewer가 REDO를 내리면 수정 지시를 붙여 writer를 재호출하고, PASS가 나면 사용자 확인을 거쳐
판정의 기준이 되는 참조 파일은 세 개입니다.
화법·전개·화자 목소리를 담은 style-guide.md, frontmatter 스키마를 미러한 frontmatter-schema.md, 기존 포스트를 유형별로 정리한 corpus-map.md.
에이전트 두 개, 스킬 하나, 참조 파일 셋. .claude/ 아래 파일 여섯 개짜리 팀입니다.
마치며
역시 직접 만들어 보니 더 와닿는게 있는 것 같습니다.
처음에 write-tech-post 스킬의 description을 짧게 썼더니 Claude가 이 스킬을 찾지 못하고 범용 답변을 내놓았습니다.
동사로 시작하는 트리거 상황과 "이런 요청에는 반드시 이 스킬을 써라"는 경계 조건을 명시하자 그제야 제대로 불렸습니다. Pushy하게 써야 한다던 책의 조언이 정확했습니다.
tech-post-style-reviewer가 처음엔 초안을 직접 수정해버리는 일도 있었습니다.
프롬프트에 "고치지 마라"라고 쓰는 건 설득일 뿐이고, 실제 강제는 프론트매터의 tools 필드라는 걸 그때 몸으로 알았습니다.
Edit을 지우자 리뷰어는 비로소 검토자 역할에만 머물렀습니다.
스타일 가이드에는 "이렇게 써라" 대신 "왜 그렇게 쓰는지"를 담으려 했습니다. 책에서 읽었던 Why-First가 참조 파일을 쓸 때도 그대로 적용됐습니다.
그리고 지금 읽고 계신 이 글이, 그 하네스가 만들어낸 결과물을 조금만 다듬어서 완성한 글입니다. 브리프를 넣자 writer가 초안을 쓰고, style-reviewer가 두 번 REDO를 내렸고, 세 번째에 PASS가 나왔습니다.
모델이 더 좋아지기를 기다리는 것도 방법이지만, 그 사이에 제가 직접 설계할 수 있는 환경이 이렇게 많다는 걸 알게 된 게 이 책을 읽고 얻은 가장 큰 수확이었습니다. 비슷한 고민을 하고 계신 분들께 이 책을 읽어보길 권하며, 이 포스트가 조금이나마 도움이 되었으면 좋겠습니다.
우리 모두 Happy Coding 하는 그날까지, 파이팅입니다.