상세 컨텐츠

본문 제목

AI가 만든 테스트는 통과했는데 결과가 틀렸다 | 바이브 코딩 261편 중 6편 사례와 검증 3가지

서버·개발/코드 노트

by 사이 (SAI) 2026. 9. 30. 15:24

본문

728x90
반응형

AI 에이전트에게 스크립트를 맡기고 "테스트 전부 통과했습니다"라는 보고를 받으면 마음이 놓입니다. 그런데 며칠 뒤 결과를 열어 보니 숫자가 처음부터 틀려 있었다면 어떨까요.

개발자 블로거 워니즈가 9월 27일 이 경험을 숫자와 함께 공개했고, 긱뉴스에도 소개됐습니다. 에이전트가 만든 도구 세 개가 셀프테스트를 모두 통과했지만, 실제 데이터를 넣자 글 261편 가운데 6편만 맞았습니다. 왜 이런 일이 생기는지, 바이브 코딩을 계속하면서 무엇을 확인하면 되는지 원문을 바탕으로 정리하고 직접 돌려 본 예제를 붙였습니다.

바이브 코딩으로 만든 도구의 셀프테스트는 코드와 테스트를 같은 에이전트가 같은 가정으로 만들기 때문에, 가정이 틀리면 둘 다 함께 틀려도 통과한다. 워니즈의 사례에서 서치콘솔 원장 도구는 테스트를 통과했지만 실데이터에서 261편 중 6편만 매칭됐다. 원인은 표 셀의 innerText에 숨은 버튼 문구가 붙은 것이었다. 해결책은 테스트를 늘리는 것이 아니라 확인의 종류를 바꾸는 것이다. 변이 테스트로 테스트가 망가진 코드를 잡는지 보고, 만든 직후 실데이터로 한 번 돌려 기대 수치와 비교하고, 도구가 볼 수 없는 것은 "판별 불가"로 남긴다.

1. 무슨 일이 있었나: 초록불 세 개, 틀린 결과 세 개

왼쪽 모니터엔 초록 체크가 가득한 터미널, 오른쪽 모니터엔 대부분 빨간 행인 표가 떠 있고 실데이터라고 적힌 메모가 붙은 늦은 밤 개발자 책상

워니즈의 원문에 따르면 필자는 블로그 운영 자동화 도구 세 개를 에이전트에게 맡겼고, 셋 다 만든 날 셀프테스트를 통과했습니다. 그런데 9월 25~26일 실제 데이터로 돌리자 셋 다 틀렸습니다.

워니즈 블로그 원문 첫머리, 한 줄 요약과 무엇이 초록이었고 실데이터는 뭐라 했는지 정리한 목록
출처: 워니즈 블로그 「바이브 코딩 현실」 갈무리

도구 셀프테스트 실데이터 결과 틀린 가정
서치콘솔 원장(글별 노출·순위 기록) 통과 261편 중 6편만 매칭 표 첫 칸에는 URL만 있다
광고 점검(슬롯 수와 노출 비교) 통과, "렌더 실패" 판정 브라우저로 열어 보니 광고 정상 표시 슬롯이 노출보다 많으면 렌더 실패다
검색 수요 게이트(파생 검색어 20개 미만 차단) 파생어 65개로 통과 실제 주제어는 파생어 2개 적어 둔 키워드가 글의 검색어다

재구성한 예시 화면, 셀프테스트는 GATE_OK인데 실제 실행은 261편 중 6편만 매칭되고 키 값에 버튼 문구가 붙은 터미널
재구성한 예시 화면

첫 번째 사례가 가장 극적입니다. 표 셀의 글자를 innerText로 읽었더니 URL 뒤에 마우스를 올려야 보이는 버튼 문구("클립보드에 URL 복사 새 탭에서 열기 URL 검사")까지 붙어 와서 키가 깨졌습니다. innerText는 요소와 자손의 렌더된 글자를 돌려주는 속성인데, 이 사례에서는 셀 안 버튼 문구까지 함께 들어왔습니다(원문 필자도 CSS 수준의 원인은 확인하지 않았다고 밝혔습니다). 에이전트가 만든 테스트 입력은 깨끗한 URL만 든 상상 속 표였으니, 테스트는 몇 번을 돌려도 통과할 수밖에 없었습니다.

재구성한 예시 화면, 서치콘솔 실적 표에서 마우스를 올린 행에 URL 복사·새 탭·URL 검사 버튼이 나타나고 innerText에 그 문구가 함께 들어오는 모습
재구성한 예시 화면

URL만 뽑아내도록 고친 뒤에는 261편 중 100편이 이어졌고, 나머지는 3개월 동안 노출이 없어 표에 행이 없는 글이라 정상 범위로 봤다고 합니다.

