Skip to main content

Dense / Sparse Retrieval

문서 검색의 두 가지 기본 접근법인 Dense Retrieval(벡터 검색)과 Sparse Retrieval(키워드 검색)을 비교합니다.

Dense Retrieval (벡터 검색)

텍스트를 밀집 벡터(dense vector)로 변환하여 의미적 유사도로 검색합니다.

원리

코드 예제

from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma(
    collection_name="documents",
    embedding_function=embeddings,
)

# 문서 추가
vectorstore.add_documents(chunks)

# Dense Retrieval
results = vectorstore.similarity_search(
    query="LLM의 환각 문제를 해결하는 방법",
    k=4,
)

# 유사도 점수와 함께 검색
results_with_scores = vectorstore.similarity_search_with_score(
    query="LLM의 환각 문제를 해결하는 방법",
    k=4,
)
for doc, score in results_with_scores:
    print(f"유사도: {score:.4f} | {doc.page_content[:80]}")

임베딩 모델 비교

모델차원다국어비용특징
text-embedding-3-small1536O$0.02/1M tokensOpenAI, 범용
text-embedding-3-large3072O$0.13/1M tokensOpenAI, 고성능
BAAI/bge-m31024O무료 (로컬)다국어 최강, 한국어 우수
jhgan/ko-sroberta-multitask768한국어무료 (로컬)한국어 특화

유사도 메트릭

메트릭설명값 범위벡터 DB 기본값
Cosine Similarity벡터 방향 유사도-1 ~ 1Chroma, Qdrant
Dot Product (내적)벡터 크기 + 방향-∞ ~ ∞Milvus
Euclidean Distance벡터 간 거리0 ~ ∞-

장단점

장점단점
의미적 유사도 포착키워드 정확 매칭에 약함
동의어/패러프레이즈 처리임베딩 모델 품질에 의존
다국어 검색 가능고유명사, 코드 검색에 부적합
짧은 쿼리에서도 효과적임베딩 비용 발생

Sparse Retrieval (키워드 검색)

단어의 출현 빈도와 희귀성을 기반으로 검색합니다.

BM25

from langchain_community.retrievers import BM25Retriever

# BM25 Retriever 생성
bm25_retriever = BM25Retriever.from_documents(
    documents=chunks,
    k=4,
)

# 키워드 기반 검색
results = bm25_retriever.invoke("RAPTOR 트리 구조")

BM25 파라미터

파라미터설명기본값효과
k1용어 빈도 포화도1.2~2.0높을수록 빈도 가중치 증가
b문서 길이 정규화0.750=무시, 1=완전 정규화
k반환 문서 수4검색 결과 수

TF-IDF

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

# TF-IDF 벡터화
texts = [doc.page_content for doc in chunks]
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(texts)

# 쿼리 검색
query_vector = vectorizer.transform(["RAG 인덱싱 과정"])
similarities = cosine_similarity(query_vector, tfidf_matrix).flatten()

# 상위 K개 결과
top_k_indices = np.argsort(similarities)[-4:][::-1]
results = [chunks[i] for i in top_k_indices]

Sparse Retrieval 장단점

장점단점
키워드 정확 매칭동의어/패러프레이즈 미처리
고유명사, 코드 검색에 강함의미적 유사도 무시
임베딩 모델 불필요다국어 처리 제한
빠른 속도짧은 쿼리에서 성능 저하

Dense vs Sparse 비교

항목Dense RetrievalSparse Retrieval
검색 기준의미적 유사도키워드 매칭
동의어 처리OX
정확 키워드 매칭약함우수
고유명사 검색약함우수
다국어O (모델 의존)제한적
속도보통빠름
비용임베딩 비용무료
인프라벡터 DB 필요인메모리 가능

사용 시나리오

시나리오추천이유
일반 Q&ADense의미 검색이 중요
기술 문서 검색Sparse → Hybrid정확한 용어 매칭 필요
코드 검색Sparse함수명, 변수명 정확 매칭
다국어 검색Dense다국어 임베딩 모델 활용
프로토타이핑Sparse (BM25)임베딩 없이 빠르게 시작
프로덕션Hybrid두 장점을 결합
단일 전략으로는 Dense Retrieval이 대부분의 경우에서 더 나은 성능을 보입니다. 하지만 프로덕션에서는 Dense + Sparse를 결합한 Hybrid Search가 가장 안정적입니다.