LLM 평가, 왜 이렇게 어려운 걸까 — 지표와 전략 정리
LLM 기반 서비스를 만들다 보면 어느 순간 "이거 평가를 어떻게 하지?"라는 질문에 부딪힌다. 기존 소프트웨어는 테스트 케이스를 작성하면 되지만, LLM은 같은 입력에 다른 출력이 나온다. 정답이 하나가 아니라 여러 개일 수 있고, 심지어 "좋은 답변"의 기준도 사람마다 다르다.
솔직히 나도 처음에는 "프롬프트 잘 쓰면 되는 거 아닌가?"라고 가볍게 생각했다. 평가를 대충 넘기면 나중에 진짜 고생한다는 걸 알게 된 건, 프로덕션에 올린 뒤 유저 피드백이 쏟아지고 나서였다.
LLM은 예측 불가능하다, 진짜로
전통적인 소프트웨어는 결정론적이다. f(x) = y라면 언제 호출하든 y가 나온다. 그런데 LLM은 다르다. 같은 프롬프트를 넣어도 temperature 설정에 따라, 심지어 같은 temperature에서도 토큰 샘플링 과정의 확률적 특성 때문에 미묘하게 다른 답변이 나올 수 있다.
이게 왜 문제가 되냐면, "어제까지 잘 되던 게 오늘 갑자기 이상하게 동작한다"는 상황이 실제로 일어난다. 프롬프트를 하나도 안 바꿨는데 말이다. 모델 제공사가 조용히 모델을 업데이트하는 경우도 있고, 추론 서버의 배칭 방식이 결과에 영향을 주는 경우도 있다.
여기에 할루시네이션 문제가 겹친다. LLM은 자신 있는 말투로 거짓 정보를 내놓는다. 산업 보고서에 따르면 할루시네이션 관련 사고로 연간 2억 5천만 달러 이상의 손실이 발생하고 있다고 한다. 숫자가 정확한지는 모르겠지만, 문제의 심각성을 보여주기엔 충분하다.
안정적인 서비스를 원한다면 평가는 선택이 아니다
"데모에서는 잘 되는데 프로덕션에서 망한다"는 LLM 서비스의 클래식한 패턴이다. 데모에서 보여준 몇 가지 시나리오는 체리피킹된 결과일 뿐이고, 실제 유저는 우리가 상상하지 못한 방식으로 질문을 던진다.
체계적인 평가 없이 서비스를 운영하면 생기는 일들:
- 모델이나 프롬프트를 수정했을 때 성능이 좋아진 건지 나빠진 건지 알 수 없다
- 특정 유형의 질문에서 반복적으로 실패하는데 그걸 모른다
- 유저 불만이 누적되고 나서야 문제를 인지한다
결국 평가는 "품질을 측정해서 개선하기 위한 것"이다. 측정할 수 없으면 개선할 수도 없다. 당연한 말 같지만, LLM 프로젝트에서 평가를 체계적으로 하는 팀은 생각보다 많지 않다.
LLM 평가가 유독 어려운 이유
기존 ML 모델 평가와 비교해보면 LLM 평가의 특수한 난점이 드러난다.
정답이 하나가 아니다. "서울의 수도는?"처럼 명확한 질문은 괜찮은데, "좋은 마케팅 전략을 제안해줘"라는 요청에 대한 정답은 무한히 많다. 어떤 답변이 더 "좋은" 건지 판단하는 것 자체가 주관적이다.
평가도 LLM한테 시키면 되지 않나? LLM-as-a-Judge라는 접근이 있는데, 강력한 모델(GPT-4 클래스)로 다른 모델의 출력을 평가하는 방식이다. 인간 평가자와 80~90% 정도 일치한다는 연구 결과도 있지만, 문제가 없는 건 아니다. LLM 판정자는 긴 답변을 선호하는 경향이 있고, 제시 순서에 따라 점수가 달라지기도 한다. 전문 지식이 필요한 영역(의료, 법률 등)에서는 전문가와의 일치율이 64~68%까지 떨어진다는 보고도 있다.
비용과 속도의 트레이드오프. 인간 평가가 가장 정확하지만 느리고 비싸다. 자동 지표는 빠르고 저렴하지만 뉘앙스를 놓친다. 이 사이에서 적절한 균형을 찾는 것이 매번 고민이다.
체계적인 평가, 어떻게 접근할까
내 경험상 괜찮았던 접근법은 이렇다.
먼저 평가 데이터셋을 만든다. 실제 유저 질문을 기반으로 50~100개 정도의 테스트 케이스를 모은다. 여기에 기대하는 답변(또는 답변에 반드시 포함되어야 할 정보)을 함께 적어둔다. 이건 한 번 만들면 끝이 아니라, 유저 피드백에서 발견된 실패 케이스를 계속 추가하면서 키워나가야 한다.
자동 지표와 인간 평가를 조합한다. CI/CD 파이프라인에 자동 지표를 붙여서 매번 돌리고, 중요한 릴리스 전에는 샘플링해서 인간이 직접 확인한다. 자동 지표가 갑자기 떨어지면 뭔가 문제가 생긴 신호로 활용하는 식이다.
평가를 한 번이 아니라 지속적으로 한다. 모델이 바뀌고, 데이터가 바뀌고, 유저 행동이 바뀐다. 주기적으로 평가를 돌리고 추세를 모니터링하는 게 중요하다.
검색 정확도를 측정하는 지표들
RAG 시스템이라면 검색 단계의 품질을 먼저 봐야 한다. 검색이 엉망이면 아무리 좋은 LLM을 써도 좋은 답변이 나올 수 없다.
| 지표 | 의미 | 직관적 해석 |
|---|---|---|
| Precision@K | 검색된 K개 중 관련 문서 비율 | "가져온 것 중에 쓸 만한 게 얼마나 되나?" |
| Recall@K | 전체 관련 문서 중 검색된 비율 | "있어야 할 문서를 다 찾았나?" |
| MRR (Mean Reciprocal Rank) | 첫 번째 관련 문서의 순위 역수 평균 | "관련 문서가 얼마나 위에 나오나?" |
| NDCG | 이상적 순위 대비 실제 순위의 품질 | "순서까지 제대로 됐나?" |
Precision과 Recall의 균형이 중요하다. Precision만 높이면 확실한 문서만 가져오니까 빠트리는 정보가 생기고, Recall만 높이면 관련 없는 문서까지 마구 가져와서 LLM의 컨텍스트 윈도우를 낭비한다. 상황에 따라 어느 쪽에 가중치를 둘지가 달라지는데, 의료나 법률처럼 빠트림이 위험한 도메인은 Recall을, 빠른 응답이 중요한 챗봇은 Precision을 우선하는 경향이 있다.
응답 품질, 어떻게 숫자로 만들까
응답의 질을 측정하는 지표는 크게 세 세대로 나눌 수 있다.
1세대: n-gram 기반 지표. BLEU와 ROUGE가 대표적이다. BLEU는 생성 텍스트의 n-gram이 참조 텍스트에 얼마나 등장하는지(precision 중심), ROUGE는 참조 텍스트의 n-gram이 생성 텍스트에 얼마나 포함되는지(recall 중심)를 본다. 빠르고 결정론적이라는 장점이 있지만, "의미적으로 같은데 표현이 다른" 경우를 전혀 잡아내지 못한다. "서울은 한국의 수도이다"와 "대한민국의 수도는 서울이다"가 낮은 점수를 받을 수 있다는 거다.
2세대: 임베딩 기반 지표. BERTScore가 여기에 속한다. BERT 임베딩으로 토큰 간 코사인 유사도를 계산해서, 표면적으로 다르지만 의미적으로 유사한 표현을 잡아낸다. n-gram 지표보다 인간 판단과의 상관관계가 높다.
3세대: LLM 기반 평가. 앞서 말한 LLM-as-a-Judge 방식이다. 평가 기준(rubric)을 주고 LLM에게 점수를 매기게 한다. 뉘앙스를 가장 잘 잡지만, 비결정론적이고 비용이 든다.
솔직히 실무에서는 1세대 지표만으로 충분한 경우가 거의 없다. 최소한 BERTScore 정도는 쓰는 게 좋고, 중요한 평가에는 LLM-as-a-Judge를 병행하는 게 요즘 추세다.
사용자 경험 지표도 빠트리면 안 된다
모델 성능만 좋으면 뭐하나, 유저가 불편하면 소용없다.
**응답 지연 시간(Latency)**은 생각보다 중요하다. Time to First Token(TTFT), 토큰 간 지연(Inter-Token Latency), 총 생성 시간으로 나눠서 측정하는데, 재미있는 건 평균 지연보다 일관성이 더 중요하다는 점이다. 가끔 빠르고 가끔 느린 것보다, 항상 적당히 빠른 게 유저 만족도에 더 좋다. 스트리밍 방식으로 토큰이 하나씩 출력되면 체감 대기시간이 줄어드는 효과도 있다.
**태스크 완료율(Task Completion Rate)**은 에이전트 시스템에서 특히 중요해지고 있다. LLM이 단순히 텍스트를 생성하는 것을 넘어서 도구를 호출하고, 단계별로 작업을 수행하는 시대가 됐으니까. "유저가 원하는 결과를 실제로 얻었는가?"를 직접적으로 보여주는 지표다.
유저 만족도는 결국 설문이나 thumbs up/down 같은 명시적 피드백, 그리고 재방문율이나 대화 길이 같은 암묵적 시그널로 측정한다. 오프라인 지표(BLEU, BERTScore)와 실제 유저 만족도 사이에 괴리가 없는지 주기적으로 확인하는 게 중요하다.
RAG 시스템이라면 반드시 봐야 할 것들
RAG 파이프라인은 검색기(Retriever)와 생성기(Generator)가 합쳐진 구조라서, 각각을 따로 평가하고 합쳐서도 평가해야 한다. RAGAS 프레임워크가 이 영역에서 가장 많이 언급되는데, 핵심 지표를 정리하면 이렇다.
| 지표 | 평가 대상 | 무엇을 보나 |
|---|---|---|
| Faithfulness | 생성기 | 답변이 검색된 문맥에 기반하는가? 지어낸 건 없는가? |
| Answer Relevancy | 생성기 | 답변이 질문에 관련 있는가? |
| Context Precision | 검색기 | 검색된 문맥 중 관련 있는 것의 비율은? |
| Context Recall | 검색기 | 답변에 필요한 정보를 빠트리지 않았는가? |
이 중에서 Faithfulness가 가장 중요하다고 생각한다. Answer Relevancy가 높더라도 Faithfulness가 낮으면, LLM이 검색된 문맥을 무시하고 자기 지식으로 그럴듯하게 답변을 만들어낸 것일 수 있다. 즉, 할루시네이션이 숨어있다는 뜻이다.
반대로 Faithfulness는 높은데 Answer Relevancy가 낮다면? 검색된 문맥에 충실하게 답변하긴 했는데, 애초에 검색이 잘못돼서 엉뚱한 문서를 기반으로 답변한 경우다. 이때는 검색기를 개선해야 한다.
이렇게 지표들을 조합해서 보면 "문제가 파이프라인의 어디에서 발생하는가"를 진단할 수 있다. 한 지표만 보면 원인을 특정하기 어렵다.
지표 간의 균형, 정답은 없다
여기까지 읽으면 지표가 너무 많아서 머리가 아플 수도 있다. 현실적으로 모든 지표를 다 최적화할 수는 없다. 트레이드오프가 있기 때문이다.
응답 품질을 높이려고 프롬프트를 길게 쓰고 CoT(Chain of Thought)를 적용하면 지연 시간이 늘어난다. 검색 문서 수를 늘리면 recall은 올라가지만 precision이 내려가고 비용도 늘어난다. Faithfulness를 극단적으로 높이면("문서에 없으면 절대 답하지 마") 유저 입장에서 "모르겠습니다"만 반복하는 불친절한 봇이 된다.
결국 서비스의 성격에 따라 어떤 지표에 가중치를 둘지 결정해야 한다. 내부 지식 검색 시스템이면 faithfulness를 최우선으로, 일반 챗봇이면 답변의 자연스러움과 유저 만족도에 더 비중을 두는 식이다.
실무 팁
모든 걸 한 번에 최적화하려 하지 말고, "지금 가장 아픈 곳"을 먼저 찾자. 유저가 할루시네이션을 자주 제보하면 faithfulness부터, 답변이 엉뚱하다는 피드백이 많으면 검색 품질(precision/recall)부터 잡는 게 효율적이다.
아직 풀리지 않은 고민들
LLM 평가 분야는 아직 빠르게 변하고 있다. LLM-as-a-Judge의 편향 문제를 줄이려는 연구가 활발하고, 동적으로 테스트셋을 생성해서 데이터 누출(data leakage)을 방지하는 벤치마크도 등장하고 있다. 에이전트 시스템이 복잡해지면서 멀티스텝 태스크의 평가 방법론도 아직 정립되는 중이다.
내가 느끼는 건, 완벽한 평가 체계를 한 번에 구축하려는 것보다 작게 시작해서 점진적으로 확장하는 게 현실적이라는 것이다. 처음에는 수동으로 50개 테스트 케이스를 만들어서 돌려보는 것만으로도 의미 있는 인사이트를 얻을 수 있다. 거기서 시작해서 자동화하고, 지표를 추가하고, 모니터링을 붙이는 거다.
평가 없이 LLM 서비스를 운영하는 건, 계기판 없이 비행기를 모는 것과 비슷하다. 일단 날 수는 있지만, 어디로 가고 있는지 모른다.