RAG에 CRAG를 붙였더니, 검색 품질을 AI가 스스로 판단하기 시작했다
RAG 리랭크 점수가 0.003인데 정답이었다고?: 검색 결과가 나왔는데, 이걸 믿어야 하나
사내 문서 검색 시스템을 만들다 보면, 사용자가 "물류 서버 IP 알려줘"처럼 명확하게 물어볼 때도 있지만 "보안 이슈"처럼 애매하게 물어볼 때도 있거든요.
문제는 검색 엔진이 뭔가를 항상 가져오긴 한다는 겁니다.
"삼성전자 주가 알려줘"처럼 사내 문서에 절대 없는 질문을 해도 검색 결과는 나옵니다.
유사도 점수가 가장 높은 문서를 그냥 끌고 오니까요.
그러면 사용자한테 보여줄 때 이 결과를 그대로 쓸 건지, 아니면 "답을 못 찾았습니다"라고 할 건지를 누군가 판단해야 합니다.
사람이 매번 확인할 수도 없으니, AI가 스스로 "내 답이 맞는지"를 채점하는 구조가 필요하더라고요.
검색은 왜 2단계가 필요한가
도서관에서 책을 찾는 과정을 떠올려보면 이해가 빠릅니다.
1단계: 후보를 빠르게 뽑기 (Bi-Encoder)
문서가 10만 건이 있다고 치면, 질문과 문서를 각각 숫자 목록(벡터)으로 바꿔놓고 "숫자가 비슷한 것" 20개를 빠르게 뽑아옵니다.
빠른 대신 정밀하지 않거든요.
"물류 서버 IP"를 물어봤는데 "물류 서버 점검 일정"이 같이 딸려 나오는 식입니다.
2단계: 꼼꼼하게 다시 줄 세우기 (Cross-Encoder)
1단계에서 뽑아온 20건을 한 건씩 질문과 나란히 놓고 읽습니다.
"이 문서가 진짜 이 질문의 답이 되는가?"를 판단하는 거거든요.
이때 사용한 모델이 BGE-Reranker-v2-m3입니다.
1단계는 속도, 2단계는 정확도가 핵심입니다. 대충 뽑고 → 꼼꼼히 재채점하는 구조라고 보면 됩니다.

리랭크 점수는 이렇게 읽는다
BGE-Reranker는 질문과 문서를 한꺼번에 읽고, 0.0에서 1.0 사이의 점수를 매깁니다.
단순히 "단어가 겹치나"가 아니라 "이 문서가 이 질문의 답이 되는가"를 판단하는 점수거든요.
예를 들어 "물류 서버 IP 알려줘"라는 질문에 대해서:
문서 | 리랭크 점수 | 해석 |
|---|---|---|
"물류 서버의 IP 주소는 10.1.2.3이며…" | 0.934 | 딱 맞는 답 |
"물류 서버 장애 복구 절차는…" | 0.183 | 관련은 있지만 IP 얘기는 아님 |
"회의실 예약 시스템 안내…" | 0.003 | 전혀 상관없음 |
이 모델은 수백만 개의 질문-답변 쌍을 학습해서 이런 판단력을 갖게 된 건데요.
사람이 기준을 일일이 정해준 게 아니라, AI가 패턴을 스스로 익힌 겁니다.
9개 질문으로 기준선을 잡아봤다
리랭크 점수가 나오는 건 좋은데, "몇 점 이상이면 믿어도 되는 건가?"라는 기준이 필요하거든요.
이걸 잡기 위해 질문을 세 종류로 나눠서 실험했습니다.
명확한 질문 — 시스템에 답이 확실히 있거나 없는 질문
질문 | 점수 |
|---|---|
물류 서버 IP | 0.934 |
ERP 장애 이력 | 0.900 |
인사시스템 장애 이메일 | 0.001 |
애매한 질문 — 답이 있을 수도 없을 수도 있는 질문
질문 | 점수 |
|---|---|
성능 개선 | 0.790 |
장애 대응 절차 | 0.132 |
보안 이슈 | 0.033 |
답이 없는 질문 — 사내 시스템과 무관한 질문
질문 | 점수 |
|---|---|
삼성전자 주가 | 0.000 |
피자 맛집 | 0.000 |
파이썬 설치 방법 | 0.002 |
패턴이 보이더라고요.
답이 있는 건 0.7 이상, 없는 건 0.01 이하, 애매한 건 그 사이에 분포합니다.

