RAG 챗봇 답변이 자주 빗나간다면, 모델·프롬프트보다 검색 단계가 약할 가능성이 큽니다. 벡터 검색은 빠르지만 의미 매칭의 정밀도가 부족합니다. cross-encoder 재순위(re-ranking)는 1단계 검색의 Top 50을 다시 정렬해 정말 관련 있는 Top 5를 LLM에 넘깁니다. 한 단계 추가로 답변 품질이 눈에 띄게 올라갑니다.
마케터가 이 글을 읽어야 하는 이유: RAG 챗봇이 운영에 들어가 있다면, 답변 품질의 절반이 검색 단계에서 결정됩니다. 모델 교체보다 비용 효율적인 개선이 재순위 단계 추가입니다. 비용 약간 증가에 정밀도 큰 폭 상승. 사내 챗봇 신뢰도가 흔들리는 자리라면 가장 먼저 시도할 카드입니다.

빠른 1차 검색 + 정밀한 2차 재순위. 비용은 작게, 품질은 크게.
1. 왜 1차 검색만으로 부족한가
벡터 검색(bi-encoder 기반)은 사용자 질문과 문서를 각각 독립적으로 임베딩한 뒤 코사인 유사도로 비교합니다. 이 구조는 빠르지만 한 가지 약점이 있습니다.
질문과 문서가 서로 직접 비교되지 않고, 미리 만든 임베딩으로만 비교된다.
같은 단어라도 문맥이 다르면 의미가 다릅니다. "Meta 캠페인 ROAS"가 페이스북 광고를 의미하는지 메타분석을 의미하는지의 구분이 1차 검색에서는 약합니다. 그래서 Top 5가 깨끗하지 않고 무관한 문서가 자주 섞입니다.
| 검색 단계 | 입력 | 비교 방식 | 정밀도 | 속도 |
|---|---|---|---|---|
| 1차 (벡터) | 질문 임베딩 | 미리 만든 문서 임베딩과 코사인 | 중간 | 매우 빠름 |
| 2차 (cross-encoder) | 질문 + 문서 쌍 | 매번 함께 입력해 점수 출력 | 매우 높음 | 느림 |
cross-encoder는 정밀하지만 모든 문서에 적용하면 너무 느립니다. 그래서 1차 검색으로 Top 50을 빠르게 가져온 뒤 그 50개에만 cross-encoder를 적용하는 2단계 흐름이 표준이 되었습니다.
📌 이 글의 전제
독자가 RAG 챗봇·임베딩·벡터 검색이라는 단어를 일상으로 쓴다고 가정합니다. 코드를 직접 짠 적은 없어도 OK이고, 검색 단계가 답변 품질에 영향을 준다는 직관은 받아들인다고 가정합니다.
2. Cross-encoder의 한 줄 직관
cross-encoder는 질문과 문서를 한 번에 모델에 넣어 "얼마나 관련 있는가"의 점수를 직접 출력합니다.
입력: [질문] [SEP] [문서] → 출력: 관련도 점수 (0~1)
bi-encoder처럼 임베딩을 미리 만들어 둘 수 없습니다. 매 쿼리마다 50개 문서 각각에 대해 모델 forward를 돌려야 합니다. 그래서 느림. 대신 두 텍스트의 모든 토큰이 attention으로 직접 연결되니 의미 매칭의 정밀도가 폭발적입니다.
수식 직관:
bi-encoder는 로 두 임베딩의 코사인을 계산하지만, cross-encoder는 두 텍스트를 함께 모델에 넣어 단일 점수를 출력합니다. 토큰끼리 직접 attention하니 미묘한 문맥 차이를 잡아냅니다.
3. 2단계 검색의 표준 흐름
사용자 질문
│
▼
1차 검색 (bi-encoder + vector DB)
→ Top 50 문서를 매우 빠르게 (수십 ms)
│
▼
2차 재순위 (cross-encoder)
→ Top 50을 정밀 점수로 정렬
→ 상위 Top 5만 살림 (수백 ms)
│
▼
Top 5를 LLM 프롬프트에 컨텍스트로 삽입
│
▼
LLM이 답변 생성
각 단계의 책임이 분명해지고, 시스템 전체의 정밀도가 올라갑니다. 비용은 cross-encoder 50번 호출 = 수백 ms 지연 + 약간의 GPU/API 비용. 품질 개선이 비용을 항상 정당화한다는 게 RAG 운영 표준이 되어가는 이유입니다.
4. 코드 한 묶음 — sentence-transformers cross-encoder
이게 글에 박는 유일한 코드입니다.
from sentence_transformers import CrossEncoder
# 1. cross-encoder 모델 로드 (한 번만)
reranker = CrossEncoder("BAAI/bge-reranker-base")
# 2. 1차 검색 결과 (벡터 DB가 빠르게 가져온 Top 50)
query = "Meta 광고 ROAS 분기별 평균은?"
candidates = [
"2024 Q3 Meta 광고 ROAS 평균은 4.2였습니다...",
"메타분석에서 평균 효과크기는 0.35로...",
"TikTok ROAS는 평균 3.1, Meta는 4.2...",
# ... 47개 더
]
# 3. cross-encoder로 (질문, 문서) 쌍을 점수화
pairs = [(query, doc) for doc in candidates]
scores = reranker.predict(pairs)
# scores: [0.92, 0.18, 0.85, ...]
# 4. 점수 기준 정렬 후 Top 5만 살림
ranked = sorted(zip(scores, candidates), reverse=True)[:5]
top_5 = [doc for _, doc in ranked]
print(top_5)
# 1차 검색에서 메타분석 문서가 섞여 있었지만 cross-encoder가 점수 0.18로 떨궈냄.
50개 문서에 대해 각각 점수를 계산하니 수백 ms 지연이 추가됩니다. 그러나 잘못 섞여 들어왔던 메타분석 문서가 0.18 점수로 떨어져 Top 5에서 빠지고, 정확한 광고 ROAS 문서들이 살아 LLM 컨텍스트로 들어갑니다.
5. 모델 선택 — 어떤 cross-encoder를 쓸까
| 모델 | 크기 | 한국어 지원 | 추론 속도 |
|---|---|---|---|
cross-encoder/ms-marco-MiniLM-L-6-v2 |
작음 (22M) | 약함 | 가장 빠름 |
cross-encoder/ms-marco-MiniLM-L-12-v2 |
중간 (33M) | 약함 | 빠름 |
BAAI/bge-reranker-base |
중간 (278M) | 강함 (multilingual) | 중간 |
BAAI/bge-reranker-large |
큼 (560M) | 매우 강함 | 느림 |
| Cohere Rerank API | 매니지드 | 강함 | 빠름 (클라우드) |
한국어 RAG에는 BAAI/bge-reranker-base 이상을 권장합니다. 영어 전용 모델은 한국어 매칭이 약함. 매니지드 솔루션이 필요하면 Cohere Rerank API.
5-1. Cohere Rerank API의 자리
API 호출 한 번으로 100개 문서 재순위. 자체 호스팅 부담 없음. 비용은 1000번 검색당 약 $1-2. 챗봇 검색 트래픽이 일일 수만 건 이하면 합리적.
💡 모델 선택 트레이드오프
처음에는
BAAI/bge-reranker-base또는 Cohere Rerank로 시작. 정밀도 부족 시 large 모델로 업그레이드. 큰 모델일수록 GPU 비용·지연이 비례적으로 증가하니, 골든셋 평가에서 구체적 정밀도 차이를 확인 후 결정.
6. 1차 검색의 K값 — Top 몇 개를 재순위에 넘기나
| K (1차 결과 수) | 효과 | 비용 |
|---|---|---|
| 10 | 정밀도 한도 (재순위가 살릴 수 있는 게 적음) | 매우 낮음 |
| 50 | 표준 — 대부분 자리에 적합 | 적당 |
| 100 | 높은 recall, cross-encoder 100번 호출 | 높음 |
| 200+ | 거의 모든 후보 검토, 비용 폭발 | 매우 높음 |
K=50이 표준이 되어가고 있습니다. 정밀도와 비용의 균형이 가장 좋은 자리. 매우 큰 코퍼스(수백만 문서)에서는 K=100이 안전.
7. 평가 — 재순위가 정말 도움이 됐나
재순위 단계 추가가 의미 있는지 측정하려면 RAG 평가 지표를 함께 봐야 합니다.
7-1. Context Relevance와 Recall
RAG 평가에서 다룬 4가지 지표 중 Context Relevance와 Context Recall이 재순위 효과를 직접 반영합니다. 재순위 ON/OFF를 토글해 같은 골든셋에서 두 지표를 비교.
| 시나리오 | Context Relevance | Context Recall | Faithfulness |
|---|---|---|---|
| 재순위 OFF (Top 5 직접) | 0.78 | 0.85 | 0.81 |
| 재순위 ON (Top 50 → Top 5) | 0.91 | 0.88 | 0.93 |
Context Relevance가 0.78 → 0.91로 큰 폭 상승. Faithfulness도 0.81 → 0.93. 재순위 단계가 답변 품질 전반에 영향을 미친다는 게 정량적으로 확인됩니다.
7-2. 응답 시간의 트레이드오프
재순위 단계 추가는 약 200-500ms 지연을 만듭니다. 사용자가 인식할 만한 지연이 아니지만 챗봇 응답이 이미 느린 자리(p95 5초+)에서는 추가 부담이 됩니다.
⚠️ 재순위가 의미 없는 자리
코퍼스가 매우 작거나(수백 문서) 1차 검색 정밀도가 이미 매우 높은 자리에서는 재순위 효과가 미미할 수 있습니다. 도입 전에 골든셋으로 ON/OFF 비교를 한 번 돌려보고 결정.
{/* TODO_HUNY: huny가 운영 중인 RAG 시스템에 재순위가 들어가 있는지, 들어갔다면 도입 후 어느 지표가 가장 크게 개선됐는지 한 단락 추가해주세요. */}
8. 운영 흐름의 안정화
8-1. 캐싱
같은 (질문, 문서) 쌍에 대해 점수를 캐시해두면 반복 질문 시 cross-encoder 호출이 줄어듭니다. 챗봇 트래픽의 20-40%가 같은 질문 패턴이라 캐시 히트율이 높음.
8-2. 배치 처리
cross-encoder는 배치 처리가 강합니다. 50개 쌍을 한 배치로 묶어 한 번에 forward하면 개별 호출보다 5-10배 빠름. PyTorch DataLoader 같은 표준 패턴 활용.
8-3. 모니터링 알림
재순위 점수의 분포를 매주 추적합니다. 갑자기 모든 점수가 낮아지면(예: 평균 0.3 이하) 임베딩 모델·코퍼스 변화 의심.
9. 마치며 — RAG 품질 개선의 가장 비용 효율적인 자리
RAG 챗봇 품질 개선에 큰 비용을 쓰기 전에 cross-encoder 재순위 단계를 한 번 시도해보는 게 가장 비용 효율적인 카드입니다. 모델 교체·프롬프트 튜닝보다 적은 비용으로 Context Relevance·Faithfulness가 큰 폭 상승하는 케이스가 흔합니다. 운영 중인 챗봇이 자주 빗나간다면 이 단계 추가를 분기 로드맵에 박아두세요.
다음 분기에 한 번만 시도해 볼 만한 것은 골든셋 50개에 대해 재순위 ON/OFF 비교를 한 번 돌려 정밀도 차이를 정량화하는 흐름입니다. 차이가 크면 즉시 운영 도입, 작으면 다른 단계로.
{/* TODO_HUNY: 사내 RAG 시스템의 일일 검색 트래픽과 재순위 도입 시 비용 차이 한 단락 추가해주세요. */}
다음에 읽을 글
- RAG 평가 — 재순위 효과를 측정하는 4가지 지표
- 임베딩 운영 — 1차 검색 임베딩 모델 관리
- RAG 비용·latency — 재순위 추가 시 latency 트레이드오프
참고
- "Sentence-BERT" (Reimers & Gurevych, 2019): https://arxiv.org/abs/1908.10084
- BAAI BGE Reranker: https://huggingface.co/BAAI/bge-reranker-base
- Cohere, "Rerank API": https://docs.cohere.com/docs/rerank
- "MS MARCO passage ranking benchmark": https://microsoft.github.io/msmarco/
- "Pretrained Transformers for Text Ranking" (Lin et al., 2021): https://arxiv.org/abs/2010.06467
Top comments (0)