kokoball의 devlog
article thumbnail
728x90

 

Retrieval-Augmented Generation (Embedding, Vector DB)

 

이번 회차의 키워드는 한 문장으로 정리하면 이렇습니다. “LLM이 답하기 전에, 우리 문서에서 먼저 찾아오게 만들자.”

 

 LLM은 학습 시점 이후의 정보를 알 수 없고(knowledge cutoff), 회사 내부 문서·도메인 지식은 애초에 학습 데이터에 포함되지 않으며, 모르면 그럴듯하게 지어내는 환각(Hallucination)도 발생합니다.

 

그래서 실전에서는 “모델을 더 똑똑하게 만들기”보다 “모델이 참고할 근거를 먼저 주기”가 더 빠르고, 더 싸고, 더 안전한 경우가 많습니다.

 

그 구조가 바로 RAG(Retrieval-Augmented Generation) 입니다.

RAG는 말 그대로 검색(Retrieval) + 생성(Generation)  이고, 더 줄이면 “검색기술 + LLM 제시어(프롬프트)”  입니다.

 


RAG란 무엇인가

RAG(Retrieval-Augmented Generation) 는 모델이 답변을 생성하기 전에, 외부 지식 소스(사내 위키, PDF, 매뉴얼, Notion, 코드, 정책 문서 등)에서 관련 내용을 검색(Retrieval)  해서, 그 결과를 사용자 질문과 함께 LLM 입력(Context) 으로 넣고 답을 생성하는 방식입니다.

 

여기서 중요한 전제는 LLM이 “학습이 동결된 모델”이라는 점입니다. 즉, 모델 파라미터 자체는 고정되어 있으니, 최신 정보나 사내 지식을 쓰려면 Retrieval이 사실상 필수입니다. 또한 “근거 문서”를 넣어주기 때문에 환각을 줄이고, “제공한 문서 범위 안에서만 답하라” 같은 제어도 가능해집니다.

 


RAG 전체 흐름 (End-to-End 파이프라인)

 

RAG는 구현 관점에서 아래 파이프라인으로 이해하면 가장 깔끔합니다.

  1. 문서 파싱: PDF/HTML/Notion/MD/코드 등 원본을 텍스트로 추출
  2. 텍스트 분할(Chunking): 문서를 검색 가능한 단위로 쪼갬
  3. 백터화(Embedding): 각 청크를 Embedding 모델로 벡터로 변환
  4. Vector DB 저장: 벡터 + 원문 + 메타데이터를 저장
  5. 질문 입력: 사용자 질문 수신
  6. 질문 임베딩: 질문을 벡터로 변환
  7. Retrieval(검색): 유사도 기반으로 top-k 청크 검색
  8. 증강(Augmentation): 질문 + 검색된 청크를 프롬프트에 결합
  9. 응답 생성(Generation): LLM이 근거 기반 답변 생성 (+출처 첨부 가능)
  10. 검색 단계에서 흔히 쓰는 유사도 계산은 Cosine Similarity / Dot Product / Euclidean Distance(L2) 등이 있고, 실제 시스템에서는 “정확한 키워드가 중요한 경우” 때문에 벡터검색만 쓰지 않고 키워드검색(BM25)과 섞는 하이브리드도 자주 사용합니다.

RAG의 장점 / 단점

장점

  • 실시간 업데이트: DB/문서만 업데이트하면 모델을 다시 학습하지 않아도 최신 지식 반영 가능
  • 비용 대비 효율: 파인튜닝보다 빠르고 비용이 낮은 경우가 많음(“필요한 지식만 찾아서 넣기”)
  • 신뢰성과 투명성: 답변에 “근거 문서(출처)”를 함께 제시할 수 있음
  • 안전하고 제어 가능: “제공한 문서에 기반해서만 답하라” 같은 정책 적용이 상대적으로 쉬움(권한/필터/금지 문서 제어 등)

단점

  • 검색 품질의 한계: Retrieval이 빗나가면 답변 품질도 같이 흔들림(가장 흔한 실패 포인트)
  • 시스템 복잡도 증가: 파이프라인(파싱/청킹/임베딩/DB/리랭크/프롬프트)이 늘어나 운영 난이도 상승
  • Context 영향: 어떤 청크를 얼마나 넣느냐에 따라 답변이 크게 달라짐(문서 영향도가 큼)

 

Embedding과 Vector DB를 한 번에 이해하기

 

Embedding이란?

 

Embedding은 텍스트(단어/문장/문서)를 고차원 숫자 벡터로 바꿔 “의미적 거리”를 계산할 수 있게 만드는 표현입니다. 문자열 상태로는 컴퓨터가 의미 비교를 잘 못하니, 문장 하나를 “숫자 배열”로 바꿔서 서로 얼마나 비슷한지 수학적으로 비교하는 방식입니다.

 

예를 들어 2차원으로 단순화하면 “고양이 [1.0, 2.0]”와 “강아지 [1.2, 1.8]”는 가깝고, “자동차 [5.0, 0.5]”는 멀리 떨어집니다. 중요한 건 숫자 자체가 아니라 가까운 좌표 = 의미가 비슷하다는 점입니다.


Vector DB란?

Vector DB는 텍스트/이미지/오디오 같은 비정형 데이터를 벡터 형태로 저장하고, 벡터 간 유사도를 기반으로 “가까운 이웃”을 빠르게 찾아주는 데이터베이스입니다.

 

