@kood/claude-code 0.1.6 → 0.1.9

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 (107) hide show
  1. package/dist/index.js +109 -216
  2. package/package.json +8 -2
  3. package/templates/hono/CLAUDE.md +59 -328
  4. package/templates/hono/docs/architecture/architecture.md +93 -747
  5. package/templates/hono/docs/deployment/cloudflare.md +59 -513
  6. package/templates/hono/docs/deployment/docker.md +41 -356
  7. package/templates/hono/docs/deployment/index.md +54 -190
  8. package/templates/hono/docs/deployment/railway.md +36 -306
  9. package/templates/hono/docs/deployment/vercel.md +49 -434
  10. package/templates/hono/docs/library/ai-sdk/index.md +53 -290
  11. package/templates/hono/docs/library/ai-sdk/openrouter.md +19 -387
  12. package/templates/hono/docs/library/ai-sdk/providers.md +28 -394
  13. package/templates/hono/docs/library/ai-sdk/streaming.md +52 -353
  14. package/templates/hono/docs/library/ai-sdk/structured-output.md +63 -395
  15. package/templates/hono/docs/library/ai-sdk/tools.md +62 -431
  16. package/templates/hono/docs/library/hono/env-setup.md +24 -313
  17. package/templates/hono/docs/library/hono/error-handling.md +34 -295
  18. package/templates/hono/docs/library/hono/index.md +29 -121
  19. package/templates/hono/docs/library/hono/middleware.md +21 -188
  20. package/templates/hono/docs/library/hono/rpc.md +40 -341
  21. package/templates/hono/docs/library/hono/validation.md +35 -195
  22. package/templates/hono/docs/library/pino/index.md +42 -333
  23. package/templates/hono/docs/library/prisma/cloudflare-d1.md +64 -367
  24. package/templates/hono/docs/library/prisma/config.md +19 -260
  25. package/templates/hono/docs/library/prisma/index.md +67 -320
  26. package/templates/hono/docs/library/zod/index.md +53 -257
  27. package/templates/npx/CLAUDE.md +62 -274
  28. package/templates/npx/docs/references/patterns.md +160 -0
  29. package/templates/tanstack-start/CLAUDE.md +100 -256
  30. package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
  31. package/templates/tanstack-start/docs/deployment/cloudflare.md +37 -424
  32. package/templates/tanstack-start/docs/deployment/index.md +57 -286
  33. package/templates/tanstack-start/docs/deployment/nitro.md +36 -318
  34. package/templates/tanstack-start/docs/deployment/railway.md +40 -409
  35. package/templates/tanstack-start/docs/deployment/vercel.md +43 -465
  36. package/templates/tanstack-start/docs/design/components.md +77 -311
  37. package/templates/tanstack-start/docs/design/index.md +113 -69
  38. package/templates/tanstack-start/docs/design/safe-area.md +51 -250
  39. package/templates/tanstack-start/docs/design/tailwind-setup.md +45 -359
  40. package/templates/tanstack-start/docs/guides/conventions.md +103 -0
  41. package/templates/tanstack-start/docs/guides/env-setup.md +34 -340
  42. package/templates/tanstack-start/docs/guides/getting-started.md +22 -209
  43. package/templates/tanstack-start/docs/guides/hooks.md +166 -0
  44. package/templates/tanstack-start/docs/guides/routes.md +166 -0
  45. package/templates/tanstack-start/docs/guides/services.md +143 -0
  46. package/templates/tanstack-start/docs/library/better-auth/2fa.md +27 -115
  47. package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
  48. package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
  49. package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
  50. package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
  51. package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
  52. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
  53. package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
  54. package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
  55. package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
  56. package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
  57. package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
  58. package/templates/tanstack-start/docs/library/prisma/setup.md +12 -112
  59. package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
  60. package/templates/tanstack-start/docs/library/tanstack-query/index.md +26 -97
  61. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
  62. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
  63. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
  64. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
  65. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
  66. package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
  67. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
  68. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
  69. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +34 -246
  70. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
  71. package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
  72. package/templates/tanstack-start/docs/library/zod/index.md +31 -144
  73. package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
  74. package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
  75. package/templates/hono/docs/commands/git.md +0 -145
  76. package/templates/hono/docs/mcp/context7.md +0 -106
  77. package/templates/hono/docs/mcp/index.md +0 -176
  78. package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
  79. package/templates/hono/docs/mcp/serena.md +0 -269
  80. package/templates/hono/docs/mcp/sgrep.md +0 -105
  81. package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
  82. package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
  83. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
  84. package/templates/npx/docs/commands/git.md +0 -145
  85. package/templates/npx/docs/mcp/index.md +0 -60
  86. package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
  87. package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
  88. package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
  89. package/templates/tanstack-start/docs/commands/git.md +0 -145
  90. package/templates/tanstack-start/docs/design/accessibility.md +0 -433
  91. package/templates/tanstack-start/docs/design/color.md +0 -235
  92. package/templates/tanstack-start/docs/design/spacing.md +0 -341
  93. package/templates/tanstack-start/docs/design/typography.md +0 -324
  94. package/templates/tanstack-start/docs/guides/best-practices.md +0 -950
  95. package/templates/tanstack-start/docs/guides/husky-lint-staged.md +0 -303
  96. package/templates/tanstack-start/docs/guides/prettier.md +0 -189
  97. package/templates/tanstack-start/docs/guides/project-templates.md +0 -710
  98. package/templates/tanstack-start/docs/library/tanstack-query/setup.md +0 -107
  99. package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -186
  100. package/templates/tanstack-start/docs/mcp/context7.md +0 -204
  101. package/templates/tanstack-start/docs/mcp/index.md +0 -177
  102. package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
  103. package/templates/tanstack-start/docs/mcp/serena.md +0 -269
  104. package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
  105. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
  106. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
  107. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +0 -292