이 점수로 뭘 하느냐 — CRAG 전략
CRAG는 "Corrective RAG"의 줄임말인데, 핵심은 간단합니다.
검색 결과가 별로면 다른 방법으로 다시 찾아보라는 전략이거든요.
리랭크 점수를 기준으로 세 구간으로 나눕니다.
구간 | 점수 범위 | 판단 | 다음 행동 |
|---|---|---|---|
Correct | 0.5 이상 | 좋은 답을 찾았다 | 그대로 사용자에게 보여줌 |
Ambiguous | 0.02~0.5 | 애매하다 | 웹 검색 등으로 보충 |
Incorrect | 0.02 미만 | 답을 못 찾았다 | 완전히 다른 경로로 재검색 |
여기서 중요한 게 있습니다.
이 임계값(0.02, 0.5)은 논문에서 정해준 값이 아니거든요.
우리 데이터에 맞는 기준을 직접 찾아야 합니다.
사내 문서가 이메일 중심인지, 기술 문서 중심인지, 장애 보고서 중심인지에 따라 점수 분포가 달라지기 때문입니다.
위에서 9개 질문으로 실험한 이유가 바로 이 기준선을 잡기 위해서였습니다.
텍스트 점수만 믿었으면 정답을 놓칠 뻔했다
실험 중에 흥미로운 케이스가 나왔습니다.
"서버 간 의존관계 알려줘"라는 질문의 텍스트 리랭크 점수는 0.003이었거든요. CRAG 기준으로는 Incorrect, 즉 "답 없음"입니다.
그런데 실제로는 지식 관계도(Neo4j)가 정확한 답을 찾아냈습니다. 서버 간 의존관계는 문서에 글로 적혀 있는 게 아니라, 서버 노드 사이의 연결 관계로 저장되어 있었기 때문이거든요.
텍스트 검색은 "문서 안의 글"에서 답을 찾고, 관계도 검색은 "데이터 사이의 연결"에서 답을 찾습니다. 같은 질문이라도 검색 경로가 다르면 결과가 완전히 달라지는 거죠.
만약 텍스트 점수만 보고 "답 없음"으로 처리했으면, 관계도가 이미 찾아놓은 정답을 그냥 버리는 셈이었습니다. 그래서 최종 판단 규칙에 조건을 하나 추가했습니다:
"관계도 검색 결과가 있으면 텍스트 점수와 관계없이 Correct로 판단한다."

마무리
검색 시스템을 만들 때 "검색 결과를 잘 가져오는 것"까지만 신경 쓰기 쉬운데, 실제로는 그 뒤에 "이 결과를 믿어도 되는가"를 판단하는 구조가 하나 더 필요하더라고요.
Bi-Encoder로 후보를 뽑고, Cross-Encoder(BGE-Reranker)로 채점하고, 그 점수를 CRAG 전략에 넘겨서 "쓸지, 보충할지, 버릴지"를 결정하는 흐름입니다.
임계값은 논문 값을 그대로 쓰는 게 아니라 자기 데이터에 맞게 실험으로 잡는 걸 추천합니다.
그리고 텍스트 검색 점수가 낮다고 바로 "답 없음"으로 넘기면, 관계도 검색이 이미 찾은 정답을 놓칠 수 있습니다. 검색 경로가 여러 개라면 각 경로의 결과를 종합해서 최종 판단하는 로직을 별도로 두는 게 좋습니다.
🏷️ RAG, CRAG, 리랭크, BGE-Reranker, 지식그래프, 검색품질