coredot.today
기술 탐색으로 돌아가기
검색·RAG성장

turbopuffer

오브젝트 스토리지 위에 세운 서버리스 검색 엔진 — 벡터를 '주인'에서 '색인 하나'로 내리는 중

직접 해보기 4빠른 시작
종류
서비스
사실 확인
2026.10.24
pip install turbopuffer

TRY IT

직접 해보기

OVERVIEW

개요

무엇인가

turbopuffer는 원본 데이터를 S3 같은 오브젝트 스토리지에 두고, 자주 쓰는 데이터만 NVMe SSD와 메모리 캐시로 올리는 서버리스 검색 서비스입니다. 2023년 10월 "최초의 진짜 서버리스 벡터 데이터베이스"로 출발해, 지금은 벡터 검색·BM25 전문 검색·필터·집계를 한 엔진에서 처리합니다. 커서, 노션, 앤트로픽, 리니어, 아틀라시안의 검색을 떠받칩니다.

출발점은 비용이었습니다. 창업자 사이먼 에스킬드센의 추산으로 1TB를 한 달 보관하는 데 메모리 + SSD 3중 복제는 최대 $3,600, S3 + SSD 캐시는 $70입니다. 대가는 첫 읽기 지연입니다. 768차원 벡터 100만 개 검색이 캐시에 없을 때 p90 444ms, 캐시에 있을 때 10ms였습니다.

2026년 9월 30일 회사 블로그의 「RIP, vector database」는 이 회사가 3년간 써 온 '벡터 우선' 저장 구조를 버린다는 선언입니다. 벡터 검색이 죽었다는 뜻이 아니라, 벡터 색인을 여러 보조 색인 중 하나로 내린다는 뜻입니다.

어떻게 동작하나

v1·v2는 모든 데이터를 ANN 클러스터 주소(클러스터 ID + 순번) 아래 저장했습니다. 그래프 색인(HNSW·DiskANN)은 한 걸음마다 앞 결과를 읽어야 다음 걸음을 정하므로, 왕복 한 번에 수십~수백 ms가 드는 S3와 맞지 않습니다. 클러스터 트리(SPANN → SPFresh)는 캐시에 둔 중심점만 보고 열어 볼 클러스터 몇 개를 정한 뒤 한 번에 병렬로 가져옵니다. 그런데 이 배치가 세 가지 증폭을 낳았습니다.

① 저장 증폭
문서를 벡터 여러 개로 표현하면(조각 임베딩, late interaction) 벡터마다 그 주소 아래 문서를 한 벌씩 붙여야 한다.
② 쓰기 증폭
SPFresh가 클러스터 균형을 맞추려 벡터를 옮기면, 문서 전체와 그 문서를 가리키는 속성·전문 검색 색인이 모두 따라 움직인다.
③ 갇힌 벡터화
집계·스캔이 클러스터 크기(100~200개) 블록에 묶인다. DuckDB는 2,048행, ClickHouse는 약 6만 5천 행 단위로 처리한다.
v3: 문서 우선
기본 키를 자동 생성 내부 ID(세그먼트 ID, 문서 ID)로 바꾸고, ANN·사용자 ID·속성·전문 검색 색인이 모두 그 ID를 가리킨다.

이미 겪어 본 일이기도 합니다. 전문 검색 v1은 포스팅 목록을 클러스터 경계대로 나눠 블록당 포스팅이 중앙값 약 1.5개였고, v2에서 약 256개 고정 블록으로 바꾸자 색인이 51.6GiB에서 5.22GiB로 줄고 질의는 최대 약 20배 빨라졌습니다. 이 결정의 원형은 보조 색인이 물리 위치 대신 기본 키를 담는 MySQL InnoDB의 클러스터드 인덱스입니다.

빠른 시작

공식 Python 클라이언트 README의 사용법입니다. 리전과 TURBOPUFFER_API_KEY가 필요합니다.

