1. 개요[편집]
| 벡터 데이터베이스 Vector database | |
|---|---|
| 저장 대상 | 고차원 임베딩 벡터 + 메타데이터 |
| 기본 질의 | 근사 최근접 이웃 top-$k$ |
| 주력 색인 | IVF · IVF-PQ · HNSW · DiskANN · LSH |
| 유일한 진짜 지표 | 재현율-지연시간 파레토 곡선 |
| 가장 어려운 기능 | 필터 조건이 붙은 ANN |
| 대표 구현 | FAISS(라이브러리) · Milvus · Qdrant · Weaviate · Vespa · pgvector |
관계형 데이터베이스가 “이 값과 같은 행”을 찾아 주는 물건이라면, 이쪽은 “이 벡터와 비슷한 행”을 찾아 준다. 그리고 「비슷함」에는 정렬도, 등호도, 인덱스를 만들 전순서도 없다.
벡터 데이터베이스(vector database)는 고차원 임베딩 벡터를 대량으로 저장하고, 질의 벡터에 대한 근사 최근접 이웃(ANN) 검색을 일급 연산으로 제공하는 데이터 시스템이다. 핵심 알고리즘 자체는 새로운 것이 없다 — 최근접 이웃 탐색 연구가 20년 넘게 쌓아 온 색인 구조를 가져다 쓴다. 벡터 데이터베이스가 별도의 물건인 이유는 그 색인에 지속성·갱신·삭제·필터링·샤딩·복제를 붙여야 하기 때문이고, 실제로 이 시스템들이 실무에서 부러지는 지점도 알고리즘이 아니라 이 목록 쪽이다.
이 문서는 시스템으로서의 설계 결정을 본다. 개별 색인의 내부 동작은 각 문서가 소스 오브 트루스다 — 그래프 탐색과 LSH 이론은 최근접 이웃 탐색, 압축은 곱양자화와 벡터 양자화, 저차원 트리는 KD-트리와 공간 분할 자료구조가 맡는다.
2. 왜 기존 데이터베이스로 안 되는가[편집]
관계형 DB의 B-트리와 검색엔진의 역색인은 둘 다 같은 전제 위에 서 있다 — 키에 전순서가 있거나, 일치 여부가 이산적으로 판정된다. 임베딩 벡터에는 둘 다 없다. 768차원 실수 벡터를 정렬할 축이 없고, “이 벡터가 들어 있는 문서”라는 질문 자체가 성립하지 않는다.
그렇다고 KD-트리 같은 공간 분할 색인을 그대로 얹으면 되느냐 하면, 차원의 저주가 막는다. 축 정렬 초평면 가지치기는 “질의점에서 분할면까지의 거리가 현재 최선 반경보다 크면 반대편은 볼 필요 없다”는 논거로 작동하는데, 차원이 커지면 거리 집중 현상으로 최근접과 최원접의 상대 격차가 0으로 가면서 어떤 가지도 잘라지지 않는다. 경험칙은 잔인하게 단순하다 — 가 아니면 정확 색인은 전수탐색으로 수렴한다. 768차원 벡터 1억 개는 이 조건 근처에도 못 간다.
그래서 남은 선택지가 근사다. 정확한 답 대신 “높은 확률로 상위 개 중 대부분”을 돌려주는 대신 지수적 벽을 우회한다. 벡터 데이터베이스가 제공하는 계약은 근본적으로 확률적이고, 이것이 이 시스템을 다른 모든 데이터베이스와 구분 짓는 첫 번째 사실이다.1
3. 거리 척도와 정규화[편집]
색인을 고르기 전에 거리부터 확정해야 한다. 임베딩 모델이 학습된 방식과 질의 시 쓰는 거리가 어긋나면 그 뒤의 튜닝은 전부 무의미하다.
| 척도 | 정의 | 성질 |
|---|---|---|
| 유클리드 | 진짜 거리(삼각부등식 성립). 대부분 색인의 기본 | |
| 코사인 유사도 | 노름 무시, 방향만 본다 | |
| 내적 (MIPS) | 거리가 아니다 — 삼각부등식도 자기유사성 최대도 없다 |
코사인은 함정이 아니다. 모든 벡터를 미리 단위 노름으로 정규화해 두면
이므로 코사인 순위와 유클리드 순위가 정확히 일치한다. 실무의 국룰은 “색인에 넣기 전에 정규화하고 유클리드로 돌린다”이며, 이러면 에 최적화된 커널과 압축 기법을 그대로 쓸 수 있다.
문제는 정규화되지 않은 최대 내적 탐색(MIPS)이다. 노름이 큰 벡터가 무조건 유리해지므로, 삼각부등식에 기대는 가지치기와 그래프 탐색의 국소성 가정이 함께 무너진다. 자기 자신이 자기의 최근접이 아닐 수도 있는 세계다. 대응은 두 갈래인데, 하나는 비대칭 변환으로 차원을 하나 늘려 MIPS를 유클리드 NN으로 환원하는 것(슈리바스타바·리, 2014)이고, 다른 하나는 양자화 손실 자체를 내적에 맞춰 이방적으로 설계하는 것(ScaNN)이다. 후자는 곱양자화 문서에 정리돼 있다.
4. 색인 구조 지도[편집]
시스템이 고르는 색인은 사실상 아래 다섯 갈래로 수렴한다. 각 항목의 내부 동작은 링크된 문서가 맡고, 여기서는 시스템 관점의 성질만 비교한다.
| 색인 | 손잡이 | 메모리 | 구축 비용 | 삭제 | 강점 구간 |
|---|---|---|---|---|---|
| 평면(전수) | 없음 | 원본 그대로 | 0 | 자명 | , 정답이 필요할 때 |
| IVF | nprobe | 원본 + 중심 | k-평균 1회 | 쉬움 | 중간 규모, 갱신 잦음 |
| IVF-PQ | nprobe, | 벡터당 바이트 | k-평균 + 인코딩 | 쉬움 | 십억 규모, 램 부족 |
| HNSW | ef, | 원본 + 간선 | 비쌈 | 어려움 | 고재현율, 램 충분 |
| DiskANN | 탐색 폭 | 압축본만 램 | 매우 비쌈 | 어려움 | SSD 상주, 초대규모 |
IVF(inverted file)는 k-평균 군집화로 데이터를 수천~수십만 개 셀로 나눠 두고, 질의와 가까운 셀 nprobe개만 열어 보는 방식이다. 발상이 단순한 만큼 시스템 친화적이다 — 셀이 곧 파티션이라 병렬화·샤딩·증분 삽입이 자연스럽다. 약점은 셀 경계다. 질의가 두 셀의 경계 근처에 떨어지면 정답이 열지 않은 셀에 있고, 이걸 메우려 nprobe를 올리면 그만큼 느려진다. 재현율-지연 손잡이가 여기서 나온다.
HNSW는 근접 이웃 그래프를 여러 층으로 쌓아 위층의 긴 간선으로 대충 이동하고 아래층에서 정밀 탐색한다. 구축 시 M(노드당 간선 수)과 ef_construction, 질의 시 ef_search가 손잡이다. 고재현율 구간에서 가장 빠르다는 것이 20년 벤치마크의 결론이고, 그래서 대부분의 제품이 기본값으로 삼는다. 대가는 메모리다 — 원본 벡터에 더해 간선 리스트를 통째로 램에 얹어야 한다.
산수를 해 보면 설계가 결정된다. 768차원 float32 벡터 하나가 3 KB이므로 1억 개면 307 GB. 여기에 M = 32짜리 HNSW 간선(최하층 노드당 최대 64개, 4바이트 정수)이 벡터당 256 B 남짓 더해져 25 GB가 붙는다. 이 숫자가 램 예산을 넘는 순간 선택지는 셋뿐이다 — 샤딩해서 노드를 늘리거나, 곱양자화로 벡터를 8~32바이트로 줄이거나, DiskANN처럼 그래프와 압축본은 램에, 원본은 SSD에 두고 후보 몇 백 개만 디스크에서 읽어 재순위화하거나.
LSH는 이론이 가장 튼튼하다.2 -민감 해시 족으로 질의 시간의 보증을 주고, 그 보증이 데이터 분포에 의존하지 않는다. 그런데 실측에서는 그래프 기반에 밀렸다 — 최악 케이스 기준 보증이라는 것은 실제 데이터의 구조를 하나도 이용하지 않는다는 뜻이기도 하기 때문이다. 자세한 것은 국소 민감 해싱 문서에 있다.
5. 재현율-지연시간 곡선[편집]
이 바닥에서 한 숫자로 보고된 성능은 전부 읽지 않아도 된다. 모든 색인이 손잡이를 돌려 정확도와 속도를 맞바꾸므로(HNSW의 ef, IVF의 nprobe, LSH의 테이블 수), “우리 엔진이 10배 빠릅니다”는 상대의 손잡이 위치를 밝히지 않는 한 아무 정보도 담고 있지 않다. 표준 보고 형식은 손잡이를 쓸어 가며 찍은 파레토 곡선이다.
- 가로축: 초당 질의 수(QPS) 또는 p99 지연시간
- 세로축: recall@ — 정확 전수탐색이 준 top- 중 몇 개를 회수했는가
곡선 자체를 읽는 법은 최근접 이웃 탐색 문서에 있으니, 여기서는 제품 벤치마크가 곡선 밖에서 숨기는 것들을 적어 둔다.
- 구축 시간과 구축 메모리. 질의 곡선만 예쁘고 색인 만드는 데 사흘 걸리는 설정이 흔하다.
ef_construction을 올리면 곡선이 올라가고 구축 시간이 함께 오른다. - 동시성 조건. 스레드 1개 QPS와 스레드 64개 QPS는 다른 이야기이고, 질의 배치 크기 1과 100도 다른 이야기다. 배치가 크면 메모리 대역폭이 잘 쓰여 유리하다.
- 상주 메모리. 압축률을 자랑하면서 재순위화용 원본을 어딘가에 들고 있는 구성이 흔하다.
- 데이터셋. SIFT·GIST 같은 고전 벤치마크와 최신 문장 임베딩은 내재 차원이 다르다. 내재 차원이 낮은 데이터에서는 어떤 방법이든 잘 되고, 그 결과가 우리 데이터로 이전되지 않는다.
- 정답 기준. recall의 분모는 전수탐색 결과여야 한다. 다른 근사 색인을 정답으로 삼은 재현율은 의미가 없다.
6. 필터링된 ANN — 진짜 어려운 곳[편집]
실무 질의는 순수한 최근접 이웃 질의가 아니다. “이 사용자가 접근 권한을 가진, 최근 30일 이내, 한국어 문서 중에서 가장 비슷한 10개”가 실제 요구사항이다. 그리고 이 조합이 벡터 데이터베이스 설계에서 가장 어려운 지점이다.
- 사후 필터링(post-filter). 그냥 ANN으로 개 뽑고 조건에 맞는 것만 남긴다. 구현이 자명하지만 선택률이 낮으면 파산한다 — 조건을 만족하는 문서가 전체의 0.1%라면 를 수만으로 키워야 하고, 그래도 빈 결과가 나올 수 있다.
- 사전 필터링(pre-filter). 조건을 만족하는 집합을 먼저 구하고 그 안에서만 검색한다. 집합이 작으면 전수탐색으로 끝나 최선이다. 그런데 집합이 중간 크기면 색인을 못 쓴다 — HNSW 그래프에서 통과하지 못한 노드를 전부 지우면 남은 부분그래프가 연결성을 잃어 탐욕 탐색이 국소에 갇히고, IVF에서는 셀마다 남는 후보 수가 들쭉날쭉해진다.
문제의 뿌리는 구조적이다. 색인은 이웃 관계를 구축 시점에 굳혀 놓는데, 필터는 질의마다 다른 부분집합을 요구한다. 미리 만들어 둔 지름길이 질의마다 사라지는 것이다. 실무 대응은 몇 갈래로 갈린다.
- 필터 인지 그래프 탐색. 탐색은 전체 그래프에서 하되 결과 후보에는 조건 통과 노드만 넣는다. 통과하지 못한 노드를 “경유만 허용”하면 연결성이 유지된다. 대신 선택률이 낮으면 헛걸음이 많아진다.
- 속성별 분할. 카디널리티가 낮고 자주 쓰이는 속성(테넌트 ID, 언어)은 아예 별도 색인으로 나눈다. 가장 확실하지만 속성 조합이 늘면 색인 수가 폭발한다.
- 선택률에 따른 계획 전환. 통계를 들고 있다가 선택률이 임계 이하면 전수탐색, 이상이면 ANN + 사후 필터로 갈아탄다. 관계형 DB의 질의 계획기와 발상이 같다.
주의할 점 하나. 필터가 붙으면 재현율 정의부터 다시 써야 한다. 분모가 “전체에서의 top-”가 아니라 “필터 통과 집합에서의 top-”여야 하는데, 벤치마크가 이걸 흐리면 숫자가 조용히 부풀려진다.
7. 운영 — 갱신·삭제·재색인[편집]
색인이 정적이라는 가정은 논문에서만 성립한다. 실제 시스템에서는 문서가 매일 들어오고 나간다.
삭제. 그래프 색인에서 노드를 물리적으로 제거하면 그 노드를 경유하던 경로가 끊긴다. 그래서 거의 모든 구현이 묘비(tombstone)로 논리 삭제만 하고 탐색 시 결과에서 걸러 낸다. 묘비가 쌓이면 탐색은 여전히 죽은 노드를 방문하므로 실효 지연시간이 서서히 나빠지고, 결국 주기적 압축(compaction)으로 세그먼트를 다시 만들어야 한다. 로그 구조 저장소의 문제와 정확히 같은 형태다.
삽입. HNSW는 증분 삽입이 되지만, 이미 굳은 간선들이 새 데이터를 반영하지 못해 그래프 품질이 서서히 열화한다. IVF는 더 나쁘다 — 중심은 초기 표본으로 학습됐는데 데이터 분포가 옮겨 가면 셀 크기가 극단적으로 불균형해져서 nprobe가 같아도 재현율이 떨어진다. 두 경우 모두 답은 재구축이고, 그래서 실무 시스템은 작은 세그먼트를 계속 만들어 붙이고 백그라운드에서 병합하는 구조를 택한다. 질의는 모든 세그먼트에 브로드캐스트해 결과를 병합한다.
임베딩 모델 교체. 이것이 가장 비싼 사건이다. 모델을 바꾸면 벡터 공간 자체가 달라지므로 전량 재임베딩 + 전량 재색인이며, PQ를 썼다면 코드북까지 다시 학습해야 한다. 십억 건이면 GPU 시간과 색인 구축 시간이 각각 며칠 단위다. 무중단으로 하려면 새 색인을 옆에서 만들고 원자적으로 전환하는 이중 쓰기 경로가 필요한데, 이 비용을 운영 계획에 넣지 않은 팀이 반드시 한 번은 크게 데인다.
샤딩과 복제. 벡터 색인은 상태가 크고 무거워서 재분배가 비싸다. 샤딩하면 각 샤드에서 top- 를 받아 병합하는데, 여기에 함정이 있다. 샤드가 개일 때 각 샤드에서 개씩 받으면 전역 top- 를 정확히 복원할 수 있지만(각 샤드가 정확할 때 한정), 샤드별 검색이 근사라면 전역 재현율은 샤드별 재현율보다 나빠진다. 샤드 수를 늘리면 샤드당 데이터가 줄어 개별 재현율은 오르지만 병합 오버헤드와 꼬리 지연이 커진다. 두 효과가 반대 방향이라 최적 샤드 수는 측정으로만 나온다.
8. RAG 파이프라인에서의 자리[편집]
지금 벡터 데이터베이스 수요의 대부분은 검색 증강 생성(RAG)에서 나온다. 문서를 잘라 임베딩하고 색인에 넣은 뒤, 질문을 임베딩해 가까운 조각을 뽑아 대규모 언어 모델 프롬프트에 붙이는 파이프라인이다. 여기서 벡터 검색이 차지하는 자리를 정직하게 적으면 이렇다.
- 품질을 결정하는 것은 대체로 벡터 검색이 아니다. 청킹 전략(조각 길이·겹침·문단 경계 존중)과 임베딩 모델 선택이 최종 성능에 훨씬 크게 기여한다. 색인 재현율을 0.95에서 0.99로 올리는 튜닝보다 청크를 다시 자르는 쪽이 대개 이득이 크다.
- 어휘 검색과 섞는 것이 기본값이다. 고유명사·제품 코드·오타처럼 임베딩이 약한 질의가 실무에는 잔뜩 있다. BM25 역색인과 벡터 검색의 결과를 상호 순위 융합(RRF) 등으로 합치는 하이브리드 구성이 거의 항상 단일 방식보다 낫다.
- 재순위화가 마지막 한 뼘을 담당한다. ANN이 뽑은 수십~수백 후보를 교차 인코더로 다시 채점하면 정밀도가 크게 오른다. 이 단계가 있으면 1단계 색인의 재현율 요구가 낮아져 더 공격적인 근사 설정을 쓸 수 있다는 점이 시스템 설계상 중요하다.
9. 고르는 법[편집]
- 을 먼저 적는다. 100만 건 이하라면 전수탐색이 SIMD로 충분히 빠르고, k-평균 군집화 기반 IVF만 얹어도 대개 끝난다. 십억 건부터가 진짜 시스템 문제다.
- 램 예산을 계산한다. 벡터 개수 × 차원 × 4바이트가 들어가면 HNSW, 안 들어가면 IVF-PQ나 DiskANN. 이 한 줄이 아키텍처의 절반이다.
- 재현율 요구를 숫자로 못 박는다. recall@10이 0.9면 되는 응용과 0.99가 필요한 응용은 다른 색인을 쓴다. 정하지 않으면 튜닝이 끝나지 않는다.
- 필터 요구사항을 처음부터 스펙에 넣는다. 나중에 붙이려 하면 색인 구조를 갈아엎게 된다.
- 쓰기 패턴을 본다. 하루 한 번 배치 재구축이면 삶이 편하고, 실시간 삽입·삭제가 필요하면 세그먼트 병합 설계가 있는 제품을 고른다.
- 전용 제품이 필요한지 되묻는다. 데이터가 이미 관계형 DB에 있고 규모가 천만 건 이하라면
pgvector같은 확장이 운영 복잡도를 크게 줄인다. 새 데이터스토어 하나를 늘리는 비용은 언제나 벤치마크에 안 나온다.3
10. 관련 문서[편집]
- 최근접 이웃 탐색 · 국소 민감 해싱 · KD-트리 · 공간 분할 자료구조
- 곱양자화 · 벡터 양자화 · 신경망 양자화
- 차원의 저주 · 무작위 사영 · 주성분 분석 · 다양체 학습
- k-평균 군집화 · 자카드 유사도 · 쿼드트리 · 공간 채움 곡선
- 트랜스포머 · 검색 증강 생성 · 대규모 언어 모델 · 역색인
- GPU 컴퓨팅
11. Footnotes[편집]
-
“데이터베이스”라는 이름을 달고 정확한 답을 보장하지 않는 시스템이라는 점은 생각보다 큰 인식 전환이다.
SELECT가 행을 빠뜨리면 그건 버그지만, 벡터 검색이 정답 10개 중 9개만 주면 그건 설정값이다. 장애 대응 중에 “재현율이 낮은 겁니다”와 “데이터가 유실됐습니다”를 구분하지 못하면 밤이 길어진다. ↩ -
이 분야에서 가장 아이러니한 대목이다. 이론적 보증이 유일하게 확실한 방법이 실무에서 가장 안 쓰이고, 이론적 보증이 사실상 없는 그래프 기반 방법이 표준이 됐다. 「최악 케이스 보증」은 우리 데이터가 최악 케이스가 아닐 때 아무 값도 하지 않는다는 뜻이기도 하다. 실무가 이론을 20년쯤 앞서 달리는, 전산 분야에서도 흔치 않은 풍경. ↩
-
이 바닥의 오래된 농담 — 새 데이터스토어를 도입하면 성능 문제 하나를 해결하고 운영 문제 세 개를 얻는다. 백업·복구, 스키마 이관, 모니터링, 온콜 로테이션은 벤치마크 그래프의 어느 축에도 없다. 그래서 “우리 데이터는 이미 포스트그레스에 있는데요”라는 한마디가 QPS 5배보다 강한 논거가 되는 경우가 실제로 흔하다. ↩