Claude Code가 기능을 만들게 하면, '완료했습니다'라고 말했지만 실제로 작동시켜 보니 버튼이 반응하지 않는 경우가 있습니다.
이 글은 만드는 담당자(generator)와 채점하는 담당자(evaluator)를 별도의 서브 에이전트로 분리한 기록입니다. 채점 담당자에게는 Playwright로 브라우저를 조작하게 하여 합격/불합격을 결정하도록 했습니다. 약 2주 동안 14 스프린트를 진행했고, 6 스프린트에서 불합격 판정을 받았습니다. 만드는 담당자에게 되돌려 보낸(差し戻した) 횟수는 총 9회입니다.
자신의 결과물을 스스로 채점하면 관대해진다
Anthropic은 2026년 3월 24일에 'Harness design for long-running application development'라는 글을 공개했습니다. 그 안에 다음과 같은 문장이 있습니다.
agents reliably skew positive when grading their own work.
이는 에이전트가 자신의 결과물을 채점할 때 습관적으로 관대한 쪽으로 기울어진다는 의미입니다. 같은 글에서는 작업하는 에이전트와 판정하는 에이전트를 분리하는 것이 효과적이라고 설명하고 있습니다. 이 글의 구성은 이러한 생각에 기초하여 제가 직접 짜본 것입니다.
구성
역할은 3가지이며, 메인 Claude가 지휘 역할을 하며 순서대로 호출합니다.
- 계획 담당자(planner): 짧은 요청을 사양서(spec.md)로 확장합니다. 무엇을 만들지만 적고, 구현 방법은 정하지 않습니다.
- 만드는 담당자(generator): 한 번에 1 스프린트만 구현하고, 자체 평가(sprint-N-self-eval.md)를 작성합니다.
- 채점 담당자(evaluator): 앱을 실제로 조작하여 채점하고, 결과(sprint-N-feedback.md)를 작성합니다. 코드는 수정하지 않습니다.
프로젝트 폴더/
├── CLAUDE.md 메인 Claude (지휘 역할)의 규칙
└── .claude/
...
1 스프린트의 흐름은 다음과 같습니다.
generator → 구현 + sprint-N-self-eval.md(실행 방법과 URL을 반드시 기재)
↓
evaluator → sprint-N-feedback.md(서두에 합격/불합격)
...
채점 담당자에게만 Playwright를 맡기기
서브 에이전트의 설정 파일에서는 맨 앞의 mcpServers
에 MCP 서버를 작성할 수 있습니다. 채점 담당자의 설정은 다음과 같습니다.
---
name: evaluator
description: Playwright MCP로 실제로 앱을 조작하여 스프린트 결과물을 테스트 및 채점하는 에밸류에이터. 각 기준의 임계치를 밑돌면 불합격으로 하고, 구체적인 피드백을 반환한다.
...
본문에서는 채점 규칙을 다음과 같이 지시했습니다(발췌).
- 당신은 코드를 수정하지 않는다. 평가와 피드백만 수행한다.
- 하나라도 임계치를 밑돌면, 스프린트는 불합격이다.
- 채점은 엄격하게 한다. 제네레이터의 자체 평가를 맹신하지 않는다. '작동할 것 같다'가 아니라 '작동했다'는 사실만을 근거로 삼는다.
주의해야 할 점이 두 가지 있습니다.
- 프로젝트의
.claude/agents/
에 작성된 이 MCP 설정은 해당 폴더를 신뢰 가능(trusted)하게 하기 전까지는 로드되지 않습니다. 첫 실행 시에는 Claude Code 확인에 응답하므로 -
npx
을 사용해야 하며 Node.js가 설치되어 있어야 합니다.
14 스프린트의 결과
이 구성을 통해, 해외 애니메이션 팬들을 위한, 어느 나라의 어떤 스트리밍 서비스에서 작품을 볼 수 있는지 안내하는 사이트를 만들었습니다.
| 항목 | 결과 |
|---|
| 기간 | 2026년 10월 6일 ~ 10월 18일 |
| ... | |
| 불합격된 것들은 모두 만드는 담당자가 한 번은 완료로 제출했던 것입니다. 채점 담당자가 막았던 5가지를 소개합니다. | |
미방송 작품에 'ON AIR'
2027년 1월에 시작하는 28개 작품의 카드에 빨간색 'ON AIR' 라벨이 붙어 있었습니다. 시즌 페이지에는 'Not yet airing'이라고 올바르게 표시되어 있었기 때문에, 같은 작품이 화면에 따라 '방송 중'과 '미방송'으로 나뉘게 된 것입니다.
만드는 담당자는 이를 자체 평가에서 이미 알려진 문제로 언급했지만, 템플릿 사양의 문제라고 하여 수정하지 않았습니다. 채점 담당자는 데이터 측에서도 수정할 수 있다고 지적하며, 오해를 불러일으키는 표시라며 불합격 처리했습니다. 이때의 지적은 다음과 같은 형태였습니다(일부를 줄였습니다).
문제 1(중요・오해를 유발하는 표시): 방영되지 않은 Winter 2027 작품에 "On air"가 표시됨
- 재현 절차: http://localhost:8890/을 열고, Mashle Season 3의 카드를 확인합니다.
- 기대: 시작이 2027년 1월인 작품은 "Not yet airing" 등이어야 합니다.
...
재현 절차・기대・실제・중요도를 반드시 작성하게 했기 때문에, 만드는 담당자는 어떤 화면의 무엇을 고쳐야 할지 판단할 수 있습니다.
하절기를 열람일로 판정했음
일본 방송 시간을 각 지역 시간으로 변환하여 표시하는 처리에서, 하절기 여부를 방송일이 아닌 사이트를 보는 날짜로 판정하고 있었습니다. 방송일이 동계 시간이더라도, 보고 있는 날이 하절기라면 1시간 차이가 납니다.
수정 후, 채점 담당자는 사이트 코드를 사용하지 않고 Python으로 정확한 시간을 계산하여 화면의 표시와 대조했습니다. 열람일 11가지 경우, 타임존 8개, 방송표의 행을 조합한 528가지 모든 경우에서 일치합니다.
글자의 대비가 부족했음
첫 번째 스프린트에서는 글자와 배경의 대비가 WCAG 기준(일반 텍스트로 4.5:1)에 미달하여 불합격이었습니다. 수정 후, 채점 담당자는 총 14페이지의 글자를 실제로 측정하여 최소 5.07:1 이상임을 확인한 후에 합격 처리했습니다.
목표 작품 수에 도달하지 못해도, 작품을 지어내지 않았음
사양서에는 작품 수를 120편 이상으로 하는 목표를 세웠지만, 실제로 배포처를 확인할 수 있는 작품은 당시 49편밖에 없었습니다.
만드는 담당자는 확인할 수 없는 작품을 추가하지 않고 "미달"이라고 작성했습니다. 채점 담당자도 이를 구현 실패로 보지 않고, "데이터 입력 대기 중"으로 합불 계산에서 제외합니다. 그 위에서 평가용 복사본에 시험 삼아 한 줄을 넣어, 작품을 추가하는 시스템 자체는 작동함을 확인했습니다.
확실한 정보를 모아야만 충족할 수 있는 기준을 구현 실패와 동일하게 취급하면, 만드는 담당자는 가상의 데이터로 채우거나 영원히 합격하지 못하는 둘 중 하나가 됩니다. 숫자의 목표를 설정한다면, "확인된 데이터만으로 만든다"는 조건을 함께 적어두는 것이 좋습니다.
예약 시스템에서도 같은 일이 발생했음
같은 3가지 설정 파일을 업무상 만들고 있는 예약 시스템 개수에도 사용했습니다. 거기서도 채점 담당자는 다음 문제를 발견하고 있습니다.
- 서버의 PHP가 7.4라면, 8.0부터 사용할 수 있는
match 구문 때문에 모든 페이지가 멈춥니다 - 너비 375px에서 달력 날짜를 누를 수 있는 범위가 42.85px밖에 없습니다(기준은 44px 이상)
- 입력 직후에 전송 버튼을 누르면, 첫 번째 터치가 반응하지 않습니다
이 모든 문제는 자신의 컴퓨터에서 평소처럼 만져보고는 알 수 없는 문제였습니다.
시도해 보니 효과가 있었던 것들
- 지적 사항은 "재현 절차・기대・실제・중요도・수정 방향성"의 형태로 작성하게 하고, "더 사용하기 쉽게"와 같은 추상적인 지적을 금지합니다.
- 한 번 호출할 때 전달하는 것은 1스프린트만으로 합니다. 각 서브 에이전트는 이전 대화를 기억하지 못하므로, 읽어야 할 파일 이름을 매번 알려줍니다.
- 만드는 담당자와 채점 담당자를 동시에 실행시키지 않습니다. 채점 담당자는 완성된 것을 전제로 움직이기 때문입니다.
- 평가 기준은 "30초 이내에 판단할 수 있다", "너비 360px에서 무너지지 않는다"처럼, 조작하여 확인할 수 있는 형태로 작성합니다.
요약
만드는 담당자와 채점 담당자를 별도의 서브 에이전트로 나누고, 채점 담당자에게 실제로 조작하게 하면, "되었습니다"가 진짜인지 확인할 작업도 AI에 맡길 수 있습니다. 3가지 설정 파일은 만드는 것에 좌우되지 않으므로, 애니메이션 사이트와 예약 시스템 둘 다 같은 것을 사용했습니다.
Discussion