벡터 검색을 넘어서: 지식 그래프로 만든 AI 챗봇 Nova
벡터 검색만으로는 답할 수 없는 질문이 있다. Neo4j 지식 그래프와 pgvector 벡터 검색을 결합한 GraphRAG로, 베트남 증권·법률 도메인에서 정확도와 안전성을 동시에 잡은 AI 챗봇 Nova의 설계 이야기.

"이 종목의 최대주주가 지분을 늘린 게 올해 몇 번이고, 그때마다 주가는 어떻게 움직였나?" — 일반적인 RAG 챗봇에게 이런 질문을 던지면 그럴듯하지만 틀린 답이 돌아온다. 문서 조각을 아무리 잘 찾아와도, 관계를 따라가며 세는 일은 벡터 검색이 하는 일이 아니기 때문이다.
Nova는 베트남 증권·법률 도메인에 특화된 AI 챗봇 플랫폼이다. 우리는 이 문제를 지식 그래프와 벡터 검색을 결합한 GraphRAG 구조로 풀었다. 이 글은 왜 벡터만으로는 부족했는지, 그리고 우리가 정확도와 안전성을 동시에 확보하기 위해 무엇을 만들었는지에 대한 기록이다.
왜 벡터 검색만으로는 부족한가
RAG(Retrieval-Augmented Generation)의 기본 아이디어는 단순하다. 질문과 의미가 가까운 문서 조각을 벡터 유사도로 찾아와 LLM에게 함께 건네주는 것이다. "배당 정책이 뭐야?" 같은 개념적 질문에는 훌륭하게 동작한다.
문제는 관계와 집계가 필요한 질문이다. 벡터 검색은 "비슷한 것"은 잘 찾지만 "연결된 것"은 따라가지 못한다.
- "A사의 자회사들이 보유한 채권의 총 규모는?" — 소유 관계를 여러 단계 따라가야 한다.
- "이 공시와 같은 유형의 공시를 낸 다른 종목은?" — 유형이라는 구조적 속성으로 묶어야 한다.
- "최근 3개월간 외국인 순매수 상위 종목 중 배당수익률이 높은 것은?" — 필터링과 정렬, 즉 정확한 계산이 필요하다.
이런 질문에 벡터 검색은 "그럴듯한 문장"을 반환할 뿐, 정답을 보장하지 못한다. 금융·법률처럼 틀리면 안 되는 도메인에서는 치명적이다.
GraphRAG — 그래프와 벡터의 하이브리드
우리의 해법은 두 검색 엔진을 나란히 두는 것이다.
- Neo4j 지식 그래프는 종목, 뉴스, 공시, 재무, 법률 조항 같은 개체(node)와 그 사이의 관계(edge)를 저장한다. 관계를 따라가는 질의, 정확한 집계·필터링은 그래프가 담당한다.
- PostgreSQL + pgvector는 문서 임베딩을 HNSW 인덱스로 저장한다. 개념적·서술적 질문은 벡터 검색이 담당한다.
질문의 성격에 따라 두 엔진 중 적절한 쪽을, 혹은 둘 다를 활용해 근거를 모은 뒤 LLM이 답을 생성한다. 구조적 사실은 그래프에서 정확하게 가져오고, 맥락과 설명은 벡터에서 풍부하게 채우는 방식이다.
3단계 쿼리 생성 — 정확성과 유연성의 균형
그래프에 질문하려면 결국 Cypher 쿼리로 번역해야 한다. 여기서 흔한 실수는 "모든 질문을 LLM이 Text2Cypher로 변환하게" 만드는 것이다. LLM이 만든 쿼리는 유연하지만, 예측 불가능하고 때때로 위험하다.
Nova는 쿼리 생성을 3단계로 계층화했다.
- 템플릿 (약 80%) — 자주 들어오는 질문 유형은 검증된 파라미터화 쿼리 템플릿으로 처리한다. 빠르고, 안전하고, 결과가 결정론적이다.
- DSL (약 15%) — 템플릿으로 안 되지만 패턴이 있는 질문은 제한된 도메인 특화 언어(DSL)로 표현한 뒤 안전하게 Cypher로 컴파일한다.
- Text2Cypher (약 5%) — 위 둘로 커버되지 않는 진짜 자유형 질문만 LLM이 직접 Cypher를 생성한다. 이 경로는 가장 강력하지만 가장 위험하므로, 뒤에서 설명할 검증 레이어를 반드시 통과해야 한다.
대부분의 트래픽을 안전한 경로로 흘려보내고, LLM의 창의성은 꼭 필요한 5%에만 허용한다. 성능과 안전성을 동시에 얻는 설계다.
9단계 오케스트레이션 — 무너지지 않는 파이프라인
하나의 질문이 답이 되기까지, Nova 내부에서는 9단계의 오케스트레이션 파이프라인이 돈다. 언어 감지 → 의도 라우팅 → 쿼리 생성 → 검색(그래프/벡터) → 근거 병합 → 답변 생성 → 안전성 필터 → 그라운딩 검증 → 로깅으로 이어지는 흐름이다.
핵심은 어느 단계가 실패해도 전체가 무너지지 않는다는 것이다.
- 서킷 브레이커: 특정 외부 의존성(예: 그래프 DB, LLM API)이 반복 실패하면 회로를 열어 빠르게 폴백한다.
- LLM 폴백: 답변 생성 모델이 타임아웃되면 더 가벼운 모델이나 사전 정의된 안전 응답으로 대체한다.
- 의도 라우팅에는 빠르고 저렴한 Claude Haiku를, 최종 답변 생성에는 품질 높은 Claude Sonnet을 쓴다. 다국어 임베딩은
multilingual-e5-large가 담당한다.
틀리지 않기 위한 3중 안전장치
금융·법률 챗봇에서 가장 무서운 것은 "자신 있게 틀리는 것"이다. Nova는 세 방향으로 이를 막는다.
1. 투자 권고 차단 3레이어
- 명시적 차단: "이거 사도 돼?" 같은 직접적 투자 자문 요청을 규칙으로 걸러낸다.
- 모호 구문 면책: 애매하게 권유로 읽힐 수 있는 표현에는 면책 문구를 부착한다.
- 출력 필터: 생성된 답변을 마지막으로 한 번 더 검사해 권고성 표현을 제거한다.
2. 환각(할루시네이션) 탐지
- 그라운딩 스코어: 생성된 답변이 실제로 검색된 근거에 얼마나 기반하는지 점수화한다. 근거 없는 문장은 걸러진다.
- 종목명 오탐 제거: 존재하지 않거나 문맥에 맞지 않는 종목 코드·이름이 섞이면 잡아낸다.
- 클레임 검증: 답변 속 사실 주장(claim)을 근거와 대조한다.
3. 사이퍼 인젝션 방어
Text2Cypher 경로는 SQL 인젝션에 준하는 위협을 갖는다. 사용자 입력이 그래프를 변경하거나 권한 밖 데이터를 읽지 못하도록, 생성된 쿼리를 읽기 전용·화이트리스트 패턴으로 제한하고 파괴적 연산을 차단한다.
살아있는 데이터 — 파이프라인이 계속 채운다
지식 그래프는 한 번 만들고 끝이 아니라 계속 갱신되어야 가치가 있다. Nova의 데이터 파이프라인은 다음을 자동화한다.
뉴스 수집: CafeF · VnExpress RSS 크롤링 → LLM 추출 → 그래프 반영
시장 데이터: 거래 시간 중 5초 폴링 → Redis 스트리밍
스케줄러: Celery Beat 기반 6개 자동화 작업 (수집·정제·색인·정리)
새 뉴스가 들어오면 LLM이 종목·이벤트·관계를 추출해 그래프에 연결하고, 동시에 문서 임베딩을 벡터 스토어에 색인한다. 그래프와 벡터가 같은 소스로부터 함께 성장한다.
컴플라이언스와 멀티테넌트
베트남 시장을 대상으로 하는 만큼, 개인정보보호법(PDPD)을 준수하도록 90일 자동 삭제, PII 마스킹(필드 제거 + 패턴 + 역할 기반), 감사 로그와 동의 관리, Redis 슬라이딩 윈도우 레이트 리밋을 기본 내장했다.
또한 Nova는 단일 서비스가 아니라 멀티테넌트 SaaS로 설계됐다. 새 고객의 도메인에 맞춰 "온톨로지 커스터마이징 → 데이터 입력 → 검증"을 거치면 2주 내 런칭을 목표로 한다. 온톨로지가 도메인을 정의하므로, 코드를 고치지 않고도 새로운 산업군으로 확장할 수 있다.
규모와 기술 스택
- 169개 Python 파일, 32개 REST API 엔드포인트, 18개 DB 테이블
- 131개 자동화 테스트 (약 31초에 실행)
- 한국어 · 베트남어 · 영어 3개 언어 자동 감지
Python 3.12 + FastAPI
Neo4j 5 (지식 그래프) · PostgreSQL 16 + pgvector (HNSW)
Redis 7 + Celery (비동기·스케줄)
Claude Haiku / Sonnet (LLM) · multilingual-e5-large (임베딩)
Docker Compose (7개 컨테이너) · Nginx 리버스 프록시
우리가 믿는 방향
RAG는 강력하지만 만능이 아니다. "비슷한 것을 찾는" 벡터 검색과 "연결된 것을 따라가는" 그래프 검색은 서로를 대체하는 게 아니라 보완한다. GraphRAG는 이 둘을 하나의 파이프라인에 녹여, 정확해야 할 곳에서는 정확하게, 유연해야 할 곳에서는 유연하게 답한다.
그리고 그 위에 3중 안전장치를 얹었다. 틀리지 않는 것, 위험한 답을 하지 않는 것, 모든 판단의 근거를 남기는 것. 금융과 법률처럼 신뢰가 전부인 도메인에서 AI가 실제로 쓰이려면, 화려한 답변보다 이 세 가지가 먼저다. Nova는 그 원칙 위에 서 있다.