Files
life-helper/docs/design/204-flutter-bootstrap/05-seed-data.md
joungmin b8e563176b [Architect] #204 design spec — Flutter bootstrap + 18 tables
Phase 1 설계서 작성 완료. docs/design/204-flutter-bootstrap/ 13 개 파일:
- README.md (12 섹션 모두 채움, 함수 19 개 명세, AC 16 항)
- 01-project-structure.md (feature-first + layer-first 하이브리드)
- 02-drift-schema-catalog.md (Catalog 7 테이블 Dart 정의)
- 03-drift-schema-user.md (User 11 테이블 + R1~R10 강제 매트릭스)
- 04-migrations.md (schemaVersion v1 + 인덱스 17 개)
- 05-seed-data.md (assets/seed/*.json + first-run import)
- 06-ux-contracts.md (체크인 R8 ≤ 60 초 흐름)
- fn-recommend-variant / fn-compute-streak / fn-weekly-minimum-ratio
- fn-validate-frame-level / fn-active-habit-quota / fn-seed-importer

핵심 결정: dose_variants 는 별도 habit_dose_variant 테이블로 정규화 (FK
무결성 + recommendVariant SQL 단순성). ADR-0002 승격 권장.

Refs #204

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-11 16:57:31 +09:00

130 lines
5.0 KiB
Markdown

# 05 — 시드 데이터 전략 (#204)
> 부모 설계서: [README.md](./README.md)
## 1. 전략 결정: build-time 번들 + first-run JSON import
### 검토한 대안
| 옵션 | 장점 | 단점 | 채택 |
|------|------|------|------|
| A. build-time codegen (`*.dart` 생성) | 컴파일 타임 안전, JSON parse 실패 0 | 시드 변경 시 codegen 강제. PR diff 가 dart 자동 생성. | ✗ |
| **B. asset 번들 JSON + 첫 실행 import** | SoT `schema/*.json` 호환 형식 그대로. 사람이 읽기 쉬움. diff 명료. | 첫 실행 시 ~1 초 추가 시간. parse 실패 가능성 (테스트로 커버) | **✓** |
| C. 원격 fetch | 동적 업데이트 | 네트워크 의존 (Phase 1 out of scope) | ✗ |
## 2. 파일 배치
```
app/assets/seed/
├── protocols.json # Array<Protocol> — ~34 항목
├── break_protocols.json # Array<BreakProtocol> — 8 항목
├── common_frames.json # Array<CommonFrame> — 5 항목
├── methodologies.json # Array<Methodology> — 21 항목
├── frame_patterns.json # Array<FramePattern> — ~30 항목
├── reward_menu_items.json # Array<RewardMenuItem> — ~30 항목
└── references.json # Array<Reference> — ~50 항목
```
- 각 파일 형식 = `schema/<entity>.schema.json` 을 만족하는 객체 배열.
- 인코딩 = UTF-8 (한국어 텍스트).
- `pubspec.yaml``flutter.assets:``assets/seed/` 등록.
## 3. 로딩 순서 (참조 무결성)
```
1. references.json ← 다른 시드가 reference_ids 로 참조
2. protocols.json
3. break_protocols.json
4. common_frames.json
5. methodologies.json
6. frame_patterns.json
7. reward_menu_items.json
```
- 각 파일 batch insert 는 단일 트랜잭션.
- 전체 시드 import 도 단일 transaction. 1 파일이라도 실패하면 rollback.
## 4. 첫 실행 감지
`meta_kv` 테이블에 `key='seeded_v1'` 행 존재 여부로 판단.
```dart
Future<bool> _alreadySeeded(AppDatabase db) async {
final row = await db.metaKvDao.find('seeded_v1');
return row?.value == 'true';
}
```
## 5. import 시퀀스 (의사코드 — fn-seed-importer.md 참조)
```dart
Future<void> importIfNeeded() async {
if (await _alreadySeeded(db)) return;
await db.transaction(() async {
for (final entry in _seedOrder) {
final raw = await rootBundle.loadString(entry.assetPath);
final list = jsonDecode(raw) as List;
for (final json in list) {
final adapted = entry.adapter(json as Map<String, dynamic>);
await entry.dao.insertAll(adapted);
}
}
await _ensureLocalDefaultUser();
await db.metaKvDao.put('seeded_v1', 'true');
});
}
```
## 6. 시드 데이터 출처 ↔ 카탈로그 매핑 (검증용)
| 시드 파일 | SoT 마크다운 | 추출 단위 | 추산 행 |
|-----------|-------------|----------|---------|
| protocols.json | huberman-protocols.md §1~§5 + nutrition/diet-protocols.md §1 | `###` 헤더 단위 | ~34 |
| break_protocols.json | habit-breaking-protocols.md §2 | `###` 헤더 단위 (8 카테고리) | 8 |
| common_frames.json | habit-breaking-protocols.md §1 | `###` 5 개 | 5 |
| methodologies.json | habit-todo-methodologies.md §1~§21 | `###` 헤더 단위 | 21 |
| frame_patterns.json | habit-todo-methodologies.md "흔한 끊기 목표 변환 30선" | 표 row 단위 | ~30 |
| reward_menu_items.json | habit-todo-methodologies.md "권장 리워드 메뉴 30선" | 표 row 단위 | ~30 |
| references.json | 4 SoT 의 각 출처 섹션 합계 | 인용 1 건 | ~50 |
## 7. 손 작성 vs 자동 추출
본 Phase 는 **손 작성** (Developer 가 SoT 마크다운을 보고 JSON 작성). 이유:
- 자동 추출 파서가 또 다른 코드 (스크립트) 의 SoT 가 됨 — 본 Phase 범위 초과.
- 손 작성으로 카탈로그 schema 의 비논리적 누락을 발견할 수 있음 (피드백 루프).
Phase 2 에서 `scripts/extract_seed.py` 검토 (OQ-2).
## 8. user 기본 row 생성
```dart
Future<void> _ensureLocalDefaultUser() async {
await db.users.insertOnConflictUpdate(UsersCompanion.insert(
id: 'u_local_default',
createdAt: DateTime.now().toIso8601String(),
locale: const Value('ko-KR'),
timezone: const Value('Asia/Seoul'),
));
}
```
## 9. 테스트 fixture
```
test/fixtures/seed/
├── protocols_small.json # 2 항목 (1 health + 1 diet)
├── break_protocols_small.json # 1 항목
├── common_frames_small.json # 1 항목
├── methodologies_small.json # 3 항목 (core engine 3 개)
├── frame_patterns_small.json # 2 항목
├── reward_menu_items_small.json # 5 항목 (T0~T4 각 1)
└── references_small.json # 2 항목
```
- `SeedImporter` 의 단위 테스트는 fixture 디렉토리로 path override.
## 10. 운영 메모
- 시드 변경 시 (v1 출시 후 카탈로그 한 행 추가): asset JSON 수정 → schemaVersion 그대로 → migration 으로 신규 row insert 별도 처리. 자동 import 는 `seeded_v1` flag 가 true 라 다시 안 돔.
- 카탈로그 갱신은 별도 메커니즘 (v2 또는 `seeded_v2` 플래그 신설) — Phase 2 결정.