[LLM Wiki 19] RRF: 여러 검색 결과를 순위 기준으로 합치는 방법
RRF(Reciprocal Rank Fusion)의 개념, 계산 방식, hybrid search와 QMD에서의 역할, rerank와의 차이, 장단점과 한계를 설명한다.
RRF는 Reciprocal Rank Fusion의 줄임말이다. 여러 검색 결과 목록을 하나로 합칠 때 쓰는 ranking fusion 방법이다.
검색 시스템에서는 보통 검색 방법을 하나만 쓰지 않는다. 정확한 단어를 잘 찾는 BM25/FTS 검색도 쓰고, 의미가 비슷한 문서를 찾는 vector search도 쓰고, HyDE나 query expansion으로 만든 여러 query도 같이 쓴다.
문제는 각 검색 방식의 점수 체계가 다르다는 점이다. BM25 점수 12.8과 vector similarity 0.84를 그대로 비교하면 안 된다. 둘은 같은 단위가 아니다.
RRF는 이 문제를 단순하게 푼다.
점수를 직접 비교하지 말고, 각 검색 결과에서 몇 등으로 나왔는지만 보자는 방식이다.

왜 필요한가
예를 들어 사용자가 “인증 설정 어디서 해?”라고 물었다고 하자.
BM25 검색은 authentication, config, settings 같은 단어가 정확히 들어간 문서를 잘 찾는다. 그래서 API 설정 문서가 1위로 나올 수 있다.
Vector 검색은 “인증 옵션을 초기화하는 방법”, “로그인 설정을 로드하는 흐름”처럼 표현은 다르지만 의미가 가까운 문서를 찾을 수 있다. 그래서 인증 가이드가 1위로 나올 수 있다.
둘 중 하나만 고르면 손해가 생긴다.
- BM25만 쓰면 단어는 맞지만 의미가 약한 문서가 올라올 수 있다.
- Vector만 쓰면 의미는 맞지만 함수명, 설정 키, 에러 메시지 같은 정확한 단서를 놓칠 수 있다.
- 둘을 단순 점수 합산하면 점수 스케일이 달라서 왜곡될 수 있다.
RRF는 “각 방식에서 상위에 반복해서 등장하는 문서”를 좋은 후보로 본다. 한 검색에서는 2위, 다른 검색에서는 1위라면 꽤 강한 신호다.
RRF 계산 방식
RRF의 기본 공식은 간단하다.
RRF score = Σ 1 / (k + rank)
여기서 rank는 각 검색 결과 목록에서의 순위다. k는 순위 차이가 너무 극단적으로 벌어지지 않게 만드는 완충값이다. 보통 60을 많이 쓴다.
예를 들어 어떤 문서가 BM25에서는 2위, vector search에서는 1위라면 점수는 이렇게 계산된다.
1 / (60 + 2) + 1 / (60 + 1)
반대로 어떤 문서가 BM25에서만 1위이고 vector 결과에는 없다면 이렇게 된다.
1 / (60 + 1)
즉 여러 목록에서 반복해서 높은 순위에 나온 문서가 유리하다.

실제 구현에서는 여기에 weight를 붙일 수 있다.
weighted RRF score = Σ weight / (k + rank)
예를 들어 원본 query 결과를 더 믿고 싶다면 원본 query 결과 목록에 2배 가중치를 줄 수 있다. QMD도 이런 방향의 설계를 사용한다. structured search에서는 첫 번째 ranked list에 더 큰 가중치가 붙기 때문에 가장 중요한 query를 앞에 두는 것이 좋다.
RRF와 Rerank는 다르다
RRF와 rerank는 자주 같이 나오지만 역할이 다르다.
RRF는 여러 검색 결과 목록을 합친다.
Rerank는 이미 모인 후보를 질문 기준으로 다시 평가한다.
비유하면 RRF는 여러 심사위원의 후보 명단을 하나로 합치는 단계이고, rerank는 그 후보들을 다시 면접해서 최종 순서를 정하는 단계다.
검색 flow에서는 보통 이렇게 놓인다.
사용자 질문
→ BM25 검색
→ Vector 검색
→ HyDE 검색
→ RRF로 후보 통합
→ 상위 후보 chunk 선택
→ Rerank로 재정렬
→ LLM 답변 생성
RRF는 recall을 확보하는 쪽에 가깝다. 여러 검색 방식에서 나온 후보를 최대한 균형 있게 모은다.
Rerank는 precision을 높이는 쪽에 가깝다. 모인 후보 중 실제 질문에 더 맞는 것을 위로 올린다.
QMD에서 RRF가 쓰이는 위치
QMD는 BM25 full-text search, vector semantic search, query expansion, HyDE, local rerank를 조합하는 검색 엔진이다. 여기서 RRF는 여러 검색 결과 목록을 하나로 합치는 핵심 접착제 역할을 한다.
QMD README와 소스 기준으로 query pipeline은 대략 다음 흐름을 가진다.

