이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • RAG indexing pipeline은 어떤 단계로 구성되는가?
  • 문서 수정, 삭제, 권한 변경은 vector index에 어떻게 반영해야 하는가?
  • batch indexing이 online serving을 방해하지 않게 하려면 어떻게 해야 하는가?

개요

Indexing Pipeline은 문서를 검색 가능한 vector record로 바꾸는 과정이다. 문서 수집, parsing, chunking, embedding, metadata 생성, vector DB 저장, 검증으로 이어진다.

운영에서는 처음 색인보다 수정, 삭제, 권한 변경, 재색인이 더 어렵다.

전체 흐름

Document Source
  parsing
  chunking
  metadata 생성
  embedding
  vector upsert
  verification
  serving

각 단계는 실패할 수 있으므로 job 상태를 남긴다.

Chunking

chunking은 문서를 작은 단위로 나누는 일이다. chunk가 너무 작으면 문맥이 부족하고, 너무 크면 검색 precision과 token 비용이 나빠질 수 있다.

고려할 것:

  • 문서 구조
  • 제목과 섹션
  • 코드 블록
  • overlap
  • source id
  • chunk order

코드로 이해하기

간단한 indexing job 구조다.

def index_document(document, embedding_client, vector_store):
    chunks = split_into_chunks(document.text)
    records = []
 
    for index, chunk in enumerate(chunks):
        vector = embedding_client.embed(chunk.text)
        records.append({
            "id": f"{document.id}:{index}",
            "vector": vector,
            "metadata": {
                "source_id": document.id,
                "document_version": document.version,
                "chunk_index": index,
                "tenant_id": document.tenant_id,
                "deleted": False,
                "embedding_model": embedding_client.model,
            },
        })
 
    vector_store.upsert(records)

실제 운영에서는 실패한 chunk 재시도, rate limit, idempotency, 기존 chunk 삭제가 추가된다.

수정과 삭제

문서 수정:

  • 기존 source id의 old version chunk를 제거하거나 비활성화한다.
  • 새 version chunk를 색인한다.
  • serving에서 latest version만 검색되게 한다.

문서 삭제:

  • 원본 DB 삭제와 vector delete를 연결한다.
  • delete 실패를 재처리한다.
  • 정기 reconcile job으로 잔존 chunk를 찾는다.

권한 변경:

  • metadata를 갱신하거나 재색인한다.
  • 검색 후 서버 권한 검증으로 방어한다.

장애 상황과 대응

증상:

  • 최신 문서가 검색되지 않는다.
  • 삭제한 문서가 계속 답변에 나온다.
  • 재색인 중 검색 latency가 증가한다.
  • 일부 chunk만 색인되어 답변이 불완전하다.

대응:

  • indexing job status를 본다.
  • source id 기준 vector count를 검증한다.
  • old/new version 혼재를 확인한다.
  • batch worker concurrency를 낮춘다.

인프라 협업 포인트

인프라팀과는 다음을 합의한다.

  • indexing worker 수
  • embedding API rate limit
  • vector DB write throughput
  • batch job 시간대
  • online query와 batch indexing 리소스 분리
  • backup과 restore

개인 프로젝트 최소 기준

  • 문서마다 source id를 둔다.
  • 삭제 스크립트를 둔다.
  • indexing 실패 로그를 남긴다.
  • embedding model version을 metadata에 둔다.

기업 운영 수준 기준

  • 문서 이벤트 기반 incremental indexing을 둔다.
  • 재색인 runbook을 둔다.
  • reconcile job을 둔다.
  • batch와 online 리소스를 분리한다.
  • indexing lag를 metric으로 본다.

실전 팁

  • index는 원본 데이터에서 재생성 가능해야 한다.
  • 재색인은 migration처럼 계획한다.
  • chunk id는 deterministic하게 만들면 idempotent upsert가 쉽다.
  • indexing lag를 사용자 품질 지표와 연결한다.

위험 신호!

  • 문서 삭제가 vector delete와 연결되지 않는다.
  • indexing job 상태가 없다.
  • 재색인 중 online query가 느려진다.
  • embedding model version이 metadata에 없다.

확인 질문

확인 질문

  • 문서 삭제 이벤트를 vector index에 반영해야 하는 이유는 무엇인가?
    • 삭제된 정보가 검색되어 개인정보나 권한 사고를 만들 수 있기 때문이다.
  • batch indexing과 online serving을 분리해야 하는 이유는 무엇인가?
    • 대량 write와 embedding 작업이 실시간 검색 latency를 악화시킬 수 있기 때문이다.

Spring AI 적용 연결

참고 문서