AI가 만든 테스트는 전부 통과했지만, 코드에는 버그가 남아있었다
목차
개요
AI가 생성한 테스트가 모두 통과했는데, 실제 코드에는 버그가 그대로 남아있었다. Doodledapp 팀이 17개의 스마트 컨트랙트를 변환하면서 겪은 이 경험은 AI 기반 테스팅의 구조적 한계를 보여준다. 핵심 원인은 Ground Truth(기준 정답)의 부재다. AI는 “코드가 실제로 하는 동작”을 검증할 뿐, “코드가 해야 하는 동작”을 검증하지 못한다.
배경
Doodledapp 팀은 OpenZeppelin ERC-20/721, Solmate, Uniswap V2/V3 등 17개의 실제 스마트 컨트랙트를 AI 검증 루프로 테스트했다. 첫 실행에서 모든 테스트가 통과했다. 하지만 코드에는 실제 버그가 존재했다.
2024년 앨버타 대학교 연구에 따르면, LLM이 생성한 테스트는 “명세된 동작이 아닌 구현된 동작”을 기준으로 작성된다. 코드에서 modifier가 누락되면, AI는 그 누락된 상태를 정상으로 인식하고 테스트를 작성한다. 결과적으로 테스트는 통과하지만 버그를 보호하는 역설이 발생한다.
핵심 내용
Ground Truth 문제란
AI가 코드를 읽고 테스트를 작성하면, “이 코드가 자신의 구현을 따르는가?”만 확인하게 된다. 외부 기준점 없이 코드 자체를 검증하는 테스트는 단순히 거울 역할을 할 뿐이다. 버그가 있는 코드를 기반으로 테스트를 생성하면, 그 버그를 정상 동작으로 간주하는 테스트가 만들어진다.
Goodhart의 법칙이 여기에도 적용된다. “측정 기준이 목표가 되면, 더 이상 좋은 측정이 아니다.” 테스트 통과율이 목표가 되면, 테스트 자체가 의미를 잃는다.
Round-trip 검증의 함정
Doodledapp 팀이 처음 시도한 검증 방식은 round-trip 테스트였다.
- 원본 Solidity 코드를 1차 변환
- 변환 결과를 다시 2차 변환
- 두 결과를 비교하여 일치하면 통과
이 방식의 치명적 결함은 원본 계약이 첫 번째 패스 이후 사라진다는 점이다. 1차 변환에서 modifier를 누락시키면, 그 손상된 결과가 새로운 기준이 된다. 2차 변환도 같은 손상을 반복하므로 두 결과는 일치한다. 이는 멱등성(idempotency)만 증명할 뿐, 정확성(correctness)을 보장하지 않는다.
AST 기반 비교로 해결
팀은 새로운 검증 방식을 도입했다.
- 원본 Solidity 코드를 AST(Abstract Syntax Tree)로 파싱하여 참조점으로 보존
- 비주얼 플로우로 변환 후 다시 Solidity로 역변환
- 역변환 결과도 AST로 파싱
- 두 AST를 구조 수준에서 비교
- 불일치 발견 시 AI에게 diff 분석을 요청
이 방식의 핵심 개선점은 세 가지다.
첫째, 문자열 비교를 중단했다. 포맷팅, 주석, 공백 같은 비본질적 차이를 무시하고 논리 구조 자체를 검증한다.
둘째, AI의 역할이 바뀌었다. 테스트를 작성하는 대신 구조 차이를 분석하는 역할로 전환했다.
셋째, 참조점이 코드 자체가 아닌 원본 계약이 되었다. AI가 “무엇이 맞는지”를 외부 기준과 비교할 수 있게 되었다.
발견된 실제 버그 유형
AST 기반 비교를 적용한 후 발견된 버그 유형은 다음과 같다.
| 버그 유형 | 설명 |
|---|---|
| 누락된 modifier | 접근 제어 수정자가 변환 과정에서 사라짐 |
| 연산자 우선순위 오류 | 복잡한 표현식에서 연산 순서가 변경됨 |
| 잘못된 루프 경계 | 반복문의 시작/종료 조건이 변경됨 |
| 손실된 데이터 위치 | storage/memory 등 데이터 위치 지정이 누락됨 |
| 상속 체인 오류 | 컨트랙트 간 상속 관계가 깨짐 |
의미와 시사점
이 사례에서 얻을 수 있는 핵심 교훈은 테스트 검증에 대한 관점 전환이다.
“테스트가 통과했는가?”보다 중요한 질문은 “테스트가 무엇과 비교하는가?”이다. 코드 자체와 비교하는 테스트는 거울에 불과하다. 알려진 정답과 비교하는 테스트만이 유용한 검증이 된다.
의미 있는 테스트란 코드를 보기 전에 올바른 결과가 무엇인지 아는 테스트다. AI를 테스트에 활용할 때는 반드시 외부 참조점(원본 명세, 사양서 등)을 함께 제공해야 한다. 코드 기반 단독 검증은 순환 논리에 빠질 위험이 있다.
AI의 강점과 약점을 구분하는 것도 중요하다. AI는 “코드가 하는 일”을 이해하는 데 뛰어나다. 하지만 “코드가 해야 할 일”은 외부 참조점이 제공되지 않는 한 알 수 없다.
결론
AI가 생성한 테스트의 통과율 100%는 코드의 정확성을 보장하지 않는다. Ground Truth 없이 AI에게 테스트를 맡기면, 버그를 보호하는 테스트가 만들어질 수 있다. 해결책은 AI의 역할을 재정의하는 것이다. 테스트 작성자가 아닌 구조 분석자로 활용하고, 반드시 외부 기준점과의 비교를 통해 검증해야 한다. Doodledapp 팀의 AST 기반 비교 방식은 이 원칙을 실현한 좋은 사례다.