RAG 를 만들면 임베딩한 벡터를 어딘가에 저장하고 검색해야 한다. 처음엔 쓰던 검색엔진(OpenSearch)에 벡터 기능을 얹어 시작했는데, 전용 벡터 DB 로 옮길지 고민이 생기면서 후보들을 제대로 비교해 봤다. 결론부터 말하면, 규모가 크지 않으면 뭘 골라도 성능은 충분하고 선택을 가르는 건 성능이 아니라 기능과 운영이라는 것이었다. 이 글은 Open...
RAG 를 만들면 임베딩한 벡터를 어딘가에 저장하고 검색해야 한다. 처음엔 쓰던 검색엔진(OpenSearch)에 벡터 기능을 얹어 시작했는데, 전용 벡터 DB 로 옮길지 고민이 생기면서 후보들을 제대로 비교해 봤다. 결론부터 말하면, 규모가 크지 않으면 뭘 골라도 성능은 충분하고 선택을 가르는 건 성능이 아니라 기능과 운영이라는 것이었다.
이 글은 OpenSearch · Milvus · Qdrant · Vespa 네 제품을 같은 축으로 비교하고, 데이터 규모·차원·하이브리드 필요 여부에 따라 무엇을 고르면 되는지 정리한 기록이다.
| 제품 | 성격 |
|---|---|
| OpenSearch | 범용 검색·분석 엔진에 k-NN(벡터) 플러그인을 얹은 형태 |
| Milvus | 처음부터 벡터를 위해 만든 전용 분산 DB |
| Qdrant | 전용 벡터 DB. Rust 로 작성, 가볍고 빠름 |
| Vespa | 대규모 서빙·검색 엔진. 텐서·벡터를 1급으로 내장 |
"전용이라 무조건 낫다"는 건 마케팅 수사다. 범용 엔진도 벡터 검색을 충분히 하고, billion-scale 도 가능하다. 전용 DB 의 진짜 차이는 기능의 폭(학습형 sparse, multi-vector, GPU 인덱스, DiskANN)이다.
거의 모든 제품이 HNSW(그래프 기반, 인메모리 고성능)를 기본으로 지원한다. 그래서 HNSW 만 쓸 거면 인덱스는 선택 기준이 못 된다. 차이는 그 외 선택지다.
| OpenSearch | Milvus | Qdrant | Vespa | |
|---|---|---|---|---|
| HNSW | ◎ | ◎ | ◎ | ◎ |
| IVF 계열 | ◎ | ◎ | △ | ○ |
| DiskANN(온디스크) | △ | ◎ | ○(mmap) | ○ |
| GPU 인덱스 | ✗ | ◎ | ✗ | ✗ |
| 양자화 | ○ | ○ | ◎ | ○ |
| OpenSearch | Milvus | Qdrant | Vespa | |
|---|---|---|---|---|
| dense ANN | ◎ | ◎ | ◎ | ◎ |
| 하이브리드(BM25+벡터) | ◎ | ◎ | ○ | ◎ |
| 학습형 sparse(SPLADE) | ✗ | ◎ | △ | ○ |
| multi-vector | ✗ | ◎ | ○ | ◎ |
| 메타데이터 필터링 | ◎ | ◎ | ◎(표현력 최강) | ◎ |
| OpenSearch | Milvus | Qdrant | Vespa | |
|---|---|---|---|---|
| 설치·운영 난이도 | 중 | 높음(컴포넌트 다수) | 낮음 | 높음 |
| 분산 확장 | ◎ | ◎ | ◎ | ◎ |
| 멀티테넌시 | 인덱스 단위 | collection/partition | collection/shard | 스키마 |
| 생태계·커뮤니티 | 큼 | 큼 | 중 | 중 |
비교표보다 실무에서 중요한 건 "내 조건이면 뭘 고르나"다.
차원 자체가 제품 선택을 가르진 않는다. 다만 메모리 사용량이 벡터 수 × 차원 × 4byte 로 정해진다는 점은 기억해야 한다(float32 기준). 예를 들어 1,600만 벡터에 1024차원이면 raw 약 68GB. HNSW 그래프 오버헤드를 더해도 단일 장비 메모리에 들어가는 규모다. 차원이 크거나(예: 1536) 벡터가 많아 메모리를 넘기면 그때 양자화나 DiskANN 을 검토한다.
비교하면서 가장 크게 배운 건, 벤더 블로그의 우위 주장 상당수가 교차 검증하면 흔들린다는 점이다.
벡터 DB 의 동작 원리(segment, 하이브리드)가 궁금하면 Milvus 아키텍처 글에, HNSW 같은 검색 알고리즘은 벡터 검색 알고리즘 — kNN에서 HNSW까지에 더 정리해 두었다.