[RAG] Re-ranking 도입 전후 성능 평가: 왜 단순히 상위 K개만 뽑으면 안 되는가?

검색 품질은 생각보다 쉽게 무너집니다. 벡터 검색을 붙이면 좋아질 줄 알았는데 실제 운영에서는 전혀 다른 문제가 나오더군요. 특히 상위 K개만 가져오는 방식은 생각보다 많은 문제를 만듭니다. 

Re ranking 도입 전 운영에서 발생했던 검색 품질 문제

Re ranking 이야기를 하려면 먼저 왜 필요한지부터 말씀드리는 게 좋겠습니다. 벡터 검색을 처음 붙이면 대부분 Top K 방식으로 결과를 가져옵니다. 저희도 Elasticsearch 기반 검색에 벡터 검색을 붙이면서 단순히 상위 K개 결과만 가져오는 구조로 시작했습니다.

초기에는 문제가 없어 보였습니다. 검색 latency는 평균 70ms 정도였고 RPS는 150 수준이었습니다. 그런데 서비스가 커지면서 문서 수가 300만 건을 넘기기 시작하더군요. 그때부터 검색 결과 품질에 대한 문의가 계속 올라오기 시작했습니다.

체감상 이상했습니다. 벡터 유사도 점수는 높은데 사람이 보기에는 전혀 관련 없는 결과가 상단에 올라오는 경우가 꽤 많았습니다. 이거 운영에서 한번 터져보면 기억에 남습니다. 검색이 틀리면 사용자 신뢰도가 바로 떨어지기 때문입니다.

 

단순 Top K 검색 구조의 운영 Pain Point

당시 검색 아키텍처는 굉장히 단순했습니다. 벡터 검색으로 유사도 상위 10개를 가져오고 그대로 API 응답으로 내려보내는 구조였습니다. 코드도 단순했고 latency도 낮았습니다.

문제는 정확도였습니다. 실제 로그를 분석해 보니 상위 3개 결과 중 1개 이상이 사용자가 기대한 결과가 아닌 경우가 약 28퍼센트 정도였습니다. 생각보다 높은 수치였습니다.

트래픽은 당시 RPS 120에서 200 사이였습니다. 검색 인덱스 문서는 약 500만 건이었고 하루 검색 요청은 약 900만 건 정도였습니다. 이런 상황에서 검색 정확도가 떨어지니 고객센터 문의가 계속 늘어나더군요.

특히 이런 문제가 자주 발생했습니다. 질문과 의미적으로는 맞지만 실제로는 덜 관련된 문서가 위에 올라오는 상황입니다. 벡터 모델 특성상 이런 일이 생각보다 자주 발생합니다. 

 

Top K 방식에서 발생하는 대표적인 문제

첫 번째 문제는 의미 유사도만으로 순위를 결정한다는 점입니다. 벡터 모델은 문장 의미 유사도를 계산하지만 실제 검색 의도까지 완벽하게 반영하지는 못합니다.

두 번째 문제는 미세한 점수 차이입니다. 상위 결과들의 벡터 점수 차이는 대부분 매우 작습니다. 실제 로그를 보면 상위 10개 결과 점수 차이가 0.01 수준인 경우도 많았습니다.

모델이 판단한 유사도 순서가 사람이 기대하는 순서와 달라집니다. 검색 품질 문제는 대부분 여기서 시작됩니다.

Re ranking 도입을 고민했던 의사결정 과정

이 문제를 해결하기 위해 내부에서 두 가지 접근 방법을 고민했습니다. 

 

방법 A 벡터 모델을 더 좋은 모델로 교체

첫 번째 방법은 단순했습니다. 더 좋은 임베딩 모델을 사용하는 것입니다. 모델 성능이 좋아지면 검색 품질도 좋아질 것이라는 접근입니다.

장점은 구조 변경이 거의 없다는 점입니다. 기존 검색 파이프라인을 그대로 유지할 수 있습니다. 운영 난이도도 크게 올라가지 않습니다.

