본문 바로가기
DB/PostgreSQL

[PostgreSQL] pgvector : 고속 벡터 검색부터 하이브리드 RRF 융합까지

by coding_whale 2026. 6. 11.
반응형

1. 들어가며: 왜 관계형 데이터베이스에서 벡터를 검색하는가?

ChatGPT와 대형 언어 모델(LLM)의 폭발적인 성장 이후, 기업 내부에 잠들어 있는 고유 정보나 가공되지 않은 텍스트 자산을 AI에 주입하여 답변 신뢰성을 높이는 RAG(Retrieval-Augmented Generation, 검색 증강 생성) 아키텍처는 백엔드 인프라의 표준으로 자리 잡았다. RAG의 성패를 가르는 핵심은 사용자의 프롬프트 질문과 가장 연관성이 깊은 사내 지식 베이스를 데이터베이스에서 고속으로 탐색하여 컨텍스트로 결합해 주는 의미론적 검색(Semantic Search)에 있다.

과거에는 별도의 벡터 전용 NoSQL 데이터베이스(Pinecone, Milvus 등)를 추가 도입하여 데이터를 분산 이원화 관리하곤 했다. 하지만 이는 인프라 파이프라인의 복잡도를 가중시키고 실시간 트랜잭션의 정합성 유지 비용을 폭증시킨다.

 

[PostgreSQL] Transaction: 격리 수준과 MVCC 아키텍처 완벽 가이드

1. 들어가며: 물류 데이터와 무결성 제어의 절대 조건이커머스나 공급망 관리(SCM) 시스템에서 "재고 차감"이나 "창고 간 입출고"와 같은 물류 연산은 한 치의 오차도 허용되어서는 안 된다. 수천

myblog01150.tistory.com

 

PostgreSQL은 오픈소스 데이터 확장 익스텐션인 pgvector를 통해 관계형의 견고한 강점을 보존하면서 다차원 임베딩 벡터 데이터를 이진 트리 레벨에서 초고속으로 색인 및 탐색할 수 있는 탁월한 통합 솔루션을 제공한다. 본 포스팅에서는 사내 기술 위키 및 지식 베이스 검색 엔진 비즈니스 모델을 기준으로 pgvector의 진면목을 깊이 있게 파헤친다.

 

 

2. pgvector 환경 구축 및 가변 지식 베이스 스키마 설계

PostgreSQL 환경에 pgvector 모듈을 로드하고, 8차원의 가상 기술 문서 임베딩 값을 적재할 wiki_embeddings 테이블을 구축하여 실습을 위한 준비 과정을 진행해 본다.

-- 1. pgvector 익스텐션 활성화 및 설치 상태 진단
CREATE EXTENSION IF NOT EXISTS vector;
SELECT * FROM pg_extension WHERE extname = 'vector';

-- 2. 사내 기술 위키 지식 베이스 테이블 설계
CREATE TABLE wiki_embeddings (
    doc_id      SERIAL PRIMARY KEY,
    content     TEXT NOT NULL,
    embedding   VECTOR(8) -- 8차원 임베딩 벡터를 보관하는 물리 타입
);

-- 3. 실무 지식 베이스 도메인 예제 데이터 적재
INSERT INTO wiki_embeddings (content, embedding) VALUES
    ('서버 이중화 구성 가이드',        '[0.12, 0.85, 0.09, 0.72, 0.15, 0.91, 0.32, 0.44]'),
    ('네트워크 이중화 및 장애 복구',    '[0.15, 0.83, 0.11, 0.70, 0.18, 0.88, 0.35, 0.42]'),
    ('사용자 인증 및 권한 관리',        '[0.85, 0.12, 0.65, 0.38, 0.79, 0.22, 0.51, 0.31]'),
    ('OAuth2 로그인 보안 규약',        '[0.82, 0.15, 0.63, 0.40, 0.76, 0.25, 0.53, 0.33]'),
    ('데이터베이스 백업 정책',          '[0.35, 0.55, 0.78, 0.21, 0.45, 0.62, 0.88, 0.25]'),
    ('PostgreSQL 시점 복구(PITR)',   '[0.32, 0.58, 0.75, 0.24, 0.42, 0.65, 0.85, 0.28]'),
    ('컨테이너 빌드 자동화 가이드',     '[0.55, 0.68, 0.29, 0.81, 0.32, 0.78, 0.18, 0.62]'),
    ('CI/CD 파이프라인 구축',          '[0.52, 0.70, 0.27, 0.83, 0.30, 0.75, 0.20, 0.65]'),
    ('모니터링 대시보드 설정',          '[0.22, 0.45, 0.41, 0.55, 0.91, 0.38, 0.68, 0.72]'),
    ('Grafana 지표 시각화',            '[0.20, 0.48, 0.39, 0.57, 0.89, 0.41, 0.65, 0.75]');

 

 

