본문 바로가기
RAG/Retrieval

Reranking

by AteN 2025. 11. 12.

리랭킹, 1차 검색의 거친 순위를 정밀 모델로 바로잡기

요약

  • 빠른 1차 검색기가 넓게 후보를 건져 올리고(recall), 느리지만 정밀한 재정렬기가 그 소수 후보만 다시 점수 매겨 상위 순서를 바로잡는(precision) 2단계 검색입니다.
  • 문제는 1차 검색기가 질의와 문서를 따로 보기 때문에 빠르지만 거칠다는 것입니다. 표면적으로 비슷해 보이는 엉뚱한 문서가 상위에 끼어듭니다.
  • 해법은 재정렬기가 질의와 문서를 함께 넣어 토큰 간 상호작용까지 보고 관련도를 매기는 것입니다.
  • 비용은 후보 수에 정비례합니다. 후보 하나당 추론 1회라, 1차에서 수십에서 수백 개로 좁힌 뒤에만 재정렬합니다.
  • 중요한 제약이 하나 있습니다. 재정렬의 상한은 1차 recall이 정합니다. 정답이 애초에 후보에 없으면 아무리 잘 재정렬해도 소용없습니다.

왜 검색을 2단계로 나누나

검색에는 서로 당기는 두 목표가 있습니다. recall은 정답을 빠뜨리지 않고 후보에 담는 것이고, precision은 그중 진짜 관련 있는 걸 맨 위로 올리는 것입니다. 한 모델로 둘을 동시에 최고로 내기는 어렵습니다.

넓게 보려면 빨라야 합니다. 수백만 문서를 매 질의마다 훑으려면 문서 임베딩을 미리 계산해두고 벡터 근사최근접 탐색으로 순식간에 후보를 뽑아야 합니다. 이게 bi-encoder입니다. 빠른 대신, 질의와 문서가 서로를 못 본 채 각자 벡터로 압축되므로 미세한 관련성은 놓칩니다.

정밀하게 보려면 느려집니다. 질의와 문서를 한 트랜스포머에 같이 넣어 단어끼리 attention을 시키면 관련도를 훨씬 정확히 매깁니다. 하지만 질의가 들어와야 계산이 시작되므로 미리 계산해둘 수 없고, 후보마다 한 번씩 돌려야 합니다. 수백만 문서에 이걸 쓰면 실시간 검색이 불가능합니다.

그래서 둘을 순서대로 겹칩니다. 빠른 검색기로 recall을 확보해 후보 100개쯤 건지고, 정밀 재정렬기로 그 100개만 다시 점수 매겨 상위 5개를 고릅니다. 느린 모델을 가장 값어치 있는 소수에만 쓰는 구성입니다.

bi-encoder와 cross-encoder

두 아키텍처의 차이가 곧 2단계 구성의 이유입니다.

bi-encoder는 질의와 문서를 각각 독립적으로 임베딩 벡터 하나로 바꾼 뒤, 두 벡터의 유사도로 점수를 냅니다. 문서 벡터는 색인 시점에 미리 계산해둘 수 있어 질의 때는 벡터 검색만 하면 됩니다. 매우 빠릅니다. 단, 질의와 문서가 인코딩 과정에서 서로를 전혀 못 봅니다.

cross-encoder는 질의와 문서를 이어붙여 한 번에 트랜스포머에 넣고, 두 텍스트에 걸쳐 attention을 시킨 뒤 관련도 점수 하나를 출력합니다. 질의와 문서 토큰이 직접 상호작용하니 정밀하지만, 미리 계산이 불가능하고 후보마다 1회 추론이라 비용이 후보 수에 비례합니다.

  bi-encoder (1차) cross-encoder (재정렬)
인코딩 질의와 문서 따로 질의와 문서 함께
미리 계산 가능 불가. 질의가 있어야 시작
속도 빠름 느림. 후보마다 1회
정밀도 거침 높음. 토큰 상호작용
역할 넓게 건지기 (recall) 상위 바로잡기 (precision)

후보 5개를 재정렬해보면

질의: "고양이가 밤에 우는 이유는?"

1차 검색기가 임베딩 유사도로 top-5를 뽑았고, cross-encoder가 각 후보를 질의와 함께 읽어 점수를 매겼다고 해봅시다.

