S9 · REPORT2026-07-13 — 물리 저장 패러다임

SEM 기반 DB, 어떤 모습인가 — 개념은 그래프, 물리는 record-grain

"SEM을 기반으로 DB를 설계하면 어떤 모습이 되나? 관계형인가, 아니면 다른 형태(그래프·트리플스토어)인가? 무엇이 효율적인가?" — SEM 재정초 검토가 "저장 표현은 우리 것"이라 못박았지만 그 저장이 물리적으로 무엇인지는 정면으로 다루지 않았다. 이 보고서가 그 공백을 메운다.

방법. 물리-DB 논지를 4갈래 적대 검증(효율성·SEM 저장 팩트·proto 접근 패턴·전환 조건)에 걸었다. 네 검증 모두 결론(트리플스토어 아닌 record-grain 저장이 효율적)을 확증했으나, 초안의 슬로건은 네 이음매에서 과장·범주오류를 범했다 — 이 문서는 그 교정을 반영한 형태다. SEM=RDF 팩트는 1차 출처(semanticweb.cs.vu.nl/2009/11/sem/·van Hage JWS 2011), 접근 패턴은 proto 코드(store.js·lens.js·budget.js·journey-data.js)로 대조.

요 약

판정 먼저

SEM 기반으로 DB를 설계하면 어떤 모습? 관계형인가 다른 형태인가? 뭐가 효율적?
  1. SEM에 문자 그대로 충실한 DB = RDF 트리플스토어 + SPARQL. SEM은 RDF/OWL 온톨로지다(프로퍼티 그래프가 아니다). Event/Actor/Place/Time=노드, hasActor/hasPlace/hasTime=이항 트리플, Role/View/Temporary=reify(blank node·named graph). 저자의 SEM API도 트리플 기반(SWI-Prolog semweb). — 그런데 그건 우리가 갖지 않은 '열린 웹' 문제(통제 못 하는 이질적 다중출처·다중홉)의 해법이라, 닫힌 세계인 우리에겐 부담이다.
  2. 정직한 반전 — 우리는 이미 프로퍼티 그래프를 채택했다. 네이티브 SwiftData(@Model + 양방향 @Relationship)는 이름만 다른 영속화된 라벨드 프로퍼티 그래프이고, links 엣지 테이블은 이미 존재하며, 런타임 진리집합은 인메모리 오브젝트 그래프다. 그러니 정직한 결론은 "관계형이 그래프를 이긴다"가 아니라 — "우리는 프로퍼티-그래프 모델을 이미 쓰고, 다만 두 가지를 거절한다": (a) RDF 트리플스토어의 reification 세금, (b) 별도 그래프 엔진의 운영비용. 즉 그래프의 패배는 적합성이 아니라 규모·운영에서다.
  3. 그래프가 진짜 값을 갖는 건 아직 없는 두 미래뿐. (i) 자서전→공존 연대기 정체성 피벗 시의 강형 공동증언(§10의 named-graph 쓰기-모델 변경), (ii) 그 위 speculative 다중홉 경로 읽기('누가 언제 어디서 누구와'). 그때도 쓰기 관계형 정본은 유지하고 그래프/검색/이식은 읽기 투영(CQRS)·export 층으로 얹는다. 둘 다 측정 gated — 오늘은 아무것도 아니다.
지금 후회 없는 수 — 그래프 질문과 무관하게: byEvent id-배열 blob을 1급 Involvement 조인/@Model로 승격한다. 역인덱스·복합 파셋·미래 그래프 투영의 공통 선결조건이자 오늘의 관계형 쿼리도 개선한다. 나머지(다중홉·강형·전용 그래프 DB 여부)는 실 워크로드가 등장하면 측정으로 결정.
직역

1 · SEM에 충실한 DB = RDF 트리플스토어 (LPG 아님)

먼저 세 물건을 구분해야 한다 — 뭉개면 왜 무엇을 거절하는지가 흐려진다. 'SEM에 충실'은 그래프 일반이 아니라 RDF 특정이다.

SEM의 실제 고향

