코딩 에이전트의 87% 통과가 저장소 완성을 뜻하지 않는 이유
코딩 에이전트가 테스트의 87%를 통과했다면 거의 끝난 작업처럼 보인다. 그러나 남은 13%가 결제 금액 보존, 권한 경계, 직렬화의 왕복 일관성처럼 시스템 전체를 묶는 조건이라면 이야기가 달라진다. 쉬운 검사는 대부분 통과해도 제품을 안심하고 맡길 수 없는 상태일 수 있다.
2026년 8월 공개된 Vero는 이 간극을 형식 검증으로 측정한 저장소 단위 벤치마크다. 에이전트가 코드만 생성하는 것이 아니라, 그 코드가 명세를 만족한다는 Lean 4 증명까지 함께 만들게 한다. 가장 강한 설정은 코드와 증명을 함께 작성하는 모드에서 전체 명세의 87.3%를 통과했지만, 저장소를 완전히 해결한 비율은 43개 중 27개였다.
이 결과를 “에이전트가 아직 Lean을 잘 못한다”로만 읽으면 실무적인 교훈을 놓친다. 핵심은 부분 점수가 높아도 저장소의 완료 조건을 충족하지 못할 수 있고, 검증하기 어려운 구현을 일찍 고정하면 남은 시간 동안 증명만 반복하게 된다는 것이다. 일반적인 AI 코딩 워크플로에서도 완료 기준, 검증 환경, 실패 보고 방식을 다시 설계할 이유가 여기에 있다.
Vero는 함수 하나가 아니라 저장소 전체를 묻는다
기존의 검증 코드 생성 평가는 함수 하나의 구현이나, 이미 주어진 구현에 대한 증명 생성에 집중하는 경우가 많았다. Vero는 서로 의존하는 여러 모듈에서 구현 선택과 증명 선택이 끝까지 일관되는지를 본다.
벤치마크는 Python, Dafny, Verus, Coq의 실제 저장소에서 가져온 43개 사례를 Lean 4 프로젝트로 재구성했다. 공식 저장소의 현재 인벤토리에는 평가 대상 API 743개와 명세 2,705개가 기록돼 있다. 각 사례에는 고정된 API 인터페이스, 사람이 정리한 형식 명세, 참조 구현이 있다.
평가는 두 모드로 나뉜다.
- 증명 전용(proof-only): 참조 구현은 주어지고, 에이전트가 모든 명세의 증명을 작성한다.
- 코드+증명(code-and-proof): 참조 구현의 본문을 숨기고, 에이전트가 API 구현과 그 구현에 대한 증명을 모두 작성한다.
둘의 차이는 작업량만이 아니다. 코드+증명 모드에서는 에이전트가 같은 명세를 만족하는 더 단순한 알고리즘을 선택할 수 있다. 반대로 구현을 바꾸면 여러 모듈의 증명이 함께 깨질 수 있다. 즉, “먼저 코드를 만든 뒤 마지막에 검증을 붙인다”는 직선형 흐름보다 구현과 증명을 함께 설계하는 능력을 요구한다.
87.3%와 27개가 동시에 맞는 이유
가장 강한 GPT-5.5의 xhigh 설정은 코드+증명 모드에서 명세의 87.3%를 통과했다. 하지만 43개 저장소 중 모든 명세를 닫은 저장소는 27개였다. 증명 전용 모드의 완전 해결은 25개였다. 네 가지 에이전트 설정과 두 모드를 합친 여덟 구성 가운데 어느 것도 완전히 해결하지 못한 사례도 10개였다.
Vero의 코드+증명 모드에서 가장 강한 설정은 명세 2,705개 중 87.3%를 통과했지만, 모든 명세를 닫아 완전히 해결한 저장소는 43개 중 27개였다. 두 지표의 분모와 판정 단위가 다르다. 출처: arxiv.org/abs/2608.13522v1.
모순이 아니다. 저장소 하나에 명세가 여러 개 있고, 그중 하나라도 미해결이면 그 명세가 잡아야 할 버그 가능성이 남기 때문에 Vero는 완전 해결로 세지 않는다. 연구진은 부분 통과율이 쉬운 명세를 많이 풀어 부풀려질 수 있다고 지적한다.
실패도 무작위로 퍼져 있지 않았다. 출력이 모든 관련 입력을 빠짐없이 포함하는지 묻는 ‘존재·포괄성’ 명세의 실패율은 47.1%로 가장 높았다. 제공된 도우미 정의를 사용하거나 같은 API를 반복 호출해야 하는 명세도 더 어려웠다. 한 번의 함수 호출을 몇 가지 예로 시험하는 것보다, 전체 입력 범위와 반복 동작을 관통하는 불변식을 세우는 일이 병목이 된 셈이다.
이 차이는 일반 개발에서도 익숙하다. 테스트 100개 중 95개를 통과했다는 숫자는 남은 5개가 무엇인지 말해주지 않는다. UI 문구 테스트 5개와 권한 상승 방지 테스트 5개는 같은 무게가 아니다. 코딩 에이전트의 진행률을 단일 통과율로만 표시하면 가장 어려우면서 중요한 실패를 평균 속에 숨길 수 있다.
증명에 막혔을 때 코드를 다시 보지 않았다
Vero의 실행 궤적에서 에이전트들은 대체로 실행 전반부에 구현 크기를 확정하고, 이후에는 증명 텍스트를 늘렸다. 가장 강한 설정도 중간 이후에는 구현보다 증명 작업에 집중했다. 연구진은 에이전트가 구현을 바꿀 수 있는 지렛대로 보기보다 고정된 발판처럼 다루는 경향이 있다고 해석했다.
그런데 코드+증명 모드의 장점은 바로 구현을 바꿀 자유다. 연구진이 수동 검토한 사례 중에는 에이전트가 참조 알고리즘을 같은 명세를 만족하는 더 단순한 구현으로 교체해 증명을 쉽게 만든 경우가 있었다. 성능을 일부 포기하더라도 검증 가능성을 얻은 선택이었다.
실무에서는 이 지점을 실패 정책으로 명시하는 편이 좋다.
- 같은 검증 의무에서 일정 횟수 이상 실패하면 프롬프트만 바꾸지 않는다.
- 구현이 불필요하게 상태를 많이 만들거나 분기가 깊은지 확인한다.
- 불변식을 함수 경계에서 표현할 수 있도록 API와 데이터 구조를 조정한다.
- 최적화된 구현과 검증하기 쉬운 기준 구현을 분리할지 검토한다.
- 구현을 바꾼 뒤 전체 검증을 깨끗한 환경에서 다시 실행한다.
중요한 것은 “증명 도구를 쓰라”가 아니라, 검증 실패가 구현 재설계로 되돌아가는 경로를 워크플로에 넣는 것이다. 테스트가 계속 깨질 때 테스트 코드만 고치는 대신 설계를 다시 보는 것과 같은 원리다.
명세가 틀렸다는 증거도 성공적인 산출물이다
형식 명세라고 해서 자동으로 옳아지는 것은 아니다. 빠진 전제, 서로 충돌하는 조건, 참조 구현과 맞지 않는 명세가 있을 수 있다. 실제로 Vero는 큐레이션 과정에서 9개 사례에 걸친 38개의 결함을 감사 메커니즘으로 찾아 수정했다고 보고한다.
Vero가 흥미로운 이유는 이런 상황을 단순한 에이전트 실패로 처리하지 않는다는 데 있다. 에이전트는 다음과 같은 부정적 증거를 기계 검증 가능한 형태로 제출할 수 있다.
- 참조 구현이 특정 명세를 위반한다.
- 어떤 구현도 특정 명세를 만족할 수 없다.
- 각각은 만족 가능해 보여도 명세 집합 전체는 동시에 만족할 수 없다.
이 구조를 일반 개발 워크플로로 옮기면, 에이전트에게 “무조건 고쳐라”만 요구하지 않고 다음 종료 상태를 구분하게 할 수 있다.
- 구현 결함
- 테스트 또는 명세 결함
- 요구사항끼리의 충돌
- 재현 불가
- 검증 예산 안에서 미해결
각 상태에는 로그, 최소 재현, 반례, 충돌하는 요구사항 같은 증거를 붙인다. 그러면 에이전트가 잘못된 테스트를 억지로 만족시키거나, 요구사항 충돌을 임의로 해석해 숨기는 위험을 줄일 수 있다.
에이전트의 결과물이 아니라 검증 환경을 신뢰하라
Vero는 에이전트가 수정한 프로젝트를 그대로 채점하지 않는다. 수정이 허용된 영역만 추출해 원본 벤치마크로 새 Lean 프로젝트를 만들고, 다시 컴파일한다. 신뢰하지 않는 공리나 증명을 무력화하는 선언도 검사한다.
일반 코드 저장소에서 Lean의 공리 허용 목록을 그대로 쓸 필요는 없다. 하지만 원리는 적용할 수 있다.
- 에이전트가 작업한 디렉터리와 최종 검증 디렉터리를 분리한다.
- 잠금 파일과 의존성을 고정한 깨끗한 체크아웃에서 빌드한다.
- 테스트 비활성화, 스냅샷 무조건 갱신, 예외 삼키기 같은 우회 변경을 별도 검사한다.
- 에이전트가 생성한 캐시나 로컬 설정에 성공 여부가 의존하지 않는지 확인한다.
- 통과한 검사 이름뿐 아니라 실행하지 못한 검사와 제외된 범위도 기록한다.
즉, “에이전트가 테스트가 통과했다고 말했다”가 아니라 신뢰할 수 있는 하네스가 허용된 변경만 가져와 다시 검증했다를 완료 조건으로 삼아야 한다.
지금 저장소에 적용할 최소 체크리스트
형식 검증을 전면 도입하지 않아도 Vero의 평가 원리는 사용할 수 있다.
1. 전체 완료와 부분 진척을 분리한다
대시보드에 테스트 통과율만 두지 말고, 필수 불변식과 릴리스 차단 조건이 모두 충족됐는지 별도로 표시한다. 핵심 조건 하나가 실패하면 ‘거의 완료’가 아니라 ‘미완료’다.
2. 요구사항마다 증거를 연결한다
각 요구사항에 테스트, 타입 검사, 정적 분석, 속성 기반 테스트, 수동 리뷰 중 어떤 증거가 필요한지 지정한다. 검증되지 않은 요구사항 수를 숨기지 않는다.
3. 실패를 구현과 명세로 나눠 조사한다
에이전트가 막혔을 때 코드 수정만 반복하지 않게 한다. 테스트의 전제, 요구사항 충돌, 참조 데이터 오류를 보고할 수 있는 템플릿을 제공한다.
4. 검증하기 쉬운 구현을 선택할 여지를 준다
성능 목표가 허용한다면 복잡한 최적화보다 단순하고 불변식이 선명한 구현을 먼저 만든다. 최적화는 기준 구현과 동치성을 비교할 수 있을 때 진행한다.
5. 깨끗한 환경에서 최종 판정을 내린다
에이전트의 작업 세션 밖에서 의존성을 다시 설치하고 빌드·테스트·정적 검사를 실행한다. 검증 하네스 변경은 제품 코드와 분리해 리뷰한다.
결론
Vero가 보여준 가장 중요한 사실은 코딩 에이전트의 평균 능력이 아니라 완료의 비선형성이다. 전체 명세의 87.3%를 통과해도 저장소 단위 완전 해결은 27개에 그쳤다. 남은 일부는 쉬운 작업의 연장이 아니라, 공유 불변식과 긴 증명 사슬을 요구하는 가장 어려운 부분이었다.
따라서 코딩 에이전트를 평가할 때는 “몇 퍼센트 통과했는가” 다음에 반드시 “무엇이 남았고, 그 실패가 전체 시스템에서 어떤 위험을 남기는가”를 물어야 한다. 구현 결함뿐 아니라 명세 결함을 보고할 통로를 만들고, 검증 실패가 구현 재설계로 되돌아가게 하며, 마지막 판정은 깨끗한 하네스에서 내려야 한다.
형식 증명은 명세가 포착한 버그 범위에 대해서만 보장을 준다. 하지만 바로 그 한계까지 명시적으로 드러낸다는 점에서, 테스트 통과율 하나보다 더 정직한 완료 기준을 설계하는 데 좋은 모델이 된다.
원문 및 출처
- Vero 논문, arXiv:2608.13522v1
- Vero 공식 저장소와 벤치마크 인벤토리
- Lean 4 공식 학습 문서, Theorem Proving in Lean 4

댓글
댓글 쓰기