본문 바로가기
AI

검색 증강 생성(RAG) 제대로 이해하기: 구조, 알고리즘, 평가까지 총정리

  • 카카오톡 공유하기
  • 네이버블로그 공유하기
  • 페이스북 공유하기
  • URL 복사하기

들어가며,

 LLM 기반 서비스를 개발하다 보면 항상 "어떻게 하면 성능을 더 높일 수 있을까?"라는 고민에 부딪히게 됩니다. 특히 LLM이 엉뚱한 답변을 내놓는 환각(Hallucination) 문제를 해결하고, 우리 도메인에 특화된 똑똑한 답변을 얻어내는 것이 핵심이죠.

 

이 글에서는 LLM의 성능을 끌어올릴 수 있는 대표적인 3가지 전략, 즉 RAG(검색 증강 생성), 파인튜닝(Fine-Tuning), 그리고 프롬프트 엔지니어링(Prompt Engineering)을 간단하게 비교하고, 이 중 가장 실용적인 RAG 시스템의 기본 작동 원리에 대해 깊이 있게 다룹니다. 또한, RAG 시스템의 핵심인 임베딩(Embedding) 원리부터 HNSW/IVF 같은 주요 검색 알고리즘, 효율적인 데이터 포맷인 TOON, 그리고 성능을 객관적으로 측정하는 평가 지표(mRR, NDCG)의 기초 개념까지 핵심 내용을 빠짐없이 훑어봅니다.

 

이 가이드가 여러분의 LLM 프로젝트 최적화 전략 수립에 핵심적인 이해를 돕는 출발점이 되기를 바랍니다.

 


RAG 란?

RAG(Retrieval Augmented Generation, 검색증강생성)

LLM이 문서 기반으로 답변하게 해 준다.

- LL이 답변을 생성하기 전에, 외부 지식(DB/문서/웹)을 검색해서 해당 정보를 기반으로 답변하는 방식

- hallucination 감소

- 특정 도메인에 특화된 답변 

 

 

 

LLM의 성능을 높이는 방법

프롬프트 엔지니어링

In-Context Learning (ICL)

파라미터 업데이트 없이, 모델에게 예시 (few-shot-example)를 프롬프트 안에 같이 제공하여, 패턴을 학습한 것처럼 따라 하도록 유도하는 방법

 

Chain-of-Thought (CoT)

단순 답만 내는 대신 사고의 연쇄(논리 과정)를 출력하여 모델이 중간 추론 과정을 자연어로 스스로 작성되도록 유도하는 기법

 

Self-Refinement (SRR)

모델이 1차 답변을 낸 뒤, 스스로 검토(Refine/Reflect) 하여 개선된 2차 답변을 내도록 하는 방식

 

Element-Aware Summary

입력 데이터를 구성 요소(Element) 단위로 나눠서 모델이 각 요소를 놓치지 않고 다루도록 유도하는 기법

 

 

정형 데이터는 TOON 방식으로 넣어야 더 효과적이다!

TOON = Token-Oriented Object Notation

즉, LLM에게 데이터를 줄 때 토큰 수를 최소화하려고 만든 JSON 대체 포맷 
JSON은 사람이 읽기 편하지만 LLM이 읽을 때는 {}, "", 키 반복 등 때문에 토큰 수가 많아져서 비용이 커진다.

따라서 TOON은:

  • 불필요한 기호 제거
  • 반복되는 키 최소화
  • 테이블/리스트 구조에서 극대화된 압축
  • LLM-friendly 텍스트 구조
{
  "products": [
    { "id": 1, "name": "Laptop", "price": 3999.90 },
    { "id": 2, "name": "Mouse", "price": 149.90 }
  ]
}


# TOON : 토큰 수 감소
products[2]{id,name,price}:
  1,Laptop,3999.90
  2,Mouse,149.90

 

💡 TOON의 한계

# 깊게 중첩된 JSON
{"a":{"b":{"c":{"d":1}}}}


# TOON  : 들여쓰기와 구조 설명 때문에 토큰이 더 많아짐.
a:
  b:
    c:
      d: 1

