돌아간다 ≠ 맞는다.
검증·테스트·평가 — 바이브 코딩의 속도를 지키는 안전장치
🤖 "요청하신 기능 구현을 완료했습니다. 모든 케이스에서 정상 동작하며, 기존 코드와도 완벽히 호환됩니다."
이 자신감, 어디까지 믿으시겠습니까?
def is_expired(token): """토큰 만료 여부를 반환""" now = datetime.now() return now > token.expires_at # 리뷰어: "깔끔하네요 👍" · 내 PC에서 테스트 통과
완전히 틀린 코드는 금방 걸립니다. 무서운 건 90% 맞는 코드 — 컴파일러도, 실행도 잡아주지 않습니다.
자동조종·내비게이션 시절부터 검증된 인간의 버그 — 기계가 말하면 덜 의심합니다.
매끄러운 설명 = 맞다는 착각. 말투는 품질 신호가 아닙니다. 폰트가 예쁜 보고서가 왠지 믿음직해 보이는 것과 같습니다.
동료 코드는 꼬치꼬치 의심하면서, AI 코드는 LGTM 👍 — 내가 안 짰는데 내 코드가 됩니다.
버그가 코드 리뷰가 아니라 보고서에서 발견됐습니다 — 검증은 미룰수록 비싸집니다.
디버깅의 절반은 "이 코드가 뭘 하는지" 알아내는 시간이었습니다.
검증을 설계한다 = 테스트·리뷰·CI를 생성보다 먼저 준비한다.
숫자는 직관을 위한 예시입니다 — 핵심은 검증 항이 0에 가까우면 전체가 무너진다는 것.
눈 → 실행 → 테스트 → 리뷰 → CI. 올라갈수록 사람 노력↓ 신뢰↑
실행 가능한 스펙 — 그리고 테스트를 고쳐버리는 AI(보상 해킹) 방어법
자기 리뷰 vs 신선한 눈 vs 사람 — 누가 어디를 보나
반복 실행되는 AI 작업(프롬프트·스킬·봇)의 품질 측정법
일회성·팀 도구·프로덕션 — 작업의 무게에 맞는 검증 강도
커밋 전 체크리스트 한 장 — 찍어 가시면 됩니다
눈으로만 읽는 검증이 가장 비싸고 가장 약합니다 — 사다리를 올라간 만큼 바이브 코딩의 속도가 살아납니다.
# ❌ 말로 하는 완료 보고 🤖 "수정했습니다. 이제 모든 테스트가 통과합니다. 완벽하게 동작해요!" # 실행해 보지도 않고 낙관하는 경우, # 정말로 있습니다
# ✅ 증거를 요구하는 요청 "pytest를 직접 실행하고 출력 전체를 보여줘. 실패하면 실패 로그 원문 그대로." "수정된 화면을 스크린샷으로 찍어서 보여줘." "마지막 명령의 exit code도 함께."
커밋하는 순간 lint·타입 체크·빠른 테스트 자동 실행 — 이상하면 커밋 자체를 거절합니다.
푸시할 때마다 깨끗한 환경에서 전체 테스트 — "내 PC에서는 되는데요"를 차단합니다.
PR마다 1차 리뷰를 자동으로 — 사람 리뷰어가 보기 전에 뻔한 문제를 걸러줍니다.
한 번 세팅해두면 이후의 모든 커밋이 공짜로 검증됩니다 — 세팅 자체도 에이전트에게 시키면 됩니다.
"이 입력엔 이 출력"— '맞음'의 정의를 산문이 아니라 코드로 적어둔 것.
사람이 코드를 안 읽어도 초록/빨강으로 판정 — AI에게 넘겨줄 수 있는 완료 기준이 됩니다.
다음 수정·다음 세션·다음 사람까지 지켜주는 회귀 방지선.
"먼저 이 기능의 실패하는 테스트부터 작성해줘. 구현은 아직 하지 마. 내가 테스트를 확인하면, 그때 통과할 때까지 구현해줘. 테스트 코드는 수정하지 말고."
에이전트 루프(실행→관찰→수정)에 명확한 목표 함수가 생깁니다 — 끝났는지를 사람이 아니라 기계가 판정.
# tests/test_yield.py — 사람이 확정한 테스트 def test_yield_calc(): assert calc_yield(lot42) == 98.2
# 🤖 조용히 이렇게 바꿔놨습니다 def test_yield_calc(): result = calc_yield(lot42) assert result is not None # 통과!
"테스트 파일은 절대 수정 금지. 통과 못 하면 못 한다고 보고해." — CLAUDE.md에 상주시키세요.
커밋 전 diff에 tests/가 보이면 일단 정지. 훅·CI로 테스트 파일 변경을 자동 경보할 수도 있습니다.
구현 전부를 못 읽어도 테스트 리뷰만은 포기하지 않기 — 채점 기준만 지키면 나머지는 기계가 지켜줍니다.
출제자와 응시자 분리 — 테스트를 짜는 세션과 구현하는 세션을 분리하면 담합이 어려워집니다.
# ❌ 두루뭉술한 요청 "테스트도 만들어줘." # → 성공 케이스 3개. 끝. # 자기가 짠 코드에 맞춘, # 절대 실패하지 않는 테스트
# ✅ 케이스를 명시하는 요청 "test_yield_calc에 다음을 포함해줘: - 경계값: 수율 0%·100%, wafer 0장 - 에러 경로: 측정값 누락·타입 오류 → 예외 확인 - 회귀: 이번에 고친 중복 lot 버그 재현 케이스 실패 메시지는 원인을 알 수 있게 써줘."
S3의 '단골 패턴 도감'이 그대로 테스트 케이스 목록이 됩니다.
방금 그 코드를 쓴 같은 컨텍스트. 자기 가정에 물들어 있어 같은 실수를 못 봅니다.
"내가 보기엔 완벽한데요."
새 세션·서브에이전트에 코드만 던져 리뷰. 오염 안 된 눈이 훨씬 잘 잡습니다.
컨텍스트 격리의 또 다른 쓸모
기계가 못 잡는 방향·의도의 최종 판단. 다음 장에서.
리뷰의 힘은 거리에서 나옵니다 — 쓴 사람과 보는 눈이 멀수록 잘 보입니다.
🧭 설계 방향이 맞나 · 🔐 보안 · 🏭 도메인 가정(수율·단위·장비) · 🚧 경계 조건
문법 · 스타일 · 포맷 · 오타 · 단순 버그 — 사람이 눈 버릴 곳이 아닙니다.
300줄짜리 PR 하나보다 30줄짜리 PR 열 개가 안전합니다. (github 세미나의 '작은 커밋'과 같은 이야기)
결과가 정해진 코드. 같은 입력 → 같은 정답. 일회성 스크립트·함수.
결과가 흔들리는 AI 작업(프롬프트·스킬·봇). "대체로 맞나"를 점수로 관리.
입력–기대출력 정답지. 바꿀 때마다 여기에 돌려봅니다.
고친 게 딴 걸 망가뜨렸는지 매번 자동 채점.
답을 AI가 채점 — 심판도 틀립니다. 사람 스팟체크 필수.
가볍게 · 기본 · 풀세트
전부 풀세트로 검증하면 그것도 낭비입니다 — 다이얼을 돌릴 줄 아는 게 실력.
☑️ 직접 실행해봤나 — 말로 된 보고 말고 증거
☑️ 경계값·에러 경로 테스트가 있나
☑️ 테스트가 해피 패스만 도는 건 아닌가
☑️ 신선한 눈(새 세션)으로 리뷰했나
☑️ 도메인 가정(단위·수율·장비)이 맞나
☑️ 이 작업 무게에 다이얼은 맞나
AI 코드의 위험은 '틀림'이 아니라 그럴듯하게 틀림입니다.
사다리를 올라갈수록 검증이 기계로 넘어가고, 사람은 편해집니다.
작업의 무게에 검증 강도를 맞추세요 — 전부 풀세트도, 전부 눈으로도 아닙니다.
질문을 남겨주세요 — 돌아간다 ≠ 맞는다 ⚖️