프로덕션 레벨 RAG 파이프라인 구축하기: 심층 가이드
2024년, "내 PDF와 대화하기" 같은 튜토리얼은 이제 어디서나 볼 수 있습니다. 보통 이런 식이죠. 텍스트를 글자 수대로 자르고, OpenAI로 임베딩하고, 벡터 DB에 넣은 다음 질문을 던집니다. 5페이지짜리 문서라면 마법처럼 잘 작동합니다.
하지만 10만 개의 문서, 복잡한 표, 그리고 사용자의 모호한 질문이 쏟아지는 실제 프로덕션 환경에서도 그럴까요? 마법은 깨집니다. "Lost in the Middle(중간 소실)" 현상, 엉뚱한 문맥을 가져와 생기는 환각(Hallucination), 그리고 사용자 경험을 해치는 레이턴시 스파이크를 마주하게 됩니다.
이 글은 "Hello World" 수준의 튜토리얼이 아닙니다. 프로덕션 레벨의 RAG(Retrieval-Augmented Generation) 파이프라인을 구축하기 위한 심층 가이드입니다. 고급 청킹(Chunking) 전략, 하이브리드 검색(키워드 + 벡터), 리랭킹(Re-ranking) 모델, 그리고 시스템을 체계적으로 평가하는 방법까지 깊이 있게 다뤄보겠습니다.
프로덕션 RAG 시스템의 해부학
순진한 RAG 파이프라인은 일직선입니다: 문서 -> 청크 -> 임베딩 -> 벡터 DB -> 검색 -> LLM.
하지만 프로덕션 RAG 파이프라인은 복잡한 그래프에 가깝습니다.
- 수집 및 ETL: PDF, 표, 지저분한 HTML 처리.
- 고급 청킹: 의미 기반 분할, 부모 문서 검색(Parent-Document Retrieval).
- 하이브리드 검색: 밀집(Dense) 검색과 희소(Sparse, BM25) 검색의 결합.
- 리랭킹(Re-ranking): Cross-Encoder를 사용한 결과 정제.
- 생성: 인용(Citation)을 지원하는 프롬프트 엔지니어링.
각 단계를 하나씩 파헤쳐 봅시다.
1단계: 수집과 청킹 전략 (Ingestion & Chunking)
Garbage in, garbage out. 문장이 중간에 잘리거나 표의 맥락이 사라진다면, 검색기(Retriever)가 할 수 있는 건 없습니다.
고정 크기 청킹(Fixed-Size Chunking)의 문제점
대부분의 튜토리얼은 RecursiveCharacterTextSplitter를 사용해 1000자 단위로 자르고 200자를 겹치게(overlap) 합니다. 일반 텍스트에는 "충분"할지 몰라도 구조화된 데이터에는 실패합니다.
왜 실패할까요?
- 문맥 파편화: 개념을 설명하는 문단이 둘로 쪼개지면, 양쪽 모두 의미를 잃을 수 있습니다.
- 헤더 분리: 섹션 제목이 내용과 다른 청크로 들어가면, 내용은 "고아"가 되어 검색되기 어려워집니다.
전략 1: 의미 기반 청킹 (Semantic Chunking)
글자 수가 아니라 의미를 기준으로 자르세요. 임베딩 모델을 사용해 문장 간의 코사인 유사도를 계산할 수 있습니다. 유사도가 특정 임계값 아래로 떨어지면 주제가 바뀌었다고 판단하고 새로운 청크를 시작하는 방식입니다.
# 의미 기반 청킹의 개념적 예시 sentences = split_into_sentences(text) embeddings = model.encode(sentences) chunks = [] current_chunk = [sentences[0]] for i in range(1, len(sentences)): similarity = cosine_similarity(embeddings[i-1], embeddings[i]) if similarity < THRESHOLD: chunks.append(" ".join(current_chunk)) current_chunk = [sentences[i]] else: current_chunk.append(sentences[i])
전략 2: 부모 문서 검색 (Parent-Document Retrieval)
임베딩은 긴 텍스트보다 짧은 청크를 더 잘 표현합니다. 하지만 LLM은 정확한 답변을 위해 더 많은 문맥이 필요하죠.
해결책:
- 문서를 작은 "자식(Child)" 청크(예: 200 토큰)로 잘라 임베딩합니다.
- 각 자식 청크를 "부모(Parent)" 청크(예: 1000 토큰) 또는 전체 문서와 연결합니다.
- 검색은 자식 청크의 벡터로 하되, LLM에게는 부모 청크를 전달합니다.
이 방식은 정밀한 검색과 풍부한 문맥이라는 두 마리 토끼를 모두 잡을 수 있습니다.
2단계: 검색 계층 (벡터 vs 하이브리드)
벡터 검색(Dense Retrieval)은 의미적 의도를 파악하는 데 탁월합니다. 사용자가 "배관 터짐 수리법"을 검색하면 단어가 겹치지 않아도 "배관 수리 가이드"를 찾아냅니다.
하지만 벡터 검색도 약점이 있습니다:
- 정확한 키워드 매칭:
0x80040115같은 에러 코드나 특정 제품 SKU 검색에 취약합니다. - 도메인 특화 용어: 범용 임베딩 모델은 특정 업계의 약어를 이해하지 못할 수 있습니다.
하이브리드 검색 구현하기
하이브리드 검색은 벡터 검색(의미)과 키워드 검색(BM25)을 결합합니다.
- 벡터 검색 실행: 상위 50개 결과를 가져옵니다.
- BM25 검색 실행: 상위 50개 결과를 가져옵니다.
- 결과 융합: RRF(Reciprocal Rank Fusion) 같은 알고리즘으로 두 리스트를 합칩니다.
여기서 는 각 리스트에서 문서 의 순위입니다. 이 방식은 두 리스트 모두에서 상위권에 있는 문서에 높은 점수를 부여합니다.
3단계: 리랭킹 (Re-ranking, 비장의 무기)
RAG 파이프라인 성능을 높이기 위해 딱 하나만 해야 한다면, 리랭커(Re-ranker)를 추가하세요.
벡터 데이터베이스는 빠르지만(ANN), 속도를 위해 정확도를 일부 희생합니다. 임베딩은 압축된 표현이니까요.
Cross-Encoder 모델은 쿼리와 문서를 함께 입력받아 유사도 점수를 출력합니다. Bi-encoder 임베딩보다 훨씬 정확하지만 계산 비용이 비쌉니다.
아키텍처:
- 검색(Retrieve): 하이브리드 검색으로 상위 100개 후보를 가져옵니다(빠름).
- 리랭킹(Re-rank): 이 100개의 (쿼리, 문서) 쌍을 Cross-Encoder(예:
bge-reranker-v2-m3또는 Cohere Rerank)에 통과시킵니다. - 선택(Select): 점수가 가장 높은 상위 5개를 LLM에게 전달합니다.
이 "2단계 검색(Two-stage Retrieval)" 패턴은 고성능 RAG의 업계 표준입니다.
4단계: 생성 및 환각 방지 가드레일
이제 올바른 문맥을 확보했습니다. LLM이 딴소리를 하지 않게 하려면 어떻게 해야 할까요?
1. 시스템 프롬프트 엔지니어링
단순히 "대답해줘"라고 하지 마세요. 구체적으로 지시해야 합니다.
"당신은 도움이 되는 어시스턴트입니다. 오직 제공된 문맥만을 사용하여 사용자의 질문에 답변하세요. 문맥에 답이 없다면 '모르겠습니다'라고 말하세요. 외부 지식을 사용하지 마세요. 모든 주장에 대해 문서 ID를 인용하세요."
2. 인용 검증 (Citation Verification)
모델이 인용(예: [Doc 1])을 출력하도록 강제하세요. 후처리 단계에서 인용된 텍스트가 실제로 검색된 청크에 존재하는지 검증합니다. 모델이 문서를 인용했지만 해당 내용이 없다면, 환각일 가능성이 높으므로 플래그를 띄웁니다.
평가: RAGAS와 TruLens
변경 사항이 실제로 시스템을 개선했는지 어떻게 알 수 있을까요? 지표가 필요합니다.
RAG 3대 지표 (RAG Triad):
- 문맥 관련성(Context Relevance): 검색된 문맥이 질문과 관련이 있는가?
- 충실성(Faithfulness/Groundness): 답변이 오직 문맥에서만 도출되었는가?
- 답변 관련성(Answer Relevance): 답변이 실제로 사용자의 질문을 해결하는가?
RAGAS 같은 프레임워크는 LLM(GPT-4 등)을 심판으로 사용하여 이러한 지표를 자동으로 평가합니다.
# RAGAS 평가 예시 from ragas import evaluate from ragas.metrics import context_precision, faithfulness results = evaluate( dataset, metrics=[context_precision, faithfulness] )
결론
RAG 프로토타입은 오후 한나절이면 만듭니다. 하지만 프로덕션 RAG 시스템은 몇 달의 반복 개선이 필요합니다.
2025년을 위한 핵심 요약:
- 고정 청킹을 넘어서라: 의미 기반 또는 부모 문서 전략을 사용하세요.
- 하이브리드는 필수: 벡터에만 의존하지 마세요. 키워드 검색(BM25)은 여전히 강력합니다.
- 리랭킹은 고효율 투자: 벡터 검색의 정밀도 문제를 해결해 줍니다.
- 평가는 선택이 아니다: 측정할 수 없으면 개선할 수 없습니다.
"마법 같은" AI의 시대는 지났습니다. 이제는 모델 자체보다 엄격한 시스템 설계와 평가가 중요한 AI 엔지니어링의 시대입니다.
관련 도구 둘러보기
Pockit의 무료 개발자 도구를 사용해 보세요