codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
노트›data

pgvector 와 RAG

2026-04-28 게시· 2026-05-18 갱신·0회 조회

pgvector 와 RAG

대규모 언어 모델 응답을 외부 지식과 결합하려는 흐름이 RAG (Retrieval-Augmented Generation) 라는 이름으로 자리 잡았습니다. 그 안에서 벡터 유사도 검색이 핵심 부품이고, PostgreSQL 의 pgvector extension 이 가장 가까운 자리에 있습니다.

1. pgvector 에 대한 이야기

pgvector 는 Andrew Kane 이 2021 년에 공개한 PostgreSQL extension 입니다. vector 타입과 거리 연산자, 그리고 벡터 인덱스 (IVFFlat · HNSW) 를 더합니다.

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE chunks (
  id BIGSERIAL PRIMARY KEY,
  doc_id BIGINT NOT NULL,
  content TEXT NOT NULL,
  embedding vector(1536) NOT NULL
);

거리 연산자.

연산자 거리
<-> L2 (유클리드)
<=> 코사인 거리
<#> 음수 내적 (inner product) — 작을수록 유사

ORDER BY embedding <=> $1 LIMIT 10 식으로 가장 가까운 K 개를 가져옵니다.

2. 벡터 유사도

텍스트·이미지를 고정 차원의 실수 벡터로 매핑하면, 의미가 가까운 항목이 벡터 공간에서도 가깝게 배치된다는 가정이 출발점입니다. 거리 측정 방식은 세 가지가 흔합니다.

  • 코사인 유사도 — 방향만 봅니다. 길이 차이를 무시.
  • L2 (유클리드) — 길이까지 봅니다.
  • 내적 (inner product) — 정규화된 벡터끼리는 코사인과 사실상 같습니다.

OpenAI · Cohere 같은 임베딩 API 응답은 보통 정규화돼 있어 코사인이 자주 쓰입니다. 모델 문서가 권장 거리를 명시하는 경우가 많습니다.

3. IVFFlat

브루트포스 (Seq Scan + 거리 계산) 는 작은 데이터에서는 충분히 빠릅니다. 데이터가 커지면 ANN (Approximate Nearest Neighbor) 인덱스를 씁니다.

IVFFlat 은 벡터 공간을 K 개의 클러스터로 사전 분할 (lists) 하고, 검색 시 가장 가까운 일부 클러스터 (probes) 만 봅니다.

CREATE INDEX ON chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

SET ivfflat.probes = 10;
SELECT id FROM chunks ORDER BY embedding <=> $1 LIMIT 10;
  • 빌드 빠름 · 메모리 적음.
  • 정확도와 속도가 lists · probes 의 균형에서 결정됩니다.
  • 데이터가 많이 들어온 후 인덱스를 만들어야 클러스터링 품질이 좋습니다.

4. HNSW

Yu. A. Malkov · D. A. Yashunin 의 2018 년 논문에서 제안된 알고리즘입니다. 다층 그래프를 만들어 가까운 이웃을 빠르게 찾습니다.

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

SET hnsw.ef_search = 40;
  • 검색 정확도·속도가 일반적으로 우수합니다.
  • 인덱스 크기·빌드 시간이 IVFFlat 보다 큽니다.
  • 점진적 추가에 강합니다.

pgvector 0.5 이후 HNSW 가 들어왔고 이후 버전에서 성능·메모리가 개선됐습니다.

5. 임베딩 모델

모델 제공 차원 메모
OpenAI text-embedding-3-small OpenAI API 1536 (또는 축소 가능) 다국어 · 비교적 저렴
OpenAI text-embedding-3-large OpenAI API 3072 고품질
Cohere embed-multilingual-v3.0 Cohere API 1024 다국어 강함
BGE (BAAI) 오픈 가중치 384/768/1024 자체 호스팅 가능
nomic-embed-text Nomic 768 오픈 가중치
Sentence-Transformers 오픈 다양 작은 모델 다수

차원이 클수록 정확도가 일반적으로 오르지만 저장·검색 비용도 비례합니다. Matryoshka 임베딩처럼 차원을 사후에 줄일 수 있는 모델도 있습니다.

6. 별도 벡터 DB 와의 비교

시스템 출자·시기 메모
Pinecone 2019, 매니지드 SaaS 운영 단순 · 비용은 사용량 기반
Qdrant 2021, Rust 자가 호스팅 가능 · 필터링 강함
Weaviate 2019, Go 모듈식 · 하이브리드 검색
Milvus 2019, 오픈 대규모 · GPU 가속
Chroma 2022, Python 로컬 개발 친화
Vespa 2017 오픈소스화 (Yahoo) 검색·랭킹·벡터 결합
Elasticsearch · OpenSearch 2010 / 2021 풀텍스트 + 벡터 (kNN)

