
청킹(Chunking) 설계의 기초 — 분할 사이즈에 따라 RAG의 검색 정밀도가 변하는 이유 정리
요약
RAG 시스템 구축 시 필수적인 청킹(Chunking)의 개념과 설계 전략을 다룹니다. 청크 사이즈와 오버랩 설정이 검색 정밀도에 미치는 영향을 분석하고, 다양한 분할 방식의 장단점을 설명합니다.
핵심 포인트
- 청크 사이즈가 너무 크면 여러 토픽이 섞여 검색 스코어가 분산됨
- 청크 사이즈가 너무 작으면 문맥이 끊기고 비용이 증가할 수 있음
- 고정 크기, 재귀적 문자, 의미론적 분할 등 다양한 전략 존재
- 오버랩을 통해 인접 청크 간의 문맥 단절을 방지할 수 있음
RAG를 구축하면 「문서를 청크(Chunk)로 분할하는」 공정이 반드시 나타나는데, 분할 사이즈를 바꾸는 것만으로도 검색 정밀도가 크게 변한다.
이 기사는, 청킹(Chunking)이 무엇을 위해 존재하는지, 사이즈나 오버랩(Overlap) 설계에서 어떤 일이 일어나는지를 초보자용으로 정리한다.
| 관점 | 내용 |
|---|---|
| 정의 | 긴 문서를 검색·임베딩(Embedding)하기 쉬운 단위(청크)로 분할하는 처리 |
| ... | |
| 포인트: 청킹은 한 번 결정하면 고정되는 것이 아니다. 문서의 종류(매뉴얼, FAQ, 규약)에 따라 최적의 입도가 달라진다. |
청킹(Chunking)이란, 긴 텍스트를 일정한 규칙에 따라 짧은 단편(청크)으로 분할하는 처리다.
RAG 파이프라인에서는 다음과 같은 흐름 속에서 사용된다.
[원문 문서 (PDF / Markdown / HTML 등)]
↓
[청킹] → 수백~수천 토큰(Token) 단위의 단편으로 분할
...
사용자의 질문이 들어오면, 질문문도 벡터화(Vectorization)하여, 저장된 청크 중에서 유사도가 높은 것을 검색한다.
이때, 1개 청크가 「얼마나 많은 정보를 포함하는가」가 검색 결과의 질로 직결된다.
벡터 검색은 청크 전체를 하나의 벡터로 취급한다.
청크에 포함된 텍스트가 길수록, 여러 토픽이 하나의 벡터에 섞이게 된다.
| 청크 사이즈 | 장점 | 단점 |
|---|---|---|
| 작음 (100~300 토큰) | 검색 대상을 좁히기 쉬움, 노이즈가 적음 | 앞뒤 문맥이 끊기기 쉬움, 청크 수가 늘어나 비용 증가 |
| ... | ||
| 원문 텍스트 (가상의 사내 매뉴얼 단편): |
## 퇴근 시 절차
1. PC를 종료한다
2. 책상 위를 정리한다
...
큰 청크 (위 전체를 하나로): 「퇴근 절차」로 검색해도 「유급 휴가」 정보도 동일한 벡터에 포함되어 스코어(Score)가 분산된다. -
작은 청크 (제목별로 분할): 「퇴근」에 관한 질문은 퇴근 청크만 히트(Hit)하기 쉽다.
1. 고정 크기 분할 (Fixed-size Chunking)
글자 수 또는 토큰 수로 기계적으로 자르는 가장 심플한 방식.
def fixed_chunk(text: str, chunk_size: int = 500, overlap: int = 50) -> list[str]:
chunks = []
start = 0
...
구현이 간단하지만, 문장 중간에서 끊길 수 있다.
LangChain의 CharacterTextSplitter나 LlamaIndex의 TokenTextSplitter가 이 계통이다.
2. 재귀적 문자 분할 (Recursive Character Splitting)
구분자 우선순위(단락 → 줄바꿈 → 문장 → 단어)를 사용하여, 가능한 한 자연스러운 경계에서 자른다.
# LangChain의 RecursiveCharacterTextSplitter의 사고방식
separators = ["\n\n", "\n", "」。", "、", " "]
# 큰 구분자부터 시도하며, chunk_size를 넘지 않는 범위 내에서 분할
Markdown이나 구조화된 문서에서는 제목(##)을 경계로 설정하는 것도 유효하다.
3. 의미론적 분할 (Semantic Chunking)
문장이나 단락의 의미적인 덩어리로 구분하는 방식.
임베딩 유사도가 갑자기 낮아지는 지점을 경계로 삼거나, 전용 모델로 토픽 경계를 검출한다.
정밀도는 높아지기 쉽지만, 계산 비용과 구현의 복잡성이 증가한다.
문서량이 많은 운영 환경에서는 먼저 재귀적 분할로 베이스라인을 만들고, 정밀도가 부족한 부분만 의미론적 분할을 검토하는 것이 현실적이다.
오버랩 (Overlap)
인접한 청크의 끝부분과 시작 부분을 의도적으로 중복시키는 수법을 오버랩이라고 한다.
청크1: [...........|----overlap---->
청크2: <----overlap----|...........]
| 설정 | 효과 |
|---|---|
| 오버랩 없음 | 청크 수는 최소화되지만, 경계의 문장이 누락되기 쉬움 |
| ... |
일반적인 기준은 청크 사이즈의 **10~20%**를 오버랩으로 설정하는 것이다.
500 토큰 청크라면, 50~100 토큰 정도의 중복이 출발점이 된다.
| 파라미터 | 검토 관점 |
|---|---|
| 청크 사이즈 | 문서의 평균 단락 길이, 질문의 입도 |
| ... |
메타데이터(Metadata)를 부여하면, 검색 후에 「어느 문서의 어느 장인지」를 LLM에게 전달하기 쉬워진다.
많은 벡터 DB (Pinecone, Weaviate, pgvector 등)는 메타데이터 필터링 (Metadata Filtering)을 지원한다.
대상 문서의 평균 문서 길이와 구조 (헤더 유무)를 파악한다 -
먼저 **500 토큰 전후 · 오버랩 (Overlap) 10%**로 베이스라인을 만든다 -
대표적인 질문 10~20건으로 검색 히트율 (Hit Rate)과 답변 품질을 수동 평가한다 -
청크 사이즈를 변경한 A/B 비교 (소·중·대 3가지 패턴)를 기록한다 -
분할 방식이 문장 중간에서 끊기지 않았는지 샘플 확인을 한다 -
청크에 헤더나 소스 파일명의 메타데이터를 부여한다 -
문서 업데이트 시 **재인덱싱 (Re-indexing)**이 실행되는 메커니즘을 준비한다
패턴 1: 청크가 너무 커서 무관한 단락이 함께 검색되는 경우
→ 대책: 헤더 단위 또는 500 토큰 전후로 다시 분할한다.
패턴 2: 청크가 너무 작아서 답변에 필요한 문맥 (Context)이 부족한 경우
→ 대책: 오버랩을 늘리거나, 검색 시 top_k를 높여 여러 청크를 LLM에 전달한다.
패턴 3: PDF의 페이지 구분 위치에서 기계적으로 분할되어 표나 리스트가 중간에 끊기는 경우
→ 대책: PDF 파서 (Unstructured, PyMuPDF 등)를 사용하여 구조를 유지한 후 분할한다.
패턴 4: 청크 사이즈를 결정한 뒤 평가 없이 바로 실무에 투입하는 경우
→ 대책: 대표 질문 세트로 리콜 (Recall, 올바른 청크가 상위에 오는지 여부)을 정기적으로 측정한다.
패턴 5: 오버랩이 너무 커서 동일한 내용이 검색 결과에 반복해서 나타나는 경우
→ 대책: 오버랩을 10~20%로 억제하고, 검색 후에 중복 제거 (Deduplication) 과정을 넣는다.
- 청킹 (Chunking)은 RAG의 검색 정밀도를 좌우하는 「입도 (Granularity) 설계」다.
- 너무 작으면 문맥이 결여되고, 너무 크면 노이즈가 섞인다. 500 토큰 전후와 10% 오버랩이 출발점이 된다.
- 고정 길이 (Fixed-length), 재귀적 (Recursive), 세만틱 (Semantic)의 3가지 방식이 있으며, 우선 재귀적 분할로 베이스라인을 만들고 평가 데이터로 조정하는 것이 현실적이다.
다음 단계로, 가지고 있는 Markdown 파일을 LangChain 이나 LlamaIndex를 사용하여 3가지 패턴의 사이즈로 분할하고, 동일한 질문으로 검색 결과를 비교해 보면 체감할 수 있다.
- LangChain Text Splitters
- LlamaIndex — Node Parser / Chunking
- Pinecone — Chunking Strategies for LLM Applications
- Lewis et al., 2020 — Retrieval-Augmented Generation
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기