1. 클로드 코드 테스트 게이트에서 무슨 일이 있었나요?
블로그 대표 이미지 기준이 두 번 롤백됐습니다. 2026-09-17~18 에는 남색 템플릿이, 2026-09-27 에는 숫자 강조 템플릿이 다시 나왔습니다. 그래서 규칙을 지시문에서 빼내 검사기(정해진 기준과 다르면 막는 작은 프로그램)로 옮겼습니다. 그 검사기를 셸과 클로드 코드 훅(도구를 쓰기 직전에 끼어드는 스크립트) 두 곳에 걸었습니다. 2026-10-01 빈 폴더에서 같은 훅을 마지막 숫자만 바꿔 돌렸더니, 종료 코드(프로그램이 끝나며 남기는 성공, 실패 숫자) 1일 때는 hello.txt 가 생겼고 2일 때만 쓰기가 멈췄습니다.2. 무슨 문제가 생겼나요?
검사기가 맞는 숫자를 내도, 그 숫자를 읽는 쪽이 막음으로 받아 주지 않으면 막히지 않습니다. 화면에는 “막음” 이 찍혀 있으니 사람은 막힌 줄 압니다. 이런 자리가 두 군데 있었습니다. 클로드 코드 2.1.281 의 PreToolUse 훅은 exit 2 만 막음으로 읽었습니다. 셸에서는 검사 출력을 남기려고 tee 파이프를 붙이자, 검사기의 1이 파이프 끝 tee 의 0에 덮여 올리기가 실행됐습니다.
| 훅 종료 코드 | 클로드 코드의 마지막 출력(로그 그대로) | hello.txt |
|---|---|---|
| exit 1 | 완료했습니다. hello.txt 파일이 생성되었고 “hi”가 한 줄 들어있습니다. | 생김(hi) |
| exit 2 | Write 도구가 gate.sh 훅에 의해 차단됨: 대표 이미지 기록이 기준과 다르다. | 안 생김 |
3. 클로드 코드 테스트 게이트, 어떻게 풀었나요?
검사기를 고치기보다 숫자를 읽는 자리를 하나씩 맞췄습니다.- 규칙을 지시문 밖으로 뺍니다. 정의 안의 “수치형이면 숫자 템플릿” 분기와 “실패하면 임시로 옛 방식” 문장을 지우고, 검사기가 이미지 기록(manifest) 첫 칸의 생성 도구와 배경을 직접 읽어 막게 했습니다(검사 항목 G07b)
- 검사기 종료 코드를 0, 1, 2 로 나눕니다. 기준과 같으면 0, 다르면 1, 파일을 못 열거나 JSON 이 깨졌으면 2입니다. 판정 불가를 통과로 두지 않는 것이 가장 먼저 정한 줄입니다
- 클로드 코드 훅에서는 막을 경우를 전부 exit 2 로 냅니다. Claude Code 훅 문서도 “Exit 2 means a blocking error.” 라고 적습니다
- 셸 파이프에 tee 를 쓰면 pipefail 을 켭니다. 켠 서브셸에서는 같은 줄이 “멈춤(종료 코드 1)” 로 돌아왔습니다
- 막히면 기준을 낮추지 않고 산출물을 고칩니다. bad.json 을 기준에 맞게 다시 쓰자 같은 검사기에서 통과였습니다
| 거는 자리 | 막음으로 읽는 코드 | 새어 나간 경우 | 맞춘 방법 |
|---|---|---|---|
셸 검사 && 올리기 | 0 이 아닌 전부 | 없음 | 그대로 둔다 |
| 셸 파이프 끝에 tee | 맨 끝 tee 의 코드 | 막음 1 이 통과로 바뀜 | set -o pipefail |
| 클로드 코드 PreToolUse 훅 | exit 2 만 | exit 1 로 끝난 훅 | 막을 경우를 exit 2 로 |
허용 값을 하나 더 넣는 것이 가장 빠른 길이지만, 그러면 지운 분기가 검사기 안에 다시 생깁니다. 규칙을 알려 줘도 안 지켜진 일은 AI에게 규칙을 알려줬는데 안 지켜졌습니다에서 다뤘습니다.
4. 누구에게 도움이 되나요?
에이전트가 만든 산출물을 검사기로 거르고, 그 검사기를 셸과 클로드 코드 훅에 같이 거는 분이라면 읽어 보세요. 막는 분기 하나와 파이프 한 줄만 보면 됩니다. 셸에서 검사 뒤에 바로 이어 붙이기만 하고 파이프를 쓰지 않는다면 굳이 손볼 필요는 없습니다. 그 자리에서는 1이든 2든 멈췄습니다. 검증까지가 일이라는 이야기는 AI 에이전트로 혼자 일하기, 늘어난 건 산출물이 아니라 검증이었습니다에, 되돌릴 수 있다는 믿음의 비용은 AI 에이전트 권한 설계와 되돌리기 비용에 적었습니다.5. 한 줄 정리
필자의 결론
클로드 코드 테스트 게이트는 검사기가 맞는 숫자를 내는 것만으로는 막지 못하고, 그 숫자를 읽는 자리가 막음으로 받아 줘야 막습니다. 그래서 검사기는 0, 1, 2 로 고정하고 셸에서는 pipefail, 훅에서는 막을 경우를 전부 exit 2 로 냅니다. 남은 구멍도 있습니다. 검사기는 기록만 보고 이미지 실물은 보지 않으며, 누군가 기준 값을 바꾸면 바뀐 기준으로 충실히 통과시킵니다.그래서 당신은 이것만 하면 됩니다. 지금 걸어 둔 훅 스크립트 하나를 열어 막는 분기가 exit 2 로 끝나는지, tee 를 쓰는 줄에 pipefail 이 켜져 있는지 확인해 보세요.여러분은 검사 로그를 어디에 남기고 계신가요? 댓글로 들려주세요.
부록: 재현 명령과 출력
2026-10-01 macOS 의 /tmp 빈 폴더에서 Python 3.14.7, 클로드 코드 2.1.281 로 돌렸습니다. 각 폴더의.claude/settings.json 에는 {"hooks":{"PreToolUse":[{"matcher":"Write","hooks":[{"type":"command","command":"<작업 폴더>/gate.sh"}]}]}} 한 줄을 두었고, gate.sh 는 아래와 같습니다(exit 1 판은 마지막 숫자만 다름).
#!/bin/bash
echo "막음: 대표 이미지 기록이 기준과 다르다" >&2
exit 2
클로드 코드에는 claude -p --model haiku --setting-sources project --allowedTools "Write" 로 “hello.txt 파일을 만들고 hi 한 줄을 써. 막히면 막힌 이유를 한 줄로 적고 다른 방법은 쓰지 마.” 를 넘겼습니다. exit 1 폴더의 실제 출력입니다.
== 훅이 exit 1 로 끝날 때 (/tmp/s5h-wzAd)
완료했습니다. hello.txt 파일이 생성되었고 "hi"가 한 줄 들어있습니다.
hello.txt: 생김(hi)
검사기 checkhero.py 는 ok.json 에 “통과”(0), bad.json 에 “막음: generator=stat-template, background=solid”(1), broken.json 에 “판정 불가: JSONDecodeError”(2), missing.json 에 “판정 불가: FileNotFoundError”(2) 를 냈습니다. 셸 실험은 python3 checkhero.py "$f" && publish 로 돌렸고 publish 는 “올리기 실행됨” 만 찍는 셸 함수라 실제 글은 건드리지 않았습니다. tee 를 붙인 줄의 출력입니다.
[bad.json] python3 check_hero.py bad.json | tee gate.log && publish
막음: generator=stat-template, background=solid
-> 올리기 실행됨
haiku 로 한 번씩 돌린 결과라 다른 이벤트와 도구는 미확인이고, 훅 안에서 tee 를 쓰는 경우도 재현하지 않았습니다. bash 버전은 로그에 남기지 않아 미확인이고, exit 1 판에서 훅이 불린 흔적(표준 오류 문구)은 출력에 보이지 않아 같은 구성의 exit 2 판으로 미뤄 볼 뿐입니다.
함께 보면 좋은 글
- [AI 코딩] 클로드 코드 백그라운드, 원고에 남의 글이 붙은 일
- 프롬프트 작성법, 예시 붙이니 950자 틀이 83자로 줄었을까
- [AI 코딩] 클로드 코드 작업 예약, 마감 메모에 일이 멈춘 일
- [AI 코딩] 클로드 코드 병렬, 저장 안 한 문서 6개가 사라진 일
여러분의 검사기나 훅은 실패했을 때 어떤 숫자로 끝나게 해 두셨나요?
새 글이 올라오면 Threads @wonizz.ai 에도 올립니다. 팔로우해 두면 피드에서 바로 볼 수 있습니다.