청킹 전략 — 문서를 어떻게 잘라야 RAG가 잘 작동하는가
한줄 요약
RAG의 품질은 청킹 전략에서 절반이 결정된다 — 문서를 너무 크게 자르면 검색이 부정확하고, 너무 작게 자르면 맥락이 사라진다.
본문
청킹이 왜 필요한가
임베딩 모델에는 입력 길이 제한이 있다. 보통 512~8,192 토큰이다. 20쪽 논문은 이 제한을 훨씬 넘는다.
더 근본적인 문제가 있다. 20쪽 논문을 벡터 하나로 만들면 어떻게 될까?
“와파린 용량 조절 기준”을 검색하면, 논문에 그 내용이 있더라도 논문 전체의 평균적인 의미가 벡터에 담겨 있어서 검색에서 상위에 오지 못할 수 있다. 논문이 전반적으로 심혈관 질환에 관한 것이라면 벡터도 그걸 더 반영한다.
해결책: 문서를 작은 조각(청크)으로 나눠서 각각 벡터화한다. 각 청크는 더 좁은 주제를 담고, 검색이 더 정확해진다.
청킹 방법 5가지
- 고정 크기 청킹 (Fixed-size chunking)
가장 단순하다. 토큰 수나 문자 수로 자른다.
512 토큰씩 자르기
겹침(overlap) 50 토큰
단점: 문장 중간에서 잘릴 수 있다. “혈당이 300 이상이면 입원” → “혈당이 300 이상이면” / “입원…”
- 문장/단락 기반 청킹 (Sentence/Paragraph chunking)
문장이나 단락 단위로 자른다. 의미가 끊기지 않는다.
import re
def split_by_paragraph(text: str) -> list[str]:
paragraphs = re.split(r'\n{2,}', text)
return [p.strip() for p in paragraphs if p.strip()]
단점: 단락마다 길이가 다르다. 한 단락이 너무 길 수 있다.
- 의미 기반 청킹 (Semantic chunking)
임베딩을 이용해서 의미가 바뀌는 지점을 찾아 자른다. 연속된 문장들의 임베딩 유사도가 갑자기 낮아지는 지점이 주제 전환 지점이다.
비용이 높지만 가장 자연스러운 청크를 만든다.
- 구조 기반 청킹 (Structure-based chunking)
문서의 구조(제목, 섹션, 표, 목록)를 활용한다.
진료 가이드라인은 보통 제목-소제목 구조가 명확하다:
1. 총론
1.1 적용 대상
1.2 개정 이력
2. 진단 기준
2.1 임상 기준
2.2 검사 기준
이 구조를 따라 자르면 각 청크가 하나의 논리 단위를 이룬다.
- 부모-자식 청킹 (Parent-child chunking)
작은 청크(자식)로 검색하고, 실제로 AI에게 줄 때는 큰 청크(부모)를 준다.
큰 청크: 섹션 전체 (2,000 토큰)
작은 청크: 각 문단 (200 토큰)
검색: 작은 청크로 → 더 정확한 매칭
컨텍스트: 부모 청크를 AI에게 → 더 풍부한 맥락
의료 문서에 맞는 청킹 전략
의료 문서는 일반 문서와 다른 특성이 있다:
- 표가 많다 (검사 정상 범위, 용량 표)
- 알고리즘/순서도가 있다
- 약어가 많다
- 수치가 정확해야 한다
권장 전략:
1단계: 구조 파악
- 제목 계층 파악
- 표, 알고리즘 섹션 식별
2단계: 섹션 단위로 1차 청킹
- 제목 + 해당 내용을 하나의 청크로
- 표는 표 전체를 하나의 청크로 유지
3단계: 긴 섹션은 2차 분할
- 500 토큰 초과 시 문단 단위로 분할
- 겹침(overlap) 100 토큰 적용
4단계: 메타데이터 추가
- 청크마다 "출처 문서명", "섹션명", "페이지" 추가
- 나중에 근거 제시할 때 사용
청킹 품질을 평가하는 법
청킹이 잘 됐는지 어떻게 아는가?
방법 1: 검색 품질 테스트
알려진 답이 있는 질문 50개 준비
→ RAG로 검색
→ 정답이 있는 문서가 Top 5에 들어오는가? (Recall@5)
→ 가장 관련 있는 청크가 1위인가? (MRR)
방법 2: 청크 완결성 확인 청크 하나를 랜덤으로 뽑아서 읽는다. 맥락 없이도 의미가 통하는가? 중간에 잘린 느낌이 드는가?
방법 3: 청크 크기 분포 너무 짧은 청크(50 토큰 미만)와 너무 긴 청크(1000 토큰 초과)의 비율을 확인한다.
자주 하는 실수
모든 문서에 같은 전략 적용: 약물 정보 DB, 진료 지침, 의학 교재, 병원 내부 규정은 다 다르다. 각각 맞는 전략이 있다.
겹침(overlap)을 0으로 설정: 청크 경계에서 정보가 잘리면 검색이 실패한다. 최소 10~15% overlap을 권장한다.
표를 분해: 표 안에서 자르면 행과 열의 연관성이 사라진다. 표는 항상 하나의 청크로 유지한다.
메타데이터 없음: 청크에 출처 정보가 없으면 나중에 “이 정보가 어느 문서에서 왔는지” 알 수 없다.
청킹은 한번 설정하면 끝이 아니다. 실제 검색 품질을 측정하고 지속적으로 개선하는 과정이다.