Claude 가 만들고 Codex 가 반증한다 — 사흘 · 세 프로젝트 · 잡은 것과 틀린 것

AI 코딩 시작하기··9분 읽기·

Claude 가 만들고 Codex 가 반증한다 — 사흘 · 세 프로젝트 · 잡은 것과 틀린 것

결과부터 — 사흘 동안 세 프로젝트에서 나온 판정

9월 1일부터 3일까지, Claude Code 로 만든 것을 Codex CLI 에게 검증시키는 같은 절차를 세 프로젝트에 돌렸어요. 이걸 교차검증이라고 부릅니다 — 만든 모델이 아닌 다른 계열의 모델이 결과를 독립적으로 대조하는 것이에요. 결과는 아래 표입니다.

프로젝트 · 날짜

주장

판정

Codex 가 잡은 것

Codex 가 틀린 것

블로그 발행 파이프라인 · 09-03

14건

PASS 7 · FAIL 3 · PARTIAL 4

발행 승인이 코드로 강제되지 않았다(C12) · codex.cmd 의 EINVAL(C8 — 같은 결함이 lint 훅에도 있어 조용히 통과만 하던 것은 제가 확인) · 이메일 검사가 첫 매치에서 멈췄다(C9)

"편집기 확장에 tight-lists 가 있다"(C3) — 저장된 글 30편 전수 대조로 기각

로또 분석 서비스 · 09-03

10건

PASS 4 · PARTIAL 6 (한 항목의 세부 주장 1건은 FAIL)

내가 이번에 새로 만든 버그 1건 · 같은 결함 패턴 3개 추가

"predict 페이지가 없어 엔진 출처 불명" — 정본 문서로 기각

표에 넣지 않은 둘도 있어요. 로또 서비스는 9월 2일에도 두 차례 반증을 받아 2건 반영 · 2건 기각(취약점 등급 과소평가, 기존 코드를 새 결함으로 지적). 주식 자동매매 봇은 9월 1일 도구 2개에서 우회 경로 5곳(가장 심각한 것은 판정 위조)과 결함 4건 — 이쪽은 판정표가 아니라 결함 목록으로 받았습니다.

PASS 는 근거가 주장을 뒷받침한다, FAIL 은 근거가 주장과 다르다, PARTIAL 은 방향은 맞지만 수치·시점·주체가 다르다는 뜻이에요. 두 프로젝트 합쳐 24건 중 11건이 PASS 였고 — 절반이 안 됐어요 — 나머지에서 실제 결함과 내 주장의 과장이 함께 나왔습니다. 그리고 Codex 도 틀렸어요 — 세 차례에 걸쳐 네 건. 이 글은 그 절차를 어떻게 돌리는지, 판정이 갈렸을 때 무엇으로 결론내는지에 관한 이야기입니다. 표의 훅 사건(C8)은 그 자체로 한 편이라 따로 씁니다.

왜 "검토해 줘" 가 아니라 반증인가

블로그 파이프라인 규칙 파일에 이렇게 적어 뒀어요. "같은 모델이 쓰고 같은 모델이 검사하면 놓치는 결함의 종류가 같다." 저는 코드를 읽지 못하는 사람이라 AI 가 "됐습니다" 하면 그 말을 믿을 수밖에 없는데, 만든 AI 에게 "검토해 줘" 라고 다시 물으면 거의 언제나 "문제 없습니다" 가 돌아옵니다. 실수를 만든 편향 그대로 검토하니까요. 동의를 구하는 질문에는 맞장구가 돌아옵니다.

그래서 검토 대신 반증을 시킵니다. "이게 맞는지 봐 줘" 가 아니라 "이 주장이 틀렸다는 근거를 찾아라" 로 묻는 거예요. 그리고 묻는 상대를 바꿉니다. 로또 서비스에서 9월 2일에 나온 두 건 — 1,000건 조회 상한으로 239회 누락, 로그인 쿠키 갱신 누락 — 은 작업일지에 "자기 검토로는 못 잡았을 결함" 이라고 적혀 있어요. 만든 쪽이 못 보는 종류를 다른 쪽이 봅니다.

주식 봇에서는 9월 1일 도구 2개에서 사람이 놓친 결함이 교차검증으로 나왔고 — 그중 하나는 판정을 위조할 수 있는 구멍이었어요 — 돈이 움직이는 곳이라 이튿날 거래 관련 기능·전략은 Codex 로 교차 검증하는 것을 원칙으로 고정했습니다.

절차 — 주장을 적고, 명령 한 줄로 반증을 받는다

절차는 네 단계입니다.

첫째, 주장을 적습니다. AI 가 "이걸 했다" 고 보고한 내용을 CLAIMS.md 에 항목별로 옮기고, 증거 — 고친 파일의 변경 내역(diff), 타입 검사 전후 결과, 돌아가는지만 보는 간단 테스트(스모크 테스트) 출력 — 를 같은 폴더에 모읍니다. 로또 서비스 때는 10항목, 블로그 파이프라인 때는 14항목이었어요. 근거 없이 물으면 Codex 도 추측할 뿐이라 증거 폴더가 핵심입니다. 파일 맨 위에 검증 지시를 붙여 두면 이 파일 하나가 그대로 프롬프트가 돼요.

