Back to Blog
ChunkingRAGFixed-sizeSemanticRecursive

0x07. Chunking - 문서를 잘게 나누는 기술

RAG 시스템의 핵심인 Chunking 전략들을 비교하고, 최적의 청크 설계 방법을 정리한다.

100페이지짜리 PDF를 통째로 AI에게 던져주면, 원하는 답을 정확히 찾아줄까? 대부분의 경우 그렇지 않다. LLM에는 한 번에 처리할 수 있는 텍스트 양의 한계가 있고, 설령 긴 문서를 받아들일 수 있더라도 정보가 너무 많으면 핵심을 놓치기 쉽다. 이 문제를 해결하는 핵심 기술이 바로 청킹(Chunking) 이다.


Chunking이란?

청킹(Chunking)은 긴 문서를 작은 단위(청크)로 분할하는 기술이다. 두꺼운 백과사전을 주제별 카드로 나누는 것과 비슷하다. 백과사전 전체를 넘기며 답을 찾는 것보다, 관련 카드 몇 장만 꺼내서 읽는 편이 훨씬 빠르고 정확하다.

특히 RAG(Retrieval-Augmented Generation) 시스템에서 청킹은 핵심적인 역할을 한다. RAG는 외부 문서에서 관련 정보를 검색한 뒤, 그 정보를 LLM에 전달하여 답변을 생성하는 구조다. 이때 문서가 적절한 크기로 나뉘어 있어야 검색이 정확하고, LLM이 받아들일 수 있는 범위 안에서 충분한 맥락을 제공할 수 있다.


왜 Chunking이 필요한가?

청킹이 필요한 이유는 크게 세 가지다.

1. LLM의 컨텍스트 윈도우 한계 극복

LLM은 한 번에 처리할 수 있는 토큰 수에 제한이 있다. GPT-4의 경우 128K 토큰, Claude의 경우 200K 토큰이 상한이다. 이보다 긴 문서는 물리적으로 전달할 수 없으므로, 문서를 나누어 필요한 부분만 전달해야 한다.

2. 검색 효율 향상

RAG 시스템에서 검색은 보통 임베딩 유사도(Embedding Similarity) 를 기반으로 동작한다. 문서 전체를 하나의 벡터로 만들면, 세부 주제에 대한 질문과의 유사도가 희석된다. 반면 적절한 크기의 청크로 나누면, 질문과 가장 관련 있는 부분만 정확하게 검색할 수 있다.

비유하자면, 도서관에서 "양자역학의 불확정성 원리"를 찾을 때 책 한 권 전체를 추천받는 것보다, 해당 챕터의 특정 절을 바로 펼쳐 보는 것이 훨씬 효과적이다.

3. 관련 정보의 정확한 제공

청크 크기가 너무 크면 불필요한 정보가 함께 포함되고, 너무 작으면 맥락이 손실된다. 적절한 크기와 경계로 나누는 것이 곧 답변 품질을 결정한다.


주요 Chunking 전략

청킹 전략은 크게 네 가지로 분류된다. 단순한 방법부터 점점 정교한 방법 순서로 살펴본다.

1. Fixed-size Chunking (고정 크기 청킹)

가장 단순한 방법이다. 문서를 고정된 문자 수 또는 토큰 수로 일정하게 자른다.

문서: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
청크 크기: 10
결과: ["ABCDEFGHIJ", "KLMNOPQRST", "UVWXYZ"]

장점:

  • 구현이 매우 간단하다
  • 처리 속도가 빠르다
  • 모든 청크의 크기가 균일하여 관리하기 쉽다

단점:

  • 의미적 경계를 무시한다. 문장 중간에서 잘리거나, 하나의 개념이 두 청크에 걸칠 수 있다
  • 맥락이 단절되어 검색 품질이 떨어질 수 있다

적합한 경우: 로그 파일, 코드 등 구조가 균일한 문서. 또는 빠른 프로토타이핑이 필요할 때.