🔹 넓고(flat) 정형(tabular) 데이터 → TOON이 압도적

🔹 깊은(nested) 구조 → JSON이 더 효율적

 

☑️ 사용법

JS, Python 라이브러리 사용

import { encode, decode } from '@toon-format/toon';

const toon = encode({ users: [{ id: 1, name: 'Alice' }] });
const json = decode(toon);

 

 

파인튜닝

  • pre-training : GPT, LLaMA, Qwen 같은 Base Model을 만드는 것
  • fine-tuning : 백본 모델에 특정 도메인이 특화된 데이터를 학습시켜 특정 태스크에 특화된 모델을 만드는 것

파인튜닝의 목적: 도메인 특화

- base model은 범용적으로 답변

- 기업에서는 특정 태스크를 잘 수행하는 것이 중요 : 법률, 의료, 특정 회사의 규정 등

 

파인튜닝 방법

1. 모델 작업 정도

- Full Fine-Tuning : 모든 파라미터 업데이트

- PEFT (Parameter-Efficient Fine-Tuning) : 일부 파라미터 업데이트

- LoRA / QLoRA

- Prefix-Tuning / P-Tuning 

 

2. 학습 데이트의 종류와 목표

- SFT : 정답지를 주는 감독 학습

- DPO / ORPO : 선호 비교 학습

- RLHF : 보상 기반 강화학습

- PPO 등 계열 기법 

 

 

RAG

- 최신 지식 반영 : 모델 재학습 없이 문서를 업데이트하면 즉시 새로운 지식 반영

- hallucination 방지 : 검색된 문서를 바탕으로 답변

- 도메인 특화 : 문서 기반 QA, 사내 정책, 제품 매뉴얼, 회의록 등 

 

 

  프롬프트 엔지니어링 파인튜닝 RAG
비용 난이도 매우 낮음 중간~높음 중간
데이터 수집/학습 필요 여부 없음 있음 : 많을수록 좋음 없음 : 가지고 있는 문서가 데이터
지식 업데이트 불가능 재학습 필요 즉시 반영 가능
hallucination 방지

 

 

 

 

RAG 작동원리

작동원리

 

 

임베딩 방법

1. 문서 분할 (Chunking)

긴 원본 문서를 의미 단위 일정 크기 Chunk라는 작은 조각들로 나눕니다.

  • Chunk 1: 문서의 내용을 담고 있는 첫 번째 조각.
  • Chunk 2: "임베딩 모델이 RAG 성능에 큰 영향..."을 미친다는 내용 등, 각 조각은 의미를 가진다.
  • Chunk 3: "벡터를 VectorDB에 저장하여..."와 같이 다음 단계와 관련된 내용이 포함될 수 있다.

2. 임베딩 모델 적용

  • 분할된 각 Chunk임베딩 모델(Embedding Model)에 입력
  • 임베딩 모델은 텍스트(문서 조각)를 고차원의 숫자 벡터로 변환하는 역할 
  • 출력: 임베딩 벡터 1, 2, 3... 와 같이 각 Chunk에 대응하는 다차원 숫자 배열이 생성 (예: [0.6, 0.1, 0.24, ...], [0.12, 0.15, 0.2, ...])

3. 의미상의 공간 (Semantic Space)

  • 생성된 벡터들은 의미상의 공간(Semantic Space)에 위치 
  • 이 공간에서 의미가 유사한 단어나 문장들은 가까운 거리에 배치

4. VectorDB에 저장

  • 최종적으로 변환된 다차원 임베딩 벡터들은 검색 및 활용을 위해 VectorDB에 저장
  • VectorDB에 저장된 벡터들은 3D 공간의 점들처럼 표현되며, 이 데이터베이스를 통해 의미 기반 검색을 효율적으로 수행 가능
항목 설명 예시
id 이 chunk를 식별하는 고유 ID "doc_001_chunk_01"
vector 임베딩 벡터 [0.3, 0.42, 0.1...]
metadata 검색용/보조 메타데이터 {"country": "KR", ...}
text 실제 chunk 텍스트(원문) "전원이 안 켜질 때는..."

 

 

