Supabase Hybrid Search vs FAISS/Chroma

pgvector + tsvector와 인메모리 벡터 DB 종합 비교

RAG · Vector Search · Postgres

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 1. 왜 하이브리드 검색인가

키워드와 의미, 둘 다 필요한 이유

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

단일 검색 방식의 한계

키워드 검색은 정확한 용어에 강하지만 동의어·의도를 놓치고, 시맨틱 검색은 의미는 잡지만 잡음과 false positive가 늘어난다. 'Italian recipes with tomato sauce' → 키워드는 '마리나라'를 놓치고, 시맨틱은 'Mexican salsa'까지 추천하는 식.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

하이브리드가 진짜로 필요한 워크로드

쇼핑(정확 매칭 + 유사 상품), 기술 문서(에러 코드 + 개념 검색), 사내 RAG(고유명사 + 자연어 질문), 법률·의료(고유 용어 + 의도 파악). 코드 검색은 거의 항상 키워드 우위, 멘탈헬스 포럼은 시맨틱 우위.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 2. pgvector 인덱스 알고리즘

HNSW와 IVFFlat의 동작 원리와 튜닝

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

HNSW: 다층 그래프 ANN

Hierarchical Navigable Small World는 위층에서 빠르게 후보를 좁히고 아래층에서 정밀 탐색하는 그래프 알고리즘. 데이터 없이도 인덱스 생성 가능. 메모리 사용 = (d4 + M2*4) bytes/vector. pgvector 0.7+ 권장 기본값.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

HNSW 인덱스 생성과 쿼리 튜닝

CREATE INDEX ON documents
  USING hnsw (embedding vector_ip_ops)
  WITH (m = 16, ef_construction = 64);

SET maintenance_work_mem = '8GB';
SET max_parallel_maintenance_workers = 7;

BEGIN;
  SET LOCAL hnsw.ef_search = 100;
  SELECT id FROM documents
  ORDER BY embedding <#> $1
  LIMIT 10;
COMMIT;
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

IVFFlat: 클러스터 기반 ANN

k-means로 lists 개 클러스터를 만들고 쿼리 시 probes 개만 탐색. 데이터를 먼저 적재한 뒤 빌드해야 의미가 있다. lists = rows/1000 (≤1M) 또는 sqrt(rows) (>1M), probes = sqrt(lists)부터 시작.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

HNSW vs IVFFlat 선택 기준

HNSW 선택

  • 빠른 쿼리·높은 recall이 우선
  • 데이터가 계속 증가
  • 빌드 시간·메모리 여유 있음
  • 기본값(m=16, ef_construction=64)으로 시작

IVFFlat 선택

  • 메모리 제약 강함
  • 데이터가 거의 정적
  • 빌드 시간 중요
  • 적절한 lists/probes 튜닝 가능
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 3. tsvector와 풀텍스트 검색

Postgres가 이미 가진 키워드 엔진

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

tsvector 컬럼과 GIN 인덱스

CREATE TABLE documents (
  id bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
  content text,
  fts tsvector GENERATED ALWAYS AS
    (to_tsvector('english', content)) STORED,
  embedding extensions.vector(512)
);

CREATE INDEX ON documents USING gin(fts);
CREATE INDEX ON documents
  USING hnsw (embedding vector_ip_ops);
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

ts_rank vs ts_rank_cd, 그리고 쿼리 파서

ts_rank는 빈도 기반, ts_rank_cd는 cover density(근접도)까지 반영. ts_rank_cd는 인덱서블하지 않으므로 반드시 WHERE @@ 으로 좁힌 집합에만 적용. 쿼리 파서는 websearch_to_tsquery — 사용자 입력 그대로 처리 가능.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 4. Postgres에서의 RRF 하이브리드 검색

두 검색을 SQL 한 함수로 합치기

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

RRF 공식과 smoothing constant k

score = Σ 1 / (k + rank_i). 각 검색 리스트에서의 순위 역수를 더한다. k가 작을수록 상위 노출 영향력 ↑, k=50~60이 일반적. 한쪽 리스트에 없으면 그 항목의 기여는 0. 단순하지만 다양한 평가에서 매우 강건.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Supabase hybrid_search SQL 함수

