@kood/claude-code 0.1.7 → 0.1.9
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 +118 -3
- package/package.json +8 -2
- package/templates/hono/CLAUDE.md +53 -326
- package/templates/hono/docs/architecture/architecture.md +93 -747
- package/templates/hono/docs/deployment/cloudflare.md +59 -513
- package/templates/hono/docs/deployment/docker.md +41 -356
- package/templates/hono/docs/deployment/index.md +49 -190
- package/templates/hono/docs/deployment/railway.md +36 -306
- package/templates/hono/docs/deployment/vercel.md +49 -434
- package/templates/hono/docs/library/ai-sdk/index.md +53 -290
- package/templates/hono/docs/library/ai-sdk/openrouter.md +19 -387
- package/templates/hono/docs/library/ai-sdk/providers.md +28 -394
- package/templates/hono/docs/library/ai-sdk/streaming.md +52 -353
- package/templates/hono/docs/library/ai-sdk/structured-output.md +63 -395
- package/templates/hono/docs/library/ai-sdk/tools.md +62 -431
- package/templates/hono/docs/library/hono/env-setup.md +24 -313
- package/templates/hono/docs/library/hono/error-handling.md +34 -295
- package/templates/hono/docs/library/hono/index.md +24 -122
- package/templates/hono/docs/library/hono/middleware.md +21 -188
- package/templates/hono/docs/library/hono/rpc.md +40 -341
- package/templates/hono/docs/library/hono/validation.md +35 -195
- package/templates/hono/docs/library/pino/index.md +42 -333
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +64 -367
- package/templates/hono/docs/library/prisma/config.md +19 -260
- package/templates/hono/docs/library/prisma/index.md +64 -320
- package/templates/hono/docs/library/zod/index.md +53 -257
- package/templates/npx/CLAUDE.md +58 -276
- package/templates/npx/docs/references/patterns.md +160 -0
- package/templates/tanstack-start/CLAUDE.md +0 -4
- package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
- package/templates/tanstack-start/docs/design/index.md +119 -12
- package/templates/tanstack-start/docs/guides/conventions.md +103 -0
- package/templates/tanstack-start/docs/guides/env-setup.md +34 -340
- package/templates/tanstack-start/docs/guides/getting-started.md +22 -209
- package/templates/tanstack-start/docs/guides/hooks.md +166 -0
- package/templates/tanstack-start/docs/guides/routes.md +166 -0
- package/templates/tanstack-start/docs/guides/services.md +143 -0
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +18 -2
- package/templates/tanstack-start/docs/library/zod/index.md +16 -1
- package/templates/tanstack-start/docs/design/accessibility.md +0 -163
- package/templates/tanstack-start/docs/design/color.md +0 -93
- package/templates/tanstack-start/docs/design/spacing.md +0 -122
- package/templates/tanstack-start/docs/design/typography.md +0 -80
- package/templates/tanstack-start/docs/guides/best-practices.md +0 -950
- package/templates/tanstack-start/docs/guides/husky-lint-staged.md +0 -303
- package/templates/tanstack-start/docs/guides/prettier.md +0 -189
- package/templates/tanstack-start/docs/guides/project-templates.md +0 -710
- package/templates/tanstack-start/docs/library/tanstack-query/setup.md +0 -48
- package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -74
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
# Nitro
|
|
1
|
+
# Nitro - Vercel 배포
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
Vercel을 사용하여 Hono + Nitro 애플리케이션을 서버리스로 배포합니다.
|
|
3
|
+
> 서버리스 배포
|
|
6
4
|
|
|
7
5
|
---
|
|
8
6
|
|
|
9
|
-
##
|
|
7
|
+
## 설정
|
|
10
8
|
|
|
11
9
|
```typescript
|
|
12
10
|
// nitro.config.ts
|
|
13
11
|
import { defineNitroConfig } from "nitro/config";
|
|
14
12
|
|
|
15
13
|
export default defineNitroConfig({
|
|
16
|
-
preset: "vercel",
|
|
14
|
+
preset: "vercel", // vercel-edge for Edge Functions
|
|
17
15
|
compatibilityDate: "2024-09-19",
|
|
18
16
|
});
|
|
19
17
|
```
|
|
@@ -21,318 +19,110 @@ export default defineNitroConfig({
|
|
|
21
19
|
```json
|
|
22
20
|
// vercel.json
|
|
23
21
|
{
|
|
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
22
|
"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
|
-
]
|
|
23
|
+
"outputDirectory": ".vercel/output"
|
|
140
24
|
}
|
|
141
25
|
```
|
|
142
26
|
|
|
143
27
|
---
|
|
144
28
|
|
|
145
|
-
## 배포
|
|
146
|
-
|
|
147
|
-
### 방법 1: GitHub 연동 (권장)
|
|
29
|
+
## 배포
|
|
148
30
|
|
|
149
|
-
|
|
150
|
-
- [Vercel 대시보드](https://vercel.com) 접속
|
|
151
|
-
- "Add New" → "Project" → GitHub 저장소 선택
|
|
31
|
+
### GitHub 연동 (권장)
|
|
152
32
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
- Output Directory: `.vercel/output`
|
|
157
|
-
- Install Command: `yarn install`
|
|
33
|
+
1. [Vercel 대시보드](https://vercel.com) → Add New → Project
|
|
34
|
+
2. Build Command: `yarn build`
|
|
35
|
+
3. Output Directory: `.vercel/output`
|
|
158
36
|
|
|
159
|
-
|
|
160
|
-
- Vercel 대시보드에서 Settings → Environment Variables
|
|
161
|
-
|
|
162
|
-
### 방법 2: Vercel CLI
|
|
37
|
+
### CLI
|
|
163
38
|
|
|
164
39
|
```bash
|
|
165
|
-
# Vercel CLI 설치
|
|
166
40
|
npm install -g vercel
|
|
167
|
-
|
|
168
|
-
# 로그인
|
|
169
41
|
vercel login
|
|
42
|
+
vercel # 프리뷰
|
|
43
|
+
vercel --prod # 프로덕션
|
|
170
44
|
|
|
171
|
-
# 프로젝트 연결 및 배포
|
|
172
|
-
vercel
|
|
173
|
-
|
|
174
|
-
# 프로덕션 배포
|
|
175
|
-
vercel --prod
|
|
176
|
-
|
|
177
|
-
# 환경 변수 설정
|
|
178
45
|
vercel env add DATABASE_URL
|
|
179
|
-
vercel env add API_SECRET
|
|
180
46
|
```
|
|
181
47
|
|
|
182
48
|
---
|
|
183
49
|
|
|
184
|
-
##
|
|
185
|
-
|
|
186
|
-
### ISR 설정
|
|
50
|
+
## Edge Functions
|
|
187
51
|
|
|
188
52
|
```typescript
|
|
189
53
|
// nitro.config.ts
|
|
190
|
-
import { defineNitroConfig } from "nitro/config";
|
|
191
|
-
|
|
192
54
|
export default defineNitroConfig({
|
|
193
|
-
preset: "vercel",
|
|
55
|
+
preset: "vercel-edge",
|
|
194
56
|
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
57
|
});
|
|
206
58
|
```
|
|
207
59
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
// src/server.ts
|
|
212
|
-
import { Hono } from "hono";
|
|
60
|
+
---
|
|
213
61
|
|
|
214
|
-
|
|
62
|
+
## ISR (캐시)
|
|
215
63
|
|
|
216
|
-
|
|
64
|
+
```typescript
|
|
217
65
|
app.get("/posts", async (c) => {
|
|
218
|
-
// 60초마다 재생성
|
|
219
66
|
c.header("Cache-Control", "s-maxage=60, stale-while-revalidate");
|
|
220
|
-
|
|
221
|
-
const posts = await fetchPosts();
|
|
222
|
-
return c.json(posts);
|
|
67
|
+
return c.json(await fetchPosts());
|
|
223
68
|
});
|
|
224
69
|
|
|
225
|
-
// 캐시 무효화가 필요한 엔드포인트
|
|
226
70
|
app.get("/user/:id", async (c) => {
|
|
227
|
-
//
|
|
228
|
-
c.
|
|
229
|
-
|
|
230
|
-
const user = await fetchUser(c.req.param("id"));
|
|
231
|
-
return c.json(user);
|
|
71
|
+
c.header("Cache-Control", "no-store"); // 캐시 안함
|
|
72
|
+
return c.json(await fetchUser(c.req.param("id")));
|
|
232
73
|
});
|
|
233
|
-
|
|
234
|
-
export default app;
|
|
235
74
|
```
|
|
236
75
|
|
|
237
76
|
---
|
|
238
77
|
|
|
239
78
|
## 환경 변수
|
|
240
79
|
|
|
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
80
|
```typescript
|
|
259
|
-
// src/server.ts
|
|
260
|
-
import { Hono } from "hono";
|
|
261
|
-
|
|
262
|
-
const app = new Hono();
|
|
263
|
-
|
|
264
81
|
app.get("/config", (c) => {
|
|
265
82
|
return c.json({
|
|
266
|
-
|
|
267
|
-
region: process.env.VERCEL_REGION,
|
|
268
|
-
url: process.env.VERCEL_URL, // 배포 URL
|
|
83
|
+
env: process.env.VERCEL_ENV, // production, preview
|
|
84
|
+
region: process.env.VERCEL_REGION,
|
|
269
85
|
});
|
|
270
86
|
});
|
|
271
|
-
|
|
272
|
-
export default app;
|
|
273
87
|
```
|
|
274
88
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
|
278
|
-
|
|
279
|
-
| `VERCEL` | Vercel 환경인지 여부 ("1") |
|
|
280
|
-
| `VERCEL_ENV` | 환경 (production, preview, development) |
|
|
89
|
+
| 자동 제공 변수 | 설명 |
|
|
90
|
+
|---------------|------|
|
|
91
|
+
| `VERCEL` | Vercel 환경 ("1") |
|
|
92
|
+
| `VERCEL_ENV` | 환경 |
|
|
281
93
|
| `VERCEL_URL` | 배포 URL |
|
|
282
94
|
| `VERCEL_REGION` | 실행 리전 |
|
|
283
|
-
| `VERCEL_GIT_COMMIT_SHA` | Git 커밋 SHA |
|
|
284
95
|
|
|
285
96
|
---
|
|
286
97
|
|
|
287
|
-
## 데이터베이스
|
|
98
|
+
## 데이터베이스
|
|
288
99
|
|
|
289
100
|
### Vercel Postgres
|
|
290
101
|
|
|
291
102
|
```typescript
|
|
292
|
-
// src/lib/db.ts
|
|
293
103
|
import { sql } from "@vercel/postgres";
|
|
294
104
|
|
|
295
|
-
|
|
105
|
+
const getUsers = async () => {
|
|
296
106
|
const { rows } = await sql`SELECT * FROM users`;
|
|
297
107
|
return rows;
|
|
298
108
|
};
|
|
299
109
|
```
|
|
300
110
|
|
|
301
|
-
### Vercel KV
|
|
111
|
+
### Vercel KV
|
|
302
112
|
|
|
303
113
|
```typescript
|
|
304
|
-
// src/lib/kv.ts
|
|
305
114
|
import { kv } from "@vercel/kv";
|
|
306
115
|
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
};
|
|
116
|
+
await kv.set("key", value, { ex: 3600 });
|
|
117
|
+
const data = await kv.get("key");
|
|
318
118
|
```
|
|
319
119
|
|
|
320
|
-
###
|
|
120
|
+
### Prisma
|
|
321
121
|
|
|
322
122
|
```typescript
|
|
323
|
-
|
|
324
|
-
import { PrismaClient } from "@prisma/client";
|
|
123
|
+
const globalForPrisma = globalThis as { prisma?: PrismaClient };
|
|
325
124
|
|
|
326
|
-
|
|
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
|
-
});
|
|
125
|
+
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
|
|
336
126
|
|
|
337
127
|
if (process.env.NODE_ENV !== "production") {
|
|
338
128
|
globalForPrisma.prisma = prisma;
|
|
@@ -341,99 +131,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
341
131
|
|
|
342
132
|
---
|
|
343
133
|
|
|
344
|
-
##
|
|
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
|
|
134
|
+
## CI/CD
|
|
437
135
|
|
|
438
136
|
```yaml
|
|
439
137
|
# .github/workflows/vercel.yml
|
|
@@ -442,30 +140,18 @@ name: Deploy to Vercel
|
|
|
442
140
|
on:
|
|
443
141
|
push:
|
|
444
142
|
branches: [main]
|
|
445
|
-
pull_request:
|
|
446
|
-
branches: [main]
|
|
447
143
|
|
|
448
144
|
jobs:
|
|
449
145
|
deploy:
|
|
450
146
|
runs-on: ubuntu-latest
|
|
451
|
-
|
|
452
147
|
steps:
|
|
453
148
|
- uses: actions/checkout@v4
|
|
454
|
-
|
|
455
|
-
- name: Setup Node.js
|
|
456
|
-
uses: actions/setup-node@v4
|
|
149
|
+
- uses: actions/setup-node@v4
|
|
457
150
|
with:
|
|
458
151
|
node-version: "20"
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
-
|
|
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
|
|
152
|
+
- run: yarn install --frozen-lockfile
|
|
153
|
+
- run: yarn build
|
|
154
|
+
- uses: amondnet/vercel-action@v25
|
|
469
155
|
with:
|
|
470
156
|
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
|
471
157
|
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
|
@@ -475,93 +161,22 @@ jobs:
|
|
|
475
161
|
|
|
476
162
|
---
|
|
477
163
|
|
|
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
164
|
## 문제 해결
|
|
518
165
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
|
522
|
-
|
|
523
|
-
|
|
|
524
|
-
| Edge 호환성 오류 | Node.js API 사용 | Edge 호환 API로 변경 |
|
|
525
|
-
| 환경 변수 누락 | 설정 안됨 | Vercel 대시보드에서 설정 |
|
|
526
|
-
| 빌드 실패 | 의존성 문제 | `yarn.lock` 확인 |
|
|
527
|
-
|
|
528
|
-
### 디버깅
|
|
166
|
+
| 문제 | 해결 |
|
|
167
|
+
|------|------|
|
|
168
|
+
| Function Timeout | `maxDuration` 증가 |
|
|
169
|
+
| Edge 호환성 오류 | Edge 호환 API 사용 |
|
|
170
|
+
| 번들 크기 초과 | externals 설정 |
|
|
529
171
|
|
|
530
172
|
```bash
|
|
531
|
-
#
|
|
532
|
-
vercel
|
|
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
|
-
});
|
|
173
|
+
vercel dev # 로컬 시뮬레이션
|
|
174
|
+
vercel logs # 로그 확인
|
|
175
|
+
vercel env ls # 환경 변수 확인
|
|
557
176
|
```
|
|
558
177
|
|
|
559
178
|
---
|
|
560
179
|
|
|
561
180
|
## 관련 문서
|
|
562
181
|
|
|
563
|
-
- [배포 가이드
|
|
564
|
-
- [Docker 배포](./docker.md)
|
|
565
|
-
- [Railway 배포](./railway.md)
|
|
566
|
-
- [Cloudflare 배포](./cloudflare.md)
|
|
567
|
-
- [Vercel 공식 문서](https://vercel.com/docs)
|
|
182
|
+
- [배포 가이드](./index.md)
|