2. 왜 테스트가 못 잡았나

코드와 테스트가 같은 가정을 공유해 함께 틀리는 구조를 설명한 도식

원문의 결론은 한 문장입니다. 틀린 것은 코드가 아니라 가정이었고, 그 가정을 코드와 테스트가 똑같이 품고 있었다는 것입니다. 같은 에이전트가 같은 대화에서 코드와 테스트 입력을 함께 만들면, 가정을 의심해 줄 두 번째 시선이 없습니다.

테스트가 확인하는 것 테스트가 확인하지 못하는 것
내가 만든 입력에서 코드가 기대값을 낸다 실제 입력이 내가 만든 입력과 같은 모양이다
분기와 계산이 의도대로 동작한다 판정 기준이 맞는 질문을 하고 있다
예전에 통과하던 경우가 지금도 통과한다 도구가 볼 수 없는 영역의 결론이 맞다

핵심 셀프테스트 통과는 "코드가 자기 가정대로 움직인다"는 뜻입니다. "결과가 맞다"는 뜻이 아닙니다. 원문 필자도 세 번 모두 테스트가 아니라 실데이터가 잡았다고 정리했습니다.

세 결함 모두 코드를 읽어 봐서는 멀쩡했다는 점도 중요합니다. 매칭 코드도, 산술도, 비교문도 틀리지 않았습니다. 문제는 코드 바깥의 세상이 예상과 달랐다는 것이라, 코드 리뷰를 더 꼼꼼히 해도 잡기 어렵습니다.

3. 검증 3가지: 테스트를 늘리지 말고 종류를 바꾼다

바이브 코딩 도구의 완료 조건 세 가지, 변이 테스트, 실데이터 1회 실행, 판별 불가 표시

확인 무엇을 막나 원문 사례
변이 테스트: 코드를 일부러 망가뜨려 테스트가 잡는지 본다 아무것도 확인하지 않는 테스트 테스트 자체의 품질
실데이터 1회: 만든 직후 실제 데이터로 돌리고 숫자를 눈으로 본다 입력 가정의 오류 서치콘솔 원장, 수요 게이트
판별 불가: 도구가 볼 수 없는 것은 단정하지 않는다 산술로 내린 원인 단정 광고 점검

변이 테스트는 코드에 작은 결함을 일부러 넣은 "변이"를 만들어, 테스트가 그걸 잡고 실패하는지 보는 방법입니다. 경계값 비교 하나만 바꿔도 테스트가 계속 통과한다면, 그 테스트는 그 줄을 사실상 검사하지 않고 있다는 뜻입니다. 원문의 예제(검색 수요 기준 20)와 같은 원리로 제가 무료 배송 예제를 따로 만들어 제 맥(Python 3.13.12)에서 돌려 봤습니다.

변이 테스트 예제: 무료 배송 기준 3만 원

# 무료 배송 기준: 3만 원 이상이면 무료
def free_shipping(won):        # 원래 코드
    return won >= 30000
def mutant(won):               # 일부러 망가뜨린 변이: >= 를 > 로
    return won > 30000

for tests in [(10000, 50000), (10000, 50000, 30000)]:
    caught = any(free_shipping(w) != mutant(w) for w in tests)
    print(tests, "잡힘" if caught else "못 잡음")

# 실행 결과 (Python 3.13)
# (10000, 50000) 못 잡음
# (10000, 50000, 30000) 잡힘

무료 배송 변이 테스트 예제를 실제로 실행한 터미널 결과, 경계값이 없으면 변이를 못 잡고 3만 원을 넣으면 잡힘
제 맥에서 직접 실행한 결과

1만 원과 5만 원만 넣은 테스트는 원래 코드와 변이가 같은 답을 내서 변이가 살아남습니다. 경계값 3만 원을 넣어야 비로소 둘이 갈립니다. 에이전트가 만든 테스트를 볼 때 경계값이 들어 있는지부터 확인하는 이유입니다. 자바는 PIT, 자바스크립트·C#은 Stryker 같은 도구로 변이를 자동으로 만들 수도 있습니다.

주의 변이 테스트는 입력 가정의 오류를 못 잡습니다. 서치콘솔 사례처럼 테스트 입력 자체가 실제와 다른 모양이면, 변이는 전부 잡혀도 테스트는 여전히 실제를 모릅니다. 그래서 실데이터 1회 실행이 따로 필요합니다.

4. 실데이터 1회, 이렇게 본다

검사원이 돋보기로 초록 체크 도장이 찍힌 상자 안을 들여다보고 옆 도장 선반에 판별 불가 꼬리표가 걸린 공장 일러스트

반응형

