검색
← 모듈 로드맵

RAG 파이프라인 설계: 청킹 · 하이브리드 검색 · 리랭킹 · 쿼리 재작성

강의 · 준전문가 · KAITABASE 정리

원제 · Designing a RAG Pipeline

청킹 · 하이브리드 검색 · RRF · 리랭킹 · 쿼리 재작성으로 RAG 검색 단계를 설계하는 수업

먼저 알아야 할 것

BM25와 벡터 검색recall@k바이 인코더와 크로스 인코더RAG 기본 구조

다루는 내용

RAG 품질을 좌우하는 검색 단계 부품을 다룹니다. 청크 크기 · 겹침 · 맥락 붙인 청크, BM25와 벡터 검색을 순위로 합치는 RRF 계산, 크로스 인코더 리랭킹의 비용과 2단계 구조, 쿼리 재작성 · 다중 쿼리 · 하위 질문 분해, 프롬프트 조립 원칙과 단계별 점검 순서를 정리합니다.

해설

RAG 파이프라인 설계: 청킹 · 하이브리드 검색 · 리랭킹 · 쿼리 재작성

검색 증강 생성(RAG)은 "질문 → 관련 문서 찾기 → 문서를 붙여 LLM이 답하기"라는 단순한 생각에서 출발합니다. 그런데 실제로 만들어 보면 답이 틀리는 이유의 상당수가 LLM이 아니라 검색 단계 에 있습니다. 문서를 어떻게 자르는지(청킹), 키워드 검색과 벡터 검색을 어떻게 합치는지(하이브리드 · RRF), 후보를 어떻게 다시 줄 세우는지(리랭킹), 질문을 어떻게 고쳐 묻는지(쿼리 재작성)가 품질을 좌우합니다. 이 수업은 이 부품들을 하나씩 계산과 함께 설명합니다.

항목내용
참고 출처Anthropic, Introducing Contextual Retrieval(2024-09-19) · RAG 서베이(arXiv 2312.10997) · RRF(Cormack 외, SIGIR 2009) · BERT 리랭킹(arXiv 1901.04085) · 쿼리 재작성(arXiv 2305.14283) · BEIR(arXiv 2104.08663)
트랙 · 수준RAG·검색 · 중급
이 수업이 다루는 범위기본 RAG 흐름, 청킹 전략, 맥락 붙인 청크, 하이브리드 검색과 RRF, 바이 인코더 vs 크로스 인코더 리랭킹, 쿼리 재작성 · 확장 · 분해, 프롬프트 조립, 단계별 점검 순서

들어가기 전에

한눈에 보기

  • RAG 파이프라인을 색인 · 검색 · 후처리 · 생성의 네 구간으로 나눠 설명할 수 있습니다.
  • 청크 크기와 겹침이 품질 · 비용에 어떤 영향을 주는지, 청크에 맥락을 붙이는 방법을 압니다.
  • BM25와 벡터 검색 결과를 RRF로 합치는 계산을 직접 해 봅니다.
  • 크로스 인코더 리랭커가 왜 정확하지만 비싼지, 그래서 왜 "넓게 찾고 좁게 다시 고르는" 2단계 구조를 쓰는지 압니다.
  • 쿼리 재작성 · 다중 쿼리 · 하위 질문 분해가 어떤 문제를 푸는지 압니다.

1. 전체 흐름

RAG 서베이(2312.10997)는 가장 기본 형태(Naive RAG)를 색인 → 검색 → 생성 세 단계로 설명합니다. 문서를 청크로 나눠 벡터로 바꿔 저장하고, 질문과 가장 비슷한 상위 KK 개 청크를 찾고, 질문과 청크를 함께 LLM에 넣어 답을 만듭니다. 서베이는 여기에 검색 전 · 후 처리를 더한 것을 Advanced RAG, 부품을 자유롭게 바꿔 끼우는 구조를 Modular RAG라고 부릅니다.

