청킹 전략: 문서를 어떻게 쪼갤 것인가
Day 2: 청킹 & 임베딩
청킹 전략: 문서를 어떻게 쪼갤 것인가
RAG 기초 > Day 2: 청킹 & 임베딩
- 4가지 주요 청킹 전략을 이해한다
- 각 전략의 장단점을 비교할 수 있다
- 제조 문서 유형별 최적 청킹 전략을 선택할 수 있다
청킹이란?
청킹(Chunking) = 긴 문서를 검색 가능한 작은 단위로 분할하는 과정
왜 필요한가?
├── 임베딩 모델의 토큰 제한 (대부분 512~8192 토큰)
├── 검색 정확도 향상 (관련 내용만 추출)
├── LLM 컨텍스트 효율적 사용
└── 비관련 내용 배제전략 1: 고정 크기 청킹 (Fixed-Size)
가장 단순한 방법. 정해진 글자(토큰) 수로 자른다.
원본 문서 (2,000자):
"CNC 서보 에러 E-001 대응 절차... (중략) ...점검 완료"
chunk_size=500, overlap=100 으로 분할:
[Chunk 1] 0~500자 "CNC 서보 에러 E-001 대응..."
[Chunk 2] 400~900자 "...대응 절차 3.1 냉각팬..."
[Chunk 3] 800~1300자 "...냉각팬 확인 3.2 케이블..."
[Chunk 4] 1200~1700자 "...케이블 점검 3.3 파라미터..."
[Chunk 5] 1600~2000자 "...파라미터 확인... 점검 완료"
← overlap →
┌────┤ ├────┐
Chunk 1: |AAAAAAAA|
Chunk 2: |BBBBBBBBB|
Chunk 3: |CCCCCCCCC|| 장점 | 단점 |
|---|---|
| 구현 간단 | 문맥 파괴 가능 |
| 균일한 크기 | 표/절차가 쪼개질 수 있음 |
| 예측 가능한 토큰 수 | 의미 단위 무시 |
언제 쓰나?
- 빠른 프로토타입
- 구조가 없는 일반 텍스트
전략 2: 재귀적 문자 분할 (RecursiveCharacterTextSplitter)
LangChain에서 가장 많이 쓰이는 방법. 여러 구분자를 우선순위대로 시도한다.
기본 구분자는 넷이다 (langchain-text-splitters 실제 기본값):
1순위: "\n\n" (빈 줄 = 문단 구분)
2순위: "\n" (줄바꿈)
3순위: " " (띄어쓰기)
4순위: "" (글자 단위 - 최후의 수단)
동작 방식:
1. "\n\n"으로 분할 시도
2. 청크가 chunk_size보다 크면 -> "\n"으로 재분할
3. 아직 크면 -> " "으로 재분할
4. ...반복기본값에는 문장 경계가 없다. 마침표를 기준으로 자르고 싶다면
separators에 ". "를 직접 넣어야 한다. 아래 커스텀 구분자가 그 일을 한다.
직접 확인하려면 RecursiveCharacterTextSplitter(chunk_size=500)._separators를
찍어 보면 된다.
제조 문서용 커스텀 구분자:
# 제조 문서에 최적화된 구분자
manufacturing_separators = [
"\n## ", # 마크다운 대제목
"\n### ", # 마크다운 소제목
"\n#### ", # 마크다운 소소제목
"\n\n", # 빈 줄 (문단)
"\n", # 줄바꿈
". ", # 문장 끝
" ", # 단어
]
전략 3: 시맨틱 청킹 (Semantic Chunking)
의미가 변하는 지점에서 자른다. 문장 간 임베딩 유사도를 계산하여 "의미의 경계"를 찾는다.
원본:
"서보 에러 E-001은 과전류 감지다. ← 서보 에러 관련
냉각팬 작동 여부를 먼저 확인한다. ← 서보 에러 관련
다음으로 케이블 커넥터를 점검한다. ← 서보 에러 관련
HP-500 유압 프레스의 작동유는 ← 유압 프레스 (의미 변경!)
ISO VG46을 사용한다. ← 유압 프레스
겨울에는 VG32로 교체한다." ← 유압 프레스
문장 유사도 분석 (아래 값은 동작을 보이기 위한 예시다.
실제 값은 임베딩 모델과 문서에 따라 달라진다):
문장1-문장2: 높음 → 같은 청크
문장2-문장3: 높음 → 같은 청크
문장3-문장4: 뚝 떨어짐 → ★ 여기서 분할!
문장4-문장5: 높음 → 같은 청크
문장5-문장6: 높음 → 같은 청크
결과:
[Chunk A] 서보 에러 관련 3문장
[Chunk B] 유압 프레스 관련 3문장| 장점 | 단점 |
|---|---|
| 의미 단위 보존 | 임베딩 모델 추가 호출 필요 |
| 검색 정확도 높음 | 청크 크기 불균일 |
| 문맥 자연스러움 | 구현 복잡도 높음 |
전략 4: 문서 구조 기반 청킹 (Structure-Aware)
제조 문서에 가장 적합한 방법. 문서의 기존 구조(섹션, 절차 번호)를 활용한다.
SOP 문서 예시:
1. 목적 → [Chunk 1: 목적 섹션]
2. 적용 범위 → [Chunk 2: 적용 범위 섹션]
3. 절차
3.1 냉각팬 확인 → [Chunk 3: 절차 3.1]
3.2 케이블 점검 → [Chunk 4: 절차 3.2]
3.3 파라미터 → [Chunk 5: 절차 3.3]
4. 주의사항 → [Chunk 6: 주의사항 섹션]
각 청크에 계층 정보 보존:
Chunk 3 metadata: {
section: "3.1",
parent: "3. 절차",
doc: "SOP-CNC-E001"
}핵심: 청킹 후에도 "이 청크가 어디에 속하는지" 알 수 있다.
제조 문서 유형별 최적 청킹 전략
| 문서 유형 | 권장 전략 | chunk_size | overlap | 이유 |
|---|---|---|---|---|
| SOP | 구조 기반 | 500~800 | 100 | 절차 단위 보존 |
| 설비 매뉴얼 | 재귀적 (커스텀 구분자) | 800~1000 | 150 | 섹션 단위 |
| 사양서 | 표 단위 | 300~500 | 50 | 표 행 보존 |
| 안전 규정 | 조항 단위 | 500~800 | 100 | 법적 조항 |
| FAQ | Q&A 쌍 | 300~500 | 0 | 질문-답변 묶음 |
| 트러블슈팅 | 사례 단위 | 500~800 | 100 | 증상-원인-해결 |
Overlap(중복)은 왜 필요한가?
overlap 없이:
[Chunk 1] "...파라미터 #2012 값이"
[Chunk 2] "80-120 범위 내인지 확인한다"
→ "#2012"와 "80-120"이 분리됨!
overlap 있으면:
[Chunk 1] "...파라미터 #2012 값이 80-120 범위"
[Chunk 2] "#2012 값이 80-120 범위 내인지 확인한다"
→ 양쪽 청크 모두 완전한 정보 포함출발점: overlap = chunk_size의 15~20%. 정답이 아니라 시작 값이므로 문서 유형마다 다시 잡는다.
그리고 한 가지 더. chunk_overlap은 상한이지 약속이 아니다.
분할기는 구분자 경계에 맞춰 물러나기 때문에 실제로 겹치는 글자 수는
요청한 값보다 적은 것이 보통이고, 구분자가 딱 맞아떨어지면 0이 되기도 한다.
"overlap=100이면 100자가 겹친다"고 외우지 말고,
오늘 실습의 measured_overlap()으로 자기 문서에서 직접 세어 보라.
4가지 청킹 전략(고정크기/문장/의미단위/계층적)을 제조 문서 유형과 매핑한 표를 AI로 생성하면 설계 의사결정을 빠르게 할 수 있다.
제조 RAG 시스템 설계를 위해 다음 청킹 전략 4가지(고정 크기 청킹, 문장/단락 기반 청킹, 의미 단위 청킹, 계층적 청킹)를 5가지 제조 문서 유형(설비 매뉴얼, SOP 작업표준서, FMEA 고장모드 분석서, 품질 검사 규격서, 설비 이력 로그)에 대해 비교하는 표를 만들어줘. 표 열은 '청킹 전략 / 청크 크기 권장값 / 장점 / 단점 / 최적 문서 유형 / 제조 현장 적용 예시'로 구성해줘. 마지막에 KOSHA 안전지침에는 어떤 전략이 가장 적합한지 이유와 함께 추천해줘.