AI가 만든 테스트는 일부러 숨긴 버그를 잡을 수 있을까?

정상 앱과 세 개의 결함 복사본을 향해 서로 다른 경로로 이어지는 테스트 카드들을 표현한 추상 일러스트
테스트 생성, 정상 기준 통과, 결함 구별, 변경 내구성은 서로 다른 확인 단계다. Grok Imagine을 사용해 생성한 AI 이미지입니다.

“테스트가 모두 통과했습니다.” 바이브 코딩을 하다 보면 이 문장이 안전 확인서처럼 들린다. 하지만 테스트도 결국 질문과 예상 답을 적어 둔 코드다. 누가 답을 썼는지, 그 답이 맞는지 확인하지 않았다면 초록색 체크는 무엇을 보장할까?

이번에는 Codex로 만든 작은 장바구니 앱과 내가 일부러 고장 낸 복사본을 사용했다. 실제 서비스나 개인정보는 쓰지 않았다. 실험의 질문도 좁혔다. 같은 AI가 공개 규칙만 볼 때와 정상 코드까지 볼 때 각각 만든 테스트는, 정상 앱을 통과하고 미리 숨긴 세 결함을 잡으며 이후 변경으로 예전 기능이 다시 고장 나는 회귀를 구별할 수 있을까?

이 글의 목차

초록색보다 먼저 볼 여섯 단계

테스트 결과는 한 숫자로 합치지 않았다.

  1. 테스트 파일이 만들어졌는가
  2. 실행할 수 있는가
  3. 정상 기준 앱에서 통과하는가
  4. 예상 답이 미리 만든 정답표와 맞는가
  5. 고장 낸 복사본에서 의도한 이유로 실패하는가
  6. 실제 화면 흐름도 같은 결론을 내는가

비슷한 구분은 연구에서도 나타난다. EvalPlus는 더 강한 테스트를 추가하자 기존 평가를 통과했던 생성 코드의 오류가 드러날 수 있음을 보였다. Meta의 TestGen-LLM은 사람이 쓴 기존 테스트를 개선하는 산업 환경에서 생성, 빌드, 안정적 통과, 커버리지 증가를 별도 단계로 다뤘다. 테스트 입력을 잘 고르는 일과 올바른 예상 출력을 만드는 일이 다르다는 UTGen/UTDebug의 지적도 이번 정답표 검사의 이유다. 이 논문들의 수치를 이번 장바구니 실험에 그대로 적용한 것은 아니다.

같은 모델, 다른 두 브리핑

2026년 9월 13일, codex-cli 0.153.4의 gpt-5.6-luna를 낮은 추론 설정으로 두 번 실행했다. 한 번은 공개 규칙과 함수 설명만 제공한 명세 우선 조건, 다른 한 번은 같은 자료에 정상 구현 코드도 더한 코드 참조 조건이었다. 모델과 프롬프트는 같았고 각 조건은 새 세션에서 한 번만 생성했다.

결함 목록, 비공개 정답표, 나중에 추가할 메모 기능은 생성기에서 숨겼다. 생성 작업은 임시 폴더에서만 진행했고 숨긴 자료가 있는 저장소 경로의 읽기와 쓰기를 운영체제 정책으로 막았다. 브라우저·웹 검색·플러그인도 껐다. 다만 기존 인증 서비스 연결은 사용했고, 시작 경고상 사용자 영역의 CLI 상태 정보 일부를 조회했다. 다른 사용자 영역 정보까지 완전히 격리됐는지는 독립적으로 증명하지 못했다. 처음 두 실행 방식은 모델을 돌리기 전에 격리 설정 문제로 실패했고, 그 기록도 남겼다. 세 번째 실행 방식에서만 두 조건이 끝까지 완료됐다.

규칙만 본 테스트는 정상 앱에서 실패했다

명세 우선 조건은 5개 테스트를 만들었다. 파일 문법 검사를 통과해 실행도 됐지만 정상 앱에서는 2개만 통과하고 3개가 실패했다. 여섯 단계 중 정상 앱 통과 단계에서 멈춘 셈이다.

계산은 대체로 맞았다. 문제는 쿠폰 입력값을 어떤 형태로 저장하느냐였다. 공개 규칙은 앞뒤 공백을 무시하고 대소문자 구분 없이 SAVE10을 비교하라고 했지만, 저장된 문자열까지 대문자로 바꾸거나 마지막 상품 삭제 때 지우라고 하지는 않았다. 테스트는 그 동작까지 예상 답에 넣었다. 정상 구현은 입력 원문을 보존했다.

따라서 이 테스트 묶음은 이번 실험의 규칙에 따라 무효(suite-invalid)로 분류했다. 정상 앱을 통과하지 못했기 때문이다. 고장 복사본에서 빨간불이 나더라도 버그를 잡았다고 셀 수 없어 세 결함 테스트는 진행하지 않았다. “테스트를 만들었다”와 “쓸 수 있는 예상 답을 만들었다”가 갈라진 순간이다.

코드까지 본 테스트는 숨겨 둔 세 결함을 각각 잡았다

