@kood/claude-code 0.1.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 (78) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +297 -0
  3. package/package.json +47 -0
  4. package/templates/hono/CLAUDE.md +376 -0
  5. package/templates/hono/docs/deployment/cloudflare.md +328 -0
  6. package/templates/hono/docs/deployment/index.md +291 -0
  7. package/templates/hono/docs/git/index.md +180 -0
  8. package/templates/hono/docs/library/hono/error-handling.md +400 -0
  9. package/templates/hono/docs/library/hono/index.md +241 -0
  10. package/templates/hono/docs/library/hono/middleware.md +334 -0
  11. package/templates/hono/docs/library/hono/rpc.md +454 -0
  12. package/templates/hono/docs/library/hono/validation.md +328 -0
  13. package/templates/hono/docs/library/prisma/index.md +427 -0
  14. package/templates/hono/docs/library/zod/index.md +413 -0
  15. package/templates/hono/docs/mcp/context7.md +106 -0
  16. package/templates/hono/docs/mcp/index.md +94 -0
  17. package/templates/hono/docs/mcp/sequential-thinking.md +101 -0
  18. package/templates/hono/docs/mcp/sgrep.md +105 -0
  19. package/templates/hono/docs/skills/gemini-review/SKILL.md +220 -0
  20. package/templates/hono/docs/skills/gemini-review/references/checklists.md +136 -0
  21. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +303 -0
  22. package/templates/tanstack-start/CLAUDE.md +279 -0
  23. package/templates/tanstack-start/docs/architecture/architecture.md +547 -0
  24. package/templates/tanstack-start/docs/deployment/cloudflare.md +346 -0
  25. package/templates/tanstack-start/docs/deployment/index.md +102 -0
  26. package/templates/tanstack-start/docs/deployment/nitro.md +211 -0
  27. package/templates/tanstack-start/docs/deployment/railway.md +364 -0
  28. package/templates/tanstack-start/docs/deployment/vercel.md +287 -0
  29. package/templates/tanstack-start/docs/design/accessibility.md +433 -0
  30. package/templates/tanstack-start/docs/design/color.md +235 -0
  31. package/templates/tanstack-start/docs/design/components.md +409 -0
  32. package/templates/tanstack-start/docs/design/index.md +107 -0
  33. package/templates/tanstack-start/docs/design/safe-area.md +317 -0
  34. package/templates/tanstack-start/docs/design/spacing.md +341 -0
  35. package/templates/tanstack-start/docs/design/tailwind-setup.md +470 -0
  36. package/templates/tanstack-start/docs/design/typography.md +324 -0
  37. package/templates/tanstack-start/docs/git/index.md +203 -0
  38. package/templates/tanstack-start/docs/guides/best-practices.md +753 -0
  39. package/templates/tanstack-start/docs/guides/getting-started.md +304 -0
  40. package/templates/tanstack-start/docs/guides/husky-lint-staged.md +303 -0
  41. package/templates/tanstack-start/docs/guides/prettier.md +189 -0
  42. package/templates/tanstack-start/docs/guides/project-templates.md +710 -0
  43. package/templates/tanstack-start/docs/library/better-auth/2fa.md +136 -0
  44. package/templates/tanstack-start/docs/library/better-auth/advanced.md +138 -0
  45. package/templates/tanstack-start/docs/library/better-auth/index.md +83 -0
  46. package/templates/tanstack-start/docs/library/better-auth/plugins.md +111 -0
  47. package/templates/tanstack-start/docs/library/better-auth/session.md +127 -0
  48. package/templates/tanstack-start/docs/library/better-auth/setup.md +123 -0
  49. package/templates/tanstack-start/docs/library/prisma/crud.md +218 -0
  50. package/templates/tanstack-start/docs/library/prisma/index.md +165 -0
  51. package/templates/tanstack-start/docs/library/prisma/relations.md +191 -0
  52. package/templates/tanstack-start/docs/library/prisma/schema.md +177 -0
  53. package/templates/tanstack-start/docs/library/prisma/setup.md +156 -0
  54. package/templates/tanstack-start/docs/library/prisma/transactions.md +140 -0
  55. package/templates/tanstack-start/docs/library/tanstack-query/index.md +146 -0
  56. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +146 -0
  57. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +196 -0
  58. package/templates/tanstack-start/docs/library/tanstack-query/setup.md +110 -0
  59. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +170 -0
  60. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +173 -0
  61. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +171 -0
  62. package/templates/tanstack-start/docs/library/tanstack-start/index.md +114 -0
  63. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +142 -0
  64. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +163 -0
  65. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +128 -0
  66. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +85 -0
  67. package/templates/tanstack-start/docs/library/zod/basic-types.md +186 -0
  68. package/templates/tanstack-start/docs/library/zod/complex-types.md +204 -0
  69. package/templates/tanstack-start/docs/library/zod/index.md +186 -0
  70. package/templates/tanstack-start/docs/library/zod/transforms.md +174 -0
  71. package/templates/tanstack-start/docs/library/zod/validation.md +208 -0
  72. package/templates/tanstack-start/docs/mcp/context7.md +204 -0
  73. package/templates/tanstack-start/docs/mcp/index.md +116 -0
  74. package/templates/tanstack-start/docs/mcp/sequential-thinking.md +180 -0
  75. package/templates/tanstack-start/docs/mcp/sgrep.md +174 -0
  76. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +220 -0
  77. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +150 -0
  78. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +293 -0