별도 벡터 DB 의 강점.

  • 매우 큰 규모 (수십억 이상) · 분산 샤딩.
  • 사전 필터링·메타데이터 결합이 빠른 경우가 많음.
  • 벡터 전용 운영 도구 (통계·튜닝).

pgvector 의 강점.

  • 한 DB 안에서 벡터 + 관계형 데이터 + 트랜잭션을 결합.
  • 운영 표면이 한 곳 (백업·인증·모니터링이 PostgreSQL 하나).
  • 작은~중간 규모에서 충분한 성능.

선택은 데이터 규모·운영 인력·정확도 요구의 균형입니다.

7. RAG 파이프라인

원본 → 청킹 → 임베딩 → 저장 → 검색 → reranking → LLM 컨텍스트 → 응답

청킹 — 문서를 작은 조각으로 나눕니다. 너무 크면 검색의 조준이 흐려지고 너무 작으면 의미가 흩어집니다.

  • 토큰·문자 수 고정 (예: 512 토큰, 50 토큰 오버랩).
  • 마크다운 헤딩·문장 경계 기반.
  • 의미 기반 (다른 모델로 경계 추정).

임베딩·저장 — 청크별 임베딩을 모델 API 또는 로컬 모델로 계산해 vector 컬럼에 저장합니다. 메타데이터 (문서 ID · 출처 URL · 작성일 · 태그) 도 함께 컬럼으로 둡니다.

검색 — 쿼리를 같은 모델로 임베딩하고 <=> 로 가장 가까운 K 개를 가져옵니다. 메타데이터 필터 (작성일·문서 종류) 와 결합하는 자리에서 RDBMS 의 WHERE 가 강점이 됩니다.

8. Reranking 과 하이브리드 검색

벡터 검색은 빠르지만 의미 정확도에 한계가 있습니다. 1 차로 3050 개를 가져온 뒤 cross-encoder · LLM 으로 재정렬해 상위 510 개를 LLM 컨텍스트로 보냅니다. Cohere Rerank · BGE Reranker · cross-encoder/ms-marco 같은 모델이 거론됩니다.

하이브리드 검색은 키워드 검색 (BM25 · tsvector) + 벡터 검색을 결합하는 방식입니다. 약어·고유명사가 많은 문서에서 키워드가 보완 역할을 합니다. RRF (Reciprocal Rank Fusion) 같은 단순한 결합 함수가 자주 쓰입니다.

9. 자주 걸리는 자리

모델 변경 후 재임베딩 의무 — 임베딩 모델을 바꾸면 벡터 공간이 달라집니다. 옛 벡터와 새 쿼리는 서로 다른 공간이라 비교 무의미. 마이그레이션 계획을 처음에 가집니다.

차원 불일치 — vector(1536) 컬럼에 다른 차원을 넣으려 하면 에러입니다. 모델별 차원을 분리 컬럼·테이블로.

인덱스 빌드 시점 — 데이터가 적을 때 IVFFlat 을 만들면 클러스터링이 부족합니다. 일정 양 적재 후 인덱스 생성을 권장합니다.

거리 연산자와 인덱스 일치 — 인덱스를 vector_cosine_ops 로 만들었으면 <=> 만 인덱스를 씁니다. 다른 연산자는 Seq Scan 입니다.

청크 경계의 의미 끊김 — 문장 중간에서 잘리면 검색이 흐려집니다. 오버랩 또는 경계 정렬.

컨텍스트 윈도 초과 — 검색 결과를 모두 LLM 에 넣으면 토큰 한도를 넘습니다. reranking 과 요약을 결합합니다.

하고픈 말

벡터 검색은 구현보다 청킹·reranking·메타데이터 설계가 더 어렵습니다. 인덱스 종류·차원 선택은 한 번 결정하면 다시 바꾸기가 부담이라 처음에 신중히 결정합니다.

Next

  • supabase
  • fcm-push

pgvector GitHub · pgvector 인덱스 가이드 · HNSW 논문 · OpenAI Embeddings · Pinecone Learn — RAG · Cohere Rerank 를 참고합니다.

data 카테고리의 다른 글

카테고리 전체 보기 →
  • DB 시드 소스를 코드 트리 안에 두지 않는다
  • Supabase Storage — 파일 업로드와 권한
  • Kafka 실무 — 토픽 설계와 메시지 흐름
  • 여러 PostgreSQL 풀 한 앱에서 관리하기
  • 백업과 복구
  • 이미지 파이프라인