@kood/claude-code 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +297 -0
  3. package/package.json +47 -0
  4. package/templates/hono/CLAUDE.md +376 -0
  5. package/templates/hono/docs/deployment/cloudflare.md +328 -0
  6. package/templates/hono/docs/deployment/index.md +291 -0
  7. package/templates/hono/docs/git/index.md +180 -0
  8. package/templates/hono/docs/library/hono/error-handling.md +400 -0
  9. package/templates/hono/docs/library/hono/index.md +241 -0
  10. package/templates/hono/docs/library/hono/middleware.md +334 -0
  11. package/templates/hono/docs/library/hono/rpc.md +454 -0
  12. package/templates/hono/docs/library/hono/validation.md +328 -0
  13. package/templates/hono/docs/library/prisma/index.md +427 -0
  14. package/templates/hono/docs/library/zod/index.md +413 -0
  15. package/templates/hono/docs/mcp/context7.md +106 -0
  16. package/templates/hono/docs/mcp/index.md +94 -0
  17. package/templates/hono/docs/mcp/sequential-thinking.md +101 -0
  18. package/templates/hono/docs/mcp/sgrep.md +105 -0
  19. package/templates/hono/docs/skills/gemini-review/SKILL.md +220 -0
  20. package/templates/hono/docs/skills/gemini-review/references/checklists.md +136 -0
  21. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +303 -0
  22. package/templates/tanstack-start/CLAUDE.md +279 -0
  23. package/templates/tanstack-start/docs/architecture/architecture.md +547 -0
  24. package/templates/tanstack-start/docs/deployment/cloudflare.md +346 -0
  25. package/templates/tanstack-start/docs/deployment/index.md +102 -0
  26. package/templates/tanstack-start/docs/deployment/nitro.md +211 -0
  27. package/templates/tanstack-start/docs/deployment/railway.md +364 -0
  28. package/templates/tanstack-start/docs/deployment/vercel.md +287 -0
  29. package/templates/tanstack-start/docs/design/accessibility.md +433 -0
  30. package/templates/tanstack-start/docs/design/color.md +235 -0
  31. package/templates/tanstack-start/docs/design/components.md +409 -0
  32. package/templates/tanstack-start/docs/design/index.md +107 -0
  33. package/templates/tanstack-start/docs/design/safe-area.md +317 -0
  34. package/templates/tanstack-start/docs/design/spacing.md +341 -0
  35. package/templates/tanstack-start/docs/design/tailwind-setup.md +470 -0
  36. package/templates/tanstack-start/docs/design/typography.md +324 -0
  37. package/templates/tanstack-start/docs/git/index.md +203 -0
  38. package/templates/tanstack-start/docs/guides/best-practices.md +753 -0
  39. package/templates/tanstack-start/docs/guides/getting-started.md +304 -0
  40. package/templates/tanstack-start/docs/guides/husky-lint-staged.md +303 -0
  41. package/templates/tanstack-start/docs/guides/prettier.md +189 -0
  42. package/templates/tanstack-start/docs/guides/project-templates.md +710 -0
  43. package/templates/tanstack-start/docs/library/better-auth/2fa.md +136 -0
  44. package/templates/tanstack-start/docs/library/better-auth/advanced.md +138 -0
  45. package/templates/tanstack-start/docs/library/better-auth/index.md +83 -0
  46. package/templates/tanstack-start/docs/library/better-auth/plugins.md +111 -0
  47. package/templates/tanstack-start/docs/library/better-auth/session.md +127 -0
  48. package/templates/tanstack-start/docs/library/better-auth/setup.md +123 -0
  49. package/templates/tanstack-start/docs/library/prisma/crud.md +218 -0
  50. package/templates/tanstack-start/docs/library/prisma/index.md +165 -0
  51. package/templates/tanstack-start/docs/library/prisma/relations.md +191 -0
  52. package/templates/tanstack-start/docs/library/prisma/schema.md +177 -0
  53. package/templates/tanstack-start/docs/library/prisma/setup.md +156 -0
  54. package/templates/tanstack-start/docs/library/prisma/transactions.md +140 -0
  55. package/templates/tanstack-start/docs/library/tanstack-query/index.md +146 -0
  56. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +146 -0
  57. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +196 -0
  58. package/templates/tanstack-start/docs/library/tanstack-query/setup.md +110 -0
  59. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +170 -0
  60. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +173 -0
  61. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +171 -0
  62. package/templates/tanstack-start/docs/library/tanstack-start/index.md +114 -0
  63. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +142 -0
  64. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +163 -0
  65. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +128 -0
  66. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +85 -0
  67. package/templates/tanstack-start/docs/library/zod/basic-types.md +186 -0
  68. package/templates/tanstack-start/docs/library/zod/complex-types.md +204 -0
  69. package/templates/tanstack-start/docs/library/zod/index.md +186 -0
  70. package/templates/tanstack-start/docs/library/zod/transforms.md +174 -0
  71. package/templates/tanstack-start/docs/library/zod/validation.md +208 -0
  72. package/templates/tanstack-start/docs/mcp/context7.md +204 -0
  73. package/templates/tanstack-start/docs/mcp/index.md +116 -0
  74. package/templates/tanstack-start/docs/mcp/sequential-thinking.md +180 -0
  75. package/templates/tanstack-start/docs/mcp/sgrep.md +174 -0
  76. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +220 -0
  77. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +150 -0
  78. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +293 -0
