@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
package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-remove-unused-commands.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Remove Unused Tauri Commands
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: reduces bundle by excluding unused commands
|
|
5
|
+
tags: bundle, commands, tauri-build, optimization, v2.4
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 미사용 Tauri 커맨드 자동 제거
|
|
9
|
+
|
|
10
|
+
## 왜 중요한가
|
|
11
|
+
|
|
12
|
+
Tauri v2.4부터 빌드 시스템이 프론트엔드 코드를 정적 분석하여 **실제로 사용되지 않는 커맨드를 바이너리에서 자동으로 제거**할 수 있습니다. 이는 특히 많은 커맨드를 정의했지만 일부만 사용하는 앱에서 효과적입니다.
|
|
13
|
+
|
|
14
|
+
## ❌ 잘못된 패턴
|
|
15
|
+
|
|
16
|
+
**기본 설정 (tauri.config.json):**
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"build": {
|
|
21
|
+
"beforeDevCommand": "npm run dev",
|
|
22
|
+
"devPath": "http://localhost:1420",
|
|
23
|
+
"beforeBuildCommand": "npm run build",
|
|
24
|
+
"frontendDist": "../dist"
|
|
25
|
+
// removeUnusedCommands 설정 없음
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Rust 코드에 정의된 커맨드:**
|
|
31
|
+
|
|
32
|
+
```rust
|
|
33
|
+
// src-tauri/src/main.rs
|
|
34
|
+
#[tauri::command]
|
|
35
|
+
fn greet(name: &str) -> String {
|
|
36
|
+
format!("Hello, {}!", name)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#[tauri::command]
|
|
40
|
+
fn calculate(a: i32, b: i32) -> i32 {
|
|
41
|
+
a + b
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#[tauri::command]
|
|
45
|
+
fn get_system_info() -> String {
|
|
46
|
+
// 복잡한 로직...
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fn main() {
|
|
50
|
+
tauri::Builder::default()
|
|
51
|
+
.invoke_handler(tauri::generate_handler![
|
|
52
|
+
greet,
|
|
53
|
+
calculate,
|
|
54
|
+
get_system_info // 프론트엔드에서 사용하지 않음!
|
|
55
|
+
])
|
|
56
|
+
.run(tauri::generate_context!())
|
|
57
|
+
.expect("error while running tauri application");
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**프론트엔드 코드:**
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// src/App.tsx
|
|
65
|
+
import { invoke } from '@tauri-apps/api/core'
|
|
66
|
+
|
|
67
|
+
function App() {
|
|
68
|
+
const handleClick = async () => {
|
|
69
|
+
await invoke('greet', { name: 'World' })
|
|
70
|
+
await invoke('calculate', { a: 1, b: 2 })
|
|
71
|
+
// get_system_info는 호출하지 않음
|
|
72
|
+
}
|
|
73
|
+
return <button onClick={handleClick}>Call</button>
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**문제:**
|
|
78
|
+
- `get_system_info` 커맨드가 바이너리에 포함됨
|
|
79
|
+
- 미사용 커맨드의 의존성도 함께 번들에 포함
|
|
80
|
+
|
|
81
|
+
## ✅ 올바른 패턴
|
|
82
|
+
|
|
83
|
+
**tauri.config.json에 removeUnusedCommands 활성화:**
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"build": {
|
|
88
|
+
"beforeDevCommand": "npm run dev",
|
|
89
|
+
"devPath": "http://localhost:1420",
|
|
90
|
+
"beforeBuildCommand": "npm run build",
|
|
91
|
+
"frontendDist": "../dist",
|
|
92
|
+
"removeUnusedCommands": true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Cargo.toml 버전 확인:**
|
|
98
|
+
|
|
99
|
+
```toml
|
|
100
|
+
[build-dependencies]
|
|
101
|
+
# tauri-build 2.1.0 이상 필요
|
|
102
|
+
tauri-build = "^2.1"
|
|
103
|
+
|
|
104
|
+
[dependencies]
|
|
105
|
+
# tauri 2.4.0 이상 필요
|
|
106
|
+
tauri = "^2.4"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**빌드 로그 확인:**
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npm run tauri build
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**출력:**
|
|
116
|
+
```
|
|
117
|
+
[INFO] Analyzing frontend code for command usage...
|
|
118
|
+
[INFO] Found commands: greet, calculate
|
|
119
|
+
[INFO] Removing unused commands: get_system_info
|
|
120
|
+
[INFO] Building optimized bundle...
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 추가 컨텍스트
|
|
124
|
+
|
|
125
|
+
**요구 버전:**
|
|
126
|
+
- Tauri: **2.4.0 이상**
|
|
127
|
+
- tauri-build: **2.1.0 이상**
|
|
128
|
+
|
|
129
|
+
**작동 원리:**
|
|
130
|
+
1. `tauri-build`가 프론트엔드 번들을 정적 분석
|
|
131
|
+
2. `invoke('command_name', ...)`로 호출되는 커맨드 목록 추출
|
|
132
|
+
3. `generate_handler!` 매크로에서 미사용 커맨드 제거
|
|
133
|
+
4. 바이너리 컴파일 시 미사용 코드 제외
|
|
134
|
+
|
|
135
|
+
**제약 사항:**
|
|
136
|
+
- 동적 커맨드 이름은 감지 불가:
|
|
137
|
+
```typescript
|
|
138
|
+
// ❌ 감지 안됨
|
|
139
|
+
const cmd = 'greet'
|
|
140
|
+
invoke(cmd, { name: 'World' })
|
|
141
|
+
```
|
|
142
|
+
- 정적 문자열만 감지:
|
|
143
|
+
```typescript
|
|
144
|
+
// ✅ 감지됨
|
|
145
|
+
invoke('greet', { name: 'World' })
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**효과:**
|
|
149
|
+
- 미사용 커맨드가 많을수록 효과 증가
|
|
150
|
+
- 5-10개 커맨드 중 2-3개만 사용: ~10-20% 크기 감소
|
|
151
|
+
- 특히 무거운 의존성이 있는 커맨드 제거 시 효과적
|
|
152
|
+
|
|
153
|
+
**참고:**
|
|
154
|
+
- Tauri v2.4 Release Notes: [Remove Unused Commands](https://v2.tauri.app/blog/tauri-2-4/#remove-unused-commands)
|
|
155
|
+
- tauri-build Documentation: [Command Analysis](https://docs.rs/tauri-build/latest/tauri_build/)
|
|
156
|
+
|
|
157
|
+
**영향도:**
|
|
158
|
+
- 크기: MEDIUM (10-20% 감소 가능)
|
|
159
|
+
- 빌드 시간: NEUTRAL (분석 오버헤드 미미)
|
|
160
|
+
- 개발 경험: POSITIVE (자동 최적화)
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# GitHub Actions 멀티 플랫폼 빌드
|
|
2
|
+
|
|
3
|
+
## 왜 중요한가
|
|
4
|
+
|
|
5
|
+
Tauri 앱을 수동으로 빌드하면 플랫폼별 환경 설정이 복잡하고 시간이 오래 걸립니다. GitHub Actions로 자동화하면 태그 푸시만으로 Linux/macOS/Windows 빌드를 병렬로 진행하고, 서명/공증/릴리스까지 원스톱으로 처리할 수 있습니다.
|
|
6
|
+
|
|
7
|
+
## ❌ 잘못된 패턴
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# ❌ 수동 빌드 (플랫폼마다 반복)
|
|
11
|
+
# macOS
|
|
12
|
+
pnpm tauri build
|
|
13
|
+
codesign ...
|
|
14
|
+
notarize ...
|
|
15
|
+
|
|
16
|
+
# Windows (별도 PC에서)
|
|
17
|
+
pnpm tauri build
|
|
18
|
+
signtool ...
|
|
19
|
+
|
|
20
|
+
# Linux (별도 환경에서)
|
|
21
|
+
pnpm tauri build
|
|
22
|
+
|
|
23
|
+
# 릴리스 수동 업로드
|
|
24
|
+
gh release upload v1.0.0 ./target/release/bundle/**/*
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**문제점:**
|
|
28
|
+
- 플랫폼마다 수동 빌드 필요 (시간 소요)
|
|
29
|
+
- 환경 설정 불일치로 빌드 실패 위험
|
|
30
|
+
- 서명/공증 단계 누락 가능
|
|
31
|
+
- 릴리스 업로드 실수
|
|
32
|
+
|
|
33
|
+
## ✅ 올바른 패턴
|
|
34
|
+
|
|
35
|
+
### GitHub Actions Workflow (전체 파이프라인)
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
name: Release
|
|
39
|
+
on:
|
|
40
|
+
push:
|
|
41
|
+
tags:
|
|
42
|
+
- 'v*'
|
|
43
|
+
|
|
44
|
+
jobs:
|
|
45
|
+
build:
|
|
46
|
+
permissions:
|
|
47
|
+
contents: write
|
|
48
|
+
strategy:
|
|
49
|
+
fail-fast: false
|
|
50
|
+
matrix:
|
|
51
|
+
include:
|
|
52
|
+
- platform: macos-latest
|
|
53
|
+
target: aarch64-apple-darwin
|
|
54
|
+
- platform: macos-latest
|
|
55
|
+
target: x86_64-apple-darwin
|
|
56
|
+
- platform: windows-latest
|
|
57
|
+
target: x86_64-pc-windows-msvc
|
|
58
|
+
- platform: ubuntu-22.04
|
|
59
|
+
target: x86_64-unknown-linux-gnu
|
|
60
|
+
|
|
61
|
+
runs-on: ${{ matrix.platform }}
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/checkout@v4
|
|
64
|
+
|
|
65
|
+
- uses: pnpm/action-setup@v2
|
|
66
|
+
with:
|
|
67
|
+
version: 8
|
|
68
|
+
|
|
69
|
+
- uses: actions/setup-node@v4
|
|
70
|
+
with:
|
|
71
|
+
node-version: 20
|
|
72
|
+
cache: pnpm
|
|
73
|
+
|
|
74
|
+
- name: Install Rust
|
|
75
|
+
uses: dtolnay/rust-toolchain@stable
|
|
76
|
+
with:
|
|
77
|
+
targets: ${{ matrix.target }}
|
|
78
|
+
|
|
79
|
+
- name: Install Linux dependencies
|
|
80
|
+
if: matrix.platform == 'ubuntu-22.04'
|
|
81
|
+
run: |
|
|
82
|
+
sudo apt-get update
|
|
83
|
+
sudo apt-get install -y \
|
|
84
|
+
libwebkit2gtk-4.1-dev \
|
|
85
|
+
libappindicator3-dev \
|
|
86
|
+
librsvg2-dev \
|
|
87
|
+
patchelf
|
|
88
|
+
|
|
89
|
+
- name: Install frontend dependencies
|
|
90
|
+
run: pnpm install
|
|
91
|
+
|
|
92
|
+
# macOS 서명 설정
|
|
93
|
+
- name: Import macOS certificate
|
|
94
|
+
if: matrix.platform == 'macos-latest'
|
|
95
|
+
env:
|
|
96
|
+
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
|
|
97
|
+
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
|
|
98
|
+
run: |
|
|
99
|
+
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
|
100
|
+
security create-keychain -p actions temp.keychain
|
|
101
|
+
security default-keychain -s temp.keychain
|
|
102
|
+
security unlock-keychain -p actions temp.keychain
|
|
103
|
+
security import certificate.p12 -k temp.keychain -P $MACOS_CERTIFICATE_PWD -T /usr/bin/codesign
|
|
104
|
+
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k actions temp.keychain
|
|
105
|
+
|
|
106
|
+
# 빌드 + 서명
|
|
107
|
+
- name: Build app
|
|
108
|
+
env:
|
|
109
|
+
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
110
|
+
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
|
111
|
+
run: pnpm tauri build --target ${{ matrix.target }}
|
|
112
|
+
|
|
113
|
+
# macOS 공증
|
|
114
|
+
- name: Notarize macOS app
|
|
115
|
+
if: matrix.platform == 'macos-latest'
|
|
116
|
+
env:
|
|
117
|
+
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
118
|
+
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
119
|
+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
120
|
+
run: |
|
|
121
|
+
xcrun notarytool submit \
|
|
122
|
+
./target/${{ matrix.target }}/release/bundle/macos/*.app.tar.gz \
|
|
123
|
+
--apple-id "$APPLE_ID" \
|
|
124
|
+
--password "$APPLE_PASSWORD" \
|
|
125
|
+
--team-id "$APPLE_TEAM_ID" \
|
|
126
|
+
--wait
|
|
127
|
+
xcrun stapler staple ./target/${{ matrix.target }}/release/bundle/macos/*.app
|
|
128
|
+
|
|
129
|
+
# Windows 서명
|
|
130
|
+
- name: Sign Windows app
|
|
131
|
+
if: matrix.platform == 'windows-latest'
|
|
132
|
+
env:
|
|
133
|
+
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
|
134
|
+
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
135
|
+
run: |
|
|
136
|
+
echo $env:WINDOWS_CERTIFICATE | Out-File -FilePath certificate.txt
|
|
137
|
+
certutil -decode certificate.txt certificate.pfx
|
|
138
|
+
Get-ChildItem ./target/${{ matrix.target }}/release/bundle/msi/*.msi | ForEach-Object {
|
|
139
|
+
signtool sign /f certificate.pfx /p $env:WINDOWS_CERTIFICATE_PASSWORD /tr http://timestamp.digicert.com /td sha256 /fd sha256 $_
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
# GitHub Release 업로드
|
|
143
|
+
- name: Upload to GitHub Release
|
|
144
|
+
uses: softprops/action-gh-release@v1
|
|
145
|
+
with:
|
|
146
|
+
files: |
|
|
147
|
+
./target/${{ matrix.target }}/release/bundle/macos/*.dmg
|
|
148
|
+
./target/${{ matrix.target }}/release/bundle/msi/*.msi
|
|
149
|
+
./target/${{ matrix.target }}/release/bundle/appimage/*.AppImage
|
|
150
|
+
./target/${{ matrix.target }}/release/bundle/deb/*.deb
|
|
151
|
+
draft: true
|
|
152
|
+
prerelease: false
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### GitHub Secrets 설정 가이드
|
|
156
|
+
|
|
157
|
+
**필수 Secrets (Repository → Settings → Secrets):**
|
|
158
|
+
|
|
159
|
+
| Secret 이름 | 설명 | 획득 방법 |
|
|
160
|
+
|-------------|------|----------|
|
|
161
|
+
| `MACOS_CERTIFICATE` | macOS 코드 서명 인증서 (base64) | `base64 -i certificate.p12` |
|
|
162
|
+
| `MACOS_CERTIFICATE_PWD` | 인증서 비밀번호 | Keychain Access에서 설정 |
|
|
163
|
+
| `APPLE_ID` | Apple ID 이메일 | Apple Developer 계정 |
|
|
164
|
+
| `APPLE_PASSWORD` | App-specific password | appleid.apple.com에서 생성 |
|
|
165
|
+
| `APPLE_TEAM_ID` | Apple Team ID | Developer 계정에서 확인 |
|
|
166
|
+
| `WINDOWS_CERTIFICATE` | Windows 코드 서명 인증서 (base64) | `[Convert]::ToBase64String([IO.File]::ReadAllBytes("cert.pfx"))` |
|
|
167
|
+
| `WINDOWS_CERTIFICATE_PASSWORD` | 인증서 비밀번호 | 인증서 발급 시 설정 |
|
|
168
|
+
| `TAURI_SIGNING_PRIVATE_KEY` | Updater 서명 private 키 | `pnpm tauri signer generate` |
|
|
169
|
+
| `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` | 서명 키 비밀번호 | 생성 시 설정 (없으면 빈 문자열) |
|
|
170
|
+
|
|
171
|
+
### tauri-action 사용 (간소화 버전)
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
name: Release
|
|
175
|
+
on:
|
|
176
|
+
push:
|
|
177
|
+
tags:
|
|
178
|
+
- 'v*'
|
|
179
|
+
|
|
180
|
+
jobs:
|
|
181
|
+
build:
|
|
182
|
+
permissions:
|
|
183
|
+
contents: write
|
|
184
|
+
strategy:
|
|
185
|
+
fail-fast: false
|
|
186
|
+
matrix:
|
|
187
|
+
platform: [macos-latest, ubuntu-22.04, windows-latest]
|
|
188
|
+
|
|
189
|
+
runs-on: ${{ matrix.platform }}
|
|
190
|
+
steps:
|
|
191
|
+
- uses: actions/checkout@v4
|
|
192
|
+
|
|
193
|
+
- uses: pnpm/action-setup@v2
|
|
194
|
+
- uses: actions/setup-node@v4
|
|
195
|
+
with:
|
|
196
|
+
node-version: 20
|
|
197
|
+
cache: pnpm
|
|
198
|
+
|
|
199
|
+
- name: Install Rust
|
|
200
|
+
uses: dtolnay/rust-toolchain@stable
|
|
201
|
+
|
|
202
|
+
- name: Install Linux dependencies
|
|
203
|
+
if: matrix.platform == 'ubuntu-22.04'
|
|
204
|
+
run: |
|
|
205
|
+
sudo apt-get update
|
|
206
|
+
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
|
207
|
+
|
|
208
|
+
- name: Install frontend dependencies
|
|
209
|
+
run: pnpm install
|
|
210
|
+
|
|
211
|
+
- uses: tauri-apps/tauri-action@v0
|
|
212
|
+
env:
|
|
213
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
214
|
+
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
215
|
+
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
216
|
+
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
217
|
+
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
218
|
+
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
219
|
+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
220
|
+
with:
|
|
221
|
+
tagName: ${{ github.ref_name }}
|
|
222
|
+
releaseName: 'App v__VERSION__'
|
|
223
|
+
releaseBody: 'See the assets to download this version.'
|
|
224
|
+
releaseDraft: true
|
|
225
|
+
prerelease: false
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 릴리스 트리거 방법
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# 1. 버전 업데이트 (package.json, tauri.conf.json)
|
|
232
|
+
pnpm version 1.0.1
|
|
233
|
+
|
|
234
|
+
# 2. 태그 생성 및 푸시
|
|
235
|
+
git tag v1.0.1
|
|
236
|
+
git push origin v1.0.1
|
|
237
|
+
|
|
238
|
+
# 3. GitHub Actions 자동 실행 (Release 탭에서 확인)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## 추가 컨텍스트
|
|
242
|
+
|
|
243
|
+
**matrix 빌드 장점:**
|
|
244
|
+
- 플랫폼별 빌드를 병렬로 실행 (시간 절약)
|
|
245
|
+
- 환경 불일치 방지 (GitHub 호스팅 러너 사용)
|
|
246
|
+
- 빌드 실패 시 다른 플랫폼은 계속 진행 (`fail-fast: false`)
|
|
247
|
+
|
|
248
|
+
**Linux 의존성:**
|
|
249
|
+
- Ubuntu 22.04 권장 (최신 라이브러리)
|
|
250
|
+
- `libwebkit2gtk-4.1-dev`: WebView 렌더링
|
|
251
|
+
- `patchelf`: 바이너리 수정 도구
|
|
252
|
+
|
|
253
|
+
**릴리스 전략:**
|
|
254
|
+
- `draft: true`: 수동으로 릴리스 퍼블리시 (테스트 후 배포)
|
|
255
|
+
- `prerelease: false`: 정식 릴리스로 표시
|
|
256
|
+
- `tagName`: Git 태그와 릴리스 이름 일치
|
|
257
|
+
|
|
258
|
+
**빌드 산출물:**
|
|
259
|
+
- macOS: `.dmg`, `.app.tar.gz`
|
|
260
|
+
- Windows: `.msi`, `.exe` (Installer)
|
|
261
|
+
- Linux: `.deb`, `.AppImage`, `.rpm`
|
|
262
|
+
|
|
263
|
+
**자동 업데이트 통합:**
|
|
264
|
+
- `.tar.gz.sig` 파일도 함께 업로드 필요
|
|
265
|
+
- Updater 엔드포인트를 GitHub Releases로 설정
|
|
266
|
+
|
|
267
|
+
**참고:** [tauri-action GitHub](https://github.com/tauri-apps/tauri-action)
|
|
268
|
+
|
|
269
|
+
영향도: HIGH - 배포 자동화, 멀티 플랫폼 지원, 릴리스 신뢰성
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# 코드 서명 필수
|
|
2
|
+
|
|
3
|
+
## 왜 중요한가
|
|
4
|
+
|
|
5
|
+
서명 없이 배포하면 macOS는 "손상된 앱" 경고를, Windows는 SmartScreen 경고를 표시합니다. 사용자는 앱을 신뢰할 수 없어 설치를 포기하거나 보안 위험에 노출됩니다. 코드 서명은 앱 무결성을 보장하고 사용자 신뢰를 확보하는 필수 단계입니다.
|
|
6
|
+
|
|
7
|
+
## ❌ 잘못된 패턴
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# ❌ 서명 없이 빌드
|
|
11
|
+
pnpm tauri build
|
|
12
|
+
|
|
13
|
+
# ❌ 서명 없이 배포
|
|
14
|
+
gh release upload v1.0.0 ./target/release/bundle/**/*
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**문제점:**
|
|
18
|
+
- macOS: "App is damaged and can't be opened" 경고
|
|
19
|
+
- Windows: "Windows protected your PC" SmartScreen 경고
|
|
20
|
+
- 사용자가 설치 과정을 포기
|
|
21
|
+
- 앱 무결성 검증 불가
|
|
22
|
+
|
|
23
|
+
## ✅ 올바른 패턴
|
|
24
|
+
|
|
25
|
+
### macOS 코드 서명 + 공증
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# 1. Apple Developer 인증서 설치
|
|
29
|
+
# - Keychain Access에서 Developer ID Application 인증서 확인
|
|
30
|
+
|
|
31
|
+
# 2. 빌드 시 서명
|
|
32
|
+
pnpm tauri build
|
|
33
|
+
|
|
34
|
+
# 3. 공증 (notarization)
|
|
35
|
+
xcrun notarytool submit \
|
|
36
|
+
./target/release/bundle/macos/MyApp.app.zip \
|
|
37
|
+
--apple-id "your-email@example.com" \
|
|
38
|
+
--password "app-specific-password" \
|
|
39
|
+
--team-id "YOUR_TEAM_ID" \
|
|
40
|
+
--wait
|
|
41
|
+
|
|
42
|
+
# 4. 공증 완료 후 stapler로 티켓 첨부
|
|
43
|
+
xcrun stapler staple ./target/release/bundle/macos/MyApp.app
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**tauri.conf.json 설정:**
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"bundle": {
|
|
51
|
+
"macOS": {
|
|
52
|
+
"signingIdentity": "Developer ID Application: Your Name (TEAM_ID)",
|
|
53
|
+
"entitlements": "entitlements.plist",
|
|
54
|
+
"provisioningProfile": null
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**entitlements.plist:**
|
|
61
|
+
|
|
62
|
+
```xml
|
|
63
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
64
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
65
|
+
<plist version="1.0">
|
|
66
|
+
<dict>
|
|
67
|
+
<key>com.apple.security.cs.allow-jit</key>
|
|
68
|
+
<true/>
|
|
69
|
+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
|
70
|
+
<true/>
|
|
71
|
+
<key>com.apple.security.cs.disable-library-validation</key>
|
|
72
|
+
<true/>
|
|
73
|
+
<key>com.apple.security.network.client</key>
|
|
74
|
+
<true/>
|
|
75
|
+
</dict>
|
|
76
|
+
</plist>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Windows 코드 서명
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# 1. 코드 서명 인증서 (*.pfx) 준비
|
|
83
|
+
|
|
84
|
+
# 2. signtool로 서명
|
|
85
|
+
signtool sign /f "certificate.pfx" /p "password" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "./target/release/bundle/msi/MyApp_1.0.0_x64_en-US.msi"
|
|
86
|
+
|
|
87
|
+
# 3. 서명 확인
|
|
88
|
+
signtool verify /pa "./target/release/bundle/msi/MyApp_1.0.0_x64_en-US.msi"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**tauri.conf.json 설정:**
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"bundle": {
|
|
96
|
+
"windows": {
|
|
97
|
+
"certificateThumbprint": "YOUR_CERT_THUMBPRINT",
|
|
98
|
+
"timestampUrl": "http://timestamp.digicert.com",
|
|
99
|
+
"digestAlgorithm": "sha256",
|
|
100
|
+
"wix": {
|
|
101
|
+
"language": "en-US"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**GitHub Actions CI/CD:**
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
name: Release
|
|
112
|
+
on:
|
|
113
|
+
push:
|
|
114
|
+
tags:
|
|
115
|
+
- 'v*'
|
|
116
|
+
|
|
117
|
+
jobs:
|
|
118
|
+
build-macos:
|
|
119
|
+
runs-on: macos-latest
|
|
120
|
+
steps:
|
|
121
|
+
- uses: actions/checkout@v4
|
|
122
|
+
- uses: pnpm/action-setup@v2
|
|
123
|
+
- uses: actions/setup-node@v4
|
|
124
|
+
|
|
125
|
+
- name: Install dependencies
|
|
126
|
+
run: pnpm install
|
|
127
|
+
|
|
128
|
+
- name: Import signing certificate
|
|
129
|
+
env:
|
|
130
|
+
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
|
|
131
|
+
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
|
|
132
|
+
run: |
|
|
133
|
+
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
|
134
|
+
security create-keychain -p actions temp.keychain
|
|
135
|
+
security default-keychain -s temp.keychain
|
|
136
|
+
security unlock-keychain -p actions temp.keychain
|
|
137
|
+
security import certificate.p12 -k temp.keychain -P $MACOS_CERTIFICATE_PWD -T /usr/bin/codesign
|
|
138
|
+
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k actions temp.keychain
|
|
139
|
+
|
|
140
|
+
- name: Build and sign
|
|
141
|
+
run: pnpm tauri build
|
|
142
|
+
|
|
143
|
+
- name: Notarize
|
|
144
|
+
env:
|
|
145
|
+
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
146
|
+
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
147
|
+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
148
|
+
run: |
|
|
149
|
+
xcrun notarytool submit \
|
|
150
|
+
./target/release/bundle/macos/MyApp.app.zip \
|
|
151
|
+
--apple-id "$APPLE_ID" \
|
|
152
|
+
--password "$APPLE_PASSWORD" \
|
|
153
|
+
--team-id "$APPLE_TEAM_ID" \
|
|
154
|
+
--wait
|
|
155
|
+
xcrun stapler staple ./target/release/bundle/macos/MyApp.app
|
|
156
|
+
|
|
157
|
+
build-windows:
|
|
158
|
+
runs-on: windows-latest
|
|
159
|
+
steps:
|
|
160
|
+
- uses: actions/checkout@v4
|
|
161
|
+
- uses: pnpm/action-setup@v2
|
|
162
|
+
- uses: actions/setup-node@v4
|
|
163
|
+
|
|
164
|
+
- name: Install dependencies
|
|
165
|
+
run: pnpm install
|
|
166
|
+
|
|
167
|
+
- name: Build
|
|
168
|
+
run: pnpm tauri build
|
|
169
|
+
|
|
170
|
+
- name: Sign
|
|
171
|
+
env:
|
|
172
|
+
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
|
173
|
+
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
174
|
+
run: |
|
|
175
|
+
echo $env:WINDOWS_CERTIFICATE | Out-File -FilePath certificate.txt
|
|
176
|
+
certutil -decode certificate.txt certificate.pfx
|
|
177
|
+
signtool sign /f certificate.pfx /p $env:WINDOWS_CERTIFICATE_PASSWORD /tr http://timestamp.digicert.com /td sha256 /fd sha256 .\target\release\bundle\msi\*.msi
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## 추가 컨텍스트
|
|
181
|
+
|
|
182
|
+
**플랫폼별 서명 체크리스트:**
|
|
183
|
+
|
|
184
|
+
| 플랫폼 | 필수 단계 | 비용 |
|
|
185
|
+
|--------|----------|------|
|
|
186
|
+
| macOS | Developer ID Application 인증서 + 공증 | $99/년 (Apple Developer) |
|
|
187
|
+
| Windows | Code Signing Certificate | $100-500/년 |
|
|
188
|
+
| Linux | 서명 선택사항 (권장하지만 필수 아님) | 무료 |
|
|
189
|
+
|
|
190
|
+
**인증서 종류:**
|
|
191
|
+
- **macOS**: Developer ID Application (App Store 외부 배포)
|
|
192
|
+
- **Windows**: Extended Validation (EV) 또는 Standard Code Signing
|
|
193
|
+
- **Linux**: GPG 서명 (선택사항)
|
|
194
|
+
|
|
195
|
+
**공증 (Notarization) 필수:**
|
|
196
|
+
- macOS Catalina 이상에서 공증 없으면 실행 불가
|
|
197
|
+
- 공증은 서명 후 Apple 서버에 앱 업로드하여 악성 코드 스캔
|
|
198
|
+
- 통과 시 티켓 발급 → stapler로 앱에 첨부
|
|
199
|
+
|
|
200
|
+
**Secrets 관리:**
|
|
201
|
+
- GitHub Actions Secrets에 인증서/비밀번호 저장
|
|
202
|
+
- 절대 코드에 하드코딩 금지
|
|
203
|
+
- `.gitignore`에 `*.p12`, `*.pfx` 추가
|
|
204
|
+
|
|
205
|
+
**참고:** [Tauri Code Signing Guide](https://beta.tauri.app/distribute/sign/)
|
|
206
|
+
|
|
207
|
+
영향도: CRITICAL - 사용자 신뢰, 앱 설치율, 보안
|