본문으로 건너뛰기
yutils

RAG (Retrieval-Augmented Generation) 는 어떻게 동작할까?

embedding + vector DB (Pinecone / Weaviate / pgvector), chunking 전략과 naive split 의 실패, hybrid search (BM25 + vector), re-ranking, evaluation 문제, 대부분의 knowledge task 에서 RAG 가 fine-tuning 보다 나은 이유.

약 11분 읽기

ChatGPT 가 "회사 내부 문서 모름" 의 답 — 그 시점에 회사 문서를 retrieve 해서 prompt 에 넣음. 이게 Retrieval-Augmented Generation (RAG). 단순한 아이디어인데 실제 production 은 embedding / vector DB / chunking / re-ranking / evaluation 의 여러 layer. 이 가이드는 그 각각을 정리한다.

RAG 의 흐름

Phase 1 — Indexing (offline, 1 회):
  documents → chunking → embedding → vector DB 저장

Phase 2 — Retrieval + Generation (online, 매 query):
  user question
       ↓
  embed question → vector DB 검색 → top-k 유사 chunk
       ↓
  context = retrieved chunks
       ↓
  LLM prompt = "context: {chunks}\nquestion: {q}\nanswer:"
       ↓
  LLM 응답

Embedding — 의미 vector

"sneaker" 와 "running shoe" — 의미 비슷하지만 글자 다름
   → 문자열 match 로는 찾을 수 없음

embedding model 의 답:
  embed("sneaker")     = [0.12, -0.34, 0.78, ...]  (768 차원)
  embed("running shoe") = [0.11, -0.35, 0.79, ...]
  embed("airplane")    = [-0.89, 0.45, -0.12, ...]

두 vector 의 cosine similarity:
  sim(sneaker, running shoe) = 0.95  (의미 비슷)
  sim(sneaker, airplane)     = 0.10  (의미 다름)

→ "의미 검색" 가능.

embedding model 선택:
- OpenAI text-embedding-3-small: 1536 차원, 저렴, 영어 강함
- text-embedding-3-large: 3072 차원, 더 정확
- Cohere embed-multilingual: 다국어 (한국어 포함)
- BGE / E5 / GTE (OSS): self-host 가능
- 한국어 특화: ko-sroberta-multitask

Vector DB — embedding 저장 + 검색

수백만 chunk × 768 차원 vector 에서 query 의 top-10 유사 찾기 — naive
brute force = O(N × d) 매번 = 느림.

ANN (Approximate Nearest Neighbor) 알고리즘:
- HNSW (Hierarchical NSW): 그래프 기반, 가장 popular
- IVF: clustering 기반
- LSH: hashing 기반
- DiskANN: SSD 기반 매우 큰 dataset

vector DB 도구:
- Pinecone — managed, 쉬움 + 가격
- Weaviate (OSS) — multi-modal
- Qdrant (OSS) — Rust, fast
- Milvus (OSS) — 큰 scale
- pgvector (Postgres extension) — 기존 PG 위에 / 작은 dataset
- ChromaDB (OSS) — embedded, dev 친화
- Elasticsearch 8+ — full-text + vector hybrid

작은 dataset (< 10만): pgvector 또는 ChromaDB 충분
큰 dataset (수백만+): Pinecone / Qdrant / Milvus

Chunking — naive split 의 함정

전체 문서를 한 embedding 으로? → 너무 큼, 의미 희석.
한 글자씩? → 의미 없음.

적당한 chunk 크기 (500-1500 token) 가 필요.

Naive — 글자 수로 자르기:
  chunk[0] = doc[0:1000]
  chunk[1] = doc[1000:2000]
  ...

문제:
- 문장 / 문단 중간에 잘림 → 의미 흐려짐
- "the answer is" 와 "yes" 가 분리 → 검색 시 context 잃음

Better — 의미 단위 chunking:
- 문단 단위 split + 큰 문단은 다시 split
- recursive split (큰 → 작은 separator)
- sliding window (200 token overlap) — 경계 정보 보존

modern — semantic chunking:
- embedding 비교로 의미 변화 시점에 split
- e.g. LangChain 의 SemanticChunker

