포스트

RAGChatbotServer 시스템 분석 보고서

RAGChatbotServer 시스템 분석 보고서

분석 일자: 2026-05-14
분석 대상: RAGChatbotServer (Legacy)
분석 목적: 현재 시스템 구조 파악 및 SearcheRAGWithGraphRAG (Neo4j GraphRAG + Elasticsearch + PostgreSQL) 전환 설계를 위한 기반 분석


목차

  1. 시스템 개요
  2. 현재 아키텍처 분석
  3. 핵심 구성요소 분석
  4. 발견된 문제점
  5. 향후 Hybrid RAG 전환 설계
  6. 전환 로드맵
  7. 결론 및 권고사항

1. 시스템 개요

1.1 프로젝트 목적

RAGChatbotServer는 PDF 문서 기반 RAG(Retrieval-Augmented Generation) 챗봇 서버로, 3종의 벡터 DB(Elasticsearch, OpenSearch, PGVector)를 환경변수 한 줄로 교체하며 다양한 검색 모드를 실험할 수 있는 PoC(Proof of Concept) / Legacy 시스템이다.

본 분석은 이 레거시 시스템에서 계승할 자산과 버려야 할 부채를 식별하고, SearcheRAGWithGraphRAG 신규 시스템 설계의 기반 자료로 활용하기 위해 수행되었다.

1.2 기술 스택 요약

영역기술비고
API ServerFastAPI 3.0.0 + Uvicorn 
LLMOpenAI GPT-4o-miniLangChain 경유
EmbeddingOpenAI Embeddings (기본), Cohere, HuggingFace환경변수 선택
Vector DBElasticsearch 8.x / OpenSearch 2.x / PGVector택 1 (신규: ES 단일화)
PDF 처리pdfplumber, PyPDF, Unstructured 
프레임워크LangChain 0.3.x 
인프라Docker Compose (DB별 분리) 
모니터링Kibana / OpenSearch Dashboards / pgAdmin 

1.3 현재 운영 설정 (.env 기준)

현재 .env에서 Elasticsearch를 기본 Vector Store로 설정하고 있으며, 이는 신규 시스템과 일치한다.

1
2
3
4
VECTOR_STORE_TYPE=elasticsearch
SEARCH_MODE=custom-hybrid
ELASTICSEARCH_INDEX=rcsv-pdf-documents
CHUNK_SIZE=2000 / CHUNK_OVERLAP=300

2. 현재 아키텍처 분석

2.1 전체 시스템 흐름

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[Client]
  ├── React Frontend (:5175)
  └── Terminal Chat

       ↓ HTTP

[FastAPI Server :8000]  ←  app.py (REST API)
       ↓
  rag_system.py  →  SearchRAG (base class)
       │               ├── ElasticsearchRAG
       │               ├── OpenSearchRAG        ← 신규 시스템에서 제거
       │               └── PGVectorRAG          ← 신규 시스템에서 역할 변경
       ↓
  vector_store.py  →  환경변수 기반 DB 라우팅
       ↓
  [Vector DB - 택 1]
       ├── Elasticsearch :9200                  ← 신규 시스템: 이것만 사용
       ├── OpenSearch :9201                     ← 신규 시스템: 제거
       └── PGVector :5432                       ← 신규 시스템: SSOT + 수치 데이터로 역할 전환

[Data Pipeline]
  pdf_processor.py  →  embed_pdfs.py  →  Vector DB
       ↑
  OpenAI API (GPT-4o-mini + Embeddings)

