장문서 청킹 — 왜 일률적으로 자르면 안 되나
← 전체 목차 · 이전: RAG를 어떻게 하냐고 물으면 벡터 DB만 답하지 마라 · 다음: PDF 문서는 어떻게 처리하는가
"길이대로 일률적으로 자른다"는 답은 거의 탈락이다. 컴퓨터는 글자 수만 셀 줄 알지 문장의 의미가 어디서 끝나는지 모르기 때문이다. 무리하게 자르면 핵심 용어가 반토막 나고, Embedding이 올바른 벡터를 계산하지 못하고, 검색에서 리콜되지 않고, 결국 대규모 모델이 지어내며 환각을 만든다.
많은 개발자가 만든 RAG 시스템이 늘 "헛소리를 하는" 근원은, 하찮아 보이지만 실제로는 치명적인 이 청킹 디테일에 있다.
무뇌 절단의 재난: 눈 감고 케이크 자르기
- 컴퓨터는 매우 경직되어 있고 숫자만 셀 줄 안다. 한 문장의 의미가 어디서 끝나는지 전혀 모른다.
- 비유: 눈을 감고 케이크를 자르는데, 한 칼이 하필 가장 중요한 딸기 한가운데를 지나가는 것.
- 결과: 온전한 한 단락이 억지로 잘려 컨텍스트가 전부 사라지고, 모델은 받아 들고 어리둥절해진다.
핵심 사례: "분산 일관성 프로토콜"이 반토막 나다
| 단계 | 내용 |
|---|
| 원래 개념 | 분산 일관성 프로토콜 (8글자) |
| 기계의 무뇌 절단 | 8글자 한가운데를 정확히 관통 |
| 첫 조각의 끝 | 분산 일 |
| 둘째 조각의 시작 | 관성 프로토콜 |
| 사용자 질문 | "분산 일관성 프로토콜에 대해 알고 싶습니다" |
| 검색 결과 | 그대로 실패, 적중 불가 |
실패 원인:
- 현재의 Embedding 벡터 모델은 컨텍스트와 결합해 의미를 판단한다.
- 외따로 떨어진 "분산 일"이나 "관성 프로토콜"에 대해 모델은 올바른 벡터 표현을 계산해내지 못한다.
- 그 벡터는 사용자 query의 벡터와 한참 멀어져 핵심 정보가 오히려 검색되지 않는다.
- 대규모 모델에 넘길 때 근거가 없으니 지어낼 수밖에 없고, 환각이 생긴다.
두 조각의 결함: 조각 1은 의미가 불완전하고 조각 2는 주어를 잃었다.
해법: Overlap(중첩) = 잔상이 있는 슬라이딩 윈도우
- 핵심 알고리즘의 이름은 **Overlap, 즉 "중첩"**이다.
- 메커니즘: 자를 때 한 칼로 끊어버리지 않고 잔상을 가진 슬라이딩 윈도우처럼 — 뒤 조각의 시작이 앞 조각의 끝과 조금 연결을 유지한다.
- 20%의 Overlap을 더하면: 둘째 조각을 자를 때 몇 걸음 뒤로 물러나 앞 조각의 꼬리를 함께 데려온다.
- 효과: 둘째 조각의 시작이 "분산 일관성 프로토콜" 여덟 글자를 온전히 포함하게 되어 개념이 같은 조각 안에 안전하게 보호되고 → 사용자 질문 시 정확히 적중 → 대규모 모델이 의미가 연결된 내용을 받아 → 답변이 더 믿을 만해진다.
【잘못된 방식: 고정 길이 강제 절단】
장문서 ──500자마다────┬─> chunk1: "...분산 일" ← 의미 불완전
└─> chunk2: "관성 프로토콜..." ← 주어 상실
│
Embedding
│
벡터 위치 오류 ─> query와 유사도 낮음
│
검색 리콜 실패
│
LLM 근거 없음 ─> 지어내기 / 환각
【올바른 방식: 슬라이딩 윈도우 + Overlap】
장문서 ──윈도우 슬라이딩, 스텝 = chunk_size - chunk_overlap──┐
chunk1: "분산 일에 대해 알고 싶은데" │
chunk2: "분산 일관성 프로토콜의 원리" ← 중첩분만큼 후퇴 │
│
핵심 개념 온전히 보존
│
Embedding 의미 정확
│
정확히 적중 리콜
│
LLM이 연결된 컨텍스트 확보 ─> 믿을 만한 답변
핵심 사상과 권장 파라미터
| 항목 | 내용 |
|---|
| 본질 | 약간의 추가 저장 공간을 "안전 매트"로 삼아 의미의 온전함과 교환한다 |
| 권장 중첩률 | 10%~20% |
| 수익 | 리콜 정확도 ↑, 벡터 표현 품질 ↑ |
| 대가 | 저장과 인덱스 항목 증가(chunk 간 내용 중복) |
중첩률을 50%까지 올려도 되는가
중첩이 이렇게 유용하니 절대적 안전을 위해 chunk_overlap을 50% 이상으로 올리면 어떨까? 이 방향에는 새로운 재난이 따라온다 — 인덱스 규모가 대략 두 배가 되고, 리콜 결과가 고도로 중복되어 유효 정보의 다양성이 떨어지며, Embedding과 저장 비용이 뚜렷이 상승한다. "유익한 파라미터"는 모두 부작용 곡선이 어디서 꺾이는지 먼저 물어야 한다.
핵심 통찰
- 청킹은 RAG의 "기초 공사 실효점"이지 디테일이 아니다 — 시스템이 "헛소리를 하는" 것은 대개 모델 능력이나 프롬프트 탓으로 돌려지지만, 진짜 근원은 가장 앞단의 chunking인 경우가 많다. RAG 환각의 원인을 규명할 때는 먼저 청킹 전략을 되돌아보고 그다음에 모델을 의심할 것.
- 청킹 오류는 벡터 검색에 의해 "증폭"되지 "희석"되지 않는다 — 쪼개진 핵심 용어는 단지 몇 글자가 빠진 것이 아니라 chunk 전체의 embedding을 의미 공간의 잘못된 위치로 보내 리콜 목록에서 그대로 사라지게 한다. 상류의 약간의 파손이 하류에서 100% 누락으로 바뀐다.
- Embedding은 "컨텍스트 의존적"이므로 길이보다 경계가 중요하다 — 벡터 모델이 "컨텍스트와 결합해 의미를 판단"한다는 것은, 청킹의 평가 기준이 "길이가 균등한가"가 아니라 **"각 chunk가 자족적인 의미 단위인가"**여야 한다는 뜻이다.
- Overlap의 본질은 한 번의 명시적인 공간-품질 거래다 — 중첩은 신비한 파라미터 조정이 아니라 값이 명시된 거래다. 10~20%의 잉여 텍스트를 더 저장해 "핵심 개념이 절단되지 않을 확률 보장"을 산다. 이렇게 서술할 수 있는 파라미터는 원가 계산과 A/B 검증이 가능하다.
- 파라미터에는 최적 구간이 있고 클수록 좋은 것이 아니다(단조성 함정) — 20%가 유효하니 50%는 더 좋을까? 이것은 엔지니어링에서 극히 흔한 사고 함정이다. 잉여도가 올라가면 인덱스 팽창, 같은 내용이 여러 chunk로 반복 리콜(결과 다양성 하락), 검색·저장 비용의 선형 상승이 따라온다.
- 답변의 층위가 정답 자체보다 중요하다 — 같은 문제에 "길이대로 자른다"는 초보, "길이대로 자르고 overlap을 10~20% 주며 그 이유를 설명한다"는 실무 경험자, 여기에 "더 나아가 의미/구조 단위로 자를 수 있다"를 보태면 가점이다.
- 좋은 비유는 엔지니어링 직관의 압축이다 — "눈 감고 케이크를 자르는데 한 칼이 딸기 한가운데를 지난다"는 비유가 "고정 길이 청킹은 의미를 감지하지 못한다"를 한 문장으로 꿰뚫는다.
엔지니어링 실전 Tips
- **중첩률 10~20%**를 기본 출발점으로 삼고, 업무 코퍼스에 맞춰 조정할 것.
- 키워드 길이가 overlap의 하한을 결정한다: 도메인에 긴 용어(8자 이상의 프로토콜명, 법규명, 약품명)가 있다면 overlap이 최소한 가장 긴 용어의 길이를 덮어야 한다. 그렇지 않으면 여전히 절단된다.
- 검증은 "용어 수준 query"로 할 것: 폭넓은 질문은 잘못 잘려도 다른 chunk로 우연히 맞힐 수 있지만, 용어 수준 query라야 청킹 결함을 드러낸다.
- 비용 의식: overlap이 클수록 chunk 총수가 늘어 벡터 DB 항목, Embedding 호출 비용, 저장이 전부 오르며, 같은 내용이 여러 chunk로 반복 리콜되어 top-k 자리를 잠식한다.
- 고정 길이 + overlap은 최종점이 아니라 바닥선이다: 실제 프로젝트에서는 구두점/단락/제목 계층에 따른 구조화 청킹과 의미 청킹을 겹쳐 쓸 수 있다.
- 더 파고들 방향: 재귀적 문자 분할(단락 → 문장 → 문자로 단계적 후퇴), Markdown 제목 계층 기반 분할, 의미 분할(인접 문장 embedding 유사도의 급변 지점에서 절단), Chunk 메타데이터 보강(소속 장·절 제목, 문서명, 페이지를 붙여 "주어 상실"을 완화 — overlap을 키우는 것보다 공간 효율이 좋다), 부모-자식 chunk / Small-to-Big 검색(작은 chunk로 정밀 리콜하고 적중 후 소속된 큰 chunk를 LLM에 전달), 청킹 파라미터를 회귀 테스트 범위에 넣는 품질 평가셋 구축.