흔한 실수 중 하나는 고정 크기를 너무 작게 설정하는 것이다. 예를 들어 100토큰 단위로 자르면 대부분의 청크가 문맥을 잃어 검색 시 쓸모없는 조각이 된다.


2. Recursive Chunking (재귀적 청킹)

고정 크기 청킹의 한계를 보완한 방법이다. 여러 단계의 구분자(Delimiter)를 순차적으로 적용하여, 가능한 한 의미 있는 경계에서 문서를 나눈다.

동작 방식은 다음과 같다.

  1. 먼저 가장 큰 구분자(예: \n\n, 단락 구분)로 나눈다
  2. 나뉜 결과가 여전히 크면 다음 구분자(예: \n, 줄바꿈)로 다시 나눈다
  3. 그래도 크면 더 작은 구분자(예: . , 문장 구분)로 나눈다
  4. 최종적으로 원하는 크기 이하가 될 때까지 반복한다
# LangChain의 RecursiveCharacterTextSplitter 예시
from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", ". ", " ", ""]
)
chunks = splitter.split_text(document)

장점:

  • 문서의 계층적 구조를 어느 정도 보존한다
  • 단락 > 문장 > 단어 순서로 자연스럽게 분할된다
  • 고정 크기보다 의미적 일관성이 높다

단점:

  • 구분자 선택이 문서 유형에 따라 달라져야 한다
  • 완벽한 의미 단위 분할은 보장하지 못한다

적합한 경우: 일반적인 텍스트 문서. 실무에서 가장 널리 사용되는 기본 전략이다. LangChain 등 주요 프레임워크에서 기본값으로 채택하고 있다.


3. Semantic Chunking (의미 기반 청킹)

앞선 두 방법이 "형식"을 기준으로 나눴다면, 의미 기반 청킹은 텍스트의 실제 의미 변화를 감지하여 나눈다.

핵심 원리는 다음과 같다.

  1. 문장 단위로 텍스트를 분리한다
  2. 각 문장(또는 문장 그룹)의 임베딩 벡터를 생성한다
  3. 인접한 문장 간의 코사인 유사도(Cosine Similarity) 를 계산한다
  4. 유사도가 급격히 떨어지는 지점, 즉 주제가 바뀌는 경계에서 분할한다
문장1: "양자역학은 미시 세계를 다루는 물리학 분야이다."   임베딩 A
문장2: "슈뢰딩거 방정식은 양자 상태의 시간 변화를 기술한다."  임베딩 B
문장3: "한편, 경제학에서 수요와 공급은 가격을 결정한다."   임베딩 C

유사도(A, B) = 0.92   같은 청크
유사도(B, C) = 0.21   여기서 분할!

장점:

  • 맥락 보존이 가장 뛰어나다. 하나의 주제가 하나의 청크에 온전히 담긴다
  • 검색 시 관련성 높은 결과를 반환할 가능성이 높다

단점:

  • 임베딩 모델이 필요하므로 처리 비용과 시간이 증가한다
  • 유사도 임계값(threshold) 설정이 결과에 큰 영향을 미치며, 최적값을 찾기 어렵다
  • 구현이 복잡하다

적합한 경우: 여러 주제가 혼재된 긴 문서, 학술 논문, 보고서 등 의미적 정확성이 중요한 경우.


4. Document Structure-based Chunking (문서 구조 기반 청킹)

문서 자체의 구조적 요소(제목, 소제목, 단락, 섹션)를 기준으로 나누는 방법이다.

예를 들어 마크다운 문서라면 #, ##, ### 헤더를 기준으로 분할하고, HTML이라면 <h1>, <h2>, <section> 태그를 기준으로 분할한다.

# 1장. 서론          청크 1
## 1.1 배경          청크 2
## 1.2 연구 목적      청크 3
# 2장. 관련 연구      청크 4

