요약
AI에게 문서를 만들게 하고 “검증했습니다”라는 보고를 받으면, 그 보고는 주장이지 증거가 아니다. 만든 쪽은 자기가 본 것만 본다.
이 글은 수정 권한이 없는 검증 전담 AI를 따로 두는 방법과, 그렇게 해서 실제로 잡아낸 세 가지 사고를 기록한 것이다. 그중 하나는 마을 회의 참석자 실명 12명이 문서에 숨어 있다가 배포 직전에 걸린 건이었다.
왜 이 기술인가
AI에게 일을 시키면 보통 이런 보고가 온다.
검증 완료했습니다. 표 12개 전부 폭 규격 내, 셀 272개 전량 12pt, 구값 잔존 0건입니다.
숫자가 구체적이라 믿게 된다. 그런데 이 보고에서 “구값 잔존 0건”은 사실이 아니었다. 폐기된 날짜가 두 파일에 그대로 살아 있었다.
왜 못 찾았나. 검색 패턴이 "9. 28"(마침표 뒤 공백)만 찾았는데 실제 문자열은 "9.28"(공백 없음)이었다. 자기가 짠 검색식의 사각지대는 자기가 못 본다. 같은 머리로 다시 봐도 같은 곳을 안 본다.
그래서 필요한 것은 “더 꼼꼼한 AI”가 아니라 다른 눈이다.
검증 AI에게 반드시 넣어야 할 두 가지
1. 수정 권한을 주지 않는다
검증자가 직접 고칠 수 있으면 “찾았다 → 조용히 고쳤다”가 되면서 사고가 기록에 안 남는다. 같은 실수가 왜 반복되는지 알 수 없게 된다.
찾아서 보고하고, 고치는 것은 만든 쪽에게 돌려보내는 구조로 만든다. Claude Code라면 에이전트 정의에서 tools에 Write/Edit를 빼면 된다.
---
name: 검증담당
description: 산출물을 독립 재검증한다. 직접 수정하지 않고 판정과 근거만 보고한다.
tools: Read, Bash, Glob, Grep, WebSearch
---
## 절대 하지 않는 일
- 산출물을 수정하지 않는다. 오류를 찾으면 고치지 말고 보고한다.
- 발행·배포·전송·삭제 같은 되돌릴 수 없는 작업을 하지 않는다.2. “보고서를 믿지 마라”를 제1원칙으로 박는다
이 한 줄이 검증의 전부다.
## 제1원칙 — 보고서를 믿지 마라
"완료했습니다", "검증 통과했습니다"는 주장일 뿐 증거가 아니다.
반드시 실제 파일을 직접 열고, 직접 명령을 돌려 확인해라.
보고 내용을 그대로 옮겨 적는 순간 너는 아무 일도 하지 않은 것이다.여기에 “검증하지 못한 것”을 반드시 보고하게 한다. 안 본 것을 통과로 적지 않게 하는 장치다.
실제로 무엇이 걸렸나
사례 1 — 문서 미리보기에 남은 실명 12명
한글 문서(.hwpx)를 기존 문서를 템플릿 삼아 만들었다. 본문도 서식도 깨끗했다. 그런데 파일 안 Preview/ 폴더에 템플릿 원본 1쪽이 그대로 남아 있었다. 마을 개발위원회 회의록이었고, 참석자 실명 12명과 안건이 통째로 들어 있었다.
이게 왜 위험한가. 윈도 탐색기 미리보기 창과 파일 검색 인덱스에 그대로 뜬다. 문서를 외부에 보내면 내부 회의록 첫 장이 딸려 간다.
검증 AI가 잡은 방법은 단순했다. 파일 안 항목을 전부 꺼내 템플릿 원본과 md5를 비교한 것이다.
547f8738… 템플릿/Preview/PrvText.txt
547f8738… 산출물/Preview/PrvText.txt ← 바이트 단위로 동일
만든 쪽은 본문 XML만 검사했다. 나머지 항목을 안 봤다.
사례 2 — 고치다가 생긴 새 문제
Preview를 지웠더니 이번엔 문서 목차 파일이 삭제된 파일을 계속 가리켰다. 만든 쪽은 “참조가 없는 걸 먼저 확인했다”며 세 개 파일을 근거로 댔는데, 참조를 가진 파일은 그 목록에 없었다.
여기서 배운 것: 근거로 제시된 목록은 그 목록이 완전한지부터 따져야 한다. “확인했다”는 말보다 “무엇을 확인했는지”가 중요하고, 그보다 “무엇을 안 봤는지”가 더 중요하다.
사례 3 — 조용히 사라진 쟁점
2차 수정에서 “확정이 필요한 사항” 목록의 한 줄이 사라졌다. 예산 재산정 문제였는데, 해결된 게 아니라 그냥 없어졌다. 검증 AI가 이전 판본과 표를 통째로 대조해 찾아냈다.
해결되지 않은 문제가 목록에서만 빠지는 것은 문서 작업에서 흔한 사고다. 판본 대조 없이는 안 보인다.
단계별 따라하기
1단계 — 검증 AI에게 줄 브리핑을 쓴다
핵심은 만든 쪽의 주장을 항목별로 나열하는 것이다. “검증해줘”라고만 하면 뭘 봐야 할지 모른다.
## 만든 쪽이 한 주장 — 전부 재현해서 확인해라 (믿지 말 것)
1. node --check 통과, UTF-8 BOM 없음
2. 총 29문항 / 7섹션
3. 표 12개 전부 폭 46490 이하
4. 셀 272개 전량 12pt
...
그리고 의심 가는 곳을 콕 집어준다.
## 특별히 파고들 것
- 3·4번은 내가 직접 확인하지 않고 그대로 전달했다. 직접 세어 숫자가 맞는지 확인해라.
- 값을 바꾼 뒤 구값이 남았는지 전량 검색해라.
- 1차본 대비 조용히 사라진 내용이 있는지 대조해라.
2단계 — 판정 형식을 정해둔다
합격 / 조건부 합격 / 불합격으로 먼저 말하게 한다. 그다음 발견 사항, 확인했으나 문제없던 항목(검사 범위 명시), 검증하지 못한 것, 반려할 일 순서.
“확인했으나 문제없던 항목”을 쓰게 하는 이유는, 검사 범위를 밝혀야 판정에 무게가 생기기 때문이다. 아무것도 못 찾았다는 말은 “안 찾았다”와 구분되어야 한다.
3단계 — 발견되면 만든 쪽에 반려한다
검증 AI가 고치지 않으므로, 발견 사항을 만든 쪽에게 돌려보낸다. 이때 왜 놓쳤는지도 같이 묻는다.
실제로 물었더니 이런 답이 왔다.
제 패턴이
"9. 28"(공백 포함)만 찾았습니다. 실제 문자열은"9.28"이라 전부 빠져나갔습니다. 또 본문만 검사하고 나머지 항목을 보지 않았습니다.
이 답이 있어야 검사 방식 자체를 고칠 수 있다. 증상만 고치면 다음에 또 터진다.
4단계 — 재검증한다. 단, 범위를 좁혀서
고친 뒤 다시 검증한다. 이때 이미 전수 확인한 항목을 또 파게 하면 시간만 든다. 이번 수정이 건드린 자리와 그 파급만 보게 한다.
실제로 이 단계에서 “고치다가 생긴 새 문제”(사례 2)가 나왔다. 수정은 그 자체가 새로운 위험이라는 걸 기억할 것.
교훈
“검증했다”는 보고를 받으면 무엇을 안 봤는지 물어라. 이번 일에서 만든 쪽은 “한글로 직접 열어보는 검증은 생략했습니다”라고 정직하게 밝혔다. 정직했지만, 그 생략이 무엇을 가리는지(→ 미리보기 미갱신) 아무도 확인하지 않았다. 실명 유출은 정확히 그 틈에 있었다.
숫자가 구체적인 보고일수록 검증이 필요하다. “셀 272개 전량 12pt” 같은 보고는 믿음직해 보인다. 실제로 이 숫자들은 다 맞았다. 그런데 같은 보고서의 “구값 0건”은 틀렸다. 맞는 항목과 틀린 항목이 같은 문장에 섞여 있다.
한 번에 끝나지 않는다. 이번엔 검증을 네 번 돌렸다. 1차에서 중대 2건, 2차에서 수정 중 생긴 회귀 1건, 3차에서 새 회귀 없음 확인, 4차에서 합격. 지치는 일이지만, 실명 12명이 담긴 문서를 외부에 보내는 것보다는 낫다.
도구에 박힌 결함은 산출물 결함보다 무겁다. 재발 방지로 공용 스크립트를 고쳤는데 거기서 회귀가 나왔다. 산출물 하나가 아니라 앞으로 만들 모든 문서가 영향을 받는 자리였다. 공용 도구를 건드렸으면 그것만 따로 검증 항목으로 분리할 것.
참고
- 사고 유형별 체크리스트는 각자 조직에서 실제로 터진 것으로 채우는 게 좋다. 일반론으로 쓰면 아무것도 안 걸린다.
- 검증 AI 이름은 헷갈리지 않게 지을 것. 비슷한 이름이 있으면 호출할 때 섞인다.
- 사람이 해야만 하는 확인은 남는다. 이번에도 한글 프로그램으로 직접 열어보는 검증은 끝까지 사람 몫이었다.
문서 정리 = 데카(deka2026)