콘텐츠로 이동

RAG 기초

분류: Layer 12 - AI 시스템 & LLM 애플리케이션 | 선수지식: L12-10 (LLM API), L12-20 (Prompt), L12-30 (임베딩·벡터)

RAG 기초 — Retrieval, Augmentation, Generation

섹션 제목: “RAG 기초 — Retrieval, Augmentation, Generation”

RAG(Retrieval-Augmented Generation)는 모델이 이미 알고 있는 고정 지식만으로 답하게 두지 않고, 외부 문서를 검색해 context에 붙인 뒤 답을 생성하게 하는 애플리케이션 패턴이다.

이름의 세 단어를 그대로 읽으면 된다.

  1. Retrieval: 질문에 필요한 근거 후보를 외부 저장소에서 찾는다.
  2. Augmentation: 찾은 근거를 prompt, message, tool result 같은 입력 구조에 넣는다.
  3. Generation: LLM이 그 근거를 읽고 사용자가 이해할 수 있는 답변으로 합성한다.

핵심은 “검색을 붙이면 모델이 더 똑똑해진다”가 아니다. RAG의 핵심 철학은 지식의 원본을 모델 가중치 밖에 두고, 답변할 때마다 필요한 근거만 가져와 provenance(출처)와 freshness(최신성)를 운영 로직으로 통제하는 것이다.

LLM은 학습 시점까지의 패턴과 사실을 가중치 안에 압축해 둔다. 이 지식을 parametric knowledge라고 부른다. 사용자가 “현재 사내 휴가 정책”, “오늘 적용 중인 가격표”, “이 고객에게 허용된 계약 조항”을 묻는 순간 이 방식은 세 가지 벽에 부딪힌다.

모델 고정 지식만 쓸 때 생기는 문제RAG가 줄이는 문제
최신성모델 학습 이후 바뀐 사실을 모른다원본 문서가 바뀌면 색인을 갱신해 다음 답변부터 반영한다
출처답이 어느 문서에서 왔는지 되짚기 어렵다chunk ID, URL, version을 함께 반환해 인용과 감사를 가능하게 한다
권한모델은 사용자별 문서 권한을 스스로 알지 못한다검색 단계에서 tenant, ACL, version filter를 적용한다
수정 가능성잘못된 지식을 고치려면 모델·prompt·데이터를 함께 의심하게 된다원본 문서, 색인, 검색, 생성 중 어느 단계가 깨졌는지 분리해 본다

2.1 선행 기술의 한계 — RAG가 등장한 이유

섹션 제목: “2.1 선행 기술의 한계 — RAG가 등장한 이유”

Lewis et al.의 2020년 RAG 논문은 모델의 parametric memory와 외부 문서 인덱스 같은 non-parametric memory를 결합했다. 여기서 non-parametric memory는 “지식이 모델 가중치에 박혀 있지 않고, 검색 가능한 외부 저장소에 남아 있다”는 뜻으로 이해하면 된다.

이 발상은 fine-tuning, 긴 prompt, 검색 없는 LLM 호출이 각각 잘 못 푸는 문제에서 나왔다.

  • Fine-tuning만으로 사실을 갱신하는 문제: 모델의 행동·말투·형식을 맞추는 데는 도움이 되지만, 자주 바뀌는 문서를 매번 가중치에 다시 넣는 방식은 느리고 rollback도 어렵다.
  • 긴 문서를 통째로 넣는 문제: 한 번에 넣을 수 있는 문서량은 context window와 비용에 묶인다. 또한 중요한 근거가 긴 context 중간에 묻히면 모델이 잘 활용하지 못할 수 있다.
  • 검색 없는 생성의 문제: 모델은 모르면 멈추는 시스템이 아니라, 다음 token을 그럴듯하게 이어 쓰는 시스템이다. 근거가 없을 때도 자연스러운 답을 만들 수 있다.

RAG는 이 문제를 “모델을 계속 다시 학습시키자”가 아니라 지식과 생성 능력을 분리하자로 푼다. 지식은 문서·DB·검색 인덱스에 두고, 모델은 매 호출마다 가져온 근거를 읽어 답을 합성한다.

퀴즈

RAG는 hallucination을 자동으로 없애는 장치일까?

힌트: 검색과 생성은 서로 다른 실패 지점이다.

정답 보기

아니다. RAG는 모델이 참고할 근거를 제공하고 출처를 남길 수 있게 해 주지만, 검색된 문서가 틀렸거나 prompt가 근거 밖 생성을 허용하면 여전히 그럴듯한 오답이 나온다. 검색 실패와 생성 faithfulness(근거 충실도) 실패를 분리해서 봐야 한다.

RAG는 보통 두 개의 시간대로 나뉜다.

[색인 단계 — offline 또는 background]
1. 원본 문서 수집
2. 문서를 검색 가능한 chunk로 분할
3. chunk를 embedding으로 변환
4. vector store와 lexical index에 저장
5. doc_id, version, source URL, tenant, ACL, updated_at metadata 저장
[질문 처리 단계 — online]
6. 사용자 질문과 대화 맥락 정리
7. 검색 query 생성
8. 후보 문서 검색과 재정렬
9. prompt에 근거 주입
10. LLM 생성
11. citation, refusal, 품질 gate 적용

여기서 tenant는 여러 고객·조직의 데이터를 한 시스템에 담을 때의 격리 단위이고, ACL(Access Control List)은 사용자가 볼 수 있는 문서 권한 목록이다. updated_at은 최신성 판단에 쓰는 시간 metadata다. 이 셋은 검색 점수보다 먼저 적용되어야 한다. 권한 밖 문서를 검색한 뒤 마지막 응답에서만 숨기면, trace·reranker·prompt 안에는 이미 민감 문서가 들어간 상태가 된다.