CREATE OR REPLACE FUNCTION hybrid_search(
  query_text text,
  query_embedding extensions.vector(512),
  match_count int,
  full_text_weight float DEFAULT 1,
  semantic_weight float DEFAULT 1,
  rrf_k int DEFAULT 50
) RETURNS SETOF documents LANGUAGE sql AS $$
WITH full_text AS (
  SELECT id,
    row_number() OVER (
      ORDER BY ts_rank_cd(fts, websearch_to_tsquery(query_text)) DESC
    ) AS rank_ix
  FROM documents
  WHERE fts @@ websearch_to_tsquery(query_text)
  ORDER BY rank_ix
  LIMIT LEAST(match_count, 30) * 2
),
semantic AS (
  SELECT id,
    row_number() OVER (ORDER BY embedding <#> query_embedding) AS rank_ix
  FROM documents
  ORDER BY rank_ix
  LIMIT LEAST(match_count, 30) * 2
)
SELECT documents.*
FROM full_text
  FULL OUTER JOIN semantic USING (id)
  JOIN documents ON documents.id = COALESCE(full_text.id, semantic.id)
ORDER BY
  COALESCE(1.0 / (rrf_k + full_text.rank_ix), 0) * full_text_weight +
  COALESCE(1.0 / (rrf_k + semantic.rank_ix), 0) * semantic_weight DESC
LIMIT LEAST(match_count, 30);
$$;
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

클라이언트에서 호출

const { data } = await supabase.rpc('hybrid_search', {
  query_text: '대출 상환 일정 조정',
  query_embedding: await embed(query),
  match_count: 10,
  full_text_weight: 1.0,
  semantic_weight: 1.0,
  rrf_k: 50,
});
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 5. FAISS와 Chroma

인메모리 벡터 DB의 인덱스 선택지

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

FAISS 인덱스 패밀리

Flat(정확·압축 없음·baseline) → IVFFlat(클러스터 + 정확) → IVF + PQ/OPQ(클러스터 + 압축) → HNSW(그래프) → RaBitQ(1bit/dim 극한 압축). index_factory 문자열로 조합 가능. GPU 지원은 Flat/IVF/PQ 등 일부.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

FAISS 인덱스 선택 가이드(공식)

규모별 추천 clustering

  • < 1M: IVF{4·sqrt(N) ~ 16·sqrt(N)}
  • 1M ~ 10M: IVF65536_HNSW32
  • 10M ~ 100M: IVF262144_HNSW32
  • 100M ~ 1B: IVF1048576_HNSW32

압축 정도별

  • 압축 없음: Flat
  • 약간: ...,Flat (IVF만)
  • 적당: OPQM_D,...,PQMx4fsr
  • 강한 압축: OPQM_D,...,PQM
  • 극한: RaBitQ
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

FAISS HNSW 인덱스 예시

import faiss, numpy as np

d = 768
index = faiss.IndexHNSWFlat(d, 32)   # M=32
index.hnsw.efConstruction = 200
index.hnsw.efSearch = 64

index.add(embeddings.astype('float32'))
D, I = index.search(query_vec, k=10)
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Chroma의 자리

기본 인덱스는 hnswlib 기반 HNSW. Python/TypeScript/Rust 클라이언트 제공. in-memory client는 휘발성 — production은 persistent client나 client-server, 또는 Chroma Cloud로 가야 함. metadata where 필터와 $contains substring 필터는 있지만 BM25는 아니라는 점 주의.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 6. 인메모리 환경에서의 하이브리드 검색

BM25 + FAISS를 애플리케이션 레이어에서 합치기

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

rank_bm25 + FAISS + RRF

from rank_bm25 import BM25Okapi
import faiss, numpy as np

bm25 = BM25Okapi([tokenize(d) for d in docs])
index = faiss.IndexHNSWFlat(768, 32)
index.add(embeddings)

def hybrid(query, k=10, rrf_k=50):
    bm25_scores = bm25.get_scores(tokenize(query))
    bm25_rank = np.argsort(-bm25_scores)[: k * 2]

    qv = embed(query).reshape(1, -1).astype('float32')
    _, dense_rank = index.search(qv, k * 2)
    dense_rank = dense_rank[0]

    fused = {}
    for rank, doc_id in enumerate(bm25_rank, start=1):
        fused[doc_id] = fused.get(doc_id, 0) + 1.0 / (rrf_k + rank)
    for rank, doc_id in enumerate(dense_rank, start=1):
        fused[doc_id] = fused.get(doc_id, 0) + 1.0 / (rrf_k + rank)

    return sorted(fused, key=fused.get, reverse=True)[:k]
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

키워드 엔진 선택지

rank_bm25(순수 Python, 수만 건까지), Whoosh(Pure Python, 디스크), Tantivy(Rust, Python 바인딩 tantivy-py, 한 자릿수~두 자릿수 빠름), Elasticsearch/OpenSearch(분산·운영기능 풍부). Production 규모면 Tantivy 또는 ES.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 7. 성능·메모리·운영 비교

수치로 보는 트레이드오프

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

지연시간 가이드라인 (768-dim, 1M 벡터)

Supabase pgvector HNSW

  • in-process: 2~10ms
  • 네트워크 RTT 포함: 5~20ms
  • 동시 쓰기 중 빌드 부담
  • 트랜잭션 보장

FAISS HNSW (in-process)

  • 1~5ms
  • Chroma HNSW: 3~10ms
  • 동시성 직접 제어
  • 영속화 직접 구현
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

메모리·운영 부담

메모리(HNSW M=16)

  • (d4 + M2*4) bytes/vec
  • 768-dim → ~3.2KB/vec
  • 1M → ~3.2GB
  • IVFFlat은 더 작음

운영 부담

  • Supabase: 백업·HA·RLS 제공
  • FAISS/Chroma: 영속화·복제·재인덱싱 직접
  • 클러스터링·샤딩 모두 자작
  • 인력 비용이 진짜 비용
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 8. 워크로드별 의사결정 가이드

무엇을 어디에 쓸 것인가

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

케이스 1: 사내 RAG / 검색 (≤ 1천만 문서)

이미 Postgres·Supabase를 쓰고 있다면 pgvector HNSW + tsvector + RRF SQL 함수가 최적. 트랜잭션·RLS·백업·조인을 그대로 활용. 별도 인프라 도입 없이도 한 자릿수~수십 ms 응답 가능.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

케이스 2: 대규모 추천·이미지·멀티미디어 (수억~)

FAISS IVF + PQ/OPQ/RaBitQ로 압축·샤딩. 키워드는 ES/OpenSearch나 Tantivy로 별도 운영. 운영 인력과 모니터링 비용을 충분히 산정. Chroma Cloud나 Pinecone/Qdrant 같은 매니지드 서비스도 검토.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

케이스 3: 프로토타입·연구

Chroma in-memory 또는 FAISS Flat으로 시작. 모델·청킹·평가 지표를 빠르게 반복. 영속성·동시성·HA가 필요해지는 순간 곧바로 다른 옵션으로 이동할 계획을 미리 세워둘 것.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

한국어·다국어 워크로드 주의

tsvector는 영어 외 언어에서 형태소 분석이 약함. 한국어가 핵심이면 mecab/khaiii 기반 토크나이저로 직접 토큰화해 tsvector를 만들거나, Elasticsearch + nori 같은 분석기를 별도 운영하는 편이 안전. 임베딩 모델은 다국어 모델 선택.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 9. 안티패턴과 마이그레이션 노트

흔히 빠지는 함정

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Top 5 안티패턴

  1. pgvector에 인덱스 없이 운영 → seq scan 폭발. 2) 거리 연산자와 ops 클래스 불일치로 인덱스 미사용. 3) RRF의 후보군을 너무 작게 잡아 두 검색의 교집합이 빈약. 4) 임베딩 모델 변경 시 차원·정규화 검증 부재. 5) 인메모리 DB를 무중단으로 운영하려는 시도.
Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

마이그레이션 체크리스트

거리 metric(L2/IP/Cosine)·정규화 여부 확인 → 임베딩 모델·차원 고정 및 메타데이터 기록 → 인덱스 빌드용 maintenance_work_mem과 max_parallel_maintenance_workers 사전 설정 → RRF k와 weight를 A/B로 튜닝 → Recall@k·nDCG로 회귀 테스트.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

"알고리즘은 모두 공개돼 있다. 차이는 운영 모델에서 난다."

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

Part 10. 결론

통합형 vs 전문형, 그리고 시작점

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

추천 시작점

대부분의 팀에 답은 명확하다 — pgvector HNSW + tsvector + RRF SQL 함수로 시작하라. 트래픽·데이터 규모·도메인 요구사항이 한계를 넘었다는 측정값이 나올 때만 FAISS/Chroma·전용 검색 엔진으로 부분 이전한다. 인프라 분기를 미리 만들지 말 것.

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것

감사합니다

Supabase Hybrid Search vs FAISS/Chroma 완벽 비교: pgvector + tsvector와 인메모리 벡터 DB의 모든 것