558. 벡터 데이터 ANN 인덱싱 파라미터 튜닝
⚠️ 이 문서는 생성형 AI와 RAG(검색 증강 생성) 아키텍처의 핵심인 벡터 데이터베이스(Vector DB)에서, 완벽한 정답을 찾는 대신 압도적인 속도를 위해 근사치 검색을 수행하는 ANN(Approximate Nearest Neighbor) 인덱스(특히 HNSW 알고리즘)의 생성 및 검색 성능을 결정짓는 핵심 파라미터(M, efConstruction)의 튜닝 원리를 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: 고차원(예: 1536차원) 벡터 데이터 수백만 건 사이의 거리를 일일이 다 계산(K-NN)하는 것은 불가능하다. 이를 해결하기 위해 데이터 간의 거미줄 같은 그래프 망을 구축하여 '가장 가까울 확률이 높은 이웃'을 대충(Approximate) 빠르게 찾는 기술이 ANN이다.
- 가치: 파라미터 튜닝을 통해 "검색 정확도(Recall)를 90%로 살짝 낮추는 대신, 검색 속도를 100배 빠르게 만들 것인가?" 아니면 "메모리를 더 쓰더라도 99%의 정확도를 확보할 것인가?"라는 비즈니스 트레이드오프를 직접 제어할 수 있다.
- 기술 체계: HNSW(Hierarchical Navigable Small World) 인덱스 기준, 그래프의 층을 쌓을 때 노드당 연결할 간선의 개수인 **
M**과, 인덱스 생성 시 탐색할 이웃의 깊이인efConstruction값을 조절하여 정확도와 메모리/속도의 균형을 맞춘다.
Ⅰ. KNN의 절망과 ANN(HNSW)의 구원
벡터 DB에서 전통적인 B-Tree 인덱스는 전혀 쓸모가 없다.
- 정확한 최근접 이웃 (K-NN)의 한계:
- 사용자가 "이 사진과 가장 비슷한 고양이 사진 5장 찾아줘"라고 1536차원의 벡터 쿼리를 날렸을 때, DB에 있는 1천만 장의 사진 벡터와 일일이 내적(Dot Product) 거리를 계산(Brute-force)하면 쿼리 하나당 수 초~수 분이 걸린다.
- ANN (Approximate Nearest Neighbor):
- "정확히 1, 2, 3, 4, 5등을 찾는 게 아니라, 대충 1~10등 언저리에 있는 비슷한 애들 5명만 0.01초 만에 찾아주면 어떨까?"라는 발상에서 출발한 근사치 탐색 알고리즘이다.
- HNSW (계층적 탐색 가능한 좁은 세상):
- 현재 거의 모든 벡터 DB(Milvus, Pinecone 등)가 채택한 최고의 ANN 알고리즘이다. 지하철 노선도처럼 KTX 망(최상위 층), 완행열차 망(중간 층), 시내버스 망(최하위 층)으로 계층을 나누어, 멀리 있는 데이터는 KTX를 타고 듬성듬성 빠르게 접근한 뒤, 시내버스로 갈아타고 세밀하게 목적지를 찾는 방식을 쓴다.
📢 섹션 요약 비유: 전국에서 나랑 가장 취향이 비슷한 사람을 찾기 위해 5천만 명을 일일이 다 만나서 물어보는 것(KNN)이 아니라, 일단 도지사들(KTX망)을 만나서 제일 비슷한 도를 찾고, 그 도의 시장들(완행)을 만나서 시를 찾은 뒤, 동네 사람들(시내버스) 중 가장 비슷한 사람을 대충 찍어내는(ANN) 초고속 인맥 탐색법입니다.
Ⅱ. 인덱스 생성 파라미터: M과 efConstruction
HNSW 그래프 망을 짤 때(Build) 얼마나 촘촘하게 거미줄을 칠 것인가를 결정한다.
M파라미터 (Max Connections):- 하나의 노드(데이터)가 그래프 안에서 최대 몇 개의 다른 노드와 선(간선, Edge)으로 연결될 것인가를 뜻한다. 보통 16 ~ 64 사이의 값을 쓴다.
M값이 커지면 거미줄이 엄청나게 촘촘해져서, 길을 잃지 않고 정확한 정답을 찾아갈 확률(Recall)이 높아지지만, 그만큼 길(메모리)을 저장할 공간이 많이 필요하고 길을 뚫는 시간(인덱싱 속도)이 오래 걸린다.
efConstruction파라미터 (탐색 깊이):- 새로운 데이터를 인덱스(그래프)에 삽입할 때, 내 자리를 찾기 위해 주변 이웃을 몇 명이나 탐색해 볼 것인가를 뜻한다. (보통 100 ~ 500)
- 이 값이 높으면 내가 어디에 거미줄을 쳐야 가장 최적인지 아주 꼼꼼하게 따져보므로 검색 정확도(Recall)가 극도로 높아진다.
- 단, 데이터를
INSERT할 때 인덱스 빌드 속도가 기하급수적으로 느려진다. 한 번 지어놓으면 조회 속도에는 영향을 주지 않는다.
📢 섹션 요약 비유: M은 내가 카카오톡에 '몇 명의 친구(간선)'를 등록해 둘 것인가이고, efConstruction은 이사 갔을 때 떡을 돌리며 '몇 집이나 방문해서 인사'를 하고 내 위치를 주변에 각인시킬 것인가입니다. 둘 다 숫자가 클수록 나중에 연락(검색)하기는 편하지만, 처음에 인맥(인덱스)을 쌓는 데 엄청난 시간과 뇌 용량(메모리)이 소모됩니다.
Ⅲ. 검색 파라미터 (efSearch)와 리콜(Recall) 튜닝
인덱스를 다 지어놓고 실제 SELECT 쿼리를 날릴 때의 융통성이다.
efSearch파라미터:- 쿼리를 던져서 그래프를 타고 정답을 찾아갈 때, 갈림길에서 한 번에 몇 개의 후보 경로를 킵(Keep)해두고 탐색할 것인가를 뜻한다.
- 무조건 사용자가 요구한 $K$(반환할 결과 수, 예: 5개)보다는 커야 한다.
efSearch값을 50으로 하면 50개의 길을 동시에 탐색해 보므로 정확도(Recall)가 올라가지만 쿼리 속도(Latency)가 느려지고, 10으로 낮추면 속도는 총알 같아지지만 엉뚱한 데이터를 반환할 확률이 높아진다.
- 비즈니스 트레이드오프 튜닝:
- 의료/법률 AI (정확도가 생명): 메모리가 꽉 차더라도
M=64,efConstruction=500,efSearch=100으로 높여 Recall을 99%로 맞춘다. - 실시간 상품 추천 (속도가 생명): 약간 엉뚱한 옷을 추천해도 되니, 서버 비용 절감과 0.01초의 응답을 위해
M=16,efSearch=20으로 튜닝해 응답 속도를 극대화한다.
- 의료/법률 AI (정확도가 생명): 메모리가 꽉 차더라도
📢 섹션 요약 비유: 미로를 탐색할 때 빵 부스러기(efSearch)를 몇 개나 뿌려두면서 갈 길이 막혔을 때 돌아올 후보지를 확보할 것인가의 문제입니다. 부스러기를 많이 뿌리면(값 증가) 절대 길을 안 잃고 목적지(Recall)에 닿겠지만 빵을 뿌리느라 걷는 속도(Latency)가 너무 느려집니다.