Choorai
Lv.4

벡터 데이터베이스

텍스트, 이미지 등을 벡터(숫자 배열)로 변환해 저장하고, 의미 기반 유사도 검색을 수행하는 특수 목적 데이터베이스입니다.

이게 뭐야?

텍스트/이미지를 벡터(숫자 배열)로 변환해 저장. 유사도 검색(시맨틱 검색)에 사용.

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
# app/vector_db.py
from pinecone import Pinecone

pc = Pinecone(api_key="your-api-key")
index = pc.Index("my-index")
app/main.py
# 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
// 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
// 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)로 로컬에서 임베딩을 생성할 수도 있습니다.

마지막 업데이트: 2026년 2월 22일 · 버전: v0.0.1

피드백 보내기

입력한 내용으로 새 이슈 페이지를 엽니다.

GitHub 이슈로 보내기