@kood/claude-code 0.2.4 → 0.3.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 (130) hide show
  1. package/dist/index.js +13 -8
  2. package/package.json +1 -1
  3. package/templates/.claude/agents/code-reviewer.md +371 -19
  4. package/templates/.claude/agents/dependency-manager.md +197 -0
  5. package/templates/.claude/agents/deployment-validator.md +136 -0
  6. package/templates/.claude/agents/git-operator.md +147 -0
  7. package/templates/.claude/agents/implementation-executor.md +202 -0
  8. package/templates/.claude/agents/lint-fixer.md +155 -0
  9. package/templates/.claude/agents/refactor-advisor.md +339 -29
  10. package/templates/.claude/commands/agent-creator.md +355 -0
  11. package/templates/.claude/commands/docs-creator.md +404 -163
  12. package/templates/.claude/commands/docs-refactor.md +400 -113
  13. package/templates/.claude/commands/execute.md +357 -185
  14. package/templates/.claude/commands/git-all.md +16 -70
  15. package/templates/.claude/commands/git-session.md +36 -68
  16. package/templates/.claude/commands/git.md +20 -69
  17. package/templates/.claude/commands/lint-fix.md +164 -107
  18. package/templates/.claude/commands/lint-init.md +142 -168
  19. package/templates/.claude/commands/plan.md +300 -84
  20. package/templates/.claude/commands/prd.md +613 -0
  21. package/templates/.claude/commands/pre-deploy.md +242 -0
  22. package/templates/.claude/commands/subagent-creator.md +118 -0
  23. package/templates/.claude/commands/version-update.md +45 -57
  24. package/templates/hono/CLAUDE.md +99 -54
  25. package/templates/hono/docs/guides/conventions.md +352 -0
  26. package/templates/hono/docs/guides/env-setup.md +347 -0
  27. package/templates/hono/docs/guides/getting-started.md +239 -0
  28. package/templates/hono/docs/library/hono/error-handling.md +20 -29
  29. package/templates/hono/docs/library/hono/index.md +25 -52
  30. package/templates/hono/docs/library/hono/middleware.md +16 -75
  31. package/templates/hono/docs/library/hono/rpc.md +7 -35
  32. package/templates/hono/docs/library/hono/validation.md +25 -45
  33. package/templates/hono/docs/library/t3-env/index.md +374 -0
  34. package/templates/npx/CLAUDE.md +165 -65
  35. package/templates/npx/docs/library/commander/index.md +10 -73
  36. package/templates/npx/docs/library/fs-extra/index.md +21 -113
  37. package/templates/npx/docs/library/prompts/index.md +30 -176
  38. package/templates/npx/docs/references/patterns.md +75 -48
  39. package/templates/tanstack-start/CLAUDE.md +101 -77
  40. package/templates/tanstack-start/docs/architecture.md +427 -0
  41. package/templates/tanstack-start/docs/design.md +558 -0
  42. package/templates/tanstack-start/docs/guides/conventions.md +132 -32
  43. package/templates/tanstack-start/docs/guides/env-setup.md +127 -62
  44. package/templates/tanstack-start/docs/guides/getting-started.md +81 -20
  45. package/templates/tanstack-start/docs/guides/hooks.md +241 -36
  46. package/templates/tanstack-start/docs/guides/routes.md +213 -61
  47. package/templates/tanstack-start/docs/guides/services.md +260 -24
  48. package/templates/tanstack-start/docs/library/better-auth/index.md +469 -16
  49. package/templates/tanstack-start/docs/library/t3-env/index.md +307 -0
  50. package/templates/tanstack-start/docs/library/tanstack-query/index.md +12 -21
  51. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +22 -35
  52. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +7 -24
  53. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +26 -39
  54. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +23 -26
  55. package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +32 -147
  56. package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +25 -167
  57. package/templates/tanstack-start/docs/library/tanstack-router/index.md +39 -74
  58. package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +46 -116
  59. package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +35 -154
  60. package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +32 -171
  61. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +7 -15
  62. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +16 -23
  63. package/templates/tanstack-start/docs/library/zod/complex-types.md +12 -31
  64. package/templates/tanstack-start/docs/library/zod/index.md +18 -35
  65. package/templates/tanstack-start/docs/library/zod/transforms.md +11 -25
  66. package/templates/tanstack-start/docs/library/zod/validation.md +12 -34
  67. package/templates/.claude/agents/debug-detective.md +0 -37
  68. package/templates/.claude/agents/test-writer.md +0 -41
  69. package/templates/.claude/commands/feedback.md +0 -199
  70. package/templates/.claude/commands/ts-fix.md +0 -176
  71. package/templates/.claude/skills/command-creator/LICENSE.txt +0 -202
  72. package/templates/.claude/skills/command-creator/SKILL.md +0 -245
  73. package/templates/.claude/skills/command-creator/scripts/init_command.py +0 -244
  74. package/templates/.claude/skills/command-creator/scripts/package_command.py +0 -125
  75. package/templates/.claude/skills/command-creator/scripts/quick_validate.py +0 -143
  76. package/templates/.claude/skills/frontend-design/SKILL.md +0 -310
  77. package/templates/.claude/skills/frontend-design/references/animation-patterns.md +0 -446
  78. package/templates/.claude/skills/frontend-design/references/colors-2026.md +0 -244
  79. package/templates/.claude/skills/frontend-design/references/typography-2026.md +0 -302
  80. package/templates/.claude/skills/gemini-review/SKILL.md +0 -118
  81. package/templates/.claude/skills/gemini-review/references/checklists.md +0 -129
  82. package/templates/.claude/skills/gemini-review/references/prompt-templates.md +0 -274
  83. package/templates/.claude/skills/skill-creator/LICENSE.txt +0 -202
  84. package/templates/.claude/skills/skill-creator/SKILL.md +0 -184
  85. package/templates/.claude/skills/skill-creator/scripts/init_skill.py +0 -303
  86. package/templates/.claude/skills/skill-creator/scripts/package_skill.py +0 -110
  87. package/templates/.claude/skills/skill-creator/scripts/quick_validate.py +0 -65
  88. package/templates/hono/docs/library/ai-sdk/index.md +0 -190
  89. package/templates/hono/docs/library/ai-sdk/openrouter.md +0 -111
  90. package/templates/hono/docs/library/ai-sdk/providers.md +0 -102
  91. package/templates/hono/docs/library/ai-sdk/streaming.md +0 -146
  92. package/templates/hono/docs/library/ai-sdk/structured-output.md +0 -161
  93. package/templates/hono/docs/library/ai-sdk/tools.md +0 -144
  94. package/templates/hono/docs/library/drizzle/cloudflare-d1.md +0 -247
  95. package/templates/hono/docs/library/drizzle/config.md +0 -167
  96. package/templates/hono/docs/library/drizzle/index.md +0 -259
  97. package/templates/hono/docs/library/hono/env-setup.md +0 -169
  98. package/templates/hono/docs/library/pino/index.md +0 -146
  99. package/templates/tanstack-start/docs/architecture/architecture.md +0 -243
  100. package/templates/tanstack-start/docs/deployment/cloudflare.md +0 -132
  101. package/templates/tanstack-start/docs/deployment/index.md +0 -163
  102. package/templates/tanstack-start/docs/deployment/nitro.md +0 -110
  103. package/templates/tanstack-start/docs/deployment/railway.md +0 -147
  104. package/templates/tanstack-start/docs/deployment/vercel.md +0 -135
  105. package/templates/tanstack-start/docs/design/components.md +0 -175
  106. package/templates/tanstack-start/docs/design/index.md +0 -151
  107. package/templates/tanstack-start/docs/design/safe-area.md +0 -118
  108. package/templates/tanstack-start/docs/design/tailwind-setup.md +0 -156
  109. package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +0 -472
  110. package/templates/tanstack-start/docs/library/ai-sdk/index.md +0 -264
  111. package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +0 -371
  112. package/templates/tanstack-start/docs/library/ai-sdk/providers.md +0 -403
  113. package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +0 -320
  114. package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +0 -454
  115. package/templates/tanstack-start/docs/library/ai-sdk/tools.md +0 -473
  116. package/templates/tanstack-start/docs/library/better-auth/2fa.md +0 -48
  117. package/templates/tanstack-start/docs/library/better-auth/advanced.md +0 -55
  118. package/templates/tanstack-start/docs/library/better-auth/plugins.md +0 -34
  119. package/templates/tanstack-start/docs/library/better-auth/session.md +0 -47
  120. package/templates/tanstack-start/docs/library/better-auth/setup.md +0 -41
  121. package/templates/tanstack-start/docs/library/drizzle/cloudflare-d1.md +0 -147
  122. package/templates/tanstack-start/docs/library/drizzle/config.md +0 -118
  123. package/templates/tanstack-start/docs/library/drizzle/crud.md +0 -205
  124. package/templates/tanstack-start/docs/library/drizzle/index.md +0 -79
  125. package/templates/tanstack-start/docs/library/drizzle/relations.md +0 -202
  126. package/templates/tanstack-start/docs/library/drizzle/schema.md +0 -154
  127. package/templates/tanstack-start/docs/library/drizzle/setup.md +0 -96
  128. package/templates/tanstack-start/docs/library/drizzle/transactions.md +0 -127
  129. package/templates/tanstack-start/docs/library/pino/index.md +0 -320
  130. /package/templates/hono/docs/{architecture/architecture.md → architecture.md} +0 -0