→ chunking 전략이 RAG quality 의 30%+. 실험 필수.

Hybrid Search — vector + keyword

vector search 의 약점:
- 정확한 keyword (제품 모델명, 사람 이름) 매칭 약함
- "iPhone 15 Pro Max" 검색 시 "iPhone 13" 도 의미 유사 → 같이 retrieve

Keyword search (BM25) 의 약점:
- 동의어 매칭 X
- "fast running shoes" 검색 시 "sneaker" 안 찾음

Hybrid:
- BM25 + vector 의 score 결합 (RRF — Reciprocal Rank Fusion)
- 또는 weighted (0.5 × bm25 + 0.5 × vector)

→ 정확성과 의미를 모두 잡음. modern production 의 표준.

도구:
- Elasticsearch / OpenSearch 의 hybrid query
- Weaviate / Pinecone 의 hybrid
- LangChain / LlamaIndex 의 EnsembleRetriever

Re-Ranking — 정밀도 ↑

vector / hybrid search 의 top-50 → 그 중 top-10 을 다시 rank.

이유:
- vector embedding 의 유사도 = 의미 유사 (proxy)
- 진짜 "이 question 에 답하기 좋은 chunk" 는 다른 criteria
- cross-encoder re-ranker = question + chunk 를 함께 입력 → 직접 relevance score

도구:
- Cohere Rerank — API 형태, 강력
- BGE Reranker — OSS
- ColBERT — late interaction, fast

trade-off:
- top-50 retrieve + re-rank top-10 → 정확도 ↑, latency +50-200ms
- 중요 task 의 standard, latency 민감하면 skip

Evaluation — 가장 어려운 부분

"이 RAG 가 좋은가?" 의 답 어려움:
- ground truth (정답) 가 거의 없음
- LLM 의 답이 매번 약간 달라 (sampling)
- 사람 평가가 비쌈

도구:
- Ragas — LLM 으로 자동 평가 (faithfulness, relevance, context recall)
- TruLens — 각 단계의 metric
- LLM-as-judge — GPT-4 가 두 답 비교

metric:
- Context recall: retrieved chunk 가 정답을 포함하는가
- Context precision: retrieved chunk 가 noise 가 적은가
- Faithfulness: LLM 의 답이 context 안 사실에 충실한가
- Answer relevance: 답이 question 에 직접 답하는가

practical:
- 50-100 question 의 golden set 만들고 weekly evaluate
- production 의 query log + user feedback 도 분석

RAG vs Fine-tuning

특성RAGFine-tuning
새 지식 추가document 추가만 (즉시)재학습 필요
costretrieval cost + LLM APItraining cost ↑ + serving 같음
style 변경약함 (prompt 의지)강함 (LLM 의 출력 style)
hallucinationcontext 의지로 줄임여전히 가능
source citation자연 (retrieved chunk 인용)어려움

대부분의 knowledge task = RAG. style / behavior 변경 = fine-tuning. 둘 다 결합도 가능 (fine-tune base + RAG 로 새 지식).

흔한 함정

  • naive character split — 의미 단위 안 보존 → RAG quality 저하. recursive 또는 semantic.
  • vector search 만 — keyword 매칭 약함. hybrid (BM25 + vector).
  • top-k 너무 작음 — k=3 면 정답 chunk 못 들어옴. k=10-20 + re-rank.
  • evaluation 없음 — "잘 작동하는 것 같음" 의 안주. golden set + RAGas 같은 자동 평가.
  • context window overflow — retrieved chunk 의 합이 LLM context limit 초과. dynamic chunk 수 또는 더 큰 context window 모델.

마무리

RAG 의 본질 — LLM 의 파라미터 학습 없이 retrieval 로 새 지식 주입. embedding + vector DB + chunking + hybrid + re-rank 의 layer. fine-tuning 의 대안이지만 둘 다 결합 가능.

실용 — 작은 시작: ChromaDB (in-memory) + OpenAI embedding + recursive chunk + naive top-k. production 으로 가면 hybrid + re-rank + RAGas eval. 대부분 knowledge chatbot / Q&A 의 표준 패턴.

가이드 목록으로