13 KiB
13 KiB
tags
| tags | |||||||
|---|---|---|---|---|---|---|---|
|
260317 non-RDB 계층 PostgreSQL 통일 계획
상태: closed
상위 원칙
- Infra Project Identity
- Core Infrastructure Principles
- Operational Guardrails
- 공통 작성 원칙: 0_VALUE Writing Principles
관련 문서
- Infra Journey
- PostgreSQL 통합 vs 전용 DB 구조성능 리서치
- 모든 DB를 PostgreSQL로 통일하는 아이디어
- non-RDB 계층 PostgreSQL 통일 1차 실행 완료
- PostgreSQL Neo4j TCP healthcheck
- 백엔드: PostgreSQL, ChromaDB, Vector Memory 설계
- Phase 2: ChromaDB + Neo4j 하이브리드 기억 회상 시스템 구현
문제 정의
- 현재 운영 구조는 관계형 데이터는 PostgreSQL, 벡터는 ChromaDB, 관계 추론은 Neo4j, 검색은 별도 전용 계층 가능성을 함께 열어 둔 하이브리드 상태다.
- 이 구조는 기능 분화 측면에서는 설명 가능하지만, 운영 기준으로는 백업, 복구, 권한, 런타임 SSOT, 장애 추적, 데이터 정합성 경로를 여러 저장소에 분산시킨다.
- 이번 계획의 목표는
벡터,검색,그래프계층을 PostgreSQL로 통일하고, 현 단계의 전용 DB를 제거 가능한 상태까지 실제 실행 순서를 고정하는 것이다.
범위
포함
- ChromaDB가 맡고 있는 벡터/메모리/RAG 저장 구조를 PostgreSQL
pgvector기반으로 재설계 - Neo4j가 맡고 있거나 맡을 예정인 관계 추론 구조를 PostgreSQL 관계 모델 +
WITH RECURSIVE중심으로 재설계 - 검색 전용 계층 후보를 PostgreSQL
FTS + pg_trgm + jsonb_to_tsvector구조로 흡수 - 운영 기준 SSOT를 PostgreSQL 중심 백업/복구/모니터링 구조로 재정렬
제외
- 지금 단계에서 Redis까지 함께 없애는 캐시 전략 전체 재설계
- 대규모 분산 클러스터링, 샤딩, 멀티리전 설계
- 구현 완료 보고와 성능 확정 수치 기록
결정
- 기본 저장소 전략은
PostgreSQL only until proven otherwise로 고정한다. - 현 단계의 non-RDB 기능은 전용 DB 존치를 기본값으로 두지 않고 PostgreSQL 흡수를 기본값으로 둔다.
- 검색 해법은
FTS + pg_trgm + metadata filter + vector hybrid rank조합을 기본으로 한다. - 그래프 해법은
adjacency table + recursive query를 기본 모델로 삼고, 필요 시ltree를 보조 선택지로 쓴다. - 벡터 해법은
pgvector를 기본으로 하고, 인덱스는HNSW를 우선 후보로 검토한다. - 전환 우선순위는
ChromaDB -> 검색 계층 -> Neo4j순서로 둔다.- 이유: 현재 벡터 계층은 이미 임베딩 SSOT와 직접 연결돼 있고, 검색은 PostgreSQL 기능만으로 빠르게 흡수 가능하며, 그래프는 모델 재설계 논의가 가장 많이 필요하다.
- 이번 계획에서 제외하는 경계도 고정한다.
Redis 전체 캐시 전략은 별도 주제로 남긴다.- 이번 계획의 닫힘은
ChromaDB,Neo4j, 검색 전용 저장소 제거 기준으로 판단한다.
목표 상태
1. 벡터
- 문서/메모리/질의 임베딩은 PostgreSQL
pgvector(768)컬럼으로 저장한다. - tenant 분리는 별도 컬렉션이 아니라
tenant_id또는 동등한 범위 키로 관리한다. - 메타데이터 필터, 최근성, 중요도, 사용자 범위는 SQL 조건으로 함께 평가한다.
벡터 테이블 초안
create table memory_vectors (
id uuid primary key,
tenant_id uuid not null,
source_type text not null,
source_id uuid not null,
content text not null,
embedding vector(768) not null,
metadata jsonb not null default '{}'::jsonb,
importance numeric(6,3),
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
2. 검색
- 문서 본문, 요약, 태그, metadata jsonb는 PostgreSQL 내부에서 색인한다.
- 정확 키워드/구문은 FTS, 오타/부분일치는
pg_trgm, 의미 유사도는pgvector로 처리한다. - 최종 검색 랭킹은 SQL 안에서 결합 가능하도록 정의한다.
검색 테이블 초안
create table search_documents (
id uuid primary key,
tenant_id uuid not null,
title text,
content text not null,
summary text,
tags text[] not null default '{}',
metadata jsonb not null default '{}'::jsonb,
search_tsv tsvector,
embedding vector(768),
created_at timestamptz not null default now()
);
3. 그래프
- 사건, 감정, 결과, 참여자 관계는 PostgreSQL 테이블과 edge 구조로 저장한다.
- 관계 점수 계산은 SQL 또는 DB 인접 계층 서비스 로직으로 계산하되 저장소는 PostgreSQL 하나로 고정한다.
- bounded-depth traversal과 cycle 방지는
WITH RECURSIVE,SEARCH,CYCLE구문을 우선 사용한다.
그래프 테이블 초안
create table graph_nodes (
node_id uuid primary key,
tenant_id uuid not null,
node_type text not null,
payload jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create table graph_edges (
edge_id uuid primary key,
tenant_id uuid not null,
src_node_id uuid not null references graph_nodes(node_id),
dst_node_id uuid not null references graph_nodes(node_id),
edge_type text not null,
weight numeric(6,3) not null default 1.0,
payload jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
실행 순서
1. 벡터 저장 구조를 먼저 PostgreSQL로 확정한다
Chroma collection의 공통 속성을 추출한다.tenant_iddocument_idcontentembedding vector(768)metadata jsonbcreated_atupdated_at
- 저장 전략은
global table + tenant key를 기본값으로 둔다. - 인덱스 초안은 아래를 기본으로 둔다.
embedding용 HNSWtenant_id,created_at, 주요 metadata key용 btree 또는 표현식 인덱스- 필요 시 tenant 또는 도메인 단위 partition
2. 검색 스키마와 랭킹 공식을 고정한다
- 검색 대상 테이블은
document_search같은 단일 검색 뷰 또는 검색 전용 테이블로 수렴시킨다. - 색인 필드는 최소 아래를 포함한다.
titlecontentsummarytagsmetadata jsonb
- 랭킹은 아래 순서로 결합한다.
ts_rank_cd(weighted_tsvector, query)pg_trgm similarity- 필요 시
vector distance - 최신성 또는 중요도 가중치
- 이 결합은 SQL 함수 또는 view로 감싼다.
3. 그래프 구조를 PostgreSQL 관계 모델로 재작성한다
- 기본 구조는 아래 두 테이블 계열로 시작한다.
graph_nodes(node_id, node_type, payload jsonb, tenant_id, created_at)graph_edges(edge_id, src_node_id, dst_node_id, edge_type, weight, payload jsonb, tenant_id, created_at)
- 사건-감정-결과 관계는
edge_type으로 표준화한다. - 회상과 추론은 bounded-depth recursive query로 먼저 구현한다.
- 계층형 경로나 고정 깊이 탐색이 반복되면
ltree또는 materialized path를 보조 채택한다.
4. 이관 단위를 서비스별로 나눈다
- 1차:
rb8001메모리 벡터와 recall - 2차:
skill-rag-file문서 벡터와 검색 - 3차: 검색 전용 API 또는 검색 보조 기능
- 4차: Neo4j 관계 추론 경로
- 각 단계는
기존 읽기 경로 병행 -> PostgreSQL 결과 비교 -> 읽기 경로 전환 -> 기존 저장소 쓰기 중지 -> 기존 저장소 제거순으로 진행한다.
4-1. 대표 질의셋을 먼저 고정한다
- 벡터 질의셋:
- 최근 기억 회상
- 사용자별 유사 대화 top-k
- 메타데이터 필터 포함 회상
- 검색 질의셋:
- 정확 키워드
- 두 단어 구문 검색
- 오타 1~2글자 포함 검색
- 태그/metadata 필터 포함 검색
- 그래프 질의셋:
- 사건 -> 감정 -> 결과 연결 조회
- 최근 1년 bounded-depth 관계 회상
- 성공 사건 우선 랭킹
5. 운영 기준을 PostgreSQL 중심으로 다시 묶는다
- 백업 기준은 PostgreSQL dump/physical backup을 우선 SSOT로 삼는다.
- 모니터링은
pg_stat_statements, 인덱스 크기, bloat, query latency, vacuum 상태를 중심으로 본다. - 장애 복구 문서도
Chroma/Neo4j 복구가 아니라PostgreSQL 스키마/인덱스/데이터 복구중심으로 재작성한다.
검증 기준
기능 검증
- ChromaDB가 제공하던 top-k 벡터 검색이 PostgreSQL
pgvector에서 동일 tenant 범위로 재현된다. - 기존 검색 대표 질의셋이
FTS + pg_trgm경로에서 허용 가능한 품질로 재현된다. - Neo4j에서 표현하던 사건-감정-결과 관계 질의가 PostgreSQL recursive query로 재현된다.
운영 검증
- 백업/복구 절차가 PostgreSQL 기준 1세트로 단순화된다.
- 런타임 env와 문서 SSOT에서 ChromaDB, Neo4j, 검색 전용 저장소를 필수 의존성으로 더 이상 요구하지 않는다.
- 서비스 로그에 전용 DB 연결 실패가 핵심 경로 장애 원인으로 남지 않는다.
닫힘 조건
rb8001,skill-rag-file기준 주요 벡터·검색·관계 기능이 PostgreSQL 경로로 동작한다.- 전용 DB 없이도 대표 사용자 시나리오가 재현된다.
- 관련 문서의 아키텍처 설명이
PostgreSQL + ChromaDB + Neo4j에서PostgreSQL 중심 단일 구조로 교체된다. - cut-over 후 worklog가 남고, 전용 DB 제거 또는 비활성화 근거가 기록된다.
- 24 런타임과 배포 문서에서
ChromaDB,Neo4j, 검색 전용 저장소가 필수 서비스 목록에서 제거된다.
리스크와 대응
- 벡터 검색 품질 저하 가능성:
- 동일 질의셋으로 ChromaDB와 PostgreSQL 결과를 병렬 비교한다.
- 검색 랭킹 불안정 가능성:
- 가중치 조정용 대표 질의셋을 먼저 고정한다.
- 그래프 질의 복잡성 증가 가능성:
- 무제한 탐색을 허용하지 않고 bounded-depth 시나리오만 먼저 지원한다.
- 테이블 비대화 가능성:
- tenant key, partial index, partitioning 후보를 초기에 같이 검토한다.
롤백 기준
- PostgreSQL 경로가 대표 질의셋에서 기존 결과 품질을 현저히 깨면 읽기 경로를 즉시 기존 저장소로 되돌린다.
- PostgreSQL 전환 후 p95 응답 시간이 합의 기준을 넘기면 쓰기 중지는 유지하되 읽기 cut-over는 보류한다.
- 롤백은
읽기 경로 restore -> 기존 저장소 쓰기 재개 -> PostgreSQL 비교 로그 보존순서로 수행한다.
다음 단계로 넘길 결정 항목
memory_vectors,document_vectors,graph_nodes,graph_edges,search_documents같은 실제 테이블 명세- HNSW 파라미터와 vacuum/maintenance 기준
- hybrid rank 공식
- 서비스별 cut-over 순서와 rollback 기준
실행 결과
- 1차:
rb8001메모리 벡터와 recall은 PostgreSQLmemory_vectors,memory_graph_nodes,memory_graph_edges로 전환 완료. - 2차:
skill-rag-file문서 벡터와 검색은 PostgreSQLteam_document_chunk+pgvector(768)로 전환 완료. - 3차:
rb8001의 잔여 Neo4j 런타임 경로였던coldmail memory,startup valuation comparable prior,valuation premia recalculation도 PostgreSQL 경로로 전환 완료. - 24 배포는
rb8001Gitea Actions와skill-rag-file실배포 검증으로 반영됐고, 컨테이너 헬스체크와 실제 저장/검색/재계산 결과로 확인됐다. - 이 계획의 닫힘 조건은 non-RDB 계층 PostgreSQL 통일 1차 실행 완료에서 충족 증거를 남겼다.
한 줄 결론
- 이번 계획의 핵심은
전용 DB를 유지할 이유를 찾는 것이 아니라,벡터 -> 검색 -> 그래프순서로 non-RDB 계층을 PostgreSQL 하나로 흡수하는 실제 전환 순서를 고정하는 것이다.