2.2 파일 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
RAGChatbotServer/  (Legacy)
├── .env                           # 환경변수 (현재: ES + custom-hybrid)
├── requirements.txt               # Python 의존성
│
├── app.py                         # FastAPI 메인 (432줄)
├── rag_system.py                  # RAG 기본 클래스 + DB별 서브클래스 (898줄)
├── vector_store.py                # 벡터 스토어 라우터
├── pdf_processor.py               # PDF 파싱 + LLM 메타데이터 생성
├── embed_pdfs.py                  # 배치 임베딩 CLI
├── chat_interface.py              # 터미널 챗봇
├── run_terminal_chat.py           # 터미널 실행 스크립트
├── test_search_modes.py           # 검색 모드 벤치마크
│
├── vector_store_elasticsearch.py  # ES 구현 (1,130줄) ← 재활용 대상
├── vector_store_opensearch.py     # OS 구현 (1,100줄) ← 제거 대상
├── vector_store_pgvector.py       # PGVector 구현 (1,380줄) ← 역할 전환
│
├── ElasticSearch/                 # ES 인프라 (Nori 한국어 포함) ← 재활용
├── OpenSearch/                    # OS 인프라 ← 제거
└── PGVector/                      # PG 인프라 (초기화 SQL + 백업) ← 스키마 재설계

2.3 클래스 계층 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SearchRAG (기본 클래스)
  ├── vectorstore
  ├── llm: ChatOpenAI (gpt-4o-mini)
  ├── retriever
  ├── search_mode: str
  ├── prompt_template: str
  ├── query(question, chat_history) → Dict
  ├── format_chat_history(history) → str
  ├── format_sources_info(docs) → str
  └── setup_retriever()

ElasticsearchRAG(SearchRAG)             ← 재활용 및 확장 예정
  └── configure_search_strategy(type, hybrid) → bool

OpenSearchRAG(SearchRAG)                ← 제거 예정
  └── set_search_weights(vector_w, keyword_w) → bool

PGVectorRAG(SearchRAG)                  ← 제거 예정 (PG는 SSOT 역할로 분리)
  ├── pgvector_manager: PGVectorManager
  └── ...

2.4 검색 모드 지원 매트릭스 (레거시 기준)

검색 모드ElasticsearchOpenSearchPGVector신규 시스템
vector✅ ES
bm25✅ ES
custom-hybrid✅ ES
hybrid_search--- (제거)
dense-vector--✅ ES
script-score-✅ ES
similarity--- (제거)
mmr--- (제거)
Graph Search---✅ Neo4j 신규

2.5 API 엔드포인트 (레거시)

MethodPath기능신규 시스템
POST/ai/chat채팅 (질문 → 답변)계승 + GraphRAG 통합
POST/reset_session세션 초기화계승
GET/health서버 상태 확인계승 (LLM 쿼리 제거 필요)
GET/vector-store/info벡터 스토어 정보계승 + Graph 정보 추가
POST/vector-store/search-mode검색 모드 변경계승
GET/search-modes사용 가능 검색 모드 목록계승
GET/sessions활성 세션 목록계승

3. 핵심 구성요소 분석

3.1 app.py (FastAPI 메인 서버)

역할: REST API 진입점, 세션 관리, RAG 시스템 라이프사이클 관리

주요 특징:

  • 전역 변수로 rag_system, chat_sessions 관리 (Dict 기반 인메모리)
  • 검색 모드 변경 시 create_rag_instance() 전체 재생성 방식
  • @app.on_event("startup/shutdown") 사용 (deprecated API)
  • 세션 히스토리 최근 10개 유지

문제점: health_check() 내부에서 rag_system.query("테스트", []) 실제 호출 → OpenAI API 과금 발생

3.2 rag_system.py (RAG 엔진)

역할: LLM + 벡터 검색 결합, 검색 모드별 retriever 구성

주요 특징:

  • Strategy 패턴 적용: SearchRAG → ES/OS/PG 서브클래스
  • Factory 함수 create_rag_instance()로 통일된 생성 인터페이스
  • LangChain EnsembleRetriever 활용한 custom-hybrid 지원
  • 한국어 최적화 프롬프트 템플릿 내장 → 신규 시스템에 계승

심각한 버그: PGVectorRAG.__init__ 이중 초기화 (미정의 변수 참조 → NameError)

3.3 pdf_processor.py (PDF 처리) — 핵심 재활용 자산

역할: PDF → 청킹 → LLM 메타데이터 자동 생성

