프로젝트 기억의 관계를 PostgreSQL 안에 둔다
맥락
ADR-0020은 프로젝트 기억의 관계를 Neo4j 에 두고 검색을 GraphRAG 로 하기로
제안했다. 그러나 상태가 제안됨에서 올라가지 못했다. 그 ADR 스스로 「아래가 채워지기 전에는
채택됨으로 올리지 않는다」며 네 가지를 열어 뒀고, 그중 어느 것도 답이 나오지 않았다.
그리고 그 네 가지 중 하나가 다른 셋을 막고 있었다 — 무엇을 그래프에 넣을지가 아직 안 정해졌다. 노드와 엣지 타입 목록이 없다. 무엇을 넣을지 모르는 채로 저장소를 고르면 고른 것이 맞는지 확인할 방법이 없다.
확인된 사실이 하나 더 있다. neo4j 문자열이 구현 저장소 셋(heymoa-server·heymoa-web·heymoa-ai)
어디에도 없다. 즉 지금 저장소를 바꾸는 비용이 0이다. ADR-0020 이 대안 1(Postgres 관계 테이블)을
기각한 근거는 "가변 깊이 탐색과 경로 질의가 재귀 CTE 가 된다"였는데, 그 부담을 실제로 겪어 본 적이
없다.
결정
- 프로젝트 기억의 관계를
heymoa데이터베이스 안의 관계 테이블로 둔다. 가변 깊이 탐색은 재귀 CTE 로 짠다. - Neo4j 를 도입하지 않는다. 「나중에 옮긴다」도 아니다 — 전환을 계획에 두지 않는다.
- 벡터 검색은 ADR-0013 그대로
heymoa-ai의 pgvector 에 남는다. 관계와 벡터가 다른 데이터베이스에 있다는 뜻이고, cross-database 쿼리 금지 규칙은 그대로다. - 이 결정은 「관계 질문을 제품에서 뺀다」가 아니다. ADR-0020 이 대안 3(현행 유지)을 기각한 근거는 여전히 유효하다 — "왜 바뀌었어?"·"이 결정과 관련된 할 일은?"은 답해야 하는 질문이고, 관계 테이블 + 재귀 CTE 로 답한다.
대안
대안 1 — ADR-0020 그대로 Neo4j + GraphRAG. 기각한 이유: 운영 데이터베이스가 둘이 되고 그 정합성을 앱이 진다. 노트 삭제·재분석이 그래프에도 전파돼야 하는데, 파괴적 마이그레이션 규칙은 Postgres 에만 있다. ADR-0020 이 「결과」 절에 스스로 적어 둔 대가들이고, 그것을 감수할 근거가 되어야 할 "관계 질문의 모양"이 아직 정의되지 않았다. 3인 팀에서 Cypher·GraphRAG 를 아는 사람이 하나면 버스 팩터 1 이 된다는 것도 같은 ADR 이 적었다.
대안 2 — PostgreSQL 로 먼저 짓고 조건이 오면 Neo4j 로 옮긴다. 기각한 이유: 2026-08-15 에 한 번 이 판정을 했다가 하루 만에 뒤집었다. 전환 조건을 세워 두면 「먼저 PG」가 「영영 PG」가 되거나 반대로 근거 없이 옮기게 된다는 것이 그때의 걱정이었는데, 실제로 조건을 써 보니 그 조건이 관측될지 자체가 미지였다. 계획에 두지 않고 관측이 오면 그때 새 ADR 을 쓰는 것이 정직하다.
대안 3 — 요약 인덱스 agentic 검색. 기각한 이유: ADR-0020 의 판단을 그대로 잇는다. 근거 링크의 정확성이 매 호출의 운에 걸린다.
결과
- 운영 데이터베이스가 하나로 유지된다. 백업·마이그레이션·접근 제어·모니터링이 한 벌이다. 인프라 형상 문서에서 「VPC 밖에 저장소가 없다」가 참으로 남는다.
- 두 저장소 사이의 정합성을 앱이 지지 않는다. 노트 삭제와 재분석이 관계 테이블에 FK 와 CASCADE 로 전파된다 — 코드가 관리하는 약속이 아니라 스키마가 강제하는 것이 된다.
- 간선 종류가 늘수록 쿼리가 커진다. 이것이 감수하는 대가다. 재귀 CTE 는 홉 수가 늘면 읽기 어렵고, 경로 질의는 Cypher 로 짜는 것보다 길다.
- Cypher·GraphRAG 학습 비용이 0 이다.
- 되살아나는 문은 열려 있다 — 재귀 CTE 의 홉 수가 3을 넘는 질의가 화면에 필요해지거나, 재귀 CTE 로 표현 자체가 안 되는 질문이 나오면 그때 새 ADR 을 쓴다. 판정이 아니라 관측이 그 문을 연다.