빌드가 통과했는데 품질이 떨어졌다
AI-First 팀에서 가장 위험한 실패는 조용한 실패다. 모델을 바꾸거나 시스템 프롬프트를 한 줄 수정했을 때 유닛 테스트는 여전히 초록색이고, JSON은 잘 파싱되고, 배포도 정상적으로 완료된다. 그런데 사용자 응답 품질은 슬그머니 나빠져 있다. 이 문제를 보통 팀이 아니라 유저가 먼저 발견한다.
이건 테스트가 없어서가 아니다. 테스트가 잘못된 것을 잡고 있기 때문이다. 기존 유닛 테스트는 '크래시'를 잡는다. 하지만 LLM의 실패 모드는 크래시가 아니라 품질 저하다. 타입 에러가 없어도, 스키마 검증을 통과해도, 모델 출력이 의도에서 멀어질 수 있다.
evalgate: 프롬프트 품질을 빌드 아티팩트처럼 다루는 접근
dev.to에서 소개된 evalgate는 이 문제를 정면으로 다룬다. 핵심 설계 철학은 단순하다. "이 프롬프트가 좋은가?"는 자동화된 게이트로 답할 수 없는 주관적 질문이다. 하지만 "이 프롬프트가 어제보다 나빠졌는가?"는 객관적으로 답할 수 있다. evalgate는 바로 이 두 번째 질문만 CI에게 묻는다.
작동 방식은 명확하다. YAML로 eval 스위트를 작성하고, 기준선(baseline)을 저장한 뒤, PR마다 현재 점수와 기준선의 델타를 비교한다. 점수가 허용 범위 이상 떨어지면 빌드가 실패한다. GitHub Action이 PR 코멘트로 케이스별 점수 변화표를 남긴다. 리뷰어는 코드 변경이 프롬프트 품질에 어떤 영향을 줬는지 머지 전에 확인할 수 있다.
스코어러는 10종으로 구성된다. exact-match, regex, json-schema 같은 결정론적 검증부터, embedding-similarity와 llm-judge로 의미적 유사도와 기준 기반 평가까지 커버한다. 여기에 latency와 cost 스코어러가 있다는 점이 흥미롭다. 프롬프트 품질이 올라갔어도 응답 지연이 두 배가 됐다면, 그것도 회귀다.
"오프라인에서 돌아간다"는 설계가 중요한 이유
CI 환경에서 LLM 품질 검증을 도입하려 할 때 가장 먼저 나오는 반론은 두 가지다. "API 키 관리가 번거롭다"와 "결과가 매번 달라서 신뢰할 수 없다".
evalgate는 deterministic mock provider를 내장해 이 두 문제를 동시에 해결한다. 실제 API를 호출하지 않고도 스위트를 실행하고, 기준선을 저장하고, 델타를 비교할 수 있다. llm-judge는 mock 모드에서 단어 겹침 기반 재현 가능한 점수를 계산하고, embedding-similarity는 로컬 해시 기반 임베딩으로 대체된다. 프로젝트 자체 테스트 67개가 모두 네트워크 없이 실행된다는 것이 이 설계의 신뢰성을 보여준다.
팀 CI 파이프라인에 도입할 때 비용 예측이 가능하다는 의미이기도 하다. 매 PR마다 실제 LLM을 호출하는 구조는 API 비용이 파이프라인 비용으로 전환되는 문제가 생긴다. mock-first 설계는 그 리스크를 제거한다.
다만 한계도 솔직하게 짚어야 한다. evalgate는 '점수가 움직였다'는 것을 알려줄 뿐, '새 점수가 옳다'는 것을 보장하지 않는다. 프롬프트가 실제로 개선됐는데 reference expectation이 낡아있으면 여전히 경고가 뜬다. 기준선과 평가 기준을 팀이 주기적으로 업데이트해야 하는 오너십은 사람 몫이다.
Postman의 변화가 같은 방향을 가리킨다
같은 흐름이 API 테스팅 영역에서도 일어나고 있다. dev.to에 소개된 Postman의 최근 변화 정리에서 가장 주목할 대목은 Postbot이다. 자연어 프롬프트로 테스트를 생성하고, 깨진 스크립트를 수리하고, 컬렉션 전체에 baseline 테스트를 일괄 추가한다.
그런데 이 글은 이것이 "진짜로 유용하고 진짜로 위험하다"고 정확하게 표현한다. Postbot은 현재 API가 반환하는 응답 기반으로 assertion을 작성한다. 지금 동작이 버그라면, 그 버그가 expected result가 된다. AI가 테스트를 생성하는 속도는 올라가지만, 그 테스트가 올바른 스펙을 검증하는지는 여전히 사람이 확인해야 한다.
이건 evalgate의 한계와 구조적으로 동일한 문제다. AI 도구가 검증을 자동화할수록, '무엇을 기준으로 검증할 것인가'를 정의하는 책임은 오히려 더 명확하게 사람에게 남는다.
AI-First 팀이 지금 당장 설계해야 할 것
두 사례가 함께 가리키는 방향은 하나다. AI가 코드를 짜는 속도에 맞춰, 검증 파이프라인도 AI-First로 재설계해야 한다. 그리고 그 재설계는 코드 레이어에서 멈추면 안 된다.
AI 코딩 어시스턴트가 생성한 코드는 기존 CI로 검증할 수 있다. 하지만 그 코드가 호출하는 프롬프트, 그 프롬프트가 만들어내는 LLM 출력의 품질은 기존 파이프라인이 전혀 보지 못하는 영역이다. evalgate 같은 도구가 필요한 이유가 여기 있다.
실행 가능한 시작점 세 가지:
- 프롬프트를 코드처럼 버전 관리하라. eval 스위트를 코드 옆에 YAML로 두고, 프롬프트 변경은 반드시 스위트 업데이트와 함께 PR로 올린다.
- baseline은 main 브랜치 기준으로 관리하라. 절대적 품질 기준을 정의하려 하지 말고, main 대비 델타를 보는 것만으로도 회귀를 잡을 수 있다.
- AI가 생성한 테스트는 스펙 기반으로 검토하라. Postbot이든 Copilot이든 AI가 만든 assertion은 현재 동작이 아닌 의도된 스펙에 맞게 한 번은 사람이 확인해야 한다.
검증의 속도를 개발의 속도와 맞추는 것이 테크 리드의 몫
AI-First 팀에서 속도는 이제 개발자 개인의 문제가 아니다. AI 어시스턴트가 코드를 만들고, 프롬프트가 동작을 정의하고, 에이전트가 실행하는 구조에서, 검증 파이프라인이 이 속도를 따라가지 못하면 팀 전체의 신뢰가 흔들린다.
프롬프트 회귀 테스트는 거창한 새 프레임워크가 아니다. 기존 CI에 evalgate compare를 한 줄 추가하는 것에서 시작할 수 있다. 팀이 LLM을 프로덕션에서 쓰고 있다면, 지금 당장 질문해볼 가치가 있다. 우리 CI는 프롬프트가 나빠진 걸 알고 있는가, 아니면 사용자가 먼저 알고 있는가.