주요 특징 (신규 시스템에 계승 가치 높음):

  • LLM 기반 메타데이터 자동 생성: 키워드/카테고리/요약/기술용어/개체명
  • BM25 검색 최적화용 all_search_text 필드 합성
  • 빈도 분석 기반 자동 키워드 보강 (_extract_frequent_terms)
  • 3종 엔진 지원: pdfplumber(기본), pypdf, unstructured

GraphRAG 전환 시 NER + 관계 추출 단계 추가 가능한 기반 코드

3.4 vector_store_elasticsearch.py — 핵심 재활용 자산

역할: Elasticsearch 벡터 스토어 전체 구현 (1,130줄)

계승 가치:

  • ElasticsearchManager 클래스: ES 연결, 인덱스 관리, 문서 추가/삭제
  • DenseVector / BM25 / custom-hybrid 전략 구현
  • 한국어 Nori 분석기 설정 포함
  • 비동기 처리 지원 (AsyncElasticsearch)

3.5 인프라 구성 (신규 시스템 대비)

서비스레거시 포트신규 시스템비고
FastAPI Server80008000계승
Elasticsearch92009200계승 + 단일화
Kibana56015601계승
OpenSearch9201제거신규에서 미사용
OpenSearch Dashboards5602제거 
PostgreSQL54325432역할 전환: SSOT + 수치 관리
pgAdmin50505050계승
Neo4j-7474/7687신규 추가

4. 발견된 문제점

4.1 Critical (신규 시스템 설계 시 반드시 해결)

C-1. PGVectorRAG 이중 초기화 버그 (rag_system.py)

1
2
3
4
5
6
7
8
9
class PGVectorRAG(SearchRAG):
    def __init__(self, pgvector_manager):
        super().__init__(...)   # ← 1차 초기화 (정상)
        
        # ↓ 2차 초기화 — connection_string 등 미정의 변수 참조
        self.pgvector_manager = create_pgvector_manager(
            connection_string=connection_string,   # NameError!
            collection_name=collection_name,       # NameError!
        )

신규 시스템 교훈: PGVectorRAG를 완전히 제거하고 PostgreSQL은 SSOT/수치 데이터 전용으로 분리. super().__init__() 중복 호출 패턴 금지.

C-2. Health Check에서 실제 RAG 쿼리 실행 (app.py)

1
2
async def health_check():
    test_response = rag_system.query("테스트", [])  # 매 호출마다 LLM API 호출!

신규 시스템 교훈: Health Check은 DB ping + 연결 상태 확인만. LLM 호출 절대 금지.

C-3. API 인증/인가 완전 부재

신규 시스템 교훈: 처음부터 JWT / API Key 기반 인증 미들웨어 설계 필수.

4.2 Major (신규 시스템 설계 반영 필요)

#문제신규 시스템 대응
M-1In-memory 세션 저장소Redis 기반 분산 세션 저장소
M-2embed_pdfs.py PGVector 전용 하드코딩ES 전용 임베딩 파이프라인으로 재구현
M-3@app.on_event deprecatedlifespan context manager 사용
M-4플랫 파일 구조 (루트에 모든 .py)src/ 패키지 구조 도입

4.3 설계 부채 (신규 시스템에서 처음부터 해결)

항목레거시 현황신규 시스템 목표
테스트벤치마크 스크립트만 존재유닛/통합 테스트 + CI
컨테이너화DB용 Dockerfile만 존재앱 포함 통합 Compose
로깅한/영 혼용, 무제한 파일 생성구조화 로깅 (JSON)
보안API 키 콘솔 출력시크릿 관리 (Vault 등)

5. 향후 Hybrid RAG 전환 설계