후보 문서 1단계 순위 cross-encoder 점수 최종 순위
A. 고양이의 야행성과 밤 울음소리 1 0.95 1
B. 고양이 사료 브랜드 추천 2 0.06 5
C. 반려동물 야간 소음, 이웃 분쟁 사례 3 0.48 3
D. 고양이 분리불안이 밤 울음으로 나타날 때 4 0.89 2
E. 강아지가 밤에 짖는 이유 5 0.30 4

무슨 일이 일어났는지 보겠습니다.

B가 2등에서 5등으로 추락했습니다. 1차 검색은 "고양이"라는 표면 신호가 강해 사료 글을 위로 올렸지만, 함께 읽는 재정렬기는 이 문서가 밤 울음과 무관함을 잡아냈습니다.

D가 4등에서 2등으로 올라왔습니다. "분리불안에서 밤 울음으로"가 질문의 핵심 답인데 1차에선 묻혀 있었습니다. 재정렬기가 질의와의 미세한 관련성을 보고 끌어올렸습니다.

결과적으로 사용자에게 보여줄 상위 문서가 A와 D로 바뀌었습니다. recall은 1차가, precision은 재정렬이 책임진 셈입니다.

위 점수는 설명용 예시입니다. 실제 점수와 모델 동작은 각 모델 카드를 따릅니다.

재정렬기의 세 갈래

1. Cross-encoder (pointwise) 는 고전적이고 표준적인 방식입니다. 질의와 문서 쌍마다 독립적으로 관련도 점수 하나를 냅니다. 오픈 모델 BAAI/bge-reranker-v2-m3나 Cohere의 호스티드 Rerank API가 여기 속합니다. 구현이 단순하고 통합 도구가 많아 실무 1순위 기본값입니다.

2. LLM 기반 재정렬기 는 생성형 LLM을 재정렬에 쓰는 흐름입니다. 두 방식이 있습니다.

Pointwise 는 질의와 문서 쌍을 넣고 "이 문서가 관련 있나"에 대한 yes와 no 토큰 확률을 관련도 점수로 씁니다. Qwen3-Reranker가 이 방식이고, instruction을 함께 줄 수 있어 태스크별로 지시할 수 있습니다.

Listwise 는 질의와 여러 후보를 한 컨텍스트에 통째로 넣어 서로 비교시킨 뒤 순위를 냅니다. 후보끼리의 상대적 우열을 직접 보는 게 강점입니다. Jina Reranker v3가 이 방식으로, 질의와 모든 후보를 한 컨텍스트에 넣어 상호작용시킨 뒤 각 문서 마지막 토큰에서 점수를 뽑습니다.

3. ColBERT와 late interaction 은 bi와 cross의 절충입니다. 질의와 문서를 토큰별 임베딩 여러 개로 각각 인코딩해두고, 질의 때는 MaxSim이라는 값싼 연산으로 상호작용시킵니다. 질의 토큰 각각에 대해 문서 토큰들 중 가장 비슷한 것의 유사도를 취해 합산하는 방식입니다.

문서 인코딩을 미리 해두는 bi-encoder의 속도와, 토큰 수준 상호작용이라는 cross-encoder의 정밀함을 절충한 겁니다. 원논문은 기존 BERT 랭커 대비 약 100배 빠르고 쿼리당 FLOPs는 약 10,000배 적다고 보고합니다. 후속 ColBERTv2는 잔차 압축으로 저장공간을 6배에서 10배 줄였습니다.

조정 옵션

옵션 언제 조정하나
후보 수 k 1차에서 몇 개를 재정렬에 넘길지. 크면 recall이 오르지만 지연과 비용이 k에 선형 비례합니다. 보통 수십에서 수백
최종 반환 n 재정렬 후 몇 개를 실제로 쓸지. RAG 프롬프트에 넣을 상위 5개 같은 식
지연 cross-encoder는 후보마다 1회 추론이라 k가 병목입니다. 경량 모델, 배치 추론, ONNX나 GGUF 양자화, 호스티드 API로 완화
모델 선택 정밀도 최우선이면 큰 cross-encoder나 LLM 재정렬, 속도 절충이면 ColBERT 계열, 운영 회피면 호스티드
언어 적합성 다국어와 전문 도메인은 모델별 편차가 큽니다. 한국어면 한국어 미세조정 모델을 우선 검토

성능 비교는 MTEB의 reranking 태스크가 공용 기준으로 쓰입니다.

파이프라인에서의 위치

질의
 │
 ▼
1단계 검색  (bi-encoder 또는 BM25, 빠름)
 │
 ▼
