- AI 코드 작성 에이전트가 개발자가 자는중에도 코드를 생성하고 브랜치에 변경사항을 반영하지만, 결과의 정확성과 신뢰성 검증이 어려움
- AI가 작성한 코드를 같은 AI가 테스트하면 자기 축하 기계가 되어, 원래 의도와 다른 오해를 잡아내지 못함
- TDD의 핵심 원칙을 차용해 코드 작성전에 수용 기준을 먼저 작성하고, 에이전트가 이를 기준으로 구현 후 별도 검증 수행
- 검증 도구로 Claude Code의 headless 모드(claude -p)와 Playwright MCP를 결합한 4단계 파이프라인 구축, 별도 백엔드 불필요
- 에이전트 산출물을 신뢰하려면 작업 시작 전에 "완료"의 정의를 명확히 해야 하며, 이는 프롬프트 작성보다 어렵지만 필수적인 과정
자율 에이전트의 코드 검증 문제
- Gastown 같은 AI도구를 활용해 에이전트가 수 시간 동안 코드를 작성하고 브랜치에 변경 사항을 반영하지만, 그 결과물이 실제로 올바른지 신뢰할 수 있는 검증 방법이 없음
- 지난 6개월간 100명 이상의 엔지니어 대상 Claude Code 워크숍을 진행한 결과, 모든 팀에서 동일한 문제 확인
- Claude를 일상적 PR에 사용하는 팀들은 주당 10개에서 40~50개로 PR 병합량이 증가해, 코드 리뷰에 훨씬 더 많은 시간 소비
- 시스템이 자율적으로 동작할수록 문제가 심화됨 - 어느 시점에서는 diff를 리뷰하지 않고 배포를 지켜보며 문제가 없기를 바라고, 배포 후에야 오류를 발견하는 구조가 됨
기존 해결책의 한계
- 리뷰어를 추가 채용하는 방법은 속도가 따라가지 못하고, 시니어 엔지니어가 하루 종일 AI 생성 코드를 읽는 것은 비효율적
- Claude가 자신이 작성한 코드의 테스트를 작성하면, 사용자가 실제로 원한 것이 아니라 Claude가 원한다고 판단한 것을 검증하는 구조
- 회귀 버그는 잡을 수 있지만 원래의 오해(misunderstanding) 는 포착 불가
- 같은 AI로 작성과 검증을 동시에 수행하면 "자기 축하 기계(self-congratulation machine)" 가 됨
- 코드 리뷰의 본래 목적은 원래 작성자가 아닌 두 번째 시선인데, AI 간 교차 검토는 동일한 출처에서 비롯되어 같은 것을 놓침
TDD가 올바르게 짚은 핵심
- TDD의 원칙: 테스트를 먼저 작성하고, 코드를 작성하고, 테스트가 통과하면 멈춤(더 구현하지 않고)
- 대부분의 팀이 TDD를 하지 않는 이유는 코드가 무엇을 해야 하는지 미리 생각하는 데 시간이 걸리기 때문
- AI가 속도 문제를 해결하므로 이 핑계가 사라짐 — 이제 느린 부분은 코드가 올바른지 판단하는 것
- 단위 테스트 대신 기능이 해야 할 일을 평문으로 기술하는 방식이 더 쉬움
- 예시: "사용자가 이메일과 비밀번호로 인증. 잘못된 자격 증명 시 'Invalid email or password' 표시. 성공 시 /dashboard 이동. 세션 토큰은 24시간 후 만료"
- 코드 에디터를 열기 전에 이 기준을 작성 가능하며, 에이전트가 구현하고 다른 무언가가 검증
실제 적용 사례
-
프론트엔드 변경
- 스펙 파일 기반으로 수용 기준(Acceptance Criteria) 을 생성
- AC-1: 유효한 자격 증명으로 /login 접속 시 /dashboard로 리다이렉트, 세션 쿠키 설정
- AC-2: 잘못된 비밀번호 입력 시 정확히 "Invalid email or password" 표시, /login 페이지 유지
- AC-3: 필드가 비어 있으면 제출 버튼 비활성화 또는 인라인 에러 표시
- AC-4: 5회 실패 후 60초간 로그인 차단, 대기 시간 메시지 표시
- 각 기준은 통과 또는 실패로 명확히 판별 가능
- 에이전트가 기능 구축 후, Playwright 브라우저 에이전트가 각 AC에 대해 검증 실행, 스크린샷 촬영, 기준별 판정 리포트 생성
- 실패 시 어떤 기준이 실패했고 브라우저에서 무엇이 보였는지 정확히 확인 가능
- 스펙 파일 기반으로 수용 기준(Acceptance Criteria) 을 생성
-
백엔드 변경
- 브라우저 없이 동일한 패턴 적용
- 관찰 가능한 API 동작(상태 코드, 응답 헤더, 에러 메시지)을 명시하고 curl 명령어로 검증
-
한계점
- 스펙 자체의 오해는 잡아내지 못함 — 스펙이 처음부터 잘못되면 검증을 통과해도 기능이 틀린 상태
- Playwright가 잡아내는 것: 통합 실패, 렌더링 버그, 실제 브라우저에서 깨지는 동작
- "검증된 정확성"보다는 좁은 범위의 주장이지만, 코드 리뷰가 안정적으로 잡아내던 것보다는 더 많은 것을 포착
-
워크플로우 요약
- 프롬프트 전에 수용 기준 작성 → 에이전트가 기준에 맞춰 구현 → 검증 실행 → 실패한 것만 리뷰 (diff가 아닌 실패 리뷰)
구축 방법: 4단계 파이프라인
- Claude Skill로 구현 (github.com/opslane/verify), claude -p(Claude Code headless 모드)와 Playwright MCP 사용
- 별도 커스텀 백엔드나 추가 API 키 불필요, 기존 Claude OAuth 토큰만 사용
-
1단계: Pre-flight
- 순수 bash, LLM 호출 없음
- 개발 서버 실행 여부, 인증 세션 유효성, 스펙 파일 존재 여부 확인
- 토큰 소비 전에 빠르게 실패 처리
-
2단계: Planner
- Opus 한 번 호출
- 스펙과 변경된 파일을 읽고, 각 검증에 필요한 사항과 실행 방법 결정
- 코드를 읽어 올바른 셀렉터를 찾으므로 클래스 이름을 추측하지 않음
-
3단계: Browser Agents
- AC당 Sonnet 한 번 호출, 모두 병렬 실행
- 5개 AC이면 5개 에이전트가 독립적으로 네비게이션 및 스크린샷 촬영
- Sonnet은 Opus 대비 3~4배 저렴하며 클릭 기반 작업에서 동등한 성능
-
4단계: Judge
- Opus 한 번 최종 호출로 모든 증거를 읽고 기준별 판정 반환: pass, fail, 또는 needs-human-review
-
설치 방법
- Claude Code 플러그인으로 설치 가능:
/plugin marketplace add opslane/verify - 또는 레포를 클론하여 커스터마이징 가능 — 각 단계는 단일 claude -p 호출로 명확한 입력과 구조화된 출력 보유
- 모델 교체, 단계 추가, --dangerously-skip-permissions 옵션으로 CI 연동 가능
- Claude Code 플러그인으로 설치 가능:
핵심 교훈
- “완료의 정의를 사전에 명시하지 않으면, 결과를 신뢰할 수 없다” 는 점이 핵심
- 수용 기준 작성은 프롬프트보다 어렵지만, 엣지 케이스를 사전에 고려하게 만들어 품질을 높임
- 엔지니어들이 TDD를 거부했던 이유와 동일하게, 처음에 더 느리게 느껴지기 때문에 저항함
- 수용 기준 없이는 결과물을 읽고 올바르기를 바라는 것만 가능
- 이는 AI 주도 개발 환경에서 신뢰성을 확보하는 필수 절차임