하네스 란?
AI를 똑똑하게 사용하는 방법을 알아보았습니다.
AI한테 코드 맡겼더니 테스트를 삭제해버렸다
"AI가 다 해주니까 코드 안 배워도 되겠다" — 이게 가장 위험한 생각이다.
프로젝트 개발시 # AI한테 코드 맡겼더니 테스트를 삭제해버렸다
"AI가 다 해주니까 코드 안 배워도 되겠다" — 이게 가장 위험한 생각이다.
회사에서 Claude Code 도입 후 처음엔 신세계였다.
버튼 하나로 MVP가 나오고, 기능 구현 속도가 3배는 빨라진 것 같았다. 그런데 한 달쯤 지나자 이상한 일이 생기기 시작했다.
- 어제 잘 됐는데 오늘은 결과가 다르다
- 세션이 길어질수록 AI가 점점 이상한 코드를 짠다
- 테스트가 실패하면... 테스트를 그냥 지워버렸다
- 분명히 "이 함수 고쳐줘"라고 했는데 다른 파일이 바뀌어 있다
문제는 AI 자체가 아니었다. AI한테 일을 맡기는 방식이 잘못됐던 거다.
이 글은 그 경험을 통해 배운 것들을 정리한 글이다.
AI 코딩 도구, 지금 어디쯤 왔나
잠깐 현실부터 보자.
- YC(미국 유명 스타트업 육성기관) 2025년 스타트업 중 25%는 코드의 95%를 AI로 생성한다
- Meta 엔지니어 중에는 3개월 동안 직접 타이핑을 안 한 사람이 있다
- AI가 짠 코드가 검토 없이 그대로 배포되는 것도 흔한 일이 됐다
이미 AI가 코드를 짜는 시대다. 근데 그렇다고 개발자가 필요 없어지는 게 아니다.
달라지는 건 딱 하나다. 예전엔 "코드를 잘 짜는 능력"이 중요했다면, 지금은 "AI가 잘 일할 수 있는 환경을 만드는 능력" 이 중요해졌다.
오케스트라로 치면, 직접 바이올린을 켜는 게 아니라 지휘자 역할이 된 거다.
왜 AI가 제멋대로 행동할까
AI를 쓰다 보면 이런 경험을 하게 된다.
"분명히 테스트 통과시켜달라고 했는데, 테스트를 삭제해버렸네?"
AI 입장에서 생각해보면 이해가 된다. "테스트를 통과하라"고 했으니, 가장 빠른 방법은 테스트를 없애는 거다. 틀린 말이 아니잖아.
AI는 내가 원하는 의도가 아니라, 내가 한 말을 그대로 수행한다.
또 다른 문제가 있다. 대화가 길어질수록 AI 성능이 떨어진다.
연구 결과를 보면, 대화창에 5만 토큰(한국어 약 4만 자) 이 쌓이면 AI가 슬슬 이상해지기 시작한다. 아무 관계 없는 내용이 한 줄만 섞여도 정확도가 뚝 떨어진다.
이걸 "Context Rot(컨텍스트 부패)" 라고 부른다. 대화창이 길어질수록 조용히 썩어가는 거다.
그리고 수학적으로도 문제가 있다.
AI가 각 단계를 95% 확률로 성공한다고 가정해보자. 딱 20단계짜리 작업을 시키면?
0.95 × 0.95 × ... (20번) = 0.358 → 36%
10번 중 6번은 실패한다. "95% 성공률"인데도.
그래서 "AI한테 그냥 다 맡기면 되겠지"는 환상이다. 뭔가 울타리 가 필요하다.
하네스(Harness)가 뭔가
갑자기 낯선 단어가 나왔다. 쉽게 설명하면 이렇다.
말(馬)에 비유해보자. 말은 힘이 세고 빠르다. 근데 그냥 두면 어디로 튈지 모른다. 그래서 고삐, 안장, 재갈 같은 장비를 씌운다. 이게 하네스(마구, 馬具)다.
AI도 똑같다. 실력은 있는데 방치하면 제멋대로다. 그래서 AI가 볼 정보, 할 수 있는 행동, 멈춰야 할 때를 설계해줘야 한다. 이 설계가 하네스 엔지니어링이다.
에이전트 = AI 모델 + 하네스
"모델이 아닌 것은 전부 하네스입니다." — LangChain
Claude Code에서 하네스를 만드는 도구는 4가지다:
| 도구 | 한 줄 설명 |
|---|---|
| CLAUDE.md | 프로젝트 규칙서. 모든 대화 시작 전에 자동으로 읽힘 |
| Skills | 반복 작업을 명령어로 저장. /commit 하면 팀 컨벤션대로 커밋 |
| Hooks | AI가 특정 행동을 할 때 자동 실행되는 스크립트 |
| Plugins | 위 3가지를 묶어서 팀 전체에 배포하는 패키지 |
하나씩 뜯어보자.
CLAUDE.md — AI에게 주는 "우리 팀 규칙서"
CLAUDE.md는 쉽게 말해 "우리 팀은 이렇게 일해" 를 적어두는 파일이다.
프로젝트 폴더에 이 파일을 놓으면, Claude Code가 대화를 시작할 때마다 자동으로 읽는다. 매번 "우리는 이런 컨벤션 써" 하고 설명 안 해도 된다.
이렇게 쓰면 안 된다:
# ❌ 이런 건 의미없음
- 깔끔한 코드 작성
- 적절한 에러 핸들링
- 좋은 패턴 사용
왜? 저걸 보고 AI가 뭘 해야 할지 알 수가 없다. "깔끔한"이 뭔데?
이렇게 써야 한다:
# ✅ 구체적이고 확인 가능한 규칙
## 코드 규칙
- 함수 길이: 50줄 이하
- try-catch는 외부 API 호출할 때만 쓸 것
- 에러 메시지엔 에러 코드 반드시 포함
## 커밋 규칙
- 형식: #{이슈번호} {타입} : {설명}
- 예시: #123 feat : 로그인 페이지 추가
- 구조 변경이랑 기능 변경은 커밋 분리
## 절대 금지
- 테스트 파일 수정 금지
- assert 조건 약화 금지 (값 검증을 타입 검증으로 바꾸는 것)
크기는 짧을수록 좋다. 공식 문서에서도 200줄 이하를 권장한다.
판단 기준이 있다. "한 줄씩 지워봐라. 지워도 Claude가 똑같이 동작하면 — 그 줄은 잡음이다."
Claude Code 창시자인 Boris Cherny는 이런 방식으로 CLAUDE.md를 관리한다:
- Claude가 실수할 때마다 한 줄씩 추가
- PR에서
@claude태그 달면 GitHub Action이 자동으로 커밋
"버그를 한 번 고치는 게 아니라, CLAUDE.md에 한 줄 추가하면서 고치는 것이다."
Skills — 반복 작업을 명령어 하나로
매번 "우리 팀 커밋 컨벤션은 이렇고, 이슈 번호 붙이고..." 설명하기 귀찮지 않나?
Skills는 이 반복 작업을 패키지로 저장해두는 기능이다.
<!-- .claude/skills/commit.md -->
---
name: commit
description: Git 커밋할 때 팀 컨벤션 메시지 자동 생성
---
# 이렇게 해줘
1. 현재 브랜치 이름에서 이슈 번호 뽑기
- 예: feature/PIMS-123-login → 123
2. 변경된 파일 보고 타입 정하기
- 새 기능 추가 → feat
- 버그 수정 → fix
- 코드 구조 변경(기능 변화 없음) → refactor
3. 이 형식으로 커밋 메시지 만들기
- #123 feat : 로그인 페이지 추가
이제 /commit 이라고만 치면 된다. 또는 그냥 "커밋해줘"라고 해도 Claude가 알아서 이 파일을 불러온다.
똑똑한 점: Skills는 호출할 때만 불러와서 읽는다. 100개를 등록해도 안 쓰는 건 토큰을 전혀 안 먹는다. CLAUDE.md처럼 항상 올라가 있는 게 아니라 "필요할 때만 꺼내 쓰는 서랍" 이다.
실제로 이 발표 자료를 만든 팀에서 운영 중인 Skills 목록:
| 명령어 | 기능 |
|---|---|
/code-review | PR 자동 리뷰 (보안·성능·테스트 체크) |
/commit | 이슈 번호 포함 커밋 메시지 자동 생성 |
/kickoff | 새 프로젝트 초기 세팅 |
/figma-to-react | Figma 디자인 → React 컴포넌트 변환 |
/wrap-up | 하루 작업 정리·보고 |
Hooks — AI가 실수하기 전에 막는 안전망
Hooks는 특정 이벤트가 발생했을 때 자동으로 실행되는 스크립트다.
AI가 파일을 수정하려 할 때, 커밋하려 할 때 — 그 전에 먼저 검사를 돌린다.
# .claude/hooks/pre-commit.sh
# 커밋 전에 자동으로 실행됨
# ESLint 검사 → 오류 있으면 커밋 차단
npx eslint src/ --max-warnings 0
if [ $? -ne 0 ]; then
echo "코드 스타일 오류 있음. 커밋 차단."
exit 1 # 여기서 막힘
fi
# 테스트 실행 → 실패하면 커밋 차단
npm test --silent
if [ $? -ne 0 ]; then
echo "테스트 실패. 커밋 차단."
exit 1
fi
Skills vs Hooks, 뭐가 다른가?
- Skills → 내가 부를 때 실행 (선택)
- Hooks → 항상 자동으로 실행 (강제)
테스트를 삭제하거나 .env 파일을 건드리는 걸 원천 차단하고 싶다면 Hooks를 쓰면 된다.
AI 시대의 개발 방법론
도구를 알았으니, 이제 어떻게 일할지 방법론 이야기다.
TDD — "테스트 먼저 써, 코드는 AI가 짜"
TDD(Test-Driven Development)는 원래 테스트를 먼저 쓰고, 그 테스트를 통과하는 코드를 나중에 쓰는 방식이다.
AI 시대에 이게 왜 중요하냐면, 테스트가 "AI에게 내가 원하는 게 뭔지"를 명확히 알려주는 유일한 방법이기 때문이다.
# 1단계: 내가 먼저 테스트를 쓴다 (실패하는 테스트)
def test_운동_상세_보기():
# "사용자가 과거 운동을 클릭하면 상세 정보가 나와야 한다"
사용자 = 테스트_사용자_만들기()
운동 = 운동_기록_만들기(사용자, 날짜="2024-01-01")
응답 = 클라이언트.get(f"/운동/{운동.id}")
# 이 조건들을 통과해야 성공
assert 응답.상태코드 == 200
assert 응답.json()["날짜"] == "2024-01-01"
assert 응답.json()["칼로리"] is not None # None이면 안 됨
# 2단계: Claude Code한테 맡긴다
# "이 테스트를 통과하는 코드 짜줘"
# 3단계: 내가 코드 리뷰하고, AI가 리팩토링
근데 AI는 꼼수를 부린다. 테스트를 통과하는 가장 쉬운 방법 = 테스트 자체를 없애거나 조건을 약화시키는 것.
그래서 CLAUDE.md에 이걸 반드시 넣어야 한다:
## 테스트 관련 절대 금지 사항
- 테스트 파일 삭제 금지
- assert 조건 약화 금지 (예: 값 비교를 타입 비교로 바꾸는 것)
- 테스트 skip 처리 금지
- 테스트 실패 확인 전에 구현 코드 작성 금지
SDD — "뭘 만들지 먼저 문서로, 어떻게 만들지는 AI가"
SDD(Spec-Driven Development)는 좀 더 큰 그림에서 쓰는 방법이다.
새 기능을 만들 때 코드부터 짜는 게 아니라, "이 기능이 뭘 해야 하는지"를 문서로 먼저 정의한다.
# 실시간 채팅 기능 스펙
## 이 기능이 하는 일
- 사용자끼리 실시간으로 메시지를 주고받을 수 있다
- 대화 기록 최근 100개를 볼 수 있다
- 상대방이 온라인인지 오프라인인지 표시된다
## 완료 기준 (이게 되면 성공)
- 메시지를 보내면 0.2초 안에 상대방 화면에 뜬다
- 인터넷이 끊겼다 연결되면 자동으로 재접속된다 (최대 3번)
## 아직 모르는 것 (결정 필요)
- [NEEDS CLARIFICATION] 오프라인일 때 온 메시지를 저장해야 하나?
문서가 준비되면 그때 AI한테 맡긴다. [NEEDS CLARIFICATION] 이 남아있으면 AI가 멈추고 물어본다.
TDD vs SDD 언제 쓰나?
- 기존 코드 고칠 때, 버그 잡을 때 → TDD
- 새 기능 만들 때, 대규모 설계할 때 → SDD
- 가장 강력한 조합 → SDD로 설계 + TDD로 검증
"계획하고 만들기" — AI가 가장 많이 실패하는 순간
AI한테 바로 "이거 만들어줘" 하면 안 된다. 왜냐면 AI는 계획 없이 일단 코드부터 짜기 시작한다.
초반에 방향이 틀리면, 그걸 기반으로 계속 쌓아가다가 나중에 전부 뜯어고쳐야 하는 상황이 온다.
해결책은 간단하다. 계획 단계와 실행 단계를 분리한다.
1단계 PLAN → "코드는 절대 건드리지 마. 어떻게 할지 계획만 세워"
파일 읽기·검색·질문만 가능
결과: 계획 문서 (내가 검토하고 수정 가능)
2단계 CRITIC → "이 계획에 문제는 없나?"
다른 에이전트가 계획의 허점을 찾음
3단계 BUILD → "이 계획대로 만들어줘" (내가 승인한 후)
이때야 비로소 코드 작성 시작
Claude Code에서는 Shift+Tab Shift+Tab 을 누르면 계획 모드로 바뀐다.
"계획과 실행을 분리하는 것이 AI 코딩에서 내가 하는 가장 중요한 행위다." — Armin Ronacher
에이전트 하나한테 너무 많이 시키지 마라
한 명한테 "기획도 하고, 개발도 하고, 테스트도 하고, 배포도 해"라고 하면 어떻게 될까?
AI도 마찬가지다.
하나의 에이전트가 오래 일할수록 세 가지 문제가 생긴다:
- 대화창이 쓰레기로 가득 찬다 — 파일, 테스트, 로그가 쌓이면서 5만 토큰쯤 되면 성능 저하
- 자기 코드를 자기가 리뷰한다 — 자기가 쓴 버그를 자기가 못 잡는다
- 20단계면 성공률 36% — 앞서 본 수학
해결책은 여러 에이전트로 쪼개기다.
메인 에이전트 (총괄)
↓ "이 파일들 읽고 분석해줘"
탐색 에이전트 (읽기 전용)
- 파일 50개를 뒤져도 메인은 깨끗함
- 결과만 1~2줄 요약해서 올려줌
↑ 요약 결과 반환
핵심은 메인 에이전트의 대화창을 오염시키지 않는 것이다.
멀티 에이전트를 실무에서 돌릴 때는 이런 세팅을 쓴다:
창 1: 메인 작업 (지금 만드는 기능)
창 2: 조사·탐색 (코드베이스 검색)
창 3: 감시 (테스트·빌드 결과 확인)
창 4: 이슈·PR 관리
각 창은 독립된 Git 브랜치에서 작업하니까 서로 충돌도 없다.
결국 핵심은 하나
이 발표 자료 89장 전부를 Claude Code로 만들었다. HTML 한 줄 직접 안 썼다.
어떻게 했냐면:
1. 섹션별로 내용을 마크다운으로 먼저 정리했다 (내가)
2. CLAUDE.md에 디자인 규칙을 명세했다 (내가)
3. Claude Code가 HTML 슬라이드를 생성했다 (AI)
4. 피드백을 8회 반복했다 (내가 검토, AI가 수정)
AI를 잘 쓰는 방법은 결국 이거다:
원하는 것을 글로 먼저 → 규칙을 문서로 고정 → 결과를 사람이 검증
새로 배울 게 없다. 이미 알고 있는 원칙 — 명확한 요구사항, 코드 리뷰, 테스트 — 을 AI 시대에 더 의식적으로 하는 것뿐이다.
이 글은 AI 1팀 김영동 대리의 전사 세미나 발표(2026.04.07)를 기반으로 작성됐습니다.공유콘텐츠pdf