@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,320 @@
1
+ # Pino - Structured Logging
2
+
3
+ > 초고속 JSON 로거 (Server Functions 전용)
4
+
5
+ ---
6
+
7
+ ## ⚠️ 중요: Server Functions에서만 사용
8
+
9
+ Pino는 **Server Functions에서만** 사용해야 합니다. 클라이언트 컴포넌트에서는 사용하지 마세요.
10
+
11
+ ```
12
+ ✅ src/functions/*.ts → Pino 사용 가능
13
+ ✅ routes/*/-functions/*.ts → Pino 사용 가능
14
+ ❌ routes/*.tsx (컴포넌트) → Pino 사용 금지 (console.log 사용)
15
+ ❌ components/*.tsx → Pino 사용 금지
16
+ ```
17
+
18
+ ---
19
+
20
+ ## 왜 console.log 대신 Pino를 사용해야 하나요?
21
+
22
+ | 항목 | console.log | Pino |
23
+ |------|-------------|------|
24
+ | **출력 형식** | 비정형 텍스트 | 구조화된 JSON |
25
+ | **성능** | 느림 | 초고속 (30x 빠름) |
26
+ | **로그 레벨** | 없음 | debug, info, warn, error, fatal |
27
+ | **컨텍스트 추가** | 수동 문자열 연결 | 자동 객체 바인딩 |
28
+ | **프로덕션 분석** | 어려움 | JSON 파싱으로 쉬움 |
29
+ | **Child Logger** | 불가 | 요청별 컨텍스트 분리 |
30
+
31
+ ---
32
+
33
+ ## 설치
34
+
35
+ ```bash
36
+ # pino + pino-pretty (개발용 포맷터)
37
+ npm install pino pino-pretty
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 기본 설정
43
+
44
+ ### lib/logger.ts
45
+
46
+ ```typescript
47
+ import pino from 'pino'
48
+
49
+ const isDev = process.env.NODE_ENV === 'development'
50
+
51
+ export const logger = pino({
52
+ level: isDev ? 'debug' : 'info',
53
+ transport: isDev
54
+ ? {
55
+ target: 'pino-pretty',
56
+ options: {
57
+ colorize: true,
58
+ translateTime: 'SYS:yyyy-mm-dd HH:MM:ss',
59
+ ignore: 'pid,hostname',
60
+ },
61
+ }
62
+ : undefined,
63
+ })
64
+ ```
65
+
66
+ ### 환경별 출력
67
+
68
+ **개발 환경** (pino-pretty):
69
+ ```
70
+ 2024-01-15 10:30:45 INFO: User created successfully
71
+ userId: "user_123"
72
+ email: "user@example.com"
73
+ ```
74
+
75
+ **프로덕션** (JSON):
76
+ ```json
77
+ {"level":30,"time":1705312245000,"msg":"User created successfully","userId":"user_123","email":"user@example.com"}
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Server Functions에서 사용
83
+
84
+ ### 기본 사용법
85
+
86
+ ```typescript
87
+ // functions/user.ts
88
+ import { createServerFn } from '@tanstack/react-start'
89
+ import { logger } from '@/lib/logger'
90
+ import { prisma } from '@/database/prisma'
91
+ import { createUserSchema } from '@/validators/user'
92
+ import { authMiddleware } from '@/middleware/auth'
93
+
94
+ export const createUser = createServerFn({ method: 'POST' })
95
+ .middleware([authMiddleware])
96
+ .inputValidator(createUserSchema)
97
+ .handler(async ({ data, context }) => {
98
+ logger.info({ email: data.email }, 'Creating new user')
99
+
100
+ try {
101
+ const user = await prisma.user.create({ data })
102
+ logger.info({ userId: user.id }, 'User created successfully')
103
+ return user
104
+ } catch (error) {
105
+ logger.error({ error, email: data.email }, 'Failed to create user')
106
+ throw error
107
+ }
108
+ })
109
+ ```
110
+
111
+ ### Child Logger로 요청 컨텍스트 추가
112
+
113
+ ```typescript
114
+ // functions/user.ts
115
+ import { createServerFn } from '@tanstack/react-start'
116
+ import { logger } from '@/lib/logger'
117
+ import { prisma } from '@/database/prisma'
118
+
119
+ export const getUser = createServerFn({ method: 'GET' })
120
+ .middleware([authMiddleware])
121
+ .handler(async ({ context }) => {
122
+ // 요청별 컨텍스트가 포함된 child logger 생성
123
+ const log = logger.child({
124
+ requestId: context.requestId,
125
+ userId: context.userId,
126
+ })
127
+
128
+ log.info('Fetching user profile')
129
+
130
+ const user = await prisma.user.findUnique({
131
+ where: { id: context.userId },
132
+ })
133
+
134
+ if (!user) {
135
+ log.warn('User not found')
136
+ throw new Error('User not found')
137
+ }
138
+
139
+ log.debug({ user }, 'User fetched successfully')
140
+ return user
141
+ })
142
+ ```
143
+
144
+ **출력 예시**:
145
+ ```json
146
+ {"level":30,"time":1705312245000,"requestId":"req_abc123","userId":"user_456","msg":"Fetching user profile"}
147
+ {"level":20,"time":1705312245050,"requestId":"req_abc123","userId":"user_456","user":{"id":"user_456","name":"John"},"msg":"User fetched successfully"}
148
+ ```
149
+
150
+ ---
151
+
152
+ ## 로그 레벨
153
+
154
+ ```typescript
155
+ logger.trace('매우 상세한 디버깅 정보') // level: 10
156
+ logger.debug('디버깅 정보') // level: 20
157
+ logger.info('일반 정보') // level: 30
158
+ logger.warn('경고') // level: 40
159
+ logger.error('에러') // level: 50
160
+ logger.fatal('치명적 에러') // level: 60
161
+ ```
162
+
163
+ ### 레벨별 사용 가이드
164
+
165
+ | 레벨 | 용도 | 예시 |
166
+ |------|------|------|
167
+ | `trace` | 매우 상세한 흐름 추적 | 함수 진입/종료, 변수 값 |
168
+ | `debug` | 개발 중 디버깅 | 쿼리 결과, 중간 계산값 |
169
+ | `info` | 주요 이벤트 | 사용자 생성, 결제 완료 |
170
+ | `warn` | 주의 필요 | 재시도 발생, 느린 쿼리 |
171
+ | `error` | 에러 발생 | API 실패, 예외 처리 |
172
+ | `fatal` | 시스템 중단 | 서버 시작 실패 |
173
+
174
+ ---
175
+
176
+ ## 구조화된 로깅 패턴
177
+
178
+ ### 객체와 메시지 함께 로깅
179
+
180
+ ```typescript
181
+ // ✅ 올바른 패턴: 객체 먼저, 메시지 나중
182
+ logger.info({ userId: '123', action: 'login' }, 'User logged in')
183
+
184
+ // ❌ 잘못된 패턴: 문자열 연결
185
+ logger.info('User ' + userId + ' logged in') // 구조화되지 않음
186
+ ```
187
+
188
+ ### 에러 로깅
189
+
190
+ ```typescript
191
+ try {
192
+ await riskyOperation()
193
+ } catch (error) {
194
+ // ✅ err 키로 에러 객체 전달 (스택 트레이스 자동 포함)
195
+ logger.error({ err: error, context: 'riskyOperation' }, 'Operation failed')
196
+ }
197
+ ```
198
+
199
+ **출력**:
200
+ ```json
201
+ {
202
+ "level": 50,
203
+ "time": 1705312245000,
204
+ "err": {
205
+ "type": "Error",
206
+ "message": "Connection refused",
207
+ "stack": "Error: Connection refused\n at ..."
208
+ },
209
+ "context": "riskyOperation",
210
+ "msg": "Operation failed"
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## 고급 설정
217
+
218
+ ### pino-pretty 전체 옵션
219
+
220
+ ```typescript
221
+ // lib/logger.ts
222
+ import pino from 'pino'
223
+
224
+ export const logger = pino({
225
+ level: process.env.LOG_LEVEL || 'info',
226
+ transport:
227
+ process.env.NODE_ENV === 'development'
228
+ ? {
229
+ target: 'pino-pretty',
230
+ options: {
231
+ colorize: true,
232
+ translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l',
233
+ ignore: 'pid,hostname',
234
+ singleLine: false,
235
+ levelFirst: true,
236
+ messageFormat: '{levelLabel} - {msg}',
237
+ customColors: 'info:blue,warn:yellow,error:red,fatal:bgRed',
238
+ errorProps: 'stack,code,cause',
239
+ },
240
+ }
241
+ : undefined,
242
+ })
243
+ ```
244
+
245
+ ### TypeScript 타입 강제
246
+
247
+ ```typescript
248
+ // types/pino.d.ts
249
+ declare module 'pino' {
250
+ interface LogFnFields {
251
+ userId?: string
252
+ requestId?: string
253
+ action?: string
254
+ }
255
+ }
256
+ ```
257
+
258
+ ```typescript
259
+ // 사용 시 타입 검사
260
+ logger.info({ userId: '123' }, 'User action') // ✅
261
+ logger.info({ userId: 123 }, 'User action') // ❌ 타입 에러
262
+ ```
263
+
264
+ ---
265
+
266
+ ## 프로덕션 설정
267
+
268
+ ### 환경 변수
269
+
270
+ ```bash
271
+ # .env
272
+ LOG_LEVEL=info # production
273
+ # LOG_LEVEL=debug # staging
274
+ ```
275
+
276
+ ### 멀티 스트림 (파일 + stdout)
277
+
278
+ ```typescript
279
+ import pino from 'pino'
280
+
281
+ const streams = [
282
+ { level: 'info', stream: process.stdout },
283
+ { level: 'error', stream: pino.destination('./logs/error.log') },
284
+ ]
285
+
286
+ export const logger = pino(
287
+ { level: 'debug' },
288
+ pino.multistream(streams)
289
+ )
290
+ ```
291
+
292
+ ---
293
+
294
+ ## ❌ 하지 말아야 할 것
295
+
296
+ ```typescript
297
+ // ❌ 클라이언트 컴포넌트에서 pino 사용 금지
298
+ const MyComponent = () => {
299
+ logger.info('Component rendered') // ❌ 서버에서만 동작
300
+ return <div>Hello</div>
301
+ }
302
+
303
+ // ❌ 민감한 정보 로깅 금지
304
+ logger.info({ password: user.password }, 'User logged in') // ❌
305
+
306
+ // ❌ 문자열 연결 사용 금지
307
+ logger.info('User ' + userId + ' created at ' + new Date()) // ❌
308
+
309
+ // ❌ console.log와 혼용 금지 (Server Functions에서)
310
+ console.log('Processing...') // ❌ pino 사용하세요
311
+ logger.info('Processing...') // ✅
312
+ ```
313
+
314
+ ---
315
+
316
+ ## 관련 문서
317
+
318
+ - [Server Functions](../tanstack-start/server-functions.md)
319
+ - [미들웨어](../tanstack-start/middleware.md)
320
+ - [아키텍처](../../architecture/architecture.md)
@@ -0,0 +1,404 @@
1
+ # Prisma - Cloudflare D1
2
+
3
+ > **상위 문서**: [Prisma](./index.md)
4
+
5
+ ---
6
+
7
+ ## ⚠️ 주의사항
8
+
9
+ Cloudflare D1은 **SQLite 기반 서버리스 데이터베이스**입니다. 일반 Prisma 마이그레이션과 **다른 워크플로우**를 사용합니다.
10
+
11
+ ```
12
+ ⚠️ D1은 트랜잭션을 지원하지 않음 (ACID 보장 X)
13
+ ⚠️ prisma migrate dev 사용 불가 - wrangler CLI 사용
14
+ ⚠️ Prisma ORM D1 지원은 Preview 상태
15
+ ```
16
+
17
+ ---
18
+
19
+ ## 🚀 Quick Reference
20
+
21
+ ```typescript
22
+ // D1 Adapter 설정
23
+ import { PrismaClient } from './generated/prisma'
24
+ import { PrismaD1 } from '@prisma/adapter-d1'
25
+
26
+ export interface Env {
27
+ DB: D1Database
28
+ }
29
+
30
+ export default {
31
+ async fetch(request: Request, env: Env): Promise<Response> {
32
+ const adapter = new PrismaD1(env.DB)
33
+ const prisma = new PrismaClient({ adapter })
34
+
35
+ const users = await prisma.user.findMany()
36
+ return new Response(JSON.stringify(users))
37
+ },
38
+ }
39
+ ```
40
+
41
+ ### schema.prisma (D1용)
42
+
43
+ ```prisma
44
+ generator client {
45
+ provider = "prisma-client"
46
+ output = "../src/generated/prisma"
47
+ runtime = "cloudflare" // D1 필수!
48
+ }
49
+
50
+ datasource db {
51
+ provider = "sqlite" // D1은 SQLite 기반
52
+ }
53
+
54
+ model User {
55
+ id Int @id @default(autoincrement())
56
+ email String @unique
57
+ name String?
58
+ }
59
+ ```
60
+
61
+ ---
62
+
63
+ ## 설치
64
+
65
+ ```bash
66
+ # 필수 패키지
67
+ npm install @prisma/client @prisma/adapter-d1
68
+ npm install -D prisma wrangler
69
+
70
+ # Prisma 초기화
71
+ npx prisma init --datasource-provider sqlite
72
+ ```
73
+
74
+ ---
75
+
76
+ ## D1 데이터베이스 생성
77
+
78
+ ```bash
79
+ # Cloudflare D1 데이터베이스 생성
80
+ npx wrangler d1 create my-database
81
+
82
+ # 출력 예시:
83
+ # ✅ Successfully created DB 'my-database'
84
+ # database_id = "xxxx-xxxx-xxxx-xxxx"
85
+ ```
86
+
87
+ ---
88
+
89
+ ## wrangler.jsonc 설정
90
+
91
+ ```jsonc
92
+ {
93
+ "$schema": "node_modules/wrangler/config-schema.json",
94
+ "name": "my-worker",
95
+ "main": "src/index.ts",
96
+ "compatibility_date": "2025-01-01",
97
+ "d1_databases": [
98
+ {
99
+ "binding": "DB",
100
+ "database_name": "my-database",
101
+ "database_id": "YOUR_DATABASE_ID"
102
+ }
103
+ ]
104
+ }
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Schema 설정
110
+
111
+ ### schema.prisma
112
+
113
+ ```prisma
114
+ generator client {
115
+ provider = "prisma-client"
116
+ output = "../src/generated/prisma"
117
+ runtime = "cloudflare"
118
+ }
119
+
120
+ datasource db {
121
+ provider = "sqlite"
122
+ }
123
+
124
+ model User {
125
+ id Int @id @default(autoincrement())
126
+ email String @unique
127
+ name String?
128
+ posts Post[]
129
+ }
130
+
131
+ model Post {
132
+ id Int @id @default(autoincrement())
133
+ title String
134
+ content String?
135
+ published Boolean @default(false)
136
+ author User @relation(fields: [authorId], references: [id])
137
+ authorId Int
138
+ }
139
+ ```
140
+
141
+ ---
142
+
143
+ ## 마이그레이션 워크플로우
144
+
145
+ D1은 일반 Prisma 마이그레이션(`prisma migrate dev`)을 사용하지 않습니다.
146
+
147
+ ### 1단계: 마이그레이션 디렉토리 생성
148
+
149
+ ```bash
150
+ mkdir -p prisma/migrations
151
+ ```
152
+
153
+ ### 2단계: 마이그레이션 파일 생성 (wrangler)
154
+
155
+ ```bash
156
+ npx wrangler d1 migrations create my-database create_user_table
157
+ ```
158
+
159
+ ### 3단계: SQL 생성 (prisma migrate diff)
160
+
161
+ ```bash
162
+ # 초기 마이그레이션 (빈 스키마에서)
163
+ npx prisma migrate diff \
164
+ --from-empty \
165
+ --to-schema-datamodel prisma/schema.prisma \
166
+ --script \
167
+ --output prisma/migrations/0001_create_user_table.sql
168
+
169
+ # 후속 마이그레이션 (로컬 D1에서)
170
+ npx prisma migrate diff \
171
+ --from-local-d1 \
172
+ --to-schema-datamodel prisma/schema.prisma \
173
+ --script \
174
+ --output prisma/migrations/0002_add_post_table.sql
175
+ ```
176
+
177
+ ### 4단계: 마이그레이션 적용
178
+
179
+ ```bash
180
+ # 로컬 데이터베이스에 적용
181
+ npx wrangler d1 migrations apply my-database --local
182
+
183
+ # 원격(프로덕션) 데이터베이스에 적용
184
+ npx wrangler d1 migrations apply my-database --remote
185
+ ```
186
+
187
+ ### 생성된 SQL 예시
188
+
189
+ ```sql
190
+ -- 0001_create_user_table.sql
191
+ -- CreateTable
192
+ CREATE TABLE "User" (
193
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
194
+ "email" TEXT NOT NULL,
195
+ "name" TEXT
196
+ );
197
+
198
+ -- CreateIndex
199
+ CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Prisma Client 설정
205
+
206
+ ### Cloudflare Worker에서 사용
207
+
208
+ ```typescript
209
+ // src/index.ts
210
+ import { PrismaClient } from './generated/prisma'
211
+ import { PrismaD1 } from '@prisma/adapter-d1'
212
+
213
+ export interface Env {
214
+ DB: D1Database
215
+ }
216
+
217
+ export default {
218
+ async fetch(
219
+ request: Request,
220
+ env: Env,
221
+ ctx: ExecutionContext
222
+ ): Promise<Response> {
223
+ const adapter = new PrismaD1(env.DB)
224
+ const prisma = new PrismaClient({ adapter })
225
+
226
+ const url = new URL(request.url)
227
+
228
+ if (url.pathname === '/users' && request.method === 'GET') {
229
+ const users = await prisma.user.findMany()
230
+ return new Response(JSON.stringify(users), {
231
+ headers: { 'Content-Type': 'application/json' },
232
+ })
233
+ }
234
+
235
+ if (url.pathname === '/users' && request.method === 'POST') {
236
+ const body = await request.json()
237
+ const user = await prisma.user.create({
238
+ data: body,
239
+ })
240
+ return new Response(JSON.stringify(user), {
241
+ status: 201,
242
+ headers: { 'Content-Type': 'application/json' },
243
+ })
244
+ }
245
+
246
+ return new Response('Not Found', { status: 404 })
247
+ },
248
+ }
249
+ ```
250
+
251
+ ---
252
+
253
+ ## TanStack Start + D1 통합
254
+
255
+ D1은 Cloudflare Workers 환경에서 실행되므로, TanStack Start의 Cloudflare 배포와 함께 사용합니다.
256
+
257
+ ### Server Function에서 사용
258
+
259
+ ```typescript
260
+ // lib/prisma.ts
261
+ import { PrismaClient } from './generated/prisma'
262
+ import { PrismaD1 } from '@prisma/adapter-d1'
263
+
264
+ export const createPrismaClient = (db: D1Database) => {
265
+ const adapter = new PrismaD1(db)
266
+ return new PrismaClient({ adapter })
267
+ }
268
+
269
+ // Server Function
270
+ import { createServerFn } from '@tanstack/react-start'
271
+
272
+ export const getUsers = createServerFn({ method: 'GET' })
273
+ .handler(async ({ context }) => {
274
+ // context에서 D1 바인딩 접근 필요
275
+ const prisma = createPrismaClient(context.env.DB)
276
+ return prisma.user.findMany()
277
+ })
278
+ ```
279
+
280
+ ---
281
+
282
+ ## 로컬 개발
283
+
284
+ ### 로컬 D1로 개발
285
+
286
+ ```bash
287
+ # 로컬 Worker 실행 (D1 포함)
288
+ npx wrangler dev
289
+
290
+ # 로컬 D1에 데이터 삽입
291
+ npx wrangler d1 execute my-database --local \
292
+ --command "INSERT INTO User (email, name) VALUES ('test@example.com', 'Test User');"
293
+
294
+ # 로컬 D1 조회
295
+ npx wrangler d1 execute my-database --local \
296
+ --command "SELECT * FROM User;"
297
+ ```
298
+
299
+ ---
300
+
301
+ ## 배포
302
+
303
+ ```bash
304
+ # Prisma Client 생성
305
+ npx prisma generate
306
+
307
+ # 원격 D1에 마이그레이션 적용
308
+ npx wrangler d1 migrations apply my-database --remote
309
+
310
+ # Worker 배포
311
+ npx wrangler deploy
312
+ ```
313
+
314
+ ---
315
+
316
+ ## ⚠️ 제한사항
317
+
318
+ ### 트랜잭션 미지원
319
+
320
+ ```typescript
321
+ // ❌ 트랜잭션이 무시됨 - ACID 보장 안됨
322
+ await prisma.$transaction([
323
+ prisma.user.create({ data: { email: 'user1@example.com' } }),
324
+ prisma.post.create({ data: { title: 'Post', authorId: 1 } }),
325
+ ])
326
+
327
+ // ❌ Interactive 트랜잭션도 미지원
328
+ await prisma.$transaction(async (tx) => {
329
+ // 각 쿼리가 독립적으로 실행됨
330
+ })
331
+ ```
332
+
333
+ ### D1 vs 일반 SQLite 차이점
334
+
335
+ | 항목 | 일반 SQLite | Cloudflare D1 |
336
+ |------|-------------|---------------|
337
+ | 마이그레이션 | `prisma migrate dev` | `wrangler d1 migrations` |
338
+ | 트랜잭션 | ✅ 지원 | ❌ 미지원 |
339
+ | 데이터베이스 위치 | 로컬 파일 | Cloudflare Edge |
340
+ | 접속 방식 | 직접 연결 | HTTP (어댑터) |
341
+ | 환경 | 로컬 `.wrangler/state` | 원격 Cloudflare |
342
+
343
+ ---
344
+
345
+ ## prisma.config.ts (선택사항)
346
+
347
+ Prisma CLI에서 D1에 직접 접근이 필요한 경우:
348
+
349
+ ```typescript
350
+ // prisma.config.ts
351
+ import path from 'node:path'
352
+ import type { PrismaConfig } from 'prisma'
353
+ import { PrismaD1 } from '@prisma/adapter-d1'
354
+
355
+ export default {
356
+ experimental: {
357
+ adapter: true,
358
+ },
359
+ engine: 'js',
360
+ schema: path.join('prisma', 'schema.prisma'),
361
+ async adapter() {
362
+ return new PrismaD1({
363
+ CLOUDFLARE_D1_TOKEN: process.env.CLOUDFLARE_D1_TOKEN,
364
+ CLOUDFLARE_ACCOUNT_ID: process.env.CLOUDFLARE_ACCOUNT_ID,
365
+ CLOUDFLARE_DATABASE_ID: process.env.CLOUDFLARE_DATABASE_ID,
366
+ })
367
+ },
368
+ } satisfies PrismaConfig
369
+ ```
370
+
371
+ ---
372
+
373
+ ## 마이그레이션 명령어 요약
374
+
375
+ ```bash
376
+ # D1 데이터베이스 생성
377
+ npx wrangler d1 create my-database
378
+
379
+ # 마이그레이션 파일 생성
380
+ npx wrangler d1 migrations create my-database migration_name
381
+
382
+ # SQL 생성 (초기)
383
+ npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script
384
+
385
+ # SQL 생성 (후속)
386
+ npx prisma migrate diff --from-local-d1 --to-schema-datamodel prisma/schema.prisma --script
387
+
388
+ # 로컬 적용
389
+ npx wrangler d1 migrations apply my-database --local
390
+
391
+ # 원격 적용
392
+ npx wrangler d1 migrations apply my-database --remote
393
+
394
+ # Prisma Client 생성
395
+ npx prisma generate
396
+ ```
397
+
398
+ ---
399
+
400
+ ## 참고 자료
401
+
402
+ - [Prisma D1 공식 문서](https://www.prisma.io/docs/orm/overview/databases/cloudflare-d1)
403
+ - [Cloudflare D1 문서](https://developers.cloudflare.com/d1/)
404
+ - [Prisma D1 가이드](https://www.prisma.io/guides/cloudflare-d1)