@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.
- package/dist/index.js +7 -1
- package/package.json +1 -1
- package/templates/.claude/agents/analyst.md +5 -0
- package/templates/.claude/agents/architect.md +5 -0
- package/templates/.claude/agents/build-fixer.md +1 -0
- package/templates/.claude/agents/code-reviewer.md +1 -0
- package/templates/.claude/agents/critic.md +4 -0
- package/templates/.claude/agents/deep-executor.md +1 -0
- package/templates/.claude/agents/dependency-manager.md +2 -0
- package/templates/.claude/agents/deployment-validator.md +2 -0
- package/templates/.claude/agents/designer.md +2 -0
- package/templates/.claude/agents/document-writer.md +3 -0
- package/templates/.claude/agents/explore.md +1 -0
- package/templates/.claude/agents/git-operator.md +2 -0
- package/templates/.claude/agents/implementation-executor.md +2 -0
- package/templates/.claude/agents/ko-to-en-translator.md +3 -0
- package/templates/.claude/agents/lint-fixer.md +2 -0
- package/templates/.claude/agents/planner.md +3 -0
- package/templates/.claude/agents/pm.md +349 -0
- package/templates/.claude/agents/qa-tester.md +1 -0
- package/templates/.claude/agents/refactor-advisor.md +4 -0
- package/templates/.claude/agents/researcher.md +9 -1
- package/templates/.claude/agents/scientist.md +1 -0
- package/templates/.claude/agents/security-reviewer.md +1 -0
- package/templates/.claude/agents/tdd-guide.md +1 -0
- package/templates/.claude/agents/vision.md +1 -0
- package/templates/.claude/instructions/agent-patterns/agent-teams-usage.md +376 -0
- package/templates/.claude/instructions/sourcing/reliable-search.md +49 -2
- package/templates/.claude/scripts/agent-teams/check-availability.sh +238 -0
- package/templates/.claude/scripts/agent-teams/setup-tmux.sh +125 -0
- package/templates/.claude/skills/agent-teams-setup/SKILL.md +460 -0
- package/templates/.claude/skills/brainstorm/SKILL.md +1 -0
- package/templates/.claude/skills/bug-fix/SKILL.md +1 -0
- package/templates/.claude/skills/crawler/SKILL.md +2 -0
- package/templates/.claude/skills/docs-creator/SKILL.md +1 -0
- package/templates/.claude/skills/docs-fetch/SKILL.md +6 -4
- package/templates/.claude/skills/docs-refactor/SKILL.md +1 -0
- package/templates/.claude/skills/elon-musk/SKILL.md +1 -0
- package/templates/.claude/skills/execute/SKILL.md +1 -0
- package/templates/.claude/skills/feedback/SKILL.md +1 -0
- package/templates/.claude/skills/figma-to-code/SKILL.md +1 -0
- package/templates/.claude/skills/genius-thinking/SKILL.md +1 -0
- package/templates/.claude/skills/global-uiux-design/SKILL.md +1 -0
- package/templates/.claude/skills/korea-uiux-design/SKILL.md +1 -0
- package/templates/.claude/skills/nextjs-react-best-practices/SKILL.md +1 -0
- package/templates/.claude/skills/plan/SKILL.md +1 -0
- package/templates/.claude/skills/prd/SKILL.md +1 -0
- package/templates/.claude/skills/project-optimizer/AGENTS.md +275 -0
- package/templates/.claude/skills/project-optimizer/SKILL.md +375 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-config-centralize.md +66 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-hot-path.md +35 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-interface-segregation.md +51 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-module-boundary.md +42 -0
- package/templates/.claude/skills/project-optimizer/rules/build-cache.md +57 -0
- package/templates/.claude/skills/project-optimizer/rules/build-code-split.md +56 -0
- package/templates/.claude/skills/project-optimizer/rules/build-incremental.md +65 -0
- package/templates/.claude/skills/project-optimizer/rules/build-minify.md +61 -0
- package/templates/.claude/skills/project-optimizer/rules/build-tree-shake.md +60 -0
- package/templates/.claude/skills/project-optimizer/rules/code-complexity.md +65 -0
- package/templates/.claude/skills/project-optimizer/rules/code-dead-elimination.md +32 -0
- package/templates/.claude/skills/project-optimizer/rules/code-duplication.md +54 -0
- package/templates/.claude/skills/project-optimizer/rules/code-error-handling.md +75 -0
- package/templates/.claude/skills/project-optimizer/rules/code-naming.md +52 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-defer-await.md +54 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-parallel.md +90 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-pipeline.md +68 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-pool.md +68 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-lightweight-alt.md +37 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-peer-align.md +44 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-security-audit.md +45 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-unused-removal.md +25 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-version-pin.md +40 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-ci-speed.md +47 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-dev-server.md +35 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-lint-config.md +36 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-test-coverage.md +34 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-type-safety.md +49 -0
- package/templates/.claude/skills/project-optimizer/rules/io-batch-queries.md +67 -0
- package/templates/.claude/skills/project-optimizer/rules/io-cache-layer.md +67 -0
- package/templates/.claude/skills/project-optimizer/rules/io-connection-reuse.md +67 -0
- package/templates/.claude/skills/project-optimizer/rules/io-serialize-minimal.md +61 -0
- package/templates/.claude/skills/project-optimizer/rules/io-stream.md +75 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-bounded-cache.md +65 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-large-data.md +64 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-lazy-init.md +78 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-leak-prevention.md +79 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-pool-reuse.md +70 -0
- package/templates/.claude/skills/ralph/SKILL.md +1 -0
- package/templates/.claude/skills/refactor/SKILL.md +1 -0
- package/templates/.claude/skills/research/SKILL.md +1 -0
- package/templates/.claude/skills/sql-optimizer/SKILL.md +438 -0
- package/templates/.claude/skills/sql-optimizer/orm-patterns.md +218 -0
- package/templates/.claude/skills/startup-validator/SKILL.md +1 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/AGENTS.md +53 -14
- package/templates/.claude/skills/tanstack-start-react-best-practices/SKILL.md +94 -27
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-defer-third-party.md +42 -19
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-optimistic-updates.md +109 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-suspense-query.md +74 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-use-hook.md +81 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-react-compiler.md +81 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-beforeload-auth.md +121 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-file-conventions.md +104 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-link-navigation.md +119 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-nested-layouts.md +155 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-path-params.md +89 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-pending-component.md +110 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-preload-strategy.md +91 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-router-context.md +120 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-search-params.md +114 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-deferred-data.md +1 -1
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-error-boundaries.md +79 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-middleware.md +85 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-serialization.md +56 -21
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-streaming.md +84 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-validator.md +71 -0
- package/templates/.claude/skills/tauri-react-best-practices/AGENTS.md +527 -0
- package/templates/.claude/skills/tauri-react-best-practices/SKILL.md +571 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-barrel-imports.md +140 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-cargo-profile.md +96 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-frontend-treeshake.md +242 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-lazy-components.md +255 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-remove-unused-commands.md +160 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-ci-pipeline.md +269 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-signing.md +207 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-updater.md +226 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-async-commands.md +172 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-batch-commands.md +133 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-binary-response.md +198 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-channel-streaming.md +186 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-error-handling.md +250 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-type-safe.md +227 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-derived-state.md +231 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-functional-setstate.md +191 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-index-maps.md +276 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-lazy-state-init.md +196 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-lifecycle.md +265 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-mobile-compat.md +199 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-permission-scope.md +193 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-error-boundary.md +239 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-event-listener.md +151 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-file-src.md +155 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-invoke-hook.md +139 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-optimistic-update.md +211 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-capability-split.md +205 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-csp.md +207 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-least-privilege.md +106 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-no-wildcard.md +253 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-scope-paths.md +160 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-async-mutex.md +270 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-mutex-pattern.md +265 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-react-sync.md +375 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-single-container.md +275 -0
- package/templates/tanstack-start/docs/architecture.md +238 -167
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +777 -38
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +549 -37
- package/templates/tanstack-start/docs/library/tanstack-router/index.md +895 -111
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +641 -43
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +889 -38
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +891 -29
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +972 -36
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +1525 -881
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +1099 -20
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +796 -30
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +953 -35
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +371 -15
- package/templates/tauri/CLAUDE.md +189 -0
- package/templates/tauri/docs/guides/distribution.md +261 -0
- package/templates/tauri/docs/guides/getting-started.md +302 -0
- package/templates/tauri/docs/guides/mobile.md +288 -0
- package/templates/tauri/docs/library/tauri/index.md +510 -0
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tauri-react-best-practices
|
|
3
|
+
description: Tauri v2와 React 성능 최적화 가이드. Tauri 데스크톱/모바일 앱의 IPC, 보안, 번들 최적화, 상태 관리 패턴 보장. React 컴포넌트, Tauri Commands, 플러그인, 배포 작업에 트리거.
|
|
4
|
+
license: MIT
|
|
5
|
+
framework: tauri-v2
|
|
6
|
+
metadata:
|
|
7
|
+
author: tauri-community
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
adapted_for: tauri-v2-react
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
@../../instructions/agent-patterns/read-parallelization.md
|
|
13
|
+
@../../instructions/agent-patterns/agent-teams-usage.md
|
|
14
|
+
@../../instructions/validation/forbidden-patterns.md
|
|
15
|
+
@../../instructions/validation/required-behaviors.md
|
|
16
|
+
@../../instructions/multi-agent/coordination-guide.md
|
|
17
|
+
@../../instructions/multi-agent/execution-patterns.md
|
|
18
|
+
|
|
19
|
+
# Tauri v2 React 베스트 프랙티스
|
|
20
|
+
|
|
21
|
+
Tauri v2 + React 19 데스크톱/모바일 애플리케이션 성능 및 보안 최적화 가이드. 8개 카테고리, 40+ 규칙 포함. IPC 최적화(Commands, Events, Channels), 보안(Capabilities, Permissions, Scopes), 번들 크기 최소화, 상태 관리, 플러그인 패턴, 배포 최적화 등 Tauri 특화 패턴 반영.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<when_to_use>
|
|
26
|
+
|
|
27
|
+
## 사용 시점
|
|
28
|
+
|
|
29
|
+
| 상황 | 설명 |
|
|
30
|
+
|------|------|
|
|
31
|
+
| **Tauri Command 작성** | Rust 명령 정의, invoke 호출, 에러 처리 |
|
|
32
|
+
| **IPC 패턴 구현** | Commands, Events, Channels 통신 패턴 |
|
|
33
|
+
| **보안 설정** | Capabilities, Permissions, Scopes 구성 |
|
|
34
|
+
| **번들 최적화** | 앱 크기 감소, Cargo 프로필 최적화 |
|
|
35
|
+
| **상태 관리** | Rust 상태 + React 상태 통합 |
|
|
36
|
+
| **플러그인 사용** | 공식/커스텀 플러그인 통합 |
|
|
37
|
+
| **배포** | 빌드, 코드 서명, 자동 업데이트 |
|
|
38
|
+
| **React 성능** | Re-render 최적화, 번들 스플리팅 |
|
|
39
|
+
|
|
40
|
+
</when_to_use>
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
<parallel_agent_execution>
|
|
45
|
+
|
|
46
|
+
## 병렬 에이전트 실행
|
|
47
|
+
|
|
48
|
+
**ULTRAWORK MODE:** Tauri + React 최적화 작업 시 여러 규칙을 동시에 적용.
|
|
49
|
+
|
|
50
|
+
### 기본 원칙
|
|
51
|
+
|
|
52
|
+
| 원칙 | 실행 방법 | 효과 |
|
|
53
|
+
|------|----------|------|
|
|
54
|
+
| **PARALLEL** | 독립 작업을 단일 메시지에서 동시 실행 | 5-15배 속도 향상 |
|
|
55
|
+
| **DELEGATE** | 전문 에이전트에게 즉시 위임 | 품질 향상, 컨텍스트 격리 |
|
|
56
|
+
| **SMART MODEL** | 복잡도별 모델 선택 (haiku/sonnet/opus) | 비용 최적화 |
|
|
57
|
+
|
|
58
|
+
### Phase별 에이전트 활용
|
|
59
|
+
|
|
60
|
+
| Phase | 작업 | 에이전트 | 병렬 실행 |
|
|
61
|
+
|-------|------|---------|----------|
|
|
62
|
+
| **1. 코드베이스 분석** | Rust commands, React 컴포넌트, capabilities 파악 | explore (haiku) | O |
|
|
63
|
+
| **2. 규칙 적용** | IPC 최적화, 보안 강화, 번들 최적화 | implementation-executor (sonnet) | O |
|
|
64
|
+
| **3. 검증** | typecheck/lint/build, 보안 리뷰 | lint-fixer (sonnet), code-reviewer (opus) | lint 순차, review 병렬 |
|
|
65
|
+
| **4. 완료** | git commit | git-operator (sonnet) | 순차 |
|
|
66
|
+
|
|
67
|
+
### 에이전트별 역할
|
|
68
|
+
|
|
69
|
+
| 에이전트 | 모델 | Tauri 작업 | 병렬 실행 |
|
|
70
|
+
|---------|------|-----------|----------|
|
|
71
|
+
| **explore** | haiku | Rust commands/상태/capabilities 구조 분석 | O |
|
|
72
|
+
| **implementation-executor** | sonnet | IPC 최적화, 보안 설정, 번들 최적화 | O |
|
|
73
|
+
| **code-reviewer** | opus | 보안/성능 검토 | O |
|
|
74
|
+
| **lint-fixer** | sonnet | tsc/eslint/clippy 에러 수정 | 순차 |
|
|
75
|
+
|
|
76
|
+
### Model Routing
|
|
77
|
+
|
|
78
|
+
| 복잡도 | 모델 | Tauri 작업 예시 |
|
|
79
|
+
|--------|------|---------------|
|
|
80
|
+
| **LOW** | haiku | 파일 구조 파악, capabilities 확인 |
|
|
81
|
+
| **MEDIUM** | sonnet | IPC 패턴 적용, 플러그인 통합, 번들 최적화 |
|
|
82
|
+
| **HIGH** | opus | 보안 아키텍처 설계, 멀티 윈도우 IPC 전략 |
|
|
83
|
+
|
|
84
|
+
</parallel_agent_execution>
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
<categories>
|
|
89
|
+
|
|
90
|
+
## 카테고리별 우선순위
|
|
91
|
+
|
|
92
|
+
| 우선순위 | 카테고리 | 영향도 | 접두사 |
|
|
93
|
+
|---------|---------|--------|--------|
|
|
94
|
+
| 1 | IPC 최적화 | **CRITICAL** | `ipc-` |
|
|
95
|
+
| 2 | 보안 설정 | **CRITICAL** | `security-` |
|
|
96
|
+
| 3 | 번들 크기 최적화 | **HIGH** | `bundle-` |
|
|
97
|
+
| 4 | Tauri 상태 관리 | HIGH | `state-` |
|
|
98
|
+
| 5 | React 통합 패턴 | MEDIUM-HIGH | `react-` |
|
|
99
|
+
| 6 | 플러그인 패턴 | MEDIUM | `plugin-` |
|
|
100
|
+
| 7 | 배포 최적화 | MEDIUM | `deploy-` |
|
|
101
|
+
| 8 | Re-render/JS 성능 | LOW-MEDIUM | `perf-` |
|
|
102
|
+
|
|
103
|
+
</categories>
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
<rules>
|
|
108
|
+
|
|
109
|
+
## 빠른 참조
|
|
110
|
+
|
|
111
|
+
### 1. IPC 최적화 (CRITICAL)
|
|
112
|
+
|
|
113
|
+
| 규칙 | 설명 |
|
|
114
|
+
|------|------|
|
|
115
|
+
| `ipc-batch-commands` | 여러 invoke를 하나의 배치 커맨드로 통합 |
|
|
116
|
+
| `ipc-channel-streaming` | 대용량 데이터는 Channel 사용 (Events 대신) |
|
|
117
|
+
| `ipc-async-commands` | Rust 커맨드는 async로 비차단 실행 |
|
|
118
|
+
| `ipc-binary-response` | 바이너리 데이터는 Response로 JSON 직렬화 우회 |
|
|
119
|
+
| `ipc-type-safe` | tauri-specta로 TypeScript 바인딩 자동 생성 |
|
|
120
|
+
| `ipc-error-handling` | 구조화된 에러 타입 (thiserror + serde) |
|
|
121
|
+
|
|
122
|
+
### 2. 보안 설정 (CRITICAL)
|
|
123
|
+
|
|
124
|
+
| 규칙 | 설명 |
|
|
125
|
+
|------|------|
|
|
126
|
+
| `security-least-privilege` | 최소 권한 원칙, 필요한 커맨드만 허용 |
|
|
127
|
+
| `security-scope-paths` | 파일 경로 Scope 제한 ($APPDATA 등) |
|
|
128
|
+
| `security-capability-split` | 윈도우별 Capability 분리 |
|
|
129
|
+
| `security-csp` | Content Security Policy 설정 |
|
|
130
|
+
| `security-no-wildcard` | 와일드카드 권한/경로 사용 금지 |
|
|
131
|
+
|
|
132
|
+
### 3. 번들 크기 최적화 (HIGH)
|
|
133
|
+
|
|
134
|
+
| 규칙 | 설명 |
|
|
135
|
+
|------|------|
|
|
136
|
+
| `bundle-cargo-profile` | Cargo release 프로필 (lto, codegen-units=1, strip) |
|
|
137
|
+
| `bundle-remove-unused-commands` | 미사용 커맨드 자동 제거 (v2.4+) |
|
|
138
|
+
| `bundle-barrel-imports` | 직접 import, barrel 파일 회피 |
|
|
139
|
+
| `bundle-lazy-components` | 무거운 컴포넌트 lazy() 로드 |
|
|
140
|
+
| `bundle-frontend-treeshake` | 프론트엔드 tree-shaking 확인 |
|
|
141
|
+
|
|
142
|
+
### 4. Tauri 상태 관리 (HIGH)
|
|
143
|
+
|
|
144
|
+
| 규칙 | 설명 |
|
|
145
|
+
|------|------|
|
|
146
|
+
| `state-mutex-pattern` | Mutex로 가변 상태 관리, 타입 별칭 사용 |
|
|
147
|
+
| `state-single-container` | 동일 타입 중복 등록 방지, 컨테이너로 통합 |
|
|
148
|
+
| `state-async-mutex` | IO 리소스만 Tokio Mutex, 나머지는 std Mutex |
|
|
149
|
+
| `state-react-sync` | Rust 상태와 React 상태 동기화 패턴 |
|
|
150
|
+
|
|
151
|
+
### 5. React 통합 패턴 (MEDIUM-HIGH)
|
|
152
|
+
|
|
153
|
+
| 규칙 | 설명 |
|
|
154
|
+
|------|------|
|
|
155
|
+
| `react-invoke-hook` | useEffect + invoke 패턴, 정리(cleanup) 필수 |
|
|
156
|
+
| `react-event-listener` | listen/unlisten 라이프사이클 관리 |
|
|
157
|
+
| `react-file-src` | convertFileSrc()로 로컬 파일 직접 렌더링 |
|
|
158
|
+
| `react-error-boundary` | invoke 실패에 대한 에러 바운더리 |
|
|
159
|
+
| `react-optimistic-update` | useOptimistic으로 IPC 대기 시간 마스킹 |
|
|
160
|
+
|
|
161
|
+
### 6. 플러그인 패턴 (MEDIUM)
|
|
162
|
+
|
|
163
|
+
| 규칙 | 설명 |
|
|
164
|
+
|------|------|
|
|
165
|
+
| `plugin-permission-scope` | 플러그인별 최소 권한 + Scope 설정 |
|
|
166
|
+
| `plugin-lifecycle` | setup/on_event/on_drop 라이프사이클 관리 |
|
|
167
|
+
| `plugin-mobile-compat` | 모바일 호환성 확인 (Android/iOS) |
|
|
168
|
+
|
|
169
|
+
### 7. 배포 최적화 (MEDIUM)
|
|
170
|
+
|
|
171
|
+
| 규칙 | 설명 |
|
|
172
|
+
|------|------|
|
|
173
|
+
| `deploy-signing` | 코드 서명 필수 (macOS/Windows) |
|
|
174
|
+
| `deploy-updater` | 자동 업데이트 서명 키 관리 |
|
|
175
|
+
| `deploy-ci-pipeline` | GitHub Actions 멀티 플랫폼 빌드 |
|
|
176
|
+
|
|
177
|
+
### 8. Re-render/JS 성능 (LOW-MEDIUM)
|
|
178
|
+
|
|
179
|
+
| 규칙 | 설명 |
|
|
180
|
+
|------|------|
|
|
181
|
+
| `perf-functional-setstate` | 함수형 setState로 안정적 콜백 |
|
|
182
|
+
| `perf-lazy-state-init` | 비싼 초기값은 함수로 useState에 전달 |
|
|
183
|
+
| `perf-derived-state` | 파생 boolean 구독, raw 값 구독 회피 |
|
|
184
|
+
| `perf-index-maps` | 반복 조회용 Map 빌드 |
|
|
185
|
+
|
|
186
|
+
</rules>
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
<patterns>
|
|
191
|
+
|
|
192
|
+
## 핵심 패턴
|
|
193
|
+
|
|
194
|
+
### IPC 최적화: 배치 커맨드
|
|
195
|
+
|
|
196
|
+
```rust
|
|
197
|
+
// ❌ 프론트엔드에서 N번 호출
|
|
198
|
+
// for (item of items) await invoke('process', { item })
|
|
199
|
+
|
|
200
|
+
// ✅ 배치 처리 (1번 호출)
|
|
201
|
+
#[tauri::command]
|
|
202
|
+
fn process_batch(items: Vec<String>) -> Result<Vec<String>, String> {
|
|
203
|
+
items.iter().map(|item| process_item(item)).collect()
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### IPC 최적화: Channel 스트리밍
|
|
208
|
+
|
|
209
|
+
```rust
|
|
210
|
+
use tauri::ipc::Channel;
|
|
211
|
+
|
|
212
|
+
// ❌ Events로 대용량 스트리밍 (느림)
|
|
213
|
+
#[tauri::command]
|
|
214
|
+
async fn download(app: AppHandle, url: String) {
|
|
215
|
+
for chunk in download_stream(&url) {
|
|
216
|
+
app.emit("progress", chunk).unwrap();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ✅ Channel로 스트리밍 (빠름)
|
|
221
|
+
#[tauri::command]
|
|
222
|
+
async fn download(url: String, on_progress: Channel<u32>) -> Result<(), String> {
|
|
223
|
+
for (i, _chunk) in download_stream(&url).enumerate() {
|
|
224
|
+
on_progress.send(i as u32).unwrap();
|
|
225
|
+
}
|
|
226
|
+
Ok(())
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
// JavaScript
|
|
232
|
+
import { invoke, Channel } from '@tauri-apps/api/core';
|
|
233
|
+
|
|
234
|
+
const onProgress = new Channel<number>();
|
|
235
|
+
onProgress.onmessage = (bytes) => updateProgressBar(bytes);
|
|
236
|
+
await invoke('download', { url, onProgress });
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### IPC 최적화: 바이너리 응답
|
|
240
|
+
|
|
241
|
+
```rust
|
|
242
|
+
use tauri::ipc::Response;
|
|
243
|
+
|
|
244
|
+
// ❌ JSON 직렬화 (느림, 크기 증가)
|
|
245
|
+
#[tauri::command]
|
|
246
|
+
fn get_image() -> Result<Vec<u8>, String> {
|
|
247
|
+
std::fs::read("/path/to/image.png").map_err(|e| e.to_string())
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ✅ Raw 바이너리 응답 (직렬화 우회)
|
|
251
|
+
#[tauri::command]
|
|
252
|
+
fn get_image() -> Result<Response, String> {
|
|
253
|
+
let bytes = std::fs::read("/path/to/image.png").map_err(|e| e.to_string())?;
|
|
254
|
+
Ok(Response::new(bytes))
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 보안: 최소 권한 Capability
|
|
259
|
+
|
|
260
|
+
```json
|
|
261
|
+
{
|
|
262
|
+
"identifier": "main-window",
|
|
263
|
+
"description": "메인 윈도우 최소 권한",
|
|
264
|
+
"windows": ["main"],
|
|
265
|
+
"permissions": [
|
|
266
|
+
"core:window:allow-close",
|
|
267
|
+
"core:window:allow-minimize",
|
|
268
|
+
"fs:allow-read"
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
```toml
|
|
274
|
+
# ❌ 와일드카드 (위험)
|
|
275
|
+
[[scope.allow]]
|
|
276
|
+
path = "/*"
|
|
277
|
+
|
|
278
|
+
# ✅ 특정 경로만 (안전)
|
|
279
|
+
[[scope.allow]]
|
|
280
|
+
path = "$APPDATA/my-app/data/**"
|
|
281
|
+
|
|
282
|
+
[[scope.deny]]
|
|
283
|
+
path = "$HOME/.ssh/**"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 상태 관리: Mutex + 타입 별칭
|
|
287
|
+
|
|
288
|
+
```rust
|
|
289
|
+
use std::sync::Mutex;
|
|
290
|
+
use tauri::State;
|
|
291
|
+
|
|
292
|
+
// ✅ 타입 별칭으로 불일치 방지
|
|
293
|
+
type AppState = Mutex<AppStateInner>;
|
|
294
|
+
|
|
295
|
+
#[derive(Default)]
|
|
296
|
+
struct AppStateInner {
|
|
297
|
+
counter: u32,
|
|
298
|
+
users: Vec<String>,
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
#[tauri::command]
|
|
302
|
+
fn increment(state: State<'_, AppState>) -> u32 {
|
|
303
|
+
let mut s = state.lock().unwrap();
|
|
304
|
+
s.counter += 1;
|
|
305
|
+
s.counter
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### React 통합: invoke Hook 패턴
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
import { invoke } from '@tauri-apps/api/core';
|
|
313
|
+
import { listen } from '@tauri-apps/api/event';
|
|
314
|
+
|
|
315
|
+
// ✅ 이벤트 리스너 정리 필수
|
|
316
|
+
function StatusMonitor() {
|
|
317
|
+
const [status, setStatus] = useState('idle');
|
|
318
|
+
|
|
319
|
+
useEffect(() => {
|
|
320
|
+
let unlisten: (() => void) | undefined;
|
|
321
|
+
|
|
322
|
+
const setup = async () => {
|
|
323
|
+
unlisten = await listen('status-changed', (event) => {
|
|
324
|
+
setStatus(event.payload as string);
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
setup();
|
|
328
|
+
|
|
329
|
+
return () => { unlisten?.(); };
|
|
330
|
+
}, []);
|
|
331
|
+
|
|
332
|
+
return <div>Status: {status}</div>;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// ✅ invoke + 에러 처리
|
|
336
|
+
function FileReader({ path }: { path: string }) {
|
|
337
|
+
const [content, setContent] = useState('');
|
|
338
|
+
const [error, setError] = useState<string | null>(null);
|
|
339
|
+
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
invoke<string>('read_file', { path })
|
|
342
|
+
.then(setContent)
|
|
343
|
+
.catch((err) => setError(String(err)));
|
|
344
|
+
}, [path]);
|
|
345
|
+
|
|
346
|
+
if (error) return <div>Error: {error}</div>;
|
|
347
|
+
return <pre>{content}</pre>;
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### 번들 최적화: Cargo 프로필
|
|
352
|
+
|
|
353
|
+
```toml
|
|
354
|
+
# src-tauri/Cargo.toml
|
|
355
|
+
[profile.release]
|
|
356
|
+
codegen-units = 1 # LLVM 최적화 극대화
|
|
357
|
+
lto = true # 링크 타임 최적화
|
|
358
|
+
opt-level = "s" # 크기 우선 최적화
|
|
359
|
+
panic = "abort" # 패닉 핸들러 제거
|
|
360
|
+
strip = true # 디버그 심볼 제거
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### 에러 처리: 구조화된 에러
|
|
364
|
+
|
|
365
|
+
```rust
|
|
366
|
+
#[derive(Debug, thiserror::Error)]
|
|
367
|
+
enum AppError {
|
|
368
|
+
#[error("File not found: {0}")]
|
|
369
|
+
FileNotFound(String),
|
|
370
|
+
#[error("Permission denied")]
|
|
371
|
+
PermissionDenied,
|
|
372
|
+
#[error(transparent)]
|
|
373
|
+
Io(#[from] std::io::Error),
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
impl serde::Serialize for AppError {
|
|
377
|
+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
378
|
+
where S: serde::ser::Serializer {
|
|
379
|
+
serializer.serialize_str(self.to_string().as_ref())
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
#[tauri::command]
|
|
384
|
+
fn read_file(path: String) -> Result<String, AppError> {
|
|
385
|
+
std::fs::read_to_string(&path).map_err(|_| AppError::FileNotFound(path))
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
</patterns>
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
<tauri_specific>
|
|
394
|
+
|
|
395
|
+
## Tauri v2 특화 패턴
|
|
396
|
+
|
|
397
|
+
### Commands vs Events vs Channels
|
|
398
|
+
|
|
399
|
+
| 측면 | Commands | Events | Channels |
|
|
400
|
+
|------|----------|--------|----------|
|
|
401
|
+
| **프로토콜** | JSON-RPC | 단방향 메시지 | 스트리밍 |
|
|
402
|
+
| **방향** | Frontend -> Rust | 양방향 | Rust -> Frontend |
|
|
403
|
+
| **응답** | 필수 | 없음 | 연속 |
|
|
404
|
+
| **처리량** | 보통 | 낮음 | 높음 |
|
|
405
|
+
| **사용 사례** | 함수 호출 | 알림, 상태 변경 | 파일 다운로드, 진행률 |
|
|
406
|
+
|
|
407
|
+
### Commands 인자 규칙
|
|
408
|
+
|
|
409
|
+
```rust
|
|
410
|
+
// ❌ camelCase 자동 변환 혼동
|
|
411
|
+
#[tauri::command]
|
|
412
|
+
fn process_data(user_id: i32) {} // JS: invoke('process_data', { userId: 1 })
|
|
413
|
+
|
|
414
|
+
// ✅ 명시적 snake_case 유지
|
|
415
|
+
#[tauri::command(rename_all = "snake_case")]
|
|
416
|
+
fn process_data(user_id: i32) {} // JS: invoke('process_data', { user_id: 1 })
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### 특수 파라미터 자동 주입
|
|
420
|
+
|
|
421
|
+
```rust
|
|
422
|
+
use tauri::{AppHandle, State, WebviewWindow};
|
|
423
|
+
use tauri::ipc::Request;
|
|
424
|
+
|
|
425
|
+
#[tauri::command]
|
|
426
|
+
fn my_command(
|
|
427
|
+
app: AppHandle, // 앱 핸들 (자동 주입)
|
|
428
|
+
window: WebviewWindow, // 현재 윈도우 (자동 주입)
|
|
429
|
+
state: State<'_, AppState>, // 상태 (자동 주입)
|
|
430
|
+
request: Request, // Raw IPC 요청 (자동 주입)
|
|
431
|
+
user_input: String, // 사용자 인자 (invoke에서 전달)
|
|
432
|
+
) -> Result<String, String> {
|
|
433
|
+
Ok(format!("Hello from {}", window.label()))
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 모듈 구조화
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
src-tauri/src/
|
|
441
|
+
├── main.rs (또는 lib.rs)
|
|
442
|
+
├── commands/
|
|
443
|
+
│ ├── mod.rs
|
|
444
|
+
│ ├── auth.rs
|
|
445
|
+
│ ├── files.rs
|
|
446
|
+
│ └── settings.rs
|
|
447
|
+
└── state.rs
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
```rust
|
|
451
|
+
// commands/mod.rs
|
|
452
|
+
pub mod auth;
|
|
453
|
+
pub mod files;
|
|
454
|
+
|
|
455
|
+
// lib.rs
|
|
456
|
+
mod commands;
|
|
457
|
+
mod state;
|
|
458
|
+
|
|
459
|
+
tauri::Builder::default()
|
|
460
|
+
.manage(Mutex::new(state::AppState::default()))
|
|
461
|
+
.invoke_handler(tauri::generate_handler![
|
|
462
|
+
commands::auth::login,
|
|
463
|
+
commands::auth::logout,
|
|
464
|
+
commands::files::read_file,
|
|
465
|
+
])
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 보안 파일 구조
|
|
469
|
+
|
|
470
|
+
```
|
|
471
|
+
src-tauri/
|
|
472
|
+
├── capabilities/
|
|
473
|
+
│ ├── main-window.json # 메인 UI 권한
|
|
474
|
+
│ ├── worker-window.json # 백그라운드 권한
|
|
475
|
+
│ └── admin.json # 관리자 권한
|
|
476
|
+
├── permissions/
|
|
477
|
+
│ ├── fs.toml # 파일시스템 권한
|
|
478
|
+
│ └── http.toml # HTTP 권한
|
|
479
|
+
└── tauri.conf.json
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### 자동 업데이트 설정
|
|
483
|
+
|
|
484
|
+
```json
|
|
485
|
+
{
|
|
486
|
+
"bundle": { "createUpdaterArtifacts": true },
|
|
487
|
+
"plugins": {
|
|
488
|
+
"updater": {
|
|
489
|
+
"pubkey": "PUBLIC_KEY",
|
|
490
|
+
"endpoints": ["https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}"]
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
import { check } from '@tauri-apps/plugin-updater';
|
|
498
|
+
import { relaunch } from '@tauri-apps/plugin-process';
|
|
499
|
+
|
|
500
|
+
const update = await check();
|
|
501
|
+
if (update) {
|
|
502
|
+
await update.downloadAndInstall();
|
|
503
|
+
await relaunch();
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
</tauri_specific>
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
<usage>
|
|
512
|
+
|
|
513
|
+
## 사용법
|
|
514
|
+
|
|
515
|
+
**상세 규칙 및 예시:**
|
|
516
|
+
|
|
517
|
+
```
|
|
518
|
+
rules/ipc-batch-commands.md
|
|
519
|
+
rules/ipc-channel-streaming.md
|
|
520
|
+
rules/security-least-privilege.md
|
|
521
|
+
rules/bundle-cargo-profile.md
|
|
522
|
+
rules/state-mutex-pattern.md
|
|
523
|
+
rules/react-invoke-hook.md
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
각 규칙 파일 포함 내용:
|
|
527
|
+
- 중요한 이유 설명
|
|
528
|
+
- ❌ 잘못된 코드 예시 + 설명
|
|
529
|
+
- ✅ 올바른 코드 예시 + 설명
|
|
530
|
+
- 추가 컨텍스트 및 참조
|
|
531
|
+
|
|
532
|
+
</usage>
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
<references>
|
|
537
|
+
|
|
538
|
+
## 참고 자료
|
|
539
|
+
|
|
540
|
+
### Tauri v2 공식 문서
|
|
541
|
+
1. [Tauri Overview](https://tauri.app/start/)
|
|
542
|
+
2. [Calling Rust from Frontend](https://tauri.app/develop/calling-rust/)
|
|
543
|
+
3. [Calling Frontend from Rust](https://tauri.app/develop/calling-frontend/)
|
|
544
|
+
4. [Inter-Process Communication](https://tauri.app/concept/inter-process-communication/)
|
|
545
|
+
5. [State Management](https://tauri.app/develop/state-management/)
|
|
546
|
+
6. [Security Overview](https://tauri.app/security/)
|
|
547
|
+
7. [Capabilities](https://tauri.app/security/capabilities/)
|
|
548
|
+
8. [Permissions](https://tauri.app/security/permissions/)
|
|
549
|
+
9. [Configuration](https://tauri.app/develop/configuration/)
|
|
550
|
+
10. [Plugin Development](https://tauri.app/develop/plugins/)
|
|
551
|
+
11. [App Size Optimization](https://tauri.app/concept/size/)
|
|
552
|
+
12. [Distribution](https://tauri.app/distribute/)
|
|
553
|
+
13. [Updater Plugin](https://tauri.app/plugin/updater/)
|
|
554
|
+
14. [Debug Guide](https://tauri.app/develop/debug/)
|
|
555
|
+
15. [Migration from v1](https://tauri.app/start/migrate/from-tauri-1/)
|
|
556
|
+
|
|
557
|
+
### React 19
|
|
558
|
+
16. [React 공식 문서](https://react.dev)
|
|
559
|
+
17. [React use() API](https://react.dev/reference/react/use)
|
|
560
|
+
18. [React useOptimistic](https://react.dev/reference/react/useOptimistic)
|
|
561
|
+
19. [React Compiler](https://react.dev/learn/react-compiler)
|
|
562
|
+
|
|
563
|
+
### TypeScript 타입 안전성
|
|
564
|
+
20. [tauri-specta](https://github.com/specta-rs/tauri-specta)
|
|
565
|
+
21. [TauRPC](https://github.com/MatsDK/TauRPC)
|
|
566
|
+
|
|
567
|
+
### 외부 자료
|
|
568
|
+
22. [Tauri v2 + React 19 Template](https://github.com/dannysmith/tauri-template)
|
|
569
|
+
23. [Tauri Plugins Workspace](https://github.com/tauri-apps/plugins-workspace)
|
|
570
|
+
|
|
571
|
+
</references>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Avoid Barrel Imports
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents importing entire library
|
|
5
|
+
tags: bundle, imports, tree-shaking, barrel, frontend
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Barrel Import 회피, 직접 Import 사용
|
|
9
|
+
|
|
10
|
+
## 왜 중요한가
|
|
11
|
+
|
|
12
|
+
많은 라이브러리(특히 아이콘 라이브러리)는 **barrel file**(모든 export를 모아놓은 index 파일)을 제공합니다. 하나의 아이콘만 필요해도 전체 라이브러리가 번들에 포함되어 **수 MB의 불필요한 코드**가 추가될 수 있습니다.
|
|
13
|
+
|
|
14
|
+
## ❌ 잘못된 패턴
|
|
15
|
+
|
|
16
|
+
**Barrel file에서 import (전체 라이브러리 번들링):**
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
// ❌ lucide-react 전체 (~2MB) 번들에 포함
|
|
20
|
+
import { Home, Settings, User } from 'lucide-react'
|
|
21
|
+
|
|
22
|
+
// ❌ @mui/icons-material 전체 (~3MB) 번들에 포함
|
|
23
|
+
import { HomeOutlined, SettingsOutlined } from '@mui/icons-material'
|
|
24
|
+
|
|
25
|
+
// ❌ react-icons 전체 (~1.5MB) 번들에 포함
|
|
26
|
+
import { FaHome, FaUser } from 'react-icons/fa'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**번들 분석 결과:**
|
|
30
|
+
```
|
|
31
|
+
lucide-react: 2.1 MB (전체 아이콘 셋)
|
|
32
|
+
@mui/icons-material: 3.5 MB (전체 Material 아이콘)
|
|
33
|
+
react-icons: 1.8 MB (전체 Font Awesome 아이콘)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## ✅ 올바른 패턴
|
|
37
|
+
|
|
38
|
+
**직접 경로로 개별 모듈 import:**
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// ✅ 필요한 아이콘만 번들에 포함 (~5KB per icon)
|
|
42
|
+
import Home from 'lucide-react/dist/esm/icons/home'
|
|
43
|
+
import Settings from 'lucide-react/dist/esm/icons/settings'
|
|
44
|
+
import User from 'lucide-react/dist/esm/icons/user'
|
|
45
|
+
|
|
46
|
+
// ✅ @mui/icons-material 개별 import
|
|
47
|
+
import HomeOutlined from '@mui/icons-material/HomeOutlined'
|
|
48
|
+
import SettingsOutlined from '@mui/icons-material/SettingsOutlined'
|
|
49
|
+
|
|
50
|
+
// ✅ react-icons 개별 import
|
|
51
|
+
import { FaHome } from 'react-icons/fa/index.esm.js'
|
|
52
|
+
import { FaUser } from 'react-icons/fa/index.esm.js'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**번들 분석 결과:**
|
|
56
|
+
```
|
|
57
|
+
lucide-react: 15 KB (3개 아이콘만)
|
|
58
|
+
@mui/icons-material: 10 KB (2개 아이콘만)
|
|
59
|
+
react-icons: 8 KB (2개 아이콘만)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Vite 설정으로 자동화 (추가 옵션):**
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// vite.config.ts
|
|
66
|
+
import { defineConfig } from 'vite'
|
|
67
|
+
|
|
68
|
+
export default defineConfig({
|
|
69
|
+
resolve: {
|
|
70
|
+
alias: {
|
|
71
|
+
// lucide-react barrel import 방지
|
|
72
|
+
'lucide-react': 'lucide-react/dist/esm/icons'
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
optimizeDeps: {
|
|
76
|
+
include: ['lucide-react']
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 추가 컨텍스트
|
|
82
|
+
|
|
83
|
+
**영향 받는 주요 라이브러리:**
|
|
84
|
+
|
|
85
|
+
| 라이브러리 | Barrel Import | Direct Import | 크기 차이 |
|
|
86
|
+
|-----------|---------------|---------------|-----------|
|
|
87
|
+
| `lucide-react` | `from 'lucide-react'` | `from 'lucide-react/dist/esm/icons/icon-name'` | ~2MB → ~5KB/icon |
|
|
88
|
+
| `@mui/icons-material` | `from '@mui/icons-material'` | `from '@mui/icons-material/IconName'` | ~3.5MB → ~5KB/icon |
|
|
89
|
+
| `react-icons` | `from 'react-icons/fa'` | `from 'react-icons/fa/index.esm.js'` | ~1.8MB → ~4KB/icon |
|
|
90
|
+
| `heroicons` | `from '@heroicons/react/24/outline'` | `from '@heroicons/react/24/outline/IconName'` | ~500KB → ~2KB/icon |
|
|
91
|
+
| `phosphor-react` | `from 'phosphor-react'` | `from 'phosphor-react/dist/icons/IconName'` | ~1.2MB → ~3KB/icon |
|
|
92
|
+
|
|
93
|
+
**Tree-shaking이 작동하지 않는 이유:**
|
|
94
|
+
|
|
95
|
+
1. **Re-export Chain**: barrel file이 모든 모듈을 re-export
|
|
96
|
+
2. **Side Effects**: 일부 라이브러리는 초기화 코드 실행
|
|
97
|
+
3. **CommonJS**: ESM이 아닌 경우 tree-shaking 불가
|
|
98
|
+
|
|
99
|
+
**IDE 자동완성 유지:**
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// 타입 정의만 barrel에서 import (번들 영향 없음)
|
|
103
|
+
import type { LucideIcon } from 'lucide-react'
|
|
104
|
+
|
|
105
|
+
// 실제 컴포넌트는 직접 import
|
|
106
|
+
import Home from 'lucide-react/dist/esm/icons/home'
|
|
107
|
+
|
|
108
|
+
const icon: LucideIcon = Home
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**번들 분석 도구로 확인:**
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Vite Bundle Visualizer
|
|
115
|
+
npm install -D rollup-plugin-visualizer
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// vite.config.ts
|
|
120
|
+
import { visualizer } from 'rollup-plugin-visualizer'
|
|
121
|
+
|
|
122
|
+
export default defineConfig({
|
|
123
|
+
plugins: [
|
|
124
|
+
visualizer({
|
|
125
|
+
open: true,
|
|
126
|
+
gzipSize: true,
|
|
127
|
+
brotliSize: true
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
})
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**참고:**
|
|
134
|
+
- Vite Tree-shaking: [Build Optimizations](https://vitejs.dev/guide/features.html#build-optimizations)
|
|
135
|
+
- webpack Bundle Analyzer: [Documentation](https://github.com/webpack-contrib/webpack-bundle-analyzer)
|
|
136
|
+
|
|
137
|
+
**영향도:**
|
|
138
|
+
- 크기: HIGH (아이콘 라이브러리 사용 시 1-3MB 감소)
|
|
139
|
+
- 개발 경험: MEDIUM (import 경로가 길어짐)
|
|
140
|
+
- 런타임 성능: POSITIVE (초기 로드 시간 감소)
|