AI 에이전트로 일하는 법이 바뀝니다: 클로드 코드와 하네스 엔지니어링 실무 메모¶
클로드 코드(Claude Code)에게 일을 맡기다 보면 같은 장면을 반복해서 보게 됩니다. 규칙을 분명히 적어 줬는데 어느 날 그 규칙을 어기고, "다 됐습니다"라고 보고했는데 열어 보면 절반만 되어 있습니다. 처음에는 프롬프트를 더 길고 단호하게 고쳤습니다. 효과는 오래가지 않았습니다. 이 글은 그 다음 단계, 즉 부탁을 구조로 바꾸는 일을 블로그 자동화와 개인 위키를 운영하며 실제로 해 본 기록입니다.
이 글의 기준
2026년 4월에 올린 같은 제목의 글은 유튜브 영상 한 편을 요약한 것이었습니다. 2026-10-24에 직접 운영 중인 프로젝트에서 겪은 사례와 실측값으로 전면 다시 썼습니다. 사례의 날짜와 수치는 각 프로젝트의 작업 기록에서 옮겼습니다.
1. 하네스 엔지니어링이란: 표지판 대신 중앙 분리대¶
하네스(harness)는 말에 채우는 마구입니다. 말에게 "저쪽으로 뛰어"라고 외치는 것이 프롬프트라면, 마구를 채워 달리는 방향 자체를 제한하는 것이 하네스입니다. 도로로 비유하면 "유턴 금지" 표지판은 무시할 수 있지만 중앙 분리대는 넘을 수 없습니다.
프롬프트만으로 부족한 이유는 세 가지로 정리됩니다.
| 한계 | 실제로 보이는 증상 |
|---|---|
| 희석 | 대화가 길어지면 초반에 준 규칙이 뒤로 밀려 지켜지지 않습니다 |
| 자기 보고 | 에이전트의 "완료했습니다"는 검증이 아니라 주장입니다 |
| 확인 불가 | 프롬프트를 지켰는지는 밖에서 기계적으로 확인할 수 없습니다 |
하네스는 이 세 가지를 각각 파일로 남는 규칙(CLAUDE.md), 실행되는 검사(스크립트·훅·테스트), 사람의 최종 확인 지점으로 바꿉니다. 아래 네 가지 사례가 모두 이 패턴입니다.
2. 사례 1 — 프롬프트 예시 하나가 분류를 망쳤다¶
블로그 글을 자동으로 만드는 파이프라인에는 글의 카테고리를 고르는 단계가 있습니다. 2026-08-07, 게임 공략 글이 "경제·투자"로 분류되어 발행되었습니다. 원인을 따라가 보니 모델의 실수만은 아니었습니다. 분류 프롬프트의 예시에 지금은 없는 옛 카테고리 이름이 적혀 있었고, 모델은 실제 카테고리 목록을 모른 채 그럴듯한 축을 고른 것이었습니다.
고친 방법은 "조심해서 분류해 줘"가 아니었습니다.
- 프롬프트에 실제로 존재하는 카테고리만 나열하고, 그 밖의 값은 쓰지 못하게 했습니다.
- 발행 전 검사 스크립트(
precheck)가 허용 목록에 없는 카테고리를 만나면 배포를 멈춥니다. 카테고리 목록은 한 파일에만 두고, 검사와 관리 도구가 같은 목록을 읽습니다.
교훈: 에이전트가 틀렸을 때 먼저 볼 곳은 모델이 아니라 모델에게 준 환경입니다.
3. 사례 2 — 문장 속에 끼어든 이미지¶
2026-08-10에는 한 글에 같은 이미지가 두 번 들어갔습니다. 생성 단계에서 모델이 이미지 자리 표시자(PLACEHOLDER_1)를 단독 줄에 두지 않고 "PLACEHOLDER_1의 장면은…"처럼 문장 안에서 명사로 언급했고, 치환기는 토큰이 보이는 곳마다 이미지를 끼워 넣었습니다.
중간 산출물을 거슬러 올라가 범인이 생성 단계임을 확인한 뒤 방어선을 두 겹으로 정했습니다.
| 방어선 | 하는 일 | 혼자서는 부족한 이유 |
|---|---|---|
| 변환기 가드 | 단독 줄에 있는 토큰만 이미지로 바꾸고 남은 토큰은 지움 | 중복 이미지는 막지만 깨진 문장은 남음 |
| 프롬프트 규칙 | "자리 표시자는 단독 줄로만, 문장 안 언급 금지" | 지켜질 확률을 높일 뿐 보장하지 못함 |
교훈: 구조(가드)와 부탁(프롬프트)은 대체 관계가 아니라 겹쳐 쓰는 관계입니다. 가드는 사고를 막고, 프롬프트는 사고의 빈도를 줄입니다.
4. 사례 3 — "4건 전부 성공"이라는 보고¶
게임 화면에서 메뉴와 자막을 지우는 이미지 편집을 두 AI 도구에 맡겨 비교한 적이 있습니다(2026-07-25). 한 도구는 "4건 모두 성공"이라고 보고했습니다. 결과 이미지를 직접 열어 보니 한 장은 지운 자리에 있지도 않은 도로 이중선이 그려져 있었고, 작업 폴더에는 임시 파일 40여 개가 남아 있었습니다.
프로젝트 규칙(CLAUDE.md)에 적어 둔 다음 문장은 바로 이런 일을 막기 위한 것입니다.
Worker의 "완료" 보고를 그대로 믿지 않는다.
승인 전에 git diff로 변경을 직접 읽고, 완료 기준 명령(npm run build 등)을 직접 실행한다.
교훈: 완료 판정은 에이전트의 말이 아니라 결과물과 검사 명령이 내립니다.
5. 사례 4 — 끝을 정하는 것은 종료 코드¶
하네스의 다음 단계로 이야기되는 것이 루프입니다. 테스트가 실패하면 실패 기록을 다시 에이전트에게 주고, 통과할 때까지 반복합니다. 개인 위키에 실습을 만들며 직접 돌려 본 결과는 이렇습니다(2026-10-04 실측).
| 항목 | 값 |
|---|---|
| 과제 | 대소문자·공백·기호를 무시하는 회문 판별 함수 고치기 |
| 결과 | 2번째 사이클에서 테스트 통과 |
| 비용 | 호출 1회 약 $0.05(API 종량제 환산) |
| 걸린 함정 | --allowedTools에 Write가 빠지면 Claude가 파일을 다시 쓰지 못해 같은 실패를 반복 |
뼈대만 남기면 다음과 같습니다.
MAX=5
for i in $(seq 1 $MAX); do
node test.js > test.log 2>&1 && { echo "PASS"; break; } # 판정은 테스트가 한다
[ "$i" -eq "$MAX" ] && { echo "반복 상한 — 사람이 확인"; break; }
cat test.log | claude -p "solution.js가 아래 테스트에서 실패한다. solution.js만 고쳐라." \
--allowedTools "Read,Edit,Write"
done
여기서 중요한 것은 Claude가 "고쳤습니다"라고 말한 시점이 아니라 테스트 명령이 종료 코드 0을 돌려준 시점에 루프가 끝났다는 점입니다. 끝내 못 고치면 상한에서 멈추고 사람에게 넘깁니다.
교훈: 루프의 세 요소는 객관적인 판정(종료 코드), 실패 기록의 되먹임, 그리고 상한입니다. 셋 중 하나라도 빠지면 루프는 비용만 쓰는 메아리가 됩니다.
💡 원스의 인사이트: 같은 실수가 두 번 나오면 파일이 바뀌어야 한다
네 사례를 묶는 규칙은 하나입니다. 같은 실수가 두 번 나오면 프롬프트가 아니라 파일이 바뀌어야 합니다. 카테고리 목록 파일, 변환기 가드, CLAUDE.md의 검증 규칙, 테스트 스크립트가 모두 그렇게 생겼습니다.
시작은 작게 해도 됩니다. 지금 에이전트에게 가장 자주 다시 말하는 문장 하나를 골라 보세요. 기계가 확인할 수 있는 내용이면 스크립트나 훅으로, 확인할 수 없으면 CLAUDE.md의 규칙으로 옮깁니다. 그래도 사람이 봐야 하는 것이 남으면, 그것이 승인 지점입니다.
반대로 버리는 일도 필요합니다. 모델이 좋아지면 예전에 필요했던 규칙이 오히려 방해가 됩니다. 몇 주 동안 한 번도 걸리지 않은 규칙은 지울지 검토하되, .env 커밋 차단처럼 한 번의 사고가 치명적인 안전장치는 남겨 둡니다.
체크리스트 — 내 에이전트 작업에 하네스가 있는가¶
- [ ] 반복해서 다시 말하는 규칙이 CLAUDE.md 같은 파일에 적혀 있다
- [ ] 결과물을 판정하는 명령(테스트·빌드·린트)이 있고, 에이전트의 보고 대신 그 명령으로 완료를 판단한다
- [ ] 배포·삭제처럼 되돌리기 어려운 일 앞에 사람의 승인 지점이 있다
- [ ] 자동 반복에는 횟수나 비용의 상한이 있다
- [ ] 사고가 나면 "모델 탓"으로 끝내지 않고 환경의 어느 파일을 고칠지 정한다
참고 자료 및 출처¶
- 위키 — 개념 정리: 하네스 엔지니어링
- 위키 — 규칙을 시스템으로 강제하는 훅: Claude Code Hooks
- 위키 — 사례 4의 실습 전체: 루프 엔지니어링 실습
- 처음 글을 쓰게 된 계기: 장피엠, 나의 AI 에이전트 전환기 (w. 클로드 코드, 오픈클로)