--- tags: [research, rag, robeing, postgres, graph, relations] type: research status: closed closed_date: 2026-03-22 closed_reason: 설계 목적 달성, 200개 대상 구현 완료, Unresolved는 3차 계획 또는 후속 문서로 이관 research_target: PostgreSQL 기반 문서 관계 탐색과 그래프 확장 방식 정리 --- # PostgreSQL 그래프확장 설계 리서치 ## 상태 - **updated** (260320: 재귀 CTE → Apache AGE로 방향 변경) **작성일**: 2026-03-20 **목적**: PostgreSQL 안에서 문서 연결성과 탐색성을 확보하는 방법을 정리한다. --- ## 1. 결론 - ~~재귀 CTE로 충분~~ → **Apache AGE(PostgreSQL 그래프 확장)를 도입한다.** - AGE는 PostgreSQL 위에서 Cypher 쿼리를 지원하여, 복잡한 문서 관계 탐색을 직관적으로 처리한다. - 기존 PGVector + JSONB와 같은 DB 커넥션 안에서 벡터 검색 → 그래프 탐색 하이브리드 쿼리가 가능하다. ### 1.1 왜 Apache AGE인가 - **Cypher 지원**: `MATCH (d:Doc)-[:RELATED]->(r:Doc)` 식의 직관적 관계 탐색. 재귀 CTE 대비 쿼리 복잡도 대폭 감소. - **PGVector 동거**: 벡터 검색으로 후보군 → AGE로 맥락 확장이 하나의 DB에서 끝남. - **운영 단순화**: 별도 그래프 DB(Neo4j 등) 없이 PostgreSQL 하나로 통합. ### 1.2 설치 주의사항 - PostgreSQL 버전과 맞춰 컴파일 필요 — Docker 기반 설치 권장. - 에이전트가 Cypher를 구사하려면 프롬프트 DB에 Few-shot 예제 필요. ## 2. 연결 원천 - front matter의 `related` - 공통 `tags` - 공통 `keywords` - 같은 폴더/프로젝트/작성자 - 벡터 유사도 상 가까운 문서 ## 3. 권장 테이블 ```sql create table if not exists document_relations ( id bigserial primary key, from_document_id bigint not null references document_files(id) on delete cascade, to_document_id bigint not null references document_files(id) on delete cascade, relation_type text not null, weight numeric(6,3), metadata_jsonb jsonb not null default '{}'::jsonb, created_at timestamptz not null default now(), unique (from_document_id, to_document_id, relation_type) ); create index if not exists idx_document_relations_from on document_relations (from_document_id); create index if not exists idx_document_relations_to on document_relations (to_document_id); create index if not exists idx_document_relations_metadata on document_relations using gin (metadata_jsonb); ``` ## 4. relation_type 예시 - `explicit_related` - `same_folder` - `same_project` - `shared_tag` - `shared_keyword` - `semantic_neighbor` - `derived_from` ## 5. 내가 추천하는 연결 생성 방식 ### 5.1 명시 연결 우선 - front matter의 `related`는 사람이 검증한 연결이므로 신뢰도가 높다. ### 5.2 규칙 기반 연결 다음 - 같은 폴더, 같은 프로젝트, 같은 태그 등은 자동 생성하기 쉽다. ### 5.3 벡터 기반 연결은 후순위 - 유사도만으로 연결하면 오탐이 많을 수 있다. - `semantic_neighbor`는 보조 연결로만 두는 것이 맞다. ## 6. 재귀 탐색 예시 ```sql with recursive related_docs as ( select df.id, df.title, 0 as depth from document_files df where df.id = $1 union all select df2.id, df2.title, rd.depth + 1 from related_docs rd join document_relations dr on dr.from_document_id = rd.id join document_files df2 on df2.id = dr.to_document_id where rd.depth < 3 ) select distinct id, title, min(depth) as min_depth from related_docs group by id, title order by min_depth, id; ``` ## 7. AGE 그래프 스키마 (운영 반영 전제) ### 노드 - `Document`: 문서 (title, source_path, file_type, tags) - `Folder`: 폴더/프로젝트 단위 - `Tag`: 태그/키워드 - `User`: 작성자/소유자 ### 엣지 - `RELATED`: 명시적 연결 (front matter related) - `IN_FOLDER`: 문서 → 폴더 - `TAGGED`: 문서 → 태그 - `AUTHORED`: 작성자 → 문서 - `SEMANTIC_NEIGHBOR`: 벡터 유사도 기반 보조 연결 ### Cypher 쿼리 예시 ```cypher -- 특정 문서의 2단계 관련 문서 탐색 MATCH (d:Document {title: '사업계획서'})-[:RELATED*1..2]-(r:Document) RETURN r.title, r.source_path -- 같은 폴더 + 같은 태그 문서 MATCH (d:Document)-[:IN_FOLDER]->(f:Folder)<-[:IN_FOLDER]-(r:Document) WHERE d.title = '감사계약서' RETURN r.title ``` ## 8. 현재 추천 - 51123 서버 PostgreSQL에 Apache AGE Docker 기반 설치. - `document_relations` 테이블 대신 AGE 그래프로 관계 관리. - PGVector(의미검색) + AGE(관계탐색)를 하나의 DB에서 하이브리드 운용. ## 현재 상태 보정 (2026-03-22) - Apache AGE: 운영 중. companyx_docs, document_graph 그래프 2개 운용. - 하이브리드 검색 (vector + keyword + graph RRF): 구현 완료. graph_score가 검색 경로에 합산됨. - 설계 별칭 document_relations = 운영 실체 Apache AGE 그래프. - team_document: 1,174건 / team_document_chunk: 3,474건. ## Unresolved - 그래프 노드/엣지 생성 규칙의 최종 SSOT가 아직 약하다. - 삭제·이동·재색인 시 그래프를 언제 갱신하고 언제 재구성할지 운영 기준이 부족하다. ## 10. 관련 문서 - [PGVector·JSONB RAG 스키마 설계 리서치](./260320_PGVector_JSONB_RAG_스키마_설계_리서치.md) - [Front Matter 메타데이터 설계 리서치](./260320_FrontMatter_메타데이터_설계_리서치.md)