티스토리 뷰

 

BM25 글에서 키워드 검색을 다뤘다. 정확히 같은 단어로 물어보면 강하다. 그런데 "회의 자료"로 색인된 문서를 누가 "미팅 정리본"이라고 검색하면? 단어가 안 겹쳐서 못 찾는다. 키워드 검색의 천장이 여기다. 이걸 벡터(임베딩) 검색이 메워준다 — 단어가 달라도 의미가 가까우면 잡는다. 그럼 둘을 합치면 되지 않나? 그게 이번 글, 하이브리드 검색이다.

 

이 글은 RAG 구축 고려사항에서 1차 검색을 완성하는 자리다. 다음 글에선 이 1차 위에 리랭커(2차)를 얹는다.

1. 두 검색은 강점이 다르다 — 키워드 vs 벡터

키워드 검색(BM25)은 어휘 일치다. 질의의 단어가 문서에 그대로 있으면 점수가 붙는다.

 

그래서 파일명이나 고유한 용어처럼 "딱 그 단어"를 찾을 땐 거의 안 틀린다. 대신 같은 뜻 다른 표현엔 약하다. "기획서"와 "제안서", "미팅"과 "회의"를 서로 다른 단어로 본다.

 

벡터 검색은 반대다. 문장을 임베딩 모델로 벡터(의미 좌표)로 바꿔, 질의 벡터와 가까운 문서를 찾는다. 단어가 달라도 의미가 가까우면 잡아낸다 — "미팅 정리본"으로 "회의 자료"를 찾아준다. 대신 정확한 매칭이나 희귀한 고유어에선 흐릿해지고, 의미가 비슷한 엉뚱한 문서를 끌고 오기도 한다.

질의: "미팅 정리본"      정답 문서: "회의 자료"
─────────────────────────────────────────────
키워드(BM25)   단어 안 겹침 → 못 찾음          (정확엔 강, 표현 변형엔 약)
벡터(임베딩)   의미가 가까움 → 찾아냄          (의미엔 강, 정확 매칭엔 약)

핵심은 한쪽이 약한 자리에서 다른 쪽이 강하다는 점이다. 그래서 둘 중 하나를 고르는 게 아니라, 합치자는 발상이 나온다.

2. 어떻게 합치나 — 점수 정규화의 함정, 그리고 RRF

합치려니 문제가 하나 있다. 두 검색의 점수가 서로 다른 자로 잰 값이라는 것. BM25 점수는 위로 열려 있어(이론상 상한이 없다) 질의·코퍼스마다 범위가 들쭉날쭉한데, 벡터 코사인 유사도는 -1에서 1 사이에 갇혀 있다. 스케일도 분포도 다르니, 그냥 더하면 큰 숫자를 내는 쪽(보통 BM25)이 다른 쪽을 통째로 잡아먹는다.

 

가장 먼저 떠오르는 해법은 점수 정규화다. 각 검색의 점수를 0~1 같은 공통 범위로 눌러 맞춘 뒤 더하자는 것(min-max, z-score 같은 방식). 그럴듯한데, 막상 해보면 정규화가 새 문제를 만든다.

 

문제는 정규화 기준이 그 질의의 결과 분포에 통째로 휘둘린다는 점이다. min-max는 그 결과 집합의 최댓값·최솟값에 맞춰 누르는데, 점수 하나만 유난히 높아도(이상치) 나머지가 전부 바닥으로 깔린다.

질의 A의 BM25 점수:  [30.0,  2.1,  2.0,  1.9]   ← 1등만 유난히 튐
   min-max 정규화 →  [1.00, 0.007, 0.003, 0.0]
   2~4등은 멀쩡한 후보인데 0에 수렴 → 사실상 버려짐

게다가 이 기준이 질의마다 달라서, 똑같은 정규화 점수 0.5라도 어떤 질의에선 좋은 점수고 어떤 질의에선 형편없는 점수가 된다. 질의를 가로질러 비교가 안 되는 값이 되는 것이다. 정규화 방식을 고르고 맞추는 일도 또 다른 손이고.

 

RRF(Reciprocal Rank Fusion)는 이걸 통째로 우회한다. 점수를 아예 안 본다. 각 검색에서 몇 등을 했는지, 그 순위만 가져다 1/(k+순위)로 점수를 매겨 합산한다. 순위는 스케일도 분포도 없는 값이라(1등은 어느 검색에서나 그냥 1등이다), 정규화가 풀려던 문제 자체가 사라진다. k는 상위 순위가 과도하게 지배하지 않게 눌러주는 완충값이다(흔히 60을 쓴다).

질의 → 키워드 검색 → [랭킹 A]  ┐
                              ├─→ 순위로 합산: Σ 1/(k+순위) → 최종 순위
질의 → 벡터 검색   → [랭킹 B]  ┘

물론 RRF도 공짜는 아니다. 점수를 버리는 만큼 얼마나 더 좋은지(1등이 2등을 압도하는지, 간발의 차인지)라는 크기 정보를 잃는다. 그래도 정규화의 취약함을 떠안느니, 단순하고 분포에 안 휘둘리는 순위 융합을 기본으로 두는 편이 실전에선 더 잘 버텼다.

 

