프로덕션 RAG 시스템에 청크 오버랩 적용하기
문제 상황
사내 문서 검색 시스템에서 문장이 청크 경계에 걸쳐 있을 때 검색이 제대로 안 되는 이슈가 반복적으로 제보됐다. 특히 긴 문단의 중요한 내용이 두 청크로 나뉘면서 임베딩 품질이 떨어지는 것이 원인이었다.
청크 오버랩 전략
기존에는 단순히 1000토큰씩 잘라서 저장했는데, 이제 200토큰의 오버랩을 두기로 했다.
def chunk_with_overlap(text, chunk_size=1000, overlap=200):
tokens = tokenizer.encode(text)
chunks = []
start = 0
while start < len(tokens):
end = start + chunk_size
chunk_tokens = tokens[start:end]
chunks.append(tokenizer.decode(chunk_tokens))
if end >= len(tokens):
break
start = end - overlap
return chunks
중복 결과 처리
오버랩 때문에 같은 내용이 여러 청크에서 검색될 수 있다. 후처리에서 Jaccard 유사도로 중복을 제거했다.
def deduplicate_results(results, threshold=0.7):
filtered = []
for result in results:
is_duplicate = False
for existing in filtered:
if jaccard_similarity(result.text, existing.text) > threshold:
is_duplicate = True
break
if not is_duplicate:
filtered.append(result)
return filtered
결과
- 검색 정확도: 73% → 88%
- 평균 응답 시간: 320ms → 380ms (허용 범위)
- 저장 용량: 약 20% 증가 (예상 범위 내)
오버랩 크기를 너무 크게 하면 저장 비용이 늘고, 너무 작으면 효과가 없었다. 여러 실험 끝에 청크 크기의 20% 정도가 적당하다는 결론을 내렸다.
추가 개선 계획
문장 경계를 고려한 스마트 청킹도 검토 중이다. 현재는 토큰 기준으로만 자르지만, 문장이나 문단 단위로 자르면 더 나은 결과를 기대할 수 있을 것 같다.