5.1 목표 아키텍처 (SearcheRAGWithGraphRAG)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌─────────────────────────────────────────────────────────────────┐
│                SearcheRAGWithGraphRAG 목표 아키텍처              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  [Client / API Layer]                                           │
│      ↓ (JWT 인증)                                               │
│  [FastAPI Server :8000]                                         │
│      ↓                                                          │
│  ┌────────────────────────────────────────────────────────┐     │
│  │              Hybrid RAG Engine                         │     │
│  │                                                        │     │
│  │   ① Vector Search  ②  Graph Search  ③  Numeric Query  │     │
│  │         ↓                  ↓                 ↓         │     │
│  │   Elasticsearch        Neo4j           PostgreSQL      │     │
│  │   (Vector Store)     (GraphRAG)      (SSOT + 수치)     │     │
│  │   - Dense Vector     - 엔티티 노드    - 크기/밝기       │     │
│  │   - BM25             - 관계 엣지      - 색온도/전력     │     │
│  │   - custom-hybrid    - Cypher 쿼리   - 마스터 데이터   │     │
│  └────────────────────────────────────────────────────────┘     │
│      ↓                                                          │
│  [LLM Response Generation (통합 컨텍스트 기반)]                  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

5.2 벡터 스토어: Elasticsearch 단일화

SearcheRAGWithGraphRAG 시스템에서는 Elasticsearch만을 Vector Store로 사용한다. OpenSearch와 PGVector(벡터 역할)는 제거한다.

선택 근거

항목ElasticsearchOpenSearchPGVector
HNSW Dense Vector✅ 네이티브
BM25 전문 검색✅ 최적화제한적
Nori 한국어 분석기✅ 공식-
Neo4j GraphRAG 통합 용이성보통낮음
Kibana 시각화--
운영 단순성✅ 단일 집중--

레거시에서 계승할 ES 자산

자산파일계승 방법
ES 벡터 스토어 구현vector_store_elasticsearch.pyElasticsearchManager 클래스 정제 후 재활용
ES Docker 인프라ElasticSearch/ 폴더 전체직접 이식 (Nori 플러그인 포함)
ES 설정 파일ElasticSearch/elasticsearch.yml재활용
ES ComposeElasticSearch/elasticsearch-compose.yml통합 Compose로 흡수

5.3 Neo4j GraphRAG 통합 설계

역할 및 책임

Neo4j는 지식 그래프 기반 관계 추론 역할을 담당한다. Elasticsearch의 벡터/키워드 검색만으로 포착하기 어려운 엔티티 간 관계, 계층 구조, 경로 기반 추론을 제공한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[문서 처리 파이프라인]
     ↓
[PDF 파싱 (pdf_processor.py 재활용)]
     ↓
[NER + 관계 추출 (LLM)] ← 신규 추가 단계
     ↓                            ↓
[Elasticsearch]              [Neo4j]
 - 텍스트 청크                - 엔티티 노드 (Product, Category 등)
 - 벡터 임베딩                - 관계 엣지 (RELATES_TO, IS_PART_OF)
 - 메타데이터                 - 속성 (PG의 product_id FK 포함)
     ↓                            ↓
     └────────────┬───────────────┘
                  ↓
         [HybridGraphRAG Engine]
         ① ES Vector Search
         ② Neo4j Cypher Graph Traversal
         ③ PostgreSQL Numeric Query
                  ↓
         [LLM 통합 응답 생성]

신규 클래스 설계안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 신규 구현 예정: HybridGraphRAG
class HybridGraphRAG(SearchRAG):
    """
    Elasticsearch + Neo4j GraphRAG + PostgreSQL 수치 데이터 통합 RAG
    - SearchRAG (레거시)에서 ElasticsearchRAG만 계승
    """
    def __init__(self, es_manager, neo4j_driver, pg_conn):
        super().__init__(es_manager.vectorstore)
        self.neo4j_driver = neo4j_driver
        self.pg_conn = pg_conn
    
    def query(self, question, chat_history):
        # ① ES 벡터/BM25 검색
        vector_docs = self._vector_search(question)
        
        # ② Neo4j 그래프 탐색 (엔티티 관계 추론)
        graph_context = self._graph_search(question)
        
        # ③ PostgreSQL 수치 데이터 조회 (크기/밝기 등)
        numeric_data = self._pg_numeric_query(question)
        
        # ④ 통합 컨텍스트로 LLM 응답 생성
        return self._generate_response(
            vector_docs, graph_context, numeric_data,
            question, chat_history
        )

