본문 바로가기
Database2026년 9월 2일16분 읽기

벡터 DB 고르기 — pgvector·Pinecone·Qdrant·Milvus 운영 부담과 비용으로 비교

YS
김영삼
조회 7
벡터 DB 고르기 — pgvector·Pinecone·Qdrant·Milvus 운영 부담과 비용으로 비교

벡터가 대략 100만~500만 개 아래고 이미 Postgres를 쓰고 있다면 pgvector로 충분하다. 그 위로 올라가거나 초저지연·수평 확장·고급 필터링이 필요해지면 Qdrant나 Milvus를, 운영을 통째로 남에게 맡기고 싶으면 Pinecone을 본다.

RAG 붐 이후로 "벡터 DB 뭐 쓰지?"라는 질문을 정말 많이 받는다. 그런데 대부분은 규모 문제가 아니라 운영 부담과 비용 문제다. 이 글은 네 가지 선택지를 실제 운영 관점에서 비교하고, 어디서 갈아타야 하는지 선을 그어본다.

솔직히 말하면 나는 벡터 DB 세 개를 실서비스에 넣어봤고, 그 중 하나는 6개월 만에 다시 pgvector로 되돌렸다. 이유는 성능이 아니라 "운영할 사람이 나 하나"였기 때문이다. 그래서 이 글은 벤치마크 숫자 자랑보다 누가, 얼마의 시간과 돈으로 이걸 굴릴 수 있는가에 초점을 맞춘다.

한눈에 보는 핵심 수치

먼저 감을 잡을 수 있게 대략적인 특성을 정리했다. 아래 숫자는 공식 문서와 공개된 일반 특성 기준의 대략치이고, 실제 값은 임베딩 차원·인덱스 파라미터·하드웨어에 따라 크게 달라진다. 절대적인 벤치마크가 아니라 "어느 정도 급인지" 감을 잡는 용도로 보면 된다.

항목실무에서 흔한 값비고
임베딩 차원384 / 768 / 1536MiniLM·BGE·OpenAI text-embedding-3
벡터 1개 크기(1536·float32)약 6KB4바이트×1536, 인덱스는 별도
100만 벡터 원본 크기약 6GBHNSW 인덱스면 +50~100%
HNSW 대표 파라미터m=16, ef_construction=64~200recall↔속도 트레이드오프
pgvector가 편한 상한(경험칙)수백만 벡터그 위는 튜닝 난이도 급상승

여기서 자주 하는 착각 하나. "100만 벡터면 엄청 큰 거 아냐?"라고 생각하는데, 1536차원 float32라도 원본은 6GB 남짓이다. 요즘 RAM 붙은 인스턴스면 통째로 메모리에 올라간다. 규모를 실제 바이트로 환산해보면 대부분의 사내 문서 검색, 상품 추천, 고객센터 RAG는 pgvector 사정권 안에 있다.

왜 벡터 DB가 따로 필요한가?

결론부터. 벡터 검색은 "정확히 같은 값 찾기"가 아니라 "의미적으로 가까운 값 찾기"라서, 일반 B-tree 인덱스로는 못 하기 때문이다. 코사인 유사도나 L2 거리로 근사 최근접 이웃(ANN)을 빠르게 찾아야 하는데, 이걸 위한 전용 인덱스(HNSW, IVF 등)가 필요하다.

브루트포스로 전체를 스캔하면 100만 개 × 1536차원 내적을 매 쿼리마다 돌려야 한다. 데이터가 작을 땐 이것도 그냥 된다. 실제로 나는 초기 프로토타입을 numpy 배열 하나로 돌린 적도 있다. 문제는 데이터가 늘고 QPS가 붙는 순간이다. 그때부터 ANN 인덱스가 밥값을 한다.

# 벡터 검색이 하는 일의 본질 (개념 예시)
import numpy as np

def search(query_vec, corpus, top_k=5):
    # 코사인 유사도 = 정규화된 벡터의 내적
    q = query_vec / np.linalg.norm(query_vec)
    scores = corpus @ q          # (N, dim) @ (dim,) -> (N,)
    idx = np.argpartition(-scores, top_k)[:top_k]
    return idx[np.argsort(-scores[idx])]

# 데이터가 작으면 이걸로도 충분하다.
# 문제는 N이 수백만이 되고 QPS가 붙는 순간부터다.
참고 ANN은 이름 그대로 "근사"다. recall 100%를 보장하지 않는다. ef_search 같은 파라미터를 올리면 정확도는 오르고 속도는 떨어진다. 이 트레이드오프를 모르고 "검색 결과가 가끔 이상해요"라고 하는 경우가 실무에서 은근히 많다.

