@kood/claude-code 0.6.6 → 0.7.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 (170) hide show
  1. package/dist/index.js +7 -1
  2. package/package.json +1 -1
  3. package/templates/.claude/agents/analyst.md +5 -0
  4. package/templates/.claude/agents/architect.md +5 -0
  5. package/templates/.claude/agents/build-fixer.md +1 -0
  6. package/templates/.claude/agents/code-reviewer.md +1 -0
  7. package/templates/.claude/agents/critic.md +4 -0
  8. package/templates/.claude/agents/deep-executor.md +1 -0
  9. package/templates/.claude/agents/dependency-manager.md +2 -0
  10. package/templates/.claude/agents/deployment-validator.md +2 -0
  11. package/templates/.claude/agents/designer.md +2 -0
  12. package/templates/.claude/agents/document-writer.md +3 -0
  13. package/templates/.claude/agents/explore.md +1 -0
  14. package/templates/.claude/agents/git-operator.md +2 -0
  15. package/templates/.claude/agents/implementation-executor.md +2 -0
  16. package/templates/.claude/agents/ko-to-en-translator.md +3 -0
  17. package/templates/.claude/agents/lint-fixer.md +2 -0
  18. package/templates/.claude/agents/planner.md +3 -0
  19. package/templates/.claude/agents/pm.md +349 -0
  20. package/templates/.claude/agents/qa-tester.md +1 -0
  21. package/templates/.claude/agents/refactor-advisor.md +4 -0
  22. package/templates/.claude/agents/researcher.md +9 -1
  23. package/templates/.claude/agents/scientist.md +1 -0
  24. package/templates/.claude/agents/security-reviewer.md +1 -0
  25. package/templates/.claude/agents/tdd-guide.md +1 -0
  26. package/templates/.claude/agents/vision.md +1 -0
  27. package/templates/.claude/instructions/agent-patterns/agent-teams-usage.md +376 -0
  28. package/templates/.claude/instructions/sourcing/reliable-search.md +49 -2
  29. package/templates/.claude/scripts/agent-teams/check-availability.sh +238 -0
  30. package/templates/.claude/scripts/agent-teams/setup-tmux.sh +125 -0
  31. package/templates/.claude/skills/agent-teams-setup/SKILL.md +460 -0
  32. package/templates/.claude/skills/brainstorm/SKILL.md +1 -0
  33. package/templates/.claude/skills/bug-fix/SKILL.md +1 -0
  34. package/templates/.claude/skills/crawler/SKILL.md +2 -0
  35. package/templates/.claude/skills/docs-creator/SKILL.md +1 -0
  36. package/templates/.claude/skills/docs-fetch/SKILL.md +6 -4
  37. package/templates/.claude/skills/docs-refactor/SKILL.md +1 -0
  38. package/templates/.claude/skills/elon-musk/SKILL.md +1 -0
  39. package/templates/.claude/skills/execute/SKILL.md +1 -0
  40. package/templates/.claude/skills/feedback/SKILL.md +1 -0
  41. package/templates/.claude/skills/figma-to-code/SKILL.md +1 -0
  42. package/templates/.claude/skills/genius-thinking/SKILL.md +1 -0
  43. package/templates/.claude/skills/global-uiux-design/SKILL.md +1 -0
  44. package/templates/.claude/skills/korea-uiux-design/SKILL.md +1 -0
  45. package/templates/.claude/skills/nextjs-react-best-practices/SKILL.md +1 -0
  46. package/templates/.claude/skills/plan/SKILL.md +1 -0
  47. package/templates/.claude/skills/prd/SKILL.md +1 -0
  48. package/templates/.claude/skills/project-optimizer/AGENTS.md +275 -0
  49. package/templates/.claude/skills/project-optimizer/SKILL.md +375 -0
  50. package/templates/.claude/skills/project-optimizer/rules/arch-config-centralize.md +66 -0
  51. package/templates/.claude/skills/project-optimizer/rules/arch-hot-path.md +35 -0
  52. package/templates/.claude/skills/project-optimizer/rules/arch-interface-segregation.md +51 -0
  53. package/templates/.claude/skills/project-optimizer/rules/arch-module-boundary.md +42 -0
  54. package/templates/.claude/skills/project-optimizer/rules/build-cache.md +57 -0
  55. package/templates/.claude/skills/project-optimizer/rules/build-code-split.md +56 -0
  56. package/templates/.claude/skills/project-optimizer/rules/build-incremental.md +65 -0
  57. package/templates/.claude/skills/project-optimizer/rules/build-minify.md +61 -0
  58. package/templates/.claude/skills/project-optimizer/rules/build-tree-shake.md +60 -0
  59. package/templates/.claude/skills/project-optimizer/rules/code-complexity.md +65 -0
  60. package/templates/.claude/skills/project-optimizer/rules/code-dead-elimination.md +32 -0
  61. package/templates/.claude/skills/project-optimizer/rules/code-duplication.md +54 -0
  62. package/templates/.claude/skills/project-optimizer/rules/code-error-handling.md +75 -0
  63. package/templates/.claude/skills/project-optimizer/rules/code-naming.md +52 -0
  64. package/templates/.claude/skills/project-optimizer/rules/concurrency-defer-await.md +54 -0
  65. package/templates/.claude/skills/project-optimizer/rules/concurrency-parallel.md +90 -0
  66. package/templates/.claude/skills/project-optimizer/rules/concurrency-pipeline.md +68 -0
  67. package/templates/.claude/skills/project-optimizer/rules/concurrency-pool.md +68 -0
  68. package/templates/.claude/skills/project-optimizer/rules/deps-lightweight-alt.md +37 -0
  69. package/templates/.claude/skills/project-optimizer/rules/deps-peer-align.md +44 -0
  70. package/templates/.claude/skills/project-optimizer/rules/deps-security-audit.md +45 -0
  71. package/templates/.claude/skills/project-optimizer/rules/deps-unused-removal.md +25 -0
  72. package/templates/.claude/skills/project-optimizer/rules/deps-version-pin.md +40 -0
  73. package/templates/.claude/skills/project-optimizer/rules/dx-ci-speed.md +47 -0
  74. package/templates/.claude/skills/project-optimizer/rules/dx-dev-server.md +35 -0
  75. package/templates/.claude/skills/project-optimizer/rules/dx-lint-config.md +36 -0
  76. package/templates/.claude/skills/project-optimizer/rules/dx-test-coverage.md +34 -0
  77. package/templates/.claude/skills/project-optimizer/rules/dx-type-safety.md +49 -0
  78. package/templates/.claude/skills/project-optimizer/rules/io-batch-queries.md +67 -0
  79. package/templates/.claude/skills/project-optimizer/rules/io-cache-layer.md +67 -0
  80. package/templates/.claude/skills/project-optimizer/rules/io-connection-reuse.md +67 -0
  81. package/templates/.claude/skills/project-optimizer/rules/io-serialize-minimal.md +61 -0
  82. package/templates/.claude/skills/project-optimizer/rules/io-stream.md +75 -0
  83. package/templates/.claude/skills/project-optimizer/rules/memory-bounded-cache.md +65 -0
  84. package/templates/.claude/skills/project-optimizer/rules/memory-large-data.md +64 -0
  85. package/templates/.claude/skills/project-optimizer/rules/memory-lazy-init.md +78 -0
  86. package/templates/.claude/skills/project-optimizer/rules/memory-leak-prevention.md +79 -0
  87. package/templates/.claude/skills/project-optimizer/rules/memory-pool-reuse.md +70 -0
  88. package/templates/.claude/skills/ralph/SKILL.md +1 -0
  89. package/templates/.claude/skills/refactor/SKILL.md +1 -0
  90. package/templates/.claude/skills/research/SKILL.md +1 -0
  91. package/templates/.claude/skills/sql-optimizer/SKILL.md +438 -0
  92. package/templates/.claude/skills/sql-optimizer/orm-patterns.md +218 -0
  93. package/templates/.claude/skills/startup-validator/SKILL.md +1 -0
  94. package/templates/.claude/skills/tanstack-start-react-best-practices/AGENTS.md +53 -14
  95. package/templates/.claude/skills/tanstack-start-react-best-practices/SKILL.md +94 -27
  96. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-defer-third-party.md +42 -19
  97. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-optimistic-updates.md +109 -0
  98. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-suspense-query.md +74 -0
  99. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-use-hook.md +81 -0
  100. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-react-compiler.md +81 -0
  101. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-beforeload-auth.md +121 -0
  102. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-file-conventions.md +104 -0
  103. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-link-navigation.md +119 -0
  104. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-nested-layouts.md +155 -0
  105. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-path-params.md +89 -0
  106. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-pending-component.md +110 -0
  107. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-preload-strategy.md +91 -0
  108. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-router-context.md +120 -0
  109. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-search-params.md +114 -0
  110. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-deferred-data.md +1 -1
  111. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-error-boundaries.md +79 -0
  112. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-middleware.md +85 -0
  113. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-serialization.md +56 -21
  114. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-streaming.md +84 -0
  115. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-validator.md +71 -0
  116. package/templates/.claude/skills/tauri-react-best-practices/AGENTS.md +527 -0
  117. package/templates/.claude/skills/tauri-react-best-practices/SKILL.md +571 -0
  118. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-barrel-imports.md +140 -0
  119. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-cargo-profile.md +96 -0
  120. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-frontend-treeshake.md +242 -0
  121. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-lazy-components.md +255 -0
  122. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-remove-unused-commands.md +160 -0
  123. package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-ci-pipeline.md +269 -0
  124. package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-signing.md +207 -0
  125. package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-updater.md +226 -0
  126. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-async-commands.md +172 -0
  127. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-batch-commands.md +133 -0
  128. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-binary-response.md +198 -0
  129. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-channel-streaming.md +186 -0
  130. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-error-handling.md +250 -0
  131. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-type-safe.md +227 -0
  132. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-derived-state.md +231 -0
  133. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-functional-setstate.md +191 -0
  134. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-index-maps.md +276 -0
  135. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-lazy-state-init.md +196 -0
  136. package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-lifecycle.md +265 -0
  137. package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-mobile-compat.md +199 -0
  138. package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-permission-scope.md +193 -0
  139. package/templates/.claude/skills/tauri-react-best-practices/rules/react-error-boundary.md +239 -0
  140. package/templates/.claude/skills/tauri-react-best-practices/rules/react-event-listener.md +151 -0
  141. package/templates/.claude/skills/tauri-react-best-practices/rules/react-file-src.md +155 -0
  142. package/templates/.claude/skills/tauri-react-best-practices/rules/react-invoke-hook.md +139 -0
  143. package/templates/.claude/skills/tauri-react-best-practices/rules/react-optimistic-update.md +211 -0
  144. package/templates/.claude/skills/tauri-react-best-practices/rules/security-capability-split.md +205 -0
  145. package/templates/.claude/skills/tauri-react-best-practices/rules/security-csp.md +207 -0
  146. package/templates/.claude/skills/tauri-react-best-practices/rules/security-least-privilege.md +106 -0
  147. package/templates/.claude/skills/tauri-react-best-practices/rules/security-no-wildcard.md +253 -0
  148. package/templates/.claude/skills/tauri-react-best-practices/rules/security-scope-paths.md +160 -0
  149. package/templates/.claude/skills/tauri-react-best-practices/rules/state-async-mutex.md +270 -0
  150. package/templates/.claude/skills/tauri-react-best-practices/rules/state-mutex-pattern.md +265 -0
  151. package/templates/.claude/skills/tauri-react-best-practices/rules/state-react-sync.md +375 -0
  152. package/templates/.claude/skills/tauri-react-best-practices/rules/state-single-container.md +275 -0
  153. package/templates/tanstack-start/docs/architecture.md +238 -167
  154. package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +777 -38
  155. package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +549 -37
  156. package/templates/tanstack-start/docs/library/tanstack-router/index.md +895 -111
  157. package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +641 -43
  158. package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +889 -38
  159. package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +891 -29
  160. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +972 -36
  161. package/templates/tanstack-start/docs/library/tanstack-start/index.md +1525 -881
  162. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +1099 -20
  163. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +796 -30
  164. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +953 -35
  165. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +371 -15
  166. package/templates/tauri/CLAUDE.md +189 -0
  167. package/templates/tauri/docs/guides/distribution.md +261 -0
  168. package/templates/tauri/docs/guides/getting-started.md +302 -0
  169. package/templates/tauri/docs/guides/mobile.md +288 -0
  170. package/templates/tauri/docs/library/tauri/index.md +510 -0
