- OQ-1: dose_variants 정규화 결정을 ADR-0002 로 승격 (ADR-0001 = 왜, ADR-0002 = 어떻게). - OQ-3: nutrition diet 패턴 5개를 별도 diet_pattern 카탈로그(19번째 SoT)로 분리. · 02-catalog §8 신규, 인덱스 IDX_diet_patterns_evidence / IDX_diet_patterns_kfit. · 05-seed: diet_patterns.json (5행) 추가, 로딩 순서 끝에 배치. · 04-migrations: v1 테이블 합계 = Catalog 8 + User 11 + 부속 1 + meta_kv = 21. - README §2/§3/§6/§11 갱신: 18→19 SoT, AC-2 에 diet_pattern=5 검증 추가. - README §12 OQ → Resolved Open Questions 표 (OQ-1~OQ-8 결정 결과). - habit_dose_variant → habit_dose_variants 표기 통일. - fn-weekly-minimum-ratio, 03-drift-schema-user 의 ADR-0002 cross-link. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 KiB
10 KiB
life-helper 데이터 모델 (v1)
목적: 본 프로젝트의 3개 마크다운 SoT(
huberman-protocols.md,habit-todo-methodologies.md,habit-breaking-protocols.md)와 메모리 원칙(feedback_sustainable_minimal.md,feedback_reward_ladder.md,feedback_positive_framing.md)을 앱에서 쓸 수 있는 데이터 구조로 정형화.선택된 형식: JSON Schema (Draft 2020-12). SQL/TS 변환은 추후. user_id 기반 → 단일 사용자 local-first와 멀티 사용자 클라우드 모두 호환.
machine-readable schema:
./schema/*.json(엔티티별 분리) 본 문서: 엔티티 관계 + 설계 의도 + 운영 규칙 + 사용 예시
§1. 엔티티 분류
Catalog (read-only seed data, 앱에 번들)
| 엔티티 | SoT 원본 | 설명 |
|---|---|---|
protocol |
huberman-protocols.md + nutrition/diet-protocols.md |
원자 프로토콜 (category로 health/meditation/motivation/habit/learning/diet 구분) |
break_protocol |
habit-breaking-protocols.md §2 |
끊기 카테고리 8개 |
common_frame |
habit-breaking-protocols.md §1 |
끊기 공통 프레임 5개 (Dopamine Reset 등) |
methodology |
habit-todo-methodologies.md |
21개 습관/투두 방법론 |
frame_pattern |
동 문서 §"언어 프레이밍" | L0→L1/L2/L3 변환 예시 |
reward_menu_item |
동 문서 §"리워드 시스템" | 추천 보상 메뉴 |
reference |
모든 SoT의 출처 필드 | DOI/URL/책 인용 |
diet_pattern |
nutrition/diet-protocols.md §2 |
식이 패턴 5개 (지중해/저탄수/IF/Plant-Based/한식) — 의견 분열 영역, 사용자 선택 메뉴 |
User Data (사용자가 생성·변경)
| 엔티티 | 설명 | 핵심 제약 |
|---|---|---|
user |
사용자 (단일/멀티 호환) | id 필수 |
phase |
6주 사이클 1개 | user당 동시 active 1개 |
habit |
사용자 습관 (build 또는 break) | active build ≤ 3, active break ≤ 1 |
tracker_entry |
일일 ○/공백 체크 | (habit_id, date) unique |
if_then_rule |
Implementation Intentions | habit당 ≤ 3개 권장 |
lapse_log |
LEARN 5필드 (재발 일지) | break 습관 위주 |
urge_log |
충동 발생/통과 기록 (선택) | break 습관 위주 |
reward_declaration |
사전 선언 보상 (T0~T4) | phase 시작 시점에만 |
reward_claim |
실제 milestone 달성 기록 | declaration 참조 |
reflection |
주/월 회고 텍스트 | 자유 |
§2. 관계 다이어그램
user (1)
├─< phase (n) -- 시점별 6주 사이클
│ └─< reward_declaration (n) -- 이 phase 동안의 T0~T4 사전 선언
│
└─< habit (n)
├── protocol_id or break_protocol_id (catalog 참조, XOR)
├── frame {level, original_text, framed_text} -- L2 또는 L3 강제
├── anchor {when, after_what, where} -- Tiny Habits
├── stack_position -- after-this-then-that 순서 (선택)
├─< if_then_rule (n)
├─< tracker_entry (n, daily)
├─< lapse_log (n) -- break 위주
├─< urge_log (n, 선택) -- break 위주
└─< reward_claim (n) -- milestone 달성 시
catalog 측:
protocol ──< protocol_reference >── reference (M:N)
break_protocol ──< break_reference >── reference
methodology ──< methodology_reference >── reference
§3. 운영 규칙 (DB level constraint로 적용)
본 프로젝트 메모리에서 도출된 가드레일을 schema에 박는다.
| ID | 규칙 | 적용 위치 | 출처 |
|---|---|---|---|
| R1 | user당 동시 active build habit ≤ 3 |
habit.status='active' AND type='build' 집계 |
feedback_sustainable_minimal.md |
| R2 | user당 동시 active break habit ≤ 1 |
habit.status='active' AND type='break' 집계 |
project_habit_breaking_module.md |
| R3 | habit.frame.level ∈ {L2, L3} 강제 (L0 거부) |
enum 제약 | feedback_positive_framing.md |
| R4 | reward_declaration은 phase.started_at 후 7일 안에만 생성 |
timestamp 검증 | feedback_reward_ladder.md (사전성) |
| R5 | tracker_entry.value ∈ {done, blank} 2값만 |
enum (×·이모지 X) | 6 가드레일 #6 |
| R6 | phase.duration_weeks = 6 (default), 6주 전 anchor 변동 X |
변경 시 warning | 6 가드레일 #5 |
| R7 | if_then_rule.then_action 회피 키워드 감지 시 warning |
클라이언트 검증 | 코끼리 회피 UX |
| R8 | habit 일일 운영 ≤ 2분 (tracker UI 30~60초) |
UX 제약 (DB X) | 6 가드레일 #2 |
| R9 | habit.dose_variants[] 개수 제한 없음. 단 체크인 화면은 "장소 1탭 + 컨디션 1탭 → 추천 + override" 흐름으로 R8 유지. is_minimum=true variant는 0개 이상 허용 (강제 X). |
application + UI | docs/adr/0001-dose-variants.md |
| R10 | reflection.scope='weekly'은 minimum_ratio (해당 주 done 중 is_minimum 비율) 표시. 강제 임계값 없음 — hint 용도. |
application 계산 | docs/adr/0001-dose-variants.md |
§4. 핵심 enum 정의
HabitType: ["build", "break"]
HabitStatus: ["active", "paused", "completed", "abandoned"]
FrameLevel: ["L0", "L1", "L2", "L3"] # L0/L1은 입력 차단 (warning + 변환 제안)
TrackerValue: ["done", "blank"] # ○/공백 2값
RewardTier: ["T0", "T1", "T2", "T3", "T4"]
# T0=매일 / T1=3회 스트릭 / T2=7일 / T3=30일 / T4=42일(6주)
LapseFieldHALT: ["hungry", "angry", "lonely", "tired", "none"]
ProtocolCategory: ["health", "meditation", "motivation", "habit", "learning", "diet"]
# huberman-protocols.md §1~§5 + nutrition/diet-protocols.md (별도 모듈)
BreakCategory: ["alcohol", "nicotine", "porn_masturbation",
"social_media", "sugar", "caffeine", "cannabis", "behavioral"]
CommonFrameId: ["dopamine_reset", "urge_surf",
"environment_design", "relapse_recovery", "recovery_stack"]
§5. JSON Schema 파일 목록 (./schema/)
Catalog
protocol.schema.json— Huberman atomic protocolbreak_protocol.schema.json— 끊기 카테고리common_frame.schema.json— 끊기 공통 프레임 5개methodology.schema.json— 21개 방법론frame_pattern.schema.json— L0→L2/L3 변환표reward_menu_item.schema.json— 보상 메뉴reference.schema.json— DOI/URL/책
User
user.schema.jsonphase.schema.jsonhabit.schema.jsonif_then_rule.schema.jsontracker_entry.schema.jsonlapse_log.schema.jsonurge_log.schema.jsonreward_declaration.schema.jsonreward_claim.schema.jsonreflection.schema.json
메타
enums.schema.json— 위 §4 enum 통합 정의 ($ref로 재사용)_index.json— 전체 스키마 인덱스 + 운영 규칙 메타
§6. 사용 예시 (단일 사용자, build 습관 1개)
habit (build, L2 프레임)
{
"id": "hb_01J9...",
"user_id": "u_local_default",
"type": "build",
"status": "active",
"title": "아침 햇빛 10분",
"protocol_id": "huberman_1_1_morning_sunlight",
"break_protocol_id": null,
"frame": {
"level": "L2",
"original_text": "햇빛 안 빼먹기",
"framed_text": "기상 직후 야외에서 햇빛 10분 받기"
},
"anchor": {
"when": "06:30",
"after_what": "기상 직후",
"where": "현관 앞 야외"
},
"if_then_rules": [
{ "if": "비 오는 날이면", "then": "20분으로 늘려서 우산 쓰고 나간다" }
],
"started_at": "2026-06-04",
"phase_id": "ph_2026Q2_1",
"stack_position": 1
}
tracker_entry (일일)
{ "id": "te_...", "habit_id": "hb_01J9...", "date": "2026-06-04", "value": "done", "logged_at": "2026-06-04T06:42:00+09:00" }
reward_declaration (phase 시작 시 사전 선언)
{
"id": "rd_...",
"phase_id": "ph_2026Q2_1",
"habit_id": "hb_01J9...",
"tier": "T3",
"milestone_rule": "30일 중 24일 이상 done",
"reward_text": "주말 1박 단기 여행",
"estimated_cost_krw": 150000,
"declared_at": "2026-06-04T20:00:00+09:00"
}
habit (break, L3 프레임)
{
"id": "hb_brk_01...",
"user_id": "u_local_default",
"type": "break",
"status": "active",
"title": "평일 무알콜",
"protocol_id": null,
"break_protocol_id": "alcohol",
"common_frame_ids": ["dopamine_reset", "environment_design", "recovery_stack"],
"frame": {
"level": "L3",
"original_text": "술 끊기",
"framed_text": "나는 평일 무알콜인 사람이다"
},
"anchor": { "when": "18:00", "after_what": "퇴근", "where": "집 거실" },
"phase_id": "ph_2026Q2_1"
}
lapse_log (LEARN 5)
{
"id": "ll_...",
"habit_id": "hb_brk_01...",
"date": "2026-06-10",
"label_text": "회식에서 맥주 2잔. 데이터로 처리.",
"examine_halt": ["tired", "lonely"],
"antecedent": ["회식 자리", "20시 늦은 식사", "동료 권유"],
"replan": "If 회식 공지 받으면, then 첫잔 무알콜 사전 선언 + 동료에게 알림",
"next_action": "다음 평일은 즉시 정상 진행. Never miss twice."
}
§7. 단일 vs 멀티 사용자 호환 전략
- 모든 user data 엔티티에
user_id필수 필드. - 단일 사용자 local 앱:
user_id = "u_local_default"고정. - 클라우드 멀티 사용자: auth 서비스의 sub/uid를 그대로
user_id로 매핑. - catalog 엔티티에는
user_id없음 (모든 사용자 공유). - ID 형식: ULID 권장 (
hb_01J9...). prefix는 엔티티 타입.
§8. 마이그레이션 노트
- v1은 minimal viable. 다음 항목은 v2 이후 고려:
habit_stack(Atomic Habits #5 — 여러 habit 묶음 운영)dashboard_preference(사용자별 트래커 UI 옵션)notification_rule(알림/cron 트리거)social_link(Recovery Stack의 "1-person check-in" 파트너)integration_*(Apple Health / Google Fit / Notion sync)
- enum 추가는 backward compatible. enum 제거/이름 변경은 마이그레이션 스크립트 필수.
§9. 다음 단계 제안
- 본 문서 +
./schema/*.json리뷰. - seed catalog 데이터 채우기 (Huberman 29개 + break 8개 + methodology 21개) —
./seed/*.json. - 검증기(Ajv 등)로 schema 적합성 확인.
- UI 와이어프레임 (트래커 30초, 대시보드 1화면 등) — 별도 문서.
- 백엔드 결정 (SQLite local-first 권장 → 추후 Supabase 등으로 확장).