0부터 1까지 구축하는 기업급 RAG 지식 베이스: pgvector + 문서 청킹 + 하이브리드 검색
요약
기업용 RAG 구축 시 발생하는 청킹 오류, 벡터 검색의 부정확성, 멀티모달 처리 및 권한 격리 문제를 해결하는 방법을 다룹니다. pgvector를 활용하여 기존 데이터베이스와의 통합 및 비용 효율적인 지식 베이스 구축 아키텍처를 제안합니다.
핵심 포인트
- 단순 벡터 검색의 한계를 극복하기 위한 지능형 청킹의 중요성
- 의미적 유사도와 키워드 일치를 모두 잡는 하이브리드 검색 필요성
- pgvector를 활용한 데이터 일관성 및 권한 격리 구현
- 멀티모달 문서 처리를 통한 차트 및 이미지 정보 활용
0부터 1까지 구축하는 기업급 RAG 지식 베이스: pgvector + 문서 청킹 + 하이브리드 검색
당신은 회사에 GPT-4o를 연결한 AI 어시스턴트를 구축했습니다. 직원이 "2025년 Q3 판매 정책"을 묻자, AI는 "판매 정책"에 대한 내용을 지어냈습니다. 법무팀이 확인해보니 모두 환각(Hallucination)이었습니다. Q3 정책은 전혀 그렇지 않았습니다. 직원이 "제품 X의 반품 절차"를 묻자, AI는 또다시 내용을 지어냈습니다. CTO는 분노했습니다: "AI를 구축하는 데 수백만 달러를 썼는데, 회사 내부 문서조차 모른단 말인가?"
이것이 바로 LLM의 치명적인 약점입니다: LLM은 당신의 기업 내부 지식을 알지 못합니다. 미세 조정(Fine-tuning)은 너무 비싸고 느리며, 실시간 업데이트가 불가능합니다. 해결책은 RAG(Retrieval-Augmented Generation, 검색 증강 생성)입니다. 본문에서는 IHUI AI가 어떻게 pgvector + 하이브리드 검색을 사용하여 멀티모달, 권한 격리, 인용 추적을 지원하는 기업급 RAG를 구축하는지 설명합니다.
1. 페인 포인트(Pain Point): 왜 단순한 RAG로는 부족한가
인터넷에 있는 RAG 데모는 매우 간단해 보입니다: 문서를 청킹(Chunking) → 임베딩(Embedding) → 벡터 데이터베이스에 저장 → 쿼리 시 코사인 유사도 계산 → Top-K를 프롬프트(Prompt)에 삽입. 하지만 기업급 서비스로 구현할 때는 4가지 벽에 부딪히게 됩니다:
벽 1: 잘못된 청킹으로 인한 검색 결과 혼란
- 500자 단위의 강제 절단: "주문"이라는 개념을 반으로 잘라버리면, 앞부분은 "주문 생성"을 말하고 뒷부분은 "주문 상태"를 말하게 되어, 각각의 조각만으로는 검색이 되지 않습니다.
- 단락 단위 절단: 단락마다 길이 차이가 매우 커서, 어떤 단락은 50자로 너무 짧고 어떤 단락은 5000자로 컨텍스트(Context)를 초과합니다.
- 표/코드 블록 파손: Markdown 표가 4개로 쪼개져 각 조각이 깨진 텍스트가 됩니다.
벽 2: 순수 벡터 검색의 부정확한 결과
사용자가 "환불"을 물으면, 벡터 데이터베이스는 Top-5로 "상환", "반품", "청구서", "송금", "배상" 등을 반환합니다. 의미는 비슷하지만 "환불 정책"은 아닙니다. 벡터 유사도 ≠ 의미적 일치입니다.
벽 3: 멀티모달(Multimodal) 문서 처리 불가
PDF에는 차트, 스캔본, 공식이 포함되어 있습니다. 순수 텍스트 RAG는 차트를 단순 이미지로 취급하여 버리지만, 차트 안에는 가격표와 같은 핵심 정보가 들어있습니다.
벽 4: 권한 격리 부재
A 부서의 문서를 B 부서가 볼 수 없어야 하는데, RAG는 검색 시 모든 것을 노출합니다. 직원이 "급여 체계"를 물으면, HR 내부 문서가 검색되어 일반 직원에게 노출될 수 있습니다.
2. 솔루션: pgvector + 지능형 청킹 + 3-Way 하이브리드 검색
2.1 왜 Pinecone/Milvus 대신 pgvector를 선택하는가
| 차원 | pgvector | Pinecone | Milvus |
|---|---|---|---|
| 배포 비용 | 기존 PG 활용, 추가 비용 0 | SaaS, 사용량 기반 과금 | 자체 클러스터 구축 |
| ... |
결론: 중소규모 기업(< 1억 개의 벡터)은 pgvector를 선택하는 것이 이득이 가장 큽. 컴포넌트 수를 줄일 수 있고, 트랜잭션 일관성을 유지하며, 기존 PG의 권한 설정을 재사용할 수 있기 때문입니다. IHUI AI가 pgvector를 선택한 이유는 우리의 비즈니스 데이터가 이미 PostgreSQL에 있기 때문입니다. 지식 베이스와 비즈니스 데이터가 동일한 DB에 있어, RAG 검색 시 비즈니스 테이블과 직접 JOIN(예: "우리 부서에서 볼 수 있는 문서만 검색")할 수 있습니다.
2.2 전체 아키텍처
┌─────────────────────────────────────────────┐
│ 문서 수집 파이프라인 │
│ PDF/Word/Markdown/HTML → 파싱 → 지능형 청킹 │
...
3. 기술적 세부 사항
3.1 데이터베이스 스키마(Schema)
-- 확장 기능 활성화
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- 퍼지 매칭 (Fuzzy Matching)
...
핵심 설계:
- HNSW 인덱스:
m=16, ef_construction=64, 재현율(Recall) 95% 이상, 지연 시간(Latency) < 50ms. gin_trgm_ops: 중국어 퍼지 매칭 지원 (기본 PG의 전체 텍스트 인덱스는 중국어 지원이 미흡함).- RLS (Row-Level Security): 데이터베이스 계층에서 권한 격리를 강제하여, 애플리케이션 계층에서 검증을 누락하더라도 데이터베이스가 정보를 유출하지 않도록 합니다.
3.2 지능형 청킹 (Intelligent Chunking)
apps/ai-service/src/rag/chunker.py:
from langchain_text_splitters import (
MarkdownHeaderTextSplitter,
RecursiveCharacterTextSplitter,
...
핵심 설계:
- Markdown은 먼저 헤더(Header) 기준으로 자른 후 길이에 따라 잘라 의미적 완전성을 보장합니다.
- 표/코드 블록은 자르지 않고 통째로 저장합니다 (너무 길 경우 별도로 임베딩).
- 재귀적 분할기(Recursive Splitter)는 중국어 마침표
。를 우선적으로 사용하여 중국어 문서에 친화적입니다.
3.3 멀티모달 문서 처리
PDF 내의 차트는 Vision LLM을 사용하여 캡션(caption)을 생성한 후 저장소에 입력합니다:
import pypdf
from litellm import acompletion
...
이점: 사용자가 "2025년 Q3 판매 트렌드"라고 질문하면, 벡터 검색(Vector Search)을 통해 차트의 캡션을 찾아내고, LLM이 "모릅니다"라고 답하는 대신 차트 데이터를 인용하여 답변합니다.
3.4 Embedding 모델 선택
IHUI AI는 기본적으로 bge-m3(오픈 소스, 1024 차원, 중-영 이중 언어 지원, 희소 벡터(Sparse Vector) 지원)를 사용하며, 대안으로 text-embedding-3-large(OpenAI, 3072 차원, 고비용)를 고려합니다:
from litellm import aembedding
async def embed(text: str) -> list[float]:
...
핵심 포인트: 임베딩 (Embedding) 모델은 한 번 결정하면 쉽게 바꿀 수 없습니다 (차원이 다르면 인덱스를 재구축해야 함). 우리가 bge-m3를 사용하는 이유는 오픈 소스이며, 프라이빗 배포가 가능하고, 중국어 성능이 OpenAI보다 뛰어나기 때문입니다.
3.5 삼원 하이브리드 검색 (Three-way Hybrid Search)
apps/ai-service/src/rag/retriever.py:
import asyncpg
from typing import Literal
...
왜 삼원(Three-way)인가:
- 벡터 검색 (Vector Retrieval): 의미적 유사성 (사용자가 "환불"을 물으면 "반품 정책"을 검색)
- 전체 텍스트 검색 (Full-text Retrieval): 형태적 유사성 (사용자가 "환불z"라고 오타를 내도 "환불"을 검색)
- 키워드 검색 (Keyword Retrieval): 정확한 일치 (사용자가 "ISO27001"을 검색하면 반드시 이 단어가 포함되어야 함)
단일 방식은 모두 사각지대가 존재하지만, 삼원 방식을 융합하면 검색률(Recall)이 72%에서 91%로 향상됩니다.
3.6 Rerank 모델
검색 후 bge-reranker-v2-m3를 사용하여 재정렬(Rerank)합니다 (교차 인코더(Cross-Encoder)를 사용하여 벡터 유사도보다 더 정확함):
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
...
이점: 재정렬 후 Top-5 정확도가 81%에서 94%로 상승합니다.
3.7 인용 및 출처 추적 (Citation & Traceability)
LLM이 생성할 때 chunk_id를 프롬프트(Prompt)에 주입하여, 모든 답변 단락에 인용을 표시하도록 요구합니다:
async def generate_with_citations(query: str, chunks: list[dict]) -> dict:
context = "\n\n".join([
f"[{i + 1}] (출처:{c['metadata'].get('source', '알 수 없음')}, 페이지:{c['metadata'].get('page', '?')})\n{c['content']}"
...
UI 상에서 각 답변 뒤에 클릭 가능한 [1] [2] 표시가 나타나며, 클릭 시 원본 문서의 해당 페이지로 이동합니다. 직원들은 더 이상 AI가 허위 정보를 생성(Hallucination)할까 봐 걱정할 필요가 없습니다.
4. IHUI AI 실전 데이터
| 지표 | 수치 |
|---|---|
| 기본 embedding 모델 | bge-m3 (1024 차원, 중-영 이중 언어) |
| ... |
실제 사례: 한 법률 사무소에서 IHUI AI 지식 베이스를 도입하여 3,000개의 계약서를 저장했습니다. 변호사가 "경업 금지 약정 보상 기준"을 묻자, AI가 답변과 함께 구체적인 계약 조항 및 페이지를 인용하여 5초 만에 해결했습니다. 이전에는 변호사가 계약서를 찾는 데 평균 25분이 소요되었습니다.
5. 시행착오 요약 (Lessons Learned)
실수 1: Embedding 차원 선택 오류
처음에는 text-embedding-3-small(1536 차원)을 사용하다가, 나중에 저장 공간을 아끼기 위해 bge-m3(1024 차원)로 바꾸려 했으나 차원이 일치하지 않아 인덱스를 재구축해야 함을 발견했습니다. 교훈: 처음부터 잘 평가해야 합니다. 나중에 임베딩을 바꾸는 것은 지식 베이스를 재구축하는 것과 같습니다.
실수 2: 너무 작은 청크 크기로 인한 검색 분산
chunk_size=128로 설정하면 검색률은 높지만 LLM이 받는 컨텍스트(Context)가 너무 파편화되어 답변이 조각조각 끊깁니다. 우리는 최종적으로 512 토큰(Token) + 64 오버랩(Overlap)을 사용하여 검색과 컨텍스트의 완전성 사이의 균형을 맞췄습니다.
실수 3: HNSW vs IVFFlat
HNSW는 검색률이 높지만(95% 이상) 메모리 점유율이 큽니다. IVFFlat은 메모리를 절약하지만 검색률이 85%로 떨어집니다. 100만 개의 청크 이내에서는 HNSW가 더 유리하며, 천만 단위 이상일 때 IVFFlat을 고려하십시오.
실수 4: 중국어 토큰화 (Tokenization)
pg_trgm은 중국어에 친화적이지 않습니다. 우리는 jieba를 애플리케이션 계층에 통합하여 키워드를 추출한 뒤 SQL ILIKE에 전달하는 방식을 사용했습니다. 순수 데이터베이스 계층 솔루션을 쓰려면 pg_bigm(PostgreSQL 확장 기능 직접 컴파일 필요)을 사용해야 합니다.
실수 5: 권한 필터링이 한 단계 늦음
처음에 Python 계층에서 권한 필터링을 수행했다가, 한 번은 버그로 인해 내부 HR 문서가 검색되어 일반 직원에게 노출된 적이 있습니다. 교훈: 권한은 반드시 SQL 계층(RLS)에서 최종 보장되어야 하며, 애플리케이션 계층의 검증은 성능 최적화 용도로만 사용해야 합니다.
6. 결론
기업급 RAG의 핵심은 다음과 같습니다:
- 지능형 청킹 (Chunking): Markdown 제목 + 재귀적 문자(Recursive Character) 기준 적용, 표/코드는 분할하지 않음, 512/64 토큰이 최적의 지점(Sweet spot).
- 3-Way 융합: 벡터(Vector, 의미) + 전체 텍스트(Full-text, 모호한 검색) + 키워드(Keyword, 정확한 검색)를 결합, RRF(Reciprocal Rank Fusion)를 통해 재현율(Recall) 94% 달성.
- Rerank 보완: bge-reranker-v2-m3를 사용하여 Top-5 정확도를 81%에서 94%로 끌어올림.
- 멀티모달 (Multimodal): 차트/도표는 Vision LLM을 사용하여 캡션(Caption)을 생성해 저장하고, 검색 시 동일하게 취급.
- 권한 격리: PG RLS 데이터베이스 계층 보장 + 애플리케이션 계층 검증의 이중 보안.
- 인용 및 출처 추적 (Citation/Traceability): 모든 답변에 chunk_id + 페이지 번호를 첨부하여, 직원은 안심하고 사용하고 법무팀은 승인할 수 있게 함.
이 아키텍처를 통해 IHUI AI의 지식 베이스는 로펌, 컨설팅 회사, SaaS 업체 등 기업 환경에 성공적으로 안착했습니다. 만약 여러분도 RAG를 구축하고 있다면, 첫날부터 pgvector + 하이브리드 검색(Hybrid Search)을 사용할 것을 강력히 권장합니다. 순수 벡터(Pure Vector) 방식은 운영 환경(Production)에서 반드시 한계에 부딪히게 됩니다.
IHUI AI 소개
IHUI AI는 Apache 2.0 오픈 소스 기반의 원스톱 8개 엔드포인트 풀스택 AI 운영체제입니다.
- 🌐 공식 웹사이트: https://aizhs.top
- 💻 GitHub: https://github.com/IHUI-INF-AI/IHUI-AI (Star ⭐로 응원해 주세요)
- 📦 8개 엔드포인트 동일 소스: Web / API / CLI / Desktop / Extension / Mobile / Miniapp
- 🤖 176개 모델: OpenAI / Claude / Gemini / 通义 (Tongyi) / DeepSeek / 智谱 (Zhipu) / 文心 (ERNIE) / 豆包 (Doubao) / Kimi / Ollama
- 💰 가격 정책: Free / Pro ¥49/월 / Team ¥199/인/월 / Enterprise ¥2999/월부터
5분 만에 Fork 하여 배포 가능하며, ChatGPT Team + Claude Code + Notion AI를 대체하여 매월 $60 이상을 절약할 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기