QMD의 일반 query 검색에서는 자연어 질문을 local query expansion 모델이 lex, vec, hyde 형태로 확장할 수 있다. 그러면 각 query가 별도 검색 결과 목록을 만든다.
QMD의 structured search에서는 호출자가 이미 lex, vec, hyde typed query를 넘긴다. 이 경우 QMD는 query expansion을 다시 하지 않고, 각 typed query를 실행한 뒤 RRF로 합친다.
그 다음 후보 문서에서 chunk를 고르고, reranker가 chunk를 다시 평가한다. 최종 점수는 RRF 위치 점수와 reranker 점수를 섞는다.
QMD는 이때 position-aware blending을 사용한다.
- RRF rank 1-3: RRF 비중을 크게 유지한다.
- RRF rank 4-10: RRF와 rerank를 균형 있게 섞는다.
- RRF rank 11 이후: reranker 판단 비중을 더 키운다.
이 설계의 의도는 분명하다. 검색 단계에서 매우 강하게 잡힌 상위 후보를 reranker가 쉽게 망가뜨리지 않게 하면서, 뒤쪽 후보는 reranker가 더 적극적으로 재평가하게 만드는 것이다.
실제 예시
질문:
가격 때문에 막힌 고객 미팅 찾아줘
검색 시스템은 여러 query를 만들 수 있다.
lex: 가격 예산 고객 미팅
lex: budget price objection
vec: customer meeting delayed because of pricing concerns
hyde: The customer delayed the purchasing decision because the proposed price exceeded the available budget.
각 검색 결과는 다르게 나올 수 있다.
BM25는 “가격”, “예산”이라는 단어가 정확히 들어간 회의록을 찾는다.
Vector search는 “too expensive”, “budget concern”, “cost blocker” 같은 표현이 들어간 영어 문서를 찾을 수 있다.
HyDE는 “고객이 예산 문제 때문에 구매를 미뤘다”는 가상의 답변 문장과 비슷한 실제 회의록을 찾을 수 있다.
RRF는 이 결과들을 합친다. 어떤 회의록이 lex에서도 상위, vector에서도 상위, HyDE에서도 상위라면 최종 후보에서 강하게 올라온다.
그 다음 rerank가 “이 문서가 정말 가격 때문에 막힌 고객 미팅인가?”를 다시 판단한다.
언제 쓰면 좋은가
RRF는 hybrid search에 특히 잘 맞는다.
다음 상황에서 유용하다.
- BM25와 vector search를 같이 쓰는 경우
- query expansion으로 여러 query를 만든 경우
- HyDE 결과와 일반 vector 결과를 함께 쓰는 경우
- 검색 backend마다 점수 스케일이 다른 경우
- 일단 후보를 넓게 모은 뒤 rerank로 정밀도를 높이고 싶은 경우
- agent가 lex, vec, hyde query를 직접 설계하는 structured search를 쓰는 경우
특히 RAG 시스템에서는 RRF가 실용적이다. 답변 LLM이 읽을 후보 문서를 만들기 전에, 여러 검색 신호를 안정적으로 합칠 수 있기 때문이다.
언제 덜 적합한가
검색 방식이 하나뿐이라면 RRF가 필요 없다. BM25만 쓰거나 vector search만 쓴다면 합칠 목록이 없다.
검색 목록의 품질이 매우 낮아도 RRF는 해결책이 아니다. RRF는 여러 ranking을 합치는 방법이지, 틀린 query를 고쳐주는 모델이 아니다.
또한 RRF는 문서 내용을 깊게 이해하지 않는다. 순위만 본다. 그래서 “왜 이 문서가 질문에 맞는가”를 정밀하게 판단하려면 reranker가 필요하다.
메타데이터 필터가 중요한 경우에도 RRF만으로는 부족하다. 예를 들어 “2025년 5월 이후 고객 미팅만” 같은 조건은 ranking fusion 전에 filter로 처리하는 편이 더 안전하다.
장점
첫째, 구현이 단순하다. rank만 있으면 계산할 수 있다.
둘째, 점수 정규화가 필요 없다. BM25, cosine similarity, reranker 이전 점수처럼 서로 다른 점수를 억지로 맞추지 않아도 된다.
셋째, robust하다. 특정 검색 backend 하나가 조금 흔들려도, 다른 backend에서 반복적으로 상위에 나온 문서는 살아남을 수 있다.
넷째, hybrid search와 잘 맞는다. lexical search와 semantic search를 자연스럽게 합칠 수 있다.
한계
첫째, rank만 보기 때문에 점수 차이를 버린다. 1위와 2위의 점수 차이가 아주 큰 경우에도 RRF는 단지 1위, 2위로만 본다.
둘째, 좋은 query가 전제다. query expansion이나 structured search에서 query를 잘못 만들면, 관련 없는 결과 목록이 RRF에 섞인다.
셋째, backend별 신뢰도를 세밀하게 반영하려면 weight 설계가 필요하다. 모든 목록을 같은 가중치로 합치면 원본 query의 정확한 신호가 희석될 수 있다.
넷째, 최종 답변 품질을 보장하지 않는다. RRF는 후보 융합이고, 답변 생성은 아니다. 답변 품질은 chunk 선택, rerank, prompt 구성, main LLM의 판단까지 함께 봐야 한다.
정리
RRF는 여러 검색 결과를 합치는 실용적인 방법이다.
핵심은 “점수를 비교하지 말고 순위를 합치자”다.
BM25는 정확한 단어를 잡고, vector search는 의미를 잡고, HyDE는 짧거나 모호한 질문을 보완한다. RRF는 이 결과들을 하나의 후보 목록으로 합친다. 그 다음 rerank가 더 정밀하게 줄을 세운다.
QMD에서 RRF는 단순한 보조 기능이 아니다. BM25, vector, HyDE, structured search, rerank를 연결하는 중간 접착제다.
그래서 QMD의 검색 구조를 이해하려면 RRF를 “검색 결과를 합치는 순위 기반 fusion 단계”로 잡아두면 된다. Rerank는 그 다음 단계다.