LLM 응답 품질 평가 자동화: 골든셋·회귀 테스트·LLM-as-Judge 실무 구성
요약: LLM 기능은 배포 후에도 계속 흔들립니다. 모델이 바뀌고, 프롬프트가 바뀌고, 검색 인덱스가 바뀌면 어제 맞던 답이 오늘 틀릴 수 있습니다. 품질을 감으로 보지 않으려면 골든셋, 회귀 테스트, 규칙 기반 검사, LLM-as-Judge를 함께 구성해야 합니다.
왜 LLM 기능에는 회귀 테스트가 필요한가
일반 소프트웨어는 입력과 출력이 비교적 명확합니다. 같은 함수에 같은 값을 넣으면 같은 결과가 나와야 합니다. LLM 기능은 다릅니다. 같은 질문에도 표현이 조금씩 바뀌고, 모델 버전이나 temperature, 검색 결과, 시스템 프롬프트에 따라 답변이 달라집니다. 그래서 많은 팀이 “대충 좋아 보인다”는 감으로 배포합니다.
이 방식은 초기에 빠르지만 운영에서 위험합니다. 고객지원 답변이 정책과 다르게 나가거나, 문서 검색 봇이 오래된 가이드를 인용하거나, 코드 생성 기능이 보안 규칙을 어기면 문제가 됩니다. 더 큰 문제는 프롬프트를 조금 고쳤을 때 무엇이 좋아졌고 무엇이 나빠졌는지 알기 어렵다는 점입니다.
LLM 응답 품질 평가는 이 문제를 줄이기 위한 장치입니다. 목표는 완벽한 자동 채점이 아닙니다. 배포 전후로 나빠진 부분을 빨리 찾고, 중요한 오류를 사람에게 올리는 것입니다.
실무에서는 4개 층으로 나누는 것이 좋습니다.
- 골든셋
- 규칙 기반 검사
- LLM-as-Judge
- 운영 로그 샘플링
이 4개를 같이 쓰면 비용과 정확도의 균형을 맞출 수 있습니다.
골든셋: 자주 틀리면 안 되는 질문부터 모은다
골든셋은 LLM 기능을 테스트하기 위한 대표 입력과 기대 기준 모음입니다. 이름은 거창하지만 시작은 간단합니다. “이 질문에는 최소한 이 내용이 들어가야 한다”, “이 답변은 절대 하면 안 된다”를 모으면 됩니다.
좋은 골든셋은 실제 사용자 질문에서 출발합니다. 팀원이 상상한 예쁜 질문만 넣으면 안 됩니다. 실제 사용자는 짧게 묻고, 오타를 내고, 맥락을 생략하고, 화난 상태로 말합니다. 운영 로그에서 반복되는 질문, CS 이슈, 실패 사례를 모아야 합니다.
골든셋 항목은 다음 필드를 가지면 충분합니다.
{
"id": "refund-001",
"input": "구독 취소했는데 돈이 또 나갔어요",
"must_include": ["결제일 확인", "환불 정책", "고객센터 연결"],
"must_not_include": ["무조건 환불 가능", "계정 비밀번호 요청"],
"risk": "high",
"source": "cs_log",
"updated_at": "2026-07-15"
}
정답 문장을 하나로 고정할 필요는 없습니다. LLM은 표현이 다양합니다. 대신 포함해야 할 사실, 금지해야 할 주장, 필요한 다음 액션을 기준으로 잡는 편이 낫습니다.
골든셋은 처음부터 1,000개 만들 필요가 없습니다. 위험도가 높은 30개로 시작하세요. 고객지원이라면 환불, 해지, 개인정보, 장애, 결제 오류가 우선입니다. 개발자 도구라면 인증, 권한, 데이터 삭제, 배포, 보안 설정이 우선입니다.
규칙 기반 검사: 싸고 확실한 것은 코드로 잡는다
LLM 평가를 모두 LLM에게 맡기면 비용이 들고 결과도 흔들립니다. 먼저 코드로 잡을 수 있는 것은 코드로 잡아야 합니다. 규칙 기반 검사는 빠르고 싸고 재현 가능합니다.
예를 들어 다음 항목은 정규식이나 간단한 파서로 검사할 수 있습니다.
- 빈 답변 여부
- JSON 스키마 준수 여부
- 금지 문구 포함 여부
- URL 형식 오류
- 마크다운 헤딩 규칙
- 답변 길이 제한
- 필수 필드 누락
- 개인정보 패턴 노출
- 출처 링크 개수
RAG 답변이라면 “근거 문서 ID가 포함되어 있는지”도 코드로 볼 수 있습니다. 코드 생성 기능이라면 테스트 실행 결과, 타입체크, 린트 결과가 규칙 기반 검사입니다.
예시:
function validateAnswer(answer) {
const errors = []
if (answer.length < 50) errors.push('too_short')
if (/무조건 환불|100% 보장/.test(answer)) errors.push('unsafe_promise')
if (!answer.includes('확인')) errors.push('missing_verification_step')
if (/password|비밀번호를 알려/.test(answer)) errors.push('asks_for_password')
return errors
}
이런 검사는 단순하지만 효과가 큽니다. LLM-as-Judge를 쓰기 전에 명백한 실패를 걸러낼 수 있습니다.
LLM-as-Judge: 애매한 품질을 평가하되 기준을 좁힌다
LLM-as-Judge는 모델에게 다른 모델의 답변을 평가하게 하는 방식입니다. 유용하지만 남용하면 안 됩니다. “이 답변이 좋은가?”처럼 넓게 물으면 평가가 흔들립니다. 대신 기준을 좁혀야 합니다.
좋은 평가 질문은 구체적입니다.
- 질문에 직접 답했는가?
- 정책과 충돌하는 약속을 했는가?
- 근거 문서에 없는 내용을 사실처럼 말했는가?
- 사용자가 다음에 할 행동이 명확한가?
- 불확실한 내용에 확인 필요 표시를 했는가?
평가 출력도 짧고 구조화해야 합니다.
{
"score": 4,
"pass": true,
"failure_type": null,
"reason": "환불 가능 여부를 단정하지 않고 결제일 확인과 고객센터 연결을 안내함"
}
점수는 1~5 정도면 충분합니다. 100점 척도는 정밀해 보이지만 실제로는 일관성이 떨어집니다. 중요한 것은 pass/fail과 실패 유형입니다. 실패 유형을 모으면 개선 방향이 보입니다.
LLM-as-Judge에는 기준 답변이나 정책 문서를 같이 줘야 합니다. 평가 모델이 자체 상식으로 판단하면 위험합니다. 고객지원 정책, 보안 규칙, 제품 기능 범위를 근거로 판단하게 하세요.
회귀 테스트 파이프라인 구성
LLM 품질 평가는 CI처럼 돌리는 것이 좋습니다. 프롬프트, 모델, 검색 인덱스, 정책 문서가 바뀔 때마다 골든셋을 실행하고 이전 결과와 비교합니다.
기본 파이프라인은 다음과 같습니다.
변경 발생
→ 골든셋 입력 실행
→ 규칙 기반 검사
→ LLM-as-Judge 평가
→ 이전 버전과 비교
→ 고위험 실패가 있으면 배포 차단
→ 저위험 변화는 리포트로 남김
모든 실패가 배포 차단이어야 하는 것은 아닙니다. 위험도에 따라 나눠야 합니다.
- high: 보안, 결제, 개인정보, 법적 약속 → 배포 차단
- medium: 정책 누락, 근거 부족, 다음 액션 불명확 → 검토 필요
- low: 문체, 길이, 표현 차이 → 리포트만
이렇게 나누면 테스트가 너무 시끄러워지는 것을 막을 수 있습니다. 배포 차단이 너무 자주 걸리면 팀은 테스트를 끄고 싶어집니다. 중요한 실패만 막아야 합니다.
RAG 기능은 검색 품질과 답변 품질을 나눠 평가한다
문서 기반 챗봇이나 사내 검색 에이전트는 RAG 구조를 많이 씁니다. 이때 답변만 평가하면 원인을 알기 어렵습니다. 검색이 잘못된 문서를 가져왔는지, 모델이 가져온 문서를 잘못 해석했는지 분리해야 합니다.
RAG 평가는 최소 2단계로 나눕니다.
- Retrieval 평가: 필요한 문서가 top-k 안에 들어왔는가
- Generation 평가: 가져온 문서를 근거로 올바르게 답했는가
예를 들어 “API 키를 어떻게 제한하나요?”라는 질문에 보안 설정 문서가 검색되지 않았다면 검색 문제입니다. 문서는 검색됐는데 답변이 엉뚱하면 생성 문제입니다.
검색 평가는 문서 ID 기준으로 할 수 있습니다. 골든셋에 기대 문서 ID를 넣고 top-5 안에 있는지 봅니다. 생성 평가는 필수 포함 내용과 근거 인용 여부를 봅니다.
{
"input": "API 키를 특정 도메인에서만 쓰게 제한할 수 있나요?",
"expected_docs": ["security/api-key-restrictions"],
"must_include": ["도메인 제한", "서버 키 분리", "노출 시 폐기"]
}
이 구조를 만들면 검색 인덱스를 바꿨을 때도 품질을 비교할 수 있습니다.
운영 로그 샘플링: 테스트셋은 계속 늙는다
골든셋은 한 번 만들고 끝이 아닙니다. 제품이 바뀌고 사용자 질문이 바뀌면 테스트셋도 늙습니다. 운영 로그에서 새로운 실패를 계속 골든셋으로 올려야 합니다.
추천 흐름은 다음과 같습니다.
- 매주 운영 로그에서 AI 답변 100개를 샘플링합니다.
- 사용자 불만, 상담원 수정, 재질문이 많았던 세션을 우선 봅니다.
- 실패 유형을 태깅합니다.
- 반복되는 실패 5~10개를 골든셋에 추가합니다.
- 더 이상 의미 없는 오래된 항목은 제거하거나 업데이트합니다.
운영 로그에는 개인정보가 있을 수 있으므로 샘플링 전에 마스킹이 필요합니다. 평가용 데이터셋에는 원본 PII를 넣지 않는 것이 안전합니다.
지금 적용할 체크리스트
LLM 응답 품질 평가를 시작하려면 아래 순서로 진행하세요.
- 실제 사용자 질문에서 고위험 케이스 30개를 골든셋으로 만든다.
- 각 항목에 must_include, must_not_include, risk, source를 넣는다.
- 정규식, JSON 스키마, 길이 제한, 금지어 같은 규칙 기반 검사를 먼저 만든다.
- LLM-as-Judge는 “좋은가?”가 아니라 구체 기준 3~5개로 평가한다.
- 프롬프트나 모델이 바뀔 때 골든셋을 자동 실행한다.
- high risk 실패는 배포 차단, medium은 검토, low는 리포트로 나눈다.
- RAG는 검색 평가와 답변 평가를 분리한다.
- 운영 로그에서 반복 실패를 매주 골든셋에 추가한다.
LLM 기능은 한 번 배포했다고 끝나는 기능이 아닙니다. 모델과 데이터와 사용자 질문이 계속 바뀝니다. 감으로 품질을 보지 말고, 작은 골든셋과 자동 검증부터 붙이세요. 그래야 프롬프트를 고칠 때도 자신 있게 배포할 수 있습니다.