AI에게 일을 시키고 제일 자주 겪는 일이 이겁니다. "완료했습니다"라고 하는데, 열어보면 안 돼 있어요.
거짓말을 하는 건 아닙니다. 자기 기준에서는 했거든요. 문제는 완료가 문장으로 오간다는 겁니다. 문장은 검증이 안 됩니다.
그래서 저희는 완료를 이걸로 받습니다.
2년 전엔 이 문제가 없었습니다
정확히는, 문제가 될 만큼 일을 안 맡겼습니다.
AI가 파일을 못 읽던 시절엔 코드를 채팅창에 복사해 넣고, 답을 다시 복사해 나왔습니다. 결과물이 손을 거치니까 안 된 걸 못 볼 수가 없었어요. 검증이 공짜였습니다.
지금은 다릅니다. AI가 파일을 직접 고치고, 명령어를 직접 돌리고, 수십 개를 한 번에 처리합니다. 편해진 만큼 결과물이 제 눈을 안 거치고 지나갑니다. "다 했습니다"가 위험해진 건 AI가 나빠져서가 아니라, 확인할 기회가 사라져서예요.
그래서 없어진 검증을 다시 만들어 넣어야 합니다.
이런 소식, 남들보다 먼저 받으실 분?
직접 돌려보고 되는 것만 골라 매주 보내드립니다. 광고성 하이프는 거릅니다.
게이트 — 완료의 조건을 미리 적는다
이 방식을 정리해둔 도구가 있습니다. 이름이 unlazy인데, 핵심은 단순합니다. 일을 시작하기 전에 "무엇이 되면 끝인가"를 파일로 적어둡니다.
한 칸은 세 줄입니다.
- [ ] 블로그 글이 라이브에서 열린다
CHECK: curl -s -o /dev/null -w "%{http_code}" https://.../my-post/
EXPECT: 200
목표 한 줄, 확인할 명령어 한 줄, 기대 출력 한 줄. 이게 전부입니다.
통과 조건도 명확합니다. 명령어가 종료 코드 0으로 끝나고, 출력이 기대와 맞아야 합니다. 둘 중 하나만 되면 안 된 겁니다. 체크 표시만 있고 근거가 없으면 그것도 안 된 걸로 셉니다.
제일 마음에 드는 규칙은 따로 있습니다. 못 하겠는 항목을 조용히 지우면 안 됩니다. 지우는 대신 "포기함 + 이유"를 적고, 최종 보고에 그대로 드러냅니다. 항목이 사라지는 게 제일 위험하거든요 — 아무도 그게 있었다는 걸 모르게 되니까요.
규모가 커지면 이 파일을 작업 단위로 쪼개서 트리로 만들고, 각 갈래마다 자기 게이트를 갖게 합니다. 다만 대부분의 일은 파일 하나면 충분합니다. 저희도 트리까지 가는 경우는 드뭅니다.
우리는 게이트를 도구로 굳혔습니다
매번 게이트를 새로 적는 대신, 반복되는 것들은 검사기로 만들어뒀습니다. 지금 넷입니다. 전부 사고가 먼저 있었고 검사기가 나중에 생겼습니다.
| 먼저 있었던 사고 | 그래서 만든 것 |
|---|---|
해시태그 #이 빠진 채로 5편이 나감 | 태그 검사 |
| 제휴 링크가 없는 글에 광고 고지가 붙어 있었음 — 허위표시 | 고지 검사 (양방향) |
| 이미지가 디스크엔 있는데 라이브에선 404 | SEO 검사 |
| 영상 키워드와 캡션 키워드가 갈려서 자동 답장이 안 걸림 | 렌더 전 차단 |
공통점이 보이실 겁니다. 넷 다 규칙은 이미 문서에 있었습니다. 적어뒀는데도 어긋났어요.
여기서 배운 게 이 글의 요지입니다. 문서에만 있고 기계가 안 지키는 규칙은 반드시 어긋납니다. 사람이 매번 기억해야 하는 규칙은 규칙이 아니라 희망사항입니다.
그래서 지금은 게시 전에 세 개를 돌립니다. 하나라도 0이 아니면 게시하지 않습니다.
node tools/check-seo.mjs <슬러그> --strict node tools/check-blog-tags.mjs node tools/check-ad-disclosure.mjs
그런데 검사기가 6일 동안 거짓말했습니다
이 얘기를 빼면 이 글이 반쪽입니다.
카드뉴스에 설치 명령어가 들어갔는지 보는 검사가 있었는데, 어느 날부터 모든 편에 경고가 떴습니다. 분명히 명령어를 넣었는데도요. 처음엔 검사가 좀 빡빡한가 보다 하고 넘겼습니다.
원인은 정규식 안에 백스페이스 한 바이트가 박혀 있던 것이었습니다. 화면에는 안 보입니다. 코드를 열 번 읽어도 못 찾아요. cat -A로 제어문자를 드러내고서야 보였습니다.
여섯 날 동안 그 검사는 항상 실패했습니다. 그런데 진짜 손해는 따로 있었어요 — 저희가 그 경고를 무시하는 데 익숙해졌다는 겁니다. 늘 뜨는 경고는 경고가 아니라 배경 소음이 됩니다.
그래서 규칙을 하나 더 만들었습니다. "없다"를 확인하는 검사는, 반드시 있어야 통과하는 걸 넣어서 실제로 통과하는지 봅니다. 검사가 통과하는 걸 한 번도 못 봤다면 그건 검증된 검사가 아닙니다. 그리고 정규식이 이상하게 굴면 cat -A부터 돌립니다.
조용히 실패하느니 시끄럽게 멈춥니다
같은 원리를 서버에도 넣었습니다. 예약 게시를 도는 서버가 있는데, 코드를 고치고 재시작을 안 하면 옛 코드가 계속 돕니다. 화면은 멀쩡하고, 다음 날 예약만 조용히 실패합니다.
지금은 디스크 코드와 실행 중인 코드가 다르면 실행 자체를 거부합니다. 게시가 안 되는 건 같지만, 이쪽은 즉시 보입니다.
완료 검사를 만들 때 계속 나오는 판단이 이겁니다. 실패를 감출 것인가, 드러낼 것인가. 감추는 쪽이 항상 더 매끄러워 보이는 게 함정입니다.
가져가세요 — 오늘 하나만 만든다면
도구를 깔 필요 없습니다. 파일 하나와 규칙 세 개면 시작됩니다.
1) 게이트 파일 — 일 시키기 전에 적습니다
# GATES.md - [ ] <무엇이 되면 끝인가 — 한 줄> CHECK: <확인할 명령어> EXPECT: <나와야 할 출력> # 규칙 # · 종료 코드 0 + EXPECT 일치, 둘 다여야 통과 # · 못 하겠으면 지우지 말고 "포기: <이유>" 를 남긴다 # · 근거 없는 체크 표시는 안 된 것으로 센다
2) 검사기 최소 뼈대 — 종료 코드만 있으면 됩니다
// check-something.mjs const problems = []; // ... 검사해서 problems.push("무엇이 왜 잘못됐는지") if (problems.length) { problems.forEach((p) => console.log("✕", p)); process.exit(1); // ← 이 한 줄이 핵심 } console.log("통과");
3) 게이트 쓸 때 지킬 것 셋
- 숫자를 받아 적지 말고 직접 잽니다. AI가 말한 수를 기대값에 넣으면, 그건 자기가 자기를 채점하는 겁니다.
- "없음"을 확인하는 검사는 있는 걸로 시험합니다. 통과하는 걸 한 번도 못 봤으면 검증 안 된 검사입니다.
- 성공을 뜻하는 말이 출력에 있게 만듭니다. "오류 없음"은 오류 메시지에도 들어갈 수 있습니다.
저희도 넷뿐입니다. 사고 하나에 검사기 하나씩 늘렸어요.
정리하면, AI를 못 믿어서 검사를 거는 게 아닙니다. 사람이 매번 확인하던 자리가 사라져서 그 자리를 다시 만드는 겁니다. 도구를 골라 쓰는 기준은 따로 정리해뒀고, 실제로 이 검사들을 통과시키며 만든 것들은 영상 분석과 이미지 생성 편에 있습니다.
카드뉴스로도 정리했습니다
인스타그램에 올린 10장입니다.
이 글은 클로드 코드로 혼자 일하는 법 — 6편 정리 시리즈의 한 편입니다.