timsquad 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.ko.md +288 -0
  2. package/README.md +158 -151
  3. package/dist/commands/compile.d.ts +3 -0
  4. package/dist/commands/compile.d.ts.map +1 -0
  5. package/dist/commands/compile.js +170 -0
  6. package/dist/commands/compile.js.map +1 -0
  7. package/dist/commands/daemon.d.ts.map +1 -1
  8. package/dist/commands/daemon.js +95 -5
  9. package/dist/commands/daemon.js.map +1 -1
  10. package/dist/commands/full.js +1 -0
  11. package/dist/commands/full.js.map +1 -1
  12. package/dist/commands/git/pr.js +6 -5
  13. package/dist/commands/git/pr.js.map +1 -1
  14. package/dist/commands/git/release.js +2 -7
  15. package/dist/commands/git/release.js.map +1 -1
  16. package/dist/commands/improve.js +2 -2
  17. package/dist/commands/improve.js.map +1 -1
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +12 -3
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/log.d.ts.map +1 -1
  22. package/dist/commands/log.js +2 -2
  23. package/dist/commands/log.js.map +1 -1
  24. package/dist/commands/metrics.d.ts.map +1 -1
  25. package/dist/commands/metrics.js +6 -2
  26. package/dist/commands/metrics.js.map +1 -1
  27. package/dist/commands/retro.js +8 -8
  28. package/dist/commands/retro.js.map +1 -1
  29. package/dist/commands/session.js +3 -3
  30. package/dist/commands/session.js.map +1 -1
  31. package/dist/commands/skills.d.ts +12 -0
  32. package/dist/commands/skills.d.ts.map +1 -0
  33. package/dist/commands/skills.js +228 -0
  34. package/dist/commands/skills.js.map +1 -0
  35. package/dist/commands/status.js +1 -1
  36. package/dist/commands/status.js.map +1 -1
  37. package/dist/commands/upgrade.d.ts.map +1 -1
  38. package/dist/commands/upgrade.js +23 -1
  39. package/dist/commands/upgrade.js.map +1 -1
  40. package/dist/daemon/entry.js +3 -3
  41. package/dist/daemon/entry.js.map +1 -1
  42. package/dist/daemon/event-queue.d.ts.map +1 -1
  43. package/dist/daemon/event-queue.js +2 -2
  44. package/dist/daemon/event-queue.js.map +1 -1
  45. package/dist/daemon/index.d.ts +4 -2
  46. package/dist/daemon/index.d.ts.map +1 -1
  47. package/dist/daemon/index.js +214 -52
  48. package/dist/daemon/index.js.map +1 -1
  49. package/dist/daemon/jsonl-watcher.d.ts +1 -0
  50. package/dist/daemon/jsonl-watcher.d.ts.map +1 -1
  51. package/dist/daemon/jsonl-watcher.js.map +1 -1
  52. package/dist/daemon/meta-cache.d.ts +1 -0
  53. package/dist/daemon/meta-cache.d.ts.map +1 -1
  54. package/dist/daemon/meta-cache.js +9 -0
  55. package/dist/daemon/meta-cache.js.map +1 -1
  56. package/dist/daemon/session-notes.d.ts +33 -0
  57. package/dist/daemon/session-notes.d.ts.map +1 -0
  58. package/dist/daemon/session-notes.js +74 -0
  59. package/dist/daemon/session-notes.js.map +1 -0
  60. package/dist/daemon/session-state.d.ts +27 -0
  61. package/dist/daemon/session-state.d.ts.map +1 -0
  62. package/dist/daemon/session-state.js +165 -0
  63. package/dist/daemon/session-state.js.map +1 -0
  64. package/dist/daemon/shutdown.d.ts.map +1 -1
  65. package/dist/daemon/shutdown.js +9 -1
  66. package/dist/daemon/shutdown.js.map +1 -1
  67. package/dist/index.js +4 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/lib/agent-generator.d.ts +4 -0
  70. package/dist/lib/agent-generator.d.ts.map +1 -1
  71. package/dist/lib/agent-generator.js +52 -3
  72. package/dist/lib/agent-generator.js.map +1 -1
  73. package/dist/lib/compile-rules.d.ts +66 -0
  74. package/dist/lib/compile-rules.d.ts.map +1 -0
  75. package/dist/lib/compile-rules.js +114 -0
  76. package/dist/lib/compile-rules.js.map +1 -0
  77. package/dist/lib/compiler.d.ts +105 -0
  78. package/dist/lib/compiler.d.ts.map +1 -0
  79. package/dist/lib/compiler.js +368 -0
  80. package/dist/lib/compiler.js.map +1 -0
  81. package/dist/lib/config.d.ts +1 -0
  82. package/dist/lib/config.d.ts.map +1 -1
  83. package/dist/lib/config.js +8 -1
  84. package/dist/lib/config.js.map +1 -1
  85. package/dist/lib/project.d.ts.map +1 -1
  86. package/dist/lib/project.js +8 -3
  87. package/dist/lib/project.js.map +1 -1
  88. package/dist/lib/skill-generator.d.ts.map +1 -1
  89. package/dist/lib/skill-generator.js +22 -1
  90. package/dist/lib/skill-generator.js.map +1 -1
  91. package/dist/lib/template.d.ts.map +1 -1
  92. package/dist/lib/template.js +6 -0
  93. package/dist/lib/template.js.map +1 -1
  94. package/dist/types/config.d.ts +1 -0
  95. package/dist/types/config.d.ts.map +1 -1
  96. package/dist/types/config.js +12 -1
  97. package/dist/types/config.js.map +1 -1
  98. package/dist/types/project.d.ts +1 -1
  99. package/dist/types/project.d.ts.map +1 -1
  100. package/dist/types/project.js +2 -0
  101. package/dist/types/project.js.map +1 -1
  102. package/package.json +4 -4
  103. package/templates/base/agents/base/tsq-architect.md +2 -2
  104. package/templates/base/agents/overlays/domain/mobile/_common.md +13 -0
  105. package/templates/base/knowledge/checklists/plan-quality.md +31 -0
  106. package/templates/base/knowledge/checklists/stability-verification.md +14 -0
  107. package/templates/base/skills/controller/SKILL.md +111 -0
  108. package/templates/base/skills/controller/references/README.md +35 -0
  109. package/templates/base/skills/controller/rules/README.md +18 -0
  110. package/templates/base/skills/mobile/dart/SKILL.md +69 -0
  111. package/templates/base/skills/mobile/dart/rules/async-patterns.md +112 -0
  112. package/templates/base/skills/mobile/dart/rules/code-style.md +96 -0
  113. package/templates/base/skills/mobile/dart/rules/null-safety.md +84 -0
  114. package/templates/base/skills/mobile/dart/rules/type-system.md +111 -0
  115. package/templates/base/skills/mobile/flutter/SKILL.md +89 -0
  116. package/templates/base/skills/mobile/flutter/ci-cd/SKILL.md +82 -0
  117. package/templates/base/skills/mobile/flutter/ci-cd/references/ci-cd-pipeline.md +314 -0
  118. package/templates/base/skills/mobile/flutter/ci-cd/rules/code-signing.md +106 -0
  119. package/templates/base/skills/mobile/flutter/ci-cd/rules/codemagic-setup.md +116 -0
  120. package/templates/base/skills/mobile/flutter/ci-cd/rules/fastlane-setup.md +105 -0
  121. package/templates/base/skills/mobile/flutter/ci-cd/rules/github-actions.md +112 -0
  122. package/templates/base/skills/mobile/flutter/ci-cd/rules/store-deployment.md +106 -0
  123. package/templates/base/skills/mobile/flutter/ci-cd/rules/versioning.md +107 -0
  124. package/templates/base/skills/mobile/flutter/i18n/SKILL.md +78 -0
  125. package/templates/base/skills/mobile/flutter/i18n/references/i18n-architecture.md +225 -0
  126. package/templates/base/skills/mobile/flutter/i18n/rules/arb-files.md +182 -0
  127. package/templates/base/skills/mobile/flutter/i18n/rules/locale-switching.md +226 -0
  128. package/templates/base/skills/mobile/flutter/i18n/rules/localization-setup.md +137 -0
  129. package/templates/base/skills/mobile/flutter/i18n/rules/plural-gender.md +159 -0
  130. package/templates/base/skills/mobile/flutter/i18n/rules/text-direction.md +199 -0
  131. package/templates/base/skills/mobile/flutter/monitoring/SKILL.md +81 -0
  132. package/templates/base/skills/mobile/flutter/monitoring/references/monitoring-architecture.md +269 -0
  133. package/templates/base/skills/mobile/flutter/monitoring/rules/analytics.md +227 -0
  134. package/templates/base/skills/mobile/flutter/monitoring/rules/crashlytics-setup.md +195 -0
  135. package/templates/base/skills/mobile/flutter/monitoring/rules/logging.md +258 -0
  136. package/templates/base/skills/mobile/flutter/monitoring/rules/performance-monitoring.md +248 -0
  137. package/templates/base/skills/mobile/flutter/monitoring/rules/sentry-integration.md +249 -0
  138. package/templates/base/skills/mobile/flutter/networking/SKILL.md +88 -0
  139. package/templates/base/skills/mobile/flutter/networking/references/api-client-architecture.md +305 -0
  140. package/templates/base/skills/mobile/flutter/networking/rules/caching.md +212 -0
  141. package/templates/base/skills/mobile/flutter/networking/rules/connectivity.md +213 -0
  142. package/templates/base/skills/mobile/flutter/networking/rules/dio-setup.md +159 -0
  143. package/templates/base/skills/mobile/flutter/networking/rules/error-handling.md +209 -0
  144. package/templates/base/skills/mobile/flutter/networking/rules/interceptors.md +205 -0
  145. package/templates/base/skills/mobile/flutter/networking/rules/retrofit-patterns.md +194 -0
  146. package/templates/base/skills/mobile/flutter/push-notifications/SKILL.md +87 -0
  147. package/templates/base/skills/mobile/flutter/push-notifications/references/notification-architecture.md +340 -0
  148. package/templates/base/skills/mobile/flutter/push-notifications/references/platform-setup.md +286 -0
  149. package/templates/base/skills/mobile/flutter/push-notifications/rules/background-processing.md +308 -0
  150. package/templates/base/skills/mobile/flutter/push-notifications/rules/deep-linking.md +217 -0
  151. package/templates/base/skills/mobile/flutter/push-notifications/rules/fcm-setup.md +164 -0
  152. package/templates/base/skills/mobile/flutter/push-notifications/rules/local-notifications.md +262 -0
  153. package/templates/base/skills/mobile/flutter/push-notifications/rules/notification-handling.md +210 -0
  154. package/templates/base/skills/mobile/flutter/push-notifications/rules/notification-permissions.md +246 -0
  155. package/templates/base/skills/mobile/flutter/push-notifications/rules/rich-notifications.md +320 -0
  156. package/templates/base/skills/mobile/flutter/references/freezed-patterns.md +162 -0
  157. package/templates/base/skills/mobile/flutter/references/project-structure.md +170 -0
  158. package/templates/base/skills/mobile/flutter/rules/animations.md +112 -0
  159. package/templates/base/skills/mobile/flutter/rules/architecture.md +121 -0
  160. package/templates/base/skills/mobile/flutter/rules/navigation-routing.md +117 -0
  161. package/templates/base/skills/mobile/flutter/rules/performance.md +112 -0
  162. package/templates/base/skills/mobile/flutter/rules/platform-adaptive.md +126 -0
  163. package/templates/base/skills/mobile/flutter/rules/state-management.md +110 -0
  164. package/templates/base/skills/mobile/flutter/rules/testing.md +131 -0
  165. package/templates/base/skills/mobile/flutter/rules/widget-conventions.md +122 -0
  166. package/templates/base/skills/mobile/flutter/security/SKILL.md +86 -0
  167. package/templates/base/skills/mobile/flutter/security/references/mobile-security-checklist.md +168 -0
  168. package/templates/base/skills/mobile/flutter/security/rules/api-key-protection.md +206 -0
  169. package/templates/base/skills/mobile/flutter/security/rules/authentication.md +248 -0
  170. package/templates/base/skills/mobile/flutter/security/rules/data-protection.md +271 -0
  171. package/templates/base/skills/mobile/flutter/security/rules/obfuscation.md +213 -0
  172. package/templates/base/skills/mobile/flutter/security/rules/secure-storage.md +171 -0
  173. package/templates/base/skills/mobile/flutter/security/rules/ssl-pinning.md +197 -0
  174. package/templates/base/skills/stability-verification/SKILL.md +64 -0
  175. package/templates/base/skills/stability-verification/references/release-checklist.md +34 -0
  176. package/templates/base/skills/stability-verification/references/security-fix-patterns.md +112 -0
  177. package/templates/base/skills/stability-verification/rules/verification-layers.md +67 -0
  178. package/templates/base/skills/stability-verification/rules/verification-workflow.md +69 -0
  179. package/templates/base/skills/stability-verification/scripts/verify.sh +294 -0
  180. package/templates/platforms/claude-code/CLAUDE.md.template +25 -0
  181. package/templates/platforms/claude-code/rules/build-gate.md +28 -0
  182. package/templates/platforms/claude-code/rules/completion-verification.md +30 -0
  183. package/templates/platforms/claude-code/rules/context-monitor.md +23 -0
  184. package/templates/platforms/claude-code/rules/plan-review.md +45 -0
  185. package/templates/platforms/claude-code/rules/quality-guards.md +43 -0
  186. package/templates/platforms/claude-code/rules/session-notes.md +18 -0
  187. package/templates/platforms/claude-code/rules/skill-suggest.md +27 -0
  188. package/templates/platforms/claude-code/scripts/build-gate.sh +73 -0
  189. package/templates/platforms/claude-code/scripts/completion-guard.sh +93 -0
  190. package/templates/platforms/claude-code/scripts/phase-guard.sh +79 -0
  191. package/templates/platforms/claude-code/scripts/safe-guard.sh +83 -0
  192. package/templates/platforms/claude-code/scripts/skill-rules.json +85 -0
  193. package/templates/platforms/claude-code/scripts/skill-suggest.sh +105 -0
  194. package/templates/platforms/claude-code/settings.json +111 -3
  195. package/templates/project-types/mobile-app/config.yaml +123 -0
  196. package/templates/project-types/mobile-app/process/workflow.xml +191 -0