일반 DB는 고차원 벡터의 근접 검색(ANN: Approximate Nearest Neighbor)을 효율적으로 처리하기 어렵기 때문에, Vector DB는 인덱싱/거리 계산/압축 같은 기능을 포함해 검색을 최적화해 줍니다.

 

실전에서는 벡터 유사도로 1차 후보를 뽑고, 메타데이터(lang, 날짜, 카테고리, 권한 등)로 2차 필터링을 하는 패턴이 매우 흔합니다. 예시 구조는 아래처럼 “원문 + 벡터 + 메타데이터”가 한 세트입니다.

 

{
  "id": "chunk_00123",
  "vector": [0.0123, -0.993, 0.45],
  "text": "퇴직금은 근로자 평균임금에 따라 산정되며...",
  "metadata": {
    "doc_id": "hr_rules_2024.pdf",
    "section": "3.2 퇴직금 산정 기준",
    "lang": "ko",
    "created_at": "2024-01-10",
    "source": "내부 인사 규정"
  }
}

 

 

Chunking(청킹) 전략이 RAG 성능을 좌우한다

RAG에서 “검색이 잘 되느냐”는 임베딩 모델만의 문제가 아니라, 문서를 어떻게 나눴는지(Chunking) 가 크게 좌우합니다. 너무 큰 청크는 의미가 뒤섞여 검색이 흐려지고, 너무 작은 청크는 문맥이 끊겨 답변 품질이 떨어집니다. 흔히 쓰는 방식은 다음과 같습니다.

 

  • Fixed-size(고정 길이): 구현이 쉽지만 문맥 손실 가능
  • Semantic(의미 기반): 문단/제목/불릿 기준으로 자르며 검색 품질이 좋아지는 대신 구현 난이도가 올라감
  • Hierarchical(계층형): 섹션(상위) + 문단(하위)을 함께 저장해 대형 문서에서 강함(문서-청크를 같이 다루기 쉬움)

Advanced RAG: “검색 전/중/후”를 추가로 다듬는 단계

 

기본 RAG가 “질문 → 검색 → 문서 붙임 → 생성”이라면, Advanced RAG는 검색 전(Pre) / 검색(중) / 검색 후(Post) 에 최적화 과정을 더합니다.

 

 

Pre-Retrieval

  • Query Rewriting: 사용자의 질문을 “검색 친화적” 문장으로 재작성(예: “passport 안돼요” → “passport MRZ 인식 오류 원인”)
  • HyDE(가상 문서 임베딩): 질문을 그대로 벡터화하지 않고, LLM이 질문에 대한 “가상의 답변 문서”를 먼저 써서 그 문서를 임베딩해 검색 품질을 올리는 방식(짧고 모호한 질문에서 특히 강함)

Retrieval

  • 혼합 검색(Hybrid): 벡터 유사도 + 키워드(BM25) 결합, 또는 거리 메트릭을 조합

Post-Retrieval

  • Rerank(재정렬): top-k 후보 문서를 더 정교한 모델로 다시 읽고 순위를 재조정(Cohere Rerank, bge-reranker, Voyage rerank 등)
  • Filter / Context 최적화: 중복 제거, 오래된 정보 제외, 메타데이터 기반 필터(날짜/카테고리/권한), 컨텍스트 압축(요약/추출/문장 단위 필터링), 청크 병합/재청킹(ParentDocumentRetriever, AutoMergingRetriever 등), 컨텍스트 순서 최적화(관련도/최신성/출처별 그룹화)
  • 특히 RAG-Fusion은 “하나의 질문을 여러 하위 질문으로 재작성 → 각각 독립 검색 → RRF(Reciprocal Rank Fusion)로 결과를 융합/재순위 → 최종 문서로 답변” 흐름으로, 단일 쿼리 검색이 놓치는 문서를 보강하는 데 자주 쓰입니다.

RAG 평가: RAGAS 관점으로 무엇을 보나

 

RAG는 “모델이 잘하냐”보다 “검색-근거-답변 연결이 잘 되냐”가 핵심이라, 평가도 그 축으로 봅니다. 예를 들어 RAGAS에서는

 

  • ContextRelevance / ContextPrecision: 가져온 문서가 질문과 얼마나 관련 있는지, 쓸데없는 문서가 섞였는지
  • ContextEntityRecall: 답변에 필요한 정보가 컨텍스트에 충분히 포함됐는지(유실 여부)
  • Faithfulness: 답변이 컨텍스트에 근거해 생성됐는지(근거 일탈 여부)
  • ResponseRelevance / AnswerCorrectness / SemanticSimilarity: 답변이 질문에 맞는지, 정답과 의미적으로 얼마나 유사한지
  • 같은 지표로 시스템을 점검합니다.

정리: RAG가 실제로 “하는 일”

 

결국 RAG가 하는 일은 명확합니다. 

질문이 들어오면, 내 문서들 중에서 의미적으로 가장 가까운 조각들을 찾아오는 것이고, 그 “의미적 가까움”을 계산하기 위해 문서(전체/섹션/문단)를 임베딩해 Vector DB에 저장합니다.

 

그리고 사용자 질문도 임베딩으로 바꾼 뒤, 질문 벡터와 가까운 문서 벡터를 찾아 컨텍스트로 붙여서, LLM이 “근거 기반”으로 답하게 만드는 파이프라인입니다.

728x90
profile

kokoball의 devlog

@kokoball-dev

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!