
RAG의 정밀도는 Chunking 전에 결정된다: 원본 문서를 검색 가능한 단위로 변환하기
요약
RAG 시스템의 성능은 단순한 청킹(Chunking) 이전에 원본 문서를 검색 가능한 단위로 변환하는 과정에 의해 결정됩니다. 로딩, 파싱, 클리닝 과정을 통해 텍스트의 구조와 메타데이터를 보존하는 것이 핵심입니다.
핵심 포인트
- 청킹은 단순 텍스트 분할이 아닌, 구조화된 단위를 준비하는 과정임
- 효과적인 파싱은 문서의 계층 구조와 메타데이터를 유지해야 함
- 로딩과 파싱 단계에서 텍스트 정규화 및 노이즈 제거가 필수적임
- LlamaIndex, LangChain, Docling 등 도구를 활용한 문서 처리가 중요함
RAG의 이 단계에서는, 원본 문서를 **검색 가능한 단위 (searchable unit)**로 변환해 나갑니다.
원본 문서 → 검색 가능한 단위
RAG 시스템은 통상적으로 PDF나 매뉴얼 전체를 그대로 검색하지 않습니다. 미리 준비된 단위를 검색합니다.
검색 가능한 단위 = 텍스트 + 구조 + 메타데이터
예를 들어, 사원 핸드북 안에 다음과 같은 질문에 대한 답이 포함되어 있다고 가정해 봅시다.
신입 사원은 며칠간의 유급 휴가를 사용할 수 있는가?
하지만 처리가 잘못되면, 근거가 되는 부분이 깨진 형태로 남게 됩니다.
신입 사원은 최대
15페이지
10일간의 유급 휴가를...
답 자체는 존재합니다. 하지만 검색되는 단위가 깨져 있습니다. 더 잘 준비된 단위라면, 본문과 출처·위치 정보를 함께 유지합니다.
text = 신입 사원은 최대 10일간의 유급 휴가를 사용할 수 있다.
source = employee_handbook_2026.pdf
section = Paid Leave > New Employees
...
즉, 청킹 (Chunking)은 단순히 텍스트를 자르는 작업이 아닙니다. 후속 RAG 단계가 검색할 수 있도록, 깨끗하고 추적 가능한 단위를 준비하는 작업입니다.
문서 처리 단계는 다음 요소로 구성됩니다.
| 요소 | 역할 |
|---|---|
| Loading / parsing | 소스 문서에서 텍스트와 이용 가능한 구조를 추출함 |
| ... |
소스는 처음에는 정리되지 않은 상태에 있습니다. 거기서부터 단계적으로 이용 가능한 형태로 다듬어 나갑니다.
소스는 정리되지 않은 상태
↓
텍스트와 구조를 추출함
...
청킹 (Chunking)은 원본 소스가 깨끗하고, 정규화되었으며, 구조를 가진 텍스트가 된 후에야 비로소 제대로 작동합니다.
원본 소스 → 이용 가능한 텍스트 + 유용한 구조 → 깨끗하고 정규화된 구조를 갖춘 텍스트
Loading은 소스를 파이프라인에 가져오는 것입니다. Parsing은 그 소스로부터 텍스트와 구조를 복원하는 것입니다.
Markdown이나 HTML에서는 제목(heading)이나 리스트(list)가 구조로서 명시되어 있는 경우가 많습니다. 반면, PDF, Excel, Word, Wiki 페이지, 데이터베이스 레코드에서는 의미가 레이아웃, 표, 페이지, 시트, 계층에 의존하는 경우가 있기 때문에 더욱 세심한 해석이 필요합니다.
좋은 loading / parsing이란 다음 상태를 만드는 것입니다.
이용 가능한 텍스트 + 유용한 구조
예를 들어, parsing이 불충분하면 사원 핸드북이 다음과 같이 평탄화(flattening)될 수 있습니다.
신입 사원 정책 유급 휴가 사원은 10일간 취득할 수 있다...
더 나은 parsing은 구조를 유지합니다.
Document: Employee Handbook
Section: Paid Leave Policy
Text: 신입 사원은 10일간의 유급 휴가를 사용할 수 있다...
구현의 상세 내용은 소스의 종류에 따라 달라집니다. LlamaIndex Loading Documents는 loading의 전체적인 모습을 보는 데 도움이 되며, LangChain Document Loaders는 loader의 사례를 확인하는 데 사용할 수 있습니다. Docling은 PDF 해석과 같이 복잡한 parsing이 주요 문제가 되는 경우에 유용합니다.
Cleaning은 검색 노이즈를 제거하는 처리입니다. Normalization은 추출된 텍스트를 일관된 형태로 정돈하는 처리입니다. 예를 들어, 깨진 줄바꿈을 수정하거나, 공백을 통일하거나, 전각/반각 등의 문자 표기를 맞추거나, 제목이나 리스트 기호의 표기를 통일하는 등의 처리가 포함됩니다.
사원 핸드북에서는 반복해서 등장하는 헤더(header), 푸터(footer), 페이지 번호, 정형 문구, 깨진 줄바꿈, 반복되는 주의사항 등은 노이즈가 될 수 있습니다. 반면, 섹션 제목, 계층, 불렛 포인트(bullet point), 표, 버전 번호, 업데이트 날짜 등은 구조가 될 수 있습니다.
이 차이는 중요합니다.
신입 사원은 최대 10일간의 유급 휴가를 사용할 수 있다.
이는 다음 형태보다 활용하기 어렵습니다.
Document: Employee Handbook
Section: Paid Leave > New Employees
Text: 신입 사원은 최대 10일간의 유급 휴가를 사용할 수 있다.
문장 자체는 비슷하지만, 후자가 검색, 추적, 필터링, 디버깅을 하기에 더 용이합니다.
청킹 (Chunking)은 검색 대상이 될 지식의 단위를 결정하는 처리입니다.
많은 기본적인 RAG 시스템에서 이 단위는 청크 (Chunk) 입니다. 청크란 후속 단계에서 검색 가능한 형태로 변환될 수 있도록 준비된 문서 텍스트의 일부를 의미합니다.
사원 핸드북의 경우, 단위의 후보로는 다음과 같은 것들이 있습니다.
| 단위 후보 | 문제 |
|---|---|
| 핸드북 전체 | 너무 커서 초점이 흐려짐 |
| ... |
청킹은 단순한 "텍스트 자르기"가 아닙니다. 시스템이 검색할 수 있는 지식의 단위를 정의하는 처리입니다.
모든 청킹 기법은 청크 크기 (Chunk size) 와 청크 오버랩 (Chunk overlap) 의 영향을 받습니다.
| 청크 크기 | 장점 | 리스크 |
|---|---|---|
| 큰 청크 | 문맥을 많이 포함할 수 있음 | 검색 결과가 흐려지기 쉬움 |
| 작은 청크 | 구체적인 질문에 맞추기 쉬움 | 필요한 문맥을 잃기 쉬움 |
오버랩은 경계 부분의 정보 누락을 줄여줍니다.
Chunk 1: A B C D
Chunk 2: C D E F
Chunk 3: E F G H
하지만 오버랩이 너무 많으면 중복이 증가합니다. 중복된 청크는 검색 결과에 노이즈를 늘리고, LLM에 전달할 수 있는 컨텍스트 창 (Context window)을 낭비할 가능성이 있습니다.
"최적의 청크 크기는 무엇인가?"라는 질문보다 다음 질문이 더 실용적입니다.
이 문서의 종류와 쿼리 (Query)의 종류에는 어떤 청크 설계가 적합한가?
예를 들어, FAQ에서는 하나의 Q&A 쌍을 1개 청크로 만들면 기능하기 쉬울 수 있습니다. 정책 문서에서는 섹션 단위나 조항 단위가 더 적합할 수 있습니다. API 문서에서는 헤더, 파라미터, 예시를 함께 유지해야 하는 경우가 많습니다. 코드 문서에서는 설명과 코드 블록을 함께 유지하는 것이 좋은 경우가 많습니다.
사원 핸드북에서는 임의의 글자 수로 자르는 것보다, 정책의 섹션이나 서브 섹션을 출발점으로 삼는 것이 더 적절한 경우가 많습니다.
청킹 기법의 차이는 하나의 청크가 어디서 끝나고, 다음 청크가 어디서 시작되는지를 무엇으로 결정하느냐에 있습니다.
실제로는 여러 가지 단서를 조합하기도 합니다. 먼저 문서 구조를 사용하고, 그다음 문단 경계를 사용하며, 그 위에 토큰 (Token) 수의 상한을 적용하고, 필요에 따라 오버랩을 넣는 방식입니다.
| 접근 방식 | 경계를 무엇으로 결정하는가 | 주요 리스크 | 구현 레퍼런스 |
|---|---|---|---|
| Size-based splitting | 토큰 수 또는 글자 수 | 의미 중간에 잘릴 수 있음 | LangChain Text Splitters |
| ... |
구조 인식 분할 (Structure-aware splitting)은 적절한 파싱 (Parsing)에 의존합니다. 구조 복원이 어려운 경우에는 위의 로딩 (Loading) / 파싱 (Parsing) 리소스를 참조하는 것이 좋습니다.
의미 인식 분할 (Meaning-aware splitting)은 구현 리소스에서 시맨틱 청킹 (Semantic chunking) 이라고 불리는 경우가 많습니다.
문서에 따라서는 작은 검색 단위와 큰 문맥 단위가 모두 필요할 수 있습니다.
예를 들어, 시스템은 다음과 같은 작은 단위를 준비할 수 있습니다.
Section: Paid Leave -> New Employees
Text: 신입 사원은 최대 10일간의 유급 휴가를 사용할 수 있다.
그리고 그것이 속한 큰 부모 섹션과의 관계도 유지합니다.
Parent section: Paid Leave
Subsections:
- New Employees
...
이를 통해 작은 단위의 장점을 유지하면서 주변 문맥을 완전히 잃는 것을 방지할 수 있습니다.
| 작은 단위 | 큰 부모 단위 (Parent unit) |
|---|---|
| 초점이 맞춰진 검색에 적합함 | 주변 문맥을 유지하기 쉬움 |
| ... |
부모-자식 단위 설계 (Parent-child unit design)는 고정 크기 분할 (Fixed-size splitting)과는 다릅니다. 고정 크기 분할은 길이에 따라 청크 경계를 결정합니다. 부모-자식 단위 설계는 작은 문서 단위와 큰 문서 단위 사이의 관계를 유지합니다.
그 관계를 어떻게 활용할지는 후속 검색 단계 (retrieval)에서 결정됩니다.
LangChain Parent Document Retriever는 작은 자식 단위 (child unit)와 큰 부모 단위 (parent unit)를 결합하는 구현 사례로서 참고할 만합니다. LlamaIndex Recursive Retriever는 노드 (node)를 사용하여 문서 단위 간의 관계를 다루는 사례로서 참고할 만합니다. 여기서 말하는 노드 (node)는 프레임워크 상에서 다뤄지는 문서 단위입니다.
일반적인 청킹 (chunking)에서는 청크가 주변 텍스트에 강하게 의존하는 경우, 문맥 (context)이 손실될 수 있습니다.
예를 들어, 단락 안에 "이 규칙", "위의 경우", "다음 예외"와 같은 표현이 있는 경우, 주변 텍스트가 누락되면 해당 청크는 이해하기 어려워집니다.
일부 고급 기법에서는 청크에 더 많은 주변 문맥을 부여하거나, 청크 표현을 만드는 타이밍을 변경함으로써 이 문제를 줄이려고 시도합니다.
더 기술적인 세부 사항에 대해서는, 넓은 문맥을 사용하여 표현을 만든 후 청크 단위의 표현으로 나누는 개념을 설명하는 Late Chunking이 있습니다. Reconstructing Context는 문맥을 유지하는 청킹 전략을 보다 폭넓게 비교한 연구입니다.
검색 가능한 단위는 텍스트만이 아닙니다. 텍스트에 메타데이터 (metadata)를 더한 것입니다.
검색 가능한 단위 = 텍스트 + source / section / time / language / permission 등의 메타데이터
직원 핸드북의 경우, 유용한 메타데이터는 다음과 같습니다.
{
"source": "employee_handbook_2026.pdf",
"title": "Employee Handbook",
...
자주 사용되는 메타데이터 항목에는 다음과 같은 것들이 있습니다.
| 메타데이터 | 중요한 이유 |
|---|---|
| source | 청크의 출처 |
| ... |
메타데이터는 청크를 만드는 시점에 생성해 두어야 합니다. RAG 파이프라인 (pipeline)의 후속 단계에서는 이 메타데이터를 저장, 필터링, 인용, 디버깅, 평가, 액세스 권한 제어에 사용할 수 있습니다.
단, 메타데이터 자체가 액세스 제어를 수행하는 것은 아닙니다. 예를 들어 "permission": "employees_only"를 추가하더라도, 그것은 청크에 라벨을 붙이는 것뿐입니다. 실제로 액세스를 제어하려면 시스템의 다른 부분이 그 라벨을 사용해야 합니다.
실패 패턴은 동일한 처리 흐름에 대응시켜 정리할 수 있습니다.
| 실패 지점 | 예 | 결과 |
|---|---|---|
| Loading / parsing 실패 | 추출 누락, 페이지 순서 오류, 표의 평탄화 (flattening), 제목 누락, 레이아웃 정보 누락 | 시스템이 손상된 소스 텍스트에서 시작함 |
| ... |
핸드북의 예에서는 이러한 실패로 인해, 시스템이 "10일간"이라는 정보를 찾아내더라도 그것이 유급 휴가에 관한 것인지, 어느 섹션에서 왔는지, 혹은 예외 사항이 있는지에 대한 정보를 잃어버릴 가능성이 있습니다.
디버깅 시에는 다음 두 가지 질문이 도움이 됩니다.
1. 이 단위만 검색되었을 때,
실제 사용자의 질문에 답하는 데 도움이 되는가?
2. 이 단위를 근거로 사용할 경우,
...
답이 "아니오"라면, 문서 처리 계층이 취약할 가능성이 있습니다.
문서 처리 계층은 가공되지 않은 원본 문서 (raw document)를 검색 가능한 단위로 변환합니다.
RAG는 원본 문서를 검색하는 것이 아니다.
RAG는 준비된 단위를 검색한다.
좋은 검색 가능한 단위는 검색하기 쉽고, 이해하기 쉬우며, 추적 가능하고, 노이즈가 너무 많지 않으며, 너무 잘게 분절되지 않고, 유용한 메타데이터와 결합되어 있어야 합니다.
요컨대, 다음과 같은 형태입니다.
준비된 단위 = 텍스트 + 구조 + 메타데이터
이 계층의 출력물은 준비된 단위입니다.
준비된 단위가 만들어졌다면, 다음 문제는 그것들을 어떻게 표현하고, 저장하고, 검색하고, 선택하고, 활용할 것인가입니다.
- LlamaIndex. “Loading Documents”.
LlamaIndex Documentation. - LangChain. “Document Loaders”.
LangChain Documentation. - Docling Project. “Docling Documentation”.
Docling. - LangChain. “Text Splitters”.
LangChain Documentation. - LangChain. “Semantic Chunker”.
LangChain Documentation. - LangChain. “Parent Document Retriever”.
LangChain Documentation. - LlamaIndex. “Recursive Retriever”.
LlamaIndex Documentation. - Günther, M., et al. “Late Chunking: Contextual Chunk Embeddings Using Long-Context Embedding Models”.
arXiv, 2024.
“Reconstructing Context: A Comparative Study of Contextual Chunking Approaches for Retrieval-Augmented Generation”.
arXiv, 2025.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기