@@ -0,0 +1,199 @@
1
+ ---
2
+ title: Text Direction & RTL Layout Support
3
+ impact: HIGH
4
+ impactDescription: "RTL 미대응 → 아랍어/히브리어 사용자 UX 파괴, 레이아웃 반전 오류"
5
+ tags: rtl, ltr, directionality, edge-insets-directional, alignment-directional
6
+ ---
7
+
8
+ ## Text Direction & RTL Layout Support
9
+
10
+ **Impact: HIGH (RTL 미대응 → 아랍어/히브리어 사용자 UX 파괴, 레이아웃 반전 오류)**
11
+
12
+ RTL (Right-to-Left) 레이아웃 지원. Directionality 위젯, EdgeInsetsDirectional,
13
+ AlignmentDirectional, 아이콘 미러링. RTL 로캘 지원 시 필수.
14
+
15
+ ### Directional 위젯 사용
16
+
17
+ **Incorrect (하드코딩된 left/right):**
18
+ ```dart
19
+ Container(
20
+ padding: const EdgeInsets.only(left: 16, right: 8),
21
+ alignment: Alignment.centerLeft,
22
+ child: Row(
23
+ children: [
24
+ const Icon(Icons.arrow_back), // RTL에서도 왼쪽 화살표
25
+ const SizedBox(width: 8),
26
+ Text(title),
27
+ ],
28
+ ),
29
+ );
30
+ ```
31
+
32
+ **Correct (Directional 위젯으로 RTL 자동 대응):**
33
+ ```dart
34
+ Container(
35
+ padding: const EdgeInsetsDirectional.only(start: 16, end: 8),
36
+ alignment: AlignmentDirectional.centerStart,
37
+ child: Row(
38
+ children: [
39
+ Icon(
40
+ // RTL에서는 자동으로 arrow_forward (오른쪽→왼쪽 방향)
41
+ Directionality.of(context) == TextDirection.rtl
42
+ ? Icons.arrow_forward
43
+ : Icons.arrow_back,
44
+ ),
45
+ const SizedBox(width: 8),
46
+ Text(title),
47
+ ],
48
+ ),
49
+ );
50
+ ```
51
+
52
+ ### EdgeInsets → EdgeInsetsDirectional 변환
53
+
54
+ ```dart
55
+ // ❌ 물리적 방향 (RTL에서 반전 안 됨)
56
+ EdgeInsets.only(left: 16)
57
+ EdgeInsets.fromLTRB(16, 8, 0, 8)
58
+ EdgeInsets.symmetric(horizontal: 16) // ✅ 대칭은 OK
59
+
60
+ // ✅ 논리적 방향 (RTL에서 자동 반전)
61
+ EdgeInsetsDirectional.only(start: 16)
62
+ EdgeInsetsDirectional.fromSTEB(16, 8, 0, 8) // Start, Top, End, Bottom
63
+ EdgeInsetsDirectional.only(start: 16, end: 8)
64
+
65
+ // Padding 위젯도 동일
66
+ Padding(
67
+ padding: const EdgeInsetsDirectional.only(start: 16),
68
+ child: child,
69
+ );
70
+ ```
71
+
72
+ ### Alignment → AlignmentDirectional 변환
73
+
74
+ ```dart
75
+ // ❌ 물리적 정렬
76
+ Alignment.centerLeft
77
+ Alignment.topRight
78
+
79
+ // ✅ 논리적 정렬
80
+ AlignmentDirectional.centerStart // LTR: left, RTL: right
81
+ AlignmentDirectional.topEnd // LTR: right, RTL: left
82
+
83
+ // Container, Align, Positioned 등에 적용
84
+ Container(
85
+ alignment: AlignmentDirectional.centerStart,
86
+ child: child,
87
+ );
88
+
89
+ Align(
90
+ alignment: AlignmentDirectional.topEnd,
91
+ child: badge,
92
+ );
93
+ ```
94
+
95
+ ### Positioned → PositionedDirectional
96
+
97
+ ```dart
98
+ // ❌ 물리적 위치 (RTL 미대응)
99
+ Positioned(
100
+ left: 16,
101
+ top: 8,
102
+ child: badge,
103
+ );
104
+
105
+ // ✅ 논리적 위치 (RTL 자동 반전)
106
+ PositionedDirectional(
107
+ start: 16,
108
+ top: 8,
109
+ child: badge,
110
+ );
111
+ ```
112
+
113
+ ### 아이콘 미러링
114
+
115
+ ```dart
116
+ /// 방향성을 가진 아이콘 (화살표, 체브론 등)은 RTL에서 미러링
117
+ class DirectionalIcon extends StatelessWidget {
118
+ final IconData icon;
119
+ final double? size;
120
+ final Color? color;
121
+
122
+ const DirectionalIcon(this.icon, {super.key, this.size, this.color});
123
+
124
+ @override
125
+ Widget build(BuildContext context) {
126
+ final isRtl = Directionality.of(context) == TextDirection.rtl;
127
+
128
+ // 방향성 아이콘만 미러링 (체크마크, 플러스 등은 미러링 X)
129
+ if (isRtl) {
130
+ return Transform.flip(
131
+ flipX: true,
132
+ child: Icon(icon, size: size, color: color),
133
+ );
134
+ }
135
+
136
+ return Icon(icon, size: size, color: color);
137
+ }
138
+ }
139
+
140
+ // 사용 예
141
+ DirectionalIcon(Icons.arrow_forward_ios, size: 16), // RTL에서 자동 반전
142
+ Icon(Icons.check, size: 16), // 방향 무관 → 미러링 불필요
143
+ ```
144
+
145
+ ### RTL 테스트
146
+
147
+ ```dart
148
+ // 테스트에서 RTL 환경 시뮬레이션
149
+ testWidgets('renders correctly in RTL', (tester) async {
150
+ await tester.pumpWidget(
151
+ Directionality(
152
+ textDirection: TextDirection.rtl,
153
+ child: MediaQuery(
154
+ data: const MediaQueryData(),
155
+ child: Material(
156
+ child: MyWidget(),
157
+ ),
158
+ ),
159
+ ),
160
+ );
161
+
162
+ // start padding이 RTL에서 오른쪽에 적용되는지 확인
163
+ final container = tester.widget<Container>(find.byType(Container));
164
+ // ...assertions
165
+ });
166
+
167
+ // 전체 앱을 RTL로 실행 (디버그 확인용)
168
+ MaterialApp(
169
+ locale: const Locale('ar'), // 아랍어 → RTL 자동 적용
170
+ // ...
171
+ );
172
+ ```
173
+
174
+ ### Row/Column 방향
175
+
176
+ ```dart
177
+ // Row는 TextDirection을 자동 반영
178
+ // LTR: [icon] [text] [chevron →]
179
+ // RTL: [← chevron] [text] [icon]
180
+ Row(
181
+ children: [
182
+ const Icon(Icons.person),
183
+ Expanded(child: Text(context.l10n.profileLabel)),
184
+ const DirectionalIcon(Icons.chevron_right),
185
+ ],
186
+ );
187
+ // → Row 내부 순서 변경 불필요, Flutter가 자동 반전
188
+ ```
189
+
190
+ ### 규칙
191
+
192
+ - `EdgeInsets` → `EdgeInsetsDirectional` 로 교체 (left/right → start/end)
193
+ - `Alignment` → `AlignmentDirectional` 로 교체 (centerLeft → centerStart)
194
+ - `Positioned` → `PositionedDirectional` 로 교체 (left → start)
195
+ - 대칭 padding/margin (`symmetric`) → 그대로 사용 가능 (반전 불필요)
196
+ - 방향성 아이콘 (화살표, 체브론) → RTL에서 `Transform.flip` 미러링
197
+ - 방향 무관 아이콘 (체크, 플러스, 검색) → 미러링 금지
198
+ - RTL 테스트 → `Directionality(textDirection: TextDirection.rtl)` 로 래핑
199
+ - `Row`/`ListView` → TextDirection 자동 반영, 순서 변경 불필요
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: monitoring
3
+ description: |
4
+ Flutter 모니터링 & 분석 가이드라인.
5
+ Firebase Crashlytics, Analytics, Performance Monitoring,
6
+ Sentry 통합, 구조화된 로깅.
7
+ version: "1.0.0"
8
+ tags: [flutter, crashlytics, analytics, performance, sentry, monitoring, logging]
9
+ user-invocable: false
10
+ ---
11
+
12
+ # Monitoring & Analytics
13
+
14
+ Flutter 앱 모니터링 통합 가이드.
15
+ Firebase Crashlytics + Analytics + Performance, Sentry, 구조화된 로깅으로
16
+ 프로덕션 품질을 수치로 관리.
17
+
18
+ ## Philosophy
19
+
20
+ - 크래시는 0순위 — Crashlytics 비활성화 금지, 모든 비치명 에러도 기록
21
+ - 이벤트는 설계 — 무분별한 로깅 금지, 이벤트 택소노미 먼저 정의
22
+ - 성능은 측정 — 체감이 아닌 custom trace와 HTTP metric으로 수치화
23
+
24
+ ## Resources
25
+
26
+ 5개 규칙 + 1개 참조. 크래시부터 로깅까지 모니터링 파이프라인 전체를 커버.
27
+
28
+ | Priority | Type | Resource | Description |
29
+ |----------|------|----------|-------------|
30
+ | CRITICAL | rule | [crashlytics-setup](rules/crashlytics-setup.md) | Crashlytics 초기화, 에러 캡처, 사용자 식별 |
31
+ | HIGH | rule | [analytics](rules/analytics.md) | Analytics 이벤트 택소노미, 사용자 속성, 화면 추적 |
32
+ | HIGH | rule | [performance-monitoring](rules/performance-monitoring.md) | Performance custom trace, HTTP metric, 프레임 모니터링 |
33
+ | MEDIUM | rule | [sentry-integration](rules/sentry-integration.md) | Sentry 초기화, breadcrumbs, scope, Crashlytics 공존 |
34
+ | MEDIUM | rule | [logging](rules/logging.md) | 구조화된 로깅, 레벨 관리, 민감 데이터 마스킹 |
35
+ | — | ref | [monitoring-architecture](references/monitoring-architecture.md) | 모니터링 레이어, 대시보드, 알림, 데이터 보존 |
36
+
37
+ ## Quick Rules
38
+
39
+ ### Crashlytics
40
+ - `FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError`
41
+ - `PlatformDispatcher.instance.onError` → 비동기 에러 캡처
42
+ - 비치명 에러 → `recordError(error, stack, fatal: false)`
43
+ - `setUserIdentifier` → 크래시와 사용자 매핑
44
+ - `setCustomKey` → 디바이스 상태, 기능 플래그 등 컨텍스트
45
+
46
+ ### Analytics
47
+ - 이벤트 택소노미 먼저 정의 (screen_view, button_click, feature_use)
48
+ - `setUserProperty` → user_type, subscription_tier 등 세그먼트 기준
49
+ - `AnalyticsObserver` → go_router 화면 전환 자동 추적
50
+ - 디버그 → `adb shell setprop debug.firebase.analytics.app <package>`
51
+
52
+ ### Performance
53
+ - `FirebasePerformance.instance.newTrace('name')` → custom trace
54
+ - HTTP metric → 자동 수집 (dio interceptor 또는 http_client)
55
+ - 느린 프레임 임계값 16ms (60fps), 8ms (120fps)
56
+
57
+ ### Sentry
58
+ - `SentryFlutter.init` → DSN 환경별 분리 (dev/staging/prod)
59
+ - `Sentry.addBreadcrumb` → 네비게이션, HTTP, 사용자 액션 추적
60
+ - Crashlytics + Sentry 공존 → 각자 역할 분리 (crash vs context)
61
+
62
+ ### Logging
63
+ - `logger` 패키지 → 레벨별 색상 출력 (개발), JSON 구조화 (프로덕션)
64
+ - 릴리스 빌드 → verbose/debug 레벨 비활성화
65
+ - 민감 데이터 (토큰, PII) → 마스킹 필수
66
+
67
+ ## Checklist
68
+
69
+ | Priority | Item |
70
+ |----------|------|
71
+ | CRITICAL | `FlutterError.onError` + `PlatformDispatcher.onError` 연동 |
72
+ | CRITICAL | Crashlytics 디버그 모드 비활성화 (`setCrashlyticsCollectionEnabled`) |
73
+ | CRITICAL | 릴리스 빌드에서 dSYM / ProGuard mapping 업로드 설정 |
74
+ | HIGH | Analytics 이벤트 택소노미 문서화 후 구현 |
75
+ | HIGH | `AnalyticsObserver` go_router 연동 |
76
+ | HIGH | Performance custom trace 핵심 플로우에 적용 |
77
+ | HIGH | HTTP metric 수집 (dio interceptor) |
78
+ | MEDIUM | Sentry DSN 환경별 분리 |
79
+ | MEDIUM | Sentry breadcrumb 네비게이션/HTTP 자동 기록 |
80
+ | MEDIUM | 구조화된 로깅 + 릴리스 레벨 필터 |
81
+ | MEDIUM | 민감 데이터 마스킹 검증 |
@@ -0,0 +1,269 @@
1
+ ---
2
+ title: Monitoring Architecture & Dashboard Configuration
3
+ category: reference
4
+ source: internal
5
+ tags: architecture, dashboard, alerting, data-retention, crashlytics, sentry, analytics
6
+ ---
7
+
8
+ # Monitoring Architecture & Dashboard Configuration
9
+
10
+ 모니터링 레이어 구조, 대시보드 구성, 알림 설정, 데이터 보존 정책.
11
+ 프로덕션 운영 시 참조.
12
+
13
+ ## Key Concepts
14
+
15
+ - **레이어 모델**: crash → error → performance → analytics → logging (우선순위 순)
16
+ - **대시보드 분리**: Firebase Console (크래시/성능) + Sentry (에러 컨텍스트)
17
+ - **알림 전략**: 크래시 스파이크, ANR, 성능 저하에 대한 자동 알림
18
+ - **데이터 보존**: 도구별 보존 기간 + 비용 최적화
19
+
20
+ ## Monitoring Layer Model
21
+
22
+ ```
23
+ ┌─────────────────────────────────────────────────────────┐
24
+ │ Monitoring Layers │
25
+ ├─────────┬───────────────┬───────────────┬───────────────┤
26
+ │ Layer │ Tool │ Priority │ Purpose │
27
+ ├─────────┼───────────────┼───────────────┼───────────────┤
28
+ │ L1 │ Crashlytics │ CRITICAL │ 앱 크래시 │
29
+ │ Crash │ │ │ ANR/프리징 │
30
+ │ │ │ │ 안정성 % │
31
+ ├─────────┼───────────────┼───────────────┼───────────────┤
32
+ │ L2 │ Sentry │ HIGH │ 비치명 에러 │
33
+ │ Error │ + Crashlytics │ │ 에러 컨텍스트 │
34
+ │ │ │ │ breadcrumbs │
35
+ ├─────────┼───────────────┼───────────────┼───────────────┤
36
+ │ L3 │ Firebase │ HIGH │ 앱 시작 시간 │
37
+ │ Perf │ Performance │ │ HTTP 응답 │
38
+ │ │ │ │ 프레임 렌더링 │
39
+ ├─────────┼───────────────┼───────────────┼───────────────┤
40
+ │ L4 │ Firebase │ MEDIUM │ 사용자 행동 │
41
+ │ Analyt │ Analytics │ │ 전환 퍼널 │
42
+ │ │ │ │ 리텐션 │
43
+ ├─────────┼───────────────┼───────────────┼───────────────┤
44
+ │ L5 │ logger + │ LOW │ 디버깅 추적 │
45
+ │ Logging │ Sentry/Crash │ │ 원격 컨텍스트 │
46
+ │ │ │ │ 감사 로그 │
47
+ └─────────┴───────────────┴───────────────┴───────────────┘
48
+ ```
49
+
50
+ ## Directory Structure
51
+
52
+ ```
53
+ lib/
54
+ ├── core/
55
+ │ └── monitoring/
56
+ │ ├── monitoring_service.dart # 통합 초기화 + Facade
57
+ │ ├── crashlytics/
58
+ │ │ ├── crashlytics_service.dart # Crashlytics 래퍼
59
+ │ │ └── crashlytics_error_handler.dart # 에러 핸들러 체인
60
+ │ ├── analytics/
61
+ │ │ ├── analytics_service.dart # Analytics 래퍼
62
+ │ │ ├── analytics_events.dart # 이벤트 상수
63
+ │ │ └── analytics_observer.dart # GoRouter observer
64
+ │ ├── performance/
65
+ │ │ ├── performance_service.dart # Custom trace 래퍼
66
+ │ │ └── performance_interceptor.dart # Dio HTTP metric
67
+ │ ├── sentry/
68
+ │ │ ├── sentry_service.dart # Sentry 래퍼
69
+ │ │ ├── sentry_breadcrumb_service.dart # Breadcrumb 관리
70
+ │ │ └── sentry_navigator_observer.dart # 네비게이션 추적
71
+ │ ├── logging/
72
+ │ │ ├── app_logger.dart # Logger 래퍼
73
+ │ │ ├── log_sanitizer.dart # 민감 데이터 마스킹
74
+ │ │ └── remote_log_output.dart # 원격 로그 출력
75
+ │ └── providers/
76
+ │ └── monitoring_providers.dart # Riverpod providers
77
+ ```
78
+
79
+ ## Initialization Order
80
+
81
+ ```
82
+ main.dart 초기화 순서:
83
+
84
+ ├─ 1. WidgetsFlutterBinding.ensureInitialized()
85
+ ├─ 2. Firebase.initializeApp()
86
+ ├─ 3. FlutterError.onError = Crashlytics.recordFlutterFatalError
87
+ ├─ 4. PlatformDispatcher.instance.onError → Crashlytics.recordError
88
+ ├─ 5. SentryFlutter.init(appRunner: ...)
89
+ │ └─ 내부에서 runApp() 호출
90
+ │ │
91
+ │ └─ App 초기화 시:
92
+ │ ├─ MonitoringService.initialize()
93
+ │ │ ├─ CrashlyticsService.setUser()
94
+ │ │ ├─ AnalyticsService.setUserProperties()
95
+ │ │ ├─ PerformanceService.enable()
96
+ │ │ └─ AppLogger.initialize()
97
+ │ └─ GoRouter observers: [AnalyticsObserver, SentryObserver]
98
+ ```
99
+
100
+ ## Dashboard Configuration
101
+
102
+ ### Firebase Console
103
+
104
+ ```
105
+ Firebase Console > Crashlytics:
106
+ ├─ Overview: 크래시 없는 사용자 % (목표: 99.5% 이상)
107
+ ├─ Issues: 크래시 목록 (발생 빈도, 영향 사용자 수)
108
+ ├─ Trends: 버전별 안정성 추이
109
+ └─ Velocity alerts: 크래시 급증 알림
110
+
111
+ Firebase Console > Performance:
112
+ ├─ Dashboard: 앱 시작 시간, 화면 렌더링
113
+ ├─ Network: HTTP 요청 성능 (응답 시간, 성공률)
114
+ ├─ Custom traces: 비즈니스 로직 성능
115
+ └─ Threshold alerts: 성능 임계값 알림
116
+
117
+ Firebase Console > Analytics:
118
+ ├─ Dashboard: 활성 사용자, 세션
119
+ ├─ Events: 이벤트 발생 빈도
120
+ ├─ Funnels: 전환 퍼널 (가입 → 매치 생성 → 완료)
121
+ ├─ Retention: 일별/주별 리텐션
122
+ └─ Audiences: 사용자 세그먼트
123
+ ```
124
+
125
+ ### Sentry Dashboard
126
+
127
+ ```
128
+ Sentry > Issues:
129
+ ├─ 에러 목록 (발생 빈도, 영향 사용자, 첫 발생/마지막 발생)
130
+ ├─ 에러 상세 (breadcrumbs, 태그, 디바이스 정보)
131
+ └─ 에러 그룹화 (fingerprint 기반)
132
+
133
+ Sentry > Performance:
134
+ ├─ 트랜잭션 목록 (p50, p75, p95)
135
+ ├─ 느린 트랜잭션 식별
136
+ └─ Web Vitals (웹뷰 사용 시)
137
+
138
+ Sentry > Alerts:
139
+ ├─ Issue alerts: 새 에러 발생 시
140
+ ├─ Metric alerts: 에러율 임계값 초과 시
141
+ └─ Integrations: Slack, PagerDuty, Email
142
+ ```
143
+
144
+ ## Alerting Strategy
145
+
146
+ ```
147
+ ┌──────────────────┬────────────┬──────────────────────────────┐
148
+ │ Alert Type │ Severity │ Action │
149
+ ├──────────────────┼────────────┼──────────────────────────────┤
150
+ │ Crash spike │ P0 │ Slack #alerts + PagerDuty │
151
+ │ (>1% 사용자 영향) │ │ 즉시 대응 (핫픽스 검토) │
152
+ ├──────────────────┼────────────┼──────────────────────────────┤
153
+ │ ANR rate >0.5% │ P1 │ Slack #alerts │
154
+ │ │ │ 24시간 내 조사 │
155
+ ├──────────────────┼────────────┼──────────────────────────────┤
156
+ │ New fatal crash │ P1 │ Slack #alerts │
157
+ │ │ │ 다음 스프린트 수정 │
158
+ ├──────────────────┼────────────┼──────────────────────────────┤
159
+ │ Performance │ P2 │ Slack #monitoring │
160
+ │ degradation │ │ 앱 시작 >3s, API p95 >2s │
161
+ ├──────────────────┼────────────┼──────────────────────────────┤
162
+ │ Error rate │ P2 │ Sentry alert │
163
+ │ spike (비치명) │ │ 다음 스프린트 우선순위 검토 │
164
+ ├──────────────────┼────────────┼──────────────────────────────┤
165
+ │ Drop in daily │ P3 │ Weekly review │
166
+ │ active users │ │ Analytics 퍼널 분석 │
167
+ └──────────────────┴────────────┴──────────────────────────────┘
168
+ ```
169
+
170
+ ## Data Retention Policy
171
+
172
+ ```
173
+ ┌────────────────┬──────────────┬────────────┬─────────────────┐
174
+ │ Tool │ Free Tier │ Paid Tier │ Recommendation │
175
+ ├────────────────┼──────────────┼────────────┼─────────────────┤
176
+ │ Crashlytics │ 90일 │ 90일 │ 그대로 사용 │
177
+ │ Analytics │ 14개월 │ 14개월 │ BigQuery 연동 │
178
+ │ Performance │ 자동 관리 │ 자동 관리 │ 그대로 사용 │
179
+ │ Sentry (Free) │ 30일 │ 90일 │ 주요 이슈 북마크 │
180
+ │ App logs │ 세션 내 │ — │ 원격 로깅 연동 │
181
+ └────────────────┴──────────────┴────────────┴─────────────────┘
182
+
183
+ BigQuery 연동 (Analytics 장기 보존):
184
+ Firebase Console > Project Settings > Integrations > BigQuery
185
+ - 일별 raw event export
186
+ - SQL 쿼리로 커스텀 분석
187
+ - Data Studio / Looker 대시보드 연동
188
+ ```
189
+
190
+ ## Monitoring Service (Facade)
191
+
192
+ ```dart
193
+ /// 모니터링 통합 초기화 Facade
194
+ class MonitoringService {
195
+ final CrashlyticsService _crashlytics;
196
+ final AnalyticsService _analytics;
197
+ final PerformanceService _performance;
198
+ final SentryScopeManager _sentry;
199
+ final AppLogger _logger;
200
+
201
+ MonitoringService({
202
+ required CrashlyticsService crashlytics,
203
+ required AnalyticsService analytics,
204
+ required PerformanceService performance,
205
+ required SentryScopeManager sentry,
206
+ required AppLogger logger,
207
+ }) : _crashlytics = crashlytics,
208
+ _analytics = analytics,
209
+ _performance = performance,
210
+ _sentry = sentry,
211
+ _logger = logger;
212
+
213
+ /// 사용자 로그인 시 모든 서비스에 사용자 설정
214
+ Future<void> identifyUser({
215
+ required String userId,
216
+ String? email,
217
+ Map<String, String>? properties,
218
+ }) async {
219
+ await _crashlytics.setUser(userId);
220
+ await _analytics.setUserId(userId);
221
+ await _sentry.setUser(id: userId, email: email);
222
+ _logger.info('User identified: $userId');
223
+
224
+ if (properties != null) {
225
+ await _crashlytics.setContext(
226
+ appVersion: properties['app_version'] ?? '',
227
+ buildNumber: properties['build_number'] ?? '',
228
+ subscriptionTier: properties['tier'],
229
+ );
230
+ for (final entry in properties.entries) {
231
+ await _analytics.setUserProperty(
232
+ name: entry.key,
233
+ value: entry.value,
234
+ );
235
+ }
236
+ }
237
+ }
238
+
239
+ /// 로그아웃 시 모든 서비스 정리
240
+ Future<void> clearUser() async {
241
+ await _crashlytics.clearUser();
242
+ await _analytics.setUserId(null);
243
+ await _sentry.clearUser();
244
+ _logger.info('User cleared from monitoring');
245
+ }
246
+ }
247
+
248
+ /// Riverpod Provider
249
+ final monitoringServiceProvider = Provider<MonitoringService>((ref) {
250
+ return MonitoringService(
251
+ crashlytics: ref.watch(crashlyticsServiceProvider),
252
+ analytics: ref.watch(analyticsServiceProvider),
253
+ performance: ref.watch(performanceServiceProvider),
254
+ sentry: ref.watch(sentryScopeManagerProvider),
255
+ logger: AppLogger.instance,
256
+ );
257
+ });
258
+ ```
259
+
260
+ ## Common Pitfalls
261
+
262
+ 1. **초기화 순서**: Firebase → Crashlytics 핸들러 → Sentry → 나머지 (순서 중요)
263
+ 2. **디버그 데이터 오염**: 개발 중 크래시/이벤트가 프로덕션 대시보드에 혼합 → 환경 분리
264
+ 3. **이벤트 쿼터**: Sentry 무료 5K/월, Analytics 500이벤트/사용자/일 → 필터링 필수
265
+ 4. **PII 유출**: 로그/이벤트에 이메일/전화번호 포함 → 마스킹 + sendDefaultPii:false
266
+ 5. **소스맵 미업로드**: 난독화된 스택트레이스 → dSYM/ProGuard mapping 업로드 자동화
267
+ 6. **과도한 breadcrumb**: Sentry 기본 100개 제한 → 중요한 것만 기록
268
+ 7. **성능 오버헤드**: 모니터링 SDK 자체가 성능에 영향 → 샘플링률 조절
269
+ 8. **알림 피로**: 모든 에러에 알림 → 임계값 기반 알림으로 전환