여기서 한쪽에 가중치를 둬서 "벡터를 얼마나 반영할지"를 조절한다. 그런데 이 가중치가, 다음 장의 진짜 골칫거리다.

3. 얼마나 섞을까 — 정답은 도메인마다 다르다

처음엔 "벡터를 많이 섞을수록 똑똑해지겠지" 했다. 아니었다. 벡터 가중을 올릴수록 top1(맨 위 정답률)이 오히려 떨어졌다. 의미는 넓게 잡지만, 키워드가 딱 맞히던 1등을 의미적으로 비슷한 다른 문서가 밀어내는 것이다. 반대로 벡터를 너무 줄이면 recall(정답이 후보 안에 드는 비율)에서 손해를 봤다.

 

그러니까 하이브리드는 "더하면 좋아지는" 게 아니라 균형을 맞추는 일이었다. 벡터를 적당히 낮게 섞은 지점에서 top1과 recall이 같이 사는 정점이 나왔고, 과하게 섞으면 오히려 해로웠다.

 

그리고 중요한 건, 그 정점이 도메인마다 다르다는 것이다. 파일명·키워드로 찾는 질의가 많은 데이터면 벡터 비중을 낮게, 자연어로 풀어 묻는 질의가 많으면 좀 더 높게 — 최적 가중치가 데이터 성격을 탄다.

 

그래서 가중치는 미리 정해 박는 값이 아니라, 그 도메인의 실제 질의로 테스트하며 찾아가는 값이었다. 같은 가중치를 다른 데이터에 그대로 옮기면 안 맞는다. 평가셋을 들고 가중치를 조금씩 바꿔가며 top1·recall이 어디서 제일 좋은지 재보는, 손이 가는 튜닝이 필요했다.

 

4. 공짜가 아니다 — 의미를 얻는 대신, 모든 파일을 임베딩해야 한다

여기까지면 "그럼 무조건 하이브리드네" 싶은데, 벡터를 더하는 데는 분명한 값이 따른다. 이게 이 글에서 제일 정직하게 적고 싶은 부분이다.

 

벡터 검색이 의미를 잡으려면, 검색 대상이 되는 모든 파일을 미리 임베딩해 둬야 한다. 키워드 검색은 단어만 색인하면 되지만, 벡터는 문서 하나하나를 임베딩 모델에 통과시켜 벡터로 만들어 저장해야 한다. 코퍼스가 크면 이 선행 작업이 그만큼 길어지고, 새 문서가 들어올 때마다 또 임베딩해야 한다. "한 번 켜면 끝"이 아니라 계속 따라붙는 비용이다.

 

게다가 그 임베딩 모델이 검색하는 내내 메모리에 떠 있어야 한다. 질의가 들어올 때마다 질의를 즉석에서 임베딩해야 하니까. 서버면 모를까, 온디바이스에선 이게 부담이다 — 키워드 검색기·앱과 같은 RAM을 나눠 쓰는데 임베딩 모델 하나가 수백 MB에서 GB 단위를 차지한다. 자원이 빠듯하면 모델이 메모리에서 밀려 내려가는 일까지 생긴다.

 

그래서 트레이드오프가 분명하다.

얻는 것    의미 검색 — 단어가 달라도 뜻으로 찾는다
치르는 값  · 전체 코퍼스 선행 임베딩 (+ 신규 문서마다 추가)
           · 임베딩 모델 상시 메모리 상주
           · 질의마다 임베딩하는 지연

결정적으로, 이 값을 치른다고 정확도가 반드시 오르는 것도 아니다.

 

키워드만으로 이미 잘 찾히는 질의·도메인이라면, 벡터를 더해 얻는 이득이 그 비용을 못 넘는다. "의미 검색이 되니까 좋다"가 아니라, "이 메모리와 이 임베딩 비용을 치를 만큼 의미 검색이 값을 하나"를 따져야 했다.

5. 그래서 언제 켜나 — 조건부 이득

정리하면 하이브리드는 만능이 아니라 조건부였다.

자연어로 풀어 묻고, 같은 뜻을 여러 표현으로 찾는 일이 잦다
   → 벡터가 값을 한다. 하이브리드 ㅇㅋ

대부분 파일명·정확한 키워드로 찾고, 표현 변형이 적다
   → 키워드 검색만으로 충분. 임베딩 비용을 안 치르는 BM25 단독도 합리적

실제로 어떤 환경에선 "굳이 임베딩 모델까지 올릴 이유가 없다"는 판단으로 키워드 단독을 택하기도 했다. 하이브리드가 더 고급이라서 항상 옳은 게 아니라, 데이터와 질의 성격에 맞는가의 문제였다.

마치며

하이브리드는 키워드의 정확함과 벡터의 의미를 한 검색에 합쳐, 1차 검색을 완성하는 단계였다. 다만 그 "의미"는 공짜가 아니라 전체 임베딩과 상시 메모리라는 값을 요구했고, 그 값이 늘 회수되는 것도 아니었다.

 

가중치도 도메인마다 다시 맞춰야 했고. 결국 또 같은 결론이다 — 더 좋은 기법이냐*가 아니라 *이 비용으로 어디에 쓰느냐. 이렇게 다듬은 1차 검색 위에, 다음 글에선 상위 후보만 다시 정밀 채점하는 리랭커(2차)를 얹는다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/07   »
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
글 보관함