top-k 후보  (예: 100개)          ← recall 담당
 │
 ▼
2단계 재정렬  (cross-encoder, 정밀)
 │
 ▼
top-n 결과  (예: 5개)            ← precision 담당

RAG의 컨텍스트 선별이 대표적인 용처입니다. 벡터나 하이브리드 검색으로 후보를 넓게 뽑고, 재정렬로 상위 몇 개만 골라 LLM 프롬프트에 넣습니다. 노이즈 문서를 걷어내 답변 품질을 높이는 표준 마무리 단계입니다.

하이브리드 검색 뒤에 붙이는 구성도 널리 쓰입니다. 희소와 밀집을 RRF로 거칠게 융합한 뒤 크로스인코더로 정밀 재정렬합니다. RRF는 점수 크기를 버리기 때문에 약해진 상위 정밀도를 재정렬이 메웁니다.

자원이 빠듯한 환경에서도 벡터와 전문검색 결과를 융합한 뒤 경량 재정렬기로 상위를 바로잡는 2단 구성이 자주 쓰입니다.

모델 선택

상황 모델
기본 (오픈) BAAI/bge-reranker-v2-m3. cross-encoder, Apache-2.0, 통합 도구 풍부
최상위급 (오픈) Qwen3-Reranker 0.6B, 4B, 8B. Apache-2.0. ONNX와 GGUF로 경량 배포 가능
경량 listwise (오픈) Jina Reranker v3 0.6B. 작은 크기로 더 큰 모델을 앞선다고 보고
한국어 dragonkue/bge-reranker-v2-m3-ko. 한국어 RAG 재정렬 실무 1순위
호스티드 Cohere Rerank. 운영 부담을 줄이는 대신 API 과금

LangChain과 LlamaIndex는 이들 재정렬기를 retriever 뒤 후처리 단계로 붙이는 통합을 기본 제공합니다.

재정렬이 안 통할 때

여기가 실무에서 자주 놓치는 지점입니다.

재정렬은 1차 검색을 대체하는 게 아니라 덧붙이는 것입니다. 1차가 후보 집합을 정하고, 재정렬이 그 안의 순서를 정합니다. 그래서 재정렬의 상한은 언제나 1차 recall에 묶여 있습니다.

정답이 애초에 후보 100개 안에 없으면 재정렬은 아무것도 못 합니다. 리랭커를 붙였는데 성능이 안 오른다면, 재정렬 파라미터가 아니라 검색부터 고쳐야 합니다. 청킹이나 임베딩 모델, 하이브리드 구성을 먼저 봐야 한다는 뜻입니다.

마치며

핵심 세 가지로 정리합니다.

  1. 재정렬은 빠른 1차 검색(recall)과 정밀한 2차 재정렬(precision)을 겹친 2단계 검색입니다.
  2. 차이의 근원은 아키텍처입니다. bi-encoder는 질의와 문서를 따로 봐서 빠르고 거칠며, cross-encoder는 함께 봐서 느리고 정밀합니다.
  3. 재정렬의 상한은 1차 recall이 정합니다. 정답이 후보에 없으면 재정렬은 무력합니다.

용어 정리

용어 한 줄 뜻
재정렬 (Reranking) 1차 검색 top-k 후보를 정밀 모델로 다시 점수 매겨 순서를 바꾸는 후처리
2단계 검색 빠른 검색(recall)과 정밀 재정렬(precision)을 겹친 구성
recall / precision 정답을 후보에 담기 / 담긴 것 중 관련 있는 걸 위로 올리기
bi-encoder 질의와 문서를 따로 임베딩해 벡터 유사도로 검색하는 1차 검색기
cross-encoder 질의와 문서를 함께 넣어 관련도를 내는 정밀 재정렬기
pointwise / listwise 후보를 하나씩 점수 / 여러 후보를 함께 비교해 순위
ColBERT, late interaction 토큰별 임베딩과 MaxSim으로 bi와 cross를 절충한 방식
MaxSim 질의 토큰마다 문서 토큰 중 최대 유사도를 취해 합산하는 연산
MTEB 임베딩과 리랭킹 성능을 재는 공용 벤치마크

참고자료

'RAG > Retrieval' 카테고리의 다른 글

HNSW  (0) 2025.01.06
Chunking (청킹) 이란?  (0) 2024.11.01
Hybrid search  (0) 2024.09.25

댓글