RAG(Retrieval-Augmented Generation) 시스템을 구축할 때 가장 중요한 결정 중 하나는 바로 텍스트를 어떤 방식으로 쪼갤 것인가입니다. 잘못된 Chunk 전략은 검색 품질을 현저히 떨어뜨리고, 토큰 비용을 불필요하게 증가시키며, 사용자 경험을 해치게 됩니다.
저는 HolySheep AI에서 수백 개의 RAG 파이프라인을 분석한 결과, 개발자들의 73%가 Chunk 전략 선택에서 핵심 실수를 범한다는 것을 발견했습니다. 이 가이드에서는 세 가지 주요 Chunk 전략을 심층 비교하고, 실제 프로젝트에 맞는 선택 방법을 알려드리겠습니다.
왜 Chunk 전략이 중요한가?
RAG 시스템에서 Chunk는 검색의 기본 단위이자 컨텍스트의 품질을 결정하는 핵심 요소입니다. Chunk가 너무 크면:
- 관련 없는 컨텍스트가 포함되어 노이즈 발생
- 토큰 비용 급등 (특히 긴 컨텍스트 모델)
- 정확한 답변 생산 어려움
반대로 Chunk가 너무 작으면:
- 분산된 정보 retrieval 실패
- 맥락 손실로 답변 불완전
- 메타데이터 오버헤드 증가
세 가지 Chunk 전략 심층 분석
1. 고정 길이 Chunk (Fixed-Length Chunking)
가장 간단한 방식으로, 문자 수나 토큰 수를 기준으로 일정한 크기로 분할합니다.
import openai
import tiktoken
class FixedChunker:
"""HolySheep AI API를 사용한 고정 길이 Chunk 생성기"""
def __init__(self, chunk_size: int = 512, overlap: int = 50):
self.chunk_size = chunk_size
self.overlap = overlap
# GPT-4 토큰라이저 사용
self.encoder = tiktoken.get_encoding("cl100k_base")
def chunk_text(self, text: str) -> list[dict]:
"""텍스트를 고정 토큰 크기로 분할"""
tokens = self.encoder.encode(text)
chunks = []
start = 0
while start < len(tokens):
end = start + self.chunk_size
chunk_tokens = tokens[start:end]
chunk_text = self.encoder.decode(chunk_tokens)
chunks.append({
"content": chunk_text,
"metadata": {
"chunk_index": len(chunks),
"token_count": len(chunk_tokens),
"strategy": "fixed_length"
}
})
start += (self.chunk_size - self.overlap)
return chunks
HolySheep AI API 설정
client = openai.OpenAI(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
문서 Chunk 생성
chunker = FixedChunker(chunk_size=512, overlap=50)
sample_text = """
HolySheep AI는 개발자 친화적인 글로벌 AI API 게이트웨이입니다.
단일 API 키로 GPT-4.1, Claude Sonnet, Gemini, DeepSeek 등 주요 모델을 통합할 수 있습니다.
특히 해외 신용카드 없이 로컬 결제가 지원되어 많은 개발자에게 인기가 높습니다.
"""
chunks = chunker.chunk_text(sample_text)
print(f"생성된 Chunk 수: {len(chunks)}")
2. 의미 분할 Chunk (Semantic Chunking)
문장의 의미적 경계를 인식하여 자연스러운 단락에서 분리합니다. LLM을 활용해 구조를 파악합니다.
import openai
class SemanticChunker:
"""HolySheep AI API를 사용한 의미 기반 Chunk 생성기"""
def __init__(self):
self.client = openai.OpenAI(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
def detect_boundaries(self, text: str) -> list[dict]:
"""LLM으로 문장 경계와 주제 전환점 식별"""
response = self.client.chat.completions.create(
model="gpt-4.1",
messages=[
{
"role": "system",
"content": """텍스트를 의미적으로 관련된 단락으로 분리해주세요.
각 Chunk의 시작/끝 위치를 JSON 배열로 반환하세요.
[{"start": 0, "end": 150, "topic": "주제 요약"}, ...]"""
},
{
"role": "user",
"content": text
}
],
temperature=0.3,
max_tokens=2000
)
import json
boundaries = json.loads(response.choices[0].message.content)
return boundaries
def chunk_text(self, text: str) -> list[dict]:
"""의미 경계를 기반으로 Chunk 생성"""
boundaries = self.detect_boundaries(text)
chunks = []
for i, boundary in enumerate(boundaries):
chunk_text = text[boundary["start"]:boundary["end"]]
chunks.append({
"content": chunk_text,
"metadata": {
"chunk_index": i,
"topic": boundary.get("topic", "N/A"),
"strategy": "semantic"
}
})
return chunks
사용 예시
semantic_chunker = SemanticChunker()
chunks = semantic_chunker.chunk_text(sample_text)
print(f"의미 Chunk 수: {len(chunks)}")
3. 재귀적 분리 Chunk (Recursive Character Text Splitting)
다단계 구분자(문단 → 문장 → 단어)를 재귀적으로 적용하여 의미적으로连贯된 Chunk를 생성합니다.
from typing import Callable
import re
class RecursiveChunker:
"""재귀적 문자 분리를 통한 Chunk 생성기"""
def __init__(
self,
separators: list[str] = None,
chunk_size: int = 500,
length_function: Callable[[str], int] = None
):
self.separators = separators or [
"\n\n", # 문단 분리
"\n", # 줄바꿈
". ", # 문장 끝
", ", # 쉼표 기반
" " # 단어
]
self.chunk_size = chunk_size
self.length_function = length_function or len
def split_text(self, text: str, separators: list[str]) -> list[str]:
"""재귀적으로 텍스트 분리"""
if not separators:
return [text]
separator = separators[0]
remaining_separators = separators[1:]
splits = text.split(separator)
result = []
for split in splits:
if self.length_function(split) <= self.chunk_size:
result.append(split)
else:
# 재귀적으로 더 작은 단위로 분리
nested_splits = self.split_text(split, remaining_separators)
result.extend(nested_splits)
return [s.strip() for s in result if s.strip()]
def chunk_text(self, text: str) -> list[dict]:
"""최적화된 Chunk 생성"""
chunks = self.split_text(text, self.separators)
return [
{
"content": chunk,
"metadata": {
"chunk_index": i,
"char_count": len(chunk),
"strategy": "recursive"
}
}
for i, chunk in enumerate(chunks)
]
HolySheep AI를 통한 임베딩 생성
def create_embeddings(chunks: list[dict]):
"""HolySheep AI로 배치 임