mermaid
flowchart LR
  subgraph 색인
    D[원문 문서] --> CH[청킹<br/>크기 · 겹침 · 맥락 붙이기]
    CH --> E[임베딩 → 벡터 인덱스]
    CH --> B[BM25 역색인]
  end
  Q[사용자 질문] --> RW[쿼리 재작성 · 확장]
  RW --> V[벡터 검색 상위 N]
  RW --> K[BM25 검색 상위 N]
  E --> V
  B --> K
  V --> F[RRF로 합치기]
  K --> F
  F --> RR[리랭커로 상위 K 재정렬]
  RR --> P[프롬프트 조립<br/>출처 · 지시]
  P --> L[LLM 답변 + 인용]

왜 검색이 중요한가. LLM은 프롬프트에 없는 정보를 정확히 답할 수 없습니다. 정답이 담긴 청크가 상위 KK 개에 들어오지 않으면, 아무리 좋은 모델도 추측하거나 "모른다"고 해야 합니다. 그래서 RAG 개선은 대개 검색 재현율(recall@K)부터 봅니다.

2. 청킹: 문서를 어떻게 자르나

직관. 청크는 "검색해서 꺼내 오는 한 덩어리"입니다. 너무 크면 관련 없는 내용이 섞여 검색 점수가 흐려지고 프롬프트 비용이 늘어납니다. 너무 작으면 답에 필요한 앞뒤 맥락이 잘립니다.

RAG 서베이는 고정 토큰 수(예: 100, 256, 512)로 자르는 것이 가장 흔하다고 정리하고, 큰 청크는 맥락을 더 담지만 잡음과 비용이 늘고, 작은 청크는 잡음이 적지만 맥락이 부족할 수 있다고 설명합니다. 문장이 잘리는 문제를 줄이려고 재귀 분할 · 슬라이딩 윈도(겹침)를 쓰고, 작은 문장 단위로 찾되 앞뒤 문장까지 붙여 LLM에 넘기는 Small2Big 같은 방법도 소개합니다.

숫자로 해 보기(해설용). 1만 토큰 문서를 512토큰 청크 · 64토큰 겹침으로 자르면 한 칸씩 512−64=448512-64=448 토큰 이동합니다. 청크 수는 ⌈(10000−512)/448⌉+1=23\lceil (10000-512)/448\rceil+1 = 23 개입니다. 겹침 덕분에 경계에 걸친 문장도 어느 한 청크에는 온전히 들어가지만, 저장 · 임베딩하는 토큰은 원문보다 조금 늘어납니다.

실무 체크리스트(해설용).

  1. 문서 구조(제목 · 문단 · 표)를 먼저 살려서 자릅니다. 표나 코드 블록 가운데를 자르지 않습니다.
  2. 청크마다 메타데이터(문서 제목, 날짜, 페이지, 권한)를 붙입니다. 서베이도 메타데이터로 검색 범위를 좁히는 방법을 소개합니다.
  3. 크기는 정답이 없으므로, 아래 4절 이후의 평가 세트로 두세 가지를 비교해 고릅니다.

맥락 붙인 청크(Contextual Retrieval). Anthropic(2024-09-19)은 청크만 떼어 놓으면 "이 회사의 매출이 3% 늘었다"처럼 누구 · 언제 가 빠진 문장이 된다는 문제를 지적했습니다. 그래서 LLM에게 문서 전체와 청크를 주고, 청크 앞에 붙일 짧은 설명(보통 50~100토큰)을 쓰게 한 뒤, 그 설명을 붙인 상태로 임베딩(Contextual Embeddings)하고 BM25 색인(Contextual BM25)도 만들었습니다. 이 글이 보고한 상위 20개 검색 실패율(1 − recall@20)은 다음과 같습니다.

구성실패율감소율
기본 임베딩5.7%—
맥락 붙인 임베딩3.7%35%
+ 맥락 붙인 BM252.9%49%
+ 리랭킹1.9%67%

같은 글은 지식 베이스가 20만 토큰(약 500쪽) 미만이면 RAG 없이 전체를 프롬프트에 넣는 방법도 고려하라고 권합니다. "RAG가 늘 필요한가"를 먼저 따져 보라는 뜻입니다.

3. 하이브리드 검색과 RRF