3. 다차원 벡터의 3가지 핵심 거리 측정 연산 법칙

벡터 검색 시스템의 핵심은 두 고차원 벡터 간의 유사도를 판별하는 기하학적 연산에 있다. pgvector는 실무 환경의 다양한 통계 모델에 맞춰 세 가지 핵심 내장 거리 연산자를 제공한다.

3.1 코사인 거리 (Cosine Distance) <=>

코사인 거리는 두 벡터의 크기(Magnitude)는 완전히 배제하고, 오직 다차원 공간 상에서 두 벡터가 가리키는 '각도(방향성)'의 일치 여부만을 판정한다. 데이터의 절대량이나 길이의 차이와 무관하게 텍스트의 본질적인 문맥 주제 유사도를 정확하게 집어낼 수 있어 대다수의 RAG 의미론적 유사 검색에서 표준 카드로 채택된다.

코사인 거리 $d_{\text{cosine}}$은 수학적으로 코사인 유사도 $S_{\text{cosine}}$의 역수로 정의된다. 두 벡터 $u, v$에 대하여 다음과 같이 산출된다.

$$S_{\text{cosine}}(u, v) = \frac{u \cdot v}{\|u\| \|v\|}$$$$d_{\text{cosine}}(u, v) = 1 - S_{\text{cosine}}(u, v)$$

-- '서버 이중화 구성 가이드' 벡터를 질의로 설정하고 방향성 기준으로 가장 가까운 상위 5개 검색
SELECT
    content,
    embedding <=> '[0.12, 0.85, 0.09, 0.72, 0.15, 0.91, 0.32, 0.44]' AS 코사인거리
FROM wiki_embeddings 
ORDER BY 코사인거리
LIMIT 5;

 

3.2 L2 유클리드 거리 (Euclidean Distance) <->

유클리드 거리는 다차원 공간 상에서 두 벡터의 종단점을 일직선으로 이은 '직선 거리'를 실측한다. 단순히 방향성뿐만 아니라 값의 물리적 크기 자체도 비교군으로 중요하게 반영되어야 하는 이미지 군집 분석이나 수치 통계 모델링 분석에서 주로 활용된다.

두 벡터 $u, v$의 유클리드 거리 $d_{\text{L2}}$는 다음과 같은 수식으로 정리된다.

$$d_{\text{L2}}(u, v) = \sqrt{\sum_{i=1}^{n} (u_i - v_i)^2}$$

-- '계좌 이체' 성격에 빗댄 'OAuth2 로그인 보안 규약' 벡터를 타겟으로 직선 거리 최적 항목 검출
SELECT
    content,
    embedding <-> '[0.82, 0.15, 0.63, 0.40, 0.76, 0.25, 0.53, 0.33]' AS L2거리
FROM wiki_embeddings 
ORDER BY L2거리
LIMIT 5;

 

3.3 음의 내적 거리 (Negative Inner Product) <#>

내적 거리는 두 벡터의 방향성 일치와 물리적 크기를 모두 결합하여 누적 연산한 값이다. 임베딩 모델을 거쳐 생성된 벡터들의 크기(L2 Norm)가 사전에 모두 1로 정규화(Normalize)된 상태라면, 수학적으로 코사인 유사도 연산과 완벽히 동치인 결과를 내면서 복잡한 루트 계산 분모 연산이 생략되므로 내부적인 연산 속도가 가장 빠른 극강의 성능 우위를 가져온다.

