클로드코드 검증 게이트, 결함 3건은 왜 자체 채점에서 빠졌나
클로드코드 검증 게이트를 세우기 전까지, 내 자동화의 합격 판정은 전부 만든 쪽이 스스로 내린 거였다. 그 채점자를 갈라놨더니 통과였던 것에서 결함이 나왔다.
자동화를 하나 만들면 마지막에 늘 같은 걸 한다. 잘 됐나 확인. 근데 그 확인을 누가 하냐면, 만든 쪽이 한다. 클로드코드한테 시켜서 만들었으면 클로드코드한테 "다 된 거 맞아?"라고 묻는 거지. 답은 매번 비슷하다. 다 됐고, 테스트도 통과했고, 검증 완료. 나는 그걸 믿고 넘어갔다. 그러다 한 번 크게 데였고, 결국 채점자를 아예 딴 데서 데려오기로 했다.
📑 목차
- 1. 만든 쪽이 채점하면 늘 통과가 나온다
- 2. 채점표를 빌드 시작 전에 못 박아뒀다
- 3. 같은 대화에서 "다시 봐"는 왜 소용없나
- 4. 자체 테스트 전부 통과였는데 결함 3건이 나왔다
- 5. 검증자는 고치지 않는다, 그리고 세 번까지만
- 6. 검증층을 세 겹에서 두 겹으로 줄였다
- 7. 정리, 비용과 한계
1. 만든 쪽이 채점하면 늘 통과가 나온다
한동안은 이게 문제인 줄도 몰랐다. 완료 보고가 거짓말은 아니었으니까. 진짜로 테스트를 짜서 돌렸고, 진짜로 통과했다. 근데 그 테스트를 누가 짰냐가 문제였던 거다.
만든 쪽은 자기가 세운 가정 안에서 검사한다. "이 경우엔 이렇게 동작하면 된다"고 정해놓고 만들었으니, 확인할 때도 그 경우만 본다. 가정 자체가 틀렸으면? 그건 검사 대상에 아예 안 올라온다. 안 본 걸 안 본 줄 모르는 상태. 이게 자체 채점의 구조적인 구멍이더라.
통과했다는 말이 거짓이 아니라서 더 안 잡힌다.
내가 이 구멍을 제대로 본 건 리서치 자동화를 따라 만들다 크게 데였을 때다(카파시 auto-research 실패사례: 따라 만들다 3일과 1,450줄을 버렸다). 돌아가고 있는 자동화를 감시하는 층은 그 뒤에 따로 만들어뒀지만(자동화를 다 만들면 끝일까), 그건 이미 완성된 걸 지켜보는 쪽이지 만드는 도중에 합격 도장을 누가 찍느냐는 여전히 빈칸이었다.
그래서 이번엔 만드는 과정 쪽에 채점자를 하나 더 앉히기로 했다. 이름은 그냥 검증 게이트라고 붙였다. 게이트라고 부르는 이유는 통과 못 하면 다음으로 못 넘어가게 막는 문이라서.
▲ 자체 채점 흐름과 독립 검증 게이트 흐름을 두 카드로 나눠 채점자가 갈라지는 지점을 비교한 그림 (자체 제작 이미지)
2. 채점표를 빌드 시작 전에 못 박아뒀다
검증자를 부르는 것보다 먼저 정해야 할 게 있었다. 뭘 보고 합격이라고 할 건가.
이걸 빌드가 끝난 다음에 정하면 아무 의미가 없다. 결과를 이미 본 상태에서 기준을 쓰면, 통과하게 쓰게 되니까. 사람도 그러는데 AI는 더하다.
착수 전에 도는 게이트는 원래부터 있었다. 그게 뭘 물어보는 물건인지는 앞 글에 통째로 들어가 있으니 여기서 다시 풀지 않는다(리서치 자동화 실패기). 이번에 손댄 건 그 게이트 끝에 합격 기준 칸 하나(완료조건·검증방법·요구증거)를 덧붙인 것, 딱 그 하나뿐이다.
칸 하나 늘린 게 왜 중요하냐면, 거기 쓴 문장이 나중에 올 검증자의 유일한 입력이 되기 때문이다. 검증자는 이 작업을 처음 보는 쪽이라 "잘 됐나"를 스스로 정의할 수가 없다. 미리 박아둔 문장을 그대로 들고 와서 직접 돌려보는 것 말고 할 수 있는 게 없다. 반대로 그 칸이 비어 있으면 넘겨줄 게 없어지고, 결국 만든 쪽이 알아서 좋게 해석한 판정만 남는다. 머릿속에 있는 기준과 문서에 박힌 기준의 차이가 여기서 갈린다.
결과를 보기 전에 합격선부터 정하는 습관은 트레이딩 전략 검증하다 배운 건데(유명한 개장 돌파 전략, 왜 내 데이터에선 안 먹혔을까), 코드 만들 때도 똑같이 먹히더라. 규모에 맞춰서 쓰면 된다. 파일 하나 고치는 데 세 줄, 축 하나 새로 세우는 데 열 줄 정도.
3. 같은 대화에서 "다시 봐"는 왜 소용없나
여기서 많이들 그냥 이렇게 한다. 만든 다음에 같은 창에서 "다시 한번 검토해줘"라고 치는 것. 나도 오래 그렇게 했다. 근데 이건 채점자를 바꾼 게 아니다.
용어 하나 풀고 가자. 컨텍스트는 지금 대화에 쌓여 있는 내용 전부를 말한다. 내가 뭘 시켰고, AI가 뭘 만들었고, 중간에 뭘 고쳤는지가 다 그 안에 들어 있다. 같은 창에서 "다시 봐"를 시키면 그 기억을 전부 지고 검토하는 셈이다. "아까 이렇게 하기로 했잖아"가 판단에 그대로 섞인다. 자기가 세운 가정을 자기가 다시 확인하는 거니까 결론이 바뀔 리가 없다.
그래서 필요한 게 서브에이전트다. 클로드코드 안에서 별도로 띄우는 다른 대화라고 보면 된다. 앞의 대화 내용을 하나도 안 가진 상태로 시작하고, 내가 넘겨준 문서와 실제 파일만 보고 판단한다. 이 친구한테는 "잘 만들었나 봐줘" 같은 말랑한 부탁을 하지 않는다. 아까 써둔 완료조건·검증방법·요구증거를 그대로 던지고, 네가 직접 돌려서 증거를 가져오라고 시킨다.
앞 대화를 하나도 모른다는 게 검증자한테 결격 아니냐고? 채점 자리에서는 그게 유일한 자격이다.
4. 자체 테스트 전부 통과였는데 결함 3건이 나왔다
게이트를 다 만들고 제일 먼저 한 건, 방금 그 게이트를 만든 작업 자체에 걸어보는 거였다. 자기가 만든 도구를 자기한테 먼저 써보는 걸 도그푸딩이라고 부르던데 딱 그거다. 그날 나온 건 합격 기준 칸 하나, 게이트를 부르는 명령어, 그리고 특정 행동을 할 때 자동으로 끼어드는 작은 검사기(권한 세팅 글에서 다뤘던 그 훅) 하나였다. 새 대화 검증자를 불러 합격 기준을 직접 돌리게 했고, 판정은 통과로 나왔다. 문이 열리고 닫히긴 하는구나, 거기까지 확인.
게이트가 제값을 한 건 그다음 작업에서다.
블로그 글 초안을 자동으로 써내는 파이프라인을 하나 만들고 있었다. 주제를 넣으면 자료를 모으고 초안을 뽑고 형식 검사까지 돌려서 발행 대기 목록에 얹는 물건이다. 빌드를 끝내고 자체 테스트를 돌리니 전부 통과. 예전 같으면 여기서 완료라고 적고 손 털었을 거다. 이번엔 새 대화 검증자한테 완료조건을 그대로 던지고 네가 직접 돌려보라고 시켰다. 결함이 세 건 나왔다.
먼저, 최종 검사기가 원고 두 판 중 한 판만 보고 있었다. 완료조건 원문은 "블로그판과 네이버판 둘 다"였는데 실제로 도는 검사는 블로그판 하나였다. 네이버판은 블로그판을 그대로 복사한 게 아니라 따로 생성되는 산물이라, 블로그판이 아무리 깨끗해도 거기엔 금지된 문장부호가 그대로 들어온다. 네이버로 나가는 글에는 최종 검사가 아예 없는 상태였던 거다.
두 번째는 제목 교체 기능이었다. 특정 문자가 들어간 제목을 넣으면 그 자리에서 크래시하더라. 문자열을 바꿔 끼우는 자리에 넘긴 값이 정규식 특수 기호로 해석되면서 나는 오류다. 내가 답장으로 그런 제목을 하나 보내는 순간 그날 발행이 통째로 죽는 구조였다.
마지막은 소리 없이 사라지는 쪽이라 제일 고약했다. 발행 목록에 새 글을 얹을 때 이미 있는 글인지 판정하는 부분이, 목록 문서 전체를 훑는 부분일치였다. 게다가 걸리면 아무 말 없이 그냥 건너뛰더라. 다른 항목의 자유 서술 문단에 주소 조각이 우연히 들어 있기만 해도 새 글이 목록에서 조용히 빠지고, 경고 한 줄 안 뜬다.
세 건 다 자체 테스트에서는 통과였다. 이유는 1장에 쓴 그대로다. 테스트를 만든 쪽이 자기가 상상한 입력만 넣었으니까. 원고가 두 판으로 갈린다는 걸 검사기 쪽에서 잊었으면 그 케이스는 테스트에도 안 올라오고, 이상한 문자가 든 제목은 애초에 넣어볼 생각을 안 한다.
고친 다음에 한 가지가 더 걸렸다. 결함마다 테스트를 새로 붙였는데, 이 테스트를 그냥 통과하도록 느슨하게 써놨으면 아무 의미가 없잖아. 그래서 고친 소스만 원래대로 되돌려놓고 새 테스트를 다시 돌렸다. 네 건이 전부 실패로 떨어지더라. 되돌린 걸 복구하니 다시 전부 통과. 이 테스트가 진짜로 그 결함을 잡는다는 증거를 그렇게 만들어뒀다.
▲ 자체 테스트를 전부 통과한 글 초안 자동화에서 독립 검증이 찾아낸 결함 3건과 되돌리기 재실행 결과를 담은 리포트 화면 (자체 제작 이미지)
5. 검증자는 고치지 않는다, 그리고 세 번까지만
여기서 규칙을 두 개 박았다.
첫째, 검증자는 결함을 찾기만 하고 고치지 않는다. 리포트만 던지고 끝. 수정은 원래 만든 쪽이 한다. 처음엔 "찾은 김에 고치라고 하면 되지 않나" 싶었는데, 그러면 검증자가 곧바로 만든 쪽이 되어버린다. 자기가 고친 걸 자기가 다시 통과 판정하는 순간 원점이다. 채점자와 선수를 갈라놓는 게 이 게이트의 전부인데 그걸 스스로 무너뜨릴 순 없지.
둘째, 이 왕복은 세 번까지만 돈다. 검증에서 결함이 나오면 고치고 다시 검증, 그게 세 바퀴를 넘어가면 멈추고 나한테 올라온다. 상한을 안 걸면 자잘한 지적과 자잘한 수정이 무한히 핑퐁을 치는데, 그 왕복이 전부 돈이다. 세 바퀴 돌고도 안 끝났으면 그건 코드 문제가 아니라 설계나 합격 기준이 잘못 잡힌 거라고 보는 게 맞더라.
그리고 하나 더. 증거 없는 완료는 인정 안 한다. "확인했습니다"라는 문장만 오면 미완료 처리다. 뭘 돌려서 뭐가 나왔는지가 같이 와야 한다. 사람이 손가락 하나 얹는 자리를 남겨두는 것과 비슷한 발상인데, 자동매매를 완전자동으로 안 만든 것도 같은 이유였다(체결과 보고가 따로 놀았던 얘기).
6. 검증층을 세 겹에서 두 겹으로 줄였다
처음 설계에는 검증층이 세 겹이었다.
0층은 스크립트다. 기계적으로 판정 가능한 것만 본다. 문서 맨 위에 설명 한 줄이 있나, 긴 문서에 목차가 있나, 버전 라벨이 규칙대로 붙었나. 이런 건 AI를 부를 이유가 없다. 문자열 검사면 끝이고 공짜다.
2층은 클로드다. 의미를 봐야 하는 것들. 이 출처 태그가 실제로 그 내용을 뒷받침하나, 앞으로 생길 문제를 미리 짚었나 같은 판단.
문제는 1층이었다. 내 맥 안에서 도는 로컬 AI 모델한테 가벼운 1차 선별을 맡기려고 했다. 공짜니까 부담 없이 여러 번 돌릴 수 있겠다는 계산이었다. 근데 실제로 붙이려니 얘기가 달라지더라.
일단 배선부터 걸렸다. 그 로컬 모델은 클로드코드가 서브에이전트로 부를 수 있는 물건이 아니다. 완전히 딴 프로세스로 도니까 스케줄러랑 통신이랑 출력 걸러내는 래퍼를 새로 깔아야 했다. 검증 하나 붙이자고 공사를 벌이는 꼴이지.
더 웃긴 건 그다음이었다. 1층에 쓰려던 그 로컬 모델이, 정작 내 설계 문서 안에서 "얘는 틀린 걸 통과시킬 위험이 있으니 조심해라"라고 경고해둔 당사자였다. 틀렸는데 통과시키는 건 검증층에서 제일 나쁜 실패다. 아예 검증이 없는 것보다 나쁘다. 통과 도장이 찍혔으니 아무도 다시 안 보거든.
정리하면 "로컬이라 공짜"라는 장점 하나 때문에 위험과 복잡함을 둘 다 떠안는 거래였다. 로컬 모델이 실측해보니 생각만큼 이득이 아니었다는 얘긴 따로 쓴 적 있는데(로컬 LLM이 더 이득이라는 착각), 여기서도 같은 결론이 나왔다.
그래서 내가 1층을 없애라고 했다. 대신 값싼 모델로 1층을 채우는 안도 검토했다가 그것도 접었다. 0층과 2층만으로 이미 다 커버되는데 선별층을 굳이 하나 더 낄 이유가 없었으니까.
없앨 때 검사 항목까지 같이 버리면 안 되니까, 1층이 보던 걸 양쪽으로 나눠서 옮겼다. 형식 체크리스트는 0층 스크립트로, 출처 태그가 적절한지 보는 건 2층 체크리스트로. 층은 줄었는데 검사 항목은 그대로 남았다.
▲ 검증층을 0층·1층·2층 세 겹에서 0층·2층 두 겹으로 줄이고 1층 검사 항목을 양쪽으로 흡수시킨 구조도 (자체 제작 이미지)
7. 정리, 비용과 한계
돈 얘기를 빼면 안 되겠지. 검증 서브에이전트 한 번 부르는 데 드는 건 작업 한 사이클당 대략 5만에서 25만 토큰 정도로 잡힌다. 토큰은 AI가 읽고 쓴 글자량을 세는 단위고, 이건 원래 작업에 얹히는 비용이라 전체의 5%에서 15% 정도 되는 오버헤드다. 검증자는 기본을 중간 등급 모델로 뒀다. 결함을 찾아 리포트로 정리하는 일에 제일 비싼 모델까지 갈 필요는 없었다. 모델 등급마다 값이 다르다는 건 공식 요금 페이지에 나와 있고, 이걸 어떻게 아끼는지는 비용 아끼는 법 글에 따로 정리해뒀다.
솔직하게 한계도 적어야겠다.
이걸 붙였다고 결함이 안 나오는 게 아니다. 검증자도 놓친다. 애초에 합격 기준을 부실하게 써놓으면 검증자는 그 부실한 기준을 성실하게 통과시킨다. 이 게이트가 실제로 하는 일은 결함을 없애는 게 아니라 채점자를 한 명에서 두 명으로 늘리는 것뿐이다. 두 명이 같은 걸 놓칠 수도 있다.
그리고 모든 작업에 걸 필요도 없다. 문서 몇 줄 고치는 데 검증자를 부르면 배보다 배꼽이다. 나는 되돌리기 비용을 기준으로 나눠뒀다. 돈이 나가거나 밖으로 뭔가 발송되거나 계속 떠 있는 프로그램을 건드리는 작업이면 반드시, 볼트 안에서만 도는 도구면 가볍게, 문서만 고치는 건 면제.
채점 기준을 만드는 게 채점보다 어렵다는 건 모델 비교를 하면서도 똑같이 겪었는데(AI 모델 비교, 진짜 어려운 건 순위가 아니라 채점 기준이었다), 여기서도 결국 그 문제로 돌아왔다. 검증자를 부르는 건 명령어 한 줄이고, 어려운 건 그 앞에 뭘 써두느냐다.
3줄 요약 - 만든 쪽이 채점하면 자기가 세운 가정 밖은 검사에 안 올라온다. 그래서 통과 판정이 거짓이 아닌데도 결함이 남는다. - 합격 기준(완료조건·검증방법·요구증거)을 빌드 전에 써두고, 앞 대화를 모르는 새 대화가 그걸 직접 실행하게 갈라놨다. 검증자는 고치지 않고 리포트만, 왕복은 세 번까지. - 자체 테스트를 전부 통과한 글쓰기 자동화에서 결함 3건이 나왔다. 한쪽 원고에만 걸린 최종 검사, 특정 문자 제목에서 죽는 제목 교체, 조용히 새 글을 빠뜨리는 중복 판정. 고친 뒤엔 소스를 되돌려 새 테스트가 진짜 잡는지까지 확인했다.
아직 안 풀린 것도 있다. 합격 기준을 잘 쓰게 만드는 방법은 여전히 사람 손에 달려 있고, 그건 게이트로 못 막는다. 채점자를 늘려도 채점표가 부실하면 통과는 통과다. 이 다음 구멍은 아마 거기서 나올 것 같은데.
이 글은 정보 제공을 목적으로 하며, 작성 시점(2026년 8월) 기준 정보다. 모델 요금·기능·문서 구조는 공식 페이지에서 바뀔 수 있으니 비용이 걸린 판단 전에 원문을 한 번 확인하길 권한다. 본문의 토큰 사용량·오버헤드 수치는 내 작업 환경에서 관측한 값이라 다른 환경에서는 다르게 나올 수 있고, 특정 제품 사용을 권유하거나 결과를 보장하지 않는다.
참고한 공식 자료 - 클로드코드 개요·기본 사용: code.claude.com/docs - 설치·설정: code.claude.com/docs/setup - 모델별 요금(API): platform.claude.com, pricing