@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.
Files changed (63) hide show
  1. package/dist/index.js +129 -5
  2. package/package.json +2 -2
  3. package/templates/hono/CLAUDE.md +20 -2
  4. package/templates/hono/docs/architecture/architecture.md +909 -0
  5. package/templates/hono/docs/commands/git.md +275 -0
  6. package/templates/hono/docs/deployment/cloudflare.md +527 -190
  7. package/templates/hono/docs/deployment/docker.md +514 -0
  8. package/templates/hono/docs/deployment/index.md +179 -214
  9. package/templates/hono/docs/deployment/railway.md +416 -0
  10. package/templates/hono/docs/deployment/vercel.md +567 -0
  11. package/templates/hono/docs/library/ai-sdk/index.md +427 -0
  12. package/templates/hono/docs/library/ai-sdk/openrouter.md +479 -0
  13. package/templates/hono/docs/library/ai-sdk/providers.md +468 -0
  14. package/templates/hono/docs/library/ai-sdk/streaming.md +447 -0
  15. package/templates/hono/docs/library/ai-sdk/structured-output.md +493 -0
  16. package/templates/hono/docs/library/ai-sdk/tools.md +513 -0
  17. package/templates/hono/docs/library/hono/env-setup.md +458 -0
  18. package/templates/hono/docs/library/hono/index.md +1 -3
  19. package/templates/hono/docs/library/pino/index.md +437 -0
  20. package/templates/hono/docs/library/prisma/cloudflare-d1.md +503 -0
  21. package/templates/hono/docs/library/prisma/config.md +362 -0
  22. package/templates/hono/docs/library/prisma/index.md +86 -13
  23. package/templates/hono/docs/skills/gemini-review/SKILL.md +116 -116
  24. package/templates/hono/docs/skills/gemini-review/references/checklists.md +125 -125
  25. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +191 -191
  26. package/templates/npx/CLAUDE.md +309 -0
  27. package/templates/npx/docs/commands/git.md +275 -0
  28. package/templates/npx/docs/library/commander/index.md +164 -0
  29. package/templates/npx/docs/library/fs-extra/index.md +171 -0
  30. package/templates/npx/docs/library/prompts/index.md +253 -0
  31. package/templates/npx/docs/mcp/index.md +60 -0
  32. package/templates/npx/docs/skills/gemini-review/SKILL.md +220 -0
  33. package/templates/npx/docs/skills/gemini-review/references/checklists.md +134 -0
  34. package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +301 -0
  35. package/templates/tanstack-start/CLAUDE.md +43 -5
  36. package/templates/tanstack-start/docs/architecture/architecture.md +134 -4
  37. package/templates/tanstack-start/docs/commands/git.md +275 -0
  38. package/templates/tanstack-start/docs/deployment/cloudflare.md +223 -50
  39. package/templates/tanstack-start/docs/deployment/index.md +320 -30
  40. package/templates/tanstack-start/docs/deployment/nitro.md +195 -14
  41. package/templates/tanstack-start/docs/deployment/railway.md +302 -150
  42. package/templates/tanstack-start/docs/deployment/vercel.md +345 -75
  43. package/templates/tanstack-start/docs/guides/best-practices.md +203 -1
  44. package/templates/tanstack-start/docs/guides/env-setup.md +450 -0
  45. package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +472 -0
  46. package/templates/tanstack-start/docs/library/ai-sdk/index.md +264 -0
  47. package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +371 -0
  48. package/templates/tanstack-start/docs/library/ai-sdk/providers.md +403 -0
  49. package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +320 -0
  50. package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +454 -0
  51. package/templates/tanstack-start/docs/library/ai-sdk/tools.md +473 -0
  52. package/templates/tanstack-start/docs/library/pino/index.md +320 -0
  53. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +404 -0
  54. package/templates/tanstack-start/docs/library/prisma/config.md +377 -0
  55. package/templates/tanstack-start/docs/library/prisma/index.md +3 -5
  56. package/templates/tanstack-start/docs/library/prisma/schema.md +123 -25
  57. package/templates/tanstack-start/docs/library/prisma/setup.md +0 -7
  58. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +80 -2
  59. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +116 -116
  60. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +138 -144
  61. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +186 -187
  62. package/templates/hono/docs/git/index.md +0 -180
  63. package/templates/tanstack-start/docs/git/index.md +0 -203