왜 두 가지를 섞나. BM25(키워드)는 제품 코드 · 오류 번호 · 고유명사처럼 글자가 정확히 맞아야 하는 질문에 강합니다. 벡터 검색은 표현이 달라도 뜻이 같은 질문에 강합니다. BEIR(2104.08663)는 18개 데이터셋에서 제로샷 검색을 비교해 BM25가 견고한 기준선이라는 결과를 보고했습니다. 학습 데이터와 다른 분야에서는 밀집 검색만 믿기 어렵다는 뜻이고, 그래서 둘을 함께 쓰는 하이브리드 검색이 흔히 쓰입니다.

점수를 그냥 더하면 안 되나. BM25 점수(예: 12.3)와 코사인 유사도(예: 0.82)는 단위가 달라 바로 더하면 한쪽이 지배합니다. 그래서 점수 대신 순위 를 합치는 방법을 씁니다.

RRF(Reciprocal Rank Fusion, Cormack 외 2009).

RRF(d)=∑r∈R1k+r(d)\mathrm{RRF}(d) = \sum_{r\in R}\frac{1}{k + r(d)}
기호뜻
dd문서(청크)
RR합칠 검색 결과 목록들(예: BM25 목록, 벡터 목록)
r(d)r(d)그 목록에서 dd 의 순위(1부터). 목록에 없으면 그 항은 0
kk상위 순위의 영향을 누그러뜨리는 상수. 논문은 예비 실험에서 k=60k=60 으로 정해 이후 바꾸지 않았고, 값 선택이 결정적이지는 않았다고 적었습니다

숫자로 해 보기(해설용). BM25 상위 4개가 [A, B, C, D], 벡터 상위 4개가 [C, E, B, F] 라고 합시다(k=60k=60).

  • C: 163+161=0.01587+0.01639=0.03227\frac1{63}+\frac1{61}=0.01587+0.01639=0.03227
  • B: 162+163=0.03200\frac1{62}+\frac1{63}=0.03200
  • A: 161=0.01639\frac1{61}=0.01639, E: 162=0.01613\frac1{62}=0.01613, D · F: 164=0.01563\frac1{64}=0.01563

합친 순위는 C, B, A, E, D/F 입니다. 두 목록 모두에서 상위권인 C와 B가 한쪽 1등인 A보다 앞섭니다. k=60k=60 처럼 큰 값을 쓰면 1등과 2등의 차이가 작아져 "여러 목록에 고르게 나온 문서"가 유리해집니다. k=1k=1 이면 C 0.75, B 0.583, A 0.5로 순서는 같지만 1등 보너스가 훨씬 커집니다.

4. 리랭킹: 넓게 찾고, 좁게 다시 고르기

바이 인코더 vs 크로스 인코더. 벡터 검색은 질문과 문서를 따로 임베딩해 내적만 하는 바이 인코더(bi-encoder)입니다. 문서 벡터를 미리 계산해 둘 수 있어 빠르지만, 질문과 문서의 단어가 서로를 직접 보지 못합니다. 크로스 인코더(cross-encoder)는 질문과 문서를 한 입력으로 붙여 트랜스포머에 넣고 관련도를 직접 출력합니다. 더 정확하지만 질문마다 모든 후보를 모델에 다시 통과시켜야 합니다.

얼마나 비싼가. Sentence-BERT 논문은 문장 1만 개에서 가장 비슷한 쌍을 BERT 크로스 인코더로 찾으려면 약 5천만 번(49,995,000번)의 추론, V100 GPU로 약 65시간이 걸린다고 계산했습니다. SBERT 임베딩으로는 약 5초였습니다. 그래서 크로스 인코더는 전체 검색이 아니라 상위 후보 재정렬 에만 씁니다.

BERT 리랭커의 예(Nogueira · Cho 2019). 질문을 문장 A, 문단을 문장 B로 넣고(질문은 최대 64토큰, 전체는 최대 512토큰으로 자름), BERT-large의 [CLS] 벡터로 "관련 있음" 확률을 내는 이진 분류기로 학습했습니다. MS MARCO 문단 순위 과제에서 당시 최고 기록보다 MRR@10을 상대적으로 27% 높였다고 보고했습니다.

