RAG 검색을 분해하여 설계하기: 청킹(Chunking), RRF, 리랭커(Reranker)
요약
본 기사는 RAG 검색의 품질 개선 요소를 청킹, 후보 융합(fusion), 리랭커 등 단계별로 분리하여 설계하는 방법을 제시합니다. 특히 검색에 필요한 세밀한 단위와 답변 생성에 필요한 넓은 컨텍스트를 분리하는 '부모-자식 검색' 기법을 소개하며, 각 구성 요소를 독립적으로 측정할 수 있는 데이터 계약의 중요성을 강조합니다.
핵심 포인트
- RAG 개선 시 여러 요소를 동시에 변경하지 않고 단계별로 분석해야 합니다.
- 검색(Retrieval)과 생성 컨텍스트는 분리되어야 하며, '부모-자식 검색'이 이를 구현하는 방법입니다.
- 청킹 방식은 단순히 토큰 자르기가 아닌, '어디서 자를지'와 '언제 인코딩할지'로 접근해야 합니다.
- Dense Retrieval의 세분성(granularity)과 LongRAG처럼 긴 컨텍스트 결합을 비교 분석하는 것이 중요합니다.
RAG (Retrieval-Augmented Generation, 검색 확장 생성)의 검색 품질을 개선할 때, 원인을 분리하고 싶다면 chunk_size, Embedding model, Hybrid Search, Reranker를 동시에 변경하는 것을 피해야 합니다. 최종 답변이 좋아지더라도 어떤 변경이 효과가 있었는지 알 수 없기 때문입니다.
구현에서는 검색 처리를 다음 단계(stage)로 나눕니다.
source → chunking → candidate retrieval → fusion → rerank
→ context selection → generation
본 기사에서는 청킹(Chunking, 문서를 검색 단위로 분할하는 처리), BM25와 Dense Retrieval의 후보 융합(fusion), Cross Encoder를 이용한 리랭크(rerank)를 독립적으로 측정 가능한 데이터 계약(data contract)으로 정리합니다.
앞 단계의 Dense Retrieval은 지난번 Dense Retrieval을 구현하는 과정에서 DPR, 거리 척도(distance metric), ANN 설계를 다루었습니다. 방식별 배경이나 구체적인 예시를 그림 순서대로 확인하고 싶다면 개인 블로그 완전판도 참조해 주세요.
검색 단위와 생성 컨텍스트 분리하기
청킹을 단순히 '긴 문장을 일정한 토큰 수로 자르는 전처리'라고만 생각하면, 검색 시 필요한 세밀한 정도(granularity)와 답변 시 필요한 컨텍스트를 혼동하게 됩니다.
| Unit | 책임 (責務) | 예시 |
|---|---|---|
| source document | 업데이트, 권한, 인용의 정본 | 취업 규칙 PDF |
| ... | ||
| 예를 들어, '수습 기간 중 재택근무 신청이 가능한지'라는 쿼리에 대해 검색용 청크가 '재택근무 신청은 가능'하기만 해서는 충분하지 않습니다. 직전의 '수습 기간 중 제외'가 별도의 청크라면, 관련도가 높아도 오해를 불러일으키는 근거가 됩니다. |
Dense X Retrieval은 document, passage, sentence, proposition 등 다양한 검색 세분성(retrieval granularity)을 비교하며, 이 세분성이 retrieval과 하류 작업(downstream task)에 영향을 미친다는 것을 보여주었습니다. 반면, LongRAG는 짧은 단위로 인한 컨텍스트 손실과 검색 공간의 확장에 대응하여, 긴 retrieval unit과 long-context LLM을 결합하고 있습니다.
이 둘은 모순되지 않습니다. 검색의 초점과 답변에 필요한 컨텍스트 사이에는 트레이드오프(trade-off)가 존재하므로, 코퍼스(corpus)와 쿼리에 따라 측정해야 한다는 의미입니다.
부모-자식 검색(Parent-child retrieval)으로 역할 분담하기
검색 시에는 작은 child를 사용하고, 채택할 때 parent_id로부터 넓은 섹션으로 돌아가면, retrieval unit과 generation context를 분리할 수 있습니다.

