본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 16. 09:49

에이전트 평가(Evals)를 CI에 통합하거나, 아니면 평가라고 부르지 마세요

요약

에이전트의 품질 검사(Evals)를 단순한 사후 분석용 대시보드가 아닌, CI(지속적 통합) 파이프라인의 필수 게이트로 통합해야 함을 강조합니다. 프롬프트 수정이나 모델 업데이트로 인한 성능 저하를 방지하기 위해 자동화된 스코어러와 회귀 테스트 도입이 필요합니다.

핵심 포인트

  • 에이전트 평가는 머지(Merge)를 차단할 수 있는 CI 게이트 역할을 해야 함
  • 수동 평가는 프롬프트 수정이나 모델 업데이트 시 발생하는 회귀를 포착하지 못함
  • 결정론적 검사와 모델 기반 판정(Model-as-judge)을 포함한 스코어러 구축 필요
  • 에이전트의 비결정론적 특성을 고려하여 코드와 동일하게 CI에서 보호해야 함

제가 대화하는 대부분의 팀은 "평가(evals)"를 가지고 있습니다. 저는 그들에게 평가가 어디서 실행되는지 묻습니다. 답변은 거의 항상 같습니다. 노트북, 대시보드, 혹은 누군가가 상황이 좋지 않은 주가 지난 뒤에 업데이트하는 스프레드시트입니다. 그것은 평가 스위트(eval suite)가 아닙니다. 그것은 박물관입니다.

이 글의 나머지 부분 동안 제가 고수할 의견은 다음과 같습니다: 만약 당신의 에이전트 품질 검사가 머지(merge)를 차단할 수 없다면, 그것은 장식에 불과합니다. 평가의 전체 가치는 회귀(regression)가 사용자에게 도달하기 전에 이를 차단하는 데 있습니다. 금요일에 배포한 결과물에 대해 월요일에 읽는 점수는 사후 분석(postmortem)이지, 게이트(gate)가 아닙니다.

우리는 유닛 테스트(unit tests)로 코드를 게이트합니다. 우리는 계약 테스트(contract tests)로 API를 게이트합니다. 우리는 terraform plan으로 인프라를 게이트합니다. 그런데 스택에서 가장 비결정론적(non-deterministic)인 단일 요소 — 벤더가 새로운 체크포인트(checkpoint)를 배포할 때 조용히 동작을 바꿀 수 있는 LLM 에이전트 — 를 가져와서는, 단순히 느낌(vibes)만으로 통과시켜 버립니다. 이러한 비대칭성이 실제 버그입니다.

"로컬에서 실행하고 눈으로 확인하기"가 부패하는 이유

실패의 원인은 엔지니어들이 게을러서가 아닙니다. 수동 평가 실행은 정작 평가가 가장 필요한 상황에서 정확히 성능이 저하되기 때문입니다:

  • 프롬프트(Prompt) 수정은 무해해 보입니다. 톤(tone)에 대한 불만을 해결하기 위해 시스템 프롬프트의 한 줄을 수정했는데, 전혀 관련 없는 세 가지 작업에서 도구 선택(tool-selection) 정확도가 급락합니다. 전체 세트를 다시 실행하는 데 40분이 걸리는 고된 작업이기 때문에 아무도 다시 실행하지 않습니다.
  • 모델이 당신의 통제를 벗어나 움직입니다. gpt-4o를 고정(pin)해 두었지만, gpt-4o는 상수가 아닙니다 — 제공업체들은 체크포인트를 롤링(roll)합니다. 프롬프트는 동일하지만 동작은 어쨌든 변해버립니다.
  • 의존성(Dependencies)이 유출됩니다. 검색 인덱스(retrieval index)가 다시 임베딩(re-embedded)되거나, 도구의 API 필드 이름이 변경되면, 에이전트는 자신 있게 오래된 데이터를 인용하기 시작합니다. 이 중 그 어떤 것도 코드 차이(code diff)에는 나타나지 않습니다.

이 모든 상황은 코드 리뷰를 통과합니다. 이 모든 상황은 PR(Pull Request)에서 실행되는 회귀 스위트(regression suite)에 의해 포착됩니다. 해결책은 지루하지만 효과적입니다: 에이전트의 동작을 CI로 보호해야 하는 다른 모든 요소와 동일하게 취급하세요.

실제로 필요한 두 가지 측면

에이전트를 위한 CI 게이트에는 두 가지가 필요하지만, 사람들은 지속적으로 그중 하나만 구축합니다.

첫 번째는 **스코어러 (scorer)**입니다. 이는 고정된 입력 세트에 대한 에이전트의 출력을 받아 통과/실패 (pass/fail) 신호를 반환하는 도구입니다. 즉, 반드시 참이어야 하는 사항들에 대한 결정론적 검사 (유효한 JSON, 금지된 주장 없음, 필수 필드 존재 여부 등)와, 모호한 사항들에 대한 모델 기반 판정 (model-as-judge, 답변이 실제로 도움이 되었는지, 정책을 준수했는지 등)을 수행합니다. 저는 이 계층을 위해 agent-eval에 의존합니다. 케이스를 정의하고, 단언 (assertions)을 부착하여, process.exit에 전달할 수 있는 게이트 결과를 얻습니다.