@@ -0,0 +1,376 @@
1
+ # CLAUDE.md - Claude Code Instructions
2
+
3
+ > Hono 서버 프레임워크 프로젝트 작업 지침
4
+
5
+ ---
6
+
7
+ ## 🚨 STOP - 작업 전 필수 확인
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────┐
11
+ │ 이 프로젝트에서 작업하기 전에 이 문서를 끝까지 읽으세요. │
12
+ │ 특히 ⛔ NEVER DO 섹션의 규칙은 절대 위반하지 마세요. │
13
+ │ │
14
+ │ 📖 작업 유형별 상세 문서: docs/ 폴더 참조 │
15
+ └─────────────────────────────────────────────────────────────┘
16
+ ```
17
+
18
+ ---
19
+
20
+ ## ⛔ NEVER DO (절대 금지 - 예외 없음)
21
+
22
+ ### Git 커밋 금지 사항
23
+ ```
24
+ ❌ "Generated with Claude Code" 포함 금지
25
+ ❌ "🤖" 또는 AI 관련 이모지 포함 금지
26
+ ❌ "Co-Authored-By:" 헤더 포함 금지
27
+ ❌ AI/봇이 작성했다는 어떤 표시도 금지
28
+ ❌ 커밋 메시지 여러 줄 작성 금지
29
+ ❌ 커밋 메시지에 이모지 사용 금지
30
+ ```
31
+
32
+ ### Prisma 금지 사항
33
+ ```
34
+ ❌ prisma db push 자동 실행 금지
35
+ ❌ prisma migrate 자동 실행 금지
36
+ ❌ prisma generate 자동 실행 금지
37
+ ❌ schema.prisma 임의 변경 금지 (요청된 것만)
38
+ ```
39
+
40
+ ### API 구현 금지 사항
41
+ ```
42
+ ❌ handler 내부에서 수동 검증 금지 (zValidator 사용)
43
+ ❌ handler 내부에서 수동 인증 체크 금지 (middleware 사용)
44
+ ❌ app.onError 없이 에러 처리 금지
45
+ ❌ HTTPException 없이 에러 throw 금지
46
+ ```
47
+
48
+ ### 코드 검색 금지 사항
49
+ ```
50
+ ❌ grep, rg 등 기본 검색 도구 사용 금지
51
+ ❌ find 명령어로 코드 검색 금지
52
+ ✅ 코드베이스 검색 시 sgrep 사용 필수
53
+ ```
54
+
55
+ ---
56
+
57
+ ## ✅ ALWAYS DO (필수 실행)
58
+
59
+ ### 1. 작업 전: 관련 문서 읽기
60
+ ```
61
+ API 작업 → docs/library/hono/ 읽기
62
+ DB 작업 → docs/library/prisma/ 읽기
63
+ 검증 작업 → docs/library/zod/ 읽기
64
+ 배포 작업 → docs/deployment/ 읽기
65
+ ```
66
+
67
+ ### 2. MCP 도구 적극 활용
68
+ ```
69
+ 코드베이스 검색 → sgrep 사용 (grep/rg 금지)
70
+ 복잡한 분석/디버깅 → Sequential Thinking 사용
71
+ 라이브러리 문서 → Context7 사용
72
+ ```
73
+ **상세**: `docs/mcp/` 참고
74
+
75
+ ### 3. 복잡한 작업 시: Gemini Review 실행
76
+ ```
77
+ 아키텍처 설계/변경 → gemini-review (architecture)
78
+ 구현 계획 검증 → gemini-review (plan)
79
+ 복잡한 코드 리뷰 → gemini-review (code)
80
+ ```
81
+
82
+ **실행 조건**:
83
+ - 3개 이상 파일 수정하는 기능 구현
84
+ - 새로운 아키텍처 패턴 도입
85
+ - 보안 관련 코드 (인증, 권한, 암호화)
86
+ - 성능 크리티컬 코드
87
+
88
+ **상세**: `docs/skills/gemini-review/SKILL.md` 참고
89
+
90
+ ### 4. 작업 완료 후: Git 커밋
91
+ ```bash
92
+ git add .
93
+ git commit -m "<prefix>: <설명>"
94
+ ```
95
+
96
+ **커밋 형식**: `<prefix>: <설명>` (한 줄, 본문 없음)
97
+
98
+ **Prefix**: `feat` | `fix` | `refactor` | `style` | `docs` | `test` | `chore` | `perf` | `ci`
99
+
100
+ **예시**:
101
+ ```bash
102
+ feat: 사용자 인증 API 추가
103
+ fix: JWT 토큰 검증 오류 수정
104
+ docs: API 문서 업데이트
105
+ ```
106
+
107
+ ---
108
+
109
+ ## 📚 문서 참조 테이블
110
+
111
+ | 작업 | 문서 경로 | 필독 여부 |
112
+ |------|----------|----------|
113
+ | **Git 규칙** | `docs/git/index.md` | 🔴 필수 |
114
+ | **MCP 도구** | `docs/mcp/` | 🔴 필수 |
115
+ | **Gemini Review** | `docs/skills/gemini-review/` | 🟡 복잡한 작업 시 |
116
+ | **API 개발** | `docs/library/hono/` | 🔴 필수 |
117
+ | **DB** | `docs/library/prisma/` | 🟡 해당 시 |
118
+ | **검증** | `docs/library/zod/` | 🟡 해당 시 |
119
+ | **배포** | `docs/deployment/` | 🟡 해당 시 |
120
+
121
+ ---
122
+
123
+ ## 🛠 Tech Stack (버전 주의)
124
+
125
+ | 기술 | 버전 | 주의사항 |
126
+ |------|------|----------|
127
+ | Hono | 최신 | Web Standards 기반 서버 프레임워크 |
128
+ | TypeScript | 5.x | strict mode |
129
+ | Prisma | **7.x** | `prisma-client` (js 아님), output 필수 |
130
+ | Zod | **4.x** | `z.email()`, `z.url()` (string().email() 아님) |
131
+ | @hono/zod-validator | 최신 | Zod 검증 미들웨어 |
132
+
133
+ ---
134
+
135
+ ## 📁 Directory Structure
136
+
137
+ ```
138
+ src/
139
+ ├── index.ts # Entry point
140
+ ├── routes/ # 라우트 모듈
141
+ │ ├── index.ts # 라우트 통합
142
+ │ ├── users.ts # /users 라우트
143
+ │ └── posts.ts # /posts 라우트
144
+ ├── middleware/ # 미들웨어
145
+ │ ├── auth.ts # 인증 미들웨어
146
+ │ └── logger.ts # 로깅 미들웨어
147
+ ├── validators/ # Zod 스키마
148
+ │ ├── user.ts # 사용자 스키마
149
+ │ └── post.ts # 게시글 스키마
150
+ ├── services/ # 비즈니스 로직
151
+ │ └── user.service.ts # 사용자 서비스
152
+ ├── database/ # DB 연결
153
+ │ └── prisma.ts # Prisma Client
154
+ ├── types/ # 타입 정의
155
+ │ └── env.d.ts # 환경변수 타입
156
+ └── lib/ # 유틸리티
157
+ └── errors.ts # 커스텀 에러
158
+ ```
159
+
160
+ ---
161
+
162
+ ## 🔧 Code Conventions
163
+
164
+ ### File Naming
165
+ - **kebab-case**: `user-service.ts`, `auth-middleware.ts`
166
+ - **라우트 파일**: `users.ts`, `posts.ts`
167
+
168
+ ### TypeScript
169
+ - `const` 선언 사용 (function 대신)
170
+ - 명시적 return type
171
+ - `interface` (객체) / `type` (유니온)
172
+ - `any` 금지 → `unknown` 사용
173
+
174
+ ### Import
175
+ ```typescript
176
+ // @/ → ./src/
177
+ import { prisma } from '@/database/prisma'
178
+ import { userSchema } from '@/validators/user'
179
+ ```
180
+
181
+ **순서**: 외부 → 내부(@/) → 상대경로 → type imports
182
+
183
+ ---
184
+
185
+ ## 📝 Quick Patterns (복사용)
186
+
187
+ ### App 설정
188
+ ```typescript
189
+ import { Hono } from 'hono'
190
+ import { HTTPException } from 'hono/http-exception'
191
+
192
+ type Bindings = {
193
+ DATABASE_URL: string
194
+ JWT_SECRET: string
195
+ }
196
+
197
+ const app = new Hono<{ Bindings: Bindings }>()
198
+
199
+ // 글로벌 에러 핸들러
200
+ app.onError((err, c) => {
201
+ if (err instanceof HTTPException) {
202
+ return c.json({ error: err.message }, err.status)
203
+ }
204
+ console.error(err)
205
+ return c.json({ error: 'Internal Server Error' }, 500)
206
+ })
207
+
208
+ // 404 핸들러
209
+ app.notFound((c) => {
210
+ return c.json({ error: 'Not Found', path: c.req.path }, 404)
211
+ })
212
+
213
+ export default app
214
+ ```
215
+
216
+ ### 라우트 + Zod 검증 (GET)
217
+ ```typescript
218
+ import { Hono } from 'hono'
219
+ import { zValidator } from '@hono/zod-validator'
220
+ import { z } from 'zod'
221
+
222
+ const app = new Hono()
223
+
224
+ // ✅ 올바른 패턴: zValidator 사용
225
+ const querySchema = z.object({
226
+ page: z.coerce.number().positive().optional(),
227
+ limit: z.coerce.number().max(100).optional(),
228
+ })
229
+
230
+ app.get('/users', zValidator('query', querySchema), (c) => {
231
+ const { page = 1, limit = 10 } = c.req.valid('query')
232
+ return c.json({ page, limit, users: [] })
233
+ })
234
+ ```
235
+
236
+ ### 라우트 + Zod 검증 (POST)
237
+ ```typescript
238
+ import { zValidator } from '@hono/zod-validator'
239
+ import { z } from 'zod'
240
+
241
+ // ✅ Zod v4 문법
242
+ const createUserSchema = z.object({
243
+ email: z.email(), // ✅ v4
244
+ name: z.string().min(1).trim(),
245
+ website: z.url().optional(), // ✅ v4
246
+ })
247
+
248
+ app.post('/users', zValidator('json', createUserSchema), async (c) => {
249
+ const data = c.req.valid('json')
250
+ // prisma.user.create({ data })
251
+ return c.json({ user: data }, 201)
252
+ })
253
+ ```
254
+
255
+ ### ❌ 잘못된 패턴 (금지)
256
+ ```typescript
257
+ // ❌ handler 내부에서 수동 검증 금지
258
+ app.post('/users', async (c) => {
259
+ const body = await c.req.json()
260
+ // ❌ 이렇게 하지 마세요!
261
+ if (!body.email) {
262
+ return c.json({ error: 'Email required' }, 400)
263
+ }
264
+ })
265
+
266
+ // ❌ 일반 Error throw 금지
267
+ app.get('/user/:id', async (c) => {
268
+ throw new Error('Not found') // ❌ HTTPException 사용해야 함
269
+ })
270
+ ```
271
+
272
+ ### HTTPException 사용
273
+ ```typescript
274
+ import { HTTPException } from 'hono/http-exception'
275
+
276
+ app.get('/users/:id', async (c) => {
277
+ const id = c.req.param('id')
278
+ const user = await prisma.user.findUnique({ where: { id } })
279
+
280
+ if (!user) {
281
+ throw new HTTPException(404, { message: 'User not found' })
282
+ }
283
+
284
+ return c.json({ user })
285
+ })
286
+ ```
287
+
288
+ ### 인증 미들웨어
289
+ ```typescript
290
+ import { createMiddleware } from 'hono/factory'
291
+ import { HTTPException } from 'hono/http-exception'
292
+
293
+ type Env = {
294
+ Variables: {
295
+ userId: string
296
+ }
297
+ }
298
+
299
+ export const authMiddleware = createMiddleware<Env>(async (c, next) => {
300
+ const token = c.req.header('Authorization')?.replace('Bearer ', '')
301
+
302
+ if (!token) {
303
+ throw new HTTPException(401, { message: 'Unauthorized' })
304
+ }
305
+
306
+ // JWT 검증 로직
307
+ const payload = verifyToken(token)
308
+ c.set('userId', payload.sub)
309
+
310
+ await next()
311
+ })
312
+
313
+ // 사용
314
+ app.get('/me', authMiddleware, (c) => {
315
+ const userId = c.get('userId')
316
+ return c.json({ userId })
317
+ })
318
+ ```
319
+
320
+ ### Zod Schema (v4 문법!)
321
+ ```typescript
322
+ import { z } from 'zod'
323
+
324
+ const schema = z.object({
325
+ email: z.email(), // ✅ v4
326
+ name: z.string().min(1).trim(),
327
+ website: z.url().optional(), // ✅ v4
328
+ age: z.number().min(0),
329
+ })
330
+
331
+ // 커스텀 에러 핸들링
332
+ app.post(
333
+ '/users',
334
+ zValidator('json', schema, (result, c) => {
335
+ if (!result.success) {
336
+ return c.json({ errors: result.error.flatten() }, 400)
337
+ }
338
+ }),
339
+ (c) => {
340
+ const data = c.req.valid('json')
341
+ return c.json({ user: data }, 201)
342
+ }
343
+ )
344
+ ```
345
+
346
+ ### RPC Client (Type-safe)
347
+ ```typescript
348
+ // server.ts
349
+ const app = new Hono()
350
+ .get('/users', (c) => c.json({ users: [] }))
351
+ .post('/users', zValidator('json', createUserSchema), (c) => {
352
+ const data = c.req.valid('json')
353
+ return c.json({ user: data }, 201)
354
+ })
355
+
356
+ export type AppType = typeof app
357
+
358
+ // client.ts
359
+ import { hc } from 'hono/client'
360
+ import type { AppType } from './server'
361
+
362
+ const client = hc<AppType>('http://localhost:8787/')
363
+
364
+ // Type-safe API 호출
365
+ const res = await client.users.$get()
366
+ const data = await res.json() // { users: [] }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## 🔗 Quick Links
372
+
373
+ - [Hono 가이드](./docs/library/hono/index.md)
374
+ - [Git 규칙](./docs/git/index.md)
375
+ - [MCP 가이드](./docs/mcp/index.md)
376
+ - [배포 가이드](./docs/deployment/index.md)
@@ -0,0 +1,328 @@
1
+ # Cloudflare Workers 배포
2
+
3
+ > Hono + Cloudflare Workers 상세 가이드
4
+
5
+ ---
6
+
7
+ ## 프로젝트 생성
8
+
9
+ ```bash
10
+ npm create hono@latest my-app
11
+ # cloudflare-workers 템플릿 선택
12
+
13
+ cd my-app
14
+ npm install
15
+ ```
16
+
17
+ ---
18
+
19
+ ## 프로젝트 구조
20
+
21
+ ```
22
+ my-app/
23
+ ├── src/
24
+ │ └── index.ts
25
+ ├── wrangler.toml
26
+ ├── package.json
27
+ └── tsconfig.json
28
+ ```
29
+
30
+ ---
31
+
32
+ ## 기본 설정
33
+
34
+ ### wrangler.toml
35
+
36
+ ```toml
37
+ name = "my-hono-app"
38
+ main = "src/index.ts"
39
+ compatibility_date = "2024-01-01"
40
+ compatibility_flags = ["nodejs_compat"]
41
+
42
+ [vars]
43
+ NODE_ENV = "production"
44
+
45
+ # KV Namespace
46
+ [[kv_namespaces]]
47
+ binding = "MY_KV"
48
+ id = "your-kv-namespace-id"
49
+
50
+ # D1 Database
51
+ [[d1_databases]]
52
+ binding = "DB"
53
+ database_name = "my-database"
54
+ database_id = "your-database-id"
55
+
56
+ # R2 Bucket
57
+ [[r2_buckets]]
58
+ binding = "MY_BUCKET"
59
+ bucket_name = "my-bucket"
60
+ ```
61
+
62
+ ### src/index.ts
63
+
64
+ ```typescript
65
+ import { Hono } from 'hono'
66
+
67
+ type Bindings = {
68
+ NODE_ENV: string
69
+ MY_KV: KVNamespace
70
+ DB: D1Database
71
+ MY_BUCKET: R2Bucket
72
+ }
73
+
74
+ const app = new Hono<{ Bindings: Bindings }>()
75
+
76
+ app.get('/', (c) => {
77
+ return c.json({ message: 'Hello Cloudflare Workers!' })
78
+ })
79
+
80
+ export default app
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Bindings 사용
86
+
87
+ ### KV Namespace
88
+
89
+ ```typescript
90
+ app.get('/kv/:key', async (c) => {
91
+ const key = c.req.param('key')
92
+ const value = await c.env.MY_KV.get(key)
93
+ return c.json({ key, value })
94
+ })
95
+
96
+ app.put('/kv/:key', async (c) => {
97
+ const key = c.req.param('key')
98
+ const { value } = await c.req.json()
99
+ await c.env.MY_KV.put(key, value)
100
+ return c.json({ success: true })
101
+ })
102
+ ```
103
+
104
+ ### D1 Database
105
+
106
+ ```typescript
107
+ app.get('/users', async (c) => {
108
+ const { results } = await c.env.DB.prepare(
109
+ 'SELECT * FROM users'
110
+ ).all()
111
+ return c.json({ users: results })
112
+ })
113
+
114
+ app.post('/users', async (c) => {
115
+ const { name, email } = await c.req.json()
116
+ const { success } = await c.env.DB.prepare(
117
+ 'INSERT INTO users (name, email) VALUES (?, ?)'
118
+ ).bind(name, email).run()
119
+ return c.json({ success }, 201)
120
+ })
121
+ ```
122
+
123
+ ### R2 Bucket
124
+
125
+ ```typescript
126
+ app.put('/upload/:key', async (c) => {
127
+ const key = c.req.param('key')
128
+ await c.env.MY_BUCKET.put(key, c.req.body)
129
+ return c.json({ success: true })
130
+ })
131
+
132
+ app.get('/download/:key', async (c) => {
133
+ const key = c.req.param('key')
134
+ const object = await c.env.MY_BUCKET.get(key)
135
+
136
+ if (!object) {
137
+ return c.notFound()
138
+ }
139
+
140
+ return new Response(object.body, {
141
+ headers: {
142
+ 'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',
143
+ },
144
+ })
145
+ })
146
+ ```
147
+
148
+ ---
149
+
150
+ ## 환경 변수
151
+
152
+ ### 로컬 개발 (.dev.vars)
153
+
154
+ ```
155
+ DATABASE_URL=postgresql://...
156
+ JWT_SECRET=dev-secret
157
+ API_KEY=dev-api-key
158
+ ```
159
+
160
+ ### 시크릿 설정
161
+
162
+ ```bash
163
+ # 시크릿 추가
164
+ npx wrangler secret put JWT_SECRET
165
+ npx wrangler secret put DATABASE_URL
166
+
167
+ # 시크릿 목록
168
+ npx wrangler secret list
169
+
170
+ # 시크릿 삭제
171
+ npx wrangler secret delete JWT_SECRET
172
+ ```
173
+
174
+ ---
175
+
176
+ ## 타입 생성
177
+
178
+ ```bash
179
+ # wrangler.toml 기반 타입 생성
180
+ npx wrangler types
181
+
182
+ # 또는 환경별 타입 생성
183
+ npx wrangler types --env-interface CloudflareBindings
184
+ ```
185
+
186
+ ### worker-configuration.d.ts
187
+
188
+ ```typescript
189
+ interface CloudflareBindings {
190
+ NODE_ENV: string
191
+ MY_KV: KVNamespace
192
+ DB: D1Database
193
+ MY_BUCKET: R2Bucket
194
+ JWT_SECRET: string
195
+ }
196
+ ```
197
+
198
+ ### tsconfig.json
199
+
200
+ ```json
201
+ {
202
+ "compilerOptions": {
203
+ "types": [
204
+ "@cloudflare/workers-types",
205
+ "./worker-configuration.d.ts"
206
+ ]
207
+ }
208
+ }
209
+ ```
210
+
211
+ ---
212
+
213
+ ## 배포
214
+
215
+ ### 개발 서버
216
+
217
+ ```bash
218
+ npm run dev
219
+ # 또는
220
+ npx wrangler dev
221
+ ```
222
+
223
+ ### 프로덕션 배포
224
+
225
+ ```bash
226
+ npm run deploy
227
+ # 또는
228
+ npx wrangler deploy
229
+ ```
230
+
231
+ ### 환경별 배포
232
+
233
+ ```bash
234
+ # staging
235
+ npx wrangler deploy --env staging
236
+
237
+ # production
238
+ npx wrangler deploy --env production
239
+ ```
240
+
241
+ ### wrangler.toml (환경별)
242
+
243
+ ```toml
244
+ name = "my-app"
245
+ main = "src/index.ts"
246
+
247
+ [env.staging]
248
+ name = "my-app-staging"
249
+ vars = { NODE_ENV = "staging" }
250
+
251
+ [env.production]
252
+ name = "my-app-production"
253
+ vars = { NODE_ENV = "production" }
254
+ ```
255
+
256
+ ---
257
+
258
+ ## GitHub Actions
259
+
260
+ ```yaml
261
+ name: Deploy to Cloudflare Workers
262
+
263
+ on:
264
+ push:
265
+ branches:
266
+ - main
267
+
268
+ jobs:
269
+ deploy:
270
+ runs-on: ubuntu-latest
271
+ steps:
272
+ - uses: actions/checkout@v4
273
+
274
+ - name: Setup Node.js
275
+ uses: actions/setup-node@v4
276
+ with:
277
+ node-version: '20'
278
+
279
+ - name: Install dependencies
280
+ run: npm ci
281
+
282
+ - name: Deploy
283
+ uses: cloudflare/wrangler-action@v3
284
+ with:
285
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
286
+ # 환경 지정 시
287
+ # command: deploy --env production
288
+ ```
289
+
290
+ ### GitHub Secrets 설정
291
+
292
+ 1. Cloudflare Dashboard → My Profile → API Tokens
293
+ 2. "Create Token" → "Edit Cloudflare Workers" 템플릿 사용
294
+ 3. GitHub Repository → Settings → Secrets → `CLOUDFLARE_API_TOKEN` 추가
295
+
296
+ ---
297
+
298
+ ## 로깅 및 모니터링
299
+
300
+ ### 실시간 로그
301
+
302
+ ```bash
303
+ npx wrangler tail
304
+ ```
305
+
306
+ ### 커스텀 로깅
307
+
308
+ ```typescript
309
+ app.use(async (c, next) => {
310
+ const start = Date.now()
311
+ await next()
312
+ const duration = Date.now() - start
313
+
314
+ console.log({
315
+ method: c.req.method,
316
+ path: c.req.path,
317
+ status: c.res.status,
318
+ duration: `${duration}ms`,
319
+ })
320
+ })
321
+ ```
322
+
323
+ ---
324
+
325
+ ## 관련 문서
326
+
327
+ - [배포 개요](./index.md)
328
+ - [Hono 기본](../library/hono/index.md)