이 방식에서도 parent가 너무 크면 노이즈(noise)가 돌아옵니다. 같은 parent의 child가 여러 번 히트했을 때의 중복 제거(deduplication)와, parent 단위의 점수 집계 규칙도 필요합니다.
청킹 방식은 다른 축을 조작한다
주요 방식을 '어디서 자를지'와 '언제 인코딩할지'로 나눕니다.

| 방식 | 조작하는 축 | 장점 | 주요 위험 요소 (risk) |
|---|---|---|---|
| 고정 길이 (Fixed length) | 토큰 수 | 재현하기 쉬움 | 의미나 표를 중간에 자름 |
| ... | |||
| Late Chunking은 긴 텍스트를 먼저 Transformer에 입력하여, 컨텍스트화된 토큰 표현을 청크 경계별로 풀링(pooling)합니다. Semantic chunking이 '어디서 자는지'를 다룬다면, Late Chunking은 '자르기 전후 어느 쪽에서 컨텍스트화할지'를 다룹니다. |
이 두 가지를 같은 선택지로 비교하면 설계 축이 무너집니다. 예를 들어, 제목 경계를 사용하면서도 Late Chunking으로 인코딩하는 구성도 가능합니다.
오버랩(overlap)은 경계 보험과 비용의 교환이다
청크 길이와 문서 길이 간에 
오버랩을 늘리면 경계를 넘는 근거를 남기기 쉬워지지만, Embedding 계산, 인덱스 용량, 중복 검색, LLM에 전달하는 토큰도 증가합니다. 평가에서는 경계 쿼리의 Hit@k와 근접 청크의 중복률을 동시에 측정해야 합니다.
또한, 일본어의 글자 수와 토큰 수는 일치하지 않습니다. 글자 수로 분할하는 경우에도 인코딩 직전에 대상 모델의 tokenizer를 사용하여 길이를 측정하고 입력에서 잘림(truncation)을 감지해야 합니다.
Hybrid Search는 후보 집합을 확장하는 단계
Dense Retrieval은 동의어를 찾기 쉽지만, error code, 제품 번호, 날짜 등 정확한 토큰(exact token)을 누락할 수 있습니다. BM25와 같은 sparse retrieval(단어 일치를 사용하는 검색)은 고유어에 강하지만, 쿼리와 문서에서 어휘가 다르면 동의어를 찾지 못합니다.

Hybrid Search에서는 두 가지 후보를 모두 가져와 공통 document ID로 정규화한 후 융합(fusion)합니다. 이때 BM25 score와 cosine similarity를 단순히 더해서는 안 됩니다. 점수 스케일이 다르기 때문입니다.
RRF (Reciprocal Rank Fusion, 역순위 융합)는 raw score가 아닌 순위를 사용합니다. RRF 원 논문에 기반한 점수는 다음과 같습니다.

하지만 순위로 변환하면 1위와 2위의 raw score 차이가 큰 정보가 손실됩니다. rank_constant
과 candidate window를 고정값으로 생각하지 말고, 정규화 점수 융합(normalized score fusion)과 동일한 평가 세트에서 비교해야 합니다. Elasticsearch의 RRF 자료에서도 rank_constant
와 rank_window_size
는 별개의 파라미터입니다.
RRF function의 책임을 제한하기
다음 예시는 rank list의 융합만 담당합니다. ACL, parent dedup, rerank, context 선택을 같은 함수에 넣지 않음으로써, 후보가 사라진 단계를 추적할 수 있습니다.
from __future__ import annotations
import logging
from collections import defaultdict
...
실제 운영에서는 입력 리스트가 동일한 tenant・ACL・source version・index snapshot을 사용했는지 여부를 융합 전에 검증하는 것도 중요합니다. 검색 결과의 존재만으로 정보가 유출될 가능성이 있기 때문에, 가져온 후 ACL 필터링(filter) 단계에서도 허용된 후보가 부족할 수 있습니다.
Reranker는 이미 확보한 후보들만 자세히 살펴본다
Dual Encoder는 쿼리와 패시지(passage)를 별도로 인코딩할 수 있어, 코퍼스 벡터를 사전에 계산할 수 있습니다. Cross Encoder는 쿼리와 패시지를 동시에 입력하여 토큰 간의 관계를 이용해 관련성(relevance)을 평가합니다.