5.4 PostgreSQL: SSOT 및 수치 데이터 관리

역할 전환 요약

항목레거시 역할 (PGVector)신규 역할 (SSOT + 수치 관리)
주요 목적벡터 유사도 검색마스터 데이터 + 수치 관리
벡터 저장pgvector 익스텐션 사용불필요 → ES로 완전 이전
데이터 구조Document 청크 + 벡터 컬럼정규화된 관계형 스키마
쿼리 방식<=> (벡터 유사도)SQL 집계/범위/조인
연동단독 운영ES + Neo4j 데이터 허브 역할

권장 스키마 설계 (초안)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
-- 제품 마스터 (SSOT — 모든 데이터의 원천)
CREATE TABLE products (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    product_code VARCHAR(50)  UNIQUE NOT NULL,
    name         VARCHAR(200) NOT NULL,
    category     VARCHAR(100),
    created_at   TIMESTAMPTZ  DEFAULT NOW(),
    updated_at   TIMESTAMPTZ  DEFAULT NOW()
);

-- 수치 속성 (크기, 밝기 등 정형 데이터)
CREATE TABLE product_specs (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    product_id      UUID REFERENCES products(id) ON DELETE CASCADE,
    -- 크기
    width_mm        NUMERIC(10,2),   -- 가로 (mm)
    height_mm       NUMERIC(10,2),   -- 세로 (mm)
    depth_mm        NUMERIC(10,2),   -- 깊이 (mm)
    -- 광학 특성
    brightness_lm   NUMERIC(10,2),   -- 밝기 (루멘)
    color_temp_k    INTEGER,         -- 색온도 (K)
    -- 전기 특성
    wattage_w       NUMERIC(8,2),    -- 소비전력 (W)
    -- 물리 특성
    weight_kg       NUMERIC(8,3),    -- 무게 (kg)
    UNIQUE(product_id)
);

-- ES 인덱스 동기화 추적 (SSOT 역할의 핵심)
CREATE TABLE es_sync_log (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    product_id  UUID REFERENCES products(id),
    es_doc_id   VARCHAR(200),  -- ES 문서 ID
    synced_at   TIMESTAMPTZ    DEFAULT NOW(),
    status      VARCHAR(20)    -- 'synced' | 'pending' | 'failed'
);

-- Neo4j 노드 동기화 추적
CREATE TABLE neo4j_sync_log (
    id             UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    product_id     UUID REFERENCES products(id),
    neo4j_node_id  VARCHAR(200),  -- Neo4j 노드 ID
    synced_at      TIMESTAMPTZ    DEFAULT NOW(),
    status         VARCHAR(20)
);

5.5 레거시 → 신규 시스템 계승/폐기 결정표

✅ 계승 (재활용)

자산파일계승 방법
ES 벡터 스토어 구현vector_store_elasticsearch.pyElasticsearchManager 클래스 정제
ES Docker 인프라ElasticSearch/직접 이식 (Nori 포함)
LLM 메타데이터 생성pdf_processor.pygenerate_complete_metadata_with_llm()
FastAPI 기본 구조app.py인증 추가 후 재활용
한국어 최적화 프롬프트rag_system.py신규 HybridGraphRAG에 계승
검색 모드 벤치마크test_search_modes.pyGraphRAG 포함 확장 버전으로 발전
PGVector 초기화 SQLPGVector/postgresql/init/스키마 재설계 후 부분 재활용
PG 성능 튜닝 설정PGVector/postgresql/conf/재활용

❌ 폐기 (제거)

자산파일폐기 이유
OpenSearch 전체OpenSearch/, vector_store_opensearch.pyES 단일화 결정
PGVectorRAG 클래스rag_system.py역할 분리 (SSOT로 전환)
vector_store_pgvector.pyvector_store_pgvector.py벡터 역할 제거
embed_pdfs.py 현재 버전embed_pdfs.pyES 전용 재구현 필요

🆕 신규 구현 필요