@@ -0,0 +1,177 @@
1
+ # Prisma - 스키마 정의
2
+
3
+ > **상위 문서**: [Prisma](./index.md)
4
+
5
+ ## 기본 스키마
6
+
7
+ ```prisma
8
+ // prisma/schema.prisma
9
+ datasource db {
10
+ provider = "postgresql"
11
+ url = env("DATABASE_URL")
12
+ }
13
+
14
+ generator client {
15
+ provider = "prisma-client"
16
+ output = "../generated/prisma"
17
+ }
18
+
19
+ model User {
20
+ id Int @id @default(autoincrement())
21
+ email String @unique
22
+ name String?
23
+ role Role @default(USER)
24
+ posts Post[]
25
+ profile ExtendedProfile?
26
+ createdAt DateTime @default(now())
27
+ updatedAt DateTime @updatedAt
28
+ }
29
+
30
+ model Post {
31
+ 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[]
38
+ createdAt DateTime @default(now())
39
+ updatedAt DateTime @updatedAt
40
+ }
41
+
42
+ model Category {
43
+ id Int @id @default(autoincrement())
44
+ name String @unique
45
+ posts Post[]
46
+ }
47
+
48
+ model ExtendedProfile {
49
+ 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
58
+ }
59
+ ```
60
+
61
+ ## 선택적 관계
62
+
63
+ ```prisma
64
+ model Post {
65
+ id Int @id @default(autoincrement())
66
+ author User? @relation(fields: [authorId], references: [id])
67
+ authorId Int?
68
+ }
69
+ ```
70
+
71
+ ## 커스텀 필드/모델명 매핑
72
+
73
+ ```prisma
74
+ model User {
75
+ id Int @id @default(autoincrement()) @map("user_id")
76
+ email String @unique
77
+
78
+ @@map("users")
79
+ }
80
+ ```
81
+
82
+ ## 관계 유형
83
+
84
+ ### 1:1 관계
85
+
86
+ ```prisma
87
+ model User {
88
+ id Int @id @default(autoincrement())
89
+ profile Profile?
90
+ }
91
+
92
+ model Profile {
93
+ id Int @id @default(autoincrement())
94
+ user User @relation(fields: [userId], references: [id])
95
+ userId Int @unique
96
+ }
97
+ ```
98
+
99
+ ### 1:N 관계
100
+
101
+ ```prisma
102
+ model User {
103
+ id Int @id @default(autoincrement())
104
+ posts Post[]
105
+ }
106
+
107
+ model Post {
108
+ id Int @id @default(autoincrement())
109
+ author User @relation(fields: [authorId], references: [id])
110
+ authorId Int
111
+ }
112
+ ```
113
+
114
+ ### M:N 관계 (암묵적)
115
+
116
+ ```prisma
117
+ model Post {
118
+ id Int @id @default(autoincrement())
119
+ categories Category[]
120
+ }
121
+
122
+ model Category {
123
+ id Int @id @default(autoincrement())
124
+ posts Post[]
125
+ }
126
+ ```
127
+
128
+ ### M:N 관계 (명시적)
129
+
130
+ ```prisma
131
+ model Post {
132
+ id Int @id @default(autoincrement())
133
+ categories CategoriesOnPosts[]
134
+ }
135
+
136
+ model Category {
137
+ id Int @id @default(autoincrement())
138
+ posts CategoriesOnPosts[]
139
+ }
140
+
141
+ model CategoriesOnPosts {
142
+ post Post @relation(fields: [postId], references: [id])
143
+ postId Int
144
+ category Category @relation(fields: [categoryId], references: [id])
145
+ categoryId Int
146
+ assignedAt DateTime @default(now())
147
+
148
+ @@id([postId, categoryId])
149
+ }
150
+ ```
151
+
152
+ ## 인덱스
153
+
154
+ ```prisma
155
+ model Post {
156
+ id Int @id @default(autoincrement())
157
+ title String
158
+ content String?
159
+ authorId Int
160
+ createdAt DateTime @default(now())
161
+
162
+ @@index([authorId])
163
+ @@index([createdAt])
164
+ @@index([title, authorId])
165
+ }
166
+ ```
167
+
168
+ ## 복합 키
169
+
170
+ ```prisma
171
+ model PostTag {
172
+ postId Int
173
+ tagId Int
174
+
175
+ @@id([postId, tagId])
176
+ }
177
+ ```
@@ -0,0 +1,156 @@
1
+ # Prisma - 설치 및 설정
2
+
3
+ > **상위 문서**: [Prisma](./index.md)
4
+
5
+ ## 설치
6
+
7
+ ```bash
8
+ # npm
9
+ npm install @prisma/client@7
10
+ npm install -D prisma@7
11
+
12
+ # yarn
13
+ yarn add @prisma/client@7
14
+ yarn add -D prisma@7
15
+
16
+ # pnpm
17
+ pnpm add @prisma/client@7
18
+ pnpm add -D prisma@7
19
+
20
+ # bun
21
+ bun add @prisma/client@7
22
+ bun add prisma@7 --dev
23
+
24
+ # 초기화
25
+ npx prisma init
26
+ ```
27
+
28
+ ## v6에서 v7 업그레이드
29
+
30
+ ```bash
31
+ # npm
32
+ npm install @prisma/client@7
33
+ npm install -D prisma@7
34
+
35
+ # yarn
36
+ yarn up prisma@7 @prisma/client@7
37
+
38
+ # pnpm
39
+ pnpm upgrade prisma@7 @prisma/client@7
40
+ ```
41
+
42
+ ### Generator 변경 (필수)
43
+
44
+ ```prisma
45
+ // schema.prisma - 이전 (v6)
46
+ generator client {
47
+ provider = "prisma-client-js"
48
+ }
49
+
50
+ // schema.prisma - v7
51
+ generator client {
52
+ provider = "prisma-client" // 새로운 provider
53
+ output = "../generated/prisma" // output 필수
54
+ }
55
+ ```
56
+
57
+ ## Prisma Client 설정
58
+
59
+ ### 기본 설정
60
+
61
+ ```typescript
62
+ // lib/prisma.ts
63
+ import { PrismaClient } from './generated/prisma' // output 경로에서 import
64
+
65
+ const globalForPrisma = globalThis as unknown as {
66
+ prisma: PrismaClient | undefined
67
+ }
68
+
69
+ export const prisma =
70
+ globalForPrisma.prisma ??
71
+ new PrismaClient({
72
+ log: ['query'],
73
+ })
74
+
75
+ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
76
+ ```
77
+
78
+ ### 로깅 설정
79
+
80
+ ```typescript
81
+ import { PrismaClient } from './generated/prisma'
82
+
83
+ const prisma = new PrismaClient({
84
+ log: [{ level: 'query', emit: 'event' }],
85
+ })
86
+
87
+ prisma.$on('query', (e) => {
88
+ console.log('Query:', e.query)
89
+ console.log('Params:', e.params)
90
+ console.log('Duration:', e.duration, 'ms')
91
+ })
92
+ ```
93
+
94
+ ### QueryEvent 타입
95
+
96
+ ```typescript
97
+ type QueryEvent = {
98
+ timestamp: Date
99
+ query: string
100
+ params: string
101
+ duration: number
102
+ target: string
103
+ }
104
+ ```
105
+
106
+ ## TanStack Start 통합
107
+
108
+ ```typescript
109
+ // lib/prisma.ts
110
+ import { PrismaClient } from './generated/prisma'
111
+
112
+ const globalForPrisma = globalThis as unknown as {
113
+ prisma: PrismaClient | undefined
114
+ }
115
+
116
+ export const prisma =
117
+ globalForPrisma.prisma ?? new PrismaClient()
118
+
119
+ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
120
+
121
+ // Server Function에서 사용
122
+ import { createServerFn } from '@tanstack/react-start'
123
+ import { prisma } from '~/lib/prisma'
124
+
125
+ export const getUsers = createServerFn({ method: 'GET' })
126
+ .handler(async () => {
127
+ return prisma.user.findMany({
128
+ include: { posts: true },
129
+ })
130
+ })
131
+
132
+ export const createUser = createServerFn({ method: 'POST' })
133
+ .inputValidator((data: { email: string; name: string }) => data)
134
+ .handler(async ({ data }) => {
135
+ return prisma.user.create({ data })
136
+ })
137
+ ```
138
+
139
+ ## 마이그레이션
140
+
141
+ ```bash
142
+ # 개발 환경 마이그레이션
143
+ npx prisma migrate dev --name init
144
+
145
+ # 프로덕션 마이그레이션
146
+ npx prisma migrate deploy
147
+
148
+ # 스키마 동기화 (개발용)
149
+ npx prisma db push
150
+
151
+ # Prisma Client 생성
152
+ npx prisma generate
153
+
154
+ # Prisma Studio (GUI)
155
+ npx prisma studio
156
+ ```
@@ -0,0 +1,140 @@
1
+ # Prisma - 트랜잭션
2
+
3
+ > **상위 문서**: [Prisma](./index.md)
4
+
5
+ ## 배열 기반 트랜잭션
6
+
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
+ ## 모든 데이터 삭제
44
+
45
+ ```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])
52
+ ```
53
+
54
+ ## 인터랙티브 트랜잭션
55
+
56
+ 더 복잡한 트랜잭션 로직이 필요할 때 사용합니다.
57
+
58
+ ```typescript
59
+ 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
+ })
74
+
75
+ // 3. 받는 계좌에 입금
76
+ const updatedRecipient = await tx.account.update({
77
+ where: { id: recipientId },
78
+ data: { balance: { increment: amount } },
79
+ })
80
+
81
+ return { sender: updatedSender, recipient: updatedRecipient }
82
+ })
83
+ ```
84
+
85
+ ## 트랜잭션 옵션
86
+
87
+ ```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
+ ])
120
+ ```
121
+
122
+ ## 트랜잭션 내 에러 처리
123
+
124
+ ```typescript
125
+ try {
126
+ 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 } })
135
+ })
136
+ } catch (error) {
137
+ console.error('Transaction failed:', error)
138
+ // 트랜잭션 내 모든 변경사항이 롤백됨
139
+ }
140
+ ```
@@ -0,0 +1,146 @@
1
+ # TanStack Query
2
+
3
+ > **Version**: 5.x | React Data Fetching Library
4
+
5
+ ---
6
+
7
+ ## 🚀 Quick Reference (복사용)
8
+
9
+ ```typescript
10
+ // useQuery - 데이터 조회
11
+ const { data, isLoading, error } = useQuery({
12
+ queryKey: ['users'],
13
+ queryFn: () => getUsers(),
14
+ })
15
+
16
+ // useMutation - 데이터 변경
17
+ const queryClient = useQueryClient()
18
+ const mutation = useMutation({
19
+ mutationFn: createUser,
20
+ onSuccess: () => {
21
+ queryClient.invalidateQueries({ queryKey: ['users'] })
22
+ },
23
+ })
24
+
25
+ // mutation 실행
26
+ mutation.mutate({ email, name })
27
+
28
+ // Optimistic Update
29
+ const mutation = useMutation({
30
+ mutationFn: updateUser,
31
+ onMutate: async (newUser) => {
32
+ await queryClient.cancelQueries({ queryKey: ['users'] })
33
+ const previous = queryClient.getQueryData(['users'])
34
+ queryClient.setQueryData(['users'], (old) => [...old, newUser])
35
+ return { previous }
36
+ },
37
+ onError: (err, newUser, context) => {
38
+ queryClient.setQueryData(['users'], context.previous)
39
+ },
40
+ })
41
+ ```
42
+
43
+ ### QueryClient 설정
44
+
45
+ ```tsx
46
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
47
+
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()
84
+
85
+ function App() {
86
+ return (
87
+ <QueryClientProvider client={queryClient}>
88
+ <YourApp />
89
+ </QueryClientProvider>
90
+ )
91
+ }
92
+ ```
93
+
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
+ })
134
+
135
+ return (
136
+ <button onClick={() => mutation.mutate({ title: 'New Todo' })}>
137
+ Add Todo
138
+ </button>
139
+ )
140
+ }
141
+ ```
142
+
143
+ ## 참고 자료
144
+
145
+ - [TanStack Query 공식 문서](https://tanstack.com/query/latest)
146
+ - [TanStack Query GitHub](https://github.com/tanstack/query)