왜 임베딩 저장 비용이 문제가 되는가

텍스트 임베딩은 보통 float32 차원 벡터로 저장된다. 1,024차원 벡터 하나가 4KB다. 문서 1억 개면 원본 벡터만 400GB에 달하고, 대부분의 벡터 검색 엔진은 저지연을 위해 인덱스를 메모리에 상주시킨다. 즉 RAM 비용이 곧 인프라 비용이 된다. 여기에 HNSW 같은 그래프 인덱스 오버헤드까지 더하면 실제 메모리 사용량은 원본의 1.5~2배로 불어난다.

이진 양자화(binary quantization)는 각 차원을 부호에 따라 1비트로 압축한다. float32 대비 32배 작아지고, 거리 계산은 해밍 거리(XOR + popcount)로 바뀌어 CPU에서도 매우 빠르다.

이진 양자화의 원리

방식은 단순하다. 각 차원 값이 0보다 크면 1, 아니면 0으로 매핑한다. 대부분의 최신 임베딩 모델은 차원별 분포가 0을 중심으로 대칭에 가까워, 0을 임계값으로 써도 정보 손실이 생각보다 작다.

import numpy as np

def binarize(vecs: np.ndarray) -> np.ndarray:
    # vecs: (N, D) float32  ->  packed uint8 (N, D/8)
    bits = (vecs > 0).astype(np.uint8)
    return np.packbits(bits, axis=1)

def hamming(a: np.ndarray, b: np.ndarray) -> np.ndarray:
    # a: (D/8,), b: (N, D/8)  ->  distances (N,)
    xor = np.bitwise_xor(a, b)
    return np.unpackbits(xor, axis=1).sum(axis=1)

저장 비용 비교

방식차원당 크기1억 벡터(1024D)거리 연산
float3232비트~400GB코사인/내적
int88비트~100GB내적(스케일 보정)
binary1비트~12.5GB해밍

메모리를 32배 줄이면 같은 노드에서 훨씬 많은 벡터를 처리하거나, 인스턴스 등급을 낮출 수 있다.

정확도 손실을 되돌리는 리스코어링

이진 검색만으로는 상위 랭킹이 다소 흔들린다. 실무에서는 2단계 검색으로 보완한다. 먼저 이진 인덱스로 후보를 넉넉히(예: top 200) 뽑고, 그 후보에 대해서만 원본(또는 int8) 벡터로 정밀 재정렬한다. 후보 집합이 작으므로 원본 벡터는 디스크나 오브젝트 스토리지에 둬도 된다.

def search(query_f32, bin_index, full_vecs, top_k=10, rescore=200):
    q_bin = binarize(query_f32[None, :])[0]
    cand = np.argsort(hamming(q_bin, bin_index))[:rescore]
    # 후보만 원본으로 정밀 재정렬
    scores = full_vecs[cand] @ query_f32
    order = cand[np.argsort(-scores)][:top_k]
    return order

이 방식으로 대개 float32 대비 recall 95~99%를 유지하면서 메모리 대부분을 절감한다.

벡터 DB 설정 예시

주요 엔진은 이진 양자화를 내장 옵션으로 제공한다. Qdrant는 컬렉션 설정에서 바로 켤 수 있고, 원본은 디스크에 두고 리스코어링만 켜는 구성이 흔하다.

vectors:
  size: 1024
  distance: Cosine
  on_disk: true            # 원본 벡터는 디스크에
quantization_config:
  binary:
    always_ram: true       # 이진 코드만 RAM 상주

검색 요청에서는 후보를 넉넉히 확보하도록 oversampling과 rescore를 지정한다.

client.query_points(
    collection_name="docs",
    query=vector,
    limit=10,
    search_params={
        "quantization": {"rescore": True, "oversampling": 2.0},
    },
)

적용 전 확인할 주의점

  • 모델 적합성: 차원 분포가 0 중심 대칭인 모델에서 효과가 좋다. 도입 전 자체 데이터로 recall을 측정해야 한다.
  • 저차원 위험: 256차원 이하 저차원 벡터는 1비트 손실 비중이 커서 손실이 두드러진다. 고차원(768~1536)에서 유리하다.
  • 리스코어 원본 보관: 재정렬을 쓰려면 원본 또는 int8 벡터를 어딘가엔 남겨야 한다. 완전히 버리면 되돌릴 수 없다.
  • 임계값 튜닝: 차원별 평균이 0에서 크게 벗어나면 0 대신 차원별 중앙값을 임계값으로 쓰는 편이 안전하다.

정리

이진 양자화는 고차원 임베딩에서 저장·메모리 비용을 32배 줄이는 검증된 기법이다. 핵심은 이진 검색으로 후보를 뽑고 원본으로 재정렬하는 2단계 구조다. 무작정 적용하기보다, 사용 중인 모델과 데이터로 recall을 먼저 측정하고 oversampling 비율을 조정하는 순서로 도입하면 품질 저하 없이 비용만 걷어낼 수 있다.