프로덕션 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% 정도가 적당하다는 결론을 내렸다.

추가 개선 계획

문장 경계를 고려한 스마트 청킹도 검토 중이다. 현재는 토큰 기준으로만 자르지만, 문장이나 문단 단위로 자르면 더 나은 결과를 기대할 수 있을 것 같다.

프로덕션 RAG 시스템에 청크 오버랩 적용하기