RAG에서 검색 결과가 부족하면 어떻게 해야 할까?
검색 결과 2건으로 답변을 만들고 있었다
RAG 파이프라인을 운영하다 보면, 검색 결과가 충분할 때도 있고 부족할 때도 있습니다. "이 시스템의 장애 이력을 알려줘"라고 질의하면 관련 문서가 10건 넘게 걸리는데, "이 서비스의 DR 절차가 뭐야?"처럼 특정한 질문을 하면 2건밖에 안 나오는 경우가 있거든요.
문제는 일반적인 RAG가 이 차이를 신경 쓰지 않는다는 겁니다. 검색 결과가 10건이든 2건이든, 가져온 걸로 그냥 답변을 만들어요. 2건짜리 결과로 답변을 생성하면 정보가 빈약하거나, 최악의 경우 관련 없는 문서를 근거로 엉뚱한 답변을 만들 수 있거든요.
사용자 입장에서는 "질문했는데 답이 부실하다" 또는 "뭔가 틀린 것 같다"는 경험이 되고, 이게 반복되면 시스템 자체를 신뢰하지 않게 됩니다.
"검색 결과가 부족하면 어떻게 하지?"를 고민하다가 CRAG(Corrective RAG)라는 개념을 알게 됐습니다.
CRAG는 "검색 결과를 스스로 보정하는 RAG"다
CRAG는 2024년 1월에 발표된 논문에서 제안된 프레임워크예요. 핵심 아이디어는 단순합니다. 검색 결과를 그냥 쓰지 말고, 먼저 평가한 뒤에 부족하면 보정하라는 거예요.
일반 RAG와 비교하면 이렇습니다.
일반 RAG:
질문 → 검색 → 결과 3건 → 그대로 답변 생성 (결과가 부족해도 그냥 진행)
CRAG:
질문 → 검색 → 결과 3건 → "이거 충분한가?" 평가 → 부족하면 다른 소스로 재검색 → 보강된 결과로 답변 생성
차이는 검색과 답변생성 사이에 평가 단계가 들어간다는 거예요. 이 평가 단계가 CRAG의 핵심이고, 여기서 검색 결과의 품질을 판단합니다.

