RAG 심화 (Retrieval-Augmented Generation)
난이도: 중급
선수 지식: 대규모 언어 모델, k-NN — 벡터 유사도 개념
관련 문서: 대규모 언어 모델 | 차원 축소 | 랭킹 지표
핵심 요약: RAG는 답하기 전에 관련 문서를 찾아 프롬프트에 넣어주는 방식이다. 모델을 재학습하지 않고도 최신 정보와 사내 문서를 반영할 수 있고, 출처를 제시할 수 있어 환각이 줄어든다. 다만 검색이 틀리면 답도 틀린다 — RAG 프로젝트가 실패하는 원인의 대부분은 생성 모델이 아니라 검색 단계에 있다.
초보자를 위한 핵심 용어
섹션 제목: “초보자를 위한 핵심 용어”- RAG(Retrieval-Augmented Generation): 검색으로 근거를 찾아 프롬프트에 넣은 뒤 생성하게 하는 구조.
- 청킹(Chunking): 긴 문서를 검색 단위로 잘게 나누는 것. 너무 크면 잡음이 섞이고 너무 작으면 맥락이 끊긴다.
- 임베딩(Embedding): 텍스트를 의미를 담은 숫자 벡터로 바꾼 것. 의미가 비슷하면 벡터도 가깝다.
- 벡터 DB(Vector Database): 임베딩을 저장하고 가까운 것을 빠르게 찾아주는 저장소.
- 재순위화(Reranking): 1차로 넉넉히 검색한 뒤, 더 정확한 모델로 순서를 다시 매기는 2단계 검색.
LLM에는 두 가지 근본적 한계가 있다.
- 학습 시점 이후의 사실을 모른다 — 어제 바뀐 사내 정책을 알 리가 없다
- 모르는 것도 그럴듯하게 지어낸다(환각)
파인튜닝으로 지식을 밀어넣는 방법도 있지만, 문서가 바뀔 때마다 다시 학습해야 하고 비싸며 출처를 제시할 수 없다. RAG는 다른 접근을 택한다 — 모델은 그대로 두고, 답할 때마다 근거를 찾아서 함께 준다.
비유: 오픈북 시험이다. 학생(LLM)에게 모든 것을 외우게 하는 대신, 시험장에 교재를 들고 들어가게 한다. 다만 조건이 있다 — 시험 시간이 짧아 교재 전체를 읽을 수는 없으므로, 질문에 맞는 페이지를 빠르게 찾아 펼쳐주는 조교가 필요하다. 그 조교가 검색 단계이고, 조교가 엉뚱한 페이지를 펼치면 아무리 똑똑한 학생도 틀린 답을 쓴다.
탄생 배경
섹션 제목: “탄생 배경”RAG라는 이름은 Lewis et al.(2020)의 논문 “Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks”에서 왔다. 당시 목표는 지금과 조금 달랐다 — 파라미터에 지식을 다 담기 어려우니 외부 지식 저장소를 붙이자는 연구였다.
이 아이디어가 폭발적으로 쓰이게 된 계기는 2022년 ChatGPT 이후였다. 기업들이 LLM을 사내에 도입하려 하자 곧바로 세 가지 벽에 부딪혔다.
- 사내 문서를 모른다
- 지어낸 답을 걸러낼 방법이 없다
- 파인튜닝은 비싸고, 문서가 바뀔 때마다 다시 해야 한다
RAG는 이 셋을 한꺼번에 우회했다. 모델을 건드리지 않고 문서만 갱신하면 되기 때문이다. 그래서 2023년 이후 사내 LLM 도입의 사실상 기본 아키텍처가 되었다.
핵심 개념
섹션 제목: “핵심 개념”1. 전체 흐름
섹션 제목: “1. 전체 흐름”RAG는 준비 단계와 질의 단계로 나뉜다.
준비(오프라인, 문서가 바뀔 때만)
- 문서를 청킹으로 나눈다
- 각 조각을 임베딩으로 변환한다
- 벡터 DB에 저장한다
질의(온라인, 요청마다)
- 질문을 임베딩으로 변환한다
- 가까운 조각 개를 검색한다
- (선택) 재순위화로 순서를 다듬는다
- 검색된 조각 + 질문을 프롬프트로 만들어 생성한다
2. 청킹 — 가장 과소평가되는 단계
섹션 제목: “2. 청킹 — 가장 과소평가되는 단계”청크 크기가 RAG 성능을 크게 좌우하는데도 자주 대충 정해진다.
| 청크 크기 | 장점 | 단점 |
|---|---|---|
| 작음 (100~200 토큰) | 검색이 정확 | 맥락이 끊긴다 (“그것은”이 뭔지 모름) |
| 중간 (300~600 토큰) | 대체로 무난 | — |
| 큼 (1000+ 토큰) | 맥락 보존 | 잡음이 섞이고 컨텍스트 비용 증가 |
실무 기법들:
- 겹침(overlap): 조각 사이를 10~20% 겹치게 잘라 경계에서 잘린 문장을 구제한다
- 구조 기반 분할: 글자 수가 아니라 제목·문단 단위로 자른다. 대체로 더 낫다
- 부모 문서 검색: 작은 조각으로 검색하되, 모델에게는 그 조각이 속한 큰 문단을 준다
3. 검색 — 의미 검색만으로는 부족하다
섹션 제목: “3. 검색 — 의미 검색만으로는 부족하다”| 방식 | 강점 | 약점 |
|---|---|---|
| 키워드(BM25) | 고유명사·코드·품번에 강함 | 표현이 다르면 못 찾음 |
| 벡터(의미) | 표현이 달라도 의미로 찾음 | 정확한 고유명사에 약함 |
| 하이브리드 | 둘을 결합 | 구현·튜닝 복잡 |
“모델 XR-2200의 보증 기간”처럼 제품 번호가 핵심인 질문에서 벡터 검색은 종종 실패한다. 임베딩은 XR-2200과 XR-2100을 비슷하게 보기 때문이다. 그래서 실무에서는 하이브리드 검색이 기본이 되어가고 있다.
4. 재순위화 (Reranking)
섹션 제목: “4. 재순위화 (Reranking)”2단계 구조가 표준이다.
- 1차 검색: 빠른 방법으로 넉넉히(예: 50개) 뽑는다
- 재순위화: 느리지만 정확한 모델(cross-encoder)로 질문과 각 문서를 함께 보고 점수를 다시 매겨 상위 5개만 남긴다
1차 검색은 질문과 문서를 따로 임베딩해 비교하지만, 재순위화 모델은 둘을 함께 넣어 판단하므로 훨씬 정확하다. 대신 느려서 전체 문서에는 쓸 수 없다.
숫자로 이해하기
섹션 제목: “숫자로 이해하기”문서 10만 개에서 답을 찾는다고 하자. 각 단계의 비용과 정확도를 비교해 보자.
구성 검색 대상 지연 시간 상위 5개 안에 정답 포함 벡터 검색만 (top-5) 100,000 ~50ms 68% 벡터 검색만 (top-20) 100,000 ~50ms 84% 벡터 top-50 → 재순위화 top-5 100,000 → 50 ~250ms 89% 여기서 두 가지가 보인다.
- top-k를 늘리면 정답이 포함될 확률은 오르지만(68% → 84%), 프롬프트에 20개를 다 넣으면 토큰 비용이 4배가 되고 모델이 잡음에 흔들린다.
- 재순위화는 “많이 뽑아서 정확히 추리는” 전략이다. 50개를 뽑되 모델에게는 5개만 주므로, 토큰 비용은 top-5와 같으면서 정확도는 top-20보다 높다.
비용은 지연 시간 +200ms다. 이것이 감당 가능한지가 재순위화 도입 판단 기준이다.
⚠️ 위 수치는 구성을 설명하기 위한 예시값이다. 실제 값은 문서 도메인과 임베딩 모델에 따라 크게 달라지므로 반드시 자체 평가셋으로 측정해야 한다.
상세 내용
섹션 제목: “상세 내용”RAG는 어디서 실패하는가
섹션 제목: “RAG는 어디서 실패하는가”RAG 프로젝트가 잘 안 될 때, 원인은 대부분 생성이 아니라 검색에 있다. 진단 순서는 이렇다.
| 증상 | 확인할 것 |
|---|---|
| 엉뚱한 답을 한다 | 검색된 문서를 직접 눈으로 보라. 근거가 틀렸으면 검색 문제다 |
| 근거는 맞는데 답이 틀리다 | 프롬프트 설계, 또는 모델이 근거를 무시하는 문제 |
| ”모르겠다”만 한다 | 검색이 아무것도 못 찾았거나 임계값이 너무 높다 |
| 여러 문서를 종합해야 하는 질문에 약하다 | RAG의 구조적 한계 — 다단계 검색이나 에이전트가 필요 |
가장 먼저 할 일은 검색 단계만 따로 평가하는 것이다. 질문-정답문서 쌍을 50개쯤 만들어 Recall@k를 재면, 생성 품질을 논하기 전에 병목이 어디인지 알 수 있다.
RAG는 두 단계를 따로, 그리고 함께 평가해야 한다.
- 검색: Recall@k, MRR, NDCG — 랭킹 지표
- 생성: 근거 충실성(faithfulness, 답이 근거에서 나왔는가), 답변 관련성
- 전체: 사람 평가 또는 LLM-as-judge
언제 사용하는가
섹션 제목: “언제 사용하는가”| 상황 | RAG 적합도 |
|---|---|
| 자주 바뀌는 사내 문서 기반 Q&A | 매우 적합 |
| 출처 제시가 필요한 도메인(법률·의료) | 매우 적합 |
| 학습 이후의 최신 정보 | 적합 |
| 문체·형식을 바꾸고 싶다 | 부적합 → 파인튜닝 |
| 새로운 추론 능력이 필요 | 부적합 → 더 강한 모델 |
| 문서 전체를 종합해야 함 | 제한적 → 긴 컨텍스트나 요약 파이프라인 |
RAG는 “지식”을 주는 것이지 “능력”을 주지 않는다. 모델이 못 하는 추론을 RAG로 해결할 수는 없다.
실전 사례
섹션 제목: “실전 사례”검색을 고치지 않고 모델만 바꾼 팀
섹션 제목: “검색을 고치지 않고 모델만 바꾼 팀”한 팀이 사내 규정 Q&A 챗봇을 만들었는데 정답률이 52%에 그쳤다. 팀의 대응은 더 큰 생성 모델로 교체하는 것이었다. 결과는 54% — 비용은 3배가 되었는데 성능은 거의 그대로였다.
원인 진단을 위해 검색 단계만 따로 측정해 보니 Recall@5가 61%였다. 즉 10번 중 4번은 정답이 담긴 문서가 애초에 프롬프트에 들어가지도 않았다. 생성 모델이 아무리 좋아도 없는 근거로 맞힐 수는 없다.
수정한 것은 세 가지였다.
- 청킹을 고정 500자 → 제목 단위로 변경 (규정 문서는 조항 단위로 의미가 완결됨)
- 하이브리드 검색 도입 (규정 번호 “제12조” 같은 표현이 벡터 검색에서 자주 누락되었음)
- 재순위화 추가 (top-30 → top-5)
Recall@5는 61% → 88%가 되었고, 정답률은 원래의 생성 모델 그대로 52% → 79%가 되었다.
교훈: RAG에서 성능이 안 나오면 검색을 먼저 재라. 생성 모델 교체는 가장 비싸면서 가장 효과가 작은 선택인 경우가 많다.
직접 해보기
섹션 제목: “직접 해보기”import numpy as npfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.metrics.pairwise import cosine_similarity
docs = [ "환불은 구매일로부터 14일 이내에 신청할 수 있습니다.", "환불 금액은 영업일 기준 3~5일 후에 입금됩니다.", "교환은 상품 수령 후 7일 이내에만 가능합니다.", "배송비는 3만원 이상 구매 시 무료입니다.", "회원 등급은 최근 6개월 구매액으로 산정됩니다.",]q = "환불은 며칠 안에 신청해야 하나요?"
# 한국어는 조사가 붙어 단어가 달라지므로(환불/환불은/환불을)# 문자 n-gram을 쓰면 훨씬 안정적으로 매칭된다vec = TfidfVectorizer(analyzer="char_wb", ngram_range=(2, 4))D = vec.fit_transform(docs)sim = cosine_similarity(vec.transform([q]), D)[0]
print("질문:", q, "\n")print(f"{'순위':>4} {'유사도':>7} 문서")order = np.argsort(-sim)for r, i in enumerate(order, 1): print(f"{r:>4} {sim[i]:>7.3f} {docs[i]}")
k = 2print(f"\n상위 {k}개만 프롬프트에 넣어 모델에게 준다:")for i in order[:k]: print(" -", docs[i])
# 실행 결과:# 질문: 환불은 며칠 안에 신청해야 하나요?## 순위 유사도 문서# 1 0.425 환불은 구매일로부터 14일 이내에 신청할 수 있습니다.# 2 0.117 환불 금액은 영업일 기준 3~5일 후에 입금됩니다.# 3 0.013 교환은 상품 수령 후 7일 이내에만 가능합니다.# 4 0.013 회원 등급은 최근 6개월 구매액으로 산정됩니다.# 5 0.000 배송비는 3만원 이상 구매 시 무료입니다.이 작은 예제에 RAG의 핵심이 다 들어 있다 — 질문과 문서를 같은 공간의 벡터로 바꾸고, 가까운 것을 골라 모델에게 준다.
주목할 점은 2위 문서의 유사도가 0.117로 뚝 떨어진다는 것이다. 실무에서는 이런 경우 top-k를 기계적으로 채우는 대신 유사도 임계값을 두어 걸러낸다. 관련 없는 문서를 프롬프트에 넣으면 모델이 오히려 혼란스러워지기 때문이다.
그리고 analyzer="char_wb"가 중요하다. 기본 단어 분리로는 “환불은”과 “환불”이 다른 토큰이 되어 2위 문서를 아예 못 찾는다 — 한국어 RAG에서 가장 자주 놓치는 함정이다.
흔한 오해와 함정
섹션 제목: “흔한 오해와 함정”-
“RAG를 붙이면 환각이 사라진다” — 줄어들 뿐이다. 검색된 근거가 틀리면 모델은 그 틀린 근거를 충실히 따라 답한다. 오히려 출처가 붙어 있어 더 믿음직해 보이는 것이 위험하다.
-
“청킹은 대충 500자로 자르면 된다” — 청킹이 검색 품질을 좌우한다. 문서 구조(제목·조항·문단)를 따르는 편이 대체로 낫다.
-
“벡터 검색이 키워드 검색보다 항상 낫다” — 제품번호·코드·고유명사에서는 키워드 검색이 압도적이다. 하이브리드가 기본이다.
-
“top-k를 늘리면 성능이 좋아진다” — 정답이 포함될 확률은 오르지만 잡음도 함께 늘어 모델이 흔들리고 토큰 비용도 커진다. 많이 뽑고 재순위화로 추리는 편이 낫다.
-
“성능이 안 나오면 모델을 키우자” — 대부분 검색 단계가 병목이다. 검색만 따로 평가해 보기 전에는 모델을 바꾸지 마라.
스스로 점검하기
섹션 제목: “스스로 점검하기”1. RAG 챗봇의 정답률이 낮다. 가장 먼저 확인할 것은?
정답 보기
검색 단계를 따로 평가한다. 질문-정답문서 쌍을 만들어 Recall@k를 재라. 정답 문서가 애초에 프롬프트에 들어가지 않았다면 생성 모델을 아무리 키워도 소용없다. 검색된 문서를 눈으로 직접 보는 것이 가장 빠른 진단이다.
2. “제품 XR-2200의 보증 기간”을 벡터 검색이 자주 놓치는 이유는?
정답 보기
임베딩은 의미적 유사성을 보므로 XR-2200과 XR-2100을 매우 비슷하게 취급한다. 정확한 문자열 일치가 중요한 고유명사·품번·코드에는 키워드 검색(BM25)이 훨씬 강하다. 그래서 하이브리드 검색을 쓴다.
3. RAG와 파인튜닝은 각각 무엇을 해결하는가?
정답 보기
RAG는 “지식”을, 파인튜닝은 “행동 양식”을 다룬다. 자주 바뀌는 사실·사내 문서는 RAG가 맞고(재학습 불필요, 출처 제시 가능), 특정 문체·출력 형식·도메인 말투를 익히게 하려면 파인튜닝이 맞다. 모델이 못 하는 추론은 RAG로 해결되지 않는다.
다른 주제와의 연결
섹션 제목: “다른 주제와의 연결”- 대규모 언어 모델: RAG가 해결하려는 환각과 지식 한계
- LLM 평가와 LLMOps: RAG 파이프라인을 어떻게 평가하고 운영하는가
- 랭킹 지표: 검색 단계 평가에 쓰는 Recall@k, NDCG
- k-NN: 벡터 검색의 기반이 되는 근사 최근접 이웃
- ML 시스템 설계 패턴: 캐싱·지연 시간 등 서빙 구조