@kood/claude-code 0.1.2 → 0.1.4
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 +129 -5
- package/package.json +2 -2
- package/templates/hono/CLAUDE.md +20 -2
- package/templates/hono/docs/architecture/architecture.md +909 -0
- package/templates/hono/docs/commands/git.md +275 -0
- package/templates/hono/docs/deployment/cloudflare.md +527 -190
- package/templates/hono/docs/deployment/docker.md +514 -0
- package/templates/hono/docs/deployment/index.md +179 -214
- package/templates/hono/docs/deployment/railway.md +416 -0
- package/templates/hono/docs/deployment/vercel.md +567 -0
- package/templates/hono/docs/library/ai-sdk/index.md +427 -0
- package/templates/hono/docs/library/ai-sdk/openrouter.md +479 -0
- package/templates/hono/docs/library/ai-sdk/providers.md +468 -0
- package/templates/hono/docs/library/ai-sdk/streaming.md +447 -0
- package/templates/hono/docs/library/ai-sdk/structured-output.md +493 -0
- package/templates/hono/docs/library/ai-sdk/tools.md +513 -0
- package/templates/hono/docs/library/hono/env-setup.md +458 -0
- package/templates/hono/docs/library/hono/index.md +1 -3
- package/templates/hono/docs/library/pino/index.md +437 -0
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +503 -0
- package/templates/hono/docs/library/prisma/config.md +362 -0
- package/templates/hono/docs/library/prisma/index.md +86 -13
- package/templates/hono/docs/skills/gemini-review/SKILL.md +116 -116
- package/templates/hono/docs/skills/gemini-review/references/checklists.md +125 -125
- package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +191 -191
- package/templates/npx/CLAUDE.md +309 -0
- package/templates/npx/docs/commands/git.md +275 -0
- package/templates/npx/docs/library/commander/index.md +164 -0
- package/templates/npx/docs/library/fs-extra/index.md +171 -0
- package/templates/npx/docs/library/prompts/index.md +253 -0
- package/templates/npx/docs/mcp/index.md +60 -0
- package/templates/npx/docs/skills/gemini-review/SKILL.md +220 -0
- package/templates/npx/docs/skills/gemini-review/references/checklists.md +134 -0
- package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +301 -0
- package/templates/tanstack-start/CLAUDE.md +43 -5
- package/templates/tanstack-start/docs/architecture/architecture.md +134 -4
- package/templates/tanstack-start/docs/commands/git.md +275 -0
- package/templates/tanstack-start/docs/deployment/cloudflare.md +223 -50
- package/templates/tanstack-start/docs/deployment/index.md +320 -30
- package/templates/tanstack-start/docs/deployment/nitro.md +195 -14
- package/templates/tanstack-start/docs/deployment/railway.md +302 -150
- package/templates/tanstack-start/docs/deployment/vercel.md +345 -75
- package/templates/tanstack-start/docs/guides/best-practices.md +203 -1
- package/templates/tanstack-start/docs/guides/env-setup.md +450 -0
- package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +472 -0
- package/templates/tanstack-start/docs/library/ai-sdk/index.md +264 -0
- package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +371 -0
- package/templates/tanstack-start/docs/library/ai-sdk/providers.md +403 -0
- package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +320 -0
- package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +454 -0
- package/templates/tanstack-start/docs/library/ai-sdk/tools.md +473 -0
- package/templates/tanstack-start/docs/library/pino/index.md +320 -0
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +404 -0
- package/templates/tanstack-start/docs/library/prisma/config.md +377 -0
- package/templates/tanstack-start/docs/library/prisma/index.md +3 -5
- package/templates/tanstack-start/docs/library/prisma/schema.md +123 -25
- package/templates/tanstack-start/docs/library/prisma/setup.md +0 -7
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +80 -2
- package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +116 -116
- package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +138 -144
- package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +186 -187
- package/templates/hono/docs/git/index.md +0 -180
- package/templates/tanstack-start/docs/git/index.md +0 -203
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
# Nitro v3 - Vercel 배포
|
|
2
|
+
|
|
3
|
+
> **상위 문서**: [배포 가이드](./index.md)
|
|
4
|
+
|
|
5
|
+
Vercel을 사용하여 Hono + Nitro 애플리케이션을 서버리스로 배포합니다.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🚀 Quick Reference (복사용)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// nitro.config.ts
|
|
13
|
+
import { defineNitroConfig } from "nitro/config";
|
|
14
|
+
|
|
15
|
+
export default defineNitroConfig({
|
|
16
|
+
preset: "vercel",
|
|
17
|
+
compatibilityDate: "2024-09-19",
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
// vercel.json
|
|
23
|
+
{
|
|
24
|
+
"buildCommand": "nitro build",
|
|
25
|
+
"outputDirectory": ".vercel/output"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Vercel CLI 배포
|
|
31
|
+
vercel login
|
|
32
|
+
vercel
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Nitro 설정
|
|
38
|
+
|
|
39
|
+
### 기본 설정
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// nitro.config.ts
|
|
43
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
44
|
+
// Vercel 배포용 Nitro 설정
|
|
45
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
46
|
+
import { defineNitroConfig } from "nitro/config";
|
|
47
|
+
|
|
48
|
+
export default defineNitroConfig({
|
|
49
|
+
// Vercel 서버리스 preset
|
|
50
|
+
preset: "vercel",
|
|
51
|
+
|
|
52
|
+
// 호환성 날짜
|
|
53
|
+
compatibilityDate: "2024-09-19",
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Edge Functions 설정
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// nitro.config.ts
|
|
61
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
62
|
+
// Vercel Edge Functions 설정
|
|
63
|
+
// 더 낮은 지연시간을 위해 Edge에서 실행
|
|
64
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
65
|
+
import { defineNitroConfig } from "nitro/config";
|
|
66
|
+
|
|
67
|
+
export default defineNitroConfig({
|
|
68
|
+
preset: "vercel-edge",
|
|
69
|
+
compatibilityDate: "2024-09-19",
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Bun 런타임 설정
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// nitro.config.ts
|
|
77
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
78
|
+
// Vercel + Bun 런타임 설정
|
|
79
|
+
// 빠른 실행 속도를 위해 Bun 사용
|
|
80
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
81
|
+
import { defineNitroConfig } from "nitro/config";
|
|
82
|
+
|
|
83
|
+
export default defineNitroConfig({
|
|
84
|
+
preset: "vercel",
|
|
85
|
+
compatibilityDate: "2024-09-19",
|
|
86
|
+
|
|
87
|
+
// Bun 런타임 사용
|
|
88
|
+
vercel: {
|
|
89
|
+
functions: {
|
|
90
|
+
runtime: "bun@1",
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## vercel.json 설정
|
|
99
|
+
|
|
100
|
+
### 기본 설정
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"$schema": "https://openapi.vercel.sh/vercel.json",
|
|
105
|
+
"buildCommand": "yarn build",
|
|
106
|
+
"outputDirectory": ".vercel/output",
|
|
107
|
+
"framework": null,
|
|
108
|
+
"installCommand": "yarn install"
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 고급 설정
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"$schema": "https://openapi.vercel.sh/vercel.json",
|
|
117
|
+
"buildCommand": "yarn build",
|
|
118
|
+
"outputDirectory": ".vercel/output",
|
|
119
|
+
|
|
120
|
+
"functions": {
|
|
121
|
+
"api/**/*.ts": {
|
|
122
|
+
"memory": 1024,
|
|
123
|
+
"maxDuration": 30
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
"headers": [
|
|
128
|
+
{
|
|
129
|
+
"source": "/api/(.*)",
|
|
130
|
+
"headers": [
|
|
131
|
+
{ "key": "Access-Control-Allow-Origin", "value": "*" },
|
|
132
|
+
{ "key": "Access-Control-Allow-Methods", "value": "GET, POST, PUT, DELETE, OPTIONS" }
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
|
|
137
|
+
"rewrites": [
|
|
138
|
+
{ "source": "/(.*)", "destination": "/api" }
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 배포 방법
|
|
146
|
+
|
|
147
|
+
### 방법 1: GitHub 연동 (권장)
|
|
148
|
+
|
|
149
|
+
1. **Vercel 프로젝트 생성**
|
|
150
|
+
- [Vercel 대시보드](https://vercel.com) 접속
|
|
151
|
+
- "Add New" → "Project" → GitHub 저장소 선택
|
|
152
|
+
|
|
153
|
+
2. **빌드 설정**
|
|
154
|
+
- Framework Preset: "Other"
|
|
155
|
+
- Build Command: `yarn build`
|
|
156
|
+
- Output Directory: `.vercel/output`
|
|
157
|
+
- Install Command: `yarn install`
|
|
158
|
+
|
|
159
|
+
3. **환경 변수 설정**
|
|
160
|
+
- Vercel 대시보드에서 Settings → Environment Variables
|
|
161
|
+
|
|
162
|
+
### 방법 2: Vercel CLI
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Vercel CLI 설치
|
|
166
|
+
npm install -g vercel
|
|
167
|
+
|
|
168
|
+
# 로그인
|
|
169
|
+
vercel login
|
|
170
|
+
|
|
171
|
+
# 프로젝트 연결 및 배포
|
|
172
|
+
vercel
|
|
173
|
+
|
|
174
|
+
# 프로덕션 배포
|
|
175
|
+
vercel --prod
|
|
176
|
+
|
|
177
|
+
# 환경 변수 설정
|
|
178
|
+
vercel env add DATABASE_URL
|
|
179
|
+
vercel env add API_SECRET
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## ISR (Incremental Static Regeneration)
|
|
185
|
+
|
|
186
|
+
### ISR 설정
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// nitro.config.ts
|
|
190
|
+
import { defineNitroConfig } from "nitro/config";
|
|
191
|
+
|
|
192
|
+
export default defineNitroConfig({
|
|
193
|
+
preset: "vercel",
|
|
194
|
+
compatibilityDate: "2024-09-19",
|
|
195
|
+
|
|
196
|
+
// ISR 설정
|
|
197
|
+
vercel: {
|
|
198
|
+
config: {
|
|
199
|
+
// 정적 페이지 재생성 간격 (초)
|
|
200
|
+
isr: {
|
|
201
|
+
bypassToken: process.env.ISR_BYPASS_TOKEN,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 라우트별 ISR
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
// src/server.ts
|
|
212
|
+
import { Hono } from "hono";
|
|
213
|
+
|
|
214
|
+
const app = new Hono();
|
|
215
|
+
|
|
216
|
+
// ISR 헤더 설정으로 캐시 제어
|
|
217
|
+
app.get("/posts", async (c) => {
|
|
218
|
+
// 60초마다 재생성
|
|
219
|
+
c.header("Cache-Control", "s-maxage=60, stale-while-revalidate");
|
|
220
|
+
|
|
221
|
+
const posts = await fetchPosts();
|
|
222
|
+
return c.json(posts);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// 캐시 무효화가 필요한 엔드포인트
|
|
226
|
+
app.get("/user/:id", async (c) => {
|
|
227
|
+
// 캐시하지 않음
|
|
228
|
+
c.header("Cache-Control", "no-store");
|
|
229
|
+
|
|
230
|
+
const user = await fetchUser(c.req.param("id"));
|
|
231
|
+
return c.json(user);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
export default app;
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 환경 변수
|
|
240
|
+
|
|
241
|
+
### Vercel 대시보드에서 설정
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
DATABASE_URL=postgresql://user:pass@host:5432/db
|
|
245
|
+
API_SECRET=your-secret-key
|
|
246
|
+
NODE_ENV=production
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### 환경별 설정
|
|
250
|
+
|
|
251
|
+
Vercel은 환경별로 다른 값 설정 가능:
|
|
252
|
+
- **Production**: 프로덕션 환경
|
|
253
|
+
- **Preview**: PR 프리뷰 환경
|
|
254
|
+
- **Development**: 로컬 개발 환경
|
|
255
|
+
|
|
256
|
+
### 코드에서 사용
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
// src/server.ts
|
|
260
|
+
import { Hono } from "hono";
|
|
261
|
+
|
|
262
|
+
const app = new Hono();
|
|
263
|
+
|
|
264
|
+
app.get("/config", (c) => {
|
|
265
|
+
return c.json({
|
|
266
|
+
environment: process.env.VERCEL_ENV, // production, preview, development
|
|
267
|
+
region: process.env.VERCEL_REGION, // iad1, sfo1 등
|
|
268
|
+
url: process.env.VERCEL_URL, // 배포 URL
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
export default app;
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Vercel 자동 제공 변수
|
|
276
|
+
|
|
277
|
+
| 변수 | 설명 |
|
|
278
|
+
|------|------|
|
|
279
|
+
| `VERCEL` | Vercel 환경인지 여부 ("1") |
|
|
280
|
+
| `VERCEL_ENV` | 환경 (production, preview, development) |
|
|
281
|
+
| `VERCEL_URL` | 배포 URL |
|
|
282
|
+
| `VERCEL_REGION` | 실행 리전 |
|
|
283
|
+
| `VERCEL_GIT_COMMIT_SHA` | Git 커밋 SHA |
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## 데이터베이스 연동
|
|
288
|
+
|
|
289
|
+
### Vercel Postgres
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
// src/lib/db.ts
|
|
293
|
+
import { sql } from "@vercel/postgres";
|
|
294
|
+
|
|
295
|
+
export const getUsers = async () => {
|
|
296
|
+
const { rows } = await sql`SELECT * FROM users`;
|
|
297
|
+
return rows;
|
|
298
|
+
};
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Vercel KV (Redis)
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
// src/lib/kv.ts
|
|
305
|
+
import { kv } from "@vercel/kv";
|
|
306
|
+
|
|
307
|
+
export const getCache = async (key: string) => {
|
|
308
|
+
return await kv.get(key);
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
export const setCache = async (key: string, value: unknown, ttl?: number) => {
|
|
312
|
+
if (ttl) {
|
|
313
|
+
await kv.set(key, value, { ex: ttl });
|
|
314
|
+
} else {
|
|
315
|
+
await kv.set(key, value);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 외부 데이터베이스
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
// src/lib/prisma.ts
|
|
324
|
+
import { PrismaClient } from "@prisma/client";
|
|
325
|
+
|
|
326
|
+
// Vercel 서버리스 환경에서 커넥션 풀 최적화
|
|
327
|
+
const globalForPrisma = globalThis as unknown as {
|
|
328
|
+
prisma: PrismaClient | undefined;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
export const prisma =
|
|
332
|
+
globalForPrisma.prisma ??
|
|
333
|
+
new PrismaClient({
|
|
334
|
+
log: process.env.NODE_ENV === "development" ? ["query"] : [],
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
if (process.env.NODE_ENV !== "production") {
|
|
338
|
+
globalForPrisma.prisma = prisma;
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Edge Middleware
|
|
345
|
+
|
|
346
|
+
### middleware.ts
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
// middleware.ts
|
|
350
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
351
|
+
// Vercel Edge Middleware
|
|
352
|
+
// 요청 전처리 및 라우팅
|
|
353
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
354
|
+
import { NextResponse } from "next/server";
|
|
355
|
+
import type { NextRequest } from "next/server";
|
|
356
|
+
|
|
357
|
+
export function middleware(request: NextRequest) {
|
|
358
|
+
// 인증 체크
|
|
359
|
+
const token = request.cookies.get("auth-token");
|
|
360
|
+
|
|
361
|
+
if (!token && request.nextUrl.pathname.startsWith("/api/protected")) {
|
|
362
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// 리전 기반 라우팅
|
|
366
|
+
const country = request.geo?.country || "US";
|
|
367
|
+
if (country === "KR") {
|
|
368
|
+
// 한국 사용자를 위한 특별 처리
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return NextResponse.next();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export const config = {
|
|
375
|
+
matcher: ["/api/:path*"],
|
|
376
|
+
};
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## 모니터링 및 분석
|
|
382
|
+
|
|
383
|
+
### Vercel Analytics
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
// nitro.config.ts
|
|
387
|
+
import { defineNitroConfig } from "nitro/config";
|
|
388
|
+
|
|
389
|
+
export default defineNitroConfig({
|
|
390
|
+
preset: "vercel",
|
|
391
|
+
compatibilityDate: "2024-09-19",
|
|
392
|
+
|
|
393
|
+
// Analytics 활성화
|
|
394
|
+
vercel: {
|
|
395
|
+
config: {
|
|
396
|
+
analytics: true,
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### 커스텀 로깅
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
// src/server.ts
|
|
406
|
+
import { Hono } from "hono";
|
|
407
|
+
import { logger } from "hono/logger";
|
|
408
|
+
|
|
409
|
+
const app = new Hono();
|
|
410
|
+
|
|
411
|
+
// 요청 로깅
|
|
412
|
+
app.use("*", logger());
|
|
413
|
+
|
|
414
|
+
// Vercel 로그로 전송
|
|
415
|
+
app.use("*", async (c, next) => {
|
|
416
|
+
const start = Date.now();
|
|
417
|
+
await next();
|
|
418
|
+
const duration = Date.now() - start;
|
|
419
|
+
|
|
420
|
+
console.log(JSON.stringify({
|
|
421
|
+
method: c.req.method,
|
|
422
|
+
path: c.req.path,
|
|
423
|
+
status: c.res.status,
|
|
424
|
+
duration,
|
|
425
|
+
region: process.env.VERCEL_REGION,
|
|
426
|
+
}));
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
export default app;
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## CI/CD 설정
|
|
435
|
+
|
|
436
|
+
### GitHub Actions
|
|
437
|
+
|
|
438
|
+
```yaml
|
|
439
|
+
# .github/workflows/vercel.yml
|
|
440
|
+
name: Deploy to Vercel
|
|
441
|
+
|
|
442
|
+
on:
|
|
443
|
+
push:
|
|
444
|
+
branches: [main]
|
|
445
|
+
pull_request:
|
|
446
|
+
branches: [main]
|
|
447
|
+
|
|
448
|
+
jobs:
|
|
449
|
+
deploy:
|
|
450
|
+
runs-on: ubuntu-latest
|
|
451
|
+
|
|
452
|
+
steps:
|
|
453
|
+
- uses: actions/checkout@v4
|
|
454
|
+
|
|
455
|
+
- name: Setup Node.js
|
|
456
|
+
uses: actions/setup-node@v4
|
|
457
|
+
with:
|
|
458
|
+
node-version: "20"
|
|
459
|
+
cache: "yarn"
|
|
460
|
+
|
|
461
|
+
- name: Install dependencies
|
|
462
|
+
run: yarn install --frozen-lockfile
|
|
463
|
+
|
|
464
|
+
- name: Build
|
|
465
|
+
run: yarn build
|
|
466
|
+
|
|
467
|
+
- name: Deploy to Vercel
|
|
468
|
+
uses: amondnet/vercel-action@v25
|
|
469
|
+
with:
|
|
470
|
+
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
|
471
|
+
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
|
472
|
+
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
473
|
+
vercel-args: ${{ github.ref == 'refs/heads/main' && '--prod' || '' }}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
## 최적화
|
|
479
|
+
|
|
480
|
+
### Cold Start 최소화
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
// nitro.config.ts
|
|
484
|
+
import { defineNitroConfig } from "nitro/config";
|
|
485
|
+
|
|
486
|
+
export default defineNitroConfig({
|
|
487
|
+
preset: "vercel",
|
|
488
|
+
compatibilityDate: "2024-09-19",
|
|
489
|
+
|
|
490
|
+
// 번들 최적화
|
|
491
|
+
minify: true,
|
|
492
|
+
|
|
493
|
+
// 트리 쉐이킹
|
|
494
|
+
experimental: {
|
|
495
|
+
wasm: true,
|
|
496
|
+
},
|
|
497
|
+
});
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### 응답 압축
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
// src/server.ts
|
|
504
|
+
import { Hono } from "hono";
|
|
505
|
+
import { compress } from "hono/compress";
|
|
506
|
+
|
|
507
|
+
const app = new Hono();
|
|
508
|
+
|
|
509
|
+
// Gzip/Brotli 압축
|
|
510
|
+
app.use("*", compress());
|
|
511
|
+
|
|
512
|
+
export default app;
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## 문제 해결
|
|
518
|
+
|
|
519
|
+
### 일반적인 문제
|
|
520
|
+
|
|
521
|
+
| 문제 | 원인 | 해결 |
|
|
522
|
+
|------|------|------|
|
|
523
|
+
| Function Timeout | 실행 시간 초과 | `maxDuration` 증가 또는 최적화 |
|
|
524
|
+
| Edge 호환성 오류 | Node.js API 사용 | Edge 호환 API로 변경 |
|
|
525
|
+
| 환경 변수 누락 | 설정 안됨 | Vercel 대시보드에서 설정 |
|
|
526
|
+
| 빌드 실패 | 의존성 문제 | `yarn.lock` 확인 |
|
|
527
|
+
|
|
528
|
+
### 디버깅
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
# 로컬에서 Vercel 환경 시뮬레이션
|
|
532
|
+
vercel dev
|
|
533
|
+
|
|
534
|
+
# 로그 확인
|
|
535
|
+
vercel logs
|
|
536
|
+
|
|
537
|
+
# 환경 변수 확인
|
|
538
|
+
vercel env ls
|
|
539
|
+
|
|
540
|
+
# 함수 상태 확인
|
|
541
|
+
vercel inspect
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### 함수 크기 제한
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
// nitro.config.ts
|
|
548
|
+
import { defineNitroConfig } from "nitro/config";
|
|
549
|
+
|
|
550
|
+
export default defineNitroConfig({
|
|
551
|
+
preset: "vercel",
|
|
552
|
+
compatibilityDate: "2024-09-19",
|
|
553
|
+
|
|
554
|
+
// 외부 패키지 제외 (번들 크기 감소)
|
|
555
|
+
externals: ["sharp", "prisma"],
|
|
556
|
+
});
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## 관련 문서
|
|
562
|
+
|
|
563
|
+
- [배포 가이드 개요](./index.md)
|
|
564
|
+
- [Docker 배포](./docker.md)
|
|
565
|
+
- [Railway 배포](./railway.md)
|
|
566
|
+
- [Cloudflare 배포](./cloudflare.md)
|
|
567
|
+
- [Vercel 공식 문서](https://vercel.com/docs)
|