논문의 CRAG는 3단계로 평가한다
원본 논문을 읽어보면, CRAG의 평가 단계가 꽤 정교합니다. 가벼운 retrieval evaluator(T5-large 기반)가 검색 결과 각각의 관련도를 평가해서, 전체 결과의 신뢰도를 세 등급으로 분류하거든요.
평가 결과 | 의미 | 액션 |
|---|---|---|
Correct | 검색 결과가 충분히 관련됨 | 불필요한 부분만 필터링하고 그대로 사용 |
Incorrect | 검색 결과가 부적절함 | 기존 결과를 버리고 웹 검색으로 대체 |
Ambiguous | 애매함 | 기존 결과 + 웹 검색 결과를 함께 사용 |
Correct일 때도 그냥 넘기는 게 아니라, "decompose-then-recompose" 알고리즘으로 검색 결과에서 관련 있는 부분만 골라내고 불필요한 정보를 걸러냅니다. Incorrect일 때는 과감하게 기존 결과를 버리고 웹 검색으로 대체하고요. Ambiguous는 둘 다 섞어서 쓰는 방식이에요.
이 3단계 평가가 논문의 핵심이에요. 단순히 "부족하면 재검색"이 아니라, "얼마나 부족한지"를 판단해서 대응 수준을 달리하는 것이거든요.
논문에서는 이 evaluator를 T5-large로 학습시켰는데, 파라미터 사이즈가 현재 LLM들보다 훨씬 작아서 가볍게 돌릴 수 있다는 장점이 있습니다. 평가 단계가 답변생성보다 빠르게 동작해야 전체 파이프라인 속도에 영향을 주지 않으니까, 가벼운 모델을 쓴 건 설계상 중요한 선택이에요.
우리 프로젝트에서는 건수 기반으로 단순화했다
논문의 3단계 평가를 그대로 구현하려면 retrieval evaluator를 별도로 학습시켜야 합니다. T5-large를 파인튜닝하고, 관련도 라벨 데이터를 만들고, 서빙 인프라를 구축해야 하거든요. 우리 프로젝트 규모에서는 과한 투자였어요.
대신 핵심 아이디어만 가져와서 단순화했습니다. 관련도 평가 대신 검색 결과 건수로 판단하는 방식이에요.
파이프라인에 expand_search_node라는 단계를 넣었는데, 동작은 이렇습니다. 처음에 지식 문서(knowledge)를 검색하고, 결과가 부족하면 아직 안 쓴 소스로 자동 재검색하는 거예요.
검색 순서: knowledge → emails → threads → communities
→ 결과가 부족하면, 아직 안 쓴 소스에서 추가 검색
→ 충분하면 다음 단계로 진행논문의 Correct/Incorrect/Ambiguous 3단계를 "건수가 충분한가/부족한가"의 2단계로 줄인 셈이에요. 관련도를 평가하는 건 리랭크 단계에서 처리하니까, 여기서는 "양이 충분한가"만 판단하면 되거든요.
이 방식의 장점은 별도 모델 없이 구현할 수 있다는 점이에요. 검색 결과 건수만 세면 되니까 추가 인프라가 필요 없고, 파이프라인에 조건문 하나 추가하는 정도의 수정이거든요.
CRAG와 피드백 루프는 다른 개념이다
CRAG를 처음 접하면 "사용자 피드백으로 개선하는 거 아닌가?"라고 생각할 수 있는데, 둘은 완전히 다른 개념이에요.
CRAG (자동 보정) | 피드백 루프 (학습) | |
|---|---|---|
누가 판단 | 시스템이 자동 | 사용자가 판단 |
언제 | 질문 처리 중 즉시 | 다음 질문부터 |
방법 | 안 써본 검색 소스로 재시도 | 라우팅 패턴 기록 → 규칙화 |
CRAG는 지금 이 질문에 대한 검색 결과를 즉시 보정하는 거고, 피드백 루프는 다음 질문부터 더 나은 결과를 내기 위해 학습하는 거예요. CRAG는 실시간 보정, 피드백 루프는 장기 학습. 레이어가 다릅니다.
우리 프로젝트에서는 CRAG(expand_search_node)가 먼저 들어가 있고, 피드백 루프는 그 위에 얹을 수 있는 구조예요. CRAG가 "지금 당장 답변 품질을 올리는 것"이고, 피드백 루프는 "시간이 지나면서 시스템이 더 똑똑해지는 것"이거든요.

논문 그대로 안 써도 핵심 아이디어는 가져올 수 있다
CRAG 논문을 읽으면서 배운 건, 논문의 구현을 그대로 따라할 필요는 없다는 점이에요. T5-large를 파인튜닝해서 retrieval evaluator를 만드는 건 연구 환경에서는 가능하지만, 실무 프로젝트에서는 과한 경우가 많거든요.
핵심 아이디어 — "검색 결과를 평가하고, 부족하면 보정한다" — 만 가져와서, 프로젝트 상황에 맞게 단순화하면 됩니다. 우리는 관련도 평가를 건수 기반으로 바꾸고, 재검색 대상을 웹이 아니라 내부 소스(이메일, 쓰레드, 커뮤니티)로 잡았어요.
이전 글에서 다뤘던 thinking budget 동적 조절도 비슷한 맥락이에요. 공식 문서의 Easy/Medium/Hard 분류를 검색 결과 건수로 치환해서 적용한 거거든요. 논문이나 공식 가이드의 원리를 이해하고, 자기 프로젝트에 맞는 수준으로 변환하는 게 실무에서는 더 중요하더라고요.
RAG 파이프라인에서 검색 결과가 들쑥날쑥하다면, CRAG의 핵심 아이디어를 한번 검토해보는 걸 추천합니다. 별도 모델 없이 건수 기반 조건문만으로도 답변 품질 차이가 생기거든요.