네 가지를 한 표로 비교하면

바로 본론. 아래가 이 글의 핵심 비교표다. pgvector는 Postgres 확장, Pinecone은 완전관리형 SaaS, Qdrant와 Milvus는 오픈소스 전용 벡터 DB(각각 관리형도 있음)라는 성격 차이를 먼저 머리에 넣고 보면 좋다.

기준pgvectorPineconeQdrantMilvus
형태Postgres 확장완전관리형 SaaS오픈소스+관리형오픈소스+관리형(Zilliz)
운영 부담낮음(기존 DB에 얹음)거의 없음중간(단일 바이너리라 무난)높음(분산 컴포넌트 다수)
비용 모델기존 DB 비용에 포함사용량 과금(규모 크면 비쌈)셀프호스팅 무료/관리형 유료셀프호스팅 무료/관리형 유료
인덱스HNSW, IVFFlat자체(추상화됨)HNSW(+양자화)HNSW, IVF, DiskANN 등 다수
메타데이터 필터링SQL WHERE 그대로(최강)메타데이터 필터 지원payload 필터 강력·유연스칼라 필터 지원
수평 확장제한적(읽기 복제/파티션)자동(서버리스)샤딩/복제 지원분산 설계(수십억 벡터)
편한 규모대~수백만수백만~수십억수백만~수억수억~수십억
트랜잭션/조인완전한 SQL·조인·ACID없음없음없음

표를 한 문장으로 요약하면. 이미 Postgres를 쓰고 데이터가 관계형과 얽혀 있으면 pgvector, 운영 인력을 아예 빼고 싶으면 Pinecone, 오픈소스로 성능·필터링을 챙기고 싶으면 Qdrant, 수억 개 이상 초대규모면 Milvus. 나머지는 디테일이다.

운영 부담 — 진짜 비용은 여기서 갈린다

운영 부담이 가장 낮은 건 단연 Pinecone과 pgvector다. 이유는 정반대다. Pinecone은 남이 다 해주니까, pgvector는 이미 굴리고 있는 Postgres에 확장 하나 얹는 거라 새로 배울 인프라가 없어서.

Milvus는 솔직히 각오해야 한다. etcd, 오브젝트 스토리지(MinIO/S3), 메시지 큐 같은 컴포넌트가 얽힌 분산 시스템이라, 셀프호스팅으로 제대로 굴리려면 쿠버네티스와 스토리지에 익숙한 사람이 있어야 한다. 소규모 팀이 "성능 좋다길래" 덜컥 도입했다가 운영에 발목 잡히는 대표 케이스다. 대신 규모가 진짜 크면 이 복잡성이 값을 한다.

Qdrant는 그 중간에서 균형이 좋다. Rust로 쓰인 단일 바이너리라 도커 하나로 띄우기 쉽고, 그러면서도 payload 필터링·양자화 같은 고급 기능이 탄탄하다. 개인적으로 "pgvector는 좁고 Milvus는 부담스럽다" 싶을 때 첫 번째로 보는 게 Qdrant다.

주의 "오픈소스니까 공짜"라는 계산은 위험하다. 셀프호스팅의 진짜 비용은 라이선스가 아니라 사람의 시간이다. 새벽에 인덱스가 OOM으로 죽었을 때 일으켜 세울 사람이 없다면, 그 관리형 요금이 오히려 싸다.

비용 — 규모에 따라 순위가 뒤집힌다

작은 규모에선 pgvector가 압도적으로 싸다. 어차피 있는 DB에 벡터 컬럼 하나 더 붙이는 거라 추가 비용이 사실상 0이다. 반면 Pinecone은 초반 진입은 편하지만 데이터와 QPS가 커질수록 청구서가 무섭게 는다.

규모가 커지면 계산이 바뀐다. 수천만~수억 벡터 구간에선 Qdrant나 Milvus를 셀프호스팅하는 게 SaaS보다 훨씬 저렴해지는 지점이 온다. 단, 앞서 말한 "사람 비용"을 더해야 공정한 비교다. 나는 이걸 이렇게 정리한다.

  • 수십만~수백만 벡터: pgvector가 거의 항상 최저 비용. 고민할 것도 없다.
  • 빠르게 출시·검증이 목적: Pinecone. 인프라에 시간 안 쓰고 제품에 집중.
  • 수천만 벡터 + 운영 인력 있음: Qdrant 셀프호스팅이 가성비 스위트스팟.
  • 수억 이상 + 전담 인프라 팀: Milvus. 이 규모에선 다른 선택지가 힘들어진다.