CLAIMS.md — 아래 주장에 동의하지 말고 반증하라.
각 항목에 PASS / FAIL / PARTIAL / UNVERIFIABLE 하나와 재현 가능한 근거(파일:줄)를 붙여라.
마지막에 두 가지를 따로 답하라 — 내가 놓친 것, 내가 과장한 것.

- C1 로그인 사용자용 API 에 남아 있던 미선언 session 참조를 전부 없앴다 (증거: tsc 전/후 출력)
- C2 무인증 쓰기 요청은 전부 401 을 돌려준다 (증거: 스모크 테스트 로그)

둘째, 명령 한 줄로 반증을 시킵니다. 이 글의 명령은 codex-cli 0.144.3 기준이에요(2026-09-03 실측).

  # -m / -c              모델·추론 강도를 명시 — 기본값은 조용히 바뀐다
  # -s read-only         검증자는 파일을 읽기만 한다
  # --skip-git-repo-check  git 저장소가 아니어도 실행
  # -C ./evidence        근거 파일이 있는 폴더를 작업 폴더로
  # -o verdict.md        판정을 파일로 저장
  # - < CLAIMS.md        프롬프트는 인자가 아니라 stdin 으로 — 인자로 주면 무한 대기
codex exec -m gpt-5.6-sol -c model_reasoning_effort="xhigh" -s read-only --skip-git-repo-check -C ./evidence -o verdict.md - < CLAIMS.md

세 가지가 중요해요. 모델과 추론 강도를 명시합니다 — 기본값은 조용히 바뀝니다. -s read-only 는 read-only 샌드박스, 검증자가 파일을 읽기만 하고 고치지는 못하게 잠그는 실행 모드예요. 검증하는 쪽이 코드를 만지기 시작하면 만드는 자와 검증하는 자가 다시 한 몸이 됩니다. 그리고 프롬프트는 stdin — 명령줄 인자가 아니라 파이프로 흘려 넣는 입력 — 으로 줍니다. 터미널이 아닌 곳(백그라운드 작업·자동화)에서 codex exec 에 프롬프트를 인자로 주면 입력을 기다리며 출력 0줄로 무한 대기해요. 7월에 40분 넘게 멈춘 사고로 배운 함정입니다.

셋째, 판정은 항목마다 네 값 중 하나로 받습니다. PASS, FAIL, PARTIAL, 그리고 UNVERIFIABLE — 근거 파일에 그 내용이 없어서 판정 자체를 못 한다는 뜻이에요. 위 예시의 둘째 줄처럼 프롬프트에 써 넣어야 나옵니다. 이 네 번째 값이 중요합니다. "확인 못 함" 을 "문제 없음" 과 섞지 않으려면 자기 이름을 가진 상태가 필요해요. 판정마다 재현 가능한 근거(어느 파일 몇 줄)를 붙이게 합니다.

넷째, 반드시 두 가지를 더 묻습니다(예시의 셋째 줄). 내가 놓친 것, 내가 과장한 것. 블로그 파이프라인 검증에서 "놓친 것" 으로 나온 항목 — 드라이런이 DB 를 두드리던 것, 같은 날 판정을 12시간 창으로 하던 것 — 은 제가 주장 목록에 넣지도 않은 것들이었어요. 주장한 것만 검사하면 주장하지 않은 것은 영영 안 나옵니다.

이 블로그의 발행 파이프라인도 같은 절차를 fact-check 노드로 씁니다.

갈리면 실측이 결론낸다 — Codex 가 틀린 네 건

Codex 도 틀립니다. 사흘 동안 세 차례, 네 건이었어요.

블로그 파이프라인 C3. Codex 는 "편집기 마크다운 확장에 tight-lists 가 있다" 고 판정했어요. 저는 편집기가 실제로 저장한 글 30편을 전수 대조했습니다. 30편 어디에도 그 속성이 없었어요. 문서와 실물이 갈리면 실물이 이깁니다. 기각.

로또 서비스 09-03. "predict 페이지 파일이 없어 7개 엔진의 출처가 불명" 이라는 지적이 왔는데, 출처는 홈 페이지의 엔진 목록이고 그건 8월 20일자 정본 문서에 적혀 있었어요. Codex 의 지적이 정본과 달랐습니다. 기각.

로또 서비스 09-02. 취약점 등급을 실제보다 낮게 매긴 것, 원래 있던 코드를 이번에 새로 생긴 결함으로 지적한 것. 둘 다 실측·재확인 후 반영하지 않았어요.

그리고 Codex 가 "못 본 것" 이 따로 있습니다. Codex 의 샌드박스는 네트워크와 임시 파일을 못 써서 DB 실측 행 수나 실제 렌더 결과는 전부 UNVERIFIABLE 로 돌아왔고, 그 항목은 제 쪽 실측이 근거가 됐어요. 검증자가 무엇을 닫고 무엇을 못 닫는지 적어 두지 않으면 검증자 자체가 새로운 거짓 녹색이 됩니다.

갈린 항목은 보고에서 숨기지 않습니다. 파이프라인 규칙에도 Codex 와 검토자가 갈리면 사람이 보는 체크포인트라고 박아 뒀어요. 갈렸다는 사실 자체가 정보입니다.

교훈

AI 에게 동의를 구하지 말고 반증을 시켜라. 그리고 반증하는 AI 도 틀린다 — 판정이 갈리면 제3의 의견이 아니라 실측이 결론을 낸다.

공유

댓글

0/2000

아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요.