1언제 필요해?
- 시맨틱 검색 - 키워드가 아닌 의미로 문서 검색 ("강아지" 검색 시 "반려견" 문서도 반환)
- RAG (검색 증강 생성) - LLM에 관련 문서를 컨텍스트로 제공
- 추천 시스템 - 유사한 상품/콘텐츠 추천
- 이미지 검색 - 유사한 이미지를 찾는 역이미지 검색
2주요 서비스
Pinecone
SaaS, 가장 쉬움완전 관리형 벡터 DB. 설정이 간단하고 확장이 자동입니다. 서버리스 모델로 사용한 만큼만 과금됩니다.
pgvector
PostgreSQL 확장기존 PostgreSQL에 벡터 검색 기능을 추가하는 확장. 별도 서비스 없이 SQL로 벡터 검색이 가능합니다.
Qdrant
오픈소스Rust로 작성된 고성능 벡터 DB. 자체 호스팅 또는 클라우드 서비스로 사용할 수 있습니다. 필터링이 강력합니다.
ChromaDB
로컬 개발용Python 네이티브 벡터 DB. 로컬에서 바로 실행 가능하여 프로토타이핑과 개발 단계에 적합합니다.
3비용
- Pinecone - 무료 티어 100K 벡터 (서버리스), 1개 인덱스
- pgvector - PostgreSQL에 포함 (무료, 별도 비용 없음)
- Qdrant Cloud - 무료 티어 1GB 스토리지
- ChromaDB - 오픈소스 무료 (로컬 실행)
임베딩 API 비용에 주의
벡터 DB 자체는 무료/저렴하지만, 텍스트를 벡터로 변환하는 임베딩 API(OpenAI 등)에 별도 비용이 발생합니다. OpenAI text-embedding-3-small 기준 약 $0.02/1M 토큰입니다.
4연결 예제
FastAPI + pinecone-client (Python)
# app/vector_db.py
from pinecone import Pinecone
pc = Pinecone(api_key="your-api-key")
index = pc.Index("my-index")# app/main.py
from fastapi import FastAPI
from app.vector_db import index
import openai
app = FastAPI()
openai_client = openai.OpenAI()
def get_embedding(text: str) -> list[float]:
"""텍스트를 벡터로 변환"""
response = openai_client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
@app.post("/documents")
async def upsert_document(doc_id: str, text: str):
vector = get_embedding(text)
index.upsert(vectors=[{
"id": doc_id,
"values": vector,
"metadata": {"text": text}
}])
return {"id": doc_id, "status": "indexed"}
@app.get("/search")
async def search(query: str, top_k: int = 5):
query_vector = get_embedding(query)
results = index.query(
vector=query_vector,
top_k=top_k,
include_metadata=True
)
return [
{"id": m.id, "score": m.score, "text": m.metadata["text"]}
for m in results.matches
]Hono + @pinecone-database/pinecone (TypeScript)
// src/vector.ts
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'your-api-key' });
const index = pc.index('my-index');
export default index;// src/index.ts
import { Hono } from 'hono';
import index from './vector';
import OpenAI from 'openai';
const app = new Hono();
const openai = new OpenAI();
async function getEmbedding(text: string): Promise<number[]> {
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
});
return response.data[0].embedding;
}
app.post('/documents', async (c) => {
const { id, text } = await c.req.json();
const vector = await getEmbedding(text);
await index.upsert([{
id,
values: vector,
metadata: { text },
}]);
return c.json({ id, status: 'indexed' }, 201);
});
app.get('/search', async (c) => {
const query = c.req.query('q') || '';
const vector = await getEmbedding(query);
const results = await index.query({
vector,
topK: 5,
includeMetadata: true,
});
return c.json(
results.matches?.map((m) => ({
id: m.id,
score: m.score,
text: m.metadata?.text,
})) || []
);
});
export default app;임베딩 모델 선택
OpenAI text-embedding-3-small이 가성비가 좋습니다.
오픈소스 모델을 원하면 sentence-transformers(Python)로
로컬에서 임베딩을 생성할 수도 있습니다.