RAG 시스템 구축하며 겪은 청크 사이즈 최적화 삽질기

배경

사내 기술 문서가 300개를 넘어가면서 검색 품질이 문제가 되었다. 기존 키워드 검색으로는 맥락을 고려한 답변이 불가능해서 RAG 시스템을 도입하기로 했다.

초기 구현

LangChain과 OpenAI Embedding을 사용했다. 처음엔 별 생각 없이 RecursiveCharacterTextSplitter로 chunk_size=512, overlap=0 으로 설정했다.

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=0,
    separators=["\n\n", "\n", ". ", " ", ""]
)
chunks = splitter.split_documents(docs)

문제 발견

코드 블록이 포함된 문서에서 검색 정확도가 떨어졌다. 특히 함수 설명과 예제 코드가 다른 청크로 분리되면서 맥락이 끊기는 케이스가 많았다.

512 토큰은 생각보다 짧았다. 마크다운 코드 블록 하나만 들어가도 나머지 설명이 잘렸다.

테스트와 조정

청크 크기를 256, 512, 1024로 변경하며 20개 쿼리로 품질을 비교했다. 의외로 256 토큰이 가장 정확도가 높았다. 대신 overlap을 50으로 설정해 맥락 단절을 방지했다.

splitter = RecursiveCharacterTextSplitter(
    chunk_size=256,
    chunk_overlap=50,
    separators=["\n## ", "\n### ", "\n\n", "\n", ". "]
)

마크다운 헤더를 separator 우선순위에 추가한 게 효과적이었다. 섹션 단위로 자연스럽게 분할되었다.

결과

검색 정확도는 체감상 30% 정도 개선되었다. 청크 개수는 3배 늘었지만 Vector DB 비용은 크게 문제되지 않았다. Pinecone 무료 티어로 충분했다.

정답은 없다는 걸 배웠다. 문서 특성에 따라 직접 테스트하는 수밖에 없었다.

RAG 시스템 구축하며 겪은 청크 사이즈 최적화 삽질기