@@ -1,149 +1,49 @@
1
1
  # Prisma - 설치 및 설정
2
2
 
3
- > **상위 문서**: [Prisma](./index.md)
4
-
5
3
  ## 설치
6
4
 
7
5
  ```bash
8
- # npm
9
- npm install @prisma/client@7
10
- npm install -D prisma@7
11
-
12
- # yarn
13
6
  yarn add @prisma/client@7
14
7
  yarn add -D prisma@7
15
-
16
- # bun
17
- bun add @prisma/client@7
18
- bun add prisma@7 --dev
19
-
20
- # 초기화
21
8
  npx prisma init
22
9
  ```
23
10
 
24
- ## v6에서 v7 업그레이드
25
-
26
- ```bash
27
- # npm
28
- npm install @prisma/client@7
29
- npm install -D prisma@7
30
-
31
- # yarn
32
- yarn up prisma@7 @prisma/client@7
33
- ```
34
-
35
- ### Generator 변경 (필수)
11
+ ## v6 v7 업그레이드
36
12
 
37
13
  ```prisma
38
- // schema.prisma - 이전 (v6)
14
+ // v6 (이전)
39
15
  generator client {
40
16
  provider = "prisma-client-js"
41
17
  }
42
18
 
43
- // schema.prisma - v7
19
+ // v7 (필수)
44
20
  generator client {
45
- provider = "prisma-client" // 새로운 provider
46
- output = "../generated/prisma" // output 필수
21
+ provider = "prisma-client"
22
+ output = "../generated/prisma"
47
23
  }
48
24
  ```
49
25
 
50
- ## Prisma Client 설정
51
-
52
- ### 기본 설정
26
+ ## Prisma Client
53
27
 
