Blog
vector-databaseragembeddingmilvuspineconechromapgvectorai

벡터 데이터베이스 완전 비교 - Chroma, Milvus, Pinecone, Qdrant, Weaviate, pgvector

주요 벡터 데이터베이스의 아키텍처, 설치, 성능, 인덱싱, 하이브리드 검색, 확장성, 선택 가이드를 종합 비교합니다. RAG와 AI 애플리케이션에 최적의 벡터 DB를 선택하세요.

Data Dynamics2026년 4월 16일24 min read

"내 문서에서 의미가 비슷한 내용을 찾아줘" — 일반 데이터베이스에 이런 요청을 하면 어떻게 될까요? LIKE 검색은 정확한 키워드가 있어야만 작동합니다. 하지만 사람은 "같은 말도 다르게 표현"하죠. 벡터 데이터베이스는 바로 이 문제를 풀기 위해 등장했습니다.

벡터 데이터베이스는 RAG, 시맨틱 검색, 추천 시스템 등 AI 애플리케이션의 핵심 인프라입니다. 이 글에서는 6개 주요 벡터 DB의 아키텍처, 성능, 기능을 체계적으로 비교합니다.

이 글에서 배우는 것

  • 벡터 데이터베이스가 왜 필요한지, 일반 DB와 무엇이 다른지
  • Chroma·Pinecone·Milvus·Qdrant·Weaviate·pgvector의 아키텍처 차이
  • 각 DB를 Python으로 빠르게 시작하는 방법
  • 인덱싱 알고리즘(HNSW·IVF 등)의 특성
  • 내 상황에 맞는 벡터 DB를 고르는 의사결정 흐름

1. 벡터 데이터베이스 개요

벡터 데이터베이스란

텍스트·이미지·오디오를 숫자 배열(벡터)로 변환하면 "의미가 비슷한 것끼리 숫자도 비슷해집니다." 벡터 데이터베이스는 이 고차원 벡터(임베딩)를 효율적으로 저장, 인덱싱, 검색하는 데 특화된 데이터베이스입니다. 의미적 유사도 기반으로 검색합니다.

Loading diagram…

왜 벡터 데이터베이스가 필요한가

"분산 처리"를 검색하면 "병렬 컴퓨팅"이라는 표현을 쓴 문서도 찾아줘야 하지 않을까요? 일반 DB는 그걸 못 합니다. 아래 비교를 보면 두 세계의 차이가 선명하게 드러납니다.

전통 DB 검색벡터 DB 검색
키워드 일치 (LIKE '%검색어%')의미적 유사도 기반
"분산 처리"로 검색 → "분산 처리" 포함 문서만"분산 처리"로 검색 → "병렬 컴퓨팅", "클러스터 연산" 포함 문서도 반환
정확한 키워드가 필요의미가 같으면 다른 표현도 검색
B-Tree, Hash 인덱스HNSW, IVF, PQ 인덱스

핵심 개념

용어가 낯설게 느껴질 수 있습니다. 지금 당장 전부 외울 필요는 없고, 나중에 코드를 보면서 떠올릴 수 있도록 한 번 훑어두면 충분합니다.

개념설명
임베딩 (Embedding)텍스트/이미지를 고차원 벡터로 변환한 수치 표현
유사도 (Similarity)벡터 간 거리/각도로 측정한 의미적 유사성
ANN (Approximate Nearest Neighbor)정확도를 약간 희생하여 빠르게 유사 벡터를 찾는 알고리즘
컬렉션 (Collection)동일 스키마의 벡터를 모은 논리적 그룹 (테이블에 해당)
메타데이터 (Metadata)벡터에 첨부된 필터링용 속성 정보

2. 아키텍처 비교

각 DB의 구조를 간략히 살펴봅니다. 아키텍처를 이해하면 "왜 이 DB는 빠른가, 왜 이 DB는 대규모에 강한가"가 자연스럽게 납득됩니다.

Chroma — 경량 임베디드

Loading diagram…
  • 유형: 임베디드 (in-process) 또는 클라이언트-서버
  • 언어: Python
  • 스토리지: SQLite + DuckDB
  • 적합: 프로토타입, PoC, 소규모 (< 100만 벡터)

Pinecone — 완전 관리형 SaaS

Loading diagram…
  • 유형: 관리형 SaaS (자체 호스팅 불가)
  • 스토리지: 자체 분산 스토리지
  • 적합: 운영 부담 최소화, 빠른 구축, 중대규모

Milvus — 클라우드 네이티브 분산

Loading diagram…
  • 유형: 분산 (Kubernetes 기반)
  • 언어: Go + C++
  • 적합: 엔터프라이즈 대규모 (수십억 벡터), GPU 인덱싱

Qdrant — 고성능 Rust 기반