원문 필자가 강조한 요령은 "돌리기 전에 이 정도는 나와야 한다는 숫자를 먼저 적어 두기"입니다. 261편 중 적어도 수십 편은 이어져야 한다는 감각이 있었기 때문에 6이라는 숫자가 이상하게 보였다는 것입니다.

볼 숫자 확인 방법
매칭률 두 목록을 잇는 도구라면 몇 %가 이어졌는지 기대 범위와 비교
건수 수집 도구라면 0이나 1처럼 수상한 숫자가 아닌지
표본 한 줄 키로 쓰는 값 하나를 그대로 찍어 공백·덧붙은 문구가 없는지 눈으로 읽기

한 번 만난 실제 입력은 테스트 입력으로 떠서 셀프테스트에 넣어 둡니다. 그러면 같은 오염이 나중에 되돌아와도 테스트가 먼저 실패합니다. 기대 범위만큼은 에이전트가 아니라 사람이 결과를 보기 전에 정해야 한다는 것도 원문의 조언입니다. 결과를 본 뒤 정한 기대값은 그 결과에 맞춰지기 쉽기 때문입니다.

5. 에이전트에게 요청할 때 붙일 문장

매번 손으로 확인하면 바이브 코딩의 속도가 사라집니다. 원문이 제안한 세 문장을 요청 끝에 붙여, 확인 자체를 에이전트에게 맡기는 방법이 있습니다.

도구를 맡길 때 요청 끝에 붙이기

1. 셀프테스트를 만든 뒤 경계값과 조건을 바꾼 변이를 두세 개 넣어서
   테스트가 전부 잡는지 보여 주세요.
2. 만든 직후 실데이터로 한 번 돌리고 매칭률이나 건수를
   기대 범위(내가 적은 값: ___)와 함께 보고해 주세요.
3. 이 도구가 직접 볼 수 없는 것은 판정하지 말고
   "판별 불가"와 그 이유로 남겨 주세요.

제 판단으로는 세 번째 문장이 특히 과소평가돼 있습니다. 광고 점검 도구처럼 숫자 두 개 사이에 원인을 지어내는 판정이 기록에 남으면, 다음 자동화가 그 판정을 믿고 멀쩡한 곳을 고치러 갑니다. 저도 이 블로그를 자동화하면서 검증 단계를 따로 두는데, 원문처럼 "도구가 본 것"과 "도구가 추정한 것"을 나눠 적게 하는 게 가장 싸고 효과적인 안전장치라고 느낍니다.

긱뉴스에 소개된 바이브 코딩 현실 글 요약
출처: GeekNews 갈무리

원문 필자는 이 기록이 한 블로그의 도구 세 개에서 나온 것이라, 바이브 코딩 전반에서 같은 비율로 일어난다고 말할 근거는 없다고 선을 그었습니다. 수치는 사례로 읽고, 가져갈 것은 확인 방식입니다.

Q. 테스트 코드를 사람이 직접 짜면 해결되나요?

가정이 틀린 문제는 사람이 짜도 생깁니다. 핵심은 누가 짜느냐보다 실제 입력으로 한 번 돌려 보고, 테스트가 망가진 코드를 잡는지 확인하는 것입니다.

Q. 작은 일회용 스크립트에도 다 해야 하나요?

원문 필자도 한 번 돌리고 버릴 스크립트라면 변이 테스트까지 챙길 이유가 적다고 했습니다. 다만 결과를 계속 쌓아 쓰는 도구라면 실데이터 1회 확인은 꼭 하는 편이 좋습니다.

3줄 핵심 요약

  1. 에이전트가 코드와 테스트를 함께 만들면 같은 가정을 공유해, 틀려도 테스트가 통과한다(261편 중 6편 사례).
  2. 테스트를 늘리지 말고 종류를 바꾼다: 변이 테스트, 만든 직후 실데이터 1회, 볼 수 없는 것은 판별 불가.
  3. 기대 수치는 결과를 보기 전에 사람이 먼저 적어 둔다.

마치며

초록불은 끝이 아니라 출발선이라는 것이 이 사례의 교훈입니다. 오늘은 최근 에이전트에게 맡긴 스크립트 하나를 골라, 실제 데이터로 한 번 돌리고 결과 건수나 매칭률이 예상과 맞는지 눈으로 확인해 보세요.

NEXT READ

이어서 읽어 볼 글

01  AI가 짠 코드, 그림으로 읽는다 · 에이전트 코드 이해하기

02  클로드 코드 세션끼리 대화한다 · 검증을 다른 세션에 맡기기

#바이브코딩,#AI코딩,#테스트,#변이테스트,#클로드코드,#코덱스,#개발자,#자동화,#코드노트,#검증

728x90
반응형

관련글 더보기

댓글 영역