54
28
  ```typescript
55
29
  // lib/prisma.ts
56
- import { PrismaClient } from './generated/prisma' // output 경로에서 import
57
-
58
- const globalForPrisma = globalThis as unknown as {
59
- prisma: PrismaClient | undefined
60
- }
61
-
62
- export const prisma =
63
- globalForPrisma.prisma ??
64
- new PrismaClient({
65
- log: ['query'],
66
- })
67
-
68
- if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
69
- ```
70
-
71
- ### 로깅 설정
72
-
73
- ```typescript
74
30
  import { PrismaClient } from './generated/prisma'
75
31
 
76
- const prisma = new PrismaClient({
77
- log: [{ level: 'query', emit: 'event' }],
78
- })
79
-
80
- prisma.$on('query', (e) => {
81
- console.log('Query:', e.query)
82
- console.log('Params:', e.params)
83
- console.log('Duration:', e.duration, 'ms')
84
- })
85
- ```
86
-
87
- ### QueryEvent 타입
88
-
89
- ```typescript
90
- type QueryEvent = {
91
- timestamp: Date
92
- query: string
93
- params: string
94
- duration: number
95
- target: string
96
- }
32
+ const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined }
33
+ export const prisma = globalForPrisma.prisma ?? new PrismaClient({ log: ['query'] })
34
+ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
97
35
  ```
98
36
 
99
- ## TanStack Start 통합
37
+ ## TanStack Start 연동
100
38
 
101
39
  ```typescript
102
- // lib/prisma.ts
103
- import { PrismaClient } from './generated/prisma'
104
-
105
- const globalForPrisma = globalThis as unknown as {
106
- prisma: PrismaClient | undefined
107
- }
108
-
109
- export const prisma =
110
- globalForPrisma.prisma ?? new PrismaClient()
111
-
112
- if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
113
-
114
- // Server Function에서 사용
115
40
  import { createServerFn } from '@tanstack/react-start'
116
41
  import { prisma } from '@/lib/prisma'
117
42
 
118
43
  export const getUsers = createServerFn({ method: 'GET' })
119
- .handler(async () => {
120
- return prisma.user.findMany({
121
- include: { posts: true },
122
- })
123
- })
44
+ .handler(async () => prisma.user.findMany({ include: { posts: true } }))
124
45
 
125
46
  export const createUser = createServerFn({ method: 'POST' })
126
47
  .inputValidator((data: { email: string; name: string }) => data)
127
- .handler(async ({ data }) => {
128
- return prisma.user.create({ data })
129
- })
130
- ```
131
-
132
- ## 마이그레이션
133
-
134
- ```bash
135
- # 개발 환경 마이그레이션
136
- npx prisma migrate dev --name init
137
-
138
- # 프로덕션 마이그레이션
139
- npx prisma migrate deploy
140
-
141
- # 스키마 동기화 (개발용)
142
- npx prisma db push
143
-
144
- # Prisma Client 생성
145
- npx prisma generate
146
-
147
- # Prisma Studio (GUI)
148
- npx prisma studio
48
+ .handler(async ({ data }) => prisma.user.create({ data }))
149
49
  ```
@@ -1,140 +1,50 @@
1
1
  # Prisma - 트랜잭션
2
2
 
3
- > **상위 문서**: [Prisma](./index.md)
4
-
5
3
  ## 배열 기반 트랜잭션
6
4
 
7
- 여러 쿼리를 순차적으로 실행하고, 하나라도 실패하면 모두 롤백됩니다.
8
-
9
- ```typescript
10
- // 관계 데이터 삭제
11
- const deletePosts = prisma.post.deleteMany({
12
- where: { authorId: 7 },
13
- })
14
-
15
- const deleteUser = prisma.user.delete({
16
- where: { id: 7 },
17
- })
18
-
19
- const transaction = await prisma.$transaction([deletePosts, deleteUser])
20
- ```
21
-
22
- ## GDPR 데이터 삭제 예시
23
-
24
- ```typescript
25
- const id = 9 // 삭제할 사용자
26
-
27
- const deletePosts = prisma.post.deleteMany({
28
- where: { userId: id },
29
- })
30
-
31
- const deleteMessages = prisma.privateMessage.deleteMany({
32
- where: { userId: id },
33
- })
34
-
35
- const deleteUser = prisma.user.delete({
36
- where: { id: id },
37
- })
38
-
39
- // 모든 작업이 성공하거나 모두 실패
40
- await prisma.$transaction([deletePosts, deleteMessages, deleteUser])
41
- ```
42
-
43
- ## 모든 데이터 삭제
5
+ 하나라도 실패하면 모두 롤백.
44
6
 