두 번째는 팀들이 건너뛰는 부분이며, 바로 이 때문에 그들의 CI 게이트가 한 달도 안 되어 제거되곤 합니다. CI에서 케이스가 실패했을 때, 점수만으로는 아무런 쓸모가 없습니다. 새벽 2시에 17번 케이스의 judge_helpfulness: 0.4라는 수치는 실행 가능한 정보를 전혀 주지 못합니다. 여러분에게는 트레이스 (trace) 가 필요합니다. 어떤 모델 호출이 실행되었는지, 템플릿 보간 (template interpolation) 후에 실제로 해결된 프롬프트가 무엇이었는지, 에이전트가 어떤 도구를 선택했는지, 어떤 인자 (arguments)를 전달했는지, 그리고 어떤 원시 페이로드 (raw payload)가 돌아왔는지에 대한 정보 말입니다. AgentLens가 포착하는 것이 바로 이것입니다. 즉, agent-eval이 방금 플래그를 표시한 그 출력을 에이전트가 어떻게 도출했는지에 대한 전체 실행 트레이스입니다.

이 부분을 명심하십시오: agent-eval은 목적지를 점수화하고, AgentLens는 경로를 기록합니다. 트레이스가 없는 빨간색 에발 (eval)은 집의 지도도 없는 화재 경보기와 같습니다. 이 두 가지는 하나의 단위로 함께 움직여야 합니다. 디버깅할 수 없는 게이트는 팀이 무시하게 되는 게이트이기 때문입니다. 점수는 17번 케이스가 퇴보했다는 사실을 알려주지만, 트레이스는 프롬프트 수정이 도구 선택을 search_db에서 web_fetch로 변경했음을 알려주며, 이것이 답변이 오래된 정보를 제공하게 된 이유임을 알려줍니다. 하나의 숫자, 하나의 근본 원인, 동일한 워크플로우입니다.

실제 적용 사례

다음은 간소화된 CI 하네스 (harness) 예시입니다. 골든 입력 (Golden inputs)은 버전 관리 시스템에 저장되고, agent-eval이 각 출력을 점수화하며, AgentLens가 실행 과정을 감싸서 어떤 실패라도 트레이스를 포함하도록 합니다. 그리고 0이 아닌 종료 코드 (exit code)가 머지 (merge)를 차단합니다.

import { evaluate, assert } from "agent-eval";
import { trace, flush } from "agentlens";
import { runAgent } from "../src/agent";
...

이를 워크플로우 단계에 연결하면 완료됩니다:

# .github/workflows/agent-evals.yml
- name: Agent regression gate
  run: npx tsx evals/run.ts
...

실패 출력은 단순히 score: 0.4가 아닙니다. FAIL refund_policy_edge score=0.55, why=judge_policy와 같은 형태이며, 여기에 에이전트가 경로를 벗어난 정확한 도구 호출(tool call) 지점으로 연결되는 트레이스(trace) 링크가 포함됩니다. 점수와 트레이스가 결합된 형태와 점수만 있는 형태의 차이 — 이 차이가 엔지니어들이 게이트(gate)를 우회하지 않고 신뢰하게 만드는 핵심입니다.

비용을 낮추지 않으면 도태됩니다

느리거나 불안정한 게이트는 결국 비활성화되기 때문에, 두 가지 실질적인 가드레일(guardrails)을 제안합니다:

  1. 체크 항목의 계층화 (Tier your checks). 모든 PR(Pull Request)에는 결정론적 단언(deterministic assertions)을 실행하세요. 이는 비용이 들지 않으며 결코 불안정하지 않습니다. 모델을 판사로 사용하는 호출(model-as-judge calls)은 더 작은 핵심 세트에 대해서만 예약하거나, 전체 판사 스위트(judge suite)는 매일 밤 실행하고 저렴한 세트는 커밋마다 실행하세요. 200개의 케이스 세트에 대해 임계값이 낮은 판사를 사용하면 속도 제한(rate-limit)에 걸리고 게이트의 비용을 파산시킬 것입니다.
  2. 제품 모델과 함께 변하지 않는 판사를 고정(Pin)하세요. 만약 에이전트와 판사가 동일한 모델 버전이라면, 벤더의 체크포인트(checkpoint)가 두 모델을 동시에 이동시켜 회귀(regression)를 숨길 수 있습니다. 판사를 별도로 고정하고, 판사의 버전을 평가 계약(eval contract)의 일부로 취급하세요.

핵심 요구 사항

평가 점수를 단순히 검토하는 분석 데이터(analytics)로 취급하는 것을 멈추고, 빌드를 실패시키는 테스트로 취급하기 시작하세요. 기준은 "평가(evals)가 있는가"가 아닙니다. 기준은 **"잘못된 프롬프트 수정이 머지(merge)되지 못하게 막을 수 있는가"**입니다. 만약 대답이 '아니오'라면, 당신은 평가 스위트(eval suite)를 가진 것이 아니라, 결국 열어보지 않게 될 대시보드를 가진 것뿐입니다.

agent-eval로 출력을 점수화하세요. AgentLens로 경로를 캡처하세요. 회귀가 발생하면 0이 아닌 종료 코드(non-zero exit code)로 종료하세요. 그것이 이 규율(discipline)의 전부이며, PR 단계에서 드리프트(drift)를 잡아내는 것과 고객에게 이를 설명하는 것의 차이를 만듭니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0