@@ -0,0 +1,265 @@
1
+ # setup/on_event/on_drop 라이프사이클 관리
2
+
3
+ ## 왜 중요한가
4
+
5
+ Tauri 플러그인의 리소스(DB 연결, 파일 핸들, 소켓 등)를 제대로 초기화하고 정리하지 않으면 메모리 누수, 파일 잠금, 좀비 프로세스가 발생합니다. 플러그인 라이프사이클을 명확히 관리해야 앱 안정성을 보장할 수 있습니다.
6
+
7
+ ## ❌ 잘못된 패턴
8
+
9
+ ```rust
10
+ use tauri::{plugin::{Builder, TauriPlugin}, Runtime};
11
+
12
+ pub fn init<R: Runtime>() -> TauriPlugin<R> {
13
+ Builder::new("my-plugin")
14
+ .invoke_handler(tauri::generate_handler![my_command])
15
+ .build()
16
+ }
17
+
18
+ #[tauri::command]
19
+ fn my_command(db: State<Database>) -> Result<Vec<Item>, String> {
20
+ // ❌ Database 초기화 없음
21
+ // ❌ 앱 종료 시 DB 연결 정리 없음
22
+ db.query_items().map_err(|e| e.to_string())
23
+ }
24
+ ```
25
+
26
+ **문제점:**
27
+ - 리소스 초기화 로직 없음
28
+ - 앱 종료 시 cleanup 없음 (DB 연결 유지, 파일 잠금)
29
+ - 상태 관리 누락
30
+
31
+ ## ✅ 올바른 패턴
32
+
33
+ ```rust
34
+ use tauri::{
35
+ plugin::{Builder, TauriPlugin},
36
+ AppHandle, Manager, Runtime, State
37
+ };
38
+ use std::sync::Mutex;
39
+
40
+ pub struct Database {
41
+ conn: Mutex<rusqlite::Connection>,
42
+ }
43
+
44
+ impl Database {
45
+ fn new(path: &str) -> Result<Self, rusqlite::Error> {
46
+ let conn = rusqlite::Connection::open(path)?;
47
+ Ok(Database {
48
+ conn: Mutex::new(conn),
49
+ })
50
+ }
51
+ }
52
+
53
+ pub fn init<R: Runtime>() -> TauriPlugin<R> {
54
+ Builder::new("my-plugin")
55
+ .invoke_handler(tauri::generate_handler![my_command])
56
+ .setup(|app_handle, _api| {
57
+ // ✅ 플러그인 초기화 시점
58
+ let app_data = app_handle.path().app_data_dir().unwrap();
59
+ let db_path = app_data.join("data.db");
60
+ let db = Database::new(db_path.to_str().unwrap())
61
+ .expect("Failed to init database");
62
+
63
+ app_handle.manage(db);
64
+ println!("Plugin initialized");
65
+
66
+ Ok(())
67
+ })
68
+ .on_event(|app_handle, event| {
69
+ // ✅ 앱 이벤트 핸들러
70
+ match event {
71
+ tauri::RunEvent::Exit => {
72
+ println!("App exiting, cleaning up...");
73
+ }
74
+ tauri::RunEvent::ExitRequested { .. } => {
75
+ println!("Exit requested");
76
+ }
77
+ _ => {}
78
+ }
79
+ })
80
+ .build()
81
+ }
82
+
83
+ #[tauri::command]
84
+ fn my_command(db: State<Database>) -> Result<Vec<Item>, String> {
85
+ // ✅ 초기화된 Database 사용
86
+ let conn = db.conn.lock().unwrap();
87
+ conn.query_items().map_err(|e| e.to_string())
88
+ }
89
+ ```
90
+
91
+ **파일 핸들 정리 예시:**
92
+
93
+ ```rust
94
+ use std::fs::File;
95
+ use std::sync::Mutex;
96
+
97
+ pub struct FileCache {
98
+ handles: Mutex<HashMap<String, File>>,
99
+ }
100
+
101
+ impl FileCache {
102
+ fn new() -> Self {
103
+ FileCache {
104
+ handles: Mutex::new(HashMap::new()),
105
+ }
106
+ }
107
+
108
+ fn cleanup(&self) {
109
+ let mut handles = self.handles.lock().unwrap();
110
+ for (path, _file) in handles.drain() {
111
+ println!("Closing file: {}", path);
112
+ }
113
+ }
114
+ }
115
+
116
+ impl Drop for FileCache {
117
+ fn drop(&mut self) {
118
+ // ✅ 자동 cleanup
119
+ self.cleanup();
120
+ }
121
+ }
122
+
123
+ pub fn init<R: Runtime>() -> TauriPlugin<R> {
124
+ Builder::new("file-cache")
125
+ .setup(|app_handle, _api| {
126
+ app_handle.manage(FileCache::new());
127
+ Ok(())
128
+ })
129
+ .on_event(|app_handle, event| {
130
+ if let tauri::RunEvent::Exit = event {
131
+ if let Some(cache) = app_handle.try_state::<FileCache>() {
132
+ cache.cleanup();
133
+ }
134
+ }
135
+ })
136
+ .build()
137
+ }
138
+ ```
139
+
140
+ **비동기 리소스 정리 예시:**
141
+
142
+ ```rust
143
+ use tokio::sync::RwLock;
144
+ use reqwest::Client;
145
+
146
+ pub struct ApiClient {
147
+ client: Client,
148
+ pending_requests: RwLock<Vec<tokio::task::JoinHandle<()>>>,
149
+ }
150
+
151
+ impl ApiClient {
152
+ fn new() -> Self {
153
+ ApiClient {
154
+ client: Client::new(),
155
+ pending_requests: RwLock::new(Vec::new()),
156
+ }
157
+ }
158
+
159
+ async fn shutdown(&self) {
160
+ let mut pending = self.pending_requests.write().await;
161
+ for handle in pending.drain(..) {
162
+ handle.abort();
163
+ }
164
+ println!("All pending requests aborted");
165
+ }
166
+ }
167
+
168
+ pub fn init<R: Runtime>() -> TauriPlugin<R> {
169
+ Builder::new("api-client")
170
+ .setup(|app_handle, _api| {
171
+ app_handle.manage(ApiClient::new());
172
+ Ok(())
173
+ })
174
+ .on_event(|app_handle, event| {
175
+ if let tauri::RunEvent::Exit = event {
176
+ if let Some(client) = app_handle.try_state::<ApiClient>() {
177
+ tauri::async_runtime::block_on(client.shutdown());
178
+ }
179
+ }
180
+ })
181
+ .build()
182
+ }
183
+ ```
184
+
185
+ **커스텀 플러그인 구조 템플릿:**
186
+
187
+ ```rust
188
+ use tauri::{plugin::{Builder, TauriPlugin}, Runtime, AppHandle, Manager};
189
+
190
+ pub struct MyPluginState {
191
+ // 플러그인 상태
192
+ }
193
+
194
+ impl MyPluginState {
195
+ fn new() -> Self {
196
+ // 초기화 로직
197
+ Self {}
198
+ }
199
+
200
+ fn cleanup(&self) {
201
+ // 정리 로직
202
+ }
203
+ }
204
+
205
+ impl Drop for MyPluginState {
206
+ fn drop(&mut self) {
207
+ self.cleanup();
208
+ }
209
+ }
210
+
211
+ pub fn init<R: Runtime>() -> TauriPlugin<R> {
212
+ Builder::new("my-plugin")
213
+ .invoke_handler(tauri::generate_handler![
214
+ my_command_1,
215
+ my_command_2
216
+ ])
217
+ .setup(|app_handle, _api| {
218
+ // 플러그인 초기화
219
+ let state = MyPluginState::new();
220
+ app_handle.manage(state);
221
+ Ok(())
222
+ })
223
+ .on_event(|app_handle, event| {
224
+ // 이벤트 핸들러
225
+ match event {
226
+ tauri::RunEvent::Exit => {
227
+ if let Some(state) = app_handle.try_state::<MyPluginState>() {
228
+ state.cleanup();
229
+ }
230
+ }
231
+ _ => {}
232
+ }
233
+ })
234
+ .build()
235
+ }
236
+
237
+ #[tauri::command]
238
+ fn my_command_1(state: State<MyPluginState>) -> Result<String, String> {
239
+ // 커맨드 로직
240
+ Ok("Success".to_string())
241
+ }
242
+ ```
243
+
244
+ ## 추가 컨텍스트
245
+
246
+ **라이프사이클 단계:**
247
+ 1. `setup`: 플러그인 초기화 (앱 시작 시 한 번)
248
+ 2. `invoke_handler`: 커맨드 실행 (프론트엔드 호출 시)
249
+ 3. `on_event`: 앱 이벤트 처리 (Exit, ExitRequested 등)
250
+ 4. `Drop`: 자동 정리 (플러그인 상태가 drop될 때)
251
+
252
+ **RunEvent 종류:**
253
+ - `Exit`: 앱 종료 직전
254
+ - `ExitRequested`: 앱 종료 요청 시 (취소 가능)
255
+ - `WindowEvent`: 윈도우 이벤트
256
+ - `Ready`: 앱 준비 완료
257
+
258
+ **Tauri State 관리:**
259
+ - `app_handle.manage()`: 전역 상태 등록
260
+ - `State<T>`: 커맨드에서 상태 접근
261
+ - `app_handle.try_state::<T>()`: 상태 가져오기 (Option)
262
+
263
+ **참고:** [Tauri Plugin Development](https://beta.tauri.app/develop/plugins/)
264
+
265
+ 영향도: HIGH - 메모리 누수, 리소스 잠금, 앱 안정성
@@ -0,0 +1,199 @@
1
+ # 모바일 호환성 확인
2
+
3
+ ## 왜 중요한가
4
+
5
+ Tauri v2는 iOS/Android를 지원하지만, 일부 플러그인과 API는 데스크톱 전용입니다. 모바일에서 미지원 API를 호출하면 런타임 에러나 크래시가 발생합니다. 플랫폼별 조건부 코드를 작성해야 크로스 플랫폼 앱을 안정적으로 배포할 수 있습니다.
6
+
7
+ ## ❌ 잘못된 패턴
8
+
9
+ ```tsx
10
+ import { invoke } from '@tauri-apps/api/core'
11
+ import { open } from '@tauri-apps/plugin-dialog'
12
+
13
+ function FilePicker() {
14
+ const selectFile = async () => {
15
+ // ❌ 모바일에서 dialog 플러그인 미지원 (크래시)
16
+ const file = await open({
17
+ multiple: false,
18
+ directory: false
19
+ })
20
+ console.log(file)
21
+ }
22
+
23
+ return <button onClick={selectFile}>Select File</button>
24
+ }
25
+ ```
26
+
27
+ **문제점:**
28
+ - 플랫폼 구분 없이 데스크톱 전용 API 사용
29
+ - 모바일에서 런타임 에러 발생
30
+ - 플랫폼별 대체 로직 없음
31
+
32
+ ## ✅ 올바른 패턴
33
+
34
+ ```tsx
35
+ import { invoke } from '@tauri-apps/api/core'
36
+ import { open } from '@tauri-apps/plugin-dialog'
37
+ import { platform } from '@tauri-apps/plugin-os'
38
+
39
+ function FilePicker() {
40
+ const selectFile = async () => {
41
+ const os = await platform()
42
+
43
+ if (os === 'android' || os === 'ios') {
44
+ // ✅ 모바일: 네이티브 파일 피커 사용
45
+ const result = await invoke<string>('mobile_pick_file')
46
+ console.log(result)
47
+ } else {
48
+ // ✅ 데스크톱: dialog 플러그인 사용
49
+ const file = await open({
50
+ multiple: false,
51
+ directory: false
52
+ })
53
+ console.log(file)
54
+ }
55
+ }
56
+
57
+ return <button onClick={selectFile}>Select File</button>
58
+ }
59
+ ```
60
+
61
+ **Rust 측 플랫폼 조건부 컴파일:**
62
+
63
+ ```rust
64
+ #[tauri::command]
65
+ fn get_system_info() -> String {
66
+ #[cfg(target_os = "android")]
67
+ {
68
+ "Android".to_string()
69
+ }
70
+
71
+ #[cfg(target_os = "ios")]
72
+ {
73
+ "iOS".to_string()
74
+ }
75
+
76
+ #[cfg(not(any(target_os = "android", target_os = "ios")))]
77
+ {
78
+ "Desktop".to_string()
79
+ }
80
+ }
81
+ ```
82
+
83
+ **모바일 전용 플러그인 사용:**
84
+
85
+ ```rust
86
+ // Cargo.toml
87
+ [dependencies]
88
+ tauri-plugin-barcode-scanner = "2.0.0-beta" // 모바일 전용
89
+
90
+ // src/lib.rs
91
+ #[cfg(mobile)]
92
+ use tauri_plugin_barcode_scanner::BarcodeScanner;
93
+
94
+ fn main() {
95
+ tauri::Builder::default()
96
+ .plugin(
97
+ #[cfg(mobile)]
98
+ tauri_plugin_barcode_scanner::init()
99
+ )
100
+ .run(tauri::generate_context!())
101
+ .expect("error while running tauri application");
102
+ }
103
+ ```
104
+
105
+ **React Native 스타일 플랫폼 분기:**
106
+
107
+ ```tsx
108
+ import { platform } from '@tauri-apps/plugin-os'
109
+ import { useEffect, useState } from 'react'
110
+
111
+ function usePlatform() {
112
+ const [os, setOs] = useState<string>('unknown')
113
+
114
+ useEffect(() => {
115
+ platform().then(setOs)
116
+ }, [])
117
+
118
+ return {
119
+ os,
120
+ isDesktop: ['windows', 'macos', 'linux'].includes(os),
121
+ isMobile: ['android', 'ios'].includes(os),
122
+ isAndroid: os === 'android',
123
+ isIOS: os === 'ios'
124
+ }
125
+ }
126
+
127
+ function App() {
128
+ const { isDesktop, isMobile } = usePlatform()
129
+
130
+ return (
131
+ <div>
132
+ {isDesktop && <DesktopMenu />}
133
+ {isMobile && <MobileTabBar />}
134
+ </div>
135
+ )
136
+ }
137
+ ```
138
+
139
+ **파일 경로 처리:**
140
+
141
+ ```tsx
142
+ import { appDataDir, join } from '@tauri-apps/api/path'
143
+ import { platform } from '@tauri-apps/plugin-os'
144
+
145
+ async function getConfigPath() {
146
+ const os = await platform()
147
+ const dataDir = await appDataDir()
148
+
149
+ if (os === 'android') {
150
+ // Android: /data/data/com.example.app/files
151
+ return await join(dataDir, 'config.json')
152
+ } else if (os === 'ios') {
153
+ // iOS: /var/mobile/Containers/Data/Application/.../Documents
154
+ return await join(dataDir, 'config.json')
155
+ } else {
156
+ // Desktop: ~/.local/share/com.example.app
157
+ return await join(dataDir, 'config.json')
158
+ }
159
+ }
160
+ ```
161
+
162
+ **모바일 미지원 플러그인 목록:**
163
+
164
+ | 플러그인 | 데스크톱 | 모바일 | 대체 방법 |
165
+ |---------|---------|--------|----------|
166
+ | dialog | ✅ | ❌ | 네이티브 UI 사용 |
167
+ | global-shortcut | ✅ | ❌ | 모바일은 제스처 사용 |
168
+ | updater | ✅ | ❌ | Play Store/App Store 업데이트 |
169
+ | window (일부) | ✅ | ⚠️ | 일부 API만 지원 |
170
+ | shell (open) | ✅ | ✅ | URL 열기만 지원 |
171
+ | fs | ✅ | ✅ | 전체 지원 |
172
+ | http | ✅ | ✅ | 전체 지원 |
173
+
174
+ ## 추가 컨텍스트
175
+
176
+ **모바일 개발 시 체크리스트:**
177
+ 1. `platform()` API로 플랫폼 구분
178
+ 2. 데스크톱 전용 플러그인 조건부 사용
179
+ 3. 파일 경로 플랫폼별 처리
180
+ 4. UI/UX 모바일 최적화 (터치, 작은 화면)
181
+ 5. 권한 요청 (카메라, 위치 등)
182
+
183
+ **Rust cfg 속성:**
184
+ ```rust
185
+ #[cfg(target_os = "android")] // Android 전용
186
+ #[cfg(target_os = "ios")] // iOS 전용
187
+ #[cfg(mobile)] // Android + iOS
188
+ #[cfg(desktop)] // Windows + macOS + Linux
189
+ #[cfg(not(mobile))] // 데스크톱만
190
+ ```
191
+
192
+ **권장 사항:**
193
+ - 플랫폼별 빌드 후 실제 기기에서 테스트
194
+ - 에뮬레이터/시뮬레이터에서 미지원 API 확인
195
+ - `try/catch`로 런타임 에러 처리
196
+
197
+ **참고:** [Tauri Mobile Guide](https://beta.tauri.app/develop/mobile/)
198
+
199
+ 영향도: HIGH - 모바일 앱 안정성, 크로스 플랫폼 호환성
@@ -0,0 +1,193 @@
1
+ # 플러그인별 최소 권한 + Scope
2
+
3
+ ## 왜 중요한가
4
+
5
+ Tauri 플러그인은 기본적으로 모든 권한을 허용하지 않습니다. 필요한 커맨드만 명시하고 scope를 제한해야 보안 취약점을 방지할 수 있습니다. 과도한 권한은 악의적인 코드나 XSS 공격 시 시스템 접근을 허용할 수 있습니다.
6
+
7
+ ## ❌ 잘못된 패턴
8
+
9
+ ```json
10
+ // tauri.conf.json
11
+ {
12
+ "plugins": {
13
+ "fs": {
14
+ "all": true, // ❌ 모든 파일 시스템 접근 허용
15
+ "scope": ["**"] // ❌ 전체 디렉토리 접근 가능
16
+ },
17
+ "shell": {
18
+ "all": true // ❌ 모든 셸 커맨드 실행 허용
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ **문제점:**
25
+ - 불필요한 권한 부여 (최소 권한 원칙 위반)
26
+ - 악의적인 코드가 시스템 전체 접근 가능
27
+ - XSS 공격 시 파일 삭제, 임의 명령 실행 가능
28
+
29
+ ## ✅ 올바른 패턴
30
+
31
+ ```json
32
+ // tauri.conf.json
33
+ {
34
+ "plugins": {
35
+ "fs": {
36
+ "scope": [
37
+ "$APPDATA/user-data/**", // ✅ 앱 데이터 폴더만
38
+ "$RESOURCE/assets/**" // ✅ 앱 리소스 폴더만
39
+ ],
40
+ "commands": {
41
+ "readFile": true,
42
+ "writeFile": true,
43
+ "readDir": true,
44
+ "exists": true
45
+ }
46
+ },
47
+ "shell": {
48
+ "scope": [
49
+ {
50
+ "name": "ffmpeg",
51
+ "cmd": "ffmpeg",
52
+ "args": [
53
+ "-i", { "validator": "\\.(mp4|avi|mov)$" },
54
+ "-o", { "validator": "^[^/\\\\]+$" }
55
+ ]
56
+ }
57
+ ]
58
+ },
59
+ "http": {
60
+ "scope": [
61
+ "https://api.example.com/*" // ✅ 특정 도메인만
62
+ ],
63
+ "commands": {
64
+ "fetch": true
65
+ }
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ **파일 시스템 플러그인 권한 예시:**
72
+
73
+ ```json
74
+ {
75
+ "plugins": {
76
+ "fs": {
77
+ "scope": [
78
+ // 읽기 전용 리소스
79
+ {
80
+ "path": "$RESOURCE/**",
81
+ "permissions": ["read"]
82
+ },
83
+ // 읽기/쓰기 가능한 사용자 데이터
84
+ {
85
+ "path": "$APPDATA/config.json",
86
+ "permissions": ["read", "write"]
87
+ },
88
+ {
89
+ "path": "$APPDATA/cache/**",
90
+ "permissions": ["read", "write", "delete"]
91
+ }
92
+ ],
93
+ "commands": {
94
+ "readFile": true,
95
+ "writeFile": true,
96
+ "readDir": true,
97
+ "exists": true
98
+ // removeFile, renameFile 등 불필요한 커맨드 비활성화
99
+ }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ **HTTP 플러그인 권한 예시:**
106
+
107
+ ```json
108
+ {
109
+ "plugins": {
110
+ "http": {
111
+ "scope": [
112
+ "https://api.example.com/*",
113
+ "https://cdn.example.com/assets/*"
114
+ ],
115
+ "commands": {
116
+ "fetch": true
117
+ }
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ **Shell 플러그인 권한 예시:**
124
+
125
+ ```json
126
+ {
127
+ "plugins": {
128
+ "shell": {
129
+ "scope": [
130
+ {
131
+ "name": "video-convert",
132
+ "cmd": "ffmpeg",
133
+ "args": [
134
+ "-i", { "validator": "^[a-zA-Z0-9_-]+\\.(mp4|avi)$" },
135
+ "-codec", "copy",
136
+ { "validator": "^output\\.mp4$" }
137
+ ],
138
+ "sidecar": false
139
+ }
140
+ ]
141
+ }
142
+ }
143
+ }
144
+ ```
145
+
146
+ **런타임 권한 요청 (Tauri v2.1+):**
147
+
148
+ ```tsx
149
+ import { invoke } from '@tauri-apps/api/core'
150
+ import { requestPermission } from '@tauri-apps/plugin-fs'
151
+
152
+ async function writeUserConfig(data: Config) {
153
+ const granted = await requestPermission({
154
+ path: '$APPDATA/config.json',
155
+ permissions: ['write']
156
+ })
157
+
158
+ if (!granted) {
159
+ throw new Error('Permission denied')
160
+ }
161
+
162
+ await invoke('write_config', { data })
163
+ }
164
+ ```
165
+
166
+ ## 추가 컨텍스트
167
+
168
+ **Scope 패턴:**
169
+ - `$APPDATA`: 사용자 앱 데이터 디렉토리
170
+ - `$RESOURCE`: 앱 리소스 디렉토리 (번들된 파일)
171
+ - `$HOME`: 사용자 홈 디렉토리 (가급적 피하기)
172
+ - `**`: 하위 디렉토리 포함 (주의해서 사용)
173
+
174
+ **공식 플러그인 권한 체크리스트:**
175
+
176
+ | 플러그인 | 최소 권한 예시 |
177
+ |---------|---------------|
178
+ | fs | 특정 디렉토리만 + read/write 구분 |
179
+ | http | 특정 도메인만 허용 |
180
+ | shell | 화이트리스트 커맨드 + args 검증 |
181
+ | notification | 기본 권한 (OS 수준 허용 필요) |
182
+ | clipboard | 기본 권한 |
183
+ | dialog | 기본 권한 |
184
+
185
+ **보안 원칙:**
186
+ 1. 최소 권한 원칙: 필요한 권한만 부여
187
+ 2. Scope 제한: 전체 파일 시스템 접근 금지
188
+ 3. 화이트리스트: 허용 목록 기반 권한 관리
189
+ 4. Validator: args에 정규식 검증 추가
190
+
191
+ **참고:** [Tauri Security Best Practices](https://beta.tauri.app/security/best-practices/)
192
+
193
+ 영향도: CRITICAL - 보안, 권한 관리, XSS 공격 방어