내적 값을 거리 척도(작을수록 정렬 우선순위가 높음)로 쓰기 위해 pgvector는 결과값에 음수를 취한 Negative Inner Product 방식을 채택하고 있다.

$$d_{\text{IP}}(u, v) = - (u \cdot v) = - \sum_{i=1}^{n} u_i v_i$$

-- 'CI/CD 파이프라인 구축' 벡터를 기준으로 가장 내적 거리가 일치하는 상위 5개 정렬
SELECT
    content,
    embedding <#> '[0.52, 0.70, 0.27, 0.83, 0.30, 0.75, 0.20, 0.65]' AS 내적거리
FROM wiki_embeddings 
ORDER BY 내적거리
LIMIT 5;

 

 

4. 고속 인덱싱의 양대 지식: IVFFLAT vs HNSW 인덱스 아키텍처

인덱스가 없는 최초 상태에서의 벡터 검색은 모든 개별 행의 벡터 거리를 하나씩 전수 조사하여 정렬하는 $O(N)$의 비효율적인 완전 스캔인 KNN (K-Nearest Neighbor) 방식을 수반한다. 데이터가 수백만 건에 도달하면 쿼리 엔진은 지연 오버헤드를 견디지 못한다.

PostgreSQL pgvector는 이를 타개하기 위해 두 가지 강력한 근사 최근접 이웃(ANN, Approximate Nearest Neighbor) 물리 인덱스를 마련하고 있다.

4.1 IVFFLAT (Inverted File with Flat) 인덱스

IVFFLAT은 전체 벡터 공간 상에서 K-평균 군집화(K-Means Clustering) 알고리즘을 구동하여 유사 벡터들을 지정된 개수(lists)의 클러스터 영역으로 미리 분할해두는 방식이다.

-- IVFFLAT 인덱싱 구축 구문
CREATE INDEX idx_ivfflat_wiki_embedding
    ON wiki_embeddings USING ivfflat (embedding vector_cosine_ops)
    WITH (lists = 3);
  • 동작 매커니즘: 질의 벡터가 인입되면 모든 데이터를 뒤지는 대신 가장 인접한 상위 중심점(Centroid) 블록을 가려내어, 해당 클러스터 내부의 벡터 집합들만 순차적으로 수색한다.
  • 장단점: 인덱스를 구성하는 시간 자체가 매우 짧고 물리적인 인덱스 메모리 점유가 극도로 낮아 서버 가용 자원을 크게 절약하지만, 클러스터의 경계 영역에 애매하게 겹쳐 있는 타겟 데이터를 누락할 확률이 존재하여 완벽한 정확도가 요구되는 정교한 검색에서는 소폭 한계를 보인다.

 

4.2 HNSW (Hierarchical Navigable Small World) 인덱스

HNSW는 다차원의 벡터들을 서로 연결하는 관계 지향적 계층 구조의 멀티레이어 그래프를 형성해 검색을 가속하는 최신 아키텍처다.

-- HNSW 인덱싱 구축 구문
CREATE INDEX idx_hnsw_wiki_embedding
    ON wiki_embeddings USING hnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 64);
  • 핵심 제어 파라미터:
    • m: 각 벡터 노드가 그래프를 연결해 나갈 때 맺을 수 있는 최대 이웃 노드의 연결 링크 개수다. 이 값이 클수록 탐색의 경로가 촘촘해져 검색 정확도가 완벽에 가깝게 도달하지만 물리 인덱스 크기도 정비례하여 팽창한다.
    • ef_construction: 인덱스 트리를 최초에 빌드(Construction)할 때 면밀히 탐색하고 비교해 볼 후보 노드의 최대 크기다. 이 값이 커질수록 그래프가 대단히 튼튼하게 설계되어 고품격 검색이 보장되지만 인덱싱 시간 자체는 상당히 연장된다.
  • 장단점: IVFFLAT 대비 월등하게 뛰어난 검색 정확도를 사수하며, 신규 데이터(INSERT)가 실시간으로 수없이 인입되는 동적인 런타임 환경에서도 완벽한 안정성을 견지한다. 그러나 그래프 결합을 위해 상당히 비대한 서버 메모리 자원($RAM$)을 점유하고 인덱스 빌드 비용 자체가 매우 묵직하다는 이면이 존재한다.

 

 

