RAG 시스템을 정량 평가하는 4가지 지표 — 마케팅 챗봇을 만든다면
마케팅 FAQ 챗봇·내부 위키 검색을 RAG로 만들 때, "답변이 맞다"를 어떻게 숫자로 증명할까. context relevance부터 faithfulness까지 4가지 지표를 케이스로 풀어봅니다.
마케팅팀에서 사내 FAQ 챗봇을 만들었는데, 답변이 그럴듯해 보이긴 합니다. 그런데 “이게 정말 맞는 답이야?”라고 물으면 답을 못 합니다. 이 글은 그 질문을 숫자로 바꾸는 4가지 지표 이야기예요.
마케터가 이 글을 읽어야 하는 이유: RAG 챗봇을 만들고 “잘 되는 것 같다”는 인상에 의존하면, 언제 망가졌는지 모릅니다. 4가지 지표를 매주 한 번만 돌려도 “검색이 문제인지, 생성이 문제인지”를 회의에서 5분 안에 설명할 수 있게 됩니다.
1. RAG 평가가 필요한 이유 — 두 축으로 보기
RAG는 Retrieval-Augmented Generation의 약자입니다. 풀어쓰면 “답변하기 전에 자료를 검색하는 LLM”이에요. 마케팅 도메인에 적용하면:
- 사내 위키의 광고 정책을 검색 → 마케터 질문에 답하는 챗봇
- 과거 캠페인 리포트를 검색 → “비슷한 KPI의 캠페인 결과 보여줘”
- 경쟁사 분석 문서를 검색 → “X 브랜드 최근 CPM 트렌드 알려줘”
문제는 답변이 그럴듯해 보일 뿐 진짜 맞는지를 어떻게 검증하느냐입니다.
흔한 오해는 “답변이 정확한가만 보면 된다”입니다. 실제로는 두 단계가 있어요.
사용자 질문 │ ▼[검색 단계] ── 평가 ──▶ Context Relevance (관련 자료를 가져왔나?) │ Context Recall (필요한 자료를 빠뜨리지 않았나?) ▼관련 문서들 │ ▼[생성 단계] ── 평가 ──▶ Faithfulness (자료 밖 내용을 지어내지 않았나?) │ Answer Relevance (질문에 직접 답했나?) ▼최종 답변따라서 평가 지표는 검색 품질과 답변 품질 두 축에서 각각 측정됩니다.
2. 4가지 지표 — 한 표로
| 지표 | 무엇을 보는가 | 일상어로 |
|---|---|---|
| Context Relevance | 검색된 문서가 질문과 얼마나 관련 있나 | ”검색이 진짜 답에 가까운 자료를 가져왔어?” |
| Context Recall | 정답에 필요한 자료를 빠뜨리지 않았나 | ”필요한 문서가 다 들어왔어?” |
| Faithfulness | 답변이 검색된 문서 안에서만 말하는가 | ”지어내지 않고 자료를 진짜로 봤어?” |
| Answer Relevance | 답변이 질문에 정확히 답했나 | ”동문서답 아니야?” |
이 4가지를 한 번씩 계산하면 RAG 시스템의 건강 상태가 입체적으로 보입니다.
3. 각 지표를 코드 한 묶음으로
Ragas 라이브러리가 이 4가지를 모두 LLM-as-judge 방식으로 계산해줍니다. 한 번 돌려보면 이렇게 나와요.
from datasets import Datasetfrom ragas import evaluatefrom ragas.metrics import ( context_relevancy, context_recall, faithfulness, answer_relevancy)
# 마케팅 FAQ 챗봇 테스트 케이스data = { "question": ["우리 회사 광고 채널 중 ROAS 가장 높은 채널은?"], "answer": ["지난 분기 기준 Meta 광고 ROAS가 4.2로 가장 높았습니다."], "contexts": [["분기 보고서: Meta ROAS 4.2, Google 3.5, Naver 2.8..."]], "ground_truth": ["Meta 광고가 ROAS 4.2로 가장 높음"],}
result = evaluate( Dataset.from_dict(data), metrics=[context_relevancy, context_recall, faithfulness, answer_relevancy],)print(result){'context_relevancy': 0.91, 'context_recall': 1.00, 'faithfulness': 0.95, 'answer_relevancy': 0.88}Context Relevance 0.91
검색된 문서의 91%가 질문과 관련 있다는 뜻. 90% 이상이면 좋고, 70% 아래로 떨어지면 검색기를 손봐야 합니다.
Context Recall 1.00
정답 생성에 필요한 자료를 모두 가져왔습니다. 0.7 이하면 정답 정보가 빠졌다는 뜻이에요. 인덱싱 누락·청크 크기 문제를 의심합니다.
Faithfulness 0.95
답변의 95%가 검색 문서에서 직접 지지됩니다. 0.8 이하면 LLM이 자기 지식으로 빈 칸을 채우고 있다는 신호 — 환각 위험입니다.
수식으로 보면 단순합니다.
답변 안의 명제(claim)를 LLM이 쪼갠 뒤, 각 명제가 검색 문서에 의해 지지되는지 검사합니다. 분모가 작아지면 점수가 흔들리니, 답변을 너무 짧게 만들어 점수만 올리는 함정도 조심해야 해요.
Answer Relevance 0.88
질문 자체에 88% 직접적으로 답했습니다. 0.7 이하면 동문서답이 섞이고 있어요.
직관적으로 말하면, 답변에서 거꾸로 질문을 생성해보고 원 질문과 얼마나 가까운지를 봅니다. 임베딩 코사인 유사도로 환산하면 다음과 같아요.
- — 임베딩 함수
- — 원 질문, — 답변에서 역생성된 질문 후보
- — 후보 개수 (보통 3~5개)
4. 골든셋 — 어디서부터 시작하나
마케터 입장에서 가장 큰 장벽은 “정답이 적힌 데이터(ground truth)를 어디서 구하나”입니다. 답: 30-50개로 충분합니다.
만드는 절차
- 실제 마케터·운영팀이 챗봇에 자주 물을 만한 질문 50개를 적습니다.
- 각 질문에 사람이 직접 정답을 작성합니다 (15분짜리 문서 1쪽).
- 챗봇을 돌려서 4가지 지표를 매주 계산합니다.
이게 회귀 테스트가 됩니다. 챗봇 모델·프롬프트를 바꿨을 때 4가지 지표가 어떻게 움직이는지 한눈에 보여요.
골든셋의 다양성을 챙기는 방법
50개를 무작위로 뽑으면 비슷한 질문 패턴에 쏠립니다. 다음 4분면을 고르게 채우면 됩니다.
| 축 \ 축 | 사실형 (정답 1개) | 해석형 (정답 다수) |
|---|---|---|
| 단순 (한 문장) | “Meta CPM 기준값은?" | "최근 ROAS 좋은 캠페인은?” |
| 복합 (여러 단계) | “Q3 Naver 클릭 대비 전환은?" | "지난 분기 캠페인 중 다음에도 쓸 만한 건?” |
각 셀에 12~13개씩, 총 50개. 이렇게 다양성을 강제하면 4가지 지표가 어느 종류 질문에서 약해지는지 한눈에 드러납니다.
골든셋이 진화하는 단계
- 0주차: 50개 직접 작성, 정답을 사람이 작성
- 2-4주차: 챗봇 답변 중 좋은 케이스를 골라 골든셋에 편입 (사람 검수 후)
- 2-3개월차: 사용자 로그에서 자주 나오는 질문을 추가, 100-200개로 확장
- 반기: 더 이상 통과 못 하는 도메인 영역 발견, 도메인별 별도 골든셋
골든셋은 살아 있는 데이터셋입니다. 한 번 만들고 끝이 아니에요.
5. 검색기를 어떻게 고르고 튜닝하나
지표가 나빠졌을 때, 어디를 손대야 할지 모르면 무용지물입니다. 4지표가 가리키는 손볼 위치는 다음과 같아요.
| 나빠진 지표 | 의심 위치 | 첫 조치 |
|---|---|---|
| Context Relevance | 검색기(retriever) | 임베딩 모델 교체, 또는 hybrid (BM25 + dense) |
| Context Recall | 청크 분할 / 인덱싱 | 청크 크기 줄이기, 메타데이터 필터 보강 |
| Faithfulness | 생성기(LLM) 프롬프트 | ”검색 문서에 없는 내용 금지” 명시, temperature 낮추기 |
| Answer Relevance | 생성기 추론 단계 | rerank 추가, few-shot 예시로 답변 형식 고정 |
지표를 보고 어디를 조이는지가 정해진 매핑이 있으니, 회의에서 모호하지 않습니다.
Hybrid 검색 — BM25 + Dense
마케팅 도메인은 고유명사(브랜드명·캠페인 ID)가 많아서, dense embedding만으로는 정확 매칭이 약할 수 있어요. BM25 같은 키워드 검색을 함께 쓰는 hybrid 방식이 자주 효과적입니다.
from rank_bm25 import BM25Okapiimport numpy as np
def hybrid_search(query, docs, embeddings, k=5, alpha=0.5): # dense 점수 (코사인 유사도) q_emb = embed(query) dense_scores = np.dot(embeddings, q_emb)
# sparse 점수 (BM25) bm25 = BM25Okapi([d.split() for d in docs]) sparse_scores = bm25.get_scores(query.split())
# 정규화 후 가중 합산 dense = dense_scores / dense_scores.max() sparse = sparse_scores / sparse_scores.max() final = alpha * dense + (1 - alpha) * sparse
top_idx = np.argsort(final)[-k:][::-1] return [docs[i] for i in top_idx]alpha는 0.5에서 시작해 골든셋에서 튜닝합니다. 마케팅 데이터는 보통 0.3~0.4 (sparse 비중 더 큼)이 더 잘 동작해요.
6. LLM-as-judge의 한계
한 가지 솔직하게 짚을 점. Ragas가 쓰는 방식은 LLM이 LLM을 평가하는 것입니다. 비용이 들고, 평가자 LLM의 편향이 들어갈 수 있어요.
실무 권고
- 평가자는 답변 생성 모델보다 더 강한 모델을 씀 (GPT-4o로 답변, GPT-5로 평가 식)
- 같은 입력으로 3번 평가해서 분산 확인 (LLM 출력은 stochastic)
- 정량 지표 + 분기에 1번 사람의 정성 검수 병행
평가자의 편향 종류
LLM-as-judge가 자주 빠지는 편향이 알려져 있습니다.
- Position bias — 두 답변 중 앞에 나온 걸 더 후하게 평가. 평가 시 순서를 무작위로 섞기.
- Verbosity bias — 긴 답변을 더 똑똑해 보인다고 판단. 답변 길이를 정규화하거나 짧은 답이 좋은 케이스를 골든셋에 추가.
- Self-preference — 같은 가족의 LLM(예: GPT가 GPT 답변)을 더 후하게. 가능하면 평가자와 답변 생성기를 다른 가족으로.
LLM-as-judge vs 사람 평가의 일치도
연구에서는 강한 LLM 평가자(GPT-4 클래스)와 사람의 일치도가 0.8 안팎으로 보고됩니다. 사람끼리도 0.85~0.9이니, “LLM이 사람만큼은 아니지만 거의 그 수준”이라고 보면 적당합니다. 분기마다 50개 케이스를 사람 검수해서 LLM 점수와의 일치도를 추적하면 신뢰도를 객관적으로 관리할 수 있어요.
7. 마케팅 도메인에서 자주 빠지는 함정 (확장판)
- “답변이 맞다”의 정의가 안 잡힘. 마케팅 용어는 회사마다 의미가 달라요. 정답을 적기 전에 용어집부터.
- 컨텍스트 청크가 너무 큼. 보고서 한 장 통째로 넣으면 검색기는 좋은 자료라고 판단하지만, LLM이 핵심을 못 찾습니다. 300~500자가 적정.
- 메타데이터 필터를 빠뜨림. “지난 분기” 질문에 1년치 자료가 다 검색되면 답변 흐려져요. 날짜·카테고리 필터 필수.
- 평가 자동화가 비싸다고 미루는 것. 50개 골든셋이면 GPT 비용 1주에 몇 천 원 수준. 안 하면 챗봇이 점점 나빠지는 걸 모릅니다.
- 고유명사 정규화 빠뜨리기. “메타”, “Meta”, “facebook ads”가 같은 채널이라는 걸 검색기가 모르면 recall이 무너집니다. 동의어 사전을 별도로 관리.
- 최신 데이터 업데이트 누락. 어제 만들어진 캠페인 보고서가 인덱스에 없으면 “최근 어땠어?” 질문에서 환각이 나옵니다. 인덱스 동기화 SLA를 명시.
- 실패 케이스를 보고서에 안 넣기. “실패율 12%“를 정직하게 보고하지 않으면 점진적 개선의 동기가 사라집니다.
8. 마치며
RAG 평가는 어렵지 않습니다. “검색”과 “생성” 두 단계 각각에 2개 지표씩. 그리고 골든셋 50개. 이게 시작이에요.
마케팅 챗봇을 만들고 있거나 만들 계획이 있다면, 이 4개 숫자를 매주 한 번 보는 것만으로 시스템이 살아 움직입니다. 한 분기가 지나면, 어느 지표가 어떤 변화에 민감한지 팀이 직관적으로 알게 돼요. 그게 RAG를 운영하는 진짜 능력입니다.
다음에 읽으면 좋은 글:
- 임베딩 운영 — 드리프트·버전·차원 관리 — 검색기 임베딩 모델을 유지보수하는 법
- LLM-as-judge — 편향과 보정 — Ragas가 내부적으로 쓰는 평가 방식의 상세
- RAG 비용·latency 최적화 — 4지표가 좋아진 뒤 비용·속도를 줄이는 단계
참고
AI·LLM 카테고리의 다른 글
전체 보기 →-
2026·05·16
LLM 운영 비용 폭주를 막는 6가지 guardrail — 마케팅 자동화의 cost·latency·품질 동시 관리
LLM을 운영에 올리면 어느 날 갑자기 비용이 10배로 튑니다. retry storm·프롬프트 폭증·모델 자동 승격·context 누적 등 폭주 패턴 6가지와 그것을 막는 guardrail을 정리합니다.
-
2026·05·10
LLM evaluation harness — 분기마다 챗봇 품질을 자동 평가하는 공장
챗봇·에이전트가 운영에 들어가면 한 번 평가가 아니라 분기 자동 평가가 필요합니다. 골든셋·regression·hyperparameter A/B를 묶는 evaluation harness 설계와 마케팅 자리에서의 적용.
-
2026·05·09
Context engineering — 200k 토큰 컨텍스트의 설계 원칙 5가지
컨텍스트 창이 200k 토큰까지 커졌지만 단순히 다 넣으면 lost-in-the-middle·비용 폭발·정확도 하락이 옵니다. 마케팅 자동화에 적용하는 5가지 컨텍스트 설계 원칙.
-
2026·05·09
Function calling 설계 패턴 — LLM이 도구를 부를 때 마케터가 점검할 것
LLM이 광고 API·BigQuery·Slack을 직접 부르기 시작하면, 답변 품질보다 "어느 도구를 언제 부를지"가 운영 사고의 진앙이 됩니다. function calling의 한 줄 직관과 마케터가 점검할 5가지.