메타데이터 필터링 — 의외로 여기서 승부가 난다

RAG를 실제로 돌려보면 "순수 벡터 검색"만 필요한 경우가 거의 없다. "이 사용자의", "2024년 이후", "카테고리가 X인" 문서 중에서 유사한 걸 찾는다. 즉 필터 + 벡터 검색의 조합이 실무의 기본이다.

이 지점에서 pgvector가 반칙 수준으로 강하다. 그냥 SQL WHERE다. 조인도 되고 서브쿼리도 된다. 관계형 데이터와 벡터를 한 쿼리로 묶을 수 있다는 건 생각보다 큰 무기다.

-- pgvector: 필터 + 벡터 검색을 SQL 한 방에
-- HNSW 인덱스 전제, <=> 는 코사인 거리 연산자
SELECT id, title, embedding <=> $1 AS distance
FROM documents
WHERE user_id = $2               -- 일반 조건
  AND created_at >= '2024-01-01'  -- 범위 필터
  AND category = 'billing'
ORDER BY embedding <=> $1         -- 벡터 유사도 정렬
LIMIT 10;

Qdrant도 payload 필터링이 아주 강력하다. 필터 조건을 인덱스와 함께 잘 다루도록 설계돼 있어서, 필터가 까다로운 검색에서 특히 빛난다. Pinecone과 Milvus도 메타데이터/스칼라 필터를 지원하지만, pgvector의 "임의의 SQL"이나 Qdrant의 유연함에 비하면 표현력이 제한적인 편이다.

# Qdrant: payload 필터 + 벡터 검색
from qdrant_client import QdrantClient
from qdrant_client.models import Filter, FieldCondition, MatchValue

client = QdrantClient(url="http://localhost:6333")
hits = client.query_points(
    collection_name="documents",
    query=query_vec,                # 검색할 임베딩
    query_filter=Filter(            # 메타데이터 필터
        must=[FieldCondition(key="category", match=MatchValue(value="billing"))]
    ),
    limit=10,
).points
현장 팁 필터가 너무 빡세면(예: 전체의 0.1%만 통과) ANN 인덱스가 오히려 손해일 수 있다. 후보를 좁힌 다음 벡터 정렬만 하는 게 나을 때가 있다. 필터 선택도(selectivity)에 따라 쿼리 플랜이 달라진다는 걸 염두에 두자. 이건 문서에 잘 안 나오는데 실측하면 바로 느낀다.

확장성 — pgvector의 진짜 천장은 어디인가

pgvector의 한계는 "벡터 개수" 자체보다 단일 노드 Postgres의 한계에서 온다. HNSW 인덱스는 메모리를 많이 먹고, 인덱스가 RAM에 안 들어가기 시작하면 성능이 급격히 나빠진다. 그래서 실무 경험칙으로 수백만 벡터 근처가 "편하게 굴러가는" 상한선이다. 그 위는 불가능은 아닌데 튜닝 난이도가 확 올라간다.

Milvus는 처음부터 분산을 전제로 설계돼서 수억~수십억 벡터를 노린다. Qdrant는 샤딩·복제로 수억 규모까지 무난하고, Pinecone은 서버리스로 확장을 아예 신경 안 쓰게 해준다. 대신 그 편함의 대가가 비용이라는 건 앞서 말한 대로다.

-- pgvector HNSW 인덱스 생성과 검색 튜닝
CREATE INDEX ON documents
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

-- 검색 시 recall/속도 조절 (세션 단위)
SET hnsw.ef_search = 100;  -- 올리면 정확도↑ 속도↓

-- 인덱스가 메모리에 올라가는지 반드시 확인할 것
-- (maintenance_work_mem, work_mem 설정도 함께 본다)

그래서 언제 pgvector로 충분한가

가장 많이 받는 질문이라 따로 뺀다. 아래 조건에 대부분 해당하면 전용 벡터 DB는 아직 오버엔지니어링이다.

  • 이미 Postgres를 운영 중이다 (RDS, Supabase, 자체호스팅 무관).
  • 벡터가 수백만 개 이하이고, 당장 폭증할 계획이 뚜렷하지 않다.
  • 벡터를 관계형 데이터(사용자, 문서, 권한)와 함께 다뤄야 한다.
  • 팀 규모가 작고 인프라를 새로 하나 더 떠안기 싫다.
  • 필터링이 복잡하다 — 임의의 SQL 조건이 필요하다.