5. 검색의 궁극적 완성: Full-Text Search와 벡터의 하이브리드 RRF 융합

실무 환경에서 '의미론적 벡터 검색'이 무조건 전능한 구원투수인 것은 아니다. 예를 들어 사용자가 정확한 특정 고유 식별자(예: "OAuth2", "PITR", "SKU-402")나 완벽히 매칭되어야만 하는 고유 키워드를 입력해 쿼리했을 때, 벡터 임베딩 모델의 의미 분산 처리 오류로 인해 엉뚱한 서버 이중화 문서가 검색되는 해프닝이 흔히 발생한다.

따라서 가장 완벽한 프로덕션 등급의 엔터프라이즈 검색 엔진은 전통적인 형태소 키워드 완전 일치 검색인 FTS (Full-Text Search)와 문맥 의미 탐색인 Vector Search의 장점을 하나로 결합한 하이브리드 검색(Hybrid Search)으로 설계된다.

 

5.1 단순 점수 가중치 결합 (Weighted Score Join)

가장 원초적인 결합 방식으로 두 검색 방식에서 각각 산출된 순수 원시 스코어를 단순 외부 아우터 조인(FULL OUTER JOIN)으로 엮어 가중치 합산 정렬을 가동한다.

-- FTS 스코어와 벡터 유사 스코어를 단순 더해 순위 매칭
WITH fts_results AS (
    SELECT
        doc_id,
        content,
        ts_rank(
            to_tsvector('simple', content),
            to_tsquery('simple', '이중화')
        ) AS fts_score
    FROM wiki_embeddings
    WHERE to_tsvector('simple', content) @@ to_tsquery('simple', '이중화')
),
vec_results AS (
    SELECT
        doc_id,
        content,
        -- 코사인 거리를 코사인 유사도 점수 영역(0~1)으로 스케일 변환
        1 - (embedding <=> '[0.12, 0.85, 0.09, 0.72, 0.15, 0.91, 0.32, 0.44]') AS vec_score
    FROM wiki_embeddings
    ORDER BY embedding <=> '[0.12, 0.85, 0.09, 0.72, 0.15, 0.91, 0.32, 0.44]'
    LIMIT 5
)
SELECT
    COALESCE(f.doc_id, v.doc_id) AS doc_id,
    COALESCE(f.content, v.content) AS content,
    COALESCE(f.fts_score, 0) AS fts_score,
    COALESCE(v.vec_score, 0) AS vec_score
FROM fts_results f
FULL OUTER JOIN vec_results v ON f.doc_id = v.doc_id
ORDER BY (COALESCE(f.fts_score, 0) + COALESCE(v.vec_score, 0)) DESC;

⚠️ 원시 스코어 가산의 함정: FTS 점수 스케일(ts_rank 수치는 문서 크기와 빈도에 따라 수십, 수백점 이상 치솟을 수 있음)과 코사인 유사도 점수 영역(0에서 1 사이 고정)은 물리 점수 분포의 기준값 자체가 완전히 달라, 정규화 없이 가산하면 한쪽 검색 방식의 스코어가 다른 쪽 스캔 영향력을 통째로 묵살해 버리는 성능 왜곡이 생긴다.

 

5.2 상상 그 이상의 정밀함: RRF (Reciprocal Rank Fusion) 알고리즘

하이브리드 성능 최적화의 글로벌 표준인 RRF는 각 검색 엔진이 리턴하는 원시 점수 값은 완벽하게 배제하고, 오직 검색 결과들의 '상대적 순위(Rank)' 정보만을 기반으로 가중 점수를 통합해 정렬한다.

RRF 점수 $RRF_{\text{score}}$는 상수 $k$(일반적으로 실무 표준 권장치인 $60$ 적용)에 대하여 각 검색 방식에서의 랭킹 $r_{\text{fts}}, r_{\text{vec}}$를 기반으로 다음과 같은 수식을 정밀 수렴시켜 판정한다.