RAG의 두 단계
flowchart TD
A["원본 문서"] --> B["Chunking"]
B --> C["Embedding"]
C --> D["Vector store / lexical index"]
D --> E["권한·버전·출처 metadata"]
F["사용자 질문"] --> G["Query transform"]
G --> H["Retrieval"]
E --> H
H --> I["Rerank / context packing"]
I --> J["Augmentation"]
J --> K["LLM generation"]
K --> L{"근거와 답변이 맞나?"}
L -->|yes| M["답변 + citation"]
L -->|no| N["재검색 또는 refusal"]

RAG 품질은 LLM 호출 하나가 아니라 색인, 검색, context 구성, 생성, 검증이 이어진 파이프라인 품질이다.

처음 공부할 때는 많은 기법 이름보다 아래 네 질문을 먼저 잡는다.

  1. 어떤 지식을 모델 밖에 둘 것인가? 자주 바뀌고 출처가 필요한 지식은 RAG 후보가 된다.
  2. 그 지식을 어떤 단위로 찾을 것인가? 문서 전체, 문단, 표 행, 코드 함수처럼 검색 단위가 답변 품질을 바꾼다.
  3. 찾은 근거를 어떻게 믿게 할 것인가? prompt 구조, citation, refusal 규칙이 필요하다.
  4. 검색과 생성 중 어디가 실패했는지 어떻게 알 것인가? retrieval metric과 generation metric을 분리해야 한다.

4. 작은 worked example — 사내 휴가 정책 질문

섹션 제목: “4. 작은 worked example — 사내 휴가 정책 질문”

아래처럼 사내 정책 문서가 있다고 하자.

doc_hr_v7 / section: annual_leave / updated_at: 2026-03-01
연차는 사용 1일 전까지 HR 포털에서 신청한다.
doc_hr_v8 / section: half_day / updated_at: 2026-06-15
반차는 사용 당일 오전 10시 전까지 신청할 수 있다.
단, 팀 승인 정책이 있는 조직은 전날 18시까지 신청한다.
doc_hr_v5 / section: half_day / updated_at: 2025-11-20
반차는 사용 1일 전까지 신청한다.

사용자가 묻는다.

질문: "반차는 언제까지 신청해야 해?"

검색 없는 LLM 호출은 “일반적으로 전날까지 신청합니다”처럼 답할 수 있다. 그 답이 자연스러워 보여도 현재 회사 정책과 맞는지는 알 수 없다.

RAG는 다르게 움직인다.