45
7
  ```typescript
46
- const deletePosts = prisma.post.deleteMany()
47
- const deleteProfile = prisma.profile.deleteMany()
48
- const deleteUsers = prisma.user.deleteMany()
49
-
50
- // 순서대로 실행 (deleteUsers가 마지막)
51
- await prisma.$transaction([deleteProfile, deletePosts, deleteUsers])
8
+ const deletePosts = prisma.post.deleteMany({ where: { authorId: 7 } })
9
+ const deleteUser = prisma.user.delete({ where: { id: 7 } })
10
+ await prisma.$transaction([deletePosts, deleteUser])
52
11
  ```
53
12
 
54
13
  ## 인터랙티브 트랜잭션
55
14
 
56
- 복잡한 트랜잭션 로직이 필요할 때 사용합니다.
15
+ 복잡한 로직, 조건부 처리.
57
16
 
58
17
  ```typescript
59
18
  const result = await prisma.$transaction(async (tx) => {
60
- // 1. 잔액 확인
61
- const sender = await tx.account.findUnique({
62
- where: { id: senderId },
63
- })
64
-
65
- if (!sender || sender.balance < amount) {
66
- throw new Error('Insufficient balance')
67
- }
68
-
69
- // 2. 보내는 계좌에서 차감
70
- const updatedSender = await tx.account.update({
71
- where: { id: senderId },
72
- data: { balance: { decrement: amount } },
73
- })
19
+ const sender = await tx.account.findUnique({ where: { id: senderId } })
20
+ if (!sender || sender.balance < amount) throw new Error('Insufficient balance')
74
21
 
75
- // 3. 받는 계좌에 입금
76
- const updatedRecipient = await tx.account.update({
77
- where: { id: recipientId },
78
- data: { balance: { increment: amount } },
79
- })
22
+ await tx.account.update({ where: { id: senderId }, data: { balance: { decrement: amount } } })
23
+ await tx.account.update({ where: { id: recipientId }, data: { balance: { increment: amount } } })
80
24
 
81
- return { sender: updatedSender, recipient: updatedRecipient }
25
+ return { success: true }
82
26
  })
83
27
  ```
84
28
 
85
- ## 트랜잭션 옵션
29
+ ## 옵션
86
30
 
87
31
  ```typescript
88
- await prisma.$transaction(
89
- async (tx) => {
90
- // 트랜잭션 로직
91
- },
92
- {
93
- maxWait: 5000, // 최대 대기 시간 (ms)
94
- timeout: 10000, // 트랜잭션 타임아웃 (ms)
95
- isolationLevel: 'Serializable', // 격리 수준
96
- }
97
- )
98
- ```
99
-
100
- ## 격리 수준
101
-
102
- ```typescript
103
- // 가능한 격리 수준
104
- type IsolationLevel =
105
- | 'ReadUncommitted'
106
- | 'ReadCommitted'
107
- | 'RepeatableRead'
108
- | 'Serializable'
109
- ```
110
-
111
- ## 타입 안전 Raw Query
112
-
113
- ```typescript
114
- import { selectUserTitles, updateUserName } from '@prisma/client/sql'
115
-
116
- const [userList, updateUser] = await prisma.$transaction([
117
- prisma.$queryRawTyped(selectUserTitles()),
118
- prisma.$queryRawTyped(updateUserName(2)),
119
- ])
32
+ await prisma.$transaction(async (tx) => { ... }, {
33
+ maxWait: 5000, // 최대 대기 (ms)
34
+ timeout: 10000, // 타임아웃 (ms)
35
+ isolationLevel: 'Serializable', // ReadUncommitted | ReadCommitted | RepeatableRead | Serializable
36
+ })
120
37
  ```
121
38
 
122
- ## 트랜잭션 내 에러 처리
39
+ ## 에러 처리
123
40
 