코드 참조 조건은 8개를 만들었고 정상 앱에서 모두 통과했다. 편집이나 예상값 수정은 없었다. 다만 검사 문장 16개를 따로 분류하니 8개는 공개 규칙에서 독립적으로 계산할 수 있었고, 나머지 8개는 현재 데이터 전체 모양이나 구현에서 본 저장 방식에 묶여 있었다. 초록색만으로 모든 예상 답이 구현과 독립적이었다고 말할 수는 없다. 이후 한 번에 하나씩 숨겨 둔 결함을 넣었다.

  • 할인 전 금액으로 무료 배송을 판단한 D1: 배송비와 합계 테스트가 실패했다.
  • 쿠폰을 대소문자 구분하도록 바꾼 D2: sAvE10 할인 테스트가 실패했다.
  • 마지막 상품을 지운 뒤 이전 합계를 남긴 D3: 합계 0 초기화 테스트가 실패했다.

세 실패 모두 비공개 정답표의 의도한 값에서 발생했다. 화면 사전 점검은 정상 기준 흐름을 별도로 확인했다. 다만 이것은 AI가 낯선 현실의 버그를 세 개 발견했다는 뜻이 아니다. D1~D3는 생성 전에 골라 숨긴 알려진 규칙 결함이다. 코드를 보여 준 것이 더 좋은 테스트의 원인이었다고도 말할 수 없다. 규칙에 쓰이지 않은 저장 방식을 추측해야 했다는 점도 두 조건의 차이를 설명할 수 있다. 모델 하나, 프롬프트 하나, 실행 한 번의 관찰일 뿐이며, 세 건으로 일반적인 버그 탐지율이나 안전성을 계산할 수도 없다.

새 기능 앞에서는 ‘너무 정확한’ 테스트가 정상 변경에서도 깨졌다

코드 참조 조건의 테스트 8개를 그대로 둔 채 상품 메모 기능을 추가했다. 정상 변경본에서는 마지막 상품을 지우면 메모도 사라졌다. 회귀본 LR1은 금액은 모두 0으로 되돌리지만 삭제된 상품의 메모만 화면에 남겼다. 비공개 정답표와 실제 화면 흐름은 정상 변경본 통과, LR1 실패로 둘을 구별했다.

그러나 코드 참조 테스트는 둘 다 똑같이 8개 중 5개가 실패했다. 장바구니 상태 전체를 통째로 비교하도록 쓰여서, 새로 정상적으로 추가된 메모 항목(itemNote)이 있다는 것 자체를 오류로 본 탓이다. 정상 변경본부터 빨간색이므로 LR1을 잡았다고 인정할 수 없다. 여섯 단계 중 고장 구별 단계에서 판정할 수 없었고, 결과는 판정 불가다.

이 실패는 쓸모없는 잡음이 아니다. 현재 구조를 통째로 복사한 예상 답은 기존 결함에는 민감할 수 있지만, 정상적인 확장에도 부서질 수 있음을 보여 준다. 회귀 테스트는 빨간불을 켜는 것뿐 아니라 “왜 켜졌는지”를 구별해야 한다.

그래서 무엇을 확인해야 할까?

AI가 테스트를 써 줬다면 다음 다섯 질문부터 던져 볼 만하다.

  • 정상 기준 사례에서 먼저 통과하는가?
  • 예상값은 코드가 아니라 요구사항에서 독립적으로 계산했는가?
  • 일부러 고장 낸 동작에서 바로 그 동작을 검사하는 항목이 실패하는가?
  • 저장된 데이터 전체의 모양보다 사용자가 중요하게 보는 결과를 검사하는가?
  • 자동 테스트와 실제 화면 확인이 같은 결론을 내는가?

이번 생성 시간은 명세 우선 42.26초, 코드 참조 49.24초였다. 추가 구매는 없었다. 명령줄 도구가 토큰 사용 신호는 남겼지만 실행별 금액과 구독 할당량 차감은 보여 주지 않아 비용을 0원이라고 쓰지는 않았다. 테스트 파일은 평범한 .mjs 파일로 보존했다.

결론은 “AI 테스트를 믿지 말라”도 “코드를 보여 주면 해결된다”도 아니다. 통과 여부를 신뢰의 끝으로 보지 말고, 예상 답·고장 구별·변경 내구성·화면 흐름을 따로 확인해야 한다. 이번 작은 실험에서 명세 우선 테스트는 정상 앱 단계에서 무효가 됐다. 코드 참조 테스트는 선택해 숨긴 세 결함을 잡았지만, 정상적인 기능 추가에서는 데이터 모양에 묶인 검사가 먼저 깨져 이후 회귀를 판정하지 못했다. 이것은 한 실행의 두 함정이지, 일반적인 안전성이나 버그 탐지율이 아니다.

이 글은 AI를 활용해 자료 조사와 초안 작성을 보조하고, 작성자가 직접 검증·편집했습니다.

댓글

“AI가 만든 테스트는 일부러 숨긴 버그를 잡을 수 있을까?”에 대한 2개 응답

  1. […] EXPERIMENT NOTES · 15한국어로 읽기 →Test generation, clean-baseline passing, fault discrimination, and change resilience are separate […]

    좋아요

  2. […] 선행 글AI가 만든 테스트는 일부러 숨긴 버그를 잡을 수 있을까? […]

    좋아요

답글 남기기