벡터 데이터베이스 성능 문제가 터지기 시작한 순간
벡터 데이터베이스를 처음 검토할 때는 보통 검색 정확도만 봅니다. 그런데 운영에 들어가면 먼저 보이는 것은 latency와 비용입니다. 예를 들어 문서 검색형 RAG 서비스에서 RPS가 80에서 300 사이로 올라가고 top k가 20 이상으로 커지면, 임베딩 검색 자체보다 필터링과 네트워크 왕복, 결과 페이로드 크기, 색인 유지 비용이 더 크게 체감되더군요.
실무에서는 이런 식으로 터집니다. 초반에는 문서 수가 300만 건 정도라서 큰 문제가 없어 보입니다. 그런데 고객사 테넌트가 늘고, 테넌트별 접근 제어가 붙고, 최신 문서만 검색해야 해서 메타데이터 조건이 복잡해지면 p95 latency가 70ms 수준에서 180ms 이상으로 밀리기 시작합니다. CPU보다 더 먼저 곤란해지는 것은 운영 판단이었습니다. 지금 병목이 벡터 연산인지, 필터링인지, 인덱스인지, 스토리지인지 한 번에 안 보이기 때문입니다.
이 시점에서 비교 대상이 보통 세 갈래로 갈립니다. 완전 관리형으로 운영 부담을 줄이는 Pinecone, 대규모와 튜닝 여지를 노리는 Milvus, 그리고 기존 PostgreSQL 안으로 가져와 단순성을 얻는 pgvector입니다. Pinecone은 관리형 벡터 데이터베이스로서 전용 읽기 노드와 서버리스 구조를 제공하고, Milvus는 Lite와 Standalone과 Distributed로 배포 폭이 넓으며, pgvector는 PostgreSQL 확장으로 HNSW와 IVFFlat을 지원합니다. 각각의 출발점이 애초에 다르다고 보시면 됩니다.
실제 운영에서 먼저 보는 숫자
제가 이런 비교를 할 때 먼저 보는 값은 네 가지입니다. RPS 120 전후에서 p95 latency가 100ms 아래로 유지되는지, 메타데이터 필터가 붙었을 때 recall이 급격히 떨어지지 않는지, 1천만 건 이상에서 색인과 적재 시간이 감당 가능한지, 그리고 장애 시 운영자가 어디까지 직접 만질 수 있는지입니다. 벡터 검색은 단순 조회처럼 보여도 운영 포인트가 꽤 많습니다.
Pinecone와 Milvus와 pgvector를 놓고 실제로 부딪히는 운영 문제
벡터 데이터베이스를 비교할 때 가장 많이 놓치는 부분이 필터링과 멀티테넌시입니다. 검색 데모에서는 임베딩 하나 넣고 비슷한 문서를 찾으면 끝이지만, 실제 서비스에서는 tenant id와 document type과 created at 같은 조건이 거의 반드시 붙습니다. 이 조건이 붙는 순간 제품별 장단점이 아주 선명해집니다.
Pinecone는 운영 단순성이 강하지만 비용 구조를 이해해야 합니다
Pinecone의 강점은 운영자가 인프라를 직접 붙들고 있지 않아도 된다는 점입니다. 문서 검색 API를 붙이고 namespace와 metadata filter를 설계하면 서비스 로직에 집중할 수 있습니다. 읽기 트래픽이 크고 응답 시간을 일정하게 유지해야 하는 팀이라면 꽤 매력적입니다.
다만 운영에서 바로 걸리는 제약도 있습니다. 멀티테넌트 SaaS에서 namespace를 어떻게 자를지 잘못 결정하면 비용이 금방 올라갑니다. 테넌트를 별도 namespace로 분리할지, 하나의 큰 namespace 안에서 metadata filter로만 나눌지에 따라 읽기 비용이 크게 달라집니다.
또 하나는 결과 크기입니다. 검색 엔진 자체는 빨라도 응답 페이로드가 커지면 결국 API 전체 지연 시간이 튑니다. 벡터값까지 무심코 내려주면 네트워크가 병목이 됩니다. 그래서 include values를 기본으로 끄고 필요한 metadata만 반환하는 식으로 설계하는 편이 낫습니다.
Milvus는 대규모에 유리하지만 팀의 운영 역량을 요구합니다
Milvus를 보면 느낌이 조금 다릅니다. Lite와 Standalone과 Distributed로 배포 모드가 분리되어 있고, Standalone은 단일 Docker 이미지 기반으로 쉽게 시작할 수 있고, Distributed는 Kubernetes 기반으로 확장성과 가용성을 노립니다. 숫자만 놓고 보면 데이터 규모가 큰 팀에게 확실히 눈에 들어오는 선택지입니다.
특히 대용량에서 메모리가 모자랄 때 Milvus의 색인 선택 폭이 강하게 느껴집니다. HNSW는 낮은 지연과 높은 정확도를 주지만 메모리 오버헤드가 큽니다. 반대로 DiskANN 계열 접근은 가용 RAM을 넘어가는 데이터셋에서 디스크를 활용해 버티는 쪽으로 볼 수 있습니다. 운영비 관점에서는 이 차이가 꽤 큽니다. 메모리 증설로 갈지, 디스크 기반으로 갈지 카드가 생기기 때문입니다.
대신 Milvus는 관리 포인트가 늘어납니다. 검색 노드와 적재 노드 분리, 모니터링, 색인 종류별 메모리 사용량, 필터 선택도에 따른 성능 차이 같은 것들을 팀이 이해해야 합니다. 이런 제품은 잘 쓰면 강하지만, 안 익숙한 팀에는 성능보다 운영 복잡도가 먼저 부담이 됩니다. 체감상 인프라 친화적인 팀일수록 장점이 크게 살아납니다.
pgvector는 가장 단순하지만 필터링과 대규모에서 주의가 필요합니다
pgvector의 장점은 아주 명확합니다. 이미 PostgreSQL을 운영 중이라면 같은 데이터베이스 안에서 벡터 컬럼과 일반 컬럼을 함께 관리할 수 있습니다. 일반 SQL 필터와 조합하기가 쉽고, 백업과 복구와 모니터링 흐름도 크게 바뀌지 않습니다. 팀이 Postgres 운영 경험이 충분하다면 이 단순성이 엄청난 이점입니다.
하지만 성능 관점에서 그냥 만만하게 보면 안 됩니다. pgvector도 결국 인덱스 튜닝 게임입니다. HNSW를 쓸지 IVFFlat을 쓸지, ef search를 어디까지 올릴지, 필터 컬럼 인덱스를 어떻게 붙일지에 따라 결과가 많이 달라집니다. Postgres라고 해서 자동으로 쉬워지는 것은 아닙니다.
특히 메타데이터 필터와 함께 approximate index를 쓸 때 결과가 부족하게 나올 수 있다는 점이 중요합니다. 개발 환경에서는 잘 나오는데 실제 데이터 분포에서는 top k가 비어서 나오는 경우가 생깁니다. 그래서 iterative scan과 partial index와 partitioning까지 같이 검토해야 합니다.
벡터 데이터베이스 선택 과정에서 Pinecone와 Milvus와 pgvector를 어떻게 비교했나
벡터 데이터베이스 선택은 결국 팀의 병목이 어디에 있느냐로 결정됩니다. 인프라 운영 인력이 부족한데 빠르게 출시해야 하면 Pinecone 쪽으로 기웁니다. 반대로 데이터 규모가 크고 비용 최적화와 세밀한 튜닝이 중요하면 Milvus를 진지하게 봅니다. 기존 PostgreSQL이 이미 핵심 시스템이고 벡터 검색이 서비스 전체에서 일부 기능이라면 pgvector가 가장 무난합니다.
의사결정 기준 하나는 누가 장애를 책임질 것인가였습니다
Pinecone는 장애 범위를 줄이기 쉽습니다. 인프라 운영 대신 서비스 로직에 집중할 수 있습니다. 대신 비용 모델과 namespace 설계를 초반에 잘못 잡으면 나중에 RU 비용이나 구조 제약으로 되돌리기 어려워질 수 있습니다. 운영 편의에 돈을 지불하는 구조라고 보시면 됩니다.
Milvus는 성능과 확장성 카드가 가장 많습니다. 다만 카드가 많은 만큼 실수할 지점도 많습니다. 검색이 느려졌을 때 색인 문제인지, segment compaction 문제인지, 필터 선택도 문제인지, 스토리지 IOPS 문제인지 팀이 직접 파고들어야 합니다. 체감상 인프라 친화적인 팀에는 아주 잘 맞고, 애플리케이션 개발 중심 팀에는 생각보다 버겁습니다.
pgvector는 장애 대응이 익숙합니다. 백업, 복구, 모니터링, VACUUM, 인덱스 관리 전부 기존 운영 체계 안에서 갑니다. 대신 벡터 전용 엔진처럼 대규모 고QPS를 공격적으로 밀어붙이기에는 한계가 빨리 보일 수 있습니다. 저는 이 지점에서 pgvector를 기능 내장형 선택지로 보고, Pinecone와 Milvus를 벡터 검색 중심 선택지로 보는 편입니다.
결국 이렇게 정리했습니다
Pinecone는 출시 속도와 운영 단순성이 중요할 때 유리합니다. 특히 검색 트래픽이 예측 가능하고 서비스 SLO를 빠르게 맞춰야 할 때 강합니다. 다만 멀티테넌시와 비용 구조를 처음부터 설계해야 합니다.
Milvus는 벡터 데이터베이스를 핵심 시스템으로 다루는 팀에 맞습니다. 대규모와 다양한 색인 전략, Kubernetes 운영 경험이 있다면 강합니다. 반대로 팀이 아직 observability와 capacity planning에 익숙하지 않다면 부담이 큽니다.
pgvector는 기존 Postgres에 최대한 붙여서 단순하게 가고 싶을 때 가장 무난합니다. 수백만에서 천만 단위 초반, 그리고 SQL 필터와 조인이 중요한 경우 특히 좋습니다. 다만 필터링이 복잡하고 데이터가 계속 커진다면 iterative scan과 partitioning과 partial index를 적극적으로 검토해야 합니다.
벡터 데이터베이스 실전 구현 예제
벡터 데이터베이스를 실제로 붙일 때는 제품 소개보다 데이터 모델이 먼저입니다. tenant id와 document type과 updated at 같은 필터 컬럼을 어떻게 나눌지, 임베딩 재생성 주기는 어떻게 가져갈지, 검색 결과에 원문을 어디까지 싣는지를 미리 정해야 합니다. 이 부분을 건너뛰면 어떤 제품을 골라도 나중에 다시 뜯어고치게 됩니다.
pgvector를 PostgreSQL에 붙일 때
pgvector는 기존 서비스에 가장 쉽게 넣을 수 있습니다. 다만 운영에서는 HNSW만 만들고 끝내지 말고, 필터 컬럼 인덱스와 iterative scan까지 같이 봐야 합니다. 이거 안 보면 테스트에서는 빠른데 실제 운영 데이터에서는 결과 수가 부족하게 나올 수 있습니다.
CREATE EXTENSION vector;
CREATE TABLE kb_chunk (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
document_type VARCHAR(30) NOT NULL,
updated_at TIMESTAMP NOT NULL,
embedding vector(1536) NOT NULL,
content TEXT NOT NULL
);
CREATE INDEX idx_kb_chunk_tenant_id ON kb_chunk (tenant_id);
CREATE INDEX idx_kb_chunk_updated_at ON kb_chunk (updated_at);
CREATE INDEX idx_kb_chunk_embedding_hnsw
ON kb_chunk USING hnsw (embedding vector_cosine_ops);
SET hnsw.iterative_scan = strict_order;
SELECT id, content
FROM kb_chunk
WHERE tenant_id = 1001
AND document_type = 'policy'
ORDER BY embedding <=> '[0.01, 0.02, 0.03]'
LIMIT 10;
/*
운영 팁
필터 컬럼 인덱스 없이 벡터 인덱스만 믿으면 생각보다 자주 느려집니다
테넌트가 큰 편차로 몰리면 partial index나 partitioning을 검토하는 편이 좋습니다
*/
Milvus를 Standalone으로 검증할 때
Milvus는 처음부터 Distributed로 가기보다 Standalone으로 데이터 모델과 인덱스 전략부터 검증하는 편이 좋습니다. 초반에는 이 정도만으로도 병목이 어디서 생기는지 충분히 볼 수 있습니다. 이 순서가 운영에서는 더 안전합니다.
version: '3.8'
services:
milvus:
image: milvusdb/milvus:v2.6.0
container_name: milvus
command: ["milvus", "run", "standalone"]
ports:
- "19530:19530"
- "9091:9091"
environment:
ETCD_USE_EMBED: "true"
COMMON_STORAGETYPE: "local"
volumes:
- ./volumes/milvus:/var/lib/milvus
# 운영 팁
# 초반 검증은 Standalone으로 충분한 경우가 많습니다
# 메모리 부족 징후가 보이면 HNSW만 고집하지 말고 DiskANN 계열도 같이 테스트해야 합니다
# 필터 조건이 복잡하면 scalar index와 partition key 전략까지 같이 봐야 합니다
Milvus는 벡터 검색만 빠르게 만드는 도구가 아닙니다. 메타데이터 필터와 분산 배치와 자원 계획까지 같이 봐야 성능이 안정적으로 나옵니다. 그래서 PoC 단계에서부터 필터 조건이 있는 실제 질의로 검증해야 합니다.
Pinecone를 Spring Boot 서비스에 붙일 때
Pinecone는 서비스 로직에서 복잡한 인프라 코드를 줄이는 쪽으로 접근합니다. 다만 namespace 설계와 결과 페이로드 최적화는 꼭 챙겨야 합니다. include values를 습관적으로 켜두면 성능이 금방 흔들립니다.
@Configuration
public class PineconeSearchConfig {
@Value("${app.vector.namespace}")
private String namespace;
public SearchRequest buildRequest(float[] queryEmbedding) {
return SearchRequest.builder()
.namespace(namespace)
.topK(10)
.includeMetadata(true)
.includeValues(false)
.vector(queryEmbedding)
.filter(Map.of("document_type", Map.of("$eq", "policy")))
.build();
}
}
/*
운영 팁
벡터 값은 정말 필요한 경우가 아니면 응답에 포함하지 않는 편이 좋습니다
멀티테넌트면 namespace와 metadata filter를 비용 구조까지 보고 결정해야 합니다
트래픽이 예측 가능하게 크면 전용 읽기 노드 계열 검토 가치가 있습니다
*/
벡터 데이터베이스 선택의 차가운 결론
벡터 데이터베이스를 고를 때 많은 팀이 성능 비교표 하나를 찾습니다. 그런데 실제로는 Pinecone와 Milvus와 pgvector의 성능 비교가 한 줄 숫자로 끝나지 않습니다. 어떤 인덱스를 썼는지, 메타데이터 필터가 얼마나 까다로운지, 테넌트 구조가 어떤지, top k와 payload가 어떤지에 따라 결과가 너무 달라집니다.
빠르게 출시하고 운영 인력을 아끼려면 Pinecone가 편합니다. 대규모와 튜닝 자유도가 중요하면 Milvus가 강합니다. 기존 PostgreSQL 중심 구조를 유지하고 싶다면 pgvector가 가장 무난합니다. 대신 셋 다 공짜 승자는 아닙니다.
Pinecone는 편한 대신 비용 구조를 반드시 이해해야 합니다. Milvus는 강한 대신 운영 난이도가 올라갑니다. pgvector는 단순한 대신 대규모와 복잡한 필터링에서 튜닝을 피할 수 없습니다. 이거 하나 도입한다고 모든 문제가 해결되지는 않습니다. 결국 운영 환경에 맞는 튜닝이 필요합니다.
오히려 실무에서는 이렇게 정리하는 편이 덜 후회합니다. 벡터 데이터베이스가 서비스의 중심이면 Milvus 또는 Pinecone를 검토합니다. 벡터 검색이 기능 중 하나라면 pgvector부터 시작합니다. 그리고 어떤 선택을 하든, 실제 데이터셋으로 p95 latency와 recall과 비용을 같이 측정한 뒤 결정해야 합니다. 벤치마크 숫자보다 운영 데이터가 훨씬 솔직합니다.
'IT 테크 > AI' 카테고리의 다른 글
| [RAG] GraphRAG: 지식 그래프를 결합해 복잡한 관계형 질문 해결하기 (0) | 2026.03.11 |
|---|---|
| [RAG] Re-ranking 도입 전후 성능 평가: 왜 단순히 상위 K개만 뽑으면 안 되는가? (0) | 2026.03.10 |
| [RAG] RAG의 고질병 '환각(Hallucination)'을 줄이는 3가지 검증 레이어 (0) | 2026.03.09 |
| [RAG] Chunking 전략이 답변의 질을 결정한다: 의미 단위 분할의 기술 (0) | 2026.03.08 |
| [RAG] 단순 RAG를 넘어: 고도화된 하이브리드 검색(Keyword + Semantic) 설계하기 (0) | 2026.03.06 |
