Claude Code 프롬프트 재현성 — 암묵지를 제거하는 자동 튜닝 워크플로우
작성자와 평가자를 분리하고 서브에이전트로 반복 실행해 프롬프트 품질을 객관적으로 끌어올리는 실전 방법론을 정리한다.
프롬프트를 작성하고 나서 "이 정도면 충분하겠지" 싶었는데, 다른 AI 세션에서 돌려보면 전혀 다른 결과가 나오는 경험. 이게 단순한 LLM의 확률적 특성 문제가 아니다. 핵심 원인은 암묵지다.
프롬프트 작성자는 자신의 배경 지식을 무의식적으로 채워 읽기 때문에, 작성 직후의 자체 평가는 신뢰할 수 없다. 이 문제를 구조적으로 해결하는 방법이 있다.
왜 자체 평가는 믿을 수 없나
비유하면 자기 코드를 자기가 바로 리뷰하는 것과 같다. 내가 짠 코드는 내가 의도한 대로 읽힌다. 놓친 엣지 케이스가 눈에 안 들어온다. 프롬프트도 마찬가지다.
작성자는 "이 정도 설명이면 AI가 알아서 하겠지"라고 생각하지만, 실제로 다른 세션에서 돌려보면 전혀 다른 방향으로 실행된다. 이때 나타나는 증상이 있다.
- AI가 중간에 불필요한 확인 질문을 많이 던진다
- 비슷한 도구를 여러 번 반복 호출한다
- 요건 체크리스트의 일부 항목이 달성되지 않는다
이 모두가 프롬프트의 명세 부족을 나타내는 신호다.
[💡 잠깐! 이 용어는?] 암묵지(Tacit Knowledge): 언어로 표현하기 어려운 경험적 지식. 작성자가 당연하게 여기는 맥락이나 판단 기준이 문서화되지 않은 채 남아있는 상태.
핵심 해결책: 평가자와 작성자를 분리한다
이 방법론의 핵심은 단순하다. 내가 작성한 프롬프트를 내가 평가하지 않는다.
Claude Code의 서브에이전트(Task tool)를 사용해서 별도 컨텍스트로 프롬프트를 실행하고, 그 결과를 양면으로 평가한다.
평가 구조:
1. 시나리오 고정 (일반형 1개 + 엣지 케이스 1~2개)
2. 새로운 AI 세션에 dispatch
3. 자기신고 수집: 불명확점, 재량 보완한 부분, 재시도 횟수
4. 객관 측정: 사용한 도구 수, 소요 시간, 요건 체크리스트 달성률
여기서 "같은 AI 재사용 금지"가 중요한 규칙이다. 같은 세션에서 반복하면 컨텍스트가 누적되어 학습 효과가 생기고, 실제로는 프롬프트가 그대로여도 성능이 올라간 것처럼 보인다.
실전 평가 템플릿
## 평가 시나리오
### 시나리오 A (일반형)
[일반적인 사용 케이스 정의]
### 시나리오 B (엣지 케이스)
[경계 조건이나 예외 상황 정의]
## 요건 체크리스트
- [critical] 산출물 형식이 지정된 스펙과 일치하는가
- [critical] 핵심 기능이 모두 동작하는가
- 부가 조건 1
- 부가 조건 2
## 보고 형식 (실행 AI가 작성)
산출물: [결과 요약]
요건 달성: ○/×/부분적
불명확했던 점: [목록]
재량으로 보완한 부분: [목록]
재시도 횟수: N회
사용한 도구: N개[critical] 태그가 붙은 항목은 반드시 달성해야 하는 필수 요건이다. 이 항목에서 ×가 나오면 프롬프트에 해당 내용이 명시적으로 빠져있다는 뜻이다.
반복 프로세스
| 회차 | 작업 | 판단 기준 |
|---|---|---|
| 1회 | 시나리오 실행 후 보고 수집 | 불명확점 목록 분석 |
| 2~N회 | 불명확점 1건씩 최소 수정 후 재실행 | 연속 2회 정체 시 종료 |
| 검증 | hold-out 시나리오로 과적합 확인 | 미사용 케이스에서도 성능 유지 |
한 번에 여러 부분을 고치면 무엇이 개선을 만들었는지 알 수 없다. 불명확점 1건만 수정하고 새 AI 세션에서 재실행하는 방식으로 진행해야 인과관계가 명확해진다.
수정 시 주의: 반복 중에 시나리오 자체를 바꾸면 기준이 달라져서 개선처럼 위장되는 함정이 생긴다. 시나리오는 처음에 고정하고 절대 건드리지 않는다.
tool_uses 수로 설계 결함 찾기
평가에서 수집한 tool_uses 수는 중요한 진단 지표다.
특정 시나리오에서 도구 사용 횟수가 15+로 튀어오른다면, AI가 참조 파일을 반복해서 읽고 있다는 신호다. 이 경우 프롬프트 본문에 최소 예시를 인라인으로 추가하면 도구 호출 횟수가 줄면서 성능이 개선된다.
Claude Code의 Task tool <usage> 태그에서 이 메트릭을 자동 추출할 수 있다.
interface TaskUsage {
input_tokens: number
output_tokens: number
tool_uses: number
retries: number
}
function parseUsageFromOutput(output: string): TaskUsage {
const usageMatch = output.match(/<usage>([\s\S]*?)<\/usage>/)
if (!usageMatch) {
return { input_tokens: 0, output_tokens: 0, tool_uses: 0, retries: 0 }
}
const usageText = usageMatch[1]
return {
input_tokens: parseInt(usageText.match(/input_tokens:\s*(\d+)/)?.[1] ?? '0'),
output_tokens: parseInt(usageText.match(/output_tokens:\s*(\d+)/)?.[1] ?? '0'),
tool_uses: parseInt(usageText.match(/tool_uses:\s*(\d+)/)?.[1] ?? '0'),
retries: parseInt(usageText.match(/retries:\s*(\d+)/)?.[1] ?? '0'),
}
}실제 개선 수치
8개 스킬에 이 방식을 적용한 결과:
| 지표 | 적용 전 | 적용 후 |
|---|---|---|
| 초기 달성률 | 평균 50점 | — |
| 최종 달성률 | — | 80~90점 |
| 반복 수 | — | 2~4회로 수렴 |
| 전체 시나리오 달성 | 부분 달성 | 연속 2회 100% |
conventional-changelog 스킬의 경우:
- 1회차: 시나리오 A 90%, 시나리오 B 70%
- 2회차: A 100%, B 85%
- 3~4회차: 모든 시나리오 100%
구조적으로 TDD와 같다
이 방법론은 TDD(테스트 주도 개발)와 동일한 구조다.
- TDD: 테스트 → 구현 → 리팩토링
- 프롬프트 튜닝: 시나리오/요건 고정 → 실행 → 명세 보완
차이는 테스트 코드 대신 평가 시나리오를 먼저 작성한다는 것뿐이다. 그리고 "구현"에 해당하는 프롬프트를 실제 LLM이 실행해서 피드백을 준다.
마무리
- 평가자와 작성자를 분리하는 것이 핵심이다
- 같은 세션 재사용 금지 — 새 AI 세션에서 실행해야 컨텍스트 누적 효과가 없다
- 불명확점은 1건씩 수정, 2회 연속 정체 시 종료
tool_uses수가 과다하면 참조 파일이 누락됐다는 신호- 시나리오는 처음에 고정하고 절대 수정하지 않는다
프롬프트를 "잘 쓰는 것"과 "재현 가능하게 쓰는 것"은 다른 문제다. 이 방법론은 후자를 객관적으로 담보하는 구조를 만들어준다.
참고:
같은 카테고리 · Claude Code
비슷한 주제의 최신 글
태그가 겹치는 글
공통 태그가 많을수록 위에 보인다