$$RRF_{\text{score}}(d) = \sum_{m \in M} \frac{1}{k + r_m(d)}$$$$RRF_{\text{score}}(d) = \frac{1}{k + r_{\text{fts}}(d)} + \frac{1}{k + r_{\text{vec}}(d)}$$

이 방식을 사용하면 FTS 랭킹의 상위권 문서들과 벡터 검색 상위권 문서들이 아주 조화롭고 공정하게 정규화되어, 고유명사 매칭과 세만틱 탐지가 조화롭게 정돈된 최상 품질의 RAG 추천 결과를 반환할 수 있게 된다.

-- RRF (상호 순위 융합) 하이브리드 검색 구현 쿼리
WITH fts_ranked AS (
    SELECT
        doc_id,
        content,
        -- 1. FTS 형태소 검색 결과 기준 내부 랭킹 부여
        ROW_NUMBER() OVER (
            ORDER BY ts_rank(
                to_tsvector('simple', content),
                to_tsquery('simple', '이중화')
            ) DESC
        ) AS fts_rank
    FROM wiki_embeddings
    WHERE to_tsvector('simple', content) @@ to_tsquery('simple', '이중화')
),
vec_ranked AS (
    SELECT
        doc_id,
        content,
        -- 2. pgvector 거리 연산 결과 기준 내부 랭킹 부여
        ROW_NUMBER() OVER (
            ORDER BY embedding <=> '[0.12, 0.85, 0.09, 0.72, 0.15, 0.91, 0.32, 0.44]'
        ) AS vec_rank
    FROM wiki_embeddings
    LIMIT 5
)
-- 3. 두 순위 결과를 상호 순위 수식으로 융합 결합
SELECT
    COALESCE(f.doc_id, v.doc_id) AS doc_id,
    COALESCE(f.content, v.content) AS content,
    ROUND((
        COALESCE(1.0 / (60 + f.fts_rank), 0) +
        COALESCE(1.0 / (60 + v.vec_rank), 0)
    )::NUMERIC, 6) AS rrf_score
FROM fts_ranked f
FULL OUTER JOIN vec_ranked v ON f.doc_id = v.doc_id
ORDER BY rrf_score DESC;

 

 

6. 마치며: 초격차 지능형 검색 엔진 구성을 위한 실무 아키텍처 체크리스트

PostgreSQL pgvector를 프로덕션 환경의 고부하 시점에도 흔들림 없이 가동하기 위한 최적의 엔지니어링 체크 가이드를 인포그래픽 카드로 요약 매핑하며 학습을 정리해 본다.

실무 데이터 아키텍트 가이드라인 3종

  1. 임베딩 모델과 연산자의 완벽한 합치: 사용하려는 임베딩 모델(예: OpenAI, Voyage, Cohere 등)의 반환 차원 크기를 면밀히 확인해 VECTOR(N) 데이터 타입을 정의하고, 모델이 L2 정규화를 자체 수행해 준다면 연산 오버헤드를 극단적으로 덜어내는 음의 내적 연산자(<#>)와 인덱스를 우선 매핑할 것.
  2. ANN 인덱스의 영리한 저울질:
    • 데이터 인서트 트래픽이 많지 않고 오직 실시간 최상의 품질과 정확도만 사수해야 한다면 지체 없이 HNSW 인덱스를 설계하되, 메모리 한계치를 고려해 m과 ef_construction 수치를 리소스에 알맞게 타협 조율할 것.
    • 반면 인덱스 구성 자원을 아끼고 쓰기 속도를 극한으로 올려야 하는 초대형 로그 성격의 세만틱 인프라는 IVFFLAT을 디폴트로 삼아 lists 파티션 범위를 적절히 튜닝해 대응할 것.
  3. 상호 순위 융합(RRF)의 기본 장착: 고유명사나 품번 및 코드 식별 위주의 단순 키워드 질의는 Vector 검색에서 문맥 왜곡 현상을 야기하므로, 안정적인 사내 위키 지식 베이스 검색 구현을 위해 FTS와 pgvector를 FULL OUTER JOIN으로 아우르는 RRF 알고리즘 기반 하이브리드 검색을 핵심 표준 파이프라인으로 확립할 것.

 

 

#본 이미지들은 AI를 이용하여 생성하였습니다.

반응형