RDF 트리플스토어

  • 원자 = 이항 트리플. n-항 사실·역할은 reify 필수(blank node/named graph).
  • 전역 IRI·OWL2 punning·SPARQL·개방세계·최소 확약.
  • 강하게 거절 — reification 세금 + 우리가 없는 개방-웹 문제.
인접 오해

라벨드 프로퍼티 그래프

  • 원자 = 속성 얹은 노드/엣지. Involvement.role=엣지 속성이라 reification 불필요.
  • index-free adjacency(깊은 traversal에 강함).
  • 약하게·조건부 거절 — 적합성 아니라 두 번째 엔진 운영비.
우리 선택

관계형/오브젝트 그래프

  • Event=행, Involvement=조인 행, 돈4역=사건 참조 테이블, 겹=멤버십 컬럼.
  • Supabase Postgres(인증 경로 RLS) → SwiftData(@Model).
  • 정본 — 우리 규모·정체성에 맞음.
SEM이 트리플인 진짜 이유. SEM은 'SPARQL 쓰려고 트리플'이 아니라 LOD(연결 데이터) 생태계 편입을 위해 RDF를 채택했고, 그 결과가 트리플·SPARQL이다. 그 최소 확약(무 cardinality·무 functional·disjointness 최소·punning)은 논문이 직접 "웹 데이터 출처를 통제·재설계할 수 없다"로 동기화한다. 우리는 그 문제가 없다 — 단일 소유·통제된 스키마·알려진 접근 패턴·경계 있는 소규모(개인 일생 = 10²~10⁴ 사건, 저차수). SEM의 설계 동인이 우리에겐 값 없는 세금인 이유다.
가장 날카로운 반론을 정직하게

2 · 정직한 반전 — 우리는 이미 프로퍼티 그래프다

그래프 진영의 급소는 "트리플스토어를 써라"가 아니라 "너희는 이미 프로퍼티 그래프를 채택하고 있으면서 그걸 관계형이라 부른다"이다. 이 반론은 옳고, 실어야 한다.

증거 셋. 네이티브 타깃 SwiftData(@Model + 양방향 @Relationship)는 사실상 영속화된 LPG다 — faulting을 통한 포인터-추적 adjacency(단일홉 index-free adjacency와 동형), 엣지 = Relationship, Involvement = role 속성을 얹은 엣지가 native 관용구(reification 0). repo 자체 정본도 "SwiftData(객체 그래프)는 Postgres(FK+RLS)와 성질이 달라"라 명시한다. links {fromType, fromId, toType, toId, relationType} — typed 다형 엣지 리스트가 이미 존재하고 오늘도 depth-1로 순회된다(시나리오↔결정). 런타임 진리집합은 인메모리 오브젝트 그래프(byEvent 해시맵 + 마스터 + 위성 배열)이며, 지속 백엔드(Postgres·localStorage·SwiftData)는 교환 가능한 직렬화 타깃일 뿐이다.

그래서 정직한 물리 진술은 "관계형 엔진(Postgres/SQLite) 위의 record-grain 오브젝트-그래프 매핑"이라는 하이브리드다 — 트리플스토어도, 순수 관계형도 아니다. 우리가 거절하는 두 가지:

  • (a) RDF 트리플스토어의 reification 세금 — §3에서 상술. 무거운 건 RDF이고, 관계형이 여기서 이긴다.
  • (b) 별도 그래프 엔진(Neo4j류)의 운영비용적합성 문제가 아니다. index-free adjacency의 점근 우위는 '대규모·깊은/무경계 traversal'에서 지불된다. 개인 자서전은 경계 있는 소규모·저차수라 관계형 self-join이 그 우위 지점에 도달하지 못한다. 두 번째 엔진의 운영·동기화 비용만 남는다.
무거움의 소재

3 · reification — 무거운 건 관계형이 아니라 RDF다

SEM 재정초가 "RDF reification을 문자 그대로 들이면 무겁다"고 했는데, 무거움의 소재를 정확히 해야 한다.