124
41
  ```typescript
125
42
  try {
126
43
  await prisma.$transaction(async (tx) => {
127
- await tx.user.create({ data: { email: 'alice@prisma.io' } })
128
-
129
- // 의도적 에러 발생 시 전체 롤백
130
- if (someCondition) {
131
- throw new Error('Rollback transaction')
132
- }
133
-
134
- await tx.post.create({ data: { title: 'Hello', authorId: 1 } })
44
+ await tx.user.create({ data: { email } })
45
+ if (someCondition) throw new Error('Rollback')
135
46
  })
136
47
  } catch (error) {
137
- console.error('Transaction failed:', error)
138
- // 트랜잭션 내 모든 변경사항이 롤백됨
48
+ // 전체 롤백됨
139
49
  }
140
50
  ```
@@ -1,28 +1,29 @@
1
1
  # TanStack Query
2
2
 
3
- > **Version**: 5.x | React Data Fetching Library
3
+ > 5.x | React Data Fetching Library
4
+
5
+ @use-query.md
6
+ @use-mutation.md
7
+ @invalidation.md
8
+ @optimistic-updates.md
4
9
 
5
10
  ---
6
11
 
7
- ## 🚀 Quick Reference (복사용)
12
+ ## Quick Reference
8
13
 
9
14
  ```typescript
10
- // useQuery - 데이터 조회
15
+ // useQuery
11
16
  const { data, isLoading, error } = useQuery({
12
17
  queryKey: ['users'],
13
18
  queryFn: () => getUsers(),
14
19
  })
15
20
 
16
- // useMutation - 데이터 변경
21
+ // useMutation + invalidation
17
22
  const queryClient = useQueryClient()
18
23
  const mutation = useMutation({
19
24
  mutationFn: createUser,
20
- onSuccess: () => {
21
- queryClient.invalidateQueries({ queryKey: ['users'] })
22
- },
25
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
23
26
  })
24
-
25
- // mutation 실행
26
27
  mutation.mutate({ email, name })
27
28
 
28
29
  // Optimistic Update
@@ -40,47 +41,20 @@ const mutation = useMutation({
40
41
  })
41
42
  ```
42
43
 
43
- ### QueryClient 설정
44
+ ### 설정
44
45
 
45
46
  ```tsx
46
47
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
47
48
 
48
- const queryClient = new QueryClient()
49
-
50
- function App() {
51
- return (
52
- <QueryClientProvider client={queryClient}>
53
- <YourApp />
54
- </QueryClientProvider>
55
- )
56
- }
57
- ```
58
-
59
- ---
60
-
61
- ## 문서 구조
62
-
63
- - [설치 및 설정](./setup.md) - QueryClient 설정
64
- - [useQuery](./use-query.md) - 데이터 조회 훅
65
- - [useMutation](./use-mutation.md) - 데이터 변경 훅
66
- - [무효화](./invalidation.md) - Query 무효화 및 리페치
67
- - [Optimistic Updates](./optimistic-updates.md) - 낙관적 업데이트
68
-
69
- ## 빠른 시작
70
-
71
- ```bash
72
- yarn add @tanstack/react-query
73
- ```
74
-
75
- ### QueryClient 설정
76
-
77
- ```tsx
78
- import {
79
- QueryClient,
80
- QueryClientProvider,
81
- } from '@tanstack/react-query'
82
-
83
- const queryClient = new QueryClient()
49
+ const queryClient = new QueryClient({
50
+ defaultOptions: {
51
+ queries: {
52
+ staleTime: 1000 * 60 * 5, // 5분
53
+ gcTime: 1000 * 60 * 30, // 30분 (이전 cacheTime)
54
+ retry: 3,
55
+ },
56
+ },
57
+ })
84
58
 
85
59
  function App() {
86
60
  return (
@@ -91,56 +65,11 @@ function App() {
91
65
  }
92
66
  ```
93
67
 
