@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,377 @@
1
+ # Prisma - Config 파일 (prisma.config.ts)
2
+
3
+ > **상위 문서**: [Prisma](./index.md)
4
+
5
+ Prisma v7에서 도입된 `prisma.config.ts` 설정 파일입니다.
6
+
7
+ ---
8
+
9
+ ## ⚠️ 필수: Multi-File 스키마 설정
10
+
11
+ Multi-File 스키마를 사용하려면 **반드시** `prisma.config.ts`에서 스키마 폴더를 지정해야 합니다.
12
+
13
+ ```typescript
14
+ // prisma.config.ts
15
+ import path from 'node:path'
16
+ import { defineConfig, env } from 'prisma/config'
17
+
18
+ export default defineConfig({
19
+ // Multi-File 스키마 폴더 지정
20
+ schema: path.join('prisma', 'schema'),
21
+ datasource: {
22
+ url: env('DATABASE_URL'),
23
+ },
24
+ })
25
+ ```
26
+
27
+ ---
28
+
29
+ ## 파일 위치 및 이름
30
+
31
+ ### 지원되는 파일명
32
+
33
+ ```
34
+ prisma.config.ts # 권장 (소규모 프로젝트)
35
+ prisma.config.js
36
+ prisma.config.mjs
37
+ prisma.config.cjs
38
+ prisma.config.mts
39
+ prisma.config.cts
40
+
41
+ .config/prisma.ts # 권장 (대규모 프로젝트)
42
+ .config/prisma.js
43
+ ```
44
+
45
+ ### 권장 위치
46
+
47
+ ```
48
+ 프로젝트/
49
+ ├── prisma.config.ts # 프로젝트 루트
50
+ ├── prisma/
51
+ │ ├── schema/ # Multi-File 스키마 폴더
52
+ │ │ ├── +base.prisma
53
+ │ │ ├── +enum.prisma
54
+ │ │ └── user.prisma
55
+ │ └── migrations/ # 마이그레이션 폴더
56
+ └── package.json
57
+ ```
58
+
59
+ ---
60
+
61
+ ## 설정 옵션
62
+
63
+ ### 전체 옵션 목록
64
+
65
+ | 옵션 | 타입 | 필수 | 설명 |
66
+ |------|------|------|------|
67
+ | `schema` | string | ❌ | 스키마 파일 또는 폴더 경로 |
68
+ | `datasource.url` | string | ✅ | 데이터베이스 연결 URL |
69
+ | `datasource.shadowDatabaseUrl` | string | ❌ | Shadow DB URL |
70
+ | `migrations.path` | string | ❌ | 마이그레이션 폴더 경로 |
71
+ | `migrations.seed` | string | ❌ | 시드 스크립트 명령어 |
72
+ | `migrations.initShadowDb` | string | ❌ | Shadow DB 초기화 SQL |
73
+ | `views.path` | string | ❌ | SQL 뷰 정의 폴더 |
74
+ | `typedSql.path` | string | ❌ | TypedSQL 파일 폴더 |
75
+ | `experimental` | object | ❌ | 실험적 기능 활성화 |
76
+
77
+ ---
78
+
79
+ ## 기본 설정 예시
80
+
81
+ ### defineConfig 사용 (권장)
82
+
83
+ ```typescript
84
+ // prisma.config.ts
85
+ import 'dotenv/config'
86
+ import { defineConfig, env } from 'prisma/config'
87
+
88
+ export default defineConfig({
89
+ // Multi-File 스키마 설정
90
+ schema: 'prisma/schema',
91
+
92
+ // 마이그레이션 설정
93
+ migrations: {
94
+ path: 'prisma/migrations',
95
+ seed: 'tsx prisma/seed.ts',
96
+ },
97
+
98
+ // 데이터베이스 연결
99
+ datasource: {
100
+ url: env('DATABASE_URL'),
101
+ },
102
+ })
103
+ ```
104
+
105
+ ### satisfies 사용
106
+
107
+ ```typescript
108
+ // prisma.config.ts
109
+ import 'dotenv/config'
110
+ import type { PrismaConfig } from 'prisma'
111
+ import { env } from 'prisma/config'
112
+
113
+ export default {
114
+ schema: 'prisma/schema',
115
+ migrations: {
116
+ path: 'prisma/migrations',
117
+ seed: 'tsx prisma/seed.ts',
118
+ },
119
+ datasource: {
120
+ url: env('DATABASE_URL'),
121
+ },
122
+ } satisfies PrismaConfig
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Multi-File 스키마 설정
128
+
129
+ ### 필수 설정
130
+
131
+ ```typescript
132
+ // prisma.config.ts
133
+ import path from 'node:path'
134
+ import { defineConfig, env } from 'prisma/config'
135
+
136
+ export default defineConfig({
137
+ // ⚠️ 폴더 경로 지정 (파일이 아님!)
138
+ schema: path.join('prisma', 'schema'),
139
+ datasource: {
140
+ url: env('DATABASE_URL'),
141
+ },
142
+ })
143
+ ```
144
+
145
+ ### 폴더 구조
146
+
147
+ ```
148
+ prisma/
149
+ ├── schema/ # Multi-File 스키마 폴더
150
+ │ ├── +base.prisma # datasource, generator 설정
151
+ │ ├── +enum.prisma # 모든 enum 정의
152
+ │ ├── user.prisma # User 모델
153
+ │ ├── post.prisma # Post 모델
154
+ │ └── ...
155
+ └── migrations/ # ⚠️ datasource와 같은 레벨에 위치
156
+ ```
157
+
158
+ ### +base.prisma 예시
159
+
160
+ ```prisma
161
+ // prisma/schema/+base.prisma
162
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
163
+ // Prisma 기본 설정 파일
164
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
165
+
166
+ // 데이터베이스 연결 설정
167
+ datasource db {
168
+ provider = "postgresql"
169
+ url = env("DATABASE_URL")
170
+ }
171
+
172
+ // Prisma Client 생성 설정
173
+ generator client {
174
+ provider = "prisma-client" // Prisma v7 필수
175
+ output = "../../generated/prisma"
176
+ }
177
+ ```
178
+
179
+ ---
180
+
181
+ ## 환경 변수 설정
182
+
183
+ ### dotenv 설치
184
+
185
+ ```bash
186
+ npm install dotenv
187
+ ```
188
+
189
+ ### 환경 변수 사용
190
+
191
+ ```typescript
192
+ // prisma.config.ts
193
+ import 'dotenv/config' // ⚠️ 반드시 최상단에 import
194
+ import { defineConfig, env } from 'prisma/config'
195
+
196
+ export default defineConfig({
197
+ schema: 'prisma/schema',
198
+ datasource: {
199
+ url: env('DATABASE_URL'), // 타입 안전한 환경 변수 접근
200
+ },
201
+ })
202
+ ```
203
+
204
+ ### .env 파일
205
+
206
+ ```env
207
+ DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
208
+ ```
209
+
210
+ ---
211
+
212
+ ## 마이그레이션 설정
213
+
214
+ ### 시드 스크립트
215
+
216
+ ```typescript
217
+ // prisma.config.ts
218
+ import { defineConfig, env } from 'prisma/config'
219
+
220
+ export default defineConfig({
221
+ schema: 'prisma/schema',
222
+ migrations: {
223
+ path: 'prisma/migrations',
224
+ seed: 'tsx prisma/seed.ts', // 시드 명령어
225
+ },
226
+ datasource: {
227
+ url: env('DATABASE_URL'),
228
+ },
229
+ })
230
+ ```
231
+
232
+ ### 시드 파일 예시
233
+
234
+ ```typescript
235
+ // prisma/seed.ts
236
+ import { PrismaClient } from '../generated/prisma'
237
+
238
+ const prisma = new PrismaClient()
239
+
240
+ async function main() {
241
+ // 초기 데이터 생성
242
+ await prisma.user.create({
243
+ data: {
244
+ email: 'admin@example.com',
245
+ name: '관리자',
246
+ role: 'ADMIN',
247
+ },
248
+ })
249
+ }
250
+
251
+ main()
252
+ .catch(console.error)
253
+ .finally(() => prisma.$disconnect())
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Shadow Database 설정
259
+
260
+ 마이그레이션 시 사용되는 임시 데이터베이스입니다.
261
+
262
+ ```typescript
263
+ // prisma.config.ts
264
+ import { defineConfig, env } from 'prisma/config'
265
+
266
+ export default defineConfig({
267
+ schema: 'prisma/schema',
268
+ datasource: {
269
+ url: env('DATABASE_URL'),
270
+ shadowDatabaseUrl: env('SHADOW_DATABASE_URL'),
271
+ },
272
+ })
273
+ ```
274
+
275
+ ---
276
+
277
+ ## 실험적 기능
278
+
279
+ ### External Tables
280
+
281
+ 외부에서 관리되는 테이블 설정:
282
+
283
+ ```typescript
284
+ // prisma.config.ts
285
+ import { defineConfig, env } from 'prisma/config'
286
+
287
+ export default defineConfig({
288
+ schema: 'prisma/schema',
289
+ experimental: {
290
+ externalTables: true,
291
+ },
292
+ tables: {
293
+ external: ['public.users'],
294
+ },
295
+ enums: {
296
+ external: ['public.role'],
297
+ },
298
+ datasource: {
299
+ url: env('DATABASE_URL'),
300
+ },
301
+ })
302
+ ```
303
+
304
+ ---
305
+
306
+ ## 경로 해석 규칙
307
+
308
+ ### 중요 사항
309
+
310
+ - 모든 경로는 **config 파일 위치 기준**으로 해석됩니다
311
+ - CLI 명령어 실행 위치가 아닙니다!
312
+
313
+ ### 예시
314
+
315
+ ```
316
+ 프로젝트/
317
+ ├── prisma.config.ts # 여기가 기준!
318
+ ├── prisma/
319
+ │ └── schema/
320
+ └── src/
321
+ ```
322
+
323
+ ```typescript
324
+ // prisma.config.ts
325
+ export default defineConfig({
326
+ // ✅ prisma.config.ts 기준 상대 경로
327
+ schema: 'prisma/schema',
328
+
329
+ // ❌ 이렇게 하지 마세요
330
+ schema: './prisma/schema', // ./ 불필요
331
+ })
332
+ ```
333
+
334
+ ### 커스텀 경로 지정
335
+
336
+ ```bash
337
+ # --config 플래그로 config 파일 위치 지정
338
+ npx prisma validate --config ./path/to/myconfig.ts
339
+ ```
340
+
341
+ ---
342
+
343
+ ## 전체 설정 예시
344
+
345
+ ```typescript
346
+ // prisma.config.ts
347
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
348
+ // Prisma v7 설정 파일
349
+ // Multi-File 스키마 및 마이그레이션 설정
350
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
351
+ import 'dotenv/config'
352
+ import path from 'node:path'
353
+ import { defineConfig, env } from 'prisma/config'
354
+
355
+ export default defineConfig({
356
+ // Multi-File 스키마 폴더
357
+ schema: path.join('prisma', 'schema'),
358
+
359
+ // 마이그레이션 설정
360
+ migrations: {
361
+ path: 'prisma/migrations',
362
+ seed: 'tsx prisma/seed.ts',
363
+ },
364
+
365
+ // 데이터베이스 연결
366
+ datasource: {
367
+ url: env('DATABASE_URL'),
368
+ },
369
+ })
370
+ ```
371
+
372
+ ---
373
+
374
+ ## 관련 문서
375
+
376
+ - [스키마 정의 (Multi-File)](./schema.md)
377
+ - [설치 및 설정](./setup.md)
@@ -47,11 +47,13 @@ generator client {
47
47
 
48
48
  ## 문서 구조
49
49
 
50
+ - [Config 파일](./config.md) - prisma.config.ts 설정 ⭐
50
51
  - [설치 및 설정](./setup.md) - Prisma Client 설정
51
- - [스키마 정의](./schema.md) - 모델, 관계, Enum 정의
52
+ - [스키마 정의 (Multi-File)](./schema.md) - 모델, 관계, Enum 정의
52
53
  - [CRUD 작업](./crud.md) - Create, Read, Update, Delete
53
54
  - [관계 쿼리](./relations.md) - 중첩 생성, 관계 포함 조회
54
55
  - [트랜잭션](./transactions.md) - 배열 기반 트랜잭션, 인터랙티브 트랜잭션
56
+ - [Cloudflare D1](./cloudflare-d1.md) - D1 서버리스 데이터베이스 연동
55
57
 
56
58
  ## 빠른 시작
57
59
 
@@ -64,10 +66,6 @@ npm install -D prisma@7
64
66
  yarn add @prisma/client@7
65
67
  yarn add -D prisma@7
66
68
 
67
- # pnpm
68
- pnpm add @prisma/client@7
69
- pnpm add -D prisma@7
70
-
71
69
  # 초기화
72
70
  npx prisma init
73
71
  ```
@@ -1,63 +1,161 @@
1
- # Prisma - 스키마 정의
1
+ # Prisma - 스키마 정의 (Multi-File)
2
2
 
3
3
  > **상위 문서**: [Prisma](./index.md)
4
4
 
5
- ## 기본 스키마
5
+ ## ⚠️ 필수: Multi-File 구조 사용
6
+
7
+ Prisma 스키마는 **반드시 Multi-File 구조**로 작성합니다.
8
+
9
+ ```
10
+ prisma/
11
+ ├── schema/
12
+ │ ├── +base.prisma # datasource, generator 설정
13
+ │ ├── +enum.prisma # 모든 enum 정의
14
+ │ ├── user.prisma # User 모델
15
+ │ ├── post.prisma # Post 모델
16
+ │ ├── category.prisma # Category 모델
17
+ │ └── profile.prisma # Profile 모델
18
+ ```
19
+
20
+ ## ⚠️ 필수: 한글 주석 작성
21
+
22
+ **Prisma Multi-File의 모든 요소에 한글 주석을 작성해야 합니다.**
23
+
24
+ ```
25
+ ✅ 파일별 목적 주석
26
+ ✅ 모델별 설명 주석
27
+ ✅ 필드별 설명 주석 (용도가 명확하지 않은 경우)
28
+ ✅ 관계 설명 주석
29
+ ✅ enum 값 설명 주석
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Multi-File 스키마 예시
35
+
36
+ ### +base.prisma (기본 설정)
6
37
 
7
38
  ```prisma
8
- // prisma/schema.prisma
39
+ // prisma/schema/+base.prisma
40
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
41
+ // Prisma 기본 설정 파일
42
+ // datasource 및 generator 설정
43
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
44
+
45
+ // 데이터베이스 연결 설정
9
46
  datasource db {
10
47
  provider = "postgresql"
11
48
  url = env("DATABASE_URL")
12
49
  }
13
50
 
51
+ // Prisma Client 생성 설정
14
52
  generator client {
15
- provider = "prisma-client"
53
+ provider = "prisma-client" // Prisma v7 필수
16
54
  output = "../generated/prisma"
17
55
  }
56
+ ```
57
+
58
+ ### +enum.prisma (열거형 정의)
59
+
60
+ ```prisma
61
+ // prisma/schema/+enum.prisma
62
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
63
+ // 모든 열거형(enum) 정의 파일
64
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
65
+
66
+ // 사용자 권한 열거형
67
+ enum Role {
68
+ USER // 일반 사용자
69
+ ADMIN // 관리자
70
+ }
71
+
72
+ // 게시글 상태 열거형
73
+ enum PostStatus {
74
+ DRAFT // 임시저장
75
+ PUBLISHED // 공개됨
76
+ ARCHIVED // 보관됨
77
+ }
78
+ ```
79
+
80
+ ### user.prisma (User 모델)
81
+
82
+ ```prisma
83
+ // prisma/schema/user.prisma
84
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
85
+ // 사용자 모델
86
+ // 시스템의 모든 사용자 정보를 저장
87
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
18
88
 
19
89
  model User {
20
90
  id Int @id @default(autoincrement())
21
- email String @unique
22
- name String?
23
- role Role @default(USER)
24
- posts Post[]
25
- profile ExtendedProfile?
91
+ email String @unique // 로그인 이메일 (중복 불가)
92
+ name String? // 표시 이름 (선택)
93
+ role Role @default(USER) // 사용자 권한
94
+ posts Post[] // 작성한 게시글 목록
95
+ profile ExtendedProfile? // 확장 프로필 (1:1)
26
96
  createdAt DateTime @default(now())
27
97
  updatedAt DateTime @updatedAt
28
98
  }
99
+ ```
100
+
101
+ ### post.prisma (Post 모델)
102
+
103
+ ```prisma
104
+ // prisma/schema/post.prisma
105
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
106
+ // 게시글 모델
107
+ // 사용자가 작성한 게시글 정보
108
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
29
109
 
30
110
  model Post {
31
111
  id Int @id @default(autoincrement())
32
- title String
33
- content String?
34
- published Boolean @default(false)
35
- author User @relation(fields: [authorId], references: [id])
36
- authorId Int
37
- categories Category[]
112
+ title String // 게시글 제목
113
+ content String? // 게시글 본문 (선택)
114
+ published Boolean @default(false) // 공개 여부
115
+ status PostStatus @default(DRAFT) // 게시글 상태
116
+ author User @relation(fields: [authorId], references: [id]) // 작성자 관계
117
+ authorId Int // 작성자 ID (외래키)
118
+ categories Category[] // 소속 카테고리 목록 (M:N)
38
119
  createdAt DateTime @default(now())
39
120
  updatedAt DateTime @updatedAt
40
121
  }
122
+ ```
123
+
124
+ ### category.prisma (Category 모델)
125
+
126
+ ```prisma
127
+ // prisma/schema/category.prisma
128
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
129
+ // 카테고리 모델
130
+ // 게시글 분류를 위한 카테고리
131
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
41
132
 
42
133
  model Category {
43
134
  id Int @id @default(autoincrement())
44
- name String @unique
45
- posts Post[]
135
+ name String @unique // 카테고리명 (중복 불가)
136
+ posts Post[] // 소속 게시글 목록 (M:N)
46
137
  }
138
+ ```
139
+
140
+ ### profile.prisma (Profile 모델)
141
+
142
+ ```prisma
143
+ // prisma/schema/profile.prisma
144
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
145
+ // 확장 프로필 모델
146
+ // 사용자의 추가 정보 (1:1 관계)
147
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
47
148
 
48
149
  model ExtendedProfile {
49
150
  id Int @id @default(autoincrement())
50
- biography String
51
- user User @relation(fields: [userId], references: [id])
52
- userId Int @unique
53
- }
54
-
55
- enum Role {
56
- USER
57
- ADMIN
151
+ biography String // 자기소개
152
+ user User @relation(fields: [userId], references: [id]) // 사용자 관계
153
+ userId Int @unique // 사용자 ID (외래키, 유니크)
58
154
  }
59
155
  ```
60
156
 
157
+ ---
158
+
61
159
  ## 선택적 관계
62
160
 
63
161
  ```prisma
@@ -13,10 +13,6 @@ npm install -D prisma@7
13
13
  yarn add @prisma/client@7
14
14
  yarn add -D prisma@7
15
15
 
16
- # pnpm
17
- pnpm add @prisma/client@7
18
- pnpm add -D prisma@7
19
-
20
16
  # bun
21
17
  bun add @prisma/client@7
22
18
  bun add prisma@7 --dev
@@ -34,9 +30,6 @@ npm install -D prisma@7
34
30
 
35
31
  # yarn
36
32
  yarn up prisma@7 @prisma/client@7
37
-
38
- # pnpm
39
- pnpm upgrade prisma@7 @prisma/client@7
40
33
  ```
41
34
 
42
35
  ### Generator 변경 (필수)
@@ -4,6 +4,21 @@
4
4
 
5
5
  Server Functions는 서버에서만 실행되는 타입 안전한 함수입니다.
6
6
 
7
+ ## ⚠️ 필수: TanStack Query 사용
8
+
9
+ **Server Function을 클라이언트에서 호출할 때는 반드시 TanStack Query를 사용해야 합니다.**
10
+
11
+ ```
12
+ ❌ 금지: Server Function 직접 호출
13
+ ✅ 필수: useQuery/useMutation과 함께 사용
14
+ ```
15
+
16
+ **이유**:
17
+ - 자동 캐싱 및 중복 요청 제거
18
+ - 로딩/에러 상태 관리
19
+ - 자동 재시도 및 백그라운드 갱신
20
+ - invalidateQueries로 일관된 데이터 동기화
21
+
7
22
  ## 기본 Server Function
8
23
 
9
24
  ```typescript
@@ -73,9 +88,9 @@ export const submitForm = createServerFn({ method: 'POST' })
73
88
  })
74
89
  ```
75
90
 
76
- ## 컴포넌트에서 호출
91
+ ## 컴포넌트에서 호출 (TanStack Query 필수)
77
92
 
78
- ### useServerFn 사용
93
+ ### 올바른 패턴: useQuery 사용 (데이터 조회)
79
94
 
80
95
  ```tsx
81
96
  import { useServerFn } from '@tanstack/react-start'
@@ -103,6 +118,69 @@ function PostList() {
103
118
  }
104
119
  ```
105
120
 
121
+ ### ✅ 올바른 패턴: useMutation 사용 (데이터 변경)
122
+
123
+ ```tsx
124
+ import { useServerFn } from '@tanstack/react-start'
125
+ import { useMutation, useQueryClient } from '@tanstack/react-query'
126
+ import { createPost, deletePost } from '~/lib/server-functions'
127
+
128
+ function PostForm() {
129
+ const queryClient = useQueryClient()
130
+ const createPostFn = useServerFn(createPost)
131
+
132
+ const mutation = useMutation({
133
+ mutationFn: (data: { title: string; content: string }) => createPostFn({ data }),
134
+ onSuccess: () => {
135
+ // 관련 쿼리 무효화로 데이터 동기화
136
+ queryClient.invalidateQueries({ queryKey: ['posts'] })
137
+ },
138
+ })
139
+
140
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
141
+ e.preventDefault()
142
+ const formData = new FormData(e.currentTarget)
143
+ mutation.mutate({
144
+ title: formData.get('title') as string,
145
+ content: formData.get('content') as string,
146
+ })
147
+ }
148
+
149
+ return (
150
+ <form onSubmit={handleSubmit}>
151
+ <input name="title" required />
152
+ <textarea name="content" required />
153
+ <button type="submit" disabled={mutation.isPending}>
154
+ {mutation.isPending ? '저장 중...' : '저장'}
155
+ </button>
156
+ </form>
157
+ )
158
+ }
159
+ ```
160
+
161
+ ### ❌ 금지: Server Function 직접 호출
162
+
163
+ ```tsx
164
+ // ❌ 이렇게 하지 마세요!
165
+ function BadExample() {
166
+ const [posts, setPosts] = useState([])
167
+ const [loading, setLoading] = useState(false)
168
+
169
+ useEffect(() => {
170
+ setLoading(true)
171
+ getPosts()
172
+ .then(setPosts)
173
+ .finally(() => setLoading(false))
174
+ }, [])
175
+
176
+ // 문제점:
177
+ // - 중복 요청 발생 가능
178
+ // - 캐싱 없음
179
+ // - 에러 처리 수동
180
+ // - 다른 컴포넌트와 데이터 동기화 안됨
181
+ }
182
+ ```
183
+
106
184
  ## 보안 패턴
107
185
 
108
186
  ### 서버 전용 데이터 보호