2단계 구조(해설용 수치). 1단계(BM25 + 벡터 + RRF)로 상위 50~100개를 넓게 모으고, 2단계 리랭커로 상위 5~20개만 LLM에 넘깁니다. Anthropic 글은 자기 실험에서 상위 20개를 넘기는 것이 10개나 5개보다 나았다고 보고했습니다. 이 수치는 데이터마다 달라지므로 출발점으로만 씁니다.

5. 쿼리 재작성: 질문을 검색하기 좋게 고치기

문제. 사용자의 질문은 검색에 좋은 형태가 아닐 때가 많습니다. "그거 작년이랑 비교하면?"처럼 대화 맥락에 기대거나, 여러 질문이 한 문장에 섞여 있거나, 문서와 다른 용어를 씁니다.

방법들.

  • 재작성(Rewrite-Retrieve-Read, Ma 외 2023): 검색 전에 질문을 검색용 쿼리로 다시 씁니다. 이 논문은 LLM에게 쿼리를 쓰게 하고 웹 검색으로 문서를 가져오는 구성에 더해, 작은 언어 모델(T5-large)을 재작성기로 두고 LLM 독자의 성능을 보상으로 삼는 강화학습으로 훈련했습니다. 개방형 QA와 객관식 QA에서 일관된 향상을 보고했습니다.
  • 다중 쿼리(Multi-Query): 질문을 여러 표현으로 바꿔 병렬 검색하고 결과를 합칩니다(합칠 때 RRF가 잘 맞습니다).
  • 하위 질문 분해(Sub-Query): "A사와 B사의 2023년 매출 성장률 비교"를 "A사 2023 매출", "B사 2023 매출"처럼 나눠 각각 검색합니다. RAG 서베이가 이런 확장 · 분해 방법을 정리해 두었습니다.
  • 가상 문서(HyDE): 질문 대신 "그럴듯한 답 문서"를 LLM이 먼저 쓰게 하고, 그 문서의 임베딩으로 검색합니다 → HyDE.

대화형 RAG에서 꼭 필요한 것. 이전 대화를 반영해 "그거"를 구체적 대상으로 바꾼 독립 질문(standalone question)으로 다시 쓰는 단계입니다. 이 단계가 없으면 "그거 작년이랑 비교하면?"으로 검색하게 됩니다.

6. 프롬프트 조립과 생성

검색이 끝나면 청크를 프롬프트에 넣습니다. 해설용 원칙 몇 가지입니다.

  1. 출처 표시: 청크마다 번호와 문서 제목을 붙이고, 답변에 근거 번호를 달게 지시합니다. 나중에 사람이 확인할 수 있습니다.
  2. 모르면 모른다고: "주어진 자료에 없으면 없다고 답하라"는 지시를 둡니다. 환각을 줄이는 기본 장치입니다.
  3. 순서: 긴 문맥 한가운데 놓인 정보는 덜 활용된다는 연구가 있습니다(중간에서 길을 잃다). 가장 관련 높은 청크를 앞이나 끝에 두는 것이 안전합니다.
  4. 너무 많이 넣지 않기: 관련 없는 청크는 답을 흐립니다. 리랭커 점수 기준선 아래는 버리는 것도 방법입니다.

7. 어디부터 고치나: 점검 순서

  1. 평가 세트 만들기: 질문 30~100개와 정답 근거 청크를 표시합니다(해설용 규모).
  2. 검색만 따로 재기: recall@K가 낮으면 청킹 · 하이브리드 · 쿼리 재작성부터.
  3. 순위 재기: 정답이 상위 50에는 있는데 상위 5에 없으면 리랭커.
  4. 생성 재기: 정답 청크가 들어갔는데도 답이 틀리면 프롬프트 · 모델 · 충실도 점검 → RAG 평가와 고급 패턴.