94
- ## 핵심 개념
95
-
96
- ### useQuery - 데이터 조회
97
-
98
- ```tsx
99
- import { useQuery } from '@tanstack/react-query'
100
-
101
- function Todos() {
102
- const { data, isLoading, error } = useQuery({
103
- queryKey: ['todos'],
104
- queryFn: getTodos,
105
- })
106
-
107
- if (isLoading) return <div>Loading...</div>
108
- if (error) return <div>Error: {error.message}</div>
109
-
110
- return (
111
- <ul>
112
- {data?.map((todo) => (
113
- <li key={todo.id}>{todo.title}</li>
114
- ))}
115
- </ul>
116
- )
117
- }
118
- ```
119
-
120
- ### useMutation - 데이터 변경
121
-
122
- ```tsx
123
- import { useMutation, useQueryClient } from '@tanstack/react-query'
124
-
125
- function AddTodo() {
126
- const queryClient = useQueryClient()
127
-
128
- const mutation = useMutation({
129
- mutationFn: postTodo,
130
- onSuccess: () => {
131
- queryClient.invalidateQueries({ queryKey: ['todos'] })
132
- },
133
- })
68
+ ### Query Keys 패턴
134
69
 
135
- return (
136
- <button onClick={() => mutation.mutate({ title: 'New Todo' })}>
137
- Add Todo
138
- </button>
139
- )
140
- }
70
+ ```typescript
71
+ ['todos'] // 단순
72
+ ['todo', { id: 5 }] // 파라미터
73
+ ['todos', 'list', { filters }] // 계층적
74
+ ['todos', 'detail', todoId]
141
75
  ```
142
-
143
- ## 참고 자료
144
-
145
- - [TanStack Query 공식 문서](https://tanstack.com/query/latest)
146
- - [TanStack Query GitHub](https://github.com/tanstack/query)
@@ -1,146 +1,67 @@
1
1
  # TanStack Query - Query 무효화
2
2
 
3
- > **상위 문서**: [TanStack Query](./index.md)
4
-
5
3
  ## 기본 무효화
6
4
 
7
5
  ```typescript
8
6
  const queryClient = useQueryClient()
9
7
 
10
- // 단일 쿼리 무효화
11
- await queryClient.invalidateQueries({ queryKey: ['todos'] })
8
+ // 단일
9
+ queryClient.invalidateQueries({ queryKey: ['todos'] })
12
10
 
13
- // 다중 쿼리 무효화
11
+ // 다중
14
12
  await Promise.all([
15
13
  queryClient.invalidateQueries({ queryKey: ['todos'] }),
16
14
  queryClient.invalidateQueries({ queryKey: ['reminders'] }),
17
15
  ])
18
16
 
19
- // 모든 쿼리 무효화
17
+ // 전체
20
18
  queryClient.invalidateQueries()
21
19
  ```
22
20
 
23
- ## 무효화 옵션
21
+ ## 옵션
24
22
 
25
23
  ```typescript
26
- await queryClient.invalidateQueries(
27
- {
28
- queryKey: ['posts'],
29
- exact: true, // 정확한 매칭만
30
- refetchType: 'active', // 'active' | 'inactive' | 'all' | 'none'
31
- },
32
- {
33
- throwOnError: false,
34
- cancelRefetch: true,
35
- }
36
- )
24
+ queryClient.invalidateQueries({
25
+ queryKey: ['posts'],
26
+ exact: true, // 정확한 키 매칭만
27
+ refetchType: 'active', // 'active'(기본) | 'inactive' | 'all' | 'none'
28
+ })
37
29
  ```
38
30
 
39
- ## refetchType 옵션
31
+ | refetchType | 설명 |
32
+ |-------------|------|
33
+ | active | 렌더링 중인 쿼리만 재조회 (기본) |
34
+ | inactive | 비활성 쿼리만 |
35
+ | all | 모든 매칭 쿼리 |
36
+ | none | 무효화만, 재조회 안함 |
40
37
 
41
- - `active`: 현재 렌더링 중인 쿼리만 재조회 (기본값)
42
- - `inactive`: 비활성 쿼리만 재조회
43
- - `all`: 모든 매칭 쿼리 재조회
44
- - `none`: 무효화만 하고 재조회 안 함
45
-
46
- ## Query Key로 무효화
38
+ ## Query Key 매칭
47
39
 
48
40
  ```typescript