관련 높은 문서 찾기

1. 질문을 임베딩 벡터로 변환

- "질문" -> 임베딩 모델로 벡터화 -> Query Vector

2. 메타데이터 후보군 필터링

- country="KR"인 문서(청크)만 후보군으로

3. 벡터 DB의 ANN(Approximate Nearnest Neighbor) 인덱스 알고리즘으로 Query Vector와 가까운 벡터들을 검색

- 유사도 높은 순으로 정렬해서 top-k 반환 

4. reranker로 다시 점수 매기고 상위 몇 개만 유지

5. 청크들의 text들을 LLM context로 사용

 

벡터 유사도 기반
ANN (Approximate Nearest Neighbor) 

- 근사 최근접 이웃 검색 알고리즘
- 고차원 벡터 공간에서 쿼리 벡터와 가장 가까운 벡터들을 빠르게 근사적으로 찾아내는 방법
- 기존의 정밀 최근접 이웃 검색(Exact Nearest Neighbor, 모든 벡터와 거리를 계산)은 데이터셋이 커질수록 속도가 기하급수적으로 느려지기 때문에, ANN은 약간의 정확도 손실을 감수하는 대신 검색 속도를 극대화하는 것을 목표로 한다.
- HNSW와 IVF는 모두 이 ANN을 구현하는 대표적인 방식

HNSW (Hierarchical Navigable Small World)
- 계층적 항해 가능한 작은 세상 그래프 알고리즘으로, ANN 알고리즘 중 가장 빠르고 높은 정확도를 보이는 방식 중 하나
- 검색 속도가 매우 빠르고 정확도가 높지만, 그래프 구조를 저장해야 하므로 메모리 사용량이 많은 편
- 최상위 계층은 벡터 수가 적고 연결이 듬성듬성하지만 멀리 떨어진 노드와 연결되어 있어 전역적 탐색에 유리
- 최하위 계층은 노드 수가 많고 가까운 이웃끼리 촘촘하게 연결되어 있어 지역적인 정밀 탐색에 유리
- 검색은 최상위 계층의 임의의 노드에서 시작하여 쿼리 벡터에 가까운 노드로 이동(탐색)하다가, 더 이상 가까워질 수 없으면 하위 계층으로 내려가 목표 벡터에 도달할 때까지 반복

IVF (Inverted File Index)
- 역 파일 인덱스 알고리즘으로, 벡터 공간을 분할하여 검색 범위를 줄이는 방식
- 데이터셋 전체를 K-means와 같은 클러스터링 기법을 이용해 여러 클러스터(Cluster)로 나눕니다. 각 클러스터에는 대표 벡터(Centroid)가 있으며, 각 벡터는 자신이 가장 가까운 대표 벡터를 가진 클러스터(Inverted List 또는 Cell)에 소속된다. 검색 시에는 쿼리 벡터와 가장 가까운 몇 개의 대표 벡터만을 먼저 찾고, 해당 클러스터 내부에 있는 벡터들하고만 유사도를 계산한다.
- 대규모 데이터셋에서 효율적이며, HNSW보다 메모리 사용량이 적고 인덱스 생성이 빠릅니다. 하지만 클러스터링 경계에 있는 벡터의 정확도가 떨어질 수 있어, 탐색할 클러스터의 수를 늘려 속도와 정확도를 조절

 

Lexical Retrieval
BM25 (Best Match 25)
- 희소 검색(Sparse Retrieval) 또는 키워드 기반(Lexical) 검색 방식
- 문서에 단어가 얼마나 포함되어 있는지를 기반으로 문서의 관련성 점수를 계산  
- TF-IDF (Term Frequency-Inverse Document Frequency) 모델을 개선한 것으로, 검색어 단어의 빈도(TF)와 그 단어가 전체 문서 집합에서 얼마나 희귀한지(IDF), 문서가 너무 짧거나 길지 않고(normalized), 단어가 실제로 중요한 맥락에 등장할 가능성이 높은 문서를 찾는다.
- 단어의 의미가 아닌 표현(문자)이 일치해야만 찾을 수 있다. 예를 들어, "차량"을 검색하면 "자동차"가 포함된 문서는 찾지 못할 수 있다.
- 동의어, 표현 차이 인식을 하지 못해 다국어 검색이 거의 불가능하며, 문서가 많아질수록 희귀한 단어가 지나치게 영향을 준다.

 