단점도 명확했습니다. 모델 교체 비용이 생각보다 큽니다. 임베딩 재생성 비용이 발생합니다. 문서가 500만 건이면 임베딩 재생성만 해도 몇 시간 작업입니다.

 

방법 B Re ranking 레이어 추가

두 번째 방법은 Re ranking 레이어를 추가하는 방식입니다. 벡터 검색으로 Top 50 정도를 가져온 뒤 별도의 모델로 다시 순위를 정렬하는 방식입니다.

장점은 검색 정확도가 크게 올라간다는 점입니다. 실제 논문에서도 효과가 검증된 방식입니다. 특히 문장 이해 기반 모델을 사용하면 결과 품질이 상당히 개선됩니다.

추가 모델 추론이 들어가기 때문에 응답 시간이 늘어납니다. 운영 비용도 증가합니다. GPU나 추가 CPU 리소스가 필요합니다.

결국 저희는 Re ranking 방식을 선택했습니다. 이유는 단순합니다. 검색 품질 문제가 고객 경험에 직접 영향을 주고 있었기 때문입니다. 

 

Re ranking 실제 구현 구조

최종적으로 선택한 구조는 두 단계 검색 파이프라인입니다. 1차 검색은 Elasticsearch 벡터 검색입니다. 여기서 Top 50 문서를 가져옵니다.

그 다음 Re ranking 모델이 다시 순서를 정렬합니다. 최종적으로 Top 5만 API 응답으로 반환합니다. 구조 자체는 단순합니다. 하지만 운영에서 고려할 점이 꽤 있습니다.


# search pipeline example

search request
  |
  | vector search
  v
elasticsearch
  |
  | top 50 documents
  v
rerank service
  |
  | rerank model inference
  v
top 5 results

Spring Boot 검색 서비스 구현 예시

실제 서비스 코드는 이런 형태였습니다. 먼저 Elasticsearch에서 Top K 결과를 가져옵니다. 이때 K 값을 너무 작게 잡으면 Re ranking 효과가 떨어집니다.


public List search(String query) {

    // vector search
    List<SearchResult> candidates = elasticsearchRepository
            .vectorSearch(query, 50); 

    // rerank step
    List<SearchResult> reranked = rerankService
            .rerank(query, candidates);

    return reranked.stream()
            .limit(5)
            .toList();
}

여기서 중요한 포인트가 있습니다. Top 50 정도는 가져와야 Re ranking 모델이 의미 있는 재정렬을 할 수 있습니다. Top 10만 가져오면 사실상 효과가 거의 없습니다. 

 

Re ranking 도입 이후 실제 성능 변화

Re ranking을 도입한 뒤 검색 품질은 꽤 개선되었습니다. 내부 평가 기준으로 Top 3 정확도가 약 62퍼센트에서 83퍼센트 수준으로 올라갔습니다.

대신 latency는 증가했습니다. 평균 검색 응답 시간이 70ms에서 140ms 정도로 늘어났습니다. 두 배 정도 증가했습니다.

다행히 API SLA가 300ms였기 때문에 운영에는 큰 문제는 없었습니다. 오히려 고객 문의가 눈에 띄게 줄어들었습니다. 검색 품질이 좋아지니 사용자 만족도가 올라갔습니다.

 

Re ranking 도입에 대한 현실적인 결론

Re ranking은 분명 검색 품질을 개선하는 데 도움이 됩니다. 하지만 이것 하나로 모든 문제가 해결되지는 않습니다. 실제 운영에서는 여러 가지 추가 튜닝이 필요합니다.

예를 들어 Top K 값 조정도 중요합니다. 너무 작으면 효과가 없고 너무 크면 latency가 급격히 증가합니다. 운영 환경에 맞는 균형을 찾는 과정이 필요합니다.

또 하나 말씀드리면 Re ranking 모델도 완벽하지 않습니다. 결국 데이터 품질과 검색 로그 분석이 계속 필요합니다.