단일 소스, 렌즈는 문(門)
모두가 공유하는 중심 객체 하나(Event) + 성분 마스터(Person·Place·Subject) + 그룹핑(Project) + 돈 4역이 전부다. 렌즈는 같은 데이터를 다른 각도에서 보는 필터 + 투영일 뿐 — 어디서 입력하든 같은 객체를 편집하고 즉시 상호 반영된다. 상호 참조용 별도 필드가 필요 없다 — 모든 렌즈가 같은 id를 본다.
Involvement) · 문장 사이의 참조(Link). ③ 파생은 저장하지 않는다 — 시제·롤업·곡선·겹은 계산이다(원칙 7).층 구조 — 사건 코어 + 다섯 층
가드레일이 새 개념을 '어느 층에 드는가'로 라우팅한다. L1(파생)은 저장 층이 아니라 원칙 7의 관철이라 엔티티가 없다.
Event(6하의 한 문장) · Involvement(성분) · Person·Place·Subject(마스터) · Link(참조) · Project(그룹). 시간은 리터럴(start/end).NetWorthSnapshot) + 거처(Pocket) · 이동(Flow) · 배정(Allocation) · 목표(Goal).Scenario + 소속 3필드(scenarioId·baseId·removed)를 Event·Flow·Goal·Allocation에 얹는다.User+RLS(모든 데이터는 한 사람) · Publication(기본 비공개) · 렌즈(데이터 안 소유) · ProjectModule.Interview·Reflection·Question(엘리시테이션 엔진) · 책자·백업(산출).엔티티 한눈에
마스터(점선) = 여러 사건에 재등장하는 참조점(Person·Place·Subject). 이들은 시나리오를 타지 않는다(하나뿐).
Event — 인생의 한 문장 (6하원칙)
마일스톤·일정·시대를 쪼개지 않고 하나의 Event로 관리하며 kind로만 구분한다. 6하의 성분이 각자의 자리를 갖는다.
| 6하 | 개념(별칭) | 모델 |
|---|---|---|
| (주어) | 나 | 암묵 — 모든 데이터는 한 User에 귀속(표시에서만 접힘) |
| 언제 | 일정 | Event.start/end — 시제의 원천(선택값) |
| 어디서 | 무대 | Place + Involvement |
| 누가 | 등장인물 | Person + Involvement |
| 무엇 | 대상 | title + Subject + Involvement |
| 어떻게 | 방법 | Event.how (텍스트) |
| 왜 | 이유 | Event.why (텍스트) |
Event 필드
| 필드 | 뜻 · 값 |
|---|---|
| id | 필수 식별자 |
| title | 필수 요약 서술('인생의 한 문장') |
| kind | 필수 milestone(순간·점) · span(구간·작업) · era(시대·색인) |
| projectId | 선택 → Project. null=프로젝트 없는 순수 마일스톤·시대 |
| start | 선택 시작일. 없으면 타임라인 비노출·수첩 전용(backlog). era는 필수 |
| end | 선택 종료일 — span·era의 끝. milestone(점)·날짜미정=null |
| startPrecision | 선택 A2 exact|month|year|circa — 퍼지 과거('1983년쯤')를 '날짜미정'과 구분(리터럴 유지) |
| endPrecision | 선택 A2 (동일) |
| priority | '항상 표시' 핀(이진). 축소·요약해도 보임. era는 미지정 |
| category | 선택 (era 전용) 주제 트랙 — 학교·커리어·정서 등 사용자 정의(빈 값=‘기본’) |
| status | backlog|todo|done|aborted — 맥락 중심 상태. aborted A2=자원 투입 후 무산된 과거 계획 |
| why · how · note | 선택 이유 · 방법 · 자유 메모 |
| scenarioId · baseId · removed | 시나리오 소속 3필드 → 겹. modal 전용 |
kind은 4번째 축이 아니라 '모양'이다. milestone(점)·span(구간)·era(시대)는 아래 세 선택 속성과 독립이다.세 선택 속성 — 어느 1차 렌즈에 뜨나
| 축 | 필드 | 있으면 뜨는 렌즈 |
|---|---|---|
| 언제(일정) | start·end | 여정 — 타임라인에 배치 (없으면 수첩에만) |
| 상태(task) | status + 맥락 | 수첩 — 맥락별 '할 것/이룬 것' 롤업 |
| 돈(배정) | Allocation·Goal·Flow | 여비 — 배정된 것만 |
성분과 참조 — 조인은 딱 둘
Involvement(문장 안) · Link(문장 사이). 이 둘 외의 새 조인은 페이로드가 실릴 때만 만든다(Allocation이 유일 전례 — 금액을 나름).
Involvement — 성분 | 뜻 · 값 |
|---|---|
| id | 필수 |
| eventId | 필수 → Event (어느 문장의 성분인가) |
| targetType | 필수 person | place | subject |
| targetId | 필수 → 해당 마스터 |
| role | 선택 null 출발 — with/host·at/from/to·acquire/use… (어휘 후행) |
| order | 선택 다중 경유 순서 |
| attributedTo | 선택 A2 이 사실을 누구 증언으로 귀속하나(→Person). null=암묵 '나'. '소유≠귀속'의 씨앗 |
Link — 느슨한 참조 | 뜻 · 값 |
|---|---|
| id | 필수 |
| fromType · fromId | 필수 event|reflection|project|person|place|subject|scenario |
| toType · toId | 필수 (동일) |
| relationType | 선택 null 출발 — depends-on·blocks·reflects-on·achieves·occurs-during·sameAs A2… |
성분 마스터 — 여러 사건의 공통 참조점
| 엔티티 | 필드 (전 필드 선택 · name만 권장) |
|---|---|
| Person 누가 | name · relation(관계 호칭) · birthDate · gender A2 · occupation · note. ≠ User(내 기록 속 인물) |
| Place 어디서 | name · address · geo(lat/lng) · note. 같은 장소가 '한 장소의 역사'로 쌓임 |
| Subject 무엇 | name · attrs(자유 키-값) · note. 구체물(자동차)도 범주(비상금)도 — 돈은 안 담고 정체만 |
| Project 그룹 | title · description · status(planning|active|paused|done) |
마스터는 시나리오를 타지 않는다(하나). 시변 정체성(개명·재혼)은 유예 — 지금은 Link("sameAs")로만 상관.
돈의 4역 + 지갑
돈의 역할은 넷으로 딱 떨어지고, '인생 노드'(Project·Event·Goal·Subject)가 공통 참조점이다. 스톡은 내부 구조로 지갑(Pocket)을 갖는다 — 금융상품 = 지갑(잠김) + 계약된 이동(Flow) + 성장률의 조합이다.
| 역 | 엔티티 | 질문 |
|---|---|---|
| 스톡 | NetWorthSnapshot | 지금 얼마가 있나 |
| 이동 | Flow | 돈이 언제 어떻게 드나드나 |
| 배정 | Allocation | 지금 돈이 무슨 임무를 맡았나 |
| 목표 | Goal | 얼마까지 모아야 하나 |
| 엔티티 | 주요 필드 |
|---|---|
| Pocket 지갑 | name · label(상품 종류명·자유) · balance(만원 — 음수 허용=부채 A2) · growth{rate,min?,band?} · lock{age|date}? · payout{monthly,years?|life?}? · contribution{monthly}? · est? |
| NetWorthSnapshot 스톡 | date · amount(자산−부채) · pocketId?(null=총액 한 줄) · note |
| Flow 이동 | label? · direction(in|out) · fromPocketId? · toPocketId? · amount · cadence(monthly|yearly|weekly|null=일회) · dayOfMonth? · startDate/endDate(반복) · eventId(일회성 앵커·필수) · subjectId? · projectId? · +3필드 |
| Goal 목표 | label · targetAmount · targetDate · targetType(networth|project|event|subject) · targetId(networth면 null) · +3필드 |
| Allocation 배정 | amount · targetType(project|event|goal|subject) · targetId · +3필드 |
Flow는 사건 없이 못 산다(eventId 필수) — 돈이 움직였으면 그날 무슨 일이 있었다. 시점은 앵커 start에서 파생. ② 내부 이동(from·to 둘 다 지갑) = 순자산 불변(유동성만 이동). ③ 계단(반복)/점프(일회)는 데이터가 아니라 렌더 별칭.예측 곡선·런웨이·미배정 자금·유동성 경고는 저장하지 않고 계산한다(파생). 스냅샷=시작점 · 반복 Flow=계단 · 일회 Flow=점프 · Goal=결승선.
시나리오 — 미래는 여러 벌, 결정은 하나
확정 세계 위에 미래 대안을 겹쳐 그리고 → 견주고 → 하나를 골라 승격하고 → 이력으로 남긴다. 시나리오는 이 순환을 담는 겹이다 — 별도 세계가 아니라 확정 세계에 대한 diff(계산).
Scenario | 뜻 · 값 |
|---|---|
| id · title | 필수 "제주 이주", "서울 잔류" |
| status | exploring(구상) · chosen(승격) · shelved(보류) · discarded(접음·이력 유지) · coexisting A2(비붕괴 병존) |
| authorLabel | 선택 A2 '누가 그렸나' 표시용(아버지가 그리는 내 미래 등). 진짜 소유는 user_id에서 파생 |
| asOf · note · decidedAt | 어느 현실을 전제로 · 저울질 기록 · 결정 시점 |
소속 3필드 — Event·Flow·Goal·Allocation에 공통으로 얹음
| 필드 | 뜻 |
|---|---|
| scenarioId | null = 확정 세계(baseline). 지금까지의 모든 데이터가 자동으로 확정 세계 |
| baseId | null=시나리오에서 새로 그림 · 값=확정 레코드의 '시나리오판'(원본을 가림) |
| removed | true=이 시나리오에선 '없던 일로'(원본 가리는 삭제 표식) |
baseId(가림)·removed(뺄셈)는 '기준세계 있음·붕괴 지향'에 용접돼 있어, 관점/저자축(인식적·대등)을 오버로드하면 한 관점이 다른 관점을 지운다. 관점파생 미래의 양상 절반은 status=coexisting으로, 관점/저자 절반은 유예된 L4 View로 간다.원칙: 시나리오는 미래에만 · 마스터는 안 탐 · 기본 뷰=확정 세계 · 수정판은 문장 단위(성분도 복사) · 참조는 수정판 우선 · 중첩 없음(평평).
인터뷰 / 성찰 — 타임라인을 끌어내는 엔진
인터뷰는 과거에 한정되지 않는다. 회상형 질문 → 과거 Event, 지향형 질문 → 미래 Event를 생성하며 성분(인물·장소)도 함께 채운다.
| 엔티티 | 주요 필드 |
|---|---|
| Reflection 성찰 | interviewId? · questionId? · anchorTime?(가리키는 시점) · content · voice A2(누구의 목소리→Person) · media[](멀티모달) · sensitive(기본 true) · createdAt |
| Interview 세션 | mode(self|facilitated) · intervieweeId(User) · interviewerId · date · title · context · status(in_progress|done) |
| Question 질문 | text · type(random|typology|dialogue) · orientation(retrospective|prospective|open) · theme. 유일한 공용 엔티티(User 비귀속·어드민 관리) |
Reflection은 Link로 사건·인물·장소·대상·시나리오를 가리킨다("왜 망설이는가"가 데이터로 남음). 가장 사적인 데이터라 오프라인 우선·암호화 1순위.
렌즈 — 같은 데이터, 여러 개의 문
렌즈 = 필터 + 투영. 1차 렌즈는 사건을 축으로, 2차 렌즈는 성분 마스터에서 출발해 1차를 역투영(재사용)한다. 마스터 관리 화면은 따로 없다 — 렌즈가 곧 관리 화면.
| 렌즈 | 읽는 것 |
|---|---|
| 여정 1차·언제 | start 있는 Event[] + '지금 선' 파생 + 시나리오 가지(비교) |
| 수첩 1차·맥락 | Project[] + Event[](날짜미정 backlog 포함) + 등장인물 롤업(파생) |
| 여비 1차·돈 | Pocket[] + 스냅샷 + 배정 + 예측 곡선(Flow) + Goal[] + 시나리오 곡선 비교 |
| 주소록 2차·누가 | Person[] + 성분 역참조(그 사람과의 여정·다가올 만남) |
| 지도 2차·어디서 | Place[] + 성분 역참조(그 장소의 사건·시대 무대·동선) |
| 사물함 2차·무엇 | Subject[] + 돈 4역 참조(충전 게이지) + 이벤트 이력 |
| 갤러리 2차·미디어 | Reflection.media의 시간·성분 투영 |
상태 모델 — 맥락 중심 3(+1)상태
backlog(착상·날짜미정 허용) · todo(지금 이 맥락에서 할 것·승격 시 맥락 필수) · done(맥락에서 바뀐 것) · aborted A2(무산). status ≠ 성취(outcome) — done 중 성취만 Reflection 링크로 여정에 마일스톤 승격(파생). 개입 3지점: 착수 · 성취 확정 · 갈림길 결정.
모든 데이터는 한 사람의 것
모든 최상위 엔티티는 정확히 한 User에 귀속된다(구현: user_id 컬럼 + RLS 2겹). 유일한 예외는 공용 질문 풀 Question.
| 엔티티 | 주요 필드 |
|---|---|
| User 계정 | uid(불변=Supabase Auth id) · displayName? · birthDate? · gender? · createdAt. 프로필 필수 없음 |
| Publication 공개 | targetType · targetId · channel · publishedAt · revokedAt(null=공개 중). 레코드 없으면 비공개 |
| ProjectModule 모듈 | projectId · type · scope(common|custom) · storage(lens=데이터 없음·필터 / store=고유 데이터 소유) · order · config |
스냅샷 − Σ배정) · 시나리오 확정세계 재합성 · 타인 병치·색인(co-narrate)(무소유 CQRS 읽기 투영). 저장 엔티티가 아니라 계산이라 '한 User 귀속' 불변식을 문자 그대로 지킨다.교환·수명: 백업 = md/csv/미디어 zip(무손실 자기 직렬화, 정본 경로). 표준 export(schema.org/CIDOC)는 좁은 목적의 손실 편의 투영으로 격하 — 상세는 기록의 수명 — 자기 구조로.
확장 가드레일 — 새 개념이 들어올 때
어떤 개념이 제안되든 이 순서를 통과해야 모델이 단일하게 유지된다. 앞의 표(층·엔티티·관계)는 전부 이 일곱 질문의 산물이다.
- 파생 가능한가? — 저장 전에 계산으로 될지 먼저(시제·롤업·노출의 전례).
- 어느 층인가? — 문장·성분·마스터·돈4역·겹·서사·계정 중 하나.
- 성분인가 참조인가? —
Involvement또는Link. 새 조인은 페이로드 실릴 때만. - 돈이면 4역 중 무엇인가? — 스톡·이동·배정·목표 밖의 돈 개념은 안 만든다.
- 어휘를 미리 못 박나? —
role·relationType처럼 비워 두고 출발할 수 있으면 비운다. - 이력이 남는가? — 도메인 기록은 삭제 대신 보존(
discarded·revokedAt), 확장은 nullable 추가. - 의무 3종 —
User귀속+RLS · 백업(md/csv) 매핑 · 별칭 사전 등재.
@Model 프리즈에 적대다. 그러면 nullable 곁필드·enum 확장·부호 개방으로 예약하거나 명시적 갈아엎기로 유예한다.A2 seam — 프리즈 전 예약(전건 null/미사용)
| seam | 여는 미래 |
|---|---|
| Event.startPrecision | 퍼지 과거(SEM 유연 시간) |
| Event.status=aborted | 무산된 과거 계획(가지 않은 길의 과거 축) |
| Involvement.attributedTo | 다관점 과거 — 강형 accordingTo·Claim의 record-grain 씨앗 |
| Reflection.voice | 제3자·고인의 증언을 그의 목소리로 |
| Link "sameAs" | 교차정체성(개명·재혼) — 훗날 PersonEpithet(validFrom/validTo) |
| Pocket.balance 음수 | 부채 = 음의 지갑 |
| Scenario.coexisting · authorLabel | 관점파생 미래(비붕괴) · 훗날 authorityId |
조직 원리 = 소유 ≠ 귀속(소유=user_id·귀속=Involvement.attributedTo). 범용 Frame/Context 층은 거부 — 메커니즘은 둘(modal=Scenario, epistemic=유예 View). 상세 = 프리즈전 리포트.