@@ -0,0 +1,909 @@
1
+ # Architecture
2
+
3
+ Hono 서버 애플리케이션의 기술 아키텍처 가이드입니다.
4
+
5
+ ## System Overview
6
+
7
+ ```
8
+ ┌─────────────────────────────────────────────────────────────────┐
9
+ │ Client (Browser/App) │
10
+ │ │
11
+ │ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ │
12
+ │ │ HTTP Client │───▶│ hono/client │───▶│ React UI │ │
13
+ │ │ (fetch/axios) │◀───│ (RPC Client) │◀───│ (Components) │ │
14
+ │ └────────────────┘ └───────┬────────┘ └───────────────┘ │
15
+ │ │ │
16
+ └────────────────────────────────┼─────────────────────────────────┘
17
+
18
+
19
+ ┌─────────────────────────────────────────────────────────────────┐
20
+ │ Hono Server │
21
+ │ │
22
+ │ ┌────────────────────────────────────────────────────────────┐ │
23
+ │ │ Middleware Stack │ │
24
+ │ │ - logger → 요청 로깅 │ │
25
+ │ │ - cors → CORS 설정 │ │
26
+ │ │ - secureHeaders → 보안 헤더 │ │
27
+ │ │ - authMiddleware → 인증 처리 │ │
28
+ │ └────────────────────────┬───────────────────────────────────┘ │
29
+ │ │ │
30
+ │ ┌────────────────────────▼───────────────────────────────────┐ │
31
+ │ │ Routes Layer │ │
32
+ │ │ - routes/users.ts → /users/* │ │
33
+ │ │ - routes/posts.ts → /posts/* │ │
34
+ │ │ - routes/auth.ts → /auth/* │ │
35
+ │ └────────────────────────┬───────────────────────────────────┘ │
36
+ │ │ │
37
+ │ ┌────────────────────────▼───────────────────────────────────┐ │
38
+ │ │ Validation Layer │ │
39
+ │ │ - @hono/zod-validator → 요청 검증 │ │
40
+ │ │ - Zod v4 Schemas → 타입 안전 검증 │ │
41
+ │ └────────────────────────┬───────────────────────────────────┘ │
42
+ │ │ │
43
+ │ ┌────────────────────────▼───────────────────────────────────┐ │
44
+ │ │ Services Layer │ │
45
+ │ │ - Business Logic │ │
46
+ │ │ - Data Transformation │ │
47
+ │ │ - Error Handling (HTTPException) │ │
48
+ │ └────────────────────────┬───────────────────────────────────┘ │
49
+ │ │ │
50
+ └───────────────────────────┼──────────────────────────────────────┘
51
+
52
+
53
+ ┌─────────────────────────────────────────────────────────────────┐
54
+ │ Database Layer │
55
+ │ │
56
+ │ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ │
57
+ │ │ Prisma Client │───▶│ PostgreSQL │ │ Cloudflare │ │
58
+ │ │ (ORM v7) │ │ (Primary) │ │ D1/KV/R2 │ │
59
+ │ └────────────────┘ └────────────────┘ └───────────────┘ │
60
+ │ │
61
+ └─────────────────────────────────────────────────────────────────┘
62
+ ```
63
+
64
+ ## Project Structure
65
+
66
+ ```
67
+ my-app/
68
+ ├── src/
69
+ │ ├── index.ts # Entry point & App 설정
70
+ │ ├── routes/ # 라우트 모듈
71
+ │ │ ├── index.ts # 라우트 통합 (re-export)
72
+ │ │ ├── users.ts # /users/* 라우트
73
+ │ │ ├── posts.ts # /posts/* 라우트
74
+ │ │ └── auth.ts # /auth/* 라우트
75
+ │ ├── middleware/ # 커스텀 미들웨어
76
+ │ │ ├── index.ts # re-export
77
+ │ │ ├── auth.ts # 인증 미들웨어
78
+ │ │ ├── logger.ts # 로깅 미들웨어
79
+ │ │ └── rate-limit.ts # 레이트 리밋 미들웨어
80
+ │ ├── validators/ # Zod 스키마 정의
81
+ │ │ ├── index.ts # re-export
82
+ │ │ ├── user.ts # 사용자 스키마
83
+ │ │ ├── post.ts # 게시글 스키마
84
+ │ │ └── common.ts # 공통 스키마 (pagination 등)
85
+ │ ├── services/ # 비즈니스 로직 레이어
86
+ │ │ ├── user/
87
+ │ │ │ ├── index.ts # re-export
88
+ │ │ │ ├── queries.ts # 조회 로직
89
+ │ │ │ └── mutations.ts # 생성/수정/삭제 로직
90
+ │ │ └── post/
91
+ │ │ ├── index.ts
92
+ │ │ ├── queries.ts
93
+ │ │ └── mutations.ts
94
+ │ ├── database/ # 데이터베이스 연결
95
+ │ │ └── prisma.ts # Prisma Client 싱글톤
96
+ │ ├── types/ # 타입 정의
97
+ │ │ ├── index.ts # re-export
98
+ │ │ ├── env.d.ts # 환경변수 타입
99
+ │ │ └── bindings.ts # Cloudflare Bindings 타입
100
+ │ └── lib/ # 공통 유틸리티
101
+ │ ├── errors.ts # 커스텀 에러 클래스
102
+ │ ├── jwt.ts # JWT 유틸리티
103
+ │ └── utils.ts # 범용 유틸리티
104
+ ├── prisma/
105
+ │ ├── schema.prisma # Prisma 스키마
106
+ │ └── generated/ # Prisma Client 출력
107
+ │ └── client/
108
+ ├── wrangler.toml # Cloudflare Workers 설정
109
+ ├── .dev.vars # 로컬 환경변수
110
+ ├── package.json
111
+ └── tsconfig.json
112
+ ```
113
+
114
+ ## Layer Architecture
115
+
116
+ ### 1. Entry Point (src/index.ts)
117
+
118
+ 애플리케이션의 진입점으로, 전역 설정과 라우트 마운트를 담당합니다.
119
+
120
+ ```typescript
121
+ // src/index.ts
122
+ import { Hono } from 'hono'
123
+ import { logger } from 'hono/logger'
124
+ import { cors } from 'hono/cors'
125
+ import { secureHeaders } from 'hono/secure-headers'
126
+ import { HTTPException } from 'hono/http-exception'
127
+ import { users } from './routes/users'
128
+ import { posts } from './routes/posts'
129
+ import { auth } from './routes/auth'
130
+
131
+ type Bindings = {
132
+ DATABASE_URL: string
133
+ JWT_SECRET: string
134
+ NODE_ENV: string
135
+ }
136
+
137
+ type Variables = {
138
+ userId: string
139
+ }
140
+
141
+ const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()
142
+
143
+ // 글로벌 미들웨어
144
+ app.use(logger())
145
+ app.use(secureHeaders())
146
+ app.use('/api/*', cors())
147
+
148
+ // 글로벌 에러 핸들러
149
+ app.onError((err, c) => {
150
+ if (err instanceof HTTPException) {
151
+ return c.json({ error: err.message }, err.status)
152
+ }
153
+ console.error(err)
154
+ return c.json({ error: 'Internal Server Error' }, 500)
155
+ })
156
+
157
+ // 404 핸들러
158
+ app.notFound((c) => {
159
+ return c.json({ error: 'Not Found', path: c.req.path }, 404)
160
+ })
161
+
162
+ // 라우트 마운트
163
+ app.route('/api/users', users)
164
+ app.route('/api/posts', posts)
165
+ app.route('/api/auth', auth)
166
+
167
+ // Health Check
168
+ app.get('/health', (c) => c.json({ status: 'ok' }))
169
+
170
+ export default app
171
+ ```
172
+
173
+ ### 2. Routes Layer (Presentation)
174
+
175
+ 파일 기반으로 라우트를 모듈화하여 관리합니다.
176
+
177
+ ```
178
+ routes/
179
+ ├── index.ts # 라우트 통합
180
+ ├── users.ts # /users 라우트
181
+ ├── posts.ts # /posts 라우트
182
+ └── auth.ts # /auth 라우트
183
+ ```
184
+
185
+ **특징**:
186
+ - 각 파일은 독립적인 Hono 인스턴스
187
+ - zValidator로 요청 검증
188
+ - 미들웨어 적용 가능
189
+ - RPC 타입 추론 지원
190
+
191
+ ```typescript
192
+ // routes/users.ts
193
+ import { Hono } from 'hono'
194
+ import { zValidator } from '@hono/zod-validator'
195
+ import { authMiddleware } from '@/middleware/auth'
196
+ import { createUserSchema, updateUserSchema, userIdSchema } from '@/validators/user'
197
+ import { paginationSchema } from '@/validators/common'
198
+ import { getUsers, getUserById, createUser, updateUser, deleteUser } from '@/services/user'
199
+
200
+ const users = new Hono()
201
+
202
+ // 목록 조회 (공개)
203
+ users.get('/', zValidator('query', paginationSchema), async (c) => {
204
+ const { page, limit } = c.req.valid('query')
205
+ const result = await getUsers({ page, limit })
206
+ return c.json(result)
207
+ })
208
+
209
+ // 단일 조회 (공개)
210
+ users.get('/:id', zValidator('param', userIdSchema), async (c) => {
211
+ const { id } = c.req.valid('param')
212
+ const user = await getUserById(id)
213
+ return c.json({ user })
214
+ })
215
+
216
+ // 생성 (인증 필요)
217
+ users.post(
218
+ '/',
219
+ authMiddleware,
220
+ zValidator('json', createUserSchema),
221
+ async (c) => {
222
+ const data = c.req.valid('json')
223
+ const user = await createUser(data)
224
+ return c.json({ user }, 201)
225
+ }
226
+ )
227
+
228
+ // 수정 (인증 필요)
229
+ users.put(
230
+ '/:id',
231
+ authMiddleware,
232
+ zValidator('param', userIdSchema),
233
+ zValidator('json', updateUserSchema),
234
+ async (c) => {
235
+ const { id } = c.req.valid('param')
236
+ const data = c.req.valid('json')
237
+ const user = await updateUser(id, data)
238
+ return c.json({ user })
239
+ }
240
+ )
241
+
242
+ // 삭제 (인증 필요)
243
+ users.delete(
244
+ '/:id',
245
+ authMiddleware,
246
+ zValidator('param', userIdSchema),
247
+ async (c) => {
248
+ const { id } = c.req.valid('param')
249
+ await deleteUser(id)
250
+ return c.json({ success: true })
251
+ }
252
+ )
253
+
254
+ export { users }
255
+ ```
256
+
257
+ ### 3. Middleware Layer
258
+
259
+ 요청/응답 파이프라인을 처리합니다.
260
+
261
+ ```
262
+ middleware/
263
+ ├── index.ts # re-export
264
+ ├── auth.ts # 인증 미들웨어
265
+ ├── logger.ts # 로깅 미들웨어
266
+ └── rate-limit.ts # 레이트 리밋
267
+ ```
268
+
269
+ **규칙**:
270
+ - `createMiddleware`로 타입 안전 미들웨어 작성
271
+ - `HTTPException`으로 에러 처리
272
+ - `c.set()`으로 변수 전달
273
+
274
+ ```typescript
275
+ // middleware/auth.ts
276
+ import { createMiddleware } from 'hono/factory'
277
+ import { HTTPException } from 'hono/http-exception'
278
+ import { verifyToken } from '@/lib/jwt'
279
+
280
+ type Env = {
281
+ Bindings: {
282
+ JWT_SECRET: string
283
+ }
284
+ Variables: {
285
+ userId: string
286
+ }
287
+ }
288
+
289
+ export const authMiddleware = createMiddleware<Env>(async (c, next) => {
290
+ const token = c.req.header('Authorization')?.replace('Bearer ', '')
291
+
292
+ if (!token) {
293
+ throw new HTTPException(401, { message: 'Unauthorized' })
294
+ }
295
+
296
+ try {
297
+ const payload = await verifyToken(token, c.env.JWT_SECRET)
298
+ c.set('userId', payload.sub)
299
+ await next()
300
+ } catch {
301
+ throw new HTTPException(401, { message: 'Invalid token' })
302
+ }
303
+ })
304
+ ```
305
+
306
+ ### 4. Validators Layer (Input Validation)
307
+
308
+ Zod v4를 사용한 타입 안전 요청 검증을 담당합니다.
309
+
310
+ ```
311
+ validators/
312
+ ├── index.ts # re-export
313
+ ├── user.ts # 사용자 스키마
314
+ ├── post.ts # 게시글 스키마
315
+ └── common.ts # 공통 스키마
316
+ ```
317
+
318
+ **Zod v4 문법**:
319
+
320
+ ```typescript
321
+ // validators/user.ts
322
+ import { z } from 'zod'
323
+
324
+ // ✅ Zod v4 문법
325
+ export const createUserSchema = z.object({
326
+ email: z.email(), // ✅ v4: z.email()
327
+ name: z.string().min(1).max(100).trim(),
328
+ password: z.string().min(8),
329
+ website: z.url().optional(), // ✅ v4: z.url()
330
+ })
331
+
332
+ export const updateUserSchema = createUserSchema.partial().omit({ password: true })
333
+
334
+ export const userIdSchema = z.object({
335
+ id: z.string().uuid(),
336
+ })
337
+
338
+ // 타입 추출
339
+ export type CreateUserInput = z.infer<typeof createUserSchema>
340
+ export type UpdateUserInput = z.infer<typeof updateUserSchema>
341
+ ```
342
+
343
+ ```typescript
344
+ // validators/common.ts
345
+ import { z } from 'zod'
346
+
347
+ export const paginationSchema = z.object({
348
+ page: z.coerce.number().positive().optional().default(1),
349
+ limit: z.coerce.number().min(1).max(100).optional().default(10),
350
+ })
351
+
352
+ export const searchSchema = z.object({
353
+ q: z.string().min(1),
354
+ page: z.coerce.number().positive().optional(),
355
+ limit: z.coerce.number().max(100).optional(),
356
+ })
357
+
358
+ export type PaginationInput = z.infer<typeof paginationSchema>
359
+ ```
360
+
361
+ ### 5. Services Layer (Business Logic)
362
+
363
+ 비즈니스 로직을 라우트와 분리하여 관리합니다.
364
+
365
+ ```
366
+ services/
367
+ ├── user/
368
+ │ ├── index.ts # re-export
369
+ │ ├── queries.ts # 조회 로직
370
+ │ └── mutations.ts # 생성/수정/삭제 로직
371
+ └── post/
372
+ ├── index.ts
373
+ ├── queries.ts
374
+ └── mutations.ts
375
+ ```
376
+
377
+ **Queries** - 읽기 작업:
378
+
379
+ ```typescript
380
+ // services/user/queries.ts
381
+ import { HTTPException } from 'hono/http-exception'
382
+ import { prisma } from '@/database/prisma'
383
+ import type { PaginationInput } from '@/validators/common'
384
+
385
+ export const getUsers = async ({ page, limit }: PaginationInput) => {
386
+ const [users, total] = await Promise.all([
387
+ prisma.user.findMany({
388
+ skip: (page - 1) * limit,
389
+ take: limit,
390
+ orderBy: { createdAt: 'desc' },
391
+ select: {
392
+ id: true,
393
+ email: true,
394
+ name: true,
395
+ createdAt: true,
396
+ },
397
+ }),
398
+ prisma.user.count(),
399
+ ])
400
+
401
+ return {
402
+ users,
403
+ pagination: {
404
+ page,
405
+ limit,
406
+ total,
407
+ totalPages: Math.ceil(total / limit),
408
+ },
409
+ }
410
+ }
411
+
412
+ export const getUserById = async (id: string) => {
413
+ const user = await prisma.user.findUnique({
414
+ where: { id },
415
+ include: { posts: true },
416
+ })
417
+
418
+ if (!user) {
419
+ throw new HTTPException(404, { message: 'User not found' })
420
+ }
421
+
422
+ return user
423
+ }
424
+ ```
425
+
426
+ **Mutations** - 쓰기 작업:
427
+
428
+ ```typescript
429
+ // services/user/mutations.ts
430
+ import { HTTPException } from 'hono/http-exception'
431
+ import { prisma } from '@/database/prisma'
432
+ import type { CreateUserInput, UpdateUserInput } from '@/validators/user'
433
+
434
+ export const createUser = async (data: CreateUserInput) => {
435
+ // 중복 체크
436
+ const existing = await prisma.user.findUnique({
437
+ where: { email: data.email },
438
+ })
439
+
440
+ if (existing) {
441
+ throw new HTTPException(409, { message: 'Email already exists' })
442
+ }
443
+
444
+ // 비밀번호 해싱 (실제로는 bcrypt 사용)
445
+ const hashedPassword = await hashPassword(data.password)
446
+
447
+ return prisma.user.create({
448
+ data: {
449
+ ...data,
450
+ password: hashedPassword,
451
+ },
452
+ select: {
453
+ id: true,
454
+ email: true,
455
+ name: true,
456
+ createdAt: true,
457
+ },
458
+ })
459
+ }
460
+
461
+ export const updateUser = async (id: string, data: UpdateUserInput) => {
462
+ const user = await prisma.user.findUnique({ where: { id } })
463
+
464
+ if (!user) {
465
+ throw new HTTPException(404, { message: 'User not found' })
466
+ }
467
+
468
+ return prisma.user.update({
469
+ where: { id },
470
+ data,
471
+ select: {
472
+ id: true,
473
+ email: true,
474
+ name: true,
475
+ updatedAt: true,
476
+ },
477
+ })
478
+ }
479
+
480
+ export const deleteUser = async (id: string) => {
481
+ const user = await prisma.user.findUnique({ where: { id } })
482
+
483
+ if (!user) {
484
+ throw new HTTPException(404, { message: 'User not found' })
485
+ }
486
+
487
+ await prisma.user.delete({ where: { id } })
488
+ }
489
+ ```
490
+
491
+ ### 6. Database Layer (Data Access)
492
+
493
+ Prisma v7을 통한 데이터베이스 액세스를 담당합니다.
494
+
495
+ ```typescript
496
+ // database/prisma.ts
497
+ import { PrismaClient } from '../../prisma/generated/client'
498
+
499
+ const globalForPrisma = globalThis as unknown as {
500
+ prisma: PrismaClient | undefined
501
+ }
502
+
503
+ export const prisma =
504
+ globalForPrisma.prisma ??
505
+ new PrismaClient({
506
+ log: process.env.NODE_ENV === 'development' ? ['query'] : [],
507
+ })
508
+
509
+ if (process.env.NODE_ENV !== 'production') {
510
+ globalForPrisma.prisma = prisma
511
+ }
512
+ ```
513
+
514
+ ## Data Flow
515
+
516
+ ### Query Flow (읽기)
517
+
518
+ ```
519
+ 1. Client sends GET request
520
+
521
+
522
+ ┌─────────────────┐
523
+ │ Middleware │ ← logger, cors, secureHeaders
524
+ │ Stack │
525
+ └────────┬────────┘
526
+
527
+
528
+ ┌─────────────────┐
529
+ │ Route Handler │ ← zValidator('query', schema)
530
+ └────────┬────────┘
531
+
532
+
533
+ ┌─────────────────┐
534
+ │ Service Query │ ← getUsers(), getUserById()
535
+ └────────┬────────┘
536
+
537
+
538
+ ┌─────────────────┐
539
+ │ Prisma Client │ ← findMany(), findUnique()
540
+ └────────┬────────┘
541
+
542
+
543
+ ┌─────────────────┐
544
+ │ Database │
545
+ └─────────────────┘
546
+ ```
547
+
548
+ ### Mutation Flow (쓰기)
549
+
550
+ ```
551
+ 1. Client sends POST/PUT/DELETE request
552
+
553
+
554
+ ┌─────────────────┐
555
+ │ Middleware │ ← authMiddleware (인증)
556
+ │ Stack │
557
+ └────────┬────────┘
558
+
559
+
560
+ ┌─────────────────┐
561
+ │ Zod Validation │ ← zValidator('json', schema)
562
+ └────────┬────────┘
563
+ │ Valid
564
+
565
+ ┌─────────────────┐
566
+ │ Service │ ← createUser(), updateUser()
567
+ │ Mutation │
568
+ └────────┬────────┘
569
+
570
+
571
+ ┌─────────────────┐
572
+ │ Business Logic │ ← 중복 체크, 권한 검증
573
+ └────────┬────────┘
574
+
575
+
576
+ ┌─────────────────┐
577
+ │ Prisma Mutation│ ← create(), update(), delete()
578
+ └────────┬────────┘
579
+
580
+
581
+ ┌─────────────────┐
582
+ │ Database │
583
+ └─────────────────┘
584
+ ```
585
+
586
+ ### Error Flow
587
+
588
+ ```
589
+ 1. Error occurs anywhere
590
+
591
+
592
+ ┌─────────────────┐
593
+ │ HTTPException │ ← 비즈니스 에러
594
+ │ throw │
595
+ └────────┬────────┘
596
+
597
+
598
+ ┌─────────────────┐
599
+ │ app.onError() │ ← 글로벌 에러 핸들러
600
+ └────────┬────────┘
601
+
602
+
603
+ ┌─────────────────┐
604
+ │ JSON Response │ ← { error: message }
605
+ └─────────────────┘
606
+ ```
607
+
608
+ ## RPC Pattern (Type-safe Client)
609
+
610
+ ### Server 설정
611
+
612
+ ```typescript
613
+ // src/index.ts
614
+ const app = new Hono()
615
+ .route('/api/users', users)
616
+ .route('/api/posts', posts)
617
+
618
+ export type AppType = typeof app
619
+ export default app
620
+ ```
621
+
622
+ ### Client 사용
623
+
624
+ ```typescript
625
+ // client.ts
626
+ import { hc } from 'hono/client'
627
+ import type { AppType } from './server'
628
+
629
+ const client = hc<AppType>('http://localhost:8787')
630
+
631
+ // Type-safe API 호출
632
+ const getUsers = async () => {
633
+ const res = await client.api.users.$get({
634
+ query: { page: '1', limit: '10' },
635
+ })
636
+ return res.json()
637
+ }
638
+
639
+ const createUser = async (data: CreateUserInput) => {
640
+ const res = await client.api.users.$post({
641
+ json: data,
642
+ })
643
+ return res.json()
644
+ }
645
+ ```
646
+
647
+ ## Technology Stack
648
+
649
+ ### Core Framework
650
+
651
+ | Technology | Purpose | Version |
652
+ |------------|---------|---------|
653
+ | Hono | Web Standards 서버 프레임워크 | latest |
654
+ | TypeScript | 타입 안전 개발 | 5.x |
655
+
656
+ ### Validation
657
+
658
+ | Technology | Purpose | Version |
659
+ |------------|---------|---------|
660
+ | Zod | 스키마 검증 | **4.x** |
661
+ | @hono/zod-validator | Zod 미들웨어 | latest |
662
+
663
+ ### Database
664
+
665
+ | Technology | Purpose | Version |
666
+ |------------|---------|---------|
667
+ | Prisma | ORM | **7.x** |
668
+ | PostgreSQL | Primary Database | - |
669
+ | Cloudflare D1 | Edge Database | - |
670
+
671
+ ### Runtime
672
+
673
+ | Technology | Purpose |
674
+ |------------|---------|
675
+ | Cloudflare Workers | Edge Runtime |
676
+ | Node.js | 로컬 개발 |
677
+ | Bun | 대안 런타임 |
678
+
679
+ ## TypeScript Configuration
680
+
681
+ ```json
682
+ {
683
+ "compilerOptions": {
684
+ "target": "ES2022",
685
+ "lib": ["ES2022"],
686
+ "module": "ESNext",
687
+ "moduleResolution": "bundler",
688
+ "jsx": "react-jsx",
689
+ "jsxImportSource": "hono/jsx",
690
+ "strict": true,
691
+ "noUnusedLocals": true,
692
+ "noUnusedParameters": true,
693
+ "types": ["@cloudflare/workers-types"],
694
+ "paths": {
695
+ "@/*": ["./src/*"]
696
+ }
697
+ },
698
+ "include": ["src/**/*"]
699
+ }
700
+ ```
701
+
702
+ ## Deployment Architecture
703
+
704
+ ### Cloudflare Workers
705
+
706
+ ```
707
+ ┌─────────────────────────────────────┐
708
+ │ Cloudflare Edge Network │
709
+ │ │
710
+ │ ┌─────────────┐ ┌─────────────┐ │
711
+ │ │ Workers │ │ KV │ │
712
+ │ │ (Hono App) │ │ (Cache) │ │
713
+ │ └──────┬──────┘ └─────────────┘ │
714
+ │ │ │
715
+ │ ┌──────▼──────┐ ┌─────────────┐ │
716
+ │ │ D1 │ │ R2 │ │
717
+ │ │ (Database) │ │ (Storage) │ │
718
+ │ └─────────────┘ └─────────────┘ │
719
+ │ │
720
+ └─────────────────────────────────────┘
721
+ ```
722
+
723
+ ### Node.js / Bun
724
+
725
+ ```
726
+ ┌─────────────────────────────────────┐
727
+ │ Server (Node/Bun) │
728
+ │ │
729
+ │ ┌─────────────────────────────┐ │
730
+ │ │ Hono App │ │
731
+ │ │ (Full-stack Server) │ │
732
+ │ └─────────────────────────────┘ │
733
+ │ │
734
+ └───────────────────┬─────────────────┘
735
+
736
+
737
+ ┌───────────────┐
738
+ │ Database │
739
+ │ (PostgreSQL) │
740
+ └───────────────┘
741
+ ```
742
+
743
+ ## Documentation Structure
744
+
745
+ ```
746
+ docs/
747
+ ├── library/ # 라이브러리 레퍼런스
748
+ │ ├── hono/ # Hono 가이드
749
+ │ │ ├── index.md # 기본 사용법
750
+ │ │ ├── middleware.md # 미들웨어
751
+ │ │ ├── validation.md # Zod 검증
752
+ │ │ ├── error-handling.md # 에러 처리
753
+ │ │ └── rpc.md # RPC Client
754
+ │ ├── prisma/ # Prisma 가이드
755
+ │ │ ├── index.md # 기본 사용법
756
+ │ │ └── cloudflare-d1.md # D1 연동
757
+ │ └── zod/ # Zod 가이드
758
+ │ └── index.md
759
+ ├── deployment/ # 배포 가이드
760
+ │ ├── index.md # 배포 개요
761
+ │ └── cloudflare.md # Cloudflare 배포
762
+ ├── mcp/ # MCP 도구 가이드
763
+ │ ├── index.md
764
+ │ ├── sgrep.md
765
+ │ ├── sequential-thinking.md
766
+ │ └── context7.md
767
+ ├── skills/ # 스킬 가이드
768
+ │ └── gemini-review/
769
+ ├── git/ # Git 규칙
770
+ │ └── index.md
771
+ └── architecture/ # 아키텍처
772
+ └── architecture.md # 시스템 아키텍처
773
+ ```
774
+
775
+ ## Security Considerations
776
+
777
+ ### Input Validation
778
+
779
+ 모든 라우트에서 Zod를 통한 입력 검증:
780
+
781
+ ```typescript
782
+ // ✅ 올바른 패턴: zValidator 사용
783
+ app.post(
784
+ '/users',
785
+ zValidator('json', createUserSchema), // 자동 검증
786
+ (c) => {
787
+ const data = c.req.valid('json') // data는 이미 검증됨
788
+ // ...
789
+ }
790
+ )
791
+
792
+ // ❌ 잘못된 패턴: 수동 검증 금지
793
+ app.post('/users', async (c) => {
794
+ const body = await c.req.json()
795
+ if (!body.email) { // ❌ 이렇게 하지 마세요
796
+ return c.json({ error: 'Email required' }, 400)
797
+ }
798
+ })
799
+ ```
800
+
801
+ ### Error Handling
802
+
803
+ HTTPException을 통한 안전한 에러 처리:
804
+
805
+ ```typescript
806
+ // ✅ 올바른 패턴
807
+ import { HTTPException } from 'hono/http-exception'
808
+
809
+ if (!user) {
810
+ throw new HTTPException(404, { message: 'User not found' })
811
+ }
812
+
813
+ // ❌ 잘못된 패턴
814
+ if (!user) {
815
+ throw new Error('User not found') // ❌ HTTPException 사용해야 함
816
+ }
817
+ ```
818
+
819
+ ### Authentication
820
+
821
+ 미들웨어를 통한 인증 처리:
822
+
823
+ ```typescript
824
+ // ✅ 올바른 패턴: 미들웨어 사용
825
+ app.post('/protected', authMiddleware, (c) => {
826
+ const userId = c.get('userId')
827
+ // ...
828
+ })
829
+
830
+ // ❌ 잘못된 패턴: 핸들러 내부에서 인증
831
+ app.post('/protected', async (c) => {
832
+ const token = c.req.header('Authorization') // ❌ 미들웨어 사용해야 함
833
+ // ...
834
+ })
835
+ ```
836
+
837
+ ### Environment Variables
838
+
839
+ ```typescript
840
+ // types/env.d.ts
841
+ type Bindings = {
842
+ DATABASE_URL: string
843
+ JWT_SECRET: string
844
+ NODE_ENV: 'development' | 'production'
845
+ }
846
+
847
+ // 사용
848
+ const app = new Hono<{ Bindings: Bindings }>()
849
+
850
+ app.get('/', (c) => {
851
+ const secret = c.env.JWT_SECRET // 타입 안전
852
+ })
853
+ ```
854
+
855
+ ## Performance Considerations
856
+
857
+ ### Middleware Optimization
858
+
859
+ ```typescript
860
+ // 필요한 경로에만 미들웨어 적용
861
+ app.use('/api/*', cors()) // API 전용
862
+ app.use('/api/protected/*', authMiddleware) // 인증 필요 경로만
863
+
864
+ // 불필요한 미들웨어 중복 적용 금지
865
+ ```
866
+
867
+ ### Database Optimization
868
+
869
+ ```typescript
870
+ // 필요한 필드만 선택
871
+ const users = await prisma.user.findMany({
872
+ select: { // ✅ select 사용
873
+ id: true,
874
+ name: true,
875
+ email: true,
876
+ },
877
+ take: 20, // ✅ 페이지네이션
878
+ skip: (page - 1) * 20,
879
+ })
880
+
881
+ // 병렬 쿼리 실행
882
+ const [users, total] = await Promise.all([
883
+ prisma.user.findMany({ take: 20 }),
884
+ prisma.user.count(),
885
+ ])
886
+ ```
887
+
888
+ ### Response Optimization
889
+
890
+ ```typescript
891
+ // 적절한 상태 코드 사용
892
+ app.post('/users', (c) => {
893
+ return c.json({ user }, 201) // Created
894
+ })
895
+
896
+ // 불필요한 데이터 제외
897
+ const { password, ...safeUser } = user
898
+ return c.json({ user: safeUser })
899
+ ```
900
+
901
+ ## Related Documentation
902
+
903
+ - [Hono 기본 사용법](../library/hono/index.md)
904
+ - [미들웨어](../library/hono/middleware.md)
905
+ - [Zod 검증](../library/hono/validation.md)
906
+ - [에러 처리](../library/hono/error-handling.md)
907
+ - [RPC Client](../library/hono/rpc.md)
908
+ - [Prisma v7](../library/prisma/index.md)
909
+ - [Cloudflare 배포](../deployment/cloudflare.md)