@@ -0,0 +1,427 @@
1
+ # Architecture
2
+
3
+ > TanStack Start 애플리케이션 아키텍처
4
+
5
+ <instructions>
6
+ @../guides/conventions.md
7
+ @../guides/routes.md
8
+ @../guides/services.md
9
+ @../guides/hooks.md
10
+ </instructions>
11
+
12
+ ---
13
+
14
+ <forbidden>
15
+
16
+ | 분류 | 금지 |
17
+ |------|------|
18
+ | **API** | `/api` 라우터 생성 (Server Functions 사용) |
19
+ | **레이어** | Service Layer 건너뛰기, Routes에서 직접 DB 접근 |
20
+ | **검증** | Handler 내부 수동 검증, 인증 로직 분산 |
21
+ | **Server Fn** | `createServerFn` 사용 (명시 요청 없으면 `createServerOnlyFn`) |
22
+
23
+ </forbidden>
24
+
25
+ ---
26
+
27
+ <required>
28
+
29
+ | 분류 | 필수 |
30
+ |------|------|
31
+ | **계층 구조** | Routes → Server Functions → Services → Database |
32
+ | **Route Group** | 목록 → `(main)/`, 생성/편집 → 외부 |
33
+ | **페이지 분리** | 100줄+ → `-components`, 200줄+ → `-sections` |
34
+ | **beforeLoad** | 인증 체크, Context 전달, 리다이렉트 |
35
+ | **loader** | 데이터 로딩 (beforeLoad 완료 후 병렬 실행) |
36
+ | **Server Fn** | `createServerOnlyFn` 기본 사용 |
37
+ | **검증** | `inputValidator` (POST/PUT/PATCH), Zod 스키마 |
38
+ | **인증** | `middleware` (authMiddleware) |
39
+ | **에러 처리** | `errorComponent` (라우트), `notFoundComponent` (404) |
40
+ | **타입 안전** | TypeScript strict, Prisma 타입 |
41
+
42
+ </required>
43
+
44
+ ---
45
+
46
+ <system_overview>
47
+
48
+ ## System Overview
49
+
50
+ ```
51
+ ┌─────────────────────────────────────────────────────────────────┐
52
+ │ Client (Browser) │
53
+ │ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ │
54
+ │ │ React Router │───▶│ TanStack Query │───▶│ React UI │ │
55
+ │ │ (Navigation) │◀───│ (Caching) │◀───│ (Components) │ │
56
+ │ └────────────────┘ └───────┬────────┘ └───────────────┘ │
57
+ └────────────────────────────────┼─────────────────────────────────┘
58
+
59
+ ┌─────────────────────────────────────────────────────────────────┐
60
+ │ TanStack Start Server │
61
+ │ ┌────────────────────────────────────────────────────────────┐ │
62
+ │ │ Server Functions │ │
63
+ │ │ routes/-functions/ → 페이지 전용 | functions/ → 글로벌 │ │
64
+ │ └────────────────────────────┬───────────────────────────────┘ │
65
+ │ ┌────────────────────────────▼───────────────────────────────┐ │
66
+ │ │ Services Layer │ │
67
+ │ │ Zod Validation | Business Logic | Data Transformation │ │
68
+ │ └────────────────────────────┬───────────────────────────────┘ │
69
+ └───────────────────────────────┼──────────────────────────────────┘
70
+
71
+ ┌─────────────────────────────────────────────────────────────────┐
72
+ │ Database Layer │
73
+ │ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ │
74
+ │ │ Prisma Client │───▶│ PostgreSQL │ │ Redis │ │
75
+ │ └────────────────┘ └────────────────┘ └───────────────┘ │
76
+ └─────────────────────────────────────────────────────────────────┘
77
+ ```
78
+
79
+ </system_overview>
80
+
81
+ ---
82
+
83
+ <layers>
84
+
85
+ ## Layer Architecture
86
+
87
+ ### 1. Routes Layer
88
+
89
+ ```
90
+ routes/<route-name>/
91
+ ├── (main)/ # route group (목록 페이지)
92
+ │ ├── index.tsx # 페이지 컴포넌트
93
+ │ ├── -components/ # 페이지 전용 컴포넌트
94
+ │ ├── -sections/ # UI 섹션 분리 (200줄+ 페이지)
95
+ │ ├── -tabs/ # 탭 콘텐츠 분리
96
+ │ ├── -hooks/ # 페이지 전용 훅
97
+ │ └── -utils/ # 상수, 헬퍼
98
+ ├── new/ # 생성 페이지 (route group 외부)
99
+ │ └── index.tsx
100
+ ├── route.tsx # route 설정 (loader, beforeLoad)
101
+ └── -functions/ # 페이지 전용 서버 함수
102
+ ```
103
+
104
+ | 패턴 | 위치 | 용도 |
105
+ |------|------|------|
106
+ | **Route Group** | `(main)/` | 목록 페이지, URL에 미포함 |
107
+ | **-components/** | 100-200줄 | 페이지 전용 컴포넌트 분리 |
108
+ | **-sections/** | 200줄+ | 논리적 섹션 분리 |
109
+ | **-tabs/** | 탭 UI | 탭 콘텐츠 분리 |
110
+ | **_layout/** | Pathless | 공통 레이아웃 (URL 미영향) |
111
+
112
+ #### Layout Routes 패턴
113
+
114
+ ```
115
+ routes/
116
+ ├── (auth)/_layout/ # Pathless Layout
117
+ │ ├── route.tsx # <Outlet />
118
+ │ ├── login.tsx # /login
119
+ │ └── register.tsx # /register
120
+ ```
121
+
122
+ ```typescript
123
+ // routes/(auth)/_layout/route.tsx
124
+ export const Route = createFileRoute('/(auth)/_layout')({
125
+ component: () => (
126
+ <div className="auth-container">
127
+ <Outlet />
128
+ </div>
129
+ ),
130
+ })
131
+ ```
132
+
133
+ ### 2. Services Layer
134
+
135
+ ```
136
+ services/<domain>/
137
+ ├── index.ts # 진입점 (re-export)
138
+ ├── schemas.ts # Zod 스키마
139
+ ├── queries.ts # GET 요청
140
+ └── mutations.ts # POST/PUT/PATCH
141
+ ```
142
+
143
+ ### 3. Server Functions Layer
144
+
145
+ ```
146
+ functions/ # 글로벌 (재사용)
147
+ ├── index.ts
148
+ ├── <function-name>.ts # 파일당 하나
149
+ └── middlewares/
150
+ └── <middleware-name>.ts
151
+
152
+ routes/<route>/-functions/ # 페이지 전용
153
+ └── <function-name>.ts
154
+ ```
155
+
156
+ ### 4. Database Layer
157
+
158
+ ```typescript
159
+ // database/prisma.ts
160
+ const globalForPrisma = globalThis as unknown as {
161
+ prisma: PrismaClient | undefined
162
+ }
163
+
164
+ export const prisma = globalForPrisma.prisma ?? new PrismaClient()
165
+
166
+ if (process.env.NODE_ENV !== 'production') {
167
+ globalForPrisma.prisma = prisma
168
+ }
169
+ ```
170
+
171
+ </layers>
172
+
173
+ ---
174
+
175
+ <route_lifecycle>
176
+
177
+ ## Route Lifecycle
178
+
179
+ ### beforeLoad vs loader
180
+
181
+ | 항목 | beforeLoad | loader |
182
+ |------|-----------|--------|
183
+ | **실행 순서** | 순차 (outermost → innermost) | 병렬 (beforeLoad 완료 후) |
184
+ | **용도** | 인증, Context 전달, 리다이렉트 | 데이터 로딩 |
185
+ | **블로킹** | 모든 loader 차단 | 다른 loader와 병렬 |
186
+ | **성능 영향** | ⚠️ 높음 | ✅ 낮음 |
187
+
188
+ ```
189
+ 1. Parent beforeLoad (순차) ──┐
190
+ 2. Child beforeLoad (순차) ──┼→ 완료 후
191
+ 3. All loaders (병렬) ────────┘
192
+ ```
193
+
194
+ ### 코드 패턴
195
+
196
+ ```typescript
197
+ // ✅ beforeLoad: 인증 & Context
198
+ beforeLoad: async () => {
199
+ const user = await getUser()
200
+ if (!user) throw redirect({ to: '/login' })
201
+ return { user }
202
+ }
203
+
204
+ // ✅ loader: 데이터 로딩
205
+ loader: async () => {
206
+ const [users, roles] = await Promise.all([
207
+ getUsers(),
208
+ getRoles(),
209
+ ])
210
+ return { users, roles }
211
+ }
212
+ ```
213
+
214
+ | ❌ 금지 | ✅ 권장 |
215
+ |--------|--------|
216
+ | beforeLoad에서 데이터 로딩 | loader에서 데이터 로딩 |
217
+ | loader 차단 | 병렬 실행 |
218
+
219
+ </route_lifecycle>
220
+
221
+ ---
222
+
223
+ <context_management>
224
+
225
+ ## Context Management
226
+
227
+ | 단계 | 파일 | 작업 |
228
+ |------|------|------|
229
+ | **생성** | `__root.tsx` | `createRootRouteWithContext` |
230
+ | **확장** | `route.tsx` | `beforeLoad` Context 확장 |
231
+ | **사용** | `component` | `useRouteContext()` |
232
+
233
+ ```typescript
234
+ // 1. Root: Context 정의
235
+ interface RouterContext {
236
+ user: User | null
237
+ }
238
+
239
+ export const Route = createRootRouteWithContext<RouterContext>()({
240
+ beforeLoad: async () => ({ user: await getUser() }),
241
+ })
242
+
243
+ // 2. 확장: Context 확장
244
+ beforeLoad: async ({ context }) => ({
245
+ ...context,
246
+ permissions: await getPermissions(context.user.id),
247
+ })
248
+
249
+ // 3. 사용: Component
250
+ const { user, permissions } = useRouteContext({ from: '/dashboard' })
251
+
252
+ // 4. 사용: Loader
253
+ loader: async ({ context }) => {
254
+ if (!context.permissions.includes('users:read')) {
255
+ throw new Error('Unauthorized')
256
+ }
257
+ return { users: await getUsers() }
258
+ }
259
+ ```
260
+
261
+ </context_management>
262
+
263
+ ---
264
+
265
+ <data_flow>
266
+
267
+ ## Data Flow
268
+
269
+ ### Query Flow (읽기)
270
+
271
+ ```
272
+ Page → useQuery → Server Function → Prisma → Database
273
+
274
+ TanStack Query (Cache)
275
+ ```
276
+
277
+ ```typescript
278
+ // Page
279
+ const { data } = useQuery({
280
+ queryKey: ['users'],
281
+ queryFn: getUsers,
282
+ })
283
+
284
+ // Server Function
285
+ export const getUsers = createServerOnlyFn()
286
+ .middleware([authMiddleware])
287
+ .handler(async () => prisma.user.findMany())
288
+ ```
289
+
290
+ ### Mutation Flow (쓰기)
291
+
292
+ ```
293
+ Form → useMutation → Server Function
294
+
295
+ inputValidator
296
+
297
+ Prisma → Database
298
+
299
+ invalidateQueries
300
+ ```
301
+
302
+ ```typescript
303
+ // Page
304
+ const mutation = useMutation({
305
+ mutationFn: createUser,
306
+ onSuccess: () => {
307
+ queryClient.invalidateQueries({ queryKey: ['users'] })
308
+ },
309
+ })
310
+
311
+ // Server Function
312
+ export const createUser = createServerOnlyFn({ method: 'POST' })
313
+ .middleware([authMiddleware])
314
+ .inputValidator(createUserSchema)
315
+ .handler(async ({ data }) => prisma.user.create({ data }))
316
+ ```
317
+
318
+ </data_flow>
319
+
320
+ ---
321
+
322
+ <server_functions_advanced>
323
+
324
+ ## Server Functions (Advanced)
325
+
326
+ ### Server Functions 타입
327
+
328
+ | 타입 | 실행 위치 | 사용 시나리오 |
329
+ |------|----------|-------------|
330
+ | **createServerOnlyFn** | 서버 | DB 접근, 비밀키 (기본) |
331
+ | createServerFn | 서버 (RPC) | 일반 서버 로직 |
332
+ | createClientOnlyFn | 클라이언트 | localStorage, window |
333
+ | createIsomorphicFn | 양쪽 | 환경별 구현 |
334
+
335
+ **기본 규칙**: 별도 요청 없으면 `createServerOnlyFn` 사용
336
+
337
+ ### Middleware 패턴
338
+
339
+ ```typescript
340
+ // 1. authMiddleware
341
+ export const authMiddleware = createMiddleware()
342
+ .server(async ({ next, context }) => {
343
+ const session = await getSession()
344
+ if (!session?.user) throw new Error('Unauthorized')
345
+ return next({ context: { ...context, user: session.user } })
346
+ })
347
+
348
+ // 2. 사용
349
+ export const createPost = createServerOnlyFn({ method: 'POST' })
350
+ .middleware([authMiddleware])
351
+ .inputValidator(createPostSchema)
352
+ .handler(async ({ data, context }) => {
353
+ return prisma.post.create({
354
+ data: { ...data, authorId: context.user.id },
355
+ })
356
+ })
357
+ ```
358
+
359
+ **실행 순서**: Middleware → inputValidator → handler
360
+
361
+ </server_functions_advanced>
362
+
363
+ ---
364
+
365
+ <error_handling>
366
+
367
+ ## Error Handling
368
+
369
+ | 컴포넌트 | 처리 범위 | 위치 | 필수 |
370
+ |---------|----------|------|-----|
371
+ | **errorComponent** | 라우트 에러 | 각 route | ✅ |
372
+ | **notFoundComponent** | 404 | __root.tsx | ✅ |
373
+ | **pendingComponent** | 로딩 | 각 route | 선택 |
374
+
375
+ ```typescript
376
+ // __root.tsx
377
+ export const Route = createRootRoute({
378
+ errorComponent: ({ error }) => <div>{error.message}</div>,
379
+ notFoundComponent: () => <div>404 Not Found</div>,
380
+ })
381
+
382
+ // Route 레벨
383
+ export const Route = createFileRoute('/dashboard')({
384
+ errorComponent: ({ error }) => <div>{error.message}</div>,
385
+ })
386
+
387
+ // Loader 에러
388
+ loader: async () => {
389
+ try {
390
+ return { users: await getUsers() }
391
+ } catch (error) {
392
+ throw new Error('데이터 로딩 실패')
393
+ }
394
+ }
395
+
396
+ // Server Function 에러
397
+ .handler(async ({ data }) => {
398
+ try {
399
+ return await prisma.user.create({ data })
400
+ } catch (error) {
401
+ if (error.code === 'P2002') {
402
+ throw new Error('이미 존재하는 이메일')
403
+ }
404
+ throw new Error('사용자 생성 실패')
405
+ }
406
+ })
407
+ ```
408
+
409
+ </error_handling>
410
+
411
+ ---
412
+
413
+ <tech_stack>
414
+
415
+ ## Technology Stack
416
+
417
+ | Layer | Technology | Version |
418
+ |-------|------------|---------|
419
+ | Framework | TanStack Start | latest |
420
+ | Router | TanStack Router | latest |
421
+ | Data | TanStack Query | latest |
422
+ | ORM | Prisma | 7.x |
423
+ | Validation | Zod | 4.x |
424
+ | Database | PostgreSQL | - |
425
+ | UI | React 18+ | - |
426
+
427
+ </tech_stack>