개발/AI

RAG 검색 개선기: RAG 검색 평가셋을 고를 때 고민한 것들

애쿠 2026. 4. 28. 11:02

현재 온디바이스(On-Device) 환경에서 쓸 RAG 검색 시스템을 개선하고 있다. 그런데 막상 "검색을 개선하자"고 마음먹고 나니, 제일 먼저 막힌 건 알고리즘이 아니라 "개선됐는지 어떻게 아느냐" 였다.

 

개선이라는 건 결국 "전보다 나아졌다"를 보여야 하는데, 그 "전보다"를 재는 자가 흔들리면 무슨 짓을 해도 "좋아진 것 같다"는 느낌으로만 남는다.

 

이 글은 이전 글에서 정리한 'RAG 구축 시 고려할 것들' 중 검색 품질을 측정하는 기준에 해당한다. 결론부터 말하면, 검색을 건드리기 전에 평가셋부터 다시 짜야 했고, 그 과정에서 생각보다 고민할 게 많았다.

1. 테스트 목적이 하나가 아니었다

처음엔 단순하게 생각했다. "검색 평가셋 하나 잘 만들면 그걸로 다 재면 되지." 그런데 실제로 실험을 돌리다 보니 점수 하나에 서로 다른 두 가지가 섞여 들어왔다.

 

예를 들어 임베딩 모델을 바꿨더니 점수가 올라갔다고 하자. 그런데 같은 시기에 질의를 원문 그대로 넣을지 키워드만 뽑아 넣을지도 바꿔보고 있었다. 그러면 점수가 움직였을 때 그게 임베딩 덕분인지, 질의 넘기는 방식 덕분인지를 구분할 수가 없다. 둘 다 "검색 점수"라는 같은 숫자로 보이지만, 사실은 전혀 다른 실험이다.

 

하나는 검색기 자체의 성능을 보는 실험이고, 다른 하나는 그 앞단에서 질의를 어떻게 다듬을지를 보는 실험이다. 이 둘을 한 평가셋에 섞어두면, 점수가 변해도 무엇 때문에 변했는지 영영 못 짚는다.

 

그래서 평가셋도 목적별로 나눠야 했다.

2. 공개 벤치마크 질의는 실사용 질의와 다르다

처음엔 공개 retrieval 벤치마크로 측정했다. 점수도 그럭저럭 잘 나왔다. 그런데 막상 실서비스에 가까운 질의를 넣어보니 체감이 영 달랐다. 왜 그런지 들여다보니, 질의의 생김새부터 달랐다.

 

공개 벤치마크는 대부분 완전한 문장으로 질의를 던진다. "세계 최초로 5G 데이터를 개통한 나라는 어디인가?" 같은 식이다. 그런데 실제 사용자는 이렇게 안 친다. "최근 서울 AI 바우처 지원사업" 처럼 짧은 조각으로 던진다.

이게 왜 문제냐면, 문장형 질의는 문맥이 통째로 들어가서 원질의(raw_query)가 거의 다 맞춰버린다.

 

그러면 어떤 검색 방법을 써도 점수가 비슷하게 높게 나와서, 정작 방법들 사이의 차이가 안 드러난다. 공개 벤치마크만 보면 "raw가 최고"라는 결론에서 끝나고, 실사용에서 갈리는 진짜 차이는 묻혀버린다. 그래서 실사용 파편 질의에 가까운 평가셋을 따로 만들어야 했다.

3. 범위를 섞으면 원인을 못 짚는다

검색 파이프라인은 질의처리 → 검색기 → (리랭커) 로 이어진다.

 

처음엔 이걸 한 번에, 그러니까 질의를 넣어서 최종 검색 결과가 나오는 E2E로 측정했다. 직관적이긴 한데, 점수가 떨어졌을 때가 문제였다.

 

점수가 내려가도 그게 질의처리가 질의를 망쳐서인지, 검색기가 약해서인지 알 수가 없었다. 한참을 검색기만 붙들고 튜닝하다가, 알고 보니 원인은 그 앞단에 있던 적도 있다. 측정 단위가 뭉뚱그려져 있으면 시간을 엉뚱한 데 쏟게 된다.

 

그래서 범위를 갈랐다. 검색기만 보는 셋, 질의처리만 보는 셋, 그리고 전체를 보는 셋. 원인을 짚으려면 측정부터 분리되어 있어야 했다.

4. Recall만으로는 부족했다

일반적인 검색이라면 "맞는 문서를 상위에 올렸나"(Recall)로 충분할 수 있다. 그런데 RAG는 사정이 다르다. 검색 결과 상위 몇 개가 그대로 LLM의 입력으로 들어가기 때문이다.

 

여기서 함정이 있다. 비슷하지만 틀린 문서가 상위에 끼면, 그게 LLM 입력을 오염시켜 답까지 틀리게 만든다. 정답 문서를 찾았는지만 보면 "그럭저럭 괜찮네" 싶어도, 그 옆에 끼어든 오답이 답변을 망치는 것이다.

 

그래서 평가셋에 비슷하지만 틀린 문서(hard negative)를 의도적으로 섞었다. "정답을 찾는 힘"뿐 아니라 "오답을 밀어내는 힘"까지 같이 봐야 RAG에서 쓸 만한 검색인지 판단할 수 있었다.

5. 결국, 실패가 드러나는 평가셋

이것저것 고민하다 보니 좋은 평가셋의 조건은 의외로 단순했다 — 약점이 드러나야 한다.

 

너무 쉬운 셋은 무슨 방법을 써도 다 통과해서 변별력이 없고, 너무 어려운 셋은 다 틀려서 역시 변별력이 없다. 그래서 하나로 통일하려던 생각을 접고, 용도·난이도별로 나눠 운영하게 됐다.

AutoRAGRetrieval은 임베딩 모델 비교 전용이라 증강 검증엔 맞지 않았고, MIRACL ko는 문장형이라 raw_query baseline이 너무 높아 변별력이 낮았다. 그래서 실사용 질의에 가까운 자체 평가셋을 난이도별로 나눠 만들었다.

 

빠른 확인용 표준 셋, 역순·외래어 변형을 넣어 변별력을 높인 어려운 셋(주력), 그리고 운영 회귀 비교용 셋이다.

 

같은 점수라도 어느 셋에서 나온 점수냐에 따라 해석을 달리해야 했다. 표준 셋에서 90%는 "기본은 한다"는 뜻이지만, 어려운 셋에서 90%라야 진짜 강한 알고리즘이다.

마치며

검색을 개선하려고 시작했는데, 정작 가장 먼저 한 일은 측정하는 자(자판)부터 다시 만드는 것이었다. 돌아보면 당연한 순서였다. 자가 흔들리면 어떤 개선도 증명할 수 없으니까.

 

평가셋을 정리하고 나서야 비로소 검색을 제대로 들여다볼 수 있었다. 그리고 그렇게 들여다보기 시작하니, 문제는 검색기 자체보다 그 앞단의 질의처리에 있다는 게 보였다. 다음 글에서는 그 이야기를 적는다.


오랜만에 글을 쓰는데 AI의 도움을 받아 글을 쓰니 글 쓰는 허들이 많이 낮아진 느낌이 든다.

비슷한 내용들로 3~4부작으로 쓸 거 같다.