반대로 아래면 슬슬 갈아탈 때다.

  • 벡터가 수천만을 넘어가고 HNSW 인덱스가 RAM을 초과하기 시작했다.
  • p99 지연을 한 자릿수 ms로 눌러야 하고 QPS가 높다.
  • 스칼라 양자화·이진 양자화로 메모리를 확 줄여야 한다(Qdrant/Milvus의 영역).
  • 운영을 통째로 위임하고 제품에만 집중하고 싶다 → Pinecone.
내 결론 나는 새 프로젝트는 거의 예외 없이 pgvector로 시작한다. 이유는 단순하다. 대부분의 서비스는 전용 벡터 DB가 필요한 규모에 영영 도달하지 못하기 때문이다. 필요해지면 그때 옮겨도 늦지 않고, 그 시점엔 데이터 형태도 요구사항도 더 명확해져 있다. 미리 최적화하다 운영에 데인 게 한두 번이 아니다.

자주 묻는 질문

pgvector는 성능이 떨어져서 임시방편 아닌가요?

아니다. 수백만 벡터까지는 HNSW 인덱스를 붙인 pgvector가 전용 벡터 DB와 비교해도 실사용에 전혀 부족하지 않다. "임시방편"이라는 인식은 규모가 훨씬 큰 상황을 일반화한 오해에 가깝다. 다만 단일 노드 한계와 인덱스 메모리 사용은 분명히 존재하므로, 수천만 개 이상으로 가면 재검토가 필요하다.

Pinecone과 Qdrant 중 뭘 골라야 하나요?

운영 인력이 없고 속도가 중요하면 Pinecone, 비용과 통제권이 중요하고 셀프호스팅할 여력이 있으면 Qdrant다. Qdrant도 관리형 클라우드가 있어서, "Qdrant를 쓰되 운영은 맡긴다"는 절충안도 가능하다.

Milvus는 언제 써야 하나요?

벡터가 수억 개를 넘어가거나 수십억을 바라볼 때, 그리고 이를 감당할 인프라 팀(쿠버네티스·분산 스토리지)이 있을 때다. 그 규모가 아니라면 Milvus의 강력함보다 운영 복잡성이 먼저 체감된다. 소규모 팀에는 대체로 과하다.

메타데이터 필터링이 가장 강한 건 어느 쪽인가요?

표현력만 보면 pgvector다. 임의의 SQL WHERE·조인·서브쿼리를 그대로 쓸 수 있다. 전용 벡터 DB 중에서는 Qdrant의 payload 필터링이 유연하고 강력한 편이다. Pinecone·Milvus도 필터를 지원하지만 상대적으로 표현력이 제한적이다.

나중에 pgvector에서 전용 벡터 DB로 옮기기 어렵나요?

생각보다 어렵지 않다. 임베딩 벡터와 메타데이터, id만 넘기면 되므로 마이그레이션 스크립트 자체는 단순하다. 진짜 작업은 애플리케이션의 쿼리 코드를 새 클라이언트 API에 맞추고, 인덱스 파라미터를 다시 튜닝하고, recall을 검증하는 부분이다. 그래서 "일단 pgvector로 시작" 전략이 리스크가 낮다.

임베딩 차원이 크면(예: 1536) 어디가 유리한가요?

차원이 크면 메모리와 인덱스 크기가 다 커지므로, 양자화(스칼라·이진) 지원이 좋은 Qdrant나 Milvus가 메모리 효율에서 유리하다. pgvector도 동작은 하지만 고차원·대량 조합에서는 인덱스가 RAM을 빠르게 잡아먹는다. 차원 축소(Matryoshka 임베딩 등)를 함께 고려하면 어느 DB든 부담이 줄어든다.

하이브리드 검색(키워드+벡터)은 어디가 편한가요?

pgvector는 Postgres의 전문검색(tsvector)과 벡터를 한 쿼리에서 섞기 좋아 하이브리드 구현이 자연스럽다. Qdrant와 Milvus는 스파스+덴스 벡터를 함께 다루는 하이브리드 기능을 자체 제공한다. 순수 SQL 통합의 편함은 pgvector, 벡터 특화 하이브리드 최적화는 전용 DB 쪽이 앞선다고 보면 된다.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록