코드는 통과했는데, 에이전트는 왜 망가지는가
월요일에 모든 유닛 테스트를 통과한 AI 에이전트가 수요일 프로덕션에서 환각을 일으킨다. 코드는 바뀌지 않았다. 모델이 바뀌었다. 이게 기존 CI/CD 파이프라인이 AI 에이전트 앞에서 무력해지는 핵심 이유다.
dev.to에 공개된 실전 패턴 분석에 따르면, AI 에이전트의 동작을 결정하는 요소는 코드 + 모델 + 프롬프트 + 도구 설정 + 검색 컨텍스트 다섯 가지다. 기존 CI/CD가 git으로 버전 관리하는 건 이 중 코드 하나뿐이다. 나머지 네 가지는 테스트 없이 배포된다. claude-3-5-sonnet-20241022를 claude-3-5-sonnet-20250514로 바꾸면 모든 출력이 달라지지만, git diff는 아무것도 보여주지 않는다.
이건 단순한 이론적 위험이 아니다. 같은 맥락에서 GitHub Copilot이 생성한 updateEmployer 함수가 MongoDB의 ReplaceOneAsync를 잘못 사용해 DB 필드를 조용히 밀어버린 사례가 이미 보고됐다. 유닛 테스트를 통과하고 프로덕션에 배포됐고, 손상은 나중에야 발견됐다. '조용한 실패(silent failure)'가 AI 에이전트 배포의 가장 위험한 패턴인 이유다.
에이전트 스택 전체를 버전 관리하라
첫 번째 처방은 에이전트 매니페스트다. 코드 SHA뿐 아니라 모델 ID, 프롬프트 해시, 도구 버전, 벡터 스토어 스냅샷 ID를 하나의 파일에 묶고, 이 전체를 핑거프린트로 관리한다. 예를 들어 a3f9c2e1b0d4 같은 핑거프린트가 배포 단위가 된다. 같은 코드에 프롬프트만 다르면 다른 핑거프린트를 갖는다.
이 방식의 실질적 가치는 롤백과 디버깅에 있다. 프로덕션 품질이 떨어졌을 때 두 핑거프린트를 diff하면 어떤 컴포넌트가 바뀌었는지 즉시 파악할 수 있다. "코드는 같은데 왜 달라졌지?"가 더 이상 미스터리가 아니게 된다. 롤백 타깃도 git SHA가 아니라 특정 핑거프린트가 된다.
Eval Gate: 코드 실행 여부가 아니라 출력 정확성을 막아라
두 번째 패턴은 파이프라인에 Eval Gate를 추가하는 것이다. 유닛 테스트는 코드가 에러 없이 실행되는지 확인한다. Eval Gate는 에이전트의 출력이 실제로 올바른지 확인한다. 이 둘은 완전히 다른 문제다.
실제로 DeepEval 같은 도구를 pytest에 통합하면 기존 CI 워크플로우에서 AnswerRelevancyMetric(답변 관련성)과 HallucinationMetric(환각 감지)을 자동으로 검증할 수 있다. GitHub Actions 기준으로 유닛 테스트 → Eval Gate 순서로 파이프라인을 구성하면, 에이전트가 환각을 일으키거나 엉뚱한 답변을 반환할 때 배포 전에 파이프라인이 실패한다. 수동 리뷰 없이.
전통 소프트웨어 테스트와 AI 테스트의 차이는 구조적이다. 전통 테스트는 assert result == 42 같은 확정적 검증이지만, AI 테스트는 "이 출력의 톤이 전문적인가?"처럼 확률적·의미론적 검증이 필요하다. 입력도, 출력도 자연어이기 때문에 회귀 테스트 설계 방식 자체가 달라져야 한다.
CI/CD 파이프라인에 AI 테스트를 계층화하는 방법
세 번째로 현장에서 바로 쓸 수 있는 구조가 있다. 티어드 테스트 접근법이다.
- Pre-commit: 정규표현식·키워드 기반의 빠른 휴리스틱 테스트
- PR 단계: 핵심 기능과 안전성을 검증하는 골든셋 서브셋
- 야간/전체 스위트: LLM-as-a-Judge 방식의 심층 평가와 고부하 성능 테스트
비용 문제를 직접 짚자. LLM-as-a-Judge 평가는 모든 PR마다 돌리기엔 토큰 비용이 크다. 이걸 야간 배치로 분리하고, PR 단계에서는 핵심 케이스만 돌리는 게 현실적인 설계다. 속도와 철저함 사이의 균형을 파이프라인 구조 자체로 강제하는 것이다.
결정론적 Docker 이미지와 Shadow 배포
네 번째 패턴은 결정론적 Docker 이미지다. 표준 파이썬 이미지는 빌드할 때마다 최신 의존성을 당겨온다. AI 에이전트에서 "최신"은 에이전트 동작이 조용히 바뀐다는 의미다. requirements.txt 대신 pip-compile로 생성한 requirements.lock을 써서 트랜지티브 의존성까지 전부 고정해야 한다. 언제 어디서 빌드해도 동일한 이미지가 나와야 한다.
다섯 번째는 Shadow 배포다. 카나리 배포(신규 버전에 트래픽 5% 분배)는 상태 없는 API에는 적합하지만, 에이전트에는 위험하다. 에이전트의 잘못된 응답 하나가 도구 호출을 통해 다운스트림 액션을 연쇄 트리거할 수 있기 때문이다. Shadow 배포는 새 버전이 실제 요청을 처리하되 응답은 사용자에게 반환하지 않고, 기존 버전과 출력을 오프라인에서 비교하는 방식이다. 실 트래픽으로 검증하면서 사용자 영향은 제로.
팀에 즉시 적용하려면
이 패턴들을 팀에 도입할 때 가장 먼저 해결해야 할 것은 "우리 에이전트의 동작을 무엇이 결정하는지 목록을 만들었는가" 다. 지금 당장 에이전트 매니페스트 파일 하나를 만들어 코드 SHA, 모델 ID, 프롬프트 파일 해시를 기록하는 것부터 시작하라. Eval Gate는 그다음이다.
솔직히 말하면, 팀 학습 곡선이 있다. DeepEval 통합과 골든셋 테스트 케이스 설계는 기존 유닛 테스트 작성과 감각이 다르다. "뭘 테스트해야 하는가"보다 "어떤 출력을 허용 불가로 볼 것인가"를 팀이 먼저 합의해야 한다. 이 합의 없이 도구만 붙이면 eval 결과를 해석하는 기준이 사람마다 달라진다.
전망: AI 에이전트가 많아질수록 배포 품질의 기준이 바뀐다
AI 에이전트를 팀에 더 많이 붙일수록, 코드 품질 게이트만으로는 배포 안전성을 보장할 수 없는 영역이 넓어진다. 모델 버전 업데이트, 프롬프트 개선, RAG 파이프라인 변경—이 모든 게 사실상 새로운 배포다. 기존 CI/CD는 이 변화를 감지조차 못 한다.
결국 AI-First 팀의 배포 파이프라인은 코드 변경을 추적하는 것에서 에이전트 동작 변화를 추적하는 것으로 진화해야 한다. 핑거프린트 기반 버전 관리, Eval Gate, 결정론적 빌드, Shadow 배포—이 네 가지가 그 진화의 실행 단위다. 지금 팀의 파이프라인이 에이전트의 프롬프트 변경을 추적하고 있지 않다면, 이미 테스트되지 않은 배포가 프로덕션에 나가고 있다는 뜻이다.