SEM 제약RDF 표현우리(관계형) 표현
Role (사건 내 역할)이항 트리플이라 n-항 못 담음 → reify(blank node/named graph)넓은 조인 행 하나: Involvement{event, target, role, order}
Temporary (시간 한정 유효)유효구간을 named graph로 reify·저장저장 안 하고 파생(now 대비) — 원칙 7
View (관점별 증언)accordingTo → Authority (per-property)시나리오 겹 = 멤버십 컬럼(record-grain) · 강형은 §5로 유예
관계형이 여기서 이긴다. 트리플은 이항이라 "누가·언제·어디서·어떤 역할로·누구 관점에서"라는 n-항 사실을 native로 못 담아 우회(reification)하느라 무겁다. 관계형은 reification을 '들일' 필요가 없다 — 그 n-항 자격은 넓은 조인 행 하나다. 즉 SEM의 Role/Temporary/View 제약의 자연스럽고 가벼운 집은 오히려 관계형이다. 이것이 sem-refoundation §5·다화자 §2record-grain(우리, 관계형 행) vs property-grain(SEM, 트리플) 구분과 정확히 같다 — 부담 회피가 아니라 RDF 대비 우위.
단, 과장 금지. 우리 조인 행이 평탄화한 건 참여·멤버십(event↔마스터, 다형 {target_type, target_id}, DB 강제 FK 없이 앱층 무결성)이다. per-event role-qua-role는 아직 어디에도 reify돼 있지 않다(role 필드는 후속·현재 null 근사). "Involvement이 이미 Role reification을 평탄화했다"가 아니라 "멤버십을 평탄화했고 role은 미확정"이 정확하다.
왜 관계형이 옳은가 + 어디까지 그래프꼴인가

4 · 진짜 판별자, 그리고 층별 정직

"관계형이 집계·정렬에 강하다"는 판별자가 아니다 — 프로퍼티 그래프(Cypher)도 ORDER BY·집계를 정상 수행한다. 진짜 판별자는 셋이다.

  1. RLS·강제 행-보안 — Postgres가 성숙하고 그래프/트리플은 약하다. 단 이건 Supabase-era 논거다 — 네이티브(CloudKit private DB=사용자별 컨테이너 격리) tier엔 적용되지 않는다(tier마다 다름).
  2. 정형 사건행 위 성숙한 분석 SQL·복합 파셋 pushdown — "그 사람의 특정 기간·flow 조건 사건"은 SQL WHERE+조인을 플래너가 pushdown하지만, SwiftData #Predicate는 to-many 조건을 pushdown 못 해 별도 fetch가 필요하다. 복합 파셋은 관계형을 지지한다.
  3. 단일 엔진 운영 단순성 — 두 번째 엔진(그래프 DB)의 운영·동기화 비용 회피.
패러다임-중립인 것은 근거로 쓰지 않는다. 순자산 곡선 fold(budget.js series()의 시간축 적분·복리)와 시나리오 겹 재합성(setOverlay의 확정−가림+델타)은 앱 메모리에서 도는 연산이다 — 관계형이든 그래프든 앱층에서 똑같이 fold한다. 이 둘은 '관계형 우위'의 증거가 아니다. (여비는 네 쓰기모델 위의 L1 시뮬레이션이지 그래프도 파셋도 아니다.)

어디까지가 진짜 '그래프'인가 — 오직 L0

L0
사건 코어 — Event↔성분(Involvement)↔마스터. 이분 그래프 (조인 행으로 평탄화)
L1
파생 — 시제·롤업·곡선. 그래프 아님 (fold 시뮬레이션·패러다임 중립)
L2
돈 4역 — 사건에 앵커된 역태그 flow. 그래프 아님
L3
시나리오 겹 — 전역 엔진 재합성 상태연산자(CQRS의 반대). 그래프 아님

즉 '개념적으로 그래프'는 L0 사건 코어에만 해당한다 — 그마저 조인 행으로 평탄화된 이분 그래프다. 파생·돈·겹 층은 개념적으로도 그래프가 아니다. 정직한 요약: 사건 코어는 조인 행으로 평탄화된 이분 그래프, 나머지는 시뮬·상태 재합성 — 전반적으로 관계형.

전이 조건

5 · 그래프가 값을 갖는 두 미래 — 그리고 RDF의 진짜 값

