[RAG] 2. 청크 : RAG 청크 분할하는 법

RAG 실전 가이드 2편 - RAG 청크 분할하는 법

작성자

카테고리:

* 이 게시물은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

(RAG 시리즈 ②) 청크 분할

RAG를 처음 붙일 때 제일 만만하게 봤던 게 문서 쪼개기였다. 그냥 1000자씩 뚝뚝 자르면 되는 거 아닌가 싶었다. 그렇게 해놓고 검색을 돌렸더니, 질문이랑 상관없는 조각이 자꾸 딸려 나왔다.

원인은 단순했다. 1000자 안에 서로 다른 주제 서너 개가 섞여 있으니, 그중 한 문장만 질문이랑 비슷해도 그 덩어리 전체가 딸려 온다. 검색 단위가 곧 답의 단위인데, 그 단위가 지저분했던 거다. 청크는 “검색됐을 때 그 자체로 말이 되는 최소 덩어리”여야 한다.

정리하고 나서 기본값으로 삼은 건 재귀 분할(recursive splitting)이다. 글자 수로 무작정 자르지 않고 문단 → 문장 → 단어 순으로 자연스러운 경계를 우선 존중하면서, 목표 크기를 넘지 않을 때까지 큰 단위부터 쪼갠다. 크기 감각은 한국어 기준 대략 한 조각 300~500토큰, 조각끼리 10~15% 정도 겹치게(overlap) 뒀다. 겹침은 경계에서 문맥이 뚝 끊기는 걸 완화한다. 문장 하나가 두 조각에 걸쳐 잘려도 양쪽에 조금씩 남아 있으니 검색이 덜 놓친다.

라이브러리를 쓰면 재귀 분할은 몇 줄이면 된다. 경계 우선순위와 겹침만 지정해 주면 된다.

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=400,        # 목표 크기(토큰 대략)
    chunk_overlap=50,      # 10~15% 겹침
    separators=["\n\n", "\n", ". ", " ", ""],  # 문단 → 문장 → 단어 순
)
chunks = splitter.split_text(document)

문서 성격에 따라 재귀 분할보다 나은 것도 있다. 기술 문서나 매뉴얼처럼 구조가 뚜렷하면 마크다운 헤더나 코드 블록 단위로 자르는 게 훨씬 깔끔하다. 헤더 밑 내용이 자연스러운 한 덩어리가 되니까. 표나 코드가 중간에 반토막 나는 사고도 막을 수 있다.

조각을 저장할 때 본문만 넣지 말고 메타데이터를 같이 달아둔 것도 나중에 크게 도움이 됐다. 출처 문서명, 섹션 제목, 작성일, 카테고리 정도. “2025년 이후 문서에서만 찾아”나 “이 제품 매뉴얼 안에서만” 같은 필터가 필요할 때 이게 있고 없고가 하늘과 땅이다. 처음엔 귀찮아서 안 넣었다가 전부 다시 인덱싱했다. 미리 넣자.

조금 더 들어가면 검색용 조각과 전달용 조각을 분리하는 기법도 쓸 만하다. 검색은 짧은 조각으로 정밀하게 하되, 정작 모델한테는 그 조각이 속한 더 큰 문단(부모 청크)을 넘겨주는 식이다. 검색 정확도는 작은 단위로 챙기고 답변에 필요한 문맥은 넓게 주는, 두 마리 토끼를 노리는 방법이다. 처음부터 이걸 할 필요는 없지만, 답이 자꾸 문맥 부족으로 부실하면 이 카드를 꺼내면 된다.

크기별로 재보는 법

그럼 300~500토큰이 항상 정답이냐 하면, 아니다 — 문서 성격마다 다르다. 다행히 비교 실험은 어렵지 않다. 같은 문서를 두세 가지 크기로 인덱싱해두고, 정답 셋(질문 → 정답이 든 문서)을 몇십 개 만들어 Recall@k를 재면 된다.

# 크기별 A/B — 같은 정답 셋으로 적중률만 비교
for size in [300, 500, 800]:
    index = build_index(docs, chunk_size=size, overlap=0.1)
    hit = sum(1 for q, gold in testset
              if gold in [c.doc_id for c in index.search(q, k=5)])
    print(f"chunk={size}: Recall@5 = {hit}/{len(testset)}")

한 시간짜리 실험이 몇 주의 감 논쟁을 끝낸다. FAQ처럼 짧은 문서는 작게, 서술형은 크게 나오는 게 보통이지만 — 내 수치가 나오기 전까지는 전부 남의 기본값이다.

정답은 데이터마다 다르다 — 재보고 정한다

만능 청크 크기는 없다. FAQ처럼 짧은 Q&A는 작게, 서술형 문서는 크게가 대체로 맞지만, 결국 내 데이터로 검색 품질을 재보고 조정해야 한다. 너무 작으면 맥락이 없고, 너무 크면 잡음이 섞인다. 몇 가지 크기로 A/B를 해보는 게 정석이다. 이렇게 잘 자른 청크 위에 하이브리드 검색(4편)을 얹으면 검색 품질이 한 단계 더 올라간다.

결국 청크는 “한 조각에 한 주제, 그리고 그 자체로 읽히게”라는 감각 하나로 수렴한다. 이거 하나만 지켜도 검색이 눈에 띄게 얌전해진다.

자주 묻는 질문 (FAQ)

청크 크기는 얼마가 적당한가요?

정답은 없지만 보통 200~500 토큰에 10~20% 겹침(overlap)으로 시작해 조정합니다. 코드·문서·대화 등 자료 성격에 따라 다르니, 실제 검색 품질로 검증하며 맞추는 게 정석입니다.

문장 단위로 잘게 자르면 안 되나요?

너무 잘게 자르면 문맥이 끊겨 검색 정확도가 떨어집니다. 문단·섹션 같은 의미 단위를 유지하면서 약간의 겹침을 주는 편이 대체로 낫습니다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다