항목설명
Neo4j 연동 모듈vector_store_neo4j.py — GraphRAG 검색 엔진
HybridGraphRAG 클래스ES + Neo4j + PG 통합 쿼리 클래스
NER + 관계 추출 파이프라인PDF → 엔티티/관계 → Neo4j 저장
PostgreSQL SSOT 스키마수치 데이터 테이블 + 동기화 로그
데이터 동기화 파이프라인PG → ES + Neo4j 일관성 유지
API 인증 미들웨어JWT/API Key 기반
Redis 세션 저장소분산 세션 관리
통합 Docker ComposeES + Neo4j + PG + FastAPI 일괄 실행

6. 전환 로드맵

Phase 1 — ES 단일화 + 기반 안정화

  • OpenSearch 관련 코드 전체 제거
  • PGVector → 순수 SSOT + 수치 데이터 역할로 스키마 재설계
  • Health Check에서 LLM 쿼리 제거
  • lifespan context manager 마이그레이션
  • 패키지 구조 (src/) 도입

Phase 2 — PostgreSQL SSOT 구성

  • 수치 데이터 스키마 마이그레이션 (크기, 밝기, 색온도, 소비전력)
  • ES 동기화 로그 테이블 구성
  • PostgreSQL → Elasticsearch 데이터 동기화 파이프라인 구현

Phase 3 — Neo4j GraphRAG 통합

  • Neo4j Docker Compose 추가 (ES Compose와 통합)
  • vector_store_neo4j.py 구현
  • PDF 파이프라인에 NER + 관계 추출 단계 추가
  • HybridGraphRAG 클래스 구현 (ES + Neo4j + PG 통합)

Phase 4 — 운영화

  • API 인증/인가 (JWT 기반)
  • Redis 세션 저장소 도입
  • 유닛/통합 테스트 추가
  • CI/CD 파이프라인

7. 결론 및 권고사항

7.1 레거시 시스템 평가

영역점수평가
아키텍처 설계7/10Strategy + Factory 패턴 적용, 다중 DB 추상화 양호
코드 품질5/10PGVectorRAG 초기화 버그, deprecated API, 플랫 구조
보안3/10인증/인가 없음, API 키 노출 위험
성능/확장성5/10인메모리 세션, 수평 확장 불가
테스트4/10벤치마크만 존재, 유닛/통합 테스트 없음
인프라7/10DB별 Docker Compose 분리, 한국어 분석기 포함
문서화6/10Jupyter 가이드 존재, 인라인 문서 부족
종합5.3/10PoC 실험용으로 양호, 신규 시스템 설계 기반으로 활용

7.2 SearcheRAGWithGraphRAG 핵심 결정사항

결정 항목결정 내용
Vector StoreElasticsearch 단일 사용 (OpenSearch, PGVector 벡터 역할 제거)
Graph StoreNeo4j 신규 도입 (엔티티/관계 그래프 + Cypher 쿼리)
SSOT 데이터PostgreSQL (마스터 데이터 + 수치 데이터: 크기, 밝기, 색온도, 소비전력)
임베딩현재 OpenAI → 장기적으로 BGE-M3 등 로컬 모델 검토
LLM현재 GPT-4o-mini → DeepSeek V3 등 비용 효율 모델 검토
인증처음부터 JWT 기반 인증 설계
세션Redis 분산 세션 저장소

7.3 즉시 착수 권고

1
2
3
4
5
P0: ES 단일화 — OpenSearch 코드 제거, ES 전용 구조로 단순화
P0: PG 스키마 재설계 — 벡터 제거, SSOT + 수치 데이터 테이블 설계
P1: Neo4j Docker 환경 구성 + 프로토타이핑
P1: HybridGraphRAG 클래스 설계 (ES + Neo4j + PG 통합)
P2: 통합 Docker Compose 작성 (ES + Neo4j + PG + FastAPI)

분석 대상: RAGChatbotServer (Legacy)
작성일: 2026-05-14
다음 검토 예정: Phase 2 완료 후 (PostgreSQL SSOT 구성 완료 시점)

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.