python
import os
from turbopuffer import Turbopuffer

tpuf = Turbopuffer(region="gcp-us-central1", api_key=os.environ.get("TURBOPUFFER_API_KEY"))
ns = tpuf.namespace("docs")

ns.write(
    upsert_rows=[
        {"id": 1, "vector": [0.1, 0.2], "text": "환불은 수령 후 14일 이내", "public": 1},
        {"id": 2, "vector": [0.3, 0.1], "text": "교환은 재고가 있을 때만", "public": 1},
    ],
    distance_metric="cosine_distance",
    schema={"text": {"type": "string", "full_text_search": True}},
)

# 벡터 근사 최근접 검색 + 속성 필터
print(ns.query(rank_by=("vector", "ANN", [0.1, 0.2]), top_k=10,
               filters=("public", "Eq", 1), include_attributes=["text"]).rows)

# 같은 네임스페이스에서 BM25 전문 검색
print(ns.query(rank_by=("text", "BM25", "환불 기한"), top_k=10).rows)

벡터는 직접 만들어 넣습니다. 임베딩 모델은 따로 고릅니다. 전문 검색의 언어·형태소 처리 설정은 스키마의 full_text_search 옵션으로 지정하므로, 한국어라면 토크나이저 동작을 먼저 확인합니다.

언제 쓰고, 언제 피하나

상황turbopuffer가 잘 맞는다다른 선택지를 먼저 본다
검색 종류키워드·벡터·필터·정렬을 한 엔진에서 섞는 하이브리드벡터를 필터·조인·트랜잭션과 한 쿼리로 섞어야 한다 — 쓰던 DB에 벡터를 더한다(pgvector 등)
데이터 위치검색 전용 저장소를 따로 둬도 된다이미 Postgres·레이크·S3에 있다 — 옮기지 않고 색인만 거는 선택지부터
지연 요구뜨거운 데이터는 수십 ms, 차가운 데이터는 첫 읽기가 느려도 된다드문 질의·배치 위주면 S3 Vectors 같은 오브젝트 스토리지 벡터가 더 싸다
질의자에이전트가 의미·키워드·필터 질의를 병렬로 많이 던진다사람이 가끔 묻는 내부 검색
운영검색 인프라를 직접 운영하고 싶지 않다폐쇄망·자체 호스팅이 필수다

고객 사례로는 커서가 출시 한 달 만에 옮겨 비용이 95% 줄었고, 노션이 100억 개 넘는 문서를 옮기며 80%, 리니어가 일래스틱서치와 pgvector를 함께 대체하며 70%를 줄였다고 turbopuffer가 공개했습니다(리니어 20억 문서에서 p50 13ms).

한계와 주의

  • v3는 아직 약속이다. 0일 차 공개 수치(문서 1천만 개, p90)에서 벡터 검색은 v2와 같거나 빨랐지만, 속성 정렬은 88배(1,767ms 대 20ms), 전문 검색은 19배 느렸다. v2와 성능이 같아진 뒤에 운영에 내보낸다고 했다.
  • "한 번 더 찾아가는" 비용. 논리 ID를 가리키는 색인은 읽을 때 색인 → 내부 ID → 문서로 한 단계가 더 든다. 그 한 단계가 S3 요청이면 비싸다. 캐시와 묶음 읽기로 얼마나 숨길지가 v3의 관건이다.
  • 첫 읽기는 느리다. 콜드 질의 지연(p90 444ms 사례)을 서비스 지연 예산에 넣는다.
  • 숫자 대부분이 회사 자료다. 비용 절감률·처리량은 turbopuffer와 고객사가 공개한 수치이고 독립 재현은 없다.
  • 제목에 대한 해커뉴스의 지적이 정확하다 — 끝난 것은 '벡터 데이터베이스'가 아니라 '벡터 우선 기본 인덱스'다.

DEEP DIVE

더 깊이 읽기