Semantic(Dense) Retrieval
코사인 유사도 (Cosine Similarity)
- 두 벡터가 이루는 각도의 코사인 값을 이용하여 유사도를 측정
- 벡터의 크기는 무시하고 방향에만 집중한다. 문서의 길이가 달라도(벡터의 크기가 달라도), 내용의 방향(의미)이 같으면 높은 유사도를 가진다.
- 숫자/모델명/코드 처리에 취약 
- 임베딩 모델에 따라 품질 차이가 크다.

 

Hybrid Retrieval
RRF (Reciprocal Rank Fusion, 상호 순위 융합)
- BM25(키워드 검색)와 ANN(벡터 검색)처럼 다른 방식으로 검색된 여러 결과 목록을 하나의 통합된, 더 정확한 목록으로
결합하기 위해 사용
- 각 검색 결과 목록에서 문서의 순위(Rank)만을 사용하여 점수(RRF Score)를 계산한다. 점수 대신 순위를 사용하기 때문에 서로 다른 검색 방식에서 나오는 점수 범위나 분포 문제에 영향을 받지 않는다

 

 

 

 

 

Advanced RAG

Retrieval-Augmented Generation for Large Language Models: A Survey (Gao et al., 2024)

검색 전 최적화 (Pre-Retrieval Optimization)

정보를 검색하기 전에 쿼리(질문)와 문서(데이터)를 미리 준비하여 검색의 정확도를 높인다.

 

쿼리 변환/재작성 (Query Transformation):

사용자의 복잡한 질문을 여러 개의 단순한 질문으로 분해하거나(Multi-Step Question), 질문을 더 잘 이해할 수 있도록 재작성합니다. 

- Multi-Step Question : 사용자의 원래 질문을 여러 개의 비슷한 질문으로 확장하여 각 질문으로 검색한 문서들을 통합

- Query Rewrite : 원래 질문을 검색에 더 잘 맞는 새로운 질문 형태로 재작성, 쿼리 품질을 높여 Lexical + Semantic 검색 정확도를 높인다.

 

 

보강 생성 (HyDE, Hypothetical Document Embedding):

질문을 기반으로 가상의 답변(Hypothetical Document)을 먼저 생성한 후, 이 가상의 답변을 임베딩하여 실제 문서 검색에 사용한다. 이렇게 하면 질문 자체보다 더 풍부한 의미를 담아 검색할 수 있다.

 

문서 최적화 (Document Augmentation):

문서를 임베딩하기 전에 문서의 내용(Chunk)에 제목, 요약, 핵심 키워드메타데이터를 추가하여 임베딩의 질을 높입니다.

 

 

생성 후 처리 (Post-Retrieval)

 

하이브리드 검색 (Hybrid Search):

벡터 검색 (의미 기반, HNSW/IVF)과 키워드 검색 (어휘 기반, BM25)을 RRF 같은 융합 알고리즘으로 결합하여, 의미도 유사하고 키워드도 일치하는 문서를 찾는 방식으로 검색 누락을 최소화

 

재순위화 (Re-ranking):

- 초기 검색 단계에서 수집된 상위 N개의 문서를 더 강력하고 정교한 모델 (예: 크로스 인코더)을 사용해 정확한 순위로 다시 재순위화

- RAG에서 검색된 단락이 많아지면서 중간에 있는 단락은 LLM이 참고를 잘 안 하는 문제가 발생하여, 중요한 정보일수록 상위에 배치하는 것이 중요

 

 

Augmenter:

답변의 맥락을 연결시킨다. 문장을 잘라서 Chunk로 DB에 저장할 때 이상하게 잘리는 경우가 있으므로 앞뒤 문맥을 같이 저장

 

Fillter:

score가 어느 기준 이하인 것은 모두 날리는 것이며, 모두 날아간 경우 상위 1개는 남긴다.

 

Compressor:

input token을 줄이기 위해 전치사 등 필요 없는 부분을 날려서 프롬프트를 압축

 

 

 

 

 

 

RAG 평가 지표 분석 (Metrics)

RAG(Retrieval-Augmented Generation) 시스템은 LLM의 환각(Hallucination) 문제를 줄이고 답변의 신뢰도를 높이는 핵심 기술로 주목받고 있다. 하지만 다양한 RAG 기법, 임베딩 모델, 재순위화(Re-ranker) 방법론이 존재하기 때문에, 우리 데이터와 목적에 가장 좋은 RAG 파이프라인을 선택하고 성능을 비교하기 위해서는 정확한 평가와 최적화가 필수이다.

 

RAG의 성능은 크게 검색(Retrieval) 생성(Generation) 두 단계로 나누어 평가한다.

 

검색 평가 지표 (Retrieval Metrics)

순위 무관 지표 (Rank-Unaware):

정답 단락이 Top-k 문서 내에 포함되어 있는지 여부만을 확인

  • Recall (재현율): 전체 정답 문서 중 실제로 검색에 성공한 문서의 비율
  • Precision (정밀도): 검색된 문서 중에서 실제로 정답인 문서의 비율
  • F1 Score: Precision과 Recall의 조화 평균으로, 두 지표의 균형을 나타낸다.

https://d-craftshop.tistory.com/27

Top-k를 너무 늘리면 Recall은 높아지지만, 관련 없는 문서를 많이 가져와 환각(Hallucination)의 위험을 높일 수 있다.

 

순위 인식 지표 (Rank-Aware):

정답 단락이 검색 결과의 몇 번째 순서에 포함되었는지, 즉 순서의 정확도를 평가

  • mRR (Mean Reciprocal Rank, 평균 역순위) : 질문에 대한 첫 번째 정답 문서의 순위(rank)의 역수를 평균 낸 값, 첫 번째 정답을 얼마나 빨리 찾았는지에 중점을 둔다. 순위가 1이면 점수는 1이 된다.
  • mAP (Mean Average Precision, 평균 정밀도): 정답 문서가 검색될 때마다의 Precision을 계산하고 이를 평균 낸 값, 여러 정답 문서의 순위 정확도를 전반적으로 평가한다.
  • NDCG (Normalized Discounted Cumulative Gain): 순위가 낮은 정답 문서에 패널티(Discount)를 주어, 높은 순위에 정답이 있을수록 점수를 더 주는 지표

 

생성 평가 지표 (Generation Metrics)

LLM이 검색된 문맥(Context)을 바탕으로 답변을 얼마나 잘 생성했는지 평가

분류 지표 특징 
N-gram 기반 BLEU, ROUGE, METEOR 전통적인 NLP 지표로, 생성된 답변과 정답(Reference) 간의 단어/구문 일치를 측정합니다.
LM 기반 BERT Score BERT 임베딩을 사용하여 생성된 답변과 정답 간의 의미적 유사성을 측정합니다.
LLM 기반 Coherence, Fluency, Relevance LLM을 평가자(Judge)로 사용하여 답변의 논리적 일관성, 유창성, 질문과의 관련성 등을 평가합니다.
의미 유사도 Sem Score 임베딩 모델을 활용하여 생성된 답변과 정답 간의 의미적 유사도를 비교합니다.

 

 

그 외 평가지표

Retrieval Token Metrics:

  • Compressor를 위한 metrics로, 압축된 단락과 정답이 얼마나 비슷한지 측정
  • Token Recall, Token Precision, Token F1

LLM 사용 비용 평가

  • Input Token : 직접 실험하지 않아도 토큰 사용량을 예측 가능
  • Output Token : LLM에서 출력으로 내뱉는 토큰의 수를 정확하게 예측 불가능하여 직접 실험하여 평균치 값으로 추산