| 관점 | Dual Encoder | Cross Encoder |
|---|---|---|
| 코퍼스 측 사전 계산 | 가능 | 쌍(pair)마다 필요 |
| ... | ||
| Passage Re-ranking with BERT는 BERT에 쿼리와 후보 패시지를 입력하여 rerank하는 구성을 다루었습니다. Sentence-BERT가 보여주듯이, pairwise BERT를 대규모의 모든 조합에 적용하는 비용은 크기 때문에, first-stage retrieval과 역할을 분리합니다. |
Reranker는 candidate 집합에 없는 정답을 복원할 수 없습니다. 따라서 파라미터도 하나의 top_k
로 통합하지 않습니다.
| Parameter | 측정하는 것 | 크게 했을 때의 주요 비용 |
|---|---|---|
candidate_k | 정답이 후보에 포함되는지 | 검색・융합 지연 시간(latency) |
rerank_k | 후보 내 순위가 개선되는지 | Cross Encoder 추론 비용(cost) |
context_k | 근거가 LLM에 남는지 | 토큰, 노이즈, 중복 |
예를 들어 각 retriever에서 50건씩 가져오고, 융합 후 40건을 rerank하고, deduplication과 token budget을 거친 5건을 context로 채택한다고 가정합니다. 이는 권장값이 아니라, 단계별 건수를 추적하는 예시입니다.
최종 답변이 아닌 단계별로 평가한다
답변의 정오 여부만으로는 Chunking과 Reranker 중 어느 것을 수정해야 할지 결정할 수 없습니다.

⚠️ [IMG:N] 형식 토큰은 이미지 placeholder 입니다. 번역하지 말고 원래 위치에 그대로 유지하세요.
| 단계 (Stage) | 지표 예시 (Metric例) | 질문 (問い) |
|---|---|---|
| Chunking | gold span coverage, 중복률 | 정답 근거를 보존했는가 |
| ... | ||
| 평가 세트에는 한 문장으로 답할 수 있는 사실(fact)뿐만 아니라, 조건과 예외가 분리된 질문, 표의 헤더와 셀이 필요한 질문, 모델 번호/날짜, 답변 없음 질문을 포함합니다. |
변경 사항은 다음 순서로 하나씩 추가합니다.
- fixed-size, 오버랩(overlap) 없음으로 베이스라인(baseline) 설정.
- 청크 길이만 변경.
- 오버랩만 추가.
- 구조 인식 분할(structure-aware分割)과 비교.
- BM25를 추가하여 union recall 측정.
- fusion을 추가.
- reranker를 추가하여 순위 개선 및 지연 시간(latency) 측정.
- context selection 후 답변과 인용(citation) 측정.
각 실행(run)에는 source_version,
chunker_version,
embedding_version,
검색기별 후보 ID와 순위, fusion 순위, reranker 점수, context에서 제외한 이유를 남깁니다.
장애 수정 순서
| 증상 | 먼저 확인할 단계 (stage) | 다음 확인 사항 |
|---|---|---|
| 정답 문장이 chunk에 남아있지 않음 | Chunking | parser와 source span coverage |
| ... | ||
| 사람이 고른 정답 context를 주어도 답변할 수 없다면, retrieval을 개선해도 해결되지 않습니다. 반대로 oracle context에서는 답할 수 있다면, Chunking부터 context selection까지 원인이 있습니다. |
요약
Chunking은 무엇을 검색 순위의 단위로 삼고, 무엇을 답변 근거로서 LLM에 전달할지 결정하는 data model입니다. 만능인 chunk size를 찾기보다는, retrieval unit과 generation context를 분리하여 평가해야 합니다.
Hybrid Search는 sparse와 dense의 후보 집합을 확장하고, RRF는 서로 다른 score scale을 순위로 변환하여 융합합니다. Cross Encoder reranker는 후보 내의 상세한 관련도를 평가할 수 있지만, 검색되지 않은 정답은 구할 수 없습니다.
candidate_k,
rerank_k,
context_k
를 분리하고 각 단계(stage)의 입력・출력・metric을 추적하면,
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn ML의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기