P6-11.2 검색 실패와 생성 실패를 가르는 RAG 흐름¶
Section ID:
P6-11.2Version:v2026.07.24
P6-11.1에서는 RAG(retrieval-augmented generation)가 답변 전에 외부 근거를 붙이는 구조라는 점을 보았습니다. 이제는 그 근거가 실제 입력 흐름에서 어디에 놓이고, 답변 실패를 어떻게 나누어 읽어야 하는지 봐야 합니다.
RAG에서 검색 결과는 답변 뒤에 붙는 장식이 아니라, 생성 전에 모델 입력 맥락(context)으로 들어가는 재료입니다. 그래서 같은 오답처럼 보여도 무엇을 가져왔는가와 가져온 것을 어떻게 다시 썼는가를 나누어 봐야 합니다.
검색과 생성이 결합되는 흐름¶
검색-생성 결합에서 먼저 닫아야 할 기준은 다음 세 가지입니다.
| 질문 | 여기서 잡을 기준 |
|---|---|
| 검색 결과는 생성 전에 어떻게 쓰이는가? | 검색 문서는 모델 입력 맥락에 붙는다 |
| 문서를 많이 넣으면 항상 좋은가? | 양보다 관련성, 순서, 충돌 관리가 중요하다 |
| 답이 틀렸을 때 어디를 봐야 하는가? | 검색 실패와 생성 실패를 따로 본다 |
P6-11.1의 질문이 왜 답 전에 문서를 붙여야 하는가였다면, 여기서는 붙인 문서가 입력 맥락과 최종 답 사이에서 어떻게 작동하는가를 봅니다. 그다음 P6-12에서는 그 문서를 어떤 저장 구조와 인덱스로 다시 꺼낼지로 넘어갑니다.
검색 결과는 어디에 붙나¶
가장 단순한 형태에서는 검색된 문서 일부가 프롬프트 맥락에 함께 들어갑니다.
예를 들어 입력은 다음처럼 구성될 수 있습니다.
- 사용자 질문
- 검색된 문서 발췌
- 답변 형식 지시
즉, 모델은 질문만 받는 것이 아니라, 질문 + 관련 문서 + 응답 지시를 함께 받게 됩니다.
RAG는 검색 결과를 모델 바깥에서 따로 가지고 있다가, 답하기 직전에 입력 맥락으로 붙여 넣는 구조다.
여기서 먼저 남겨야 할 것은 어떤 문서를 얼마나 관련 있다고 보고 실제로 붙였는지, 어떤 근거 문장을 선택했는지, 최종 답이 문서를 과장하거나 벗어나지 않았는지를 보여 주는 검색 기록과 답안 점검 메모입니다. 이 기록이 있어야 검색 실패와 생성 실패를 나눌 수 있고, 뒤로 갈수록 P6-12.1, P6-12.2의 검색 품질 점검, P6-16의 평가, P6-17의 운영 판단, Part 6의 검색 회수 기록과 회고 메모로 다시 읽힙니다.
문서를 많이 넣으면 항상 좋은가¶
아닙니다. 여기서 중요한 것은 양보다 관련성과 정리 방식입니다.
문서를 너무 많이 넣으면:
- 핵심이 묻힐 수 있고
- 서로 충돌하는 문장이 섞일 수 있으며
- context window를 낭비할 수 있고
- 모델이 오히려 헷갈릴 수 있습니다
따라서 검색 결과는 많이 모으는 것보다 질문에 맞는 자료를 적절한 크기와 순서로 넣는 것이 더 중요합니다.
이 지점에서 한 걸음만 더 가면 검색-생성 결합 앞에 이미 문서 준비 단계가 있다는 점도 보입니다. 검색이 잘 되려면 문서를 그냥 쌓아 두는 것이 아니라, 질문이 왔을 때 찾아 붙일 수 있는 형태로 미리 정리해 두어야 합니다.
즉, 여기서는 찾아온 문서를 어디에 붙이는가를 다루고 있지만, 그 전에 이미 붙일 수 있게 문서를 정리해 두는 단계가 있습니다. 이 차이가 보여야 벡터 데이터베이스와 인덱스 설명도 단순 저장소 소개가 아니라 검색 가능한 문서 준비의 연장선으로 읽힙니다.
이 차이를 요청 시점 기준으로 다시 나누면 다음처럼 읽는 편이 가장 안전합니다.
| 단계 | 먼저 보는 질문 | 흔한 실패 |
|---|---|---|
| 문서 준비 단계 | 지금 질문이 오기 전에 문서가 검색 가능하게 정리돼 있었는가? | 낡은 버전 혼입, 중복 문서, 너무 긴 청크 |
| 검색 단계 | 현재 질문에 맞는 문서를 실제로 잘 가져왔는가? | 무관 문서 상위 노출, 최신 문서 누락 |
| 생성 단계 | 가져온 문서를 벗어나지 않고 답을 다시 썼는가? | 조건 누락, 과장, 일반 기억 혼입 |
즉, 검색-생성 결합은 요청이 들어온 뒤의 두 단계만이 아니라, 그보다 앞선 문서 준비 단계까지 포함해야 제대로 읽힙니다.
검색 실패와 생성 실패는 어떻게 다른가¶
이 구분이 매우 중요합니다.
검색 실패¶
- 관련 문서를 못 찾았다
- 오래된 문서가 먼저 나왔다
- 질문과 상관없는 문서가 섞였다
생성 실패¶
- 문서를 가져왔는데도 잘못 요약했다
- 문서 근거보다 일반 기억으로 답했다
- 출처를 잘못 연결했다
즉, RAG 시스템에서 답이 이상하면 항상 모델이 나쁘다고만 말할 수 없습니다. 먼저 검색이 틀렸는지, 생성이 틀렸는지를 나눠 봐야 합니다.
같은 오답처럼 보여도 먼저 보인 신호에 따라 바로 확인할 기록과 다음 조치는 달라집니다.
| 먼저 보인 신호 | 먼저 의심할 실패 축 | 가장 먼저 다시 볼 기록 | 즉시 확인할 조치 | 서두르면 안 되는 결론 |
|---|---|---|---|---|
| 붙은 문서 제목이나 발췌가 질문과 어긋난다 | 검색 실패 | 어떤 문서가 붙었는지, 관련성 점수가 어땠는지, 어떤 근거 문장을 골랐는지 다시 봅니다 | 어떤 문서가 왜 상위에 왔는지 다시 보고, 질문과 무관한 문서가 섞였는지 먼저 뺍니다 | 곧바로 프롬프트 문장만 고치면 해결된다고 단정하지 않습니다 |
| 붙은 문서는 맞는데 답이 조건을 빼먹거나 과장한다 | 생성 실패 | 답 초안이 실제 근거 문장을 벗어났는지, 근거 점검에서 어디가 흔들렸는지 다시 봅니다 | 답 초안이 실제 근거 문장을 벗어났는지 확인하고, 요약 지시와 근거 점검 규칙을 다시 봅니다 | 검색 품질이 이미 충분하다고 단정하지 않습니다 |
| 검색도 어색하고 답도 함께 흔들린다 | 검색 실패가 생성으로 전염된 경우 | 검색 기록과 답 초안을 함께 봅니다 | 먼저 검색 오염을 줄인 뒤, 그다음 생성 지시를 다시 조정합니다 | 한 번의 오답만 보고 모델 전체 능력 문제로 확대하지 않습니다 |
왜 답변 품질이 흔들릴 수 있나¶
RAG는 두 단계를 결합하기 때문에 흔들릴 수 있는 지점도 늘어납니다.
- 검색 문서 선택
- 문서 길이와 발췌 방식
- 문서 순서
- 생성 지시 방식
- 인용 형식
이 때문에 RAG는 단순히 검색 하나, 생성 하나가 아니라 검색 파이프라인 + 생성 파이프라인으로 읽는 것이 더 정확합니다.
아주 단순하게 그리면¶
flowchart TD
A["사용자 질문"]
B["상위 문서 검색"]
C["질문+문서로 프롬프트 구성"]
D["답 생성"]
A --> B
B --> C
C --> D
이 도식의 핵심은 검색 결과가 답변 뒤에 붙는 것이 아니라, 답변 전에 입력 맥락으로 들어간다는 점입니다.
사례 및 예시¶
사례 1. 제품 지원 챗봇¶
고객이 자동 저장을 끄려면 어디로 들어가야 하나요?라고 묻는 제품 지원 챗봇을 생각해 볼 수 있습니다. 이 장면에서는 검색이든 생성이든 결국 답 한 번만 잘 나오면 된다고 느끼기 쉽습니다. 하지만 검색 단계는 먼저 최신 매뉴얼에서 자동 저장, 설정, 환경설정이 들어간 관련 문단을 찾아와야 합니다. 그다음 생성 단계는 그 문단 내용을 그대로 복사하는 대신, 고객 질문에 맞춰 어느 메뉴를 누르고 어떤 순서로 들어가야 하는지를 다시 설명합니다. 예를 들어 문서에는 환경설정 > 편집 > 자동 저장처럼 경로만 적혀 있고, 생성 단계는 이를 사용자가 따라 하기 쉬운 문장으로 바꾸는 역할을 맡습니다.
만약 검색이 잘못되어 다른 제품 버전 문단을 가져오면 생성이 아무리 자연스러워도 엉뚱한 기능을 안내하게 됩니다. 여기서 바뀌는 점은 답을 바로 쓰는 일에서 먼저 맞는 문단을 찾고 그다음 질문 형태로 다시 풀어 쓰는 일로 기준이 나뉜다는 것입니다. 여기서 바로잡아야 할 오해는 문장이 자연스러우면 앞 단계도 제대로 됐겠지라는 기대입니다. 그래서 이 사례에서 확인해야 할 결과는 최신 매뉴얼 경로가 실제 답변 문장 안에 올바르게 반영되는가, 그리고 검색된 경로와 최종 절차 문장이 서로 같은 버전을 가리키는가입니다.
사례 2. 법률 문서 보조¶
법률 문서 보조 도구에서 사용자가 이 조항이면 계약 해지가 바로 가능한가요?라고 묻는다고 해 봅시다. 관련 조문을 잘 찾았으면 거의 끝난 것처럼 느끼기 쉽습니다. 하지만 검색 단계는 먼저 관련 조문과 판례 요약을 찾아 현재 질문과 가까운 문서를 모으는 일이고, 생성 단계는 그 문서를 바탕으로 바로 가능, 추가 조건 필요, 판단 보류처럼 질의응답 형태로 다시 정리하는 일입니다. 예를 들어 문서에는 상당한 기간을 정해 시정 요구 후 해지 가능이라고 되어 있는데, 생성이 중간 조건을 빼고 즉시 해지 가능처럼 단정하면 검색은 맞았어도 최종 답은 위험해질 수 있습니다.
여기서 바뀌는 점은 문서를 찾았으니 끝났다는 기준에서 찾은 문서 조건을 빼먹지 않고 다시 정리했는가까지 따로 보는 기준으로 이동한다는 것입니다. 그래서 이 사례에서는 문서를 찾는 정확성과 문서 바깥으로 나가지 않는 정리를 따로 봐야 합니다. 여기서 바로잡아야 할 오해는 관련 조항이 붙었으면 최종 문장도 자동으로 안전하다는 판단입니다. 그래서 이 사례에서 확인해야 할 결과는 최종 답이 즉시 가능로 과장되지 않고 원문 조건을 그대로 포함하는가, 그리고 생성 문장이 문서 밖의 강한 결론을 새로 덧붙이지 않는가입니다.
사례 3. 개발 문서 질의응답¶
개발자가 이 API에서 timeout 옵션은 어디에 넣나요?라고 묻는 장면을 떠올려 볼 수 있습니다. 사람은 검색이 올바른 버전의 공식 문서를 가져오면 이제 거의 끝났다고 느끼기 쉽습니다. 하지만 생성 단계가 예전 예제 코드와 새 문서를 섞거나 옵션 이름을 비슷한 다른 인자로 바꿔 말하면, 최종 답은 여전히 실패로 이어질 수 있습니다. 예를 들어 문서에는 request_timeout인데 생성이 익숙한 다른 라이브러리 이름인 timeout_ms로 바꿔 말하면, 문서는 맞았어도 답은 바로 깨집니다. 즉, 검색이 맞다고 해서 자동으로 답도 맞는 것은 아닙니다.
여기서 바뀌는 점은 검색 성공과 최종 답 정확성을 같은 일로 보지 않고, 찾아온 이름을 답변에도 그대로 유지하는가를 별도 기준으로 보게 된다는 것입니다. 여기서 바로잡아야 할 오해는 공식 문서를 붙였으면 생성은 알아서 맞춰 줄 것이라는 기대입니다. 그래서 이 사례에서 확인해야 할 결과는 검색된 공식 옵션명이 최종 답변에도 그대로 유지되고, 비슷한 다른 인자 이름으로 바뀌지 않는가, 그리고 답변 예시 코드도 검색된 문서와 같은 인터페이스를 유지하는가입니다.
세 사례를 단계 구분 관점으로 다시 묶으면 다음과 같습니다.
| 상황 | 검색 단계가 먼저 맞아야 하는 것 | 생성 단계가 이어서 지켜야 하는 것 |
|---|---|---|
| 제품 지원 챗봇 | 현재 버전의 정확한 메뉴 경로 문단 회수 | 문단 내용을 사용자 절차 문장으로 정확히 풀어쓰기 |
| 법률 문서 보조 | 관련 조문과 조건 문단 회수 | 조건을 빠뜨리지 않고 단정 표현을 피하기 |
| 개발 문서 질의응답 | 현재 버전의 공식 옵션 문단 회수 | 옵션명을 비슷한 다른 이름으로 바꾸지 않기 |
같은 내용을 단계 분리 구조로 다시 보면 다음처럼 읽을 수 있습니다.
flowchart LR
A["사용자 질문"]
B["검색 단계<br/>어떤 문서가 붙는가?"]
C["생성 단계<br/>문서가 어떻게 다시 쓰이는가?"]
D["검색 실패<br/>잘못된 또는 무관한 문서"]
E["생성 실패<br/>과장 또는 잘못된 재서술"]
A --> B --> C
B --> D
C --> E
핵심은 RAG가 한 단계처럼 보이더라도 내부에서는 검색과 생성이 따로 흔들린다는 점입니다.
검색 실패와 생성 실패가 갈리는 장면¶
앞의 표를 사례 뒤에서 다시 적용하면 판단 질문은 세 개로 압축됩니다. 답이 이상하다는 인상에서 바로 모델 전체 문제로 뛰지 않고, 먼저 검색 기록과 생성 답변을 따로 놓고 봅니다.
| 이런 의심이 들면 | 먼저 던질 질문 |
|---|---|
붙은 근거부터 낯설다 | 어떤 문서가 왜 상위에 왔는가? |
근거는 맞는 것 같은데 답이 세게 말한다 | 답이 실제 문장보다 더 강하게 단정했는가? |
어디서부터 틀렸는지 모르겠다 | 검색 기록과 최종 답을 따로 놓고 봤는가? |
먼저 익혀야 하는 기준은 단순합니다. RAG를 한 단계처럼 보더라도, 점검할 때는 검색 단계와 생성 단계를 분리해서 봐야 원인을 제대로 잡을 수 있습니다.
연습 및 예제¶
예제의 목표는 검색과 생성을 한 단계로 뭉개지 않고, 문서를 찾는 단계와 그 문서를 붙여 답을 만드는 단계를 분리해서 보는 감각을 만드는 것입니다. 같은 문서 집합에서 검색 질문과 generation_style을 바꿔, 검색 오염과 생성 과장이 서로 다른 단계의 실패로 드러나는지 확인합니다.
사용자가 벡터 검색이 왜 필요한가요?라고 묻는다고 해 봅시다. 검색 단계는 관련 문서를 골라야 하고, 생성 단계는 그 문서를 바탕으로 독자용 설명을 다시 써야 합니다. 검색이 맞아도 생성이 과장되면 최종 답은 다시 틀어질 수 있습니다.
아래 예제는 두 CSV 파일을 입력으로 사용합니다.
- 문서 목록: p6-11-rag-documents.csv
- 실험 조건: p6-11-rag-experiments.csv
문서 목록의 한 행은 검색 후보 문서 조각 하나입니다. 핵심 열은 title, text, category, source_role입니다. category가 retrieval이면 현재 질문과 관련 있는 근거 문서이고, irrelevant이면 검색 조건이 흔들릴 때 섞일 수 있는 무관 문서입니다.
실험 조건의 한 행은 한 번의 RAG 요청을 뜻합니다. retrieval_terms는 질문을 구성하는 검색 신호이고, generation_style은 찾은 문서를 답으로 바꿀 때의 생성 방식을 뜻합니다. 출력에서는 검색 모델이 고른 문서 제목과 유사도, 답변 문장, 검색 실패와 생성 실패를 나누어 보는 점검값을 확인합니다. 특히 source_trace는 생성 직전에 붙은 문서 ID, 제목, 역할, 유사도, 본문 미리보기를 묶어 남기므로, 답변만 보지 않고 어떤 근거 문서가 입력 맥락으로 들어갔는지 다시 확인하게 해 줍니다.
먼저 이 예제에서 직접 바꿔 볼 설정은 다음과 같습니다.
| 실험 | 조작할 값 | 읽어야 할 핵심 |
|---|---|---|
clean_grounded | 관련 검색어와 보수적 생성 | 정상 흐름 |
noisy_retrieval | 무관한 검색어가 섞인 검색 조건 | 검색 실패가 생성으로 전염 |
clean_but_overclaim | 검색은 정상, 생성 조건만 과장형 | 생성 실패 |
코드에서 확인할 핵심은 RAG 실패는 검색이 틀린 경우와 생성이 문서 밖으로 과장한 경우를 나눠 봐야 원인을 정확히 잡을 수 있다는 점입니다. 검색은 P6-11.1과 같은 TfidfVectorizer 흐름을 사용하고, 생성 실패는 검색 결과가 맞았는데도 답변 문장이 근거보다 강하게 말하는 경우로 따로 잡습니다. 이 코드는 검색 기록과 답변 점검 기록을 따로 남겨, 어느 단계의 기록을 먼저 다시 봐야 하는지 읽는 연습에 초점을 둡니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | |
실행 결과 예시는 다음처럼 읽을 수 있습니다.
이 결과에서 먼저 봐야 할 것은 retrieval_failure_count와 generation_failure_count가 각각 따로 잡힌다는 점입니다. 즉, noisy_retrieval은 검색 조건에 섞인 잡음 때문에 무관 문서가 선택되고 생성까지 오염된 경우이고, clean_but_overclaim은 검색은 맞았지만 생성 조건이 문서 밖으로 과장된 경우입니다. 이 구분이 있어야 RAG 시스템을 손볼 때 검색을 고칠지, 생성 지시와 평가를 고칠지를 분리해서 판단할 수 있습니다.
그래서 이 예제에서 확인해야 할 결과는 두 가지입니다.
- 검색 결과가 최종 답변 안으로 바로 녹아 없어지는 것이 아니라, 생성 직전까지는
source_trace처럼 별도의 입력 근거 기록으로 남는다. - 검색 실패와 생성 실패는 같은 오답처럼 보여도 원인이 다르므로, 점검 항목도 따로 가져가야 한다.
이 예제에서 독자가 직접 해 볼 수 있는 조정은 다음과 같습니다.
experiments[1]["retrieval_terms"]에서 무관 검색어를 줄여 검색 실패가 사라지는지 보기documents에 문서를 한 개 더 넣어 문서 수 증가가 답변에 어떤 영향을 주는지 보기generate_answer를 바꿔 문서 제목을 출처처럼 같이 남기도록 해 보기answer_overclaims규칙을 더 늘려항상,완벽히,자동으로 해결같은 과장 표현을 더 잡아 보기
RAG 파이프라인에서 갈리는 실패 단계¶
앞의 예제는 검색과 생성을 모두 구현하는 코드가 아니라, 문서를 찾는 단계와 그 문서를 붙여 답을 만드는 단계가 실제로 분리되어 있다는 점을 가장 짧게 보여 주는 장면입니다. 여기서 중요한 것은 답변 문장이 아니라, 답변 직전까지 근거 문서가 독립된 입력 구성 요소로 남아 있다는 구조를 읽는 데 있습니다. 즉, 검색 결과가 마음에 들지 않으면 생성 프롬프트를 고치기 전에 어떤 문서가 붙었는가부터 다시 봐야 한다는 뜻이기도 합니다. 무관 문서가 섞였을 때 답변까지 바로 흔들린다는 점은 이 분리를 더 분명하게 보여 줍니다.
대표 실행 3건을 점검 매트릭스로 보면 정상 검색 예는 관련 문서 상위 회수만 켜지고 실패 신호가 남지 않습니다. 검색 오염 예는 무관 문서 포함, 답변 오염, 검색 실패가 함께 켜지며, 답변 과장 예는 관련 문서를 회수했는데도 과장 표현과 생성 실패가 따로 켜집니다. 즉, 같은 오답처럼 보이는 결과도 어느 단계에서 흔들렸는지 따로 읽을 수 있습니다. RAG 점검에서는 답이 틀렸다는 결론보다 먼저 어느 단계의 기록을 다시 볼지 갈라야 합니다.

