Ch.12
RAG: 검색으로 환각 줄이기
RAG 한눈에
Closed-book은 암기 시험, RAG는 교과서 찾아보고 답하는 오픈북과 비슷합니다.
같은 질문 '환불 정책이 뭐야?' 에 Closed-book LLM 은 학습 기억만으로 답하고, RAG 는 문서 저장소에서 임베딩·유사도·Top-k 로 근거 청크를 찾아 프롬프트에 넣은 뒤 생성합니다.
Closed-book: 기억만 · RAG: 검색 후 생성
Closed-book
외부 검색 없음
RAG
Top-k 선택
유사도 상위 k개 청크
Closed-book외부 문서 없이 LLM 파라미터 기억만으로 답하면 환각·구식 정보 위험이 큽니다.
RAG저장소 → 임베딩 → Top-k 검색 → 프롬프트 증강 → 생성 순으로 근거를 붙입니다.
한 질문이 어떻게 처리되나
- 사용자 질문이 들어옵니다. 목표는 최신·사내 문서에 근거한 답입니다.
- 질문·문서 청크를 임베딩해 같은 벡터 공간에서 유사도를 잴 수 있게 합니다.
- Closed-book 은 검색 없이 생성합니다. RAG 는 Top-k 로 관련 청크를 고릅니다.
- 고른 청크를 프롬프트 템플릿에 넣고 Augment 합니다. 컨텍스트 예산을 넘지 않게 조절합니다.
- LLM이 Generate 합니다. 출처·유사도·k 를 로그로 남기며 환각을 모니터링합니다.
회사에서 사내 규정 챗봇을 쓴다고 가정해 보세요. 직원이 「올해 연차는 며칠까지 쌓이나요?」라고 물었는데, 모델이 작년에 흔히 보던 일반적인 답을 그럴듯하게 말해 버리면 곧바로 신뢰가 무너집니다. 문장은 매끄러운데 근거가 없거나 낡았을 때 우리는 환각(Hallucination) 이라고 부릅니다. 쉽게 말하면, AI가 출처 없이 그럴듯하게 말하는 상황입니다.
RAG(검색 증강 생성) 는 이런 문제를 오픈북 방식으로 풉니다. 답하기 전에 회사 문서에서 관련 페이지를 찾아 질문지에 붙인 뒤 쓰게 하는 것입니다. LLM만 쓰는 Closed-book(클로즈드북) 은 학습 때 본 기억만으로 답하는 암기 시험에 가깝고, 학습이 끝난 뒤 새로 생긴 PDF·뉴스·사내 DB를 항상 정확히 알기 어렵습니다. RAG는 검색(Retrieve) → 빈칸 채우기(Augment) → 답 쓰기(Generate) 순으로 동작합니다.
실무에서 자주 만나는 말만 짚으면, 긴 문서는 청크(한 장) 로 자르고 임베딩으로 뜻을 숫자 좌표에 옮깁니다. 벡터 DB는 비슷한 글을 빨리 찾는 색인이고, Top-k는 관련도 위에서 k개만 고르는 것입니다. cos(코사인) 은 두 글이 방향이 비슷한지 보는 점수이고, ctx는 모델이 한 번에 읽을 수 있는 최대 길이입니다. 프롬프트는 지시문+질문 전체, 토큰은 대략 단어·음절 크기의 글자 묶음입니다. budget = ctx−prompt−query 는 시험지에서 문제 설명을 뺀 뒤 남은 칸이라고 기억하면 됩니다. 이 장은 위 개념을 비유와 숫자 예시로 이어서 읽습니다.
수식, 이렇게 읽으면 됩니다 (RAG)
1. 코사인 유사도 + Top-k — 검색의 심장
RAG 검색의 핵심은, 사용자 질문 q와 문서 조각 c의 의미 방향이 얼마나 비슷한지 숫자로 재는 것입니다. 그 점수가 코사인 유사도이고, 식은 다음과 같습니다.
는 질문 임베딩, 는 청크 임베딩입니다. 값이 클수록 주제가 비슷할 가능성이 높고(보통 0~1 근처로 읽습니다), 그중 Top- 로 상위 개만 LLM에 넘깁니다. k=5 이면 5개 청크만 씁니다.
유튜브가 제목·설명을 좌표로 찍어 「다음에 볼 영상」을 고르는 것과 비슷하게, RAG도 의미 좌표로 가장 가까운 페이지를 찾습니다. 청크 점수가 0.92, 0.81, 0.55, 0.30, 0.12 일 때 Top-k=3 이면 앞의 세 개만 사용합니다. 「해외 출장 비용」 질문에는 「식대·교통비」 문단은 cos가 높고, 「사내 동호회」 문단은 낮게 나옵니다. 기억할 순서는 방향(각도) 비교 → 상위 k → 근거 붙이기 입니다.
2. 청킹(Chunking) — 긴 글을 ‘한 입 크기’로
PDF·위키를 통째로 넣지 못하므로 청크라는 한 입 크기 조각으로 잘라 둡니다. 1000쪽 요리 백과사전을 레시피 카드로 나누듯, 「라면 국물」 질문에는 면·국물 카드만 꺼냅니다.
실무에서는 청크 크기(예: 200 토큰)와 오버랩(예: 40 토큰, 앞뒤 겹치기)을 조절합니다. 「…환불은 구매 후 7일 이내…」가 경계에서 잘리면, 오버랩이 없을 때 7일 조건이 다음 청크로 밀려 검색이 빗나갈 수 있습니다. 반대로 20토큰처럼 너무 작으면 문맥이 부족하고, 800토큰처럼 크면 Top- 한 장이 예산을 다 씁니다. 적당한 크기 + 오버랩이 검색 품질의 출발점입니다.
3. 컨텍스트 예산 — 시험지 한 장에 다 넣지 않기
모델이 한 번에 읽을 수 있는 ctx 는 시험지 한 장과 같습니다. 먼저 지시문(prompt) 과 질문(query) 이 자리를 쓰고, 남은 칸에만 청크를 붙입니다. 남은 분량이 청크 예산이며, 식으로는 다음과 같습니다.
ctx=4096, prompt=512, query=200 이면 budget = 4096-512-200= 3384 입니다. 청크 한 장이 200 토큰이면 대략 1200 // 200= 6장까지 들어갑니다(// 는 정수 나눗셈). ctx=8192, prompt=1024, query=256 이면 청크용은 6912 토큰입니다. 뺄셈으로 예산을 구하고, // 로 최대 장 수를 구하는 것은 같은 흐름의 앞뒤 단계입니다.
4. 프롬프트 템플릿 — 빈칸에 근거 끼우기
LLM에 보내는 글을 고정 틀(템플릿) 로 두고, 검색으로 고른 Top- 결과만 `{retrieved_chunks}` 같은 빈칸에 채웁니다. 학교 서술형 답안지처럼 「아래 참고문만 보고 답하시오」 + 붙임칸 + 문제 구조입니다.
```
Context:
{retrieved_chunks}
Question: {user_query}
Answer:
```
실제로 채우면 `[청크1] 환불은 구매 후 7일 이내…` 같은 근거만 들어가고, 질문은 `해외 배송도 환불되나요?` 처럼 사용자 문장 그대로 넣습니다. 「컨텍스트 밖 추측 금지」 지시를 함께 넣으면 환각을 줄이기 쉽습니다. 템플릿은 한마디로 Retrieve 결과를 Augment 하는 상자입니다.
RAG: 검색으로 근거 있는 답 만들기
1. 오픈북 vs 클로즈드북: RAG의 탄생
LLM만 쓰는 방식을 Closed-book(클로즈드북) 이라고 부릅니다. 교과서를 들고 오지 못하는 암기 시험과 같아서, 모델은 학습 때 본 기억만으로 답합니다. 반면 RAG(검색 증강 생성) 는 오픈북 시험에 가깝습니다. 답하기 전에 도서관(문서 저장소) 에서 관련 페이지 한 장(청크) 을 찾아 질문지에 붙입니다.
실제 흐름은 검색(Retrieve) → 빈칸 채우기(Augment) → 답 쓰기(Generate) 입니다. 먼저 질문에 맞는 청크를 고르고, 그다음 프롬프트의 `{context}` 자리에 붙인 뒤, 마지막에 LLM이 문장을 만듭니다.
직원이 「올해 연차 규정이 어떻게 바뀌었어?」라고 물었다고 해 보세요. Closed-book은 작년에 흔하던 상식으로 그럴듯하게 말할 수 있고, RAG는 올해 인사 규정 PDF 7페이지를 찾아 그 문장을 근거로 답합니다. 차이는 「말이 예쁜가」가 아니라 「어느 페이지를 봤는가」 입니다.
2. 임베딩(Embedding): 글자를 컴퓨터의 좌표로
컴퓨터는 「환불」「반품」 같은 뜻을 그대로 비교하기 어렵습니다. 그래서 임베딩으로 문장을 숫자 목록(벡터) 에 옮깁니다. 비슷한 주제는 좌표 공간에서 가깝게, 다른 주제는 멀게 놓이도록 학습합니다. 마치 지도에서 「카페」들이 한곳에 모이는 것과 비슷합니다.
검색할 때는 코사인 유사도(cos) 를 씁니다. 두 문장 벡터가 같은 방향을 가리키는지(각도) 를 보는 점수로, 직선 거리보다 「주제가 겹치는가」에 가깝습니다. 「환불」과 「반품·결제 취소」는 cos가 높게 나오고, 「점심 메뉴」는 낮게 나옵니다. RAG는 이 점수로 질문과 가장 관련 있는 청크부터 골라 냅니다.
3. 청킹(Chunking)과 Top- 검색
회사 규정 PDF가 500페이지라도, 모델 프롬프트에 통째로 넣을 수는 없습니다. 청킹은 긴 문서를 한 입 크기(예: 200토큰) 로 잘라 조각(청크) 으로 보관하는 일입니다. 잘게 자를수록 찾을 단위는 많아지지만, 한 장이 너무 짧으면 문맥이 끊길 수 있습니다.
질문이 오면 임베딩·cos로 비슷한 청크를 순위 매기고, Top- 로 상위 k장만 LLM에 넘깁니다. k=3이면 가장 관련 있는 3장만 붙입니다. 수만 장의 청크를 빠르게 찾기 위해 벡터 DB를 씁니다. 도서관 카드 색인처럼, 전체 PDF를 매번 읽지 않고 비슷한 조각만 꺼냅니다.
k를 너무 크게 잡으면 엉뚱한 문단이 섞이고 비용도 늘어납니다. 그래서 「많이 넣을수록 좋다」가 아니라 적당한 k가 중요합니다.
4. 컨텍스트 예산과 프롬프트 템플릿
모델은 한 번에 읽을 수 있는 길이에 한도(ctx, 컨텍스트 한도) 가 있습니다. A4 시험지 한 장이라고 생각하면 됩니다. 먼저 지시문(prompt) 과 사용자 질문(query) 이 자리를 쓰고, 남은 칸에만 검색한 청크를 붙입니다. 이 남은 분량이 청크 예산이며, budget = ctx−prompt−query 로 계산합니다.
붙일 때는 프롬프트 템플릿이라는 고정 양식을 씁니다. `{context}` 자리에 검색 결과를, `{question}` 자리에 사용자 질문을 넣습니다. 「아래 문서만 보고 답하라」는 문장도 함께 넣어, 모델이 빈칸 밖을 추측하지 않게 합니다.
숫자로 보면, ctx=4096, 지시문=512, 질문=200이면 예산은 3384입니다. 청크 한 장이 200 토큰이면 대략 3384 // 200 ≈ 16장까지 들어갑니다. 뺄셈(예산) 과 // (최대 장 수) 는 같은 이야기의 앞뒤 단계입니다.
왜 중요한지
1. 왜 RAG가 필요한가 — 환각을 ‘그럴듯한 추측’에서 ‘근거 있는 답’으로
LLM은 문장을 잘 이어 붙이는 능력이 강합니다. 그래서 모르는 사실을 물어도 말투만 자신 있게 답하는 경우가 많습니다. 특히 사내 규정, 제품 매뉴얼, 어제 공시된 뉴스처럼 학습 데이터에 없거나 자주 바뀌는 정보에서는, 사용자 입장에서는 틀린 답이 더 위험합니다. 틀렸다는 걸 알기 전에 이미 결재·고객 응대에 쓰였을 수 있기 때문입니다.
RAG는 답을 쓰기 전에 관련 문서를 검색해 프롬프트에 넣습니다. 그래서 「인사규정 PDF 12쪽, 3문단을 참고했습니다」처럼 출처를 따라갈 수 있고, 틀렸을 때 문서를 고치거나 검색을 조정할 수 있습니다. 환각을 0으로 만든다기보다, 검증 가능한 답에 가깝게 만드는 접근이라고 보면 됩니다.
예시: 「해외 배송도 7일 환불인가요?」 — Closed-book은 국내 기준을 일반화할 수 있고, RAG는 배송 조항이 있는 청크를 찾아 조건부로 답합니다.
2. 재학습 없이도 ‘지식을 오늘 날짜로’ 맞추기
새 규정 PDF가 월요일 아침에 올라왔다고 해도, 7B 모델 전체를 다시 학습시키는 것은 시간·GPU·검증 비용이 큽니다. 현실적인 선택은 문서 저장소만 갱신하는 것입니다. RAG에서는 PDF를 청크로 자르고 → 임베딩 → 벡터 DB에 넣는 작업만으로, 같은 LLM이 새 규정을 답에 반영할 수 있습니다.
비유: 교과서 개정판이 나왔을 때, 학생 전원의 머리를 새로 심는 대신 도서관 책장만 바꿔 끼우는 것과 비슷합니다. 모델 가중치는 그대로 두고, 참고하는 페이지만 최신으로 유지합니다.
예시: 「2026년 복지 제도」 FAQ — 재학습
②보다 청크·DB 갱신
②가 먼저인 이유가 여기 있습니다(연습문제 시나리오와도 연결됩니다).
3. ‘똑똑한 LLM’도 잘못된 페이지를 주면 틀린다 — 검색이 반쪽
생성 모델이 아무리 좋아도 검색이 빗나가면 답도 틀립니다. 「반품」 질문에 「점심 식단」 청크가 들어가면 문장은 매끄러운데 업무적으로는 실패입니다.
그래서 답이 이상할 때는 temperature(말투 무작위성)만 건드리기보다, Top-k(몇 장 가져올지), 청크 크기, 오버랩(문장이 잘리지 않게 겹치기), 재순위(순서 다시 매기기)를 먼저 봅니다. recall@k는 「정답 문서가 상위 k 안에 있었나?」를 재는 검색 성적표로, 답변이 예쁜지와는 별도로 봐야 합니다.
정리하면, RAG는 ① 근거
② 최신성
③ 검색 품질을 한 파이프라인으로 묶어 운영하는 방법입니다.
어떻게 쓰이는지
1단계: 지식 도서관 짓기 (수집·청킹)
RAG 제품의 첫 작업은 답의 근거가 될 문서를 모으는 것입니다. 회사 규정·매뉴얼·FAQ·공지를 PDF나 위키에서 가져와 청크로 자릅니다. 이때 어느 파일·몇 페이지에서 왔는지 메타데이터를 남겨 두면, 나중에 「출처 보여 주세요」에 바로 대응할 수 있습니다.
각 청크는 임베딩해 벡터 DB에 쌓습니다. 도서관에 카드 색인을 만드는 것과 같아서, 이후에는 500페이지 PDF 전체를 매번 읽지 않고 관련 조각만 꺼낼 수 있습니다.
2단계: 찰떡 문서 찾기 (검색, Retrieve)
사용자 질문이 오면 같은 방식으로 임베딩하고, cos(q,c) 가 큰 순으로 Top- 청크를 고릅니다. k=5면 다섯 장의 근거만 다음 단계로 넘깁니다.
점수만으로 부족하면 재순위(re-rank) 로 순서를 다시 매기거나 겹치는 청크를 합칩니다. 「검색은 되는데 답이 이상하다」는 대부분 k·청크 크기·오버랩 설정 문제이므로, 생성 옵션보다 이 단계를 먼저 점검합니다.
3단계: 질문지 조립하기 (증강, Augment)
고른 청크를 한 번에 다 넣을 수는 없습니다. 모델 한도 ctx에서 지시문(prompt) 과 질문(query) 을 뺀 컨텍스트 예산 안에서만 이어 붙입니다. `문맥: {context}\n질문: {question}` 같은 템플릿의 `{context}` 자리에 검색 결과만 넣고, 「아래 문서만 보고 답하라」는 문장을 함께 넣습니다.
이 과정이 증강(Augment) 입니다. LLM이 빈 머리로 추측하지 않고 붙여 준 페이지를 보도록 시험지를 완성하는 단계입니다.
4단계: 정답 쓰기 (생성, Generate) — 네 단계를 한 흐름으로
완성된 프롬프트를 LLM에 넣으면 답 문장이 나옵니다. 좋은 서비스는 답과 함께 출처 링크·페이지·청크 ID를 보여 줍니다. 운영에서는 k, 청크 크기, 예산, 유사도 점수를 로그로 남겨, 환각·구식 답이 늘 때 검색 설정을 조정합니다.
전체를 이어 보면, ① 수집·청킹으로 문서를 피자 조각처럼 잘라 보관하고(Text Splitter, Vector DB), ② 검색에서 책갈피처럼 cos·Top-로 페이지를 찾으며, ③ 증강에서 오픈북 참고문을 템플릿·예산 안에 붙이고, ④ 생성에서 LLM이 참고문을 보며 답을 씁니다. 한 문장으로는 도서관 만들기 → 페이지 찾기 → 시험지 붙이기 → 답 쓰기 — 이것이 RAG가 실제 제품에서 움직이는 모습입니다.
요약
이 장을 한 문장으로 묶으면, RAG는 도서관에서 관련 페이지를 찾아 질문지에 붙인 뒤 답을 쓰는 오픈북입니다. 순서는 검색(Retrieve) → 빈칸 채우기(Augment) → 답 쓰기(Generate) 로 기억하면 됩니다.
먼저 사용자 질문과 비슷한 문서 조각(청크) 을 고릅니다. 이때 cos(q,c) 는 쉬운 말로 「질문 q와 조각 c의 뜻이 같은 방향을 가리키는지」를 재는 점수이고, 점수가 높은 것부터 Top- 개만 남깁니다. 그다음 프롬프트 템플릿의 `{context}` 자리에 붙이는데, 모델이 한 번에 읽을 수 있는 ctx에서 지시문(prompt) 과 질문(query) 을 뺀 남은 칸이 예산입니다. 식으로는 budget = ctx−prompt−query 이고, 청크 한 장이 200 토큰이면 대략 budget // chunk_size 장까지 들어갑니다.
예를 들어 직원이 「환불 정책이 뭐야?」라고 물으면, cos로 규정 PDF에서 관련 3장만 골라 프롬프트에 넣습니다. 모델 한도가 ctx=4096이고 지시문 512·질문 200을 쓰면, 512+200을 뺀 남은 칸에만 근거 문단을 붙입니다. 그래서 「전부 다 넣기」가 아니라 남는 만큼만 넣는다고 보면 됩니다.
한 번 검색으로 답이 부족한 복잡한 질문(여러 문서를 이어 읽어야 하는 경우)은 멀티홉(검색을 여러 번 이어 붙이기)이나 에이전트(스스로 무엇을 더 찾을지 정하기)로 확장하는 쪽으로 이어집니다.
문제 풀이를 위한 설명
연습 문제를 풀 때는 먼저 「암기 시험(Closed-book) vs 오픈북(RAG)」 을 떠올리면 됩니다. Closed-book은 교과서 없이 암기만 하므로 검색 단계가 없고, RAG는 도서관에서 페이지를 찾아 cos(q,c), Top-, 예산, 템플릿으로 질문지를 채운 뒤 답합니다.
파이프라인은 Retrieve(문서 찾기) → Augment(질문지에 붙이기) → Generate(답 쓰기) 입니다. 숫자 문제에서는 budget = ctx−prompt−query 로 남는 칸을 구하고, budget // 청크크기 로 최대 몇 장 들어가는지 봅니다. temperature는 답 다양성이지 검색 품질과는 별개입니다.
자주 나오는 계산: ctx=4096, prompt=512, query=200 → 예산 3384 · Top-=5 → 청크 5개 · budget=1200, 크기=200 → 1200 // 200= 6. cos는 「반품」↔「환불 규정」은 방향이 가깝고, 「점심 메뉴」는 멀다고 읽으면 됩니다.
아래는 문제 은행과 같은 형태의 예시입니다.
예시 (개념형 · concept)
「RAG 목표에 가장 가까운 것?
① 가중치만
② 외부 문서 검색→프롬프트 증강→생성
③ 픽셀 분할
④ LR=0」
→ 정답 2 (②만 Retrieve·Augment 포함)
예시 (판별형 · ox)
「RAG는 임베딩 검색으로 청크를 고른다。」→ 1
예시 (판별형 · ox)
「Closed-book이 Top-k로 PDF를 검색한다。」→ 0 (검색 단계 없음)
세션에서는 컨텍스트 예산(vote)·Top-k(vote)·청크 개수(aggregate/config) 같은 숫자형이 자주 나옵니다. 공통 패턴은 「ctx에서 prompt·query를 빼고, 남은 예산을 청크 크기로 //」입니다.
예시 (컨텍스트 예산 · vote) — 한도 4096, 프롬프트 512, 쿼리 200 → 청크 예산? → 4096-512-200= 3384
예시 (Top-k · vote) — Top-k 5이면 고르는 청크 수는? → 5 (k 값 그대로)
예시 (청크 개수 · aggregate) — 예산 1200, 청크 크기 200 → 1200 // 200= 6
예시 (나눗셈 · config) — 1400 // 200 에 가까운 정수는? → 7
예시 (시나리오 · scenario)
「사내 규정 QA에서 최신 PDF 반영이 급하다. 먼저 할 일은?
① LLM 전체 재학습
② 문서 청킹·벡터 DB 갱신
③ softmax 제거」
→ 정답 2
예시 (시나리오 · scenario)
「검색은 되는데 답이 엉뚱하다. 먼저 볼 것은?
① temperature만 0
② Top-k·청크 크기·재순위
③ GPU 드라이버」
→ 정답 2
예시 (개념형 · concept)
「Top-k가 너무 크면 흔한 부작용은?
① 검색 불가
② 노이즈·비용 증가
③ 임베딩 차원 0」
→ 정답 2
예시 (개념형 · concept)
「임베딩에 가장 가까운 설명은?
① 옵티마이저 이름
② 텍스트를 벡터로 바꿔 유사도 검색
③ 배치 정규화만」
→ 정답 2
예시 (판별형 · ox)
「RAG에서 프롬프트 템플릿은 `{context}`·`{question}` 자리에 검색 결과를 넣는 틀이다。」
→ 정답 1
예시 (판별형 · ox)
「코사인 유사도가 항상 크면 두 벡터의 유클리드 거리도 항상 가깝다(교육용 단순화).」
→ cos는 방향만 보므로 정답 0
예시 (파이프라인 · ensemble)
「Top-k 2, 청크당 요약 4문장이면 총 문장 수? ()」
→ 8
예시 (컨텍스트 예산 · vote)
「한도 8192, 프롬프트 1024, 쿼리 256 → 청크 예산?」
→ 6912
예시 (청크 개수 · config)
「예산 2400, 청크 크기 200 → 2400 // 200= 12」