Loading diagram…
  • 유형: 단일 노드 또는 분산 클러스터
  • 언어: Rust
  • 적합: 고성능 필터링, 중대규모, 낮은 지연시간

Weaviate — 하이브리드 검색 특화

Loading diagram…
  • 유형: 단일 노드 또는 분산
  • 언어: Go
  • 적합: 하이브리드 검색 (벡터 + 키워드) 중심, 내장 임베딩

pgvector — PostgreSQL 확장

Loading diagram…
  • 유형: PostgreSQL 확장 (기존 DB 활용)
  • 언어: C
  • 적합: 이미 PostgreSQL을 사용하는 환경, 소중규모

아키텍처 비교 요약

한 문장으로: 프로토타입이면 Chroma, 프로덕션이면 상황에 따라 Milvus·Qdrant·Weaviate 중 하나를 고르면 됩니다.

항목ChromaPineconeMilvusQdrantWeaviatepgvector
배포 모델임베디드/서버SaaS분산 (K8s)단일/분산단일/분산DB 확장
핵심 언어Python-Go/C++RustGoC
수평 확장XO (자동)OOO제한적
GPU 지원X-OXXX
오픈소스O (Apache 2.0)XO (Apache 2.0)O (Apache 2.0)O (BSD-3)O (PostgreSQL)
최대 벡터 수수백만수십억수백억수십억수십억수백만

3. 설치와 빠른 시작

말보다 코드가 빠릅니다. 각 DB를 실제로 써보는 가장 짧은 예시를 모아뒀습니다. 여러분의 프로젝트에 맞는 DB를 고른 뒤, 해당 섹션의 코드를 복사해서 바로 실행해보세요.

Chroma

pip install chromadb
import 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 pinecone
from 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 pymilvus
from 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-client
from 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-client
import 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. 인덱싱 알고리즘

벡터 DB에서 "빠른 검색"을 가능하게 하는 비결이 인덱싱 알고리즘입니다. 지도를 쓸 때 전체 도시를 샅샅이 다니지 않고 대로를 따라 목적지로 가는 것처럼, ANN 알고리즘은 정확도를 조금 타협하는 대신 훨씬 빠르게 유사 벡터를 찾아줍니다.

알고리즘 비교

알고리즘원리검색 속도정확도 (Recall)메모리빌드 시간
Flat전수 비교매우 느림100%낮음없음
HNSW계층적 그래프매우 빠름95~99%높음중간
IVF-Flat클러스터 + 전수빠름90~98%중간빠름
IVF-PQ클러스터 + 양자화매우 빠름85~95%매우 낮음빠름
SCANNGoogle 최적화매우 빠름95~99%중간중간

DB별 인덱스 지원

인덱스ChromaPineconeMilvusQdrantWeaviatepgvector
HNSWO (기본)- (내부)OO (기본)O (기본)O
IVF-FlatX-OXXO
IVF-PQX-OXXX
GPU 인덱스X-OXXX
동적 인덱스OOOOOX (재빌드)

참고: 대부분의 사용 사례에서 HNSW가 최적의 선택입니다. Recall 95%+ 에서도 빠른 검색 속도를 제공합니다. 10억+ 벡터의 초대규모에서는 IVF-PQ나 GPU 인덱스를 고려하세요.


5. 검색 기능

유사도 메트릭

두 벡터가 "얼마나 비슷한가"를 재는 방법은 여러 가지입니다. 대부분의 경우 Cosine 유사도가 잘 작동하며, 특히 임베딩 모델을 통해 정규화된 벡터라면 거의 항상 Cosine을 선택하면 됩니다.

메트릭수식범위적합 상황
Cosinecos(θ) = A·B / (‖A‖·‖B‖)-1 ~ 1정규화된 임베딩 (대부분의 경우)
L2 (Euclidean)√Σ(ai - bi)²0 ~ ∞거리 기반 비교
Inner ProductΣ(ai × bi)-∞ ~ ∞정규화된 벡터 시 Cosine과 동일

메타데이터 필터링

"엔지니어링 카테고리 문서 중에서 2025년 이후의 것만 찾아줘" — 이런 요청처럼 벡터 검색에 조건을 함께 걸어야 할 때 메타데이터 필터링이 필요합니다. Qdrant는 이 부분에서 특히 강력합니다.

# 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")),
        ]
    )
)

하이브리드 검색 (벡터 + 키워드)

의미 검색(벡터)과 키워드 검색(BM25)을 함께 쓰면 각각의 약점을 보완할 수 있습니다. Weaviate는 이 하이브리드 검색을 가장 자연스럽게 지원합니다. alpha 값으로 두 방식의 비중을 조절하면 됩니다.