49
- // 'todos'로 시작하는 모든 쿼리 무효화
41
+ // prefix 매칭 (todos로 시작하는 모든 쿼리)
50
42
  queryClient.invalidateQueries({ queryKey: ['todos'] })
51
43
 
52
- // 정확히 ['todos', 'list']인 쿼리만 무효화
53
- queryClient.invalidateQueries({
54
- queryKey: ['todos', 'list'],
55
- exact: true,
56
- })
57
-
58
- // ['todos', { type: 'done' }] 무효화
59
- queryClient.invalidateQueries({
60
- queryKey: ['todos', { type: 'done' }],
61
- })
44
+ // 정확한 매칭
45
+ queryClient.invalidateQueries({ queryKey: ['todos', 'list'], exact: true })
62
46
  ```
63
47
 
64
- ## Mutation과 함께 사용
65
-
66
- ### onSuccess에서 무효화
48
+ ## Mutation과 함께
67
49
 
68
50
  ```tsx
69
- import { useMutation, useQueryClient } from '@tanstack/react-query'
70
-
71
- function TodosComponent() {
72
- const queryClient = useQueryClient()
73
-
74
- const mutation = useMutation({
75
- mutationFn: addTodo,
76
- onSuccess: async () => {
77
- // 단일 쿼리 무효화
78
- await queryClient.invalidateQueries({ queryKey: ['todos'] })
79
-
80
- // 여러 쿼리 무효화
81
- await Promise.all([
82
- queryClient.invalidateQueries({ queryKey: ['todos'] }),
83
- queryClient.invalidateQueries({ queryKey: ['reminders'] }),
84
- ])
85
- },
86
- })
87
-
88
- return (
89
- <button onClick={() => mutation.mutate(newTodo)}>
90
- Add Todo
91
- </button>
92
- )
93
- }
94
- ```
95
-
96
- ### onSettled에서 무효화
97
-
98
- ```tsx
99
- const mutation = useMutation({
100
- mutationFn: updateTodo,
101
- onSettled: () => {
102
- // 성공/실패 관계없이 무효화
103
- queryClient.invalidateQueries({ queryKey: ['todos'] })
104
- },
51
+ useMutation({
52
+ mutationFn: addTodo,
53
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
54
+ // 또는 onSettled (성공/실패 무관)
55
+ onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
105
56
  })
106
57
  ```
107
58
 
108
59
  ## 캐시 직접 업데이트 vs 무효화
109
60
 
110
61
  ```tsx
111
- // 방법 1: 캐시 직접 업데이트 (더 빠름)
62
+ // 직접 업데이트 (더 빠름)
112
63
  queryClient.setQueryData(['todos'], (old) => [...old, newTodo])
113
64
 
114
- // 방법 2: 무효화 후 재조회 (서버 데이터 보장)
115
- queryClient.invalidateQueries({ queryKey: ['todos'] })
116
- ```
117
-
118
- ## 조건부 무효화
119
-
120
- ```tsx
121
- const mutation = useMutation({
122
- mutationFn: updateTodo,
123
- onSuccess: (data, variables) => {
124
- // 특정 조건에서만 무효화
125
- if (variables.category === 'important') {
126
- queryClient.invalidateQueries({ queryKey: ['todos', 'important'] })
127
- }
128
-
129
- // 항상 개별 항목은 무효화
130
- queryClient.invalidateQueries({ queryKey: ['todo', variables.id] })
131
- },
132
- })
133
- ```
134
-
135
- ## prefetch와 조합
136
-
137
- ```tsx
138
- // 무효화 전에 새 데이터 프리페치
139
- await queryClient.prefetchQuery({
140
- queryKey: ['todos'],
141
- queryFn: fetchTodos,
142
- })
143
-
144
- // 이후 무효화 시 이미 새 데이터가 있음
65
+ // 무효화 (서버 데이터 보장)
145
66
  queryClient.invalidateQueries({ queryKey: ['todos'] })
146
67
  ```