그래프의 진짜 집은 '전 다화자 기능'(출하된 약형은 그래프 불필요 — 관계형 조인 엣지+CQRS)도 아니고 '결코'도 아니다. 아직 없는 두 미래다.

미래무엇어느 축
강형 공동증언
(§10 fork)
자서전→공존 연대기 정체성 피벗 시, 하나의 공유 사건 노드 위 비해소 병렬 증언(sem:View/accordingTo/named-graph)쓰기-모델·L4 소유권 변경 — 읽기 투영이 흡수 못 함
다중홉 경로 읽기'아버지와 제주 사건들, 그 사건에 또 등장한 인물' 같은 관계-발견 질의(speculative·미착지)읽기 투영 — 쓰기 관계형 정본 유지
"쓰기는 항상 관계형"은 무조건이 아니다. 강형 공동증언(위 첫 행)은 per-property 경쟁 증언을 결코 해소하지 않아야 하는 named-graph 쓰기-모델이라, 읽기 투영으로 흡수되지 않는 진짜 '갈아엎기'다 — 단 정체성 피벗에 gated. 다화자 커밋된 약형은 그래프가 불필요하지만, 이 강형 rung은 유예된 쓰기측 예외로 남겨 둔다.
RDF의 진짜 값 = traversal이 아니라 정체성·병합·이식. RDF/SEM이 정작 잘하는 건 다중홉이 아니라 — 전역 dereferenceable IRI 기반 교차소유 동일성 병합, 마이그레이션 없는 스키마리스 union, SEM *Type의 외부 SKOS/OWL 링크(GeoNames·Wikidata·FOAF). 방금 커밋한 다화자 correlation Link는 사실상 owl:sameAs/IRI 정체성 상관을 관계형으로 재발명한 것이다. 그리고 닫힌 세계 전제는 다화자·export 경계에서 '미니 열린 세계'로 재진입한다(이질적 정체성·비협조 스키마·병합). 이 interop 값은 트리플 저장 없이 관계형 정본 위 RDF/JSON-LD export 투영으로 수확한다 — '읽기 투영'에 interop export view를 포함시키는 것이 우리 CQRS 패턴의 정직한 확장이다.
실행

6 · 지금 할 것 · 유예할 것

지금 (후회 없음, 그래프 질문과 독립)byEvent id-배열 blob을 1급 Involvement 조인/@Model로 승격. 역인덱스 이득·복합 파셋 질의·미래 그래프 읽기투영의 공통 선결조건이자 오늘의 관계형 쿼리도 개선한다. (sem-refoundation §6의 조건부 '역인덱스'가 이걸 전제로 한다.)
측정으로 유예 — 다중홉·강형 공동증언·전용 그래프 DB 여부는 실 워크로드·데이터량이 등장한 뒤에 결정. 전용 그래프 DB를 세우기 전에 in-DB/in-framework 수단부터: 경계 있는 다중홉은 재귀 CTE로 두 번째 엔진 없이, openCypher가 필요하면 Apache AGE(Postgres 내)로 운영분할 없이. (이 구체명은 정본 근거가 아니라 이 검토의 종합 — 방향인 '측정으로 결정'만 정본에 남긴다. 그리고 네이티브는 SwiftData tier라, Postgres 그래프 수단은 교차소유 백엔드 투영 tier에만 적용된다.)
범주 구분pgvector는 그래프 수단이 아니다. 근사최근접(ANN)·의미 유사도 검색(MCP/RAG의 '비슷한 기억 찾기')이라 별개 능력 결정이다. 그래프 수단(재귀 CTE·AGE)과 뭉개지 않는다.
한 줄 요약. SEM 직역은 RDF 트리플스토어지만, 우리는 이미 프로퍼티-그래프 모델을 관계형 엔진 위에서 쓰고 있다. 거절하는 건 그래프 적합성이 아니라 RDF의 reification 세금과 별도 엔진 운영비다 — 개인 자서전 규모·정체성에서 옳은 이유(문제 모양)로 옳다. 그래프-shaped 저장은 정체성 피벗(강형 쓰기)에서만 진짜 필요하고, 그 전까지 traversal·interop은 관계형 정본 위 읽기·export 투영으로 충분하다.