# Weaviate: 네이티브 하이브리드 검색
results = collection.query.hybrid(
    query="Spark 성능 최적화",        # BM25 키워드 검색
    vector=[0.1, 0.2, ...],          # 벡터 검색
    alpha=0.7,                        # 0=키워드만, 1=벡터만, 0.7=벡터 70%
    limit=5
)

DB별 검색 기능 비교

기능ChromaPineconeMilvusQdrantWeaviatepgvector
벡터 검색OOOOOO
메타데이터 필터O (기본)OOO (강력)OO (SQL)
하이브리드 검색XO (Sparse)OO (Sparse)O (네이티브)X
멀티벡터XO (Namespace)OO (Named)OO (다중 컬럼)
전문 검색 (Full-text)XXXOO (BM25)O (tsvector)
필터+검색 동시OOOO (Pre-filter)OO

6. 확장성과 성능

벤치마크 비교 (참고용)

지표ChromaPineconeMilvusQdrantWeaviatepgvector
삽입 속도 (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수평 확장방식최소 구성
ChromaX-단일 프로세스
PineconeO (자동)관리형API 키만 필요
MilvusOK8s 기반 샤딩/복제etcd + MinIO + Pulsar
QdrantORaft 기반 클러스터3+ 노드
WeaviateO자체 클러스터링3+ 노드
pgvector제한적PostgreSQL 복제리드 레플리카

7. 엔터프라이즈 기능

기능ChromaPineconeMilvusQdrantWeaviatepgvector
인증/인가XO (API Key)O (RBAC)O (API Key)O (OIDC)O (PostgreSQL)
백업/복원파일 복사O (자동)O (Milvus Backup)O (스냅샷)OO (pg_dump)
모니터링기본O (대시보드)O (Grafana)O (Prometheus)O (Prometheus)O (pg_stat)
멀티테넌시컬렉션 분리O (Namespace)O (파티션)O (Payload 필터)O (테넌트)O (스키마)
클라우드 관리형XO (핵심)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. 선택 가이드

의사결정 플로차트

"어떤 벡터 DB를 써야 하나요?" 에 대한 체계적인 답입니다. 아래 흐름을 따라가면 대부분의 상황에서 좋은 선택에 도달할 수 있습니다.

Loading diagram…

시나리오별 추천

플로차트가 번거롭다면 아래 표에서 여러분의 상황과 가장 비슷한 행을 바로 찾아보세요.

시나리오추천이유
RAG 프로토타입 빠르게 만들기Chroma설치 없이 pip만으로 즉시 사용
기존 PostgreSQL에 벡터 검색 추가pgvector추가 인프라 불필요, SQL로 통합 쿼리
스타트업에서 빠르게 프로덕션 배포Pinecone운영 부담 제로, 자동 확장
엔터프라이즈 대규모 문서 검색Milvus수십억 벡터 지원, GPU 인덱싱
복잡한 필터 + 벡터 검색 조합QdrantRust 기반 고성능 필터링
키워드 + 벡터 하이브리드 검색WeaviateBM25 + 벡터 네이티브 하이브리드
온프레미스 + Kubernetes 환경Milvus 또는 QdrantK8s Helm 차트 제공, 자체 호스팅
다국어 검색 시스템Weaviate내장 벡터라이저, 다국어 모듈

참고: 벡터 DB 선택은 "최고의 DB"를 찾는 것이 아니라 "우리 환경에 가장 적합한 DB"를 찾는 것입니다. 프로토타입은 Chroma로 시작하고, 프로덕션 요구사항이 확정되면 전환하는 전략이 효과적입니다.


마치며 — 핵심 요약

  • 벡터 DB는 "의미가 비슷한 것을 찾는" 검색에 특화되어 있습니다. 키워드 검색의 한계를 뛰어넘어 RAG와 시맨틱 검색의 기반이 됩니다.
  • 처음 시작하는 프로젝트라면 Chroma로 시작하세요 — pip 하나로 설치되고 인프라가 필요 없습니다.
  • 기존에 PostgreSQL을 쓰고 있다면 pgvector를 먼저 시도해보세요. 추가 인프라 없이 SQL과 통합됩니다.
  • 프로덕션 규모가 되면 요구사항에 따라 나뉩니다 — 대규모 분산은 Milvus, 정교한 필터링은 Qdrant, 하이브리드 검색은 Weaviate, 운영 부담 제로는 Pinecone.
  • 대부분의 사용 사례에서 HNSW 인덱스가 가장 좋은 선택입니다. 10억 벡터 이상의 초대규모에서만 IVF-PQ나 GPU 인덱스를 고려하세요.
  • LangChain과 연동할 때는 어떤 벡터 DB를 써도 동일한 인터페이스(as_retriever())로 RAG 체인에 연결할 수 있어 나중에 전환도 어렵지 않습니다.

References


— Data Dynamics 엔지니어링 팀