키워드 검색에서 시맨틱 검색, 하이브리드 검색으로 이어지는 검색 기술의 진화 과정과 AI 검색 시스템의 핵심 구성요소를 살펴봅니다.
검색 기술은 크게 세 가지 패러다임을 거쳐 발전해 왔습니다. 각 단계는 이전 방식의 한계를 극복하면서 등장했으며, 현대 검색 시스템은 이 세 가지를 모두 활용하는 방향으로 진화하고 있습니다.
가장 오래되고 널리 사용된 방식은 키워드 검색(Keyword Search)입니다. 사용자가 입력한 검색어와 문서에 포함된 단어를 직접 대조하여 결과를 반환합니다. 대표적인 알고리즘은 BM25로, TF-IDF를 개선하여 단어 빈도와 문서 길이를 함께 고려합니다.
import math
def bm25_score(term_freq, doc_length, avg_doc_length, doc_freq, total_docs, k1=1.2, b=0.75):
"""BM25 스코어링 함수"""
idf = math.log((total_docs - doc_freq + 0.5) / (doc_freq + 0.5) + 1)
tf_norm = (term_freq * (k1 + 1)) / (term_freq + k1 * (1 - b + b * (doc_length / avg_doc_length)))
return idf * tf_normBM25는 빠르고 예측 가능하다는 장점이 있지만, 근본적인 한계를 가지고 있습니다. "자동차 수리"를 검색했을 때 "차량 정비"라는 표현이 포함된 문서를 찾지 못합니다. 동의어, 유의어, 맥락적 의미를 전혀 이해하지 못하기 때문입니다.
시맨틱 검색(Semantic Search)은 텍스트의 의미를 벡터 공간에 매핑하여 검색하는 방식입니다. 임베딩 모델(Embedding Model)이 텍스트를 고차원 벡터로 변환하고, 벡터 간의 거리(유사도)를 기반으로 관련 문서를 찾습니다.
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer("all-MiniLM-L6-v2")
query = "자동차 수리 방법"
documents = [
"차량 정비 가이드: 엔진 오일 교환 절차",
"오늘의 날씨 예보",
"자동차 고장 진단과 수리 매뉴얼",
]
query_embedding = model.encode(query)
doc_embeddings = model.encode(documents)
# 코사인 유사도 계산
similarities = np.dot(doc_embeddings, query_embedding) / (
np.linalg.norm(doc_embeddings, axis=1) * np.linalg.norm(query_embedding)
)
for doc, score in sorted(zip(documents, similarities), key=lambda x: x[1], reverse=True):
print(f"{score:.4f} | {doc}")이 방식에서는 "자동차 수리"와 "차량 정비"가 의미적으로 가까운 벡터로 표현되므로, 정확한 단어가 일치하지 않아도 관련 문서를 찾을 수 있습니다.
하이브리드 검색(Hybrid Search)은 키워드 검색과 시맨틱 검색을 결합합니다. 각 방식의 강점을 취하고 약점을 보완하는 전략입니다. 예를 들어 제품 코드나 고유명사처럼 정확한 매칭이 필요한 경우에는 BM25가, 의미적 유사성이 중요한 경우에는 시맨틱 검색이 더 효과적입니다.
키워드 기반 검색은 수십 년간 정보 검색의 표준이었지만, 다음과 같은 근본적 한계를 갖고 있습니다.
어휘 불일치 문제(Vocabulary Mismatch Problem): 같은 개념을 다른 단어로 표현하면 검색에 실패합니다. "머신러닝"과 "기계학습", "딥러닝"과 "심층학습"처럼 한국어 환경에서는 영어 용어와 한국어 번역어가 혼용되므로 이 문제가 더 심각합니다.
의도 파악 불가: "사과"를 검색했을 때 과일인지, 사과(謝過)인지 구분하지 못합니다. 검색어 자체만으로는 사용자의 의도를 파악할 수 없습니다.
문맥 무시: 문서 전체의 맥락이 아닌 개별 단어의 출현 여부만 판단합니다. 긴 문서에서 특정 단어가 한 번 등장한 것과 핵심 주제로 반복 등장한 것을 동일하게 취급할 수 있습니다.
랭킹의 한계: BM25 점수는 통계적 단어 빈도에 기반하므로, 사용자가 실제로 원하는 "관련성"과 괴리가 있을 수 있습니다.
이러한 한계는 단순히 알고리즘을 개선한다고 해결되지 않습니다. 텍스트의 "의미"를 이해하는 근본적으로 다른 접근이 필요했고, 그것이 바로 임베딩 기반 시맨틱 검색입니다.
현대 AI 검색 시스템은 네 가지 핵심 구성요소로 이루어져 있습니다.
임베딩(Embedding)은 텍스트를 고정 길이의 숫자 벡터로 변환하는 과정입니다. BERT, Sentence-BERT, E5, BGE 등의 사전 훈련된 모델이 이 역할을 수행합니다. 좋은 임베딩 모델은 의미적으로 유사한 텍스트를 벡터 공간에서 가까운 위치에 배치합니다.
| 모델 | 차원 | 특징 |
|---|---|---|
| all-MiniLM-L6-v2 | 384 | 가볍고 빠름, 범용 |
| multilingual-e5-large | 1024 | 다국어 지원, 한국어 성능 우수 |
| bge-m3 | 1024 | 다국어, 밀집+희소 벡터 동시 생성 |
| ELSER v2 | 희소 | Elasticsearch 전용, 희소 벡터 |
생성된 벡터를 효율적으로 검색할 수 있도록 인덱스 구조에 저장합니다. 수백만 개의 벡터에서 유사한 것을 찾으려면 전수 비교(brute-force)가 아닌 ANN(Approximate Nearest Neighbor) 알고리즘이 필요합니다. 대표적인 알고리즘으로 HNSW, IVF, Product Quantization 등이 있습니다.
사용자의 쿼리를 동일한 임베딩 모델로 벡터화한 뒤, 인덱스에서 가장 유사한 벡터를 가진 문서를 추출합니다. 이 단계에서는 속도가 중요하므로 Bi-encoder 방식을 사용합니다. 쿼리와 문서를 독립적으로 인코딩하기 때문에, 문서 벡터는 미리 계산해 둘 수 있습니다.
검색 단계에서 추출한 후보 문서들의 최종 순위를 결정합니다. Cross-encoder 기반의 리랭킹 모델이 쿼리와 각 문서를 함께 처리하여 더 정밀한 관련성 점수를 산출합니다. Bi-encoder보다 느리지만 정확도가 훨씬 높습니다.
검색 시스템에서 Bi-encoder는 "빠르지만 덜 정확한" 1차 필터, Cross-encoder는 "느리지만 더 정확한" 2차 정밀 평가 역할을 합니다. 이 2단계 구조가 현대 검색 시스템의 표준 패턴입니다.
AI 기반 검색 시스템의 전체 흐름을 아키텍처 다이어그램으로 표현하면 다음과 같습니다.
이 아키텍처에서 핵심 흐름은 다음과 같습니다.
이 시리즈는 총 11장으로 구성되어 있으며, AI 검색 시스템의 이론과 실전을 모두 다룹니다.
이번 장에서는 검색 기술이 키워드 매칭에서 시맨틱 이해, 그리고 하이브리드 방식으로 진화해 온 과정을 살펴보았습니다. 전통적 검색의 어휘 불일치 문제와 의도 파악 한계를 확인했고, AI 검색 시스템의 네 가지 핵심 구성요소인 임베딩, 인덱싱, 검색, 랭킹의 역할을 이해했습니다.
다음 장에서는 시맨틱 검색 아키텍처를 본격적으로 파고들어, Bi-encoder 기반 검색의 작동 원리와 임베딩 모델 선택, 문서 청킹 전략, 벡터 데이터베이스 연동까지 Python 구현과 함께 다루겠습니다.
이 글이 도움이 되셨나요?
Bi-encoder 기반 시맨틱 검색의 작동 원리, 임베딩 모델 선택, 문서 청킹 전략, ANN 검색, 벡터 데이터베이스 연동을 Python 구현과 함께 다룹니다.
Precision, Recall, NDCG, MRR, MAP 등 검색 품질 메트릭의 원리와 계산법, 오프라인/온라인 평가 방법론, A/B 테스트와 평가 데이터셋 구축을 다룹니다.
쿼리 분류, 의도 인식, 엔티티 인식부터 LLM 기반 쿼리 확장, HyDE(가상 문서 생성), 다국어 처리까지 쿼리 이해 파이프라인을 다룹니다.