From 8379e9f6475f98fac689f89a6350205f07ab1358 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Tue, 17 Mar 2026 00:08:04 +0900 Subject: [PATCH] Add PostgreSQL consolidation plan --- journey/README.md | 1 + ...postgresql로_통일하는_아이디어.md | 2 + ..._nonrdb_계층_postgresql_통일_계획.md | 172 ++++++++++++++++++ ...합_vs_전용db_구조성능_리서치.md | 3 +- 4 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 journey/plans/260317_nonrdb_계층_postgresql_통일_계획.md diff --git a/journey/README.md b/journey/README.md index 55309d9..4bb5625 100644 --- a/journey/README.md +++ b/journey/README.md @@ -73,6 +73,7 @@ - [51123 구 IP 하드코딩 실행 경로 제거 계획](./plans/260309_51123_구IP하드코딩_실행경로제거_계획.md) - [24서버 실서비스 운영전환 계획](./plans/260309_24서버_실서비스운영전환_계획.md) - [24 자동배포 0초 종료 runtime SSOT 복구 계획](./plans/260311_24자동배포_0초종료_runtime_ssot복구_계획.md) +- [non-RDB 계층 PostgreSQL 통일 계획](./plans/260317_nonrdb_계층_postgresql_통일_계획.md) - [23서버 워크스페이스 SSOT 구조전환 계획](./plans/260309_23서버_워크스페이스_SSOT_구조전환_계획.md) - [외부 NAS -> 내부 NAS 컴퍼니엑스 동기화 운영계획](./plans/260311_external_nas_companyx_sync_운영계획.md) - [외부 NAS -> 내부 NAS 컴퍼니엑스 실시간동기화 계획](./plans/260312_external_nas_companyx_실시간동기화_계획.md) diff --git a/journey/ideas/260316_모든db를_postgresql로_통일하는_아이디어.md b/journey/ideas/260316_모든db를_postgresql로_통일하는_아이디어.md index 4f1189a..e374631 100644 --- a/journey/ideas/260316_모든db를_postgresql로_통일하는_아이디어.md +++ b/journey/ideas/260316_모든db를_postgresql로_통일하는_아이디어.md @@ -12,6 +12,7 @@ tags: [infra, database, postgres, ideas, consolidation] ## 관련 문서 - [Infra Journey](../README.md) - [PostgreSQL 통합 vs 전용 DB 구조성능 리서치](../research/260316_postgres_통합_vs_전용db_구조성능_리서치.md) +- [non-RDB 계층 PostgreSQL 통일 계획](../plans/260317_nonrdb_계층_postgresql_통일_계획.md) - [PostgreSQL Neo4j TCP healthcheck](../troubleshooting/260115_postgresql_neo4j_tcp_healthcheck.md) ## 문제 인식 @@ -71,6 +72,7 @@ tags: [infra, database, postgres, ideas, consolidation] - 이 아이디어는 검토 대상이 아니라 현재 방향으로 고정할 수 있다. - 현 단계 목표는 `전용 DB와 non-RDB 저장소를 유지할 이유를 찾는 것`이 아니라 `PostgreSQL 통일 경로를 설계하는 것`이다. +- 실행 순서와 제거 대상 우선순위는 [non-RDB 계층 PostgreSQL 통일 계획](../plans/260317_nonrdb_계층_postgresql_통일_계획.md)으로 넘긴다. - 현재 시점의 해석은 아래 문장으로 고정한다. `인프라의 벡터, 그래프, 검색 계층은 지금부터 PostgreSQL로 통일하는 방향으로 정리하고, 전용 DB는 현 단계에서 제거 대상으로 본다.` diff --git a/journey/plans/260317_nonrdb_계층_postgresql_통일_계획.md b/journey/plans/260317_nonrdb_계층_postgresql_통일_계획.md new file mode 100644 index 0000000..48956a6 --- /dev/null +++ b/journey/plans/260317_nonrdb_계층_postgresql_통일_계획.md @@ -0,0 +1,172 @@ +--- +tags: [infra, database, postgres, pgvector, search, graph, plans] +--- + +# 260317 non-RDB 계층 PostgreSQL 통일 계획 + +**상태**: planned + +## 상위 원칙 +- [Infra Project Identity](../../00_Philosophy/00_IDENTITY/Infra_Project_Identity.md) +- [Core Infrastructure Principles](../../00_Philosophy/01_PRINCIPLES/Core_Infrastructure_Principles.md) +- [Operational Guardrails](../../00_Philosophy/02_GUARDRAILS/Operational_Guardrails.md) +- 공통 작성 원칙: [0_VALUE Writing Principles](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/writing-principles.md) + +## 관련 문서 +- [Infra Journey](../README.md) +- [PostgreSQL 통합 vs 전용 DB 구조성능 리서치](../research/260316_postgres_통합_vs_전용db_구조성능_리서치.md) +- [모든 DB를 PostgreSQL로 통일하는 아이디어](../ideas/260316_모든db를_postgresql로_통일하는_아이디어.md) +- [PostgreSQL Neo4j TCP healthcheck](../troubleshooting/260115_postgresql_neo4j_tcp_healthcheck.md) +- [백엔드: PostgreSQL, ChromaDB, Vector Memory 설계](https://github.com/happybell80/robeing/blob/main/DOCS/book/300_architecture/330_%EB%B0%B1%EC%97%94%EB%93%9C_PostgreSQL_ChromaDB_Vector_Memory.md) +- [Phase 2: ChromaDB + Neo4j 하이브리드 기억 회상 시스템 구현](https://github.com/happybell80/robeing/blob/main/DOCS/journey/troubleshooting/251016_phase2_hybrid_memory_implementation.md) + +## 문제 정의 + +- 현재 운영 구조는 관계형 데이터는 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 기능만으로 빠르게 흡수 가능하며, 그래프는 모델 재설계 논의가 가장 많이 필요하다. + +## 목표 상태 + +### 1. 벡터 + +- 문서/메모리/질의 임베딩은 PostgreSQL `pgvector(768)` 컬럼으로 저장한다. +- tenant 분리는 별도 컬렉션이 아니라 `tenant_id` 또는 동등한 범위 키로 관리한다. +- 메타데이터 필터, 최근성, 중요도, 사용자 범위는 SQL 조건으로 함께 평가한다. + +### 2. 검색 + +- 문서 본문, 요약, 태그, metadata jsonb는 PostgreSQL 내부에서 색인한다. +- 정확 키워드/구문은 FTS, 오타/부분일치는 `pg_trgm`, 의미 유사도는 `pgvector`로 처리한다. +- 최종 검색 랭킹은 SQL 안에서 결합 가능하도록 정의한다. + +### 3. 그래프 + +- 사건, 감정, 결과, 참여자 관계는 PostgreSQL 테이블과 edge 구조로 저장한다. +- 관계 점수 계산은 SQL 또는 DB 인접 계층 서비스 로직으로 계산하되 저장소는 PostgreSQL 하나로 고정한다. +- bounded-depth traversal과 cycle 방지는 `WITH RECURSIVE`, `SEARCH`, `CYCLE` 구문을 우선 사용한다. + +## 실행 순서 + +### 1. 벡터 저장 구조를 먼저 PostgreSQL로 확정한다 + +- `Chroma collection`의 공통 속성을 추출한다. + - `tenant_id` + - `document_id` + - `content` + - `embedding vector(768)` + - `metadata jsonb` + - `created_at` + - `updated_at` +- 저장 전략은 `global table + tenant key`를 기본값으로 둔다. +- 인덱스 초안은 아래를 기본으로 둔다. + - `embedding`용 HNSW + - `tenant_id`, `created_at`, 주요 metadata key용 btree 또는 표현식 인덱스 + - 필요 시 tenant 또는 도메인 단위 partition + +### 2. 검색 스키마와 랭킹 공식을 고정한다 + +- 검색 대상 테이블은 `document_search` 같은 단일 검색 뷰 또는 검색 전용 테이블로 수렴시킨다. +- 색인 필드는 최소 아래를 포함한다. + - `title` + - `content` + - `summary` + - `tags` + - `metadata 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 결과 비교 -> 읽기 경로 전환 -> 기존 저장소 쓰기 중지 -> 기존 저장소 제거` 순으로 진행한다. + +### 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 제거 또는 비활성화 근거가 기록된다. + +## 리스크와 대응 + +- 벡터 검색 품질 저하 가능성: + - 동일 질의셋으로 ChromaDB와 PostgreSQL 결과를 병렬 비교한다. +- 검색 랭킹 불안정 가능성: + - 가중치 조정용 대표 질의셋을 먼저 고정한다. +- 그래프 질의 복잡성 증가 가능성: + - 무제한 탐색을 허용하지 않고 bounded-depth 시나리오만 먼저 지원한다. +- 테이블 비대화 가능성: + - tenant key, partial index, partitioning 후보를 초기에 같이 검토한다. + +## 다음 단계로 넘길 결정 항목 + +- `memory_vectors`, `document_vectors`, `graph_nodes`, `graph_edges`, `search_documents` 같은 실제 테이블 명세 +- HNSW 파라미터와 vacuum/maintenance 기준 +- hybrid rank 공식 +- 서비스별 cut-over 순서와 rollback 기준 + +## 한 줄 결론 + +- 이번 계획의 핵심은 `전용 DB를 유지할 이유를 찾는 것`이 아니라, `벡터 -> 검색 -> 그래프` 순서로 non-RDB 계층을 PostgreSQL 하나로 흡수하는 실제 전환 순서를 고정하는 것이다. diff --git a/journey/research/260316_postgres_통합_vs_전용db_구조성능_리서치.md b/journey/research/260316_postgres_통합_vs_전용db_구조성능_리서치.md index 910dfc9..16e75e1 100644 --- a/journey/research/260316_postgres_통합_vs_전용db_구조성능_리서치.md +++ b/journey/research/260316_postgres_통합_vs_전용db_구조성능_리서치.md @@ -12,6 +12,7 @@ tags: [infra, database, postgres, redis, pgvector, elasticsearch, neo4j, researc ## 관련 문서 - [Infra Journey](../README.md) +- [non-RDB 계층 PostgreSQL 통일 계획](../plans/260317_nonrdb_계층_postgresql_통일_계획.md) - [PostgreSQL Neo4j TCP healthcheck](../troubleshooting/260115_postgresql_neo4j_tcp_healthcheck.md) - [백엔드: PostgreSQL, ChromaDB, Vector Memory 설계](https://github.com/happybell80/robeing/blob/main/DOCS/book/300_architecture/330_%EB%B0%B1%EC%97%94%EB%93%9C_PostgreSQL_ChromaDB_Vector_Memory.md) - [Phase 2: ChromaDB + Neo4j 하이브리드 기억 회상 시스템 구현](https://github.com/happybell80/robeing/blob/main/DOCS/journey/troubleshooting/251016_phase2_hybrid_memory_implementation.md) @@ -124,7 +125,7 @@ tags: [infra, database, postgres, redis, pgvector, elasticsearch, neo4j, researc - `ChromaDB collection -> PostgreSQL table` 매핑 단위를 `tenant per table`, `global table + tenant key`, `partition per tenant` 중 무엇으로 잡을지 결정이 아직 없다. - Neo4j의 `Event-Emotion-Result` 그래프를 `adjacency table`, `materialized path`, `ltree`, `jsonb edge payload` 중 어떤 방식으로 표현할지 결정이 아직 없다. - 검색 쪽도 `문서 원문`, `요약문`, `태그`, `metadata jsonb`에 어떤 가중치를 줄지와 `FTS + pg_trgm + vector hybrid rank` 공식을 아직 정하지 않았다. -- 즉 이 주제의 다음 단계는 추가 일반론 리서치가 아니라 `스키마/인덱스/랭킹 설계 계획`이다. +- 즉 이 주제의 다음 단계는 추가 일반론 리서치가 아니라 [non-RDB 계층 PostgreSQL 통일 계획](../plans/260317_nonrdb_계층_postgresql_통일_계획.md) 기준의 `스키마/인덱스/랭킹 설계 실행`이다. ## 한 줄 결론