Blog
vector-databaseragembeddingmilvuspineconechromapgvectorai
벡터 데이터베이스 완전 비교 - Chroma, Milvus, Pinecone, Qdrant, Weaviate, pgvector
주요 벡터 데이터베이스의 아키텍처, 설치, 성능, 인덱싱, 하이브리드 검색, 확장성, 선택 가이드를 종합 비교합니다. RAG와 AI 애플리케이션에 최적의 벡터 DB를 선택하세요.
Data Dynamics2026年4月16日18 min read
This post is not yet translated. The original Korean version is shown below.
벡터 데이터베이스는 RAG, 시맨틱 검색, 추천 시스템 등 AI 애플리케이션의 핵심 인프라입니다. 이 글에서는 6개 주요 벡터 DB의 아키텍처, 성능, 기능을 체계적으로 비교합니다.
1. 벡터 데이터베이스 개요
벡터 데이터베이스란
벡터 데이터베이스는 고차원 벡터(임베딩)를 효율적으로 저장, 인덱싱, 검색하는 데 특화된 데이터베이스입니다. 텍스트, 이미지, 오디오를 임베딩 모델로 벡터화한 뒤, 의미적 유사도 기반으로 검색합니다.
[벡터 데이터베이스 동작 흐름]
원본 데이터 ("Apache Spark는 분산 처리 프레임워크입니다")
↓ 임베딩 모델
벡터 변환 [0.021, -0.134, 0.892, ..., 0.045] (1536차원)
↓
벡터 DB에 저장 + 인덱싱 (HNSW, IVF 등)
↓
질의 벡터와 유사도 검색 (코사인, L2 등)
↓
Top-K 유사 문서 반환
왜 벡터 데이터베이스가 필요한가
| 전통 DB 검색 | 벡터 DB 검색 |
|---|---|
| 키워드 일치 (LIKE '%검색어%') | 의미적 유사도 기반 |
| "분산 처리"로 검색 → "분산 처리" 포함 문서만 | "분산 처리"로 검색 → "병렬 컴퓨팅", "클러스터 연산" 포함 문서도 반환 |
| 정확한 키워드가 필요 | 의미가 같으면 다른 표현도 검색 |
| B-Tree, Hash 인덱스 | HNSW, IVF, PQ 인덱스 |
핵심 개념
| 개념 | 설명 |
|---|---|
| 임베딩 (Embedding) | 텍스트/이미지를 고차원 벡터로 변환한 수치 표현 |
| 유사도 (Similarity) | 벡터 간 거리/각도로 측정한 의미적 유사성 |
| ANN (Approximate Nearest Neighbor) | 정확도를 약간 희생하여 빠르게 유사 벡터를 찾는 알고리즘 |
| 컬렉션 (Collection) | 동일 스키마의 벡터를 모은 논리적 그룹 (테이블에 해당) |
| 메타데이터 (Metadata) | 벡터에 첨부된 필터링용 속성 정보 |
2. 아키텍처 비교
Chroma — 경량 임베디드
[Chroma 아키텍처]
애플리케이션 프로세스
└─ Chroma (임베디드 라이브러리)
├─ SQLite (메타데이터)
└─ HNSW 인덱스 (벡터)
- 유형: 임베디드 (in-process) 또는 클라이언트-서버
- 언어: Python
- 스토리지: SQLite + DuckDB
- 적합: 프로토타입, PoC, 소규모 (< 100만 벡터)
Pinecone — 완전 관리형 SaaS
[Pinecone 아키텍처]
API 요청 → Pinecone Cloud
├─ 인덱스 관리 (자동 샤딩)
├─ 벡터 스토리지 (분산)
└─ 쿼리 엔진 (최적화)
- 유형: 관리형 SaaS (자체 호스팅 불가)
- 스토리지: 자체 분산 스토리지
- 적합: 운영 부담 최소화, 빠른 구축, 중대규모
Milvus — 클라우드 네이티브 분산
[Milvus 아키텍처]
┌─ Proxy (API Gateway)
├─ Query Node (검색)
├─ Data Node (삽입/삭제)
├─ Index Node (인덱스 구축)
└─ 의존성:
├─ etcd (메타데이터)
├─ MinIO/S3 (오브젝트 스토리지)
└─ Pulsar/Kafka (메시지 큐)
- 유형: 분산 (Kubernetes 기반)
- 언어: Go + C++
- 적합: 엔터프라이즈 대규모 (수십억 벡터), GPU 인덱싱
Qdrant — 고성능 Rust 기반
[Qdrant 아키텍처]
REST/gRPC API
└─ Qdrant Engine (Rust)
├─ HNSW 인덱스 (벡터)
├─ Payload 인덱스 (메타데이터)
└─ WAL + Segment 스토리지
- 유형: 단일 노드 또는 분산 클러스터
- 언어: Rust
- 적합: 고성능 필터링, 중대규모, 낮은 지연시간
Weaviate — 하이브리드 검색 특화
[Weaviate 아키텍처]
GraphQL / REST API
└─ Weaviate Core (Go)
├─ 벡터 인덱스 (HNSW)
├─ 역인덱스 (BM25) ← 하이브리드 검색
├─ 내장 벡터라이저 모듈
└─ 스키마 관리
- 유형: 단일 노드 또는 분산
- 언어: Go
- 적합: 하이브리드 검색 (벡터 + 키워드) 중심, 내장 임베딩
pgvector — PostgreSQL 확장
[pgvector 아키텍처]
PostgreSQL
└─ pgvector 확장
├─ vector 타입 (컬럼)
├─ ivfflat 인덱스
└─ hnsw 인덱스
- 유형: PostgreSQL 확장 (기존 DB 활용)
- 언어: C
- 적합: 이미 PostgreSQL을 사용하는 환경, 소중규모
아키텍처 비교 요약
| 항목 | Chroma | Pinecone | Milvus | Qdrant | Weaviate | pgvector |
|---|---|---|---|---|---|---|
| 배포 모델 | 임베디드/서버 | SaaS | 분산 (K8s) | 단일/분산 | 단일/분산 | DB 확장 |
| 핵심 언어 | Python | - | Go/C++ | Rust | Go | C |
| 수평 확장 | X | O (자동) | O | O | O | 제한적 |
| GPU 지원 | X | - | O | X | X | X |
| 오픈소스 | O (Apache 2.0) | X | O (Apache 2.0) | O (Apache 2.0) | O (BSD-3) | O (PostgreSQL) |
| 최대 벡터 수 | 수백만 | 수십억 | 수백억 | 수십억 | 수십억 | 수백만 |
3. 설치와 빠른 시작
Chroma
pip install chromadbimport chromadb
client = chromadb.Client() # 인메모리
# client = chromadb.PersistentClient(path="./chroma_db") # 영구 저장
collection = client.create_collection("documents")
collection.add(
ids=["doc1", "doc2", "doc3"],
documents=[
"Apache Spark는 분산 데이터 처리 프레임워크입니다",
"Kafka는 분산 이벤트 스트리밍 플랫폼입니다",
"Kubernetes는 컨테이너 오케스트레이션 도구입니다"
],
metadatas=[
{"category": "compute"},
{"category": "messaging"},
{"category": "orchestration"}
]
)
results = collection.query(
query_texts=["대용량 데이터 병렬 처리"],
n_results=2
)
print(results["documents"])Pinecone
pip install pineconefrom pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key="YOUR_API_KEY")
pc.create_index(
name="documents",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1")
)
index = pc.Index("documents")
index.upsert(vectors=[
{"id": "doc1", "values": [0.1, 0.2, ...], "metadata": {"category": "compute"}},
{"id": "doc2", "values": [0.3, 0.4, ...], "metadata": {"category": "messaging"}},
])
results = index.query(
vector=[0.1, 0.2, ...],
top_k=3,
include_metadata=True,
filter={"category": {"$eq": "compute"}}
)Milvus
# Docker로 실행
docker compose up -d # docker-compose.yml 필요
pip install pymilvusfrom pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
client.create_collection(
collection_name="documents",
dimension=1536,
metric_type="COSINE"
)
data = [
{"id": 1, "vector": [0.1, 0.2, ...], "text": "Spark는...", "category": "compute"},
{"id": 2, "vector": [0.3, 0.4, ...], "text": "Kafka는...", "category": "messaging"},
]
client.insert(collection_name="documents", data=data)
results = client.search(
collection_name="documents",
data=[[0.1, 0.2, ...]],
limit=3,
output_fields=["text", "category"]
)Qdrant
docker run -p 6333:6333 qdrant/qdrant
pip install qdrant-clientfrom qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance, PointStruct
client = QdrantClient(host="localhost", port=6333)
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE)
)
client.upsert(
collection_name="documents",
points=[
PointStruct(id=1, vector=[0.1, 0.2, ...], payload={"category": "compute", "text": "Spark는..."}),
PointStruct(id=2, vector=[0.3, 0.4, ...], payload={"category": "messaging", "text": "Kafka는..."}),
]
)
results = client.search(
collection_name="documents",
query_vector=[0.1, 0.2, ...],
limit=3,
query_filter={"must": [{"key": "category", "match": {"value": "compute"}}]}
)Weaviate
docker run -p 8080:8080 -p 50051:50051 semitechnologies/weaviate
pip install weaviate-clientimport weaviate
client = weaviate.connect_to_local()
collection = client.collections.create(
name="Document",
vectorizer_config=weaviate.classes.config.Configure.Vectorizer.none(),
properties=[
weaviate.classes.config.Property(name="text", data_type=weaviate.classes.config.DataType.TEXT),
weaviate.classes.config.Property(name="category", data_type=weaviate.classes.config.DataType.TEXT),
]
)
collection.data.insert_many([
{"text": "Spark는 분산 데이터 처리 프레임워크입니다", "category": "compute"},
{"text": "Kafka는 분산 이벤트 스트리밍 플랫폼입니다", "category": "messaging"},
])
results = collection.query.near_vector(
near_vector=[0.1, 0.2, ...],
limit=3,
return_metadata=weaviate.classes.query.MetadataQuery(distance=True)
)pgvector
-- PostgreSQL에 pgvector 확장 설치
CREATE EXTENSION vector;
-- 테이블 생성
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
text TEXT,
category TEXT,
embedding vector(1536)
);
-- 인덱스 생성 (HNSW)
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
-- 데이터 삽입
INSERT INTO documents (text, category, embedding)
VALUES ('Spark는 분산 처리 프레임워크입니다', 'compute', '[0.1, 0.2, ...]');
-- 유사도 검색
SELECT text, category, 1 - (embedding <=> '[0.1, 0.2, ...]') AS similarity
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 3;4. 인덱싱 알고리즘
알고리즘 비교
| 알고리즘 | 원리 | 검색 속도 | 정확도 (Recall) | 메모리 | 빌드 시간 |
|---|---|---|---|---|---|
| Flat | 전수 비교 | 매우 느림 | 100% | 낮음 | 없음 |
| HNSW | 계층적 그래프 | 매우 빠름 | 95~99% | 높음 | 중간 |
| IVF-Flat | 클러스터 + 전수 | 빠름 | 90~98% | 중간 | 빠름 |
| IVF-PQ | 클러스터 + 양자화 | 매우 빠름 | 85~95% | 매우 낮음 | 빠름 |
| SCANN | Google 최적화 | 매우 빠름 | 95~99% | 중간 | 중간 |
DB별 인덱스 지원
| 인덱스 | Chroma | Pinecone | Milvus | Qdrant | Weaviate | pgvector |
|---|---|---|---|---|---|---|
| HNSW | O (기본) | - (내부) | O | O (기본) | O (기본) | O |
| IVF-Flat | X | - | O | X | X | O |
| IVF-PQ | X | - | O | X | X | X |
| GPU 인덱스 | X | - | O | X | X | X |
| 동적 인덱스 | O | O | O | O | O | X (재빌드) |
참고: 대부분의 사용 사례에서 HNSW가 최적의 선택입니다. Recall 95%+ 에서도 빠른 검색 속도를 제공합니다. 10억+ 벡터의 초대규모에서는 IVF-PQ나 GPU 인덱스를 고려하세요.
5. 검색 기능
유사도 메트릭
| 메트릭 | 수식 | 범위 | 적합 상황 |
|---|---|---|---|
| Cosine | cos(θ) = A·B / (‖A‖·‖B‖) | -1 ~ 1 | 정규화된 임베딩 (대부분의 경우) |
| L2 (Euclidean) | √Σ(ai - bi)² | 0 ~ ∞ | 거리 기반 비교 |
| Inner Product | Σ(ai × bi) | -∞ ~ ∞ | 정규화된 벡터 시 Cosine과 동일 |
메타데이터 필터링
# Qdrant: 강력한 필터링 예시
from qdrant_client.models import Filter, FieldCondition, MatchValue, Range
results = client.search(
collection_name="documents",
query_vector=query_vector,
limit=5,
query_filter=Filter(
must=[
FieldCondition(key="category", match=MatchValue(value="engineering")),
FieldCondition(key="date", range=Range(gte="2025-01-01")),
],
must_not=[
FieldCondition(key="status", match=MatchValue(value="archived")),
]
)
)하이브리드 검색 (벡터 + 키워드)
# Weaviate: 네이티브 하이브리드 검색
results = collection.query.hybrid(
query="Spark 성능 최적화", # BM25 키워드 검색
vector=[0.1, 0.2, ...], # 벡터 검색
alpha=0.7, # 0=키워드만, 1=벡터만, 0.7=벡터 70%
limit=5
)DB별 검색 기능 비교
| 기능 | Chroma | Pinecone | Milvus | Qdrant | Weaviate | pgvector |
|---|---|---|---|---|---|---|
| 벡터 검색 | O | O | O | O | O | O |
| 메타데이터 필터 | O (기본) | O | O | O (강력) | O | O (SQL) |
| 하이브리드 검색 | X | O (Sparse) | O | O (Sparse) | O (네이티브) | X |
| 멀티벡터 | X | O (Namespace) | O | O (Named) | O | O (다중 컬럼) |
| 전문 검색 (Full-text) | X | X | X | O | O (BM25) | O (tsvector) |
| 필터+검색 동시 | O | O | O | O (Pre-filter) | O | O |
6. 확장성과 성능
벤치마크 비교 (참고용)
| 지표 | Chroma | Pinecone | Milvus | Qdrant | Weaviate | pgvector |
|---|---|---|---|---|---|---|
| 삽입 속도 (1M벡터) | ~5분 | ~3분 | ~2분 | ~2분 | ~4분 | ~8분 |
| 쿼리 지연 (p99) | ~15ms | ~10ms | ~8ms | ~5ms | ~12ms | ~20ms |
| 동시 쿼리 (QPS) | ~500 | ~3,000 | ~5,000 | ~4,000 | ~2,000 | ~300 |
| 최대 벡터 수 | 수백만 | 수십억 | 수백억 | 수십억 | 수십억 | 수백만 |
참고: 위 수치는 참고용이며, 하드웨어, 벡터 차원, 인덱스 설정에 따라 크게 달라집니다. 실제 환경에서의 벤치마크를 권장합니다.
수평 확장
| DB | 수평 확장 | 방식 | 최소 구성 |
|---|---|---|---|
| Chroma | X | - | 단일 프로세스 |
| Pinecone | O (자동) | 관리형 | API 키만 필요 |
| Milvus | O | K8s 기반 샤딩/복제 | etcd + MinIO + Pulsar |
| Qdrant | O | Raft 기반 클러스터 | 3+ 노드 |
| Weaviate | O | 자체 클러스터링 | 3+ 노드 |
| pgvector | 제한적 | PostgreSQL 복제 | 리드 레플리카 |
7. 엔터프라이즈 기능
| 기능 | Chroma | Pinecone | Milvus | Qdrant | Weaviate | pgvector |
|---|---|---|---|---|---|---|
| 인증/인가 | X | O (API Key) | O (RBAC) | O (API Key) | O (OIDC) | O (PostgreSQL) |
| 백업/복원 | 파일 복사 | O (자동) | O (Milvus Backup) | O (스냅샷) | O | O (pg_dump) |
| 모니터링 | 기본 | O (대시보드) | O (Grafana) | O (Prometheus) | O (Prometheus) | O (pg_stat) |
| 멀티테넌시 | 컬렉션 분리 | O (Namespace) | O (파티션) | O (Payload 필터) | O (테넌트) | O (스키마) |
| 클라우드 관리형 | X | O (핵심) | O (Zilliz) | O (Qdrant Cloud) | O (Weaviate Cloud) | O (각 클라우드 DB) |
8. AI 프레임워크 연동
LangChain 연동
# Chroma
from langchain_chroma import Chroma
vectorstore = Chroma.from_documents(docs, embeddings, persist_directory="./db")
# Pinecone
from langchain_pinecone import PineconeVectorStore
vectorstore = PineconeVectorStore.from_documents(docs, embeddings, index_name="my-index")
# Milvus
from langchain_milvus import Milvus
vectorstore = Milvus.from_documents(docs, embeddings, connection_args={"host": "localhost", "port": "19530"})
# Qdrant
from langchain_qdrant import QdrantVectorStore
vectorstore = QdrantVectorStore.from_documents(docs, embeddings, url="http://localhost:6333", collection_name="docs")
# Weaviate
from langchain_weaviate import WeaviateVectorStore
vectorstore = WeaviateVectorStore.from_documents(docs, embeddings, client=weaviate_client)
# pgvector
from langchain_postgres import PGVector
vectorstore = PGVector.from_documents(docs, embeddings, connection="postgresql://...", collection_name="docs")RAG 파이프라인에서의 활용
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# 어떤 벡터 DB든 동일한 RAG 체인
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
prompt = ChatPromptTemplate.from_template("""
컨텍스트를 참고하여 질문에 답하세요.
컨텍스트: {context}
질문: {question}
""")
rag_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| ChatOpenAI(model="gpt-4o")
| StrOutputParser()
)
answer = rag_chain.invoke("Spark 성능 최적화 방법은?")9. 선택 가이드
의사결정 플로차트
[기존에 PostgreSQL을 사용하고 있는가?]
├─ Yes, 벡터 수 < 100만 → pgvector
└─ No
↓
[프로토타입/PoC인가?]
├─ Yes → Chroma
└─ No (프로덕션)
↓
[자체 인프라 관리가 가능한가?]
├─ No → Pinecone (관리형 SaaS)
└─ Yes
↓
[하이브리드 검색(벡터+키워드)이 핵심인가?]
├─ Yes → Weaviate
└─ No
↓
[벡터 수가 10억 이상인가?]
├─ Yes → Milvus (대규모 분산)
└─ No
↓
[필터링 성능이 가장 중요한가?]
├─ Yes → Qdrant
└─ No → Qdrant 또는 Weaviate
시나리오별 추천
| 시나리오 | 추천 | 이유 |
|---|---|---|
| RAG 프로토타입 빠르게 만들기 | Chroma | 설치 없이 pip만으로 즉시 사용 |
| 기존 PostgreSQL에 벡터 검색 추가 | pgvector | 추가 인프라 불필요, SQL로 통합 쿼리 |
| 스타트업에서 빠르게 프로덕션 배포 | Pinecone | 운영 부담 제로, 자동 확장 |
| 엔터프라이즈 대규모 문서 검색 | Milvus | 수십억 벡터 지원, GPU 인덱싱 |
| 복잡한 필터 + 벡터 검색 조합 | Qdrant | Rust 기반 고성능 필터링 |
| 키워드 + 벡터 하이브리드 검색 | Weaviate | BM25 + 벡터 네이티브 하이브리드 |
| 온프레미스 + Kubernetes 환경 | Milvus 또는 Qdrant | K8s Helm 차트 제공, 자체 호스팅 |
| 다국어 검색 시스템 | Weaviate | 내장 벡터라이저, 다국어 모듈 |
참고: 벡터 DB 선택은 "최고의 DB"를 찾는 것이 아니라 "우리 환경에 가장 적합한 DB"를 찾는 것입니다. 프로토타입은 Chroma로 시작하고, 프로덕션 요구사항이 확정되면 전환하는 전략이 효과적입니다.
References
- Chroma Documentation — https://docs.trychroma.com/
- Pinecone Documentation — https://docs.pinecone.io/
- Milvus Documentation — https://milvus.io/docs
- Qdrant Documentation — https://qdrant.tech/documentation/
- Weaviate Documentation — https://weaviate.io/developers/weaviate
- pgvector GitHub — https://github.com/pgvector/pgvector
- Malkov, Y. & Yashunin, D. (2020). "Efficient and Robust Approximate Nearest Neighbor using Hierarchical Navigable Small World Graphs." IEEE TPAMI
— Data Dynamics 엔지니어링 팀