2. Vector DB & Embedding

"이 문서에서 지금 질문과 의미가 비슷한 내용을 찾아줘" — 이걸 키워드 검색으로는 할 수 없습니다. 의미 기반 검색을 가능하게 하는 것이 Embedding(임베딩)이고, 그 결과를 효율적으로 저장하고 검색하는 것이 Vector DB입니다.

1. Embedding — 의미를 숫자 벡터로 표현

Embedding 모델은 텍스트를 수백~수천 개의 숫자로 이루어진 벡터로 변환합니다. 의미가 비슷한 텍스트는 벡터 공간에서 가까이 위치합니다.

의미가 비슷한 텍스트 → 벡터 공간에서 가까움 (간략화된 시각화)
"고양이가 뛴다"
[0.82, 0.14, -0.33, ...]
"The cat runs"
[0.80, 0.16, -0.31, ...]
↑ 코사인 유사도 0.98 (거의 동일한 의미)
"서버가 다운됐다"
[0.12, -0.67, 0.55, ...]
↑ 코사인 유사도 0.21 (완전히 다른 의미)
코사인 유사도 — 벡터 간 "방향"이 얼마나 같은가

두 벡터 사이의 코사인 유사도는 -1(반대) ~ 1(동일) 범위입니다. 실무에서는 threshold를 0.75~0.85 사이로 설정해서 유사도가 그 이상인 결과만 사용합니다. 내적(Dot Product)도 유사도 측정에 쓰이는데, 벡터가 정규화된 경우 코사인 유사도와 동일합니다. 대부분의 Vector DB는 ANN(Approximate Nearest Neighbor) 검색으로 정확도를 조금 포기하고 속도를 크게 높입니다.

2. Vector DB 선택 기준

솔루션타입특징적합한 경우
pgvector PostgreSQL 확장 기존 PostgreSQL에 벡터 칼럼 추가, SQL JOIN 가능 이미 PostgreSQL을 쓰고 있고 규모가 수백만 건 이하
Pinecone Managed SaaS 운영 부담 없음, 자동 스케일링 빠른 프로토타이핑, DevOps 여력 없는 팀
Qdrant OSS / Managed Rust 기반 고성능, 필터링 강력, Self-hosted 가능 메타데이터 필터 복잡한 검색, 대용량 (수억 건)
Weaviate OSS / Managed GraphQL API, 하이브리드 검색 내장 하이브리드 검색(키워드+벡터) 바로 필요할 때
pgvector — 가장 쉬운 시작점
-- PostgreSQL에 벡터 타입 추가
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
    id BIGSERIAL PRIMARY KEY,
    content TEXT,
    embedding vector(1536) -- OpenAI 임베딩 차원
);

-- 유사도 검색 (코사인)
SELECT content, 1 - (embedding <=> $1) AS score
FROM documents
ORDER BY embedding <=> $1  -- <=> : 코사인 거리
LIMIT 5;

-- 인덱스 (대용량 시 필수)
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
Embedding 생성 (Java)
// Spring AI 또는 직접 호출
@Service
public class EmbeddingService {
    private final RestTemplate rest;

    public float[] embed(String text) {
        var body = Map.of("input", text,
            "model", "text-embedding-3-small");
        var res = rest.postForObject(
            "https://api.openai.com/v1/embeddings",
            body, EmbeddingResponse.class);
        return res.getData().get(0).getEmbedding();
    }
}

// 저장
documentRepo.save(new Document(
    content, embeddingService.embed(content)));

// 검색
List<Document> similar =
    documentRepo.findSimilar(
        embeddingService.embed(query), 5);

3. RDB와 Vector DB의 차이

같이 써야 하는 이유

Vector DB는 "의미 유사도"만 검색합니다. 정확한 값 필터링(userId=123, status='active')은 RDB가 합니다. 실무에서는 둘을 함께 씁니다: PostgreSQL에 사용자 데이터와 벡터를 함께 저장하거나(pgvector), Qdrant에 벡터를 저장하되 메타데이터 필터(userId, category)도 함께 걸어서 검색합니다. 예를 들어 "이 사용자(userId=123)의 과거 주문 중에서 현재 질문과 유사한 것 찾기" 같은 쿼리가 메타데이터 필터 + 벡터 유사도 검색 조합으로 해결됩니다.

4. 면접 대비 핵심 Q&A

Q1. "Vector DB와 기존 RDB의 차이를 설명해주세요."

RDB는 정확한 값 일치나 범위 검색에 최적화되어 있습니다(WHERE id = 1, WHERE age > 20). Vector DB는 의미적 유사성 검색에 최적화되어 있습니다. 텍스트를 고차원 숫자 벡터로 변환해서 저장하고, 쿼리도 벡터로 변환해서 가장 가까운 벡터를 찾습니다. "고양이 사진 찾기"나 "이 질문과 비슷한 FAQ 찾기" 같은 작업은 RDB로 할 수 없고 Vector DB가 필요합니다. 실무에서는 두 가지를 함께 사용합니다 — 메타데이터 필터는 RDB, 의미 검색은 Vector DB.

Q2. "Embedding 차원(dimension) 크기가 성능에 어떤 영향을 미치나요?"

차원이 클수록 더 정밀하게 의미를 표현할 수 있지만, 저장 공간과 검색 시간이 증가합니다. OpenAI text-embedding-3-small은 1536차원, large는 3072차원입니다. 대용량(수천만 건 이상)에서는 차원 축소(PCA 등) 또는 양자화(int8)로 메모리를 줄이기도 합니다. pgvector는 최대 2000차원, 전용 Vector DB(Qdrant 등)는 제한이 없습니다.

핵심 한 줄

Embedding은 의미를 벡터로 표현하고, Vector DB는 코사인 유사도로 "의미가 비슷한 것"을 찾는다. 시작은 pgvector로, 대용량/복잡한 필터는 Qdrant로.