1. query rewrite:
"반차 신청 마감 시간 사내 휴가 정책"
2. retrieval:
doc_hr_v8 half_day chunk를 상위 후보로 찾음
doc_hr_v5는 old version이라 제외하거나 낮은 우선순위로 둠
3. augmentation:
<documents>
<doc id="doc_hr_v8#half_day" updated_at="2026-06-15">
반차는 사용 당일 오전 10시 전까지 신청할 수 있다.
단, 팀 승인 정책이 있는 조직은 전날 18시까지 신청한다.
</doc>
</documents>
4. generation:
"반차는 기본적으로 사용 당일 오전 10시 전까지 신청할 수 있습니다.
다만 팀 승인 정책이 있는 조직은 전날 18시까지 신청해야 합니다.
[doc_hr_v8#half_day]"

이 예제에서 RAG가 추가한 가치는 단순히 “문서를 붙였다”가 아니다.

  • doc_hr_v8처럼 어느 version의 문서를 근거로 삼았는지 남겼다.
  • 오래된 doc_hr_v5를 그대로 넣지 않도록 freshness와 version filter를 적용했다.
  • 답변 문장 끝에 chunk ID를 붙여 provenance를 만들었다.
  • 검색 결과에 반차 정책이 없었다면 “문서를 찾지 못했다”고 거절할 수 있는 경계를 만들었다.

5. Retrieval — 근거 후보를 찾는 단계

섹션 제목: “5. Retrieval — 근거 후보를 찾는 단계”

Retrieval은 “질문과 관련 있는 문서를 찾는다”는 한 문장으로 끝나지만, 실제로는 여러 결정을 포함한다. 깊은 정의는 L12-30 임베딩과 벡터 운영 문서가 맡는다. 이 문서에서는 RAG 조립에 필요한 짧은 역할만 확인한다.

요소RAG에서의 역할여기서 기억할 정도
Chunking긴 문서를 검색 가능한 조각으로 나눈다답변에 필요한 조건과 예외가 같은 chunk에 남아야 한다
Vector storeembedding과 metadata를 함께 저장한다검색 점수뿐 아니라 tenant, ACL, version filter가 중요하다
Dense search의미가 비슷한 문서를 찾는다paraphrase에 강하지만 고유명사·코드·조항 번호를 놓칠 수 있다
BM25단어 일치와 희귀도를 보는 lexical ranking이다정확한 문자열 단서에 강하다
RRF여러 ranking을 안정적으로 합치는 방식이다dense와 BM25 결과를 섞을 때 자주 쓴다
Reranker1차 후보를 query와 함께 다시 읽어 정렬한다recall을 확보한 뒤 precision을 회복한다
Freshness원본 변경이 검색에 반영되는 상태다오래된 chunk가 top-k에 남으면 답변도 오래된다

사용자 질문은 검색 query로 바로 쓰기 어려울 때가 많다. 대화형 질문은 짧고, 생략이 많고, 문서가 쓰는 용어와 다르다.

대화 맥락:
user: "RAG 구조 알려줘"
assistant: "검색, 보강, 생성으로 나뉩니다."
user: "그럼 비용은?"
나쁜 검색어:
"그럼 비용은?"
좋은 검색어:
"RAG 시스템 비용 구성 검색 latency context token vector store 운영 비용"

rewrite의 목표는 멋진 문장을 만드는 것이 아니라 독립적으로 검색 가능한 query를 만드는 것이다. 이전 turn을 통째로 붙이면 noise가 늘 수 있으므로 핵심 entity와 intent만 남긴다.

같은 의도를 여러 표현으로 바꿔 검색한다.

원본: "Python에서 비동기 처리"
검색 1: "Python asyncio 사용법"
검색 2: "Python async await 예제"
검색 3: "Python coroutine 동시성"

Multi-Query는 recall을 올리는 대신 후보가 많아진다. 그래서 보통 reranker나 dedupe와 같이 쓴다.

HyDE(Hypothetical Document Embeddings)는 LLM이 먼저 가상의 답변 문서를 만들고, 그 가상 문서를 embedding해 검색하는 방식이다. 질문보다 답변 형태의 문장이 실제 문서와 더 비슷할 때 도움이 된다.

질문: "RAG 어떻게 해?"
가상 답변: "RAG는 문서를 chunking하고 embedding한 뒤 vector store에서..."
검색: 가상 답변을 embedding해 관련 문서 검색

반례도 기억해야 한다. 사용자가 이미 문서와 같은 용어로 질문했다면 HyDE는 추가 LLM 호출 비용과 latency만 늘릴 수 있다.

복합 질문은 여러 하위 질문으로 나눈다.

원본: "RAG와 fine-tune 중 어떤 게 비용과 최신성에 유리해?"
하위 질문:
1. RAG의 지식 갱신 방식은 무엇인가?
2. fine-tune의 지식 갱신 방식은 무엇인가?
3. 두 방식의 비용 구조는 어떤 항목으로 나뉘는가?

분해는 multi-hop 질문에 좋지만, 단순 FAQ에는 과하다. “분해할수록 좋다”가 아니라 정답이 여러 근거 조각을 필요로 할 때만 쓴다.

RAG 장애를 볼 때 가장 먼저 나눌 질문은 이것이다.

정답 근거가 검색 결과 안에 있었나?
  • 없었다: chunking, embedding 모델, query rewrite, hybrid search, metadata filter, freshness를 의심한다.
  • 있었지만 낮은 순위였다: reranker, context packing, top-k 정책을 의심한다.
  • 있었고 prompt에도 들어갔다: generation faithfulness, prompt 구조, citation gate를 의심한다.

이 분기를 하지 않으면 “모델이 나쁘다”, “vector DB가 나쁘다”, “prompt가 나쁘다”가 한 덩어리로 섞인다.

6. Augmentation — 검색 결과를 답변 가능한 context로 바꾸기

섹션 제목: “6. Augmentation — 검색 결과를 답변 가능한 context로 바꾸기”

Augmentation은 검색 결과를 prompt에 “그냥 붙이는” 단계가 아니다. 모델이 어떤 텍스트를 질문으로, 어떤 텍스트를 근거로, 어떤 텍스트를 지시로 봐야 하는지 구획을 나누는 단계다.

<documents>
<doc id="doc_hr_v8#half_day" source="/hr/leave-policy.md" updated_at="2026-06-15">
반차는 사용 당일 오전 10시 전까지 신청할 수 있다.
단, 팀 승인 정책이 있는 조직은 전날 18시까지 신청한다.
</doc>
<doc id="doc_hr_v7#annual_leave" source="/hr/leave-policy.md" updated_at="2026-03-01">
연차는 사용 1일 전까지 HR 포털에서 신청한다.
</doc>
</documents>
<question>
반차는 언제까지 신청해야 해?
</question>
<instruction>
documents에 근거해서만 답하라.
답변에는 사용한 doc id를 대괄호로 인용하라.
documents에 없는 내용은 추측하지 말고 "문서에서 찾을 수 없습니다"라고 답하라.
</instruction>

XML 자체가 정답은 아니다. Markdown heading, JSON wrapper, message role을 써도 된다. 중요한 것은 사용자 입력, 검색 문서, 시스템 지시, 출력 계약이 섞이지 않는 것이다.

검색 후보를 모두 넣으면 recall은 높아 보이지만 답변 품질은 떨어질 수 있다. 관련 없는 chunk가 많아질수록 모델이 잘못된 근거를 집거나, 중요한 근거가 긴 context 중간에 묻힌다.

안정적인 사고 순서는 다음과 같다.

retrieve: 넓게 후보를 가져온다. 예: top-50 또는 top-100
rerank: 질문에 직접 답하는 후보를 위로 올린다.
dedupe: 같은 문서·같은 문단의 중복 chunk를 줄인다.
pack: 최종 context에는 답변에 필요한 5~7개 정도의 근거만 넣는다.
cite: 각 근거의 doc_id, source, version을 남긴다.

숫자는 절대 규칙이 아니라 토큰 예산을 계산하기 위한 감각이다. 예를 들어 평균 800토큰 chunk를 10개 넣으면 검색 context만 8,000토큰이다. 여기에 system prompt, 대화 history, 사용자 질문, 출력 형식 지시가 붙는다. RAG에서 top-k를 키우는 결정은 검색 품질뿐 아니라 input token, prefill latency, lost-in-the-middle 위험까지 함께 키운다.

p95는 100번 중 느린 쪽 5%에 걸리는 응답 시간을 보는 지표이고, prefill은 모델이 입력 token을 먼저 읽어 내부 상태를 채우는 단계다. 입력 context가 길어질수록 prefill 시간이 늘 수 있다.

작은 비용·latency 예제로 감을 잡아 보자.

질문 1개 처리:
retrieval p95: 120ms
rerank p95: 180ms
최종 context: 7 chunks * 800 tokens = 5,600 input tokens
prompt/history/질문: 1,400 input tokens
예상 답변: 500 output tokens
대략적 병목:
online latency ~= retrieval + rerank + LLM prefill(7,000 input tokens) + decode(500 output tokens)
token 비용 ~= input 7,000 tokens + output 500 tokens
고정비 ~= vector store 저장량 + reindex worker + 평가 trace 저장

이 계산은 vendor 가격표를 외우기 위한 것이 아니다. top-k를 7 -> 14로 올리면 단지 근거가 두 배가 되는 것이 아니라 input token, prefill latency, citation 검증 대상, lost-in-the-middle 위험도 같이 늘어난다는 점을 보는 것이다.

Liu et al.의 “Lost in the Middle” 연구는 긴 context에서 중간에 놓인 정보가 덜 활용될 수 있음을 보여준다. 그래서 RAG prompt는 중요한 근거를 무작위 순서로 붙이지 않는다.

  • 가장 직접적인 근거를 앞쪽 또는 답변 직전의 눈에 띄는 위치에 둔다.
  • 같은 문서의 인접 chunk는 하나의 parent context로 묶어 문맥을 보존한다.
  • 오래된 version과 최신 version이 같이 들어가지 않게 한다.
  • citation ID를 답변 후처리에서 검증할 수 있게 보존한다.

7. Generation — 근거를 답변으로 합성하기

섹션 제목: “7. Generation — 근거를 답변으로 합성하기”

Generation은 LLM이 검색된 문서를 읽고 사용자가 원하는 형식으로 답을 만드는 단계다. 여기서도 RAG는 자동 안전장치가 아니다. 모델은 documents에 없는 내용을 덧붙일 수 있고, 인용처럼 보이는 문자열을 만들어낼 수도 있다.

Faithfulness는 답변 문장이 검색된 근거에 의해 지지되는지를 보는 관점이다. “답이 질문에 친절한가”와 다르다. 답변이 친절해도 근거 밖 사실을 말하면 RAG에서는 실패다.

작은 반례를 보자.

검색 문서:
"반차는 사용 당일 오전 10시 전까지 신청할 수 있다."
질문:
"반차를 취소하려면 언제까지 해야 해?"
나쁜 답변:
"반차 취소도 당일 오전 10시 전까지 가능합니다. [doc_hr_v8]"
왜 실패인가:
문서는 신청 마감만 말한다. 취소 마감은 근거가 없다.
좋은 답변:
"제공된 문서는 반차 신청 마감만 설명하고, 취소 마감은 설명하지 않습니다. [doc_hr_v8]"

이 반례가 RAG의 핵심 경계다. 검색된 문서가 관련 있어 보여도 질문에 필요한 속성을 실제로 담고 있는지는 별도로 확인해야 한다.

Citation은 답변 끝에 링크를 붙이는 UI 기능이 아니라, 운영에서 세 가지 기능을 한다.

  1. 사용자가 답변을 검증할 수 있다.
  2. 회귀 분석 때 어떤 chunk가 오답을 만들었는지 추적할 수 있다.
  3. 권한·version·source 감사 로그를 남길 수 있다.

따라서 citation은 문자열 생성만 믿지 않는 편이 좋다. 답변에 등장한 doc_id가 실제로 이번 retrieval 결과 안에 있었는지, 해당 사용자가 볼 권한이 있는지, 최신 version인지 후처리에서 확인한다.

RAG 제품에서 “모르겠습니다”는 실패가 아니라 안전한 성공일 수 있다. 검색 결과가 없거나, 관련도가 낮거나, 근거가 질문의 핵심 속성을 담고 있지 않으면 모델이 답을 만들지 않도록 해야 한다.

답변 정책:
- documents에 직접 근거가 있으면 답한다.
- 근거가 부분적이면 "문서에서 확인되는 범위"와 "확인되지 않는 범위"를 나눈다.
- 근거가 없으면 추측하지 않고 추가 문서나 담당 부서를 안내한다.

이 정책이 없으면 RAG는 “검색된 문서가 있으니 아무 답이나 해도 되는 시스템”이 된다.

RAG 이름은 계속 늘어나지만, 운영자가 볼 축은 단순하다.

  1. 검색 전에 query를 얼마나 고치는가
  2. 검색 후보를 얼마나 넓게 만들고 얼마나 비싸게 재정렬하는가
  3. 검색 결과가 부족할 때 재검색·거절·도구 호출을 할 것인가
  4. 단일 chunk가 아니라 문서 간 관계까지 봐야 하는가
변형핵심 구조적합한 상황경계
Naive RAGquery embedding → top-k → prompt작은 FAQ, PoC, 명확한 단일 문서 질문query mismatch, reranker 부재, stale data에 약함
Advanced RAGrewrite, hybrid, rerank, context packing많은 production QA의 시작 후보stage가 늘어 latency와 trace가 복잡해짐
Modular RAG검색, 재정렬, 생성, 평가를 교체 가능한 단계로 분리팀·도메인별 검색기와 평가기를 바꿔야 하는 플랫폼형 RAG추상화가 빨리 들어가면 단순 문제도 복잡해짐
Corrective RAG검색 결과를 평가하고 재검색 또는 refusal잘못된 답변 피해가 큰 도메인judge 품질이 낮으면 불필요한 refusal이 늘어남
Self-RAG모델이 검색 필요 여부와 답변 근거를 스스로 점검질문 유형이 다양하고 검색 필요성이 매번 다른 서비스loop 비용과 latency를 제한해야 함
GraphRAGentity, relation, community summary를 검색”전체 전략”, “조직 간 관계”처럼 단일 chunk에 답이 없는 질문색인 비용과 entity 추출 품질 의존이 큼
Agentic RAGagent가 검색, DB, tool을 여러 번 호출multi-hop 조사, 업무 시스템 action이 이어지는 작업permission, tool budget, 재현성 관리가 어려움

운영 기본값은 대개 Advanced RAG까지 작게 쌓는 것이다. 처음부터 GraphRAG나 agentic loop를 붙이면 retrieval 문제인지 orchestration 문제인지 분리하기 어렵다.

1. 질문이 단일 문서·단일 문단에서 답이 나는가?
yes -> Naive 또는 Advanced RAG
no -> 2로
2. 여러 문서의 관계나 요약이 필요한가?
yes -> GraphRAG 또는 hierarchical summary 검토
no -> 3으로
3. 검색 결과가 부족할 때 외부 검색·도구·DB 조회가 필요한가?
yes -> Corrective RAG 또는 Agentic RAG
no -> query decomposition + rerank부터 개선

9. RAG vs Long-context vs Fine-tune vs Tool lookup

섹션 제목: “9. RAG vs Long-context vs Fine-tune vs Tool lookup”

RAG는 모든 LLM 문제의 기본값이 아니다. 지식, 행동, 계산, 권한을 분리해서 본다.

RAG와 대안 선택 기준

RAG

외부 문서에서 근거를 검색해 최신성, 출처, 권한 필터를 운영 로직으로 통제한다.

문서가 자주 바뀌고 답변 근거를 사용자나 감사 로그에 남겨야 할 때

Long-context

관련 자료를 한 호출에 많이 넣고 모델이 직접 읽게 한다.

단발 분석이고 자료 묶음이 context window와 비용 예산 안에 들어갈 때

Fine-tune

새 지식보다 반복되는 형식, 말투, 분류 기준, 도메인 행동을 모델에 맞춘다.

지식 갱신은 느리지만 응답 스타일과 판단 습관을 일관되게 만들 때

Tool lookup

가격, 재고, 권한, 결제 상태처럼 정확한 시스템 값을 API나 DB에서 직접 조회한다.

문서 검색보다 현재 상태 조회가 본질이고, 답이 deterministic해야 할 때
상황먼저 볼 선택지이유
정책·매뉴얼·FAQ가 자주 바뀐다RAG문서 교체와 재색인이 모델 재학습보다 작게 통제된다
답변마다 출처를 보여줘야 한다RAGchunk ID와 source URL을 답변에 연결할 수 있다
사용자의 현재 잔액·재고·권한이 필요하다Tool lookup문서 검색이 아니라 실시간 상태 조회 문제다
말투·JSON 구조·분류 기준이 흔들린다Prompt, structured output, fine-tune지식보다 행동·형식 문제일 가능성이 크다
한 번 분석할 자료가 작고 고정돼 있다Long-context별도 색인과 freshness 파이프라인이 과할 수 있다
corpus가 정리돼 있지 않다Corpus 정비검색할 진실이 없으면 RAG는 오답을 더 그럴듯하게 포장한다
  • 검색 가능한 corpus가 없다: 오래된 문서, 중복 문서, 권한 없는 문서가 섞인 상태라면 모델보다 문서 정비가 먼저다.
  • 답이 실시간 상태다: 계좌 잔액, 재고, feature flag, 결제 상태는 문서 검색보다 API 조회가 맞다.
  • 출력 행동 문제가 본질이다: 답변 형식이 깨지는 문제는 RAG보다 structured output, schema validation, fine-tune 후보가 먼저다.
  • 단발 분석이다: 한 번 읽고 끝날 작은 자료 묶음이면 long-context가 더 단순할 수 있다.
  • latency 예산이 매우 빡빡하다: retrieval, rerank, generation을 모두 붙이면 단계별 지연이 누적된다. 이때는 cache, routing, 축약 context, precomputed answer를 같이 봐야 한다.

10. 평가 — 검색 실패와 생성 실패를 분리하기

섹션 제목: “10. 평가 — 검색 실패와 생성 실패를 분리하기”

RAG 평가는 “답이 좋아 보인다”로 끝나면 안 된다. 최소 네 층으로 나눠 본다.

물어볼 질문대표 지표 또는 관찰
Retrieval정답 근거가 후보 안에 들어왔나?Recall@k, Hit@k, MRR, NDCG
Context후보 중 실제로 prompt에 들어간 근거가 적절한가?Context precision, 중복률, stale chunk 비율
Generation답변 문장이 근거에 의해 지지되는가?Faithfulness, citation validity, refusal correctness
Product사용자가 문제를 해결했나?사용자 피드백, escalation rate, task success, latency, cost

MRRNDCG는 정답 문서가 후보 목록의 몇 번째에 오는지 보는 순위 품질 지표다. 처음에는 공식을 외우기보다 “정답이 후보 안에 있는가”와 “정답이 위쪽에 있는가”를 분리해서 본다고 이해하면 된다.

Gold dataset은 기대 답변, 필수 출처, 실패 사례를 사람이 검토하고 버전별로 관리하는 평가 데이터셋이다.

question: "반차는 언제까지 신청해야 해?"
expected_answer: "기본은 당일 오전 10시 전, 팀 승인 조직은 전날 18시"
required_sources:
- doc_hr_v8#half_day
forbidden_sources:
- doc_hr_v5#half_day

좋은 gold case는 정답 문장만 갖고 있지 않다. 필수 source와 금지 source를 함께 둔다. 그래야 stale data, permission leak, citation hallucination을 잡을 수 있다.

1. 질문, 기대 답변, 필수 source를 가진 gold dataset을 만든다.
2. retrieval만 먼저 실행해 정답 source가 후보 안에 들어오는지 본다.
3. rerank와 context packing 후 prompt에 실제로 들어간 source를 기록한다.
4. generation 결과의 문장과 citation을 대조한다.
5. 실패를 retrieval, context, generation, product issue로 라벨링한다.
6. prompt, chunking, retriever, reranker, corpus 변경 시 같은 set으로 회귀를 본다.

공개 블로그나 도구 문서에서 제시하는 faithfulness threshold를 그대로 복사하지 않는다. 도메인, 답변 형식, 모델, judge 방식에 따라 점수 의미가 달라진다. 팀 기준은 현재 production baseline, 사용자 피해도, 사람 검수 샘플을 기준으로 잡고, 숫자는 “배포 gate”가 아니라 “회귀 감지 신호”로 먼저 다룬다.

처음 기준을 잡을 때는 작은 절차로 충분하다. 실패가 섞인 질문 30~50개를 뽑아 사람이 정답 source 있음, 답변 문장 근거 있음, 권한 위반 없음, 거절해야 할 때 거절함 네 칸으로 라벨링한다. 그다음 현재 시스템의 점수 분포를 baseline으로 저장하고, prompt나 retriever를 바꿀 때 같은 set에서 분포가 나빠지는지 본다. 기준선은 “faithfulness 0.8 이상이면 안전” 같은 보편 규칙이 아니라, 우리 도메인에서 사람이 확인한 샘플과 피해 비용에 붙어 있어야 한다.

Ragas, TruLens, DeepEval 같은 도구는 회귀 탐지에 유용하지만 정답 판정 그 자체는 아니다. 특히 표, 코드, 짧은 숫자 답변, 다국어 답변은 문장 분해와 entailment 판단이 흔들릴 수 있다.

자동 평가는 아래처럼 쓴다.

  • 빠른 회귀 감지: prompt 변경 후 faithfulness 분포가 나빠졌는지 본다.
  • 실패 샘플링: 낮은 점수 사례를 사람 검수 queue로 보낸다.
  • 원인 분리: retrieval metric과 generation metric을 같이 저장한다.

자동 평가만으로 “안전하다”고 결론내리지 않는다. RAG는 출처·권한·최신성이 제품 요구사항이므로 샘플 기반 사람 검수와 audit log가 필요하다.

Silent failure는 HTTP 200, latency 정상, 답변 형식 정상인데 내용이 틀린 상태다. RAG에서는 특히 위험하다. 자연어 답변이 매끄러우면 사용자가 오류를 늦게 발견하기 때문이다.

증상보이는 현상먼저 의심할 지점복구 방향
Stale data옛 정책이나 삭제된 문서를 인용한다freshness pipeline, version filter, reindex lagchanged event, embedding queue, old version cleanup 확인
Permission leak다른 tenant나 권한 밖 문서가 답변에 섞인다metadata pre-filter, namespace, ACL join검색 전 필터 강제, response-stage 필터만 쓰지 않기
Query mismatch사용자의 표현과 문서 표현이 달라 정답 chunk가 빠진다query rewrite, hybrid search, synonym, BM25rewrite와 hybrid를 추가하고 gold dataset recall을 측정
Reranker 부재정답이 후보에는 있지만 context 밖으로 밀린다rerank, top-k, context packingretrieve 후보를 넓히고 rerank 후 최종 context를 줄임
Context stuffing너무 많은 chunk를 넣어 답변이 흐려진다top-k 과다, dedupe 부재, lost-in-middle중복 제거, parent context, 중요한 근거 우선 배치
Citation hallucination답변에 없는 doc id나 무관한 doc id가 붙는다generation prompt, post-validationcitation이 retrieval 결과에 존재하는지 검증
Refusal 누락근거가 없는데 답을 지어낸다instruction 약함, output policy 부재”확인 범위”와 “문서에 없음” 응답을 명시
Over-filtering권한·언어·날짜 필터가 정답까지 지운다품질 필터와 보안 필터 혼합보안 필터는 유지, 품질 필터는 fallback 규칙 분리
Architecture overkill단순 FAQ에 agent loop나 GraphRAG가 붙어 느려진다패턴 선택 과잉단순 RAG baseline으로 돌아가 단계별 품질을 비교

Permission leak과 over-filtering의 차이

섹션 제목: “Permission leak과 over-filtering의 차이”

둘 다 metadata filter에서 생기지만 방향이 반대다.

  • tenant_id, ACL, RBAC(Role-Based Access Control, 역할 기반 접근 제어) 같은 보안 필터는 완화 대상이 아니다. 후보 생성 전에 강제해야 한다.
  • language, doc_type, updated_at 같은 품질 필터는 recall이 너무 낮을 때 완화할 수 있다.

두 필터를 한 덩어리로 묶으면 위험하다. recall을 살리려고 조건을 풀다가 권한을 풀 수 있고, leak을 막으려고 조건을 강하게 하다가 정답 source까지 지울 수 있다.

12. 운영 시나리오 — 환각 답변이 늘었을 때

섹션 제목: “12. 운영 시나리오 — 환각 답변이 늘었을 때”
상황:
사내 정책 RAG 챗봇에서 "답이 이상하다"는 사용자 피드백이 늘었다.
1단계: 검색 결과 확인
최근 실패 질문 50개를 뽑아 retrieval trace를 본다.
정답 source가 top-k 후보 안에 있었는지 확인한다.
trace 예시:
query="반차 취소 마감"
top_candidates=[doc_hr_v8#half_day, doc_hr_v7#annual_leave, doc_hr_v5#half_day]
filtered_out=[doc_hr_private#exec_leave_acl_denied]
packed_context=[doc_hr_v8#half_day]
answer_citations=[doc_hr_v8#half_day]
2단계: 분기
A. 정답 source가 없다
-> chunking, query rewrite, hybrid, freshness, permission filter를 본다.
B. 정답 source는 후보에 있지만 prompt에 없다
-> reranker, dedupe, context packing, top-k 정책을 본다.
C. 정답 source가 prompt에 있는데 답이 틀렸다
-> generation prompt, citation validation, refusal rule을 본다.
3단계: 복구
retrieval 실패면 gold dataset recall을 기준으로 검색 파이프라인을 고친다.
generation 실패면 "근거 밖 내용 금지", citation post-validation, refusal 예시를 보강한다.
corpus 실패면 원본 문서 version, 삭제 문서, 권한 metadata부터 정리한다.
4단계: 회귀 방지
실패 case를 gold dataset에 추가한다.
다음 prompt, chunking, retriever 변경부터 같은 case를 자동 평가한다.

여기서 중요한 점은 “LLM 모델을 바꿔 보자”가 첫 복구가 아니라는 것이다. RAG 품질 문제는 검색, context, 생성, corpus 중 하나의 문제일 수 있다. trace 없이 모델만 바꾸면 원인을 잃는다.

RAG는 LLM에만 있는 특수 마법이 아니라, 시스템에서 자주 보던 패턴의 조합이다.

RAG 구성요소일반 시스템 매핑학습 포인트
RetrievalDB SELECT, search query, cache lookup필요한 근거 후보를 찾는다
Augmentationtemplate rendering, dynamic config injection실행 시점 정보를 입력에 주입한다
Generationresponse synthesis, report rendering여러 근거를 사용자 답변으로 합성한다
Citationprovenance tracking, audit trail결과가 어느 입력에서 왔는지 남긴다
Faithfulness checkcontract test, validation결과가 입력 계약을 위반하지 않는지 본다
Freshnesscache invalidation, CDC(Change Data Capture), materialized view refresh원본 변경이 파생물에 반영됐는지 본다

이 매핑은 비유가 아니라 설계 점검표다. RAG를 만들 때도 “저장소는 무엇인가, invalidation은 어떻게 되는가, 권한 필터는 어디서 걸리는가, 결과 provenance는 남는가”를 묻는다.

  • 사내 문서 챗봇: HR, 보안 정책, 운영 매뉴얼, FAQ
  • 고객 지원: 제품 매뉴얼과 release note 기반 답변
  • 코드 어시스턴트: 사내 코드베이스, ADR, API 문서 검색
  • 법률·의료·금융 보조: 출처와 감사 로그가 필요한 답변
  • 뉴스·리서치 요약: 최근 문서 묶음 기반 요약
  • agent의 knowledge layer: tool 호출 전에 정책·문서 근거를 찾는 단계

엔지니어가 RAG를 운영할 때 특히 중요한 판단은 다음이다.

  • 지식과 행동 분리: 최신 정책·문서는 RAG, 출력 형식·말투는 prompt/structured output/fine-tune 후보로 본다.
  • 검색 품질 우선순위: chunking, hybrid, reranker는 L12-30의 깊은 주제지만 RAG에서는 “정답 source가 prompt에 들어오게 하는 장치”로 본다.
  • 출처 인용 강제: citation은 UI 장식이 아니라 debugging과 audit의 키다.
  • 권한 필터 위치: response 직전 마스킹이 아니라 retrieval 후보 생성 전에 적용한다.
  • 회귀 검증: 문서 추가, prompt 변경, embedding 모델 변경, chunking 변경마다 gold dataset을 다시 돌린다.
  • 다국어와 고유명사: 한국어 query, 영어 문서, 코드 식별자, 법령 번호가 섞이면 dense만 믿지 말고 hybrid와 rerank를 검토한다.
개념 A개념 B차이점
RAGSearch UI검색 결과 목록을 보여주는 것이 아니라 답변 생성을 위해 근거를 주입한다
RetrievalGeneration근거 후보를 찾는 단계 vs 근거를 답변으로 합성하는 단계
Context recallFaithfulness필요한 근거가 context에 들어왔는가 vs 답변이 그 근거에 묶였는가
CitationFaithfulness출처 ID가 붙었는가 vs 그 문장이 실제 출처로 지지되는가
Query rewritingDecomposition검색어를 독립적으로 고치는 것 vs 복합 질문을 하위 질문으로 나누는 것
Multi-QueryHyDE여러 query 표현을 검색 vs 가상 답변을 만들어 검색
Semantic searchHybrid search의미 벡터만 사용 vs dense와 BM25 같은 lexical ranking을 함께 사용
RerankerRetriever후보를 처음 찾는 모델 vs 후보를 다시 읽고 순서를 고치는 모델
RAGLong-context필요한 근거를 검색해 넣음 vs 자료를 한 번에 많이 넣음
RAGFine-tune외부 지식을 조회함 vs 모델 행동·형식·습관을 맞춤
GraphRAGVector RAGentity·관계·요약 그래프 사용 vs chunk embedding 중심 검색
RAGTool lookup문서 근거 기반 답변 vs 시스템의 현재 상태를 직접 조회

RAG 운영 복습 체크리스트

  • RAG를 retrieval, augmentation, generation의 세 단계로 설명할 수 있다.
  • 고정 모델 지식과 외부 검색 지식의 차이를 최신성, 출처, 권한 관점으로 말할 수 있다.
  • 정답 근거가 검색 결과에 없을 때와 prompt에 있는데 답변이 틀릴 때의 복구 방향을 분리할 수 있다.
  • Query rewriting, Multi-Query, HyDE, Decomposition을 query mismatch 유형에 맞게 선택할 수 있다.
  • Chunking, vector store, BM25, RRF, reranker, freshness의 깊은 정의는 L12-30에 있고, RAG에서는 조립 역할만 짧게 설명할 수 있다.
  • RAG, long-context, fine-tune, tool lookup의 선택 기준을 지식 갱신, 출처, 행동 형식, 실시간 상태 조회로 나눌 수 있다.
  • Permission leak, stale data, citation hallucination, context stuffing 같은 silent failure를 식별할 수 있다.
  • Gold dataset에 expected answer뿐 아니라 required source와 forbidden source를 넣어야 하는 이유를 설명할 수 있다.
  • Query transform: HyDE, Multi-Query, Decomposition, Step-back prompting, RAG-Fusion
  • Retrieval 조립: semantic, hybrid, BM25, RRF, ColBERT, parent-child, auto-merging
  • Architecture variants: Naive RAG, Advanced RAG, Modular RAG, Corrective RAG, Self-RAG, GraphRAG, Agentic RAG
  • Context 구성: context packing, dedupe, citation validation, lost-in-the-middle
  • 평가: Recall@k, MRR, NDCG, faithfulness, answer relevance, context precision, context recall
  • 운영 도구: LangChain, LlamaIndex, Haystack, RAGAS, TruLens, DeepEval
  • 심화 패턴: RAPTOR, LightRAG, FLARE, RA-DIT, multimodal RAG
  • 작은 markdown 문서 20~50개로 RAG를 만든다. 처음에는 chunking, embedding, vector search, prompt 주입만 구현한다.
  • 질문 20개를 만들고, 각 질문마다 expected answer와 required source를 기록한다.
  • 검색 결과에 정답 source가 들어왔는지와 답변이 그 source를 인용했는지를 따로 기록한다.
  • 같은 gold dataset으로 query rewriting on/off를 비교한다.
  • 후속 질문 10개를 만들어 “그럼 비용은?”, “예외는?” 같은 생략형 query가 독립 검색어로 바뀌는지 본다.
  • Multi-Query를 켰을 때 recall은 오르지만 noise가 늘어나는지 확인하고 reranker 전후를 비교한다.
  • 고유명사, 에러 코드, 법령 번호, 함수명이 들어간 질문을 따로 만든다.
  • dense 단독과 BM25+dense hybrid를 비교한다.
  • retrieve top-50 또는 top-100 후 rerank top-5~10으로 최종 context를 만들고, 정답 source 순위가 바뀌는지 본다.
  • 검색 문서에는 “신청 마감”만 있고 질문은 “취소 마감”인 반례를 만든다.
  • prompt에 “근거 없으면 모른다”가 있을 때와 없을 때 답변을 비교한다.
  • 답변의 citation ID가 실제 retrieval 결과 안에 있는지 후처리로 검증한다.
  • 같은 정책의 old version과 new version을 동시에 넣고, version filter가 없을 때 어떤 답이 나오는지 본다.
  • tenant가 다른 문서를 일부러 섞고, retrieval pre-filter가 없으면 leak이 생기는지 확인한다.
  • 품질 필터(language, doc_type)와 보안 필터(tenant, ACL)를 코드에서 분리한다.
  • 검색 결과에 정답 source가 없다면 prompt보다 retrieval을 본다.
  • 정답 source가 후보에는 있는데 prompt에 없다면 rerank와 context packing을 본다.
  • 정답 source가 prompt에 있는데 답이 틀리면 generation prompt, refusal, citation validation을 본다.
  • 특정 문서만 계속 틀리면 원본 문서 품질, chunk 경계, version metadata를 본다.
  • 작은 FAQ인데 latency가 과하면 GraphRAG, agentic loop, 과한 Multi-Query를 줄인다.
  1. RAG는 고정 모델 지식만 믿지 않고 외부 근거를 검색해 context에 주입한 뒤 답을 생성하는 패턴이다.
  2. 핵심 철학은 지식을 모델 밖에 두고 provenance, freshness, permission을 운영 로직으로 통제하는 것이다.
  3. RAG 품질 문제는 retrieval, augmentation, generation, corpus 문제로 나눠야 복구할 수 있다.
  4. RAG는 long-context, fine-tune, tool lookup과 경쟁하는 선택지이며, 지식 갱신·출처·권한이 필요할 때 특히 강하다.
  5. 좋은 RAG 평가는 expected answer뿐 아니라 required source, forbidden source, citation validity, refusal correctness를 함께 본다.

최종 수정: 2026-07-09