LLM 답변 속도 평가

 

  • Time to first token: 첫 토큰이 나올 때까지의 시간
  • Time to last token: 마지막 토큰이 나올 때까지의 시간
  • Inter-token Latency (ITL): 한 토큰이 생성되는 평균 시간

 

 

 

RAG의 한계 

Chunking의 한계: 문맥의 단절

RAG는 문서를 일정한 길이로 잘라 Chunk 단위로 벡터화하는데, 이 과정에서 여러 문제가 발생한다.

  • 개념 간의 끊김: 중요한 개념들이 서로 다른 Chunk로 나뉘어 연결성이 끊어진다.
  • 원래 문맥의 단절: 긴 문서의 흐름이 조각나면서 주변 문맥(Local Context)이 사라져 LLM이 문서 전체를 이해하는 데 어려움
  • 정보의 분산: 같은 문맥에 있어야 하는 정보들이 물리적으로 떨어져 검색 시 함께 가져오지 못할 수 있다.
  • LLM의 추론 부담: LLM이 조각난(patchy) Chunk 몇 개를 가지고 하나의 완성된 지식처럼 재구성하고 추론해야 하는 추가적인 부담

 극복을 위해 재귀적 청킹(Recursive chunking), 의미적 청킹(Semantic chunking), 구조 기반 청킹(Document-structure-based chunking) 등 다양한 고급 청킹 전략이 연구되고 있다.

 

추론 능력 부족의 한계: 복합적 지식 처리 미흡

RAG는 저장된 단편적인 지식을 불러오는 데는 효과적이지만, 이를 조합하고 추론하여 새로운 지식을 도출하는 데는 근본적인 한계가 있다.

  • 단일 검색(Single-Hop Q&A)의 문제: 하나의 질문에 하나의 검색 과정(Hop)만 거치기 때문에, 복잡한 질문에 필요한 여러 단계의 추론이나 다중 문서 조합이 어렵다.
  • 인과적/연역적 추론 능력 부족 

 Multi-hop Q&A처럼 여러 단계를 거쳐 검색을 연속적으로 수행하거나, GraphRAG와 같이 Knowledge Graph를 이용하여 지식 간의 관계를 탐색(경로 탐색)하여 연역적 추론 문제를 해결할 수 있다.

 

임베딩 및 검색의 한계: 표현력 의존성

벡터 기반 RAG는 사용하는 임베딩 모델의 성능에 그 한계가 그대로 나타난다.

  • 문장 유사도 기반 검색의 한계: 벡터 유사성(Similarity)에 의존한 검색은 표면적인 유사성만을 반영할 수 있으며, 문서 전체의 미묘한 맥락이나 심층적인 의미론적 이해가 필요한 복잡한 태스크에서는 부정확한 답변을 초래할 수 있습니다.
  • 불필요한 정보 유입 (Noise): 정확히 일치하는 값 대신 가장 비슷한 값을 가져오기 때문에, 유사한 값 주변에 있는 불필요한 정보(Noise)가 함께 Context로 포함될 수 있습니다. 이 작은 불일치(Minor Mismatch)가 나비효과처럼 답변 전체의 맥락을 왜곡시켜 LLM의 환각을 유발할 수 있습니다.

 극복을 위해 하이브리드 검색 및 재순위화(Re-ranker)를 통해 검색 정확도를 높이고, VectorDB와 Graph DB를 결합하여 단순히 유사성뿐만 아니라 지식 간의 관계(Relationships)까지 함께 활용하는 방법이 있다.

 


 

마치며,

 

항상 RAG 프로젝트를 기획 및 진행을 할 때, 힘든 부분은 데이터셋 구축에 있습니다. 애초에 수집부터 힘든 경우가 많고, 특수한 도메인인 경우 전문가가 아닌 이상 이해하는데 많은 어려움을 겪습니다. 하지만 RAG의 성공은 검색 결과의 품질에 달려 있으며, 검색 결과의 품질은 입력된 데이터의 품질에 달려 있다는 것을 몸소 느꼈습니다. 따라서 저 또한 제가 가진 도메인 지식을 최대한 활용하는 직무로 나의 개발 커리어를 진행하고 싶다는 생각이 더욱 들었습니다.