연습 문제

  1. 2만 토큰 문서를 1,000토큰 청크 · 200토큰 겹침으로 자르면 청크는 몇 개인가요?
    • 풀이: 이동 폭 800, ⌈(20000−1000)/800⌉+1=⌈23.75⌉+1=25\lceil(20000-1000)/800\rceil+1=\lceil23.75\rceil+1=25 개입니다.
  2. BM25 목록 [X, Y, Z], 벡터 목록 [Z, W, X] 를 k=60k=60 RRF로 합친 순서는?
    • 풀이: X =161+163≈0.03226=\frac1{61}+\frac1{63}\approx0.03226, Z =163+161≈0.03226=\frac1{63}+\frac1{61}\approx0.03226(동점), Y =162≈0.01613=\frac1{62}\approx0.01613, W =162≈0.01613=\frac1{62}\approx0.01613(동점). X · Z가 공동 1위, Y · W가 공동 3위입니다. 동점은 원래 점수나 한쪽 목록 순위로 깹니다.
  3. 후보 100개를 크로스 인코더로 재정렬하면 질문당 모델 호출은 몇 번이고, 문서 100만 개 전체에 쓰면?
    • 풀이: 100번 대 100만 번입니다. 그래서 크로스 인코더는 후보 재정렬에만 씁니다.
  4. "ERR-4012 오류 해결법"이라는 질문에 벡터 검색만 쓰면 어떤 위험이 있나요?
    • 풀이: 오류 코드처럼 정확한 문자열이 중요한 질문은 임베딩이 비슷한 다른 코드 문서와 섞일 수 있습니다. BM25를 함께 쓰는 하이브리드가 안전합니다.

스스로 점검

  1. RRF가 점수 대신 순위를 쓰는 이유는?
    • 답: BM25 점수와 코사인 유사도는 단위 · 범위가 달라 그대로 더하면 한쪽이 지배하기 때문입니다. 순위는 어느 검색기에서나 같은 척도입니다.
  2. 맥락 붙인 청크는 어떤 문제를 푸나요?
    • 답: 청크를 떼어 내면 주어 · 시점 같은 맥락이 사라져 검색이 빗나가는 문제입니다. 문서 전체에서 뽑은 짧은 설명을 청크 앞에 붙여 임베딩 · BM25 색인을 만듭니다.
  3. 리랭커를 넣었는데도 품질이 그대로라면 먼저 무엇을 확인하나요?
    • 답: 1단계 후보(예: 상위 50) 안에 정답 청크가 있는지, 즉 1단계 재현율입니다. 후보에 없으면 리랭커는 고칠 수 없습니다.

용어 정리

용어쉬운 뜻
청킹(chunking)문서를 검색 단위 덩어리로 자르기
겹침(overlap)이웃 청크끼리 일부를 겹치게 자르는 것
맥락 붙인 검색청크 앞에 문서 맥락 설명을 붙여 색인하는 방법
하이브리드 검색키워드(BM25) 검색과 벡터 검색을 함께 쓰는 것
RRF여러 순위 목록을 1/(k+순위)1/(k+순위) 의 합으로 합치는 방법
바이 인코더질문 · 문서를 따로 벡터로 만들어 비교하는 모델
크로스 인코더질문과 문서를 함께 넣어 관련도를 직접 내는 모델
리랭킹1차 후보를 더 정확한 모델로 다시 줄 세우기
쿼리 재작성질문을 검색하기 좋은 형태로 고쳐 쓰기
독립 질문대화 맥락 없이도 뜻이 통하게 다시 쓴 질문

더 깊이 보려면

다음에 볼 것

라이선스

본문은 KAITABASE 자체 해설입니다. 숫자 예는 이 수업을 위해 만든 해설용 예이며 파이썬으로 검산했습니다. Anthropic 글 · 논문 수치는 각 원문에서 확인한 것만 옮겼습니다.

출처

AI 원리부터 이해하기 · RAG·검색 모듈

RAG·검색 모듈 학습

이 글은 RAG·검색 모듈의 학습 자료입니다. 전체 21개 자료 중 8번째입니다.

AI 기초 과정은 현재 진도 저장을 지원하지 않습니다.

출처·원문

원문 보기

요약만

본문 자체 작성 · 참고 자료 Anthropic 글 · arXiv 원 논문