이 매트릭스를 보고 남겨야 할 결론은 하나입니다. RAG의 실제 결합 흐름은 문서를 먼저 붙이고 그 위에서 답한다는 두 단계 구조이며, 답이 틀렸을 때 검색을 고칠지, 생성 지시와 평가를 고칠지 분리해서 판단해야 합니다. 이 구분이 있어야 다음 장의 벡터 데이터베이스와 인덱스는 검색 품질 점검으로, 이후 평가 장은 답변 품질 점검으로 이어집니다.
체크리스트¶
- 검색 결과가 답변 뒤가 아니라 생성 전 입력 구성 요소라는 점을 설명할 수 있는가?
- 검색 실패와 생성 실패를 서로 다른 문제로 분리해 말할 수 있는가?
- 다음 장을
어떻게 더 빨리, 더 관련성 있게 문서를 찾을까의 문제로 읽을 준비가 되었는가?
출처와 참고 자료¶
- Patrick Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks, NeurIPS, 2020, 확인 날짜: 2026-07-19.
- OpenAI, Retrieval, OpenAI API Docs, 확인 날짜: 2026-07-19.
- OpenAI, File search, OpenAI API Docs, 확인 날짜: 2026-07-19.
- scikit-learn developers, TfidfVectorizer, scikit-learn documentation, 확인 날짜: 2026-07-22.
- scikit-learn developers, Cosine similarity, scikit-learn documentation, 확인 날짜: 2026-07-22.