한국어 하이브리드 검색의 도전
Databricks Vector Search의 한국어 제약
Databricks Vector Search의 Full Text Search (Beta) 기능은 현재 Standard(영어) 분석기 만 지원합니다. 이는 한국어 환경에서 심각한 검색 품질 저하를 초래합니다.한국어 형태소 분석의 중요성
한국어는 교착어 로, 어근에 조사/어미가 결합되어 하나의 어절을 형성합니다. 형태소 분석 없이는 올바른 키워드 검색이 불가능합니다. 아래 예시를 통해 Standard 분석기와 한국어 형태소 분석기(Nori)의 차이를 비교합니다.| 입력 텍스트 | Standard 분석기 | Nori 분석기 |
|---|---|---|
| ”동해물과 백두산이” | ["동해물과", "백두산이"] (2토큰) | ["동해", "물", "과", "백두", "산", "이"] (6토큰) |
| “마르고 닳도록” | ["마르고", "닳도록"] (2토큰) | ["마르", "고", "닳", "도록"] (4토큰) |
- 사용자가 “동해” 로 검색
- Standard 인덱스에는
"동해물과"라는 토큰만 존재 "동해"!="동해물과"→ 매칭 실패- Nori 인덱스에는
"동해"토큰이 별도로 존재 → 매칭 성공
주의 Standard 분석기의 한국어 처리 문제: Standard 분석기는 공백과 구두점 기반으로만 토큰을 분리합니다. 한국어의 조사(이/가/을/를/에서), 어미(~하다/~한/~했던) 등을 분리하지 못하므로, 형태소 단위 검색이 사실상 불가능합니다.
오픈소스 한국어 형태소 분석기 비교
한국어 하이브리드 검색을 구현하려면 적절한 형태소 분석기를 선택해야 합니다. 아래 표는 주요 오픈소스 분석기를 비교합니다.| 분석기 | 개발 언어 | 속도 | 정확도 | 특징 | 추천 용도 |
|---|---|---|---|---|---|
| Mecab-ko | C++ | 매우 빠름 | 보통~높음 | 일본어 Mecab 포팅. CRF 기반. 설치가 까다로움 (C++ 빌드 필요) | 대용량 빠른 처리, 서버 환경 |
| Kiwi | C++ | 빠름 | 높음 | 최근 가장 활발한 개발. 띄어쓰기/오탈자 자동 교정. pip install kiwipiepy로 간편 설치 | RAG 추천. 신조어 많은 데이터, Databricks 환경 |
| Okt (Open Korean Text) | Scala/Java | 빠름 | 보통 | 트위터(X) 한국어 분석기 기반. 비표준어/신조어에 강함 | SNS, 구어체, 채팅 데이터 |
| Komoran | Java | 보통 | 보통 | 순수 자바 구현. 외부 의존성 없음 | Java 기반 시스템 |
| Hannanum | Java | 느림 | 높음 | KAIST 개발. 학술적으로 정확 | 학술 연구, 정확성 우선 |
참고
Databricks 환경에서의 추천: Kiwi 를 권장합니다. pip install kiwipiepy만으로 설치가 완료되고, C++ 바인딩으로 속도가 빠르며, 띄어쓰기 오류와 오탈자를 자동 교정하는 기능이 있어 실무 데이터에 강합니다.
Kiwi 형태소 분석기 활용 예제
Retriever 유형 비교
| Retriever | 방식 | 장점 | 단점 | 적합 시나리오 |
|---|---|---|---|---|
| Dense Retriever | 벡터 유사도 검색 (임베딩) | 의미적 유사성 포착, 동의어 처리 | 정확한 키워드 매칭 약함 | 일반 Q&A, 자연어 질의 |
| Sparse Retriever(BM25/TF-IDF) | 키워드 빈도 기반 검색 | 정확한 용어 매칭, 빠른 속도 | 동의어·문맥 이해 불가 | 전문 용어, 코드 검색 |
| Hybrid Retriever | Dense + Sparse 결합 | 두 방식의 장점 통합 | 가중치 튜닝 필요 | 대부분의 프로덕션 환경 |
| Multi-Query Retriever | 하나의 질문을 여러 쿼리로 변환 | 검색 recall 향상 | LLM 호출 비용 추가 | 복잡한 질문, 모호한 질의 |
| Parent Document Retriever | 작은 청크로 검색, 큰 문서로 반환 | 검색 정밀도 + 풍부한 컨텍스트 | 인덱스 구조 복잡 | 긴 문서 기반 Q&A |
| Self-Query Retriever | 메타데이터 필터를 자동 추출 | 구조화된 필터링 가능 | LLM 의존, 메타데이터 설계 필요 | 날짜·카테고리 기반 필터링 |
참고 실무에서는 Hybrid Retriever + Reranking 조합이 가장 균형 잡힌 성능을 제공합니다. 단일 Retriever만으로는 다양한 쿼리 패턴을 커버하기 어렵습니다.
하이브리드 검색이 왜 순수 벡터 검색보다 나은가
순수 벡터 검색(Dense Retrieval)만으로는 모든 쿼리 패턴을 커버하기 어렵습니다. 구체적인 한계를 살펴봅시다.Dense Retrieval의 약점
| 쿼리 유형 | 예시 | Dense 검색 결과 | 문제 |
|---|---|---|---|
| 정확한 용어 매칭 | ”에러 코드 DELTA_TABLE_NOT_FOUND” | 유사한 의미의 문서를 반환하지만 정확한 에러 코드 포함 문서를 놓침 | 임베딩은 의미를 압축하므로 특정 문자열 매칭에 약함 |
| 약어/코드명 | ”DBSQL” 또는 “UC" | "Databricks SQL”이나 “Unity Catalog”과 연결하지 못할 수 있음 | 약어와 풀네임의 임베딩 거리가 멀 수 있음 |
| 숫자/버전 검색 | ”DBR 15.4” | 다른 DBR 버전 문서를 반환 | 숫자의 미세한 차이를 구별하기 어려움 |
| 불용어 의존 쿼리 | ”NOT” 조건 포함 질문 | 부정 의미를 무시하고 관련 문서를 반환 | 임베딩은 부정 표현을 잘 반영하지 못함 |
Hybrid 검색이 해결하는 문제
하이브리드 검색은 Dense (의미 이해) + Sparse (정확 매칭) 을 결합하여 양쪽의 약점을 보완합니다:- Dense가 강한 경우: “데이터 품질을 관리하는 방법” → 의미적으로 유사한 “데이터 거버넌스”, “데이터 검증” 문서를 찾음
- Sparse가 강한 경우: “DELTA_TABLE_NOT_FOUND 해결법” → 정확히 해당 에러 코드가 포함된 문서를 찾음
- 둘 다 필요한 경우: “Unity Catalog에서 외부 테이블 접근 권한 에러 수정” → 의미 검색 + 키워드 매칭 조합
하이브리드 검색 핵심 개념 3가지
하이브리드 검색을 제대로 구현하려면 조합, 정규화, 가중치 라는 3가지 핵심 개념을 반드시 이해해야 합니다.조합 (Combination)
두 가지 이상의 검색 결과를 하나로 합치는 방법입니다.- 순위 기반 (Rank-based): 각 문서의 실제 점수를 무시하고, “몇 등인가” 만 봅니다. 대표적으로 RRF (Reciprocal Rank Fusion) 가 있습니다. RRF는 각 검색 시스템에서 문서가 받은 순위의 역수(1/순위)를 합산하여 최종 점수를 구합니다. 예를 들어 벡터 검색에서 2등, 키워드 검색에서 3등인 문서는
1/2 + 1/3 = 0.83의 점수를 받습니다. 점수가 아닌 순위만 사용하기 때문에, 서로 다른 스케일의 검색 시스템을 정규화 없이 통합할 수 있어 가장 안정적입니다. (자세한 수식과 계산 예시는 아래 RRF 상세 섹션을 참조) - 점수 기반 (Score-based): 각 검색 시스템의 실제 유사도 점수를 활용하여 가중 합산합니다. RRF보다 정밀할 수 있지만, 벡터 검색(0
1 범위)과 BM25(0무한대 범위)처럼 점수 스케일이 다른 시스템을 합산하려면, 정규화(Normalization) 로 스케일을 통일하는 작업이 반드시 선행되어야 합니다. 정규화 없이 합산하면 BM25 점수가 압도적으로 커서 벡터 검색 결과가 사실상 무시됩니다.
정규화 (Normalization)
서로 다른 두 검색 시스템의 점수 스케일을 동일한 범위로 맞추는 작업입니다. 점수 기반 조합을 사용할 때 필수적 입니다.- 벡터 검색 점수: 코사인 유사도 기준 0.0 ~ 1.0 (비교적 좁은 범위)
- BM25 점수: 0.0 ~ 무한대 (문서 길이, 용어 빈도에 따라 크게 변동)
- 이 두 점수를 직접 비교하면, BM25 점수가 압도적으로 크므로 벡터 검색 결과가 사실상 무시됨
| 정규화 방법 | 수식 | 특징 |
|---|---|---|
| Min-Max | (x - min) / (max - min) | 가장 직관적. 0~1 범위로 변환. 이상치에 민감 |
| L2 (유클리드) | x / sqrt(sum(x^2)) | 벡터 정규화에 적합. 크기 보존 |
| Z-score | (x - mean) / std | 평균 0, 표준편차 1로 변환. 분포 기반 |
가중치 (Weight)
각 검색 기법의 중요도(비중) 를 비즈니스 요건에 맞게 조정합니다.- 정확한 결과가 중요할 때(에러 코드, 법령 번호 검색): 키워드 검색 가중치를 높게 (예: keyword 0.7, semantic 0.3)
- 다양한 표현을 지원할 때(일반 Q&A, 자연어 질의): 시맨틱 검색 가중치를 높게 (예: keyword 0.3, semantic 0.7)
- 균형 잡힌 검색: 동일 가중치 (keyword 0.5, semantic 0.5)
참고 가중치는 고정값이 아닙니다. 도메인과 쿼리 패턴에 따라 최적값이 달라지므로, 평가 데이터셋을 활용한 실험을 통해 튜닝해야 합니다.
RRF (Reciprocal Rank Fusion) 상세
RRF는 하이브리드 검색에서 가장 널리 사용되는 결과 조합 알고리즘입니다. 핵심 수식은 다음과 같습니다.rank_i(d): i번째 검색 시스템에서 문서 d의 순위 (1부터 시작)rank_constant: 상수 (기본값 60). 순위가 낮은 문서의 영향력을 조절weight_i: i번째 검색 시스템의 가중치
- 점수의 절대값이 아니라 순위 만 사용하므로, 서로 다른 스케일의 검색 시스템을 정규화 없이 통합 가능
- Databricks Vector Search의
query_type="hybrid"가 내부적으로 RRF를 사용 - 구현이 간단하고, 대부분의 경우 점수 기반 방법과 비슷하거나 더 나은 성능
앙상블 Retriever (Ensemble Retriever)
개념
앙상블 Retriever는 서로 다른 특성의 Retriever를 결합하여 각각의 약점을 보완합니다. 가장 일반적인 조합은 BM25 (키워드) + Vector Search (의미) 입니다.Reciprocal Rank Fusion (RRF) 알고리즘
앙상블 Retriever는 RRF 알고리즘으로 결과를 병합합니다:k: 상수 (기본값 60), 순위가 낮은 문서의 영향력 조절rank_i(d): i번째 Retriever에서 문서 d의 순위- 여러 Retriever에서 모두 높은 순위를 받은 문서가 최종 상위로 올라감
가중치 조절
weights=[0.5, 0.5]: 두 Retriever를 동등하게 반영weights=[0.7, 0.3]: BM25 비중을 높이면 정확한 키워드 매칭 강화weights=[0.3, 0.7]: Vector Search 비중을 높이면 의미적 유사성 강화
LangChain EnsembleRetriever 코드 예제
LangChain의 EnsembleRetriever 는 여러 리트리버를 하나로 묶어 하이브리드 검색을 수행하며, 각 리트리버에 개별 가중치를 부여할 수 있습니다.주의 Databricks Vector Search 하이브리드 검색의 제약사항:
- Databricks VS의 “Hybrid Search”는 Dense (임베딩 유사도) + 키워드 필터 를 결합하는 방식이며, 전통적인 BM25 Sparse Retrieval과는 다릅니다
- 내장 키워드 검색은 영어 기반 토크나이저 를 사용하여, 한국어 형태소를 제대로 분리하지 못함
- 따라서 한국어 환경에서는 VS 내장 하이브리드보다 외부 BM25 (Kiwi 기반) + VS Dense를 EnsembleRetriever로 결합 하는 것이 더 효과적
- 소규모 문서 (10만건 이하): LangChain BM25Retriever (Kiwi 토크나이저) + VS Dense → EnsembleRetriever
- 대규모 문서: Elasticsearch/OpenSearch에 Kiwi 분석기 설정 → BM25 서빙 + VS Dense → EnsembleRetriever
- VS만 사용: 임베딩 모델을 한국어에 강한 모델(bge-m3, multilingual-e5)로 선택하여 Dense 검색 품질을 최대한 높임
Multi-Query Retriever 예제
하나의 질문을 LLM이 여러 관점의 쿼리로 변환하여 검색 recall을 높입니다:Databricks에서 한국어 하이브리드 검색 구현
솔루션 아키텍처: 9단계 워크플로
한국어 하이브리드 검색을 Databricks 환경에서 구현하기 위한 전체 파이프라인은 다음 9단계로 구성됩니다.| 단계 | 작업 | 설명 | 도구/기술 |
|---|---|---|---|
| 1 | PDF 파싱 + 청킹 | 원본 문서를 파싱하고 적절한 크기로 분할 | Unstructured, PyMuPDF, LangChain TextSplitter |
| 2 | 한국어 형태소 분석 | 오픈소스 분석기로 청크 텍스트를 형태소 단위로 분리 | Kiwi (추천), Mecab-ko, Okt |
| 3 | 원본 텍스트 저장 | 원본 청크 텍스트를 content_raw 컬럼에 저장 | Delta Lake |
| 4 | 분석된 텍스트 저장 | 형태소 분석된 텍스트를 content_analyzed 컬럼에 저장 | Delta Lake |
| 5 | 벡터 임베딩 생성 | 원본 텍스트를 임베딩하여 content_vector 컬럼에 저장 | bge-m3, multilingual-e5 |
| 6 | 키워드 검색 실행 | 분석된 텍스트 컬럼 대상 Full Text Search (Custom Retriever) | BM25Retriever + Kiwi |
| 7 | 벡터 검색 실행 | 벡터 컬럼 대상 의미 검색 | Databricks Vector Search |
| 8 | 결과 조합 | RRF 기반 검색 결과 병합 | EnsembleRetriever |
| 9 | 최종 결과 반환 | 조합된 결과를 LLM에 전달 | LangChain Chain |
Databricks Vector Search 한국어 설정
한국어 Custom BM25 Retriever 구현
Databricks Vector Search Hybrid Query 활용
Databricks Vector Search 자체의 hybrid 쿼리도 활용할 수 있습니다. 영어 콘텐츠가 혼합된 경우 유용합니다.참고 Databricks Vector Search 인덱스 생성 시default_language = "KOREAN"설정과, 데이터 싱크 시Language = ["KOREAN", "ENGLISH"]설정을 통해 한국어 지원을 활성화할 수 있습니다. 단, 현재 Beta 단계이므로 형태소 분석 품질은 외부 분석기(Kiwi)에 비해 제한적입니다.