장점:

  • 문서의 논리적 흐름을 가장 잘 반영한다
  • 저자가 의도한 구조를 그대로 활용하므로 의미 단위가 자연스럽다
  • 계층 정보(상위 제목 등)를 메타데이터로 보존할 수 있다

단점:

  • 문서에 명확한 구조가 없으면 적용이 어렵다 (예: 구조 없는 plain text)
  • 섹션 크기가 불균일하여, 어떤 청크는 너무 크고 어떤 청크는 너무 작을 수 있다

적합한 경우: 마크다운, HTML, LaTeX, PDF 등 구조화된 문서.


전략 비교 요약

전략분할 기준맥락 보존구현 복잡도처리 속도
Fixed-size문자/토큰 수낮음매우 낮음매우 빠름
Recursive다단계 구분자중간낮음빠름
Semantic의미 유사도높음높음느림
Structure-based문서 구조높음중간빠름

만능인 전략은 없다. 문서의 특성, 검색 요구사항, 처리 리소스에 따라 적절한 전략을 선택해야 한다.


Chunking 설계 시 고려사항

어떤 전략을 선택하든, 세 가지 핵심 파라미터를 신중하게 결정해야 한다.

1. 청크 크기 (Chunk Size)

가장 중요한 파라미터다.

  • 너무 작으면: 맥락이 손실된다. "불확정성 원리"를 설명하는 문장이 세 개의 청크에 흩어지면, 어떤 청크도 완전한 설명을 담지 못한다.
  • 너무 크면: 불필요한 정보가 포함되어 검색 정밀도가 떨어지고, LLM의 컨텍스트 윈도우를 낭비한다.
  • 일반적인 권장 범위: 200~1000 토큰. 문서 유형과 질문의 세분화 정도에 따라 조정한다.

2. 오버랩 (Overlap)

인접한 청크 간에 일정 부분을 중복시키는 기법이다.

청크1: [A B C D E F G H I J]
청크2:             [H I J K L M N O P Q]   H, I, J가 중복

오버랩이 없으면 청크 경계에 걸친 정보가 유실될 수 있다. 보통 청크 크기의 10~20% 를 오버랩으로 설정한다. 다만 오버랩이 클수록 전체 청크 수가 늘어나 저장 비용과 검색 시간이 증가하므로 균형이 필요하다.

3. 메타데이터 포함 (Metadata Inclusion)

청크에 출처 정보를 함께 저장하면 검색과 활용 모두에서 유리하다.

포함할 수 있는 메타데이터의 예시는 다음과 같다.

  • 문서 제목: 어떤 문서에서 왔는지
  • 섹션/챕터 정보: 문서 내 위치
  • 페이지 번호: 원본 참조 시 유용
  • 생성 일자: 정보의 최신성 판단

메타데이터는 검색 시 필터링 조건으로 활용하거나, LLM에 전달하여 출처 기반 답변을 생성하는 데 사용할 수 있다.


정리

청킹은 단순히 문서를 "자르는" 작업이 아니다. 어디서, 얼마나, 어떻게 나누느냐에 따라 RAG 시스템의 검색 정확도와 답변 품질이 크게 달라진다.

핵심을 요약하면 다음과 같다.

  • Fixed-size: 단순하고 빠르지만 의미를 무시한다
  • Recursive: 실무에서 가장 보편적인 균형 잡힌 선택이다
  • Semantic: 의미 보존이 뛰어나지만 비용이 크다
  • Structure-based: 구조화된 문서에 가장 자연스럽다
  • 청크 크기, 오버랩, 메타데이터 세 가지 파라미터가 성능을 좌우한다

실제 프로젝트에서는 하나의 전략만 고집하기보다, 문서 유형에 따라 전략을 조합하는 것이 효과적이다. 예를 들어 구조가 명확한 문서에는 Structure-based를, 비정형 텍스트에는 Recursive + Overlap을 적용하는 식이다.