@kood/claude-code 0.6.6 → 0.7.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 (170) hide show
  1. package/dist/index.js +7 -1
  2. package/package.json +1 -1
  3. package/templates/.claude/agents/analyst.md +5 -0
  4. package/templates/.claude/agents/architect.md +5 -0
  5. package/templates/.claude/agents/build-fixer.md +1 -0
  6. package/templates/.claude/agents/code-reviewer.md +1 -0
  7. package/templates/.claude/agents/critic.md +4 -0
  8. package/templates/.claude/agents/deep-executor.md +1 -0
  9. package/templates/.claude/agents/dependency-manager.md +2 -0
  10. package/templates/.claude/agents/deployment-validator.md +2 -0
  11. package/templates/.claude/agents/designer.md +2 -0
  12. package/templates/.claude/agents/document-writer.md +3 -0
  13. package/templates/.claude/agents/explore.md +1 -0
  14. package/templates/.claude/agents/git-operator.md +2 -0
  15. package/templates/.claude/agents/implementation-executor.md +2 -0
  16. package/templates/.claude/agents/ko-to-en-translator.md +3 -0
  17. package/templates/.claude/agents/lint-fixer.md +2 -0
  18. package/templates/.claude/agents/planner.md +3 -0
  19. package/templates/.claude/agents/pm.md +349 -0
  20. package/templates/.claude/agents/qa-tester.md +1 -0
  21. package/templates/.claude/agents/refactor-advisor.md +4 -0
  22. package/templates/.claude/agents/researcher.md +9 -1
  23. package/templates/.claude/agents/scientist.md +1 -0
  24. package/templates/.claude/agents/security-reviewer.md +1 -0
  25. package/templates/.claude/agents/tdd-guide.md +1 -0
  26. package/templates/.claude/agents/vision.md +1 -0
  27. package/templates/.claude/instructions/agent-patterns/agent-teams-usage.md +376 -0
  28. package/templates/.claude/instructions/sourcing/reliable-search.md +49 -2
  29. package/templates/.claude/scripts/agent-teams/check-availability.sh +238 -0
  30. package/templates/.claude/scripts/agent-teams/setup-tmux.sh +125 -0
  31. package/templates/.claude/skills/agent-teams-setup/SKILL.md +460 -0
  32. package/templates/.claude/skills/brainstorm/SKILL.md +1 -0
  33. package/templates/.claude/skills/bug-fix/SKILL.md +1 -0
  34. package/templates/.claude/skills/crawler/SKILL.md +2 -0
  35. package/templates/.claude/skills/docs-creator/SKILL.md +1 -0
  36. package/templates/.claude/skills/docs-fetch/SKILL.md +6 -4
  37. package/templates/.claude/skills/docs-refactor/SKILL.md +1 -0
  38. package/templates/.claude/skills/elon-musk/SKILL.md +1 -0
  39. package/templates/.claude/skills/execute/SKILL.md +1 -0
  40. package/templates/.claude/skills/feedback/SKILL.md +1 -0
  41. package/templates/.claude/skills/figma-to-code/SKILL.md +1 -0
  42. package/templates/.claude/skills/genius-thinking/SKILL.md +1 -0
  43. package/templates/.claude/skills/global-uiux-design/SKILL.md +1 -0
  44. package/templates/.claude/skills/korea-uiux-design/SKILL.md +1 -0
  45. package/templates/.claude/skills/nextjs-react-best-practices/SKILL.md +1 -0
  46. package/templates/.claude/skills/plan/SKILL.md +1 -0
  47. package/templates/.claude/skills/prd/SKILL.md +1 -0
  48. package/templates/.claude/skills/project-optimizer/AGENTS.md +275 -0
  49. package/templates/.claude/skills/project-optimizer/SKILL.md +375 -0
  50. package/templates/.claude/skills/project-optimizer/rules/arch-config-centralize.md +66 -0
  51. package/templates/.claude/skills/project-optimizer/rules/arch-hot-path.md +35 -0
  52. package/templates/.claude/skills/project-optimizer/rules/arch-interface-segregation.md +51 -0
  53. package/templates/.claude/skills/project-optimizer/rules/arch-module-boundary.md +42 -0
  54. package/templates/.claude/skills/project-optimizer/rules/build-cache.md +57 -0
  55. package/templates/.claude/skills/project-optimizer/rules/build-code-split.md +56 -0
  56. package/templates/.claude/skills/project-optimizer/rules/build-incremental.md +65 -0
  57. package/templates/.claude/skills/project-optimizer/rules/build-minify.md +61 -0
  58. package/templates/.claude/skills/project-optimizer/rules/build-tree-shake.md +60 -0
  59. package/templates/.claude/skills/project-optimizer/rules/code-complexity.md +65 -0
  60. package/templates/.claude/skills/project-optimizer/rules/code-dead-elimination.md +32 -0
  61. package/templates/.claude/skills/project-optimizer/rules/code-duplication.md +54 -0
  62. package/templates/.claude/skills/project-optimizer/rules/code-error-handling.md +75 -0
  63. package/templates/.claude/skills/project-optimizer/rules/code-naming.md +52 -0
  64. package/templates/.claude/skills/project-optimizer/rules/concurrency-defer-await.md +54 -0
  65. package/templates/.claude/skills/project-optimizer/rules/concurrency-parallel.md +90 -0
  66. package/templates/.claude/skills/project-optimizer/rules/concurrency-pipeline.md +68 -0
  67. package/templates/.claude/skills/project-optimizer/rules/concurrency-pool.md +68 -0
  68. package/templates/.claude/skills/project-optimizer/rules/deps-lightweight-alt.md +37 -0
  69. package/templates/.claude/skills/project-optimizer/rules/deps-peer-align.md +44 -0
  70. package/templates/.claude/skills/project-optimizer/rules/deps-security-audit.md +45 -0
  71. package/templates/.claude/skills/project-optimizer/rules/deps-unused-removal.md +25 -0
  72. package/templates/.claude/skills/project-optimizer/rules/deps-version-pin.md +40 -0
  73. package/templates/.claude/skills/project-optimizer/rules/dx-ci-speed.md +47 -0
  74. package/templates/.claude/skills/project-optimizer/rules/dx-dev-server.md +35 -0
  75. package/templates/.claude/skills/project-optimizer/rules/dx-lint-config.md +36 -0
  76. package/templates/.claude/skills/project-optimizer/rules/dx-test-coverage.md +34 -0
  77. package/templates/.claude/skills/project-optimizer/rules/dx-type-safety.md +49 -0
  78. package/templates/.claude/skills/project-optimizer/rules/io-batch-queries.md +67 -0
  79. package/templates/.claude/skills/project-optimizer/rules/io-cache-layer.md +67 -0
  80. package/templates/.claude/skills/project-optimizer/rules/io-connection-reuse.md +67 -0
  81. package/templates/.claude/skills/project-optimizer/rules/io-serialize-minimal.md +61 -0
  82. package/templates/.claude/skills/project-optimizer/rules/io-stream.md +75 -0
  83. package/templates/.claude/skills/project-optimizer/rules/memory-bounded-cache.md +65 -0
  84. package/templates/.claude/skills/project-optimizer/rules/memory-large-data.md +64 -0
  85. package/templates/.claude/skills/project-optimizer/rules/memory-lazy-init.md +78 -0
  86. package/templates/.claude/skills/project-optimizer/rules/memory-leak-prevention.md +79 -0
  87. package/templates/.claude/skills/project-optimizer/rules/memory-pool-reuse.md +70 -0
  88. package/templates/.claude/skills/ralph/SKILL.md +1 -0
  89. package/templates/.claude/skills/refactor/SKILL.md +1 -0
  90. package/templates/.claude/skills/research/SKILL.md +1 -0
  91. package/templates/.claude/skills/sql-optimizer/SKILL.md +438 -0
  92. package/templates/.claude/skills/sql-optimizer/orm-patterns.md +218 -0
  93. package/templates/.claude/skills/startup-validator/SKILL.md +1 -0
  94. package/templates/.claude/skills/tanstack-start-react-best-practices/AGENTS.md +53 -14
  95. package/templates/.claude/skills/tanstack-start-react-best-practices/SKILL.md +94 -27
  96. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-defer-third-party.md +42 -19
  97. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-optimistic-updates.md +109 -0
  98. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-suspense-query.md +74 -0
  99. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-use-hook.md +81 -0
  100. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-react-compiler.md +81 -0
  101. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-beforeload-auth.md +121 -0
  102. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-file-conventions.md +104 -0
  103. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-link-navigation.md +119 -0
  104. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-nested-layouts.md +155 -0
  105. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-path-params.md +89 -0
  106. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-pending-component.md +110 -0
  107. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-preload-strategy.md +91 -0
  108. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-router-context.md +120 -0
  109. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-search-params.md +114 -0
  110. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-deferred-data.md +1 -1
  111. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-error-boundaries.md +79 -0
  112. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-middleware.md +85 -0
  113. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-serialization.md +56 -21
  114. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-streaming.md +84 -0
  115. package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-validator.md +71 -0
  116. package/templates/.claude/skills/tauri-react-best-practices/AGENTS.md +527 -0
  117. package/templates/.claude/skills/tauri-react-best-practices/SKILL.md +571 -0
  118. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-barrel-imports.md +140 -0
  119. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-cargo-profile.md +96 -0
  120. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-frontend-treeshake.md +242 -0
  121. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-lazy-components.md +255 -0
  122. package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-remove-unused-commands.md +160 -0
  123. package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-ci-pipeline.md +269 -0
  124. package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-signing.md +207 -0
  125. package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-updater.md +226 -0
  126. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-async-commands.md +172 -0
  127. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-batch-commands.md +133 -0
  128. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-binary-response.md +198 -0
  129. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-channel-streaming.md +186 -0
  130. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-error-handling.md +250 -0
  131. package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-type-safe.md +227 -0
  132. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-derived-state.md +231 -0
  133. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-functional-setstate.md +191 -0
  134. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-index-maps.md +276 -0
  135. package/templates/.claude/skills/tauri-react-best-practices/rules/perf-lazy-state-init.md +196 -0
  136. package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-lifecycle.md +265 -0
  137. package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-mobile-compat.md +199 -0
  138. package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-permission-scope.md +193 -0
  139. package/templates/.claude/skills/tauri-react-best-practices/rules/react-error-boundary.md +239 -0
  140. package/templates/.claude/skills/tauri-react-best-practices/rules/react-event-listener.md +151 -0
  141. package/templates/.claude/skills/tauri-react-best-practices/rules/react-file-src.md +155 -0
  142. package/templates/.claude/skills/tauri-react-best-practices/rules/react-invoke-hook.md +139 -0
  143. package/templates/.claude/skills/tauri-react-best-practices/rules/react-optimistic-update.md +211 -0
  144. package/templates/.claude/skills/tauri-react-best-practices/rules/security-capability-split.md +205 -0
  145. package/templates/.claude/skills/tauri-react-best-practices/rules/security-csp.md +207 -0
  146. package/templates/.claude/skills/tauri-react-best-practices/rules/security-least-privilege.md +106 -0
  147. package/templates/.claude/skills/tauri-react-best-practices/rules/security-no-wildcard.md +253 -0
  148. package/templates/.claude/skills/tauri-react-best-practices/rules/security-scope-paths.md +160 -0
  149. package/templates/.claude/skills/tauri-react-best-practices/rules/state-async-mutex.md +270 -0
  150. package/templates/.claude/skills/tauri-react-best-practices/rules/state-mutex-pattern.md +265 -0
  151. package/templates/.claude/skills/tauri-react-best-practices/rules/state-react-sync.md +375 -0
  152. package/templates/.claude/skills/tauri-react-best-practices/rules/state-single-container.md +275 -0
  153. package/templates/tanstack-start/docs/architecture.md +238 -167
  154. package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +777 -38
  155. package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +549 -37
  156. package/templates/tanstack-start/docs/library/tanstack-router/index.md +895 -111
  157. package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +641 -43
  158. package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +889 -38
  159. package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +891 -29
  160. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +972 -36
  161. package/templates/tanstack-start/docs/library/tanstack-start/index.md +1525 -881
  162. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +1099 -20
  163. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +796 -30
  164. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +953 -35
  165. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +371 -15
  166. package/templates/tauri/CLAUDE.md +189 -0
  167. package/templates/tauri/docs/guides/distribution.md +261 -0
  168. package/templates/tauri/docs/guides/getting-started.md +302 -0
  169. package/templates/tauri/docs/guides/mobile.md +288 -0
  170. package/templates/tauri/docs/library/tauri/index.md +510 -0
@@ -1,53 +1,565 @@
1
1
  # TanStack Router - Hooks
2
2
 
3
- <patterns>
3
+ > TanStack Router v1.159.4
4
+
5
+ 모든 라우터 훅 참조. Route-scoped (타입 안전)과 Global (수동 타입).
6
+
7
+ ---
8
+
9
+ <route_scoped>
10
+
11
+ ## Route-Scoped Hooks: 타입 안전 (권장)
12
+
13
+ 현재 라우트 내에서만 사용. 타입 자동 추론.
14
+
15
+ ### Route.useLoaderData()
16
+
17
+ Loader에서 반환한 데이터 접근. 타입 안전.
18
+
19
+ ```tsx
20
+ export const Route = createFileRoute('/posts/$postId')({
21
+ loader: async ({ params }) => ({
22
+ post: await getPost(params.postId),
23
+ relatedPosts: await getRelated(params.postId),
24
+ }),
25
+ component: PostDetail,
26
+ })
27
+
28
+ const PostDetail = () => {
29
+ // ✅ 타입 안전: post, relatedPosts 타입 자동 추론
30
+ const { post, relatedPosts } = Route.useLoaderData()
31
+
32
+ return (
33
+ <div>
34
+ <h1>{post.title}</h1>
35
+ <div>{relatedPosts.map(p => <span key={p.id}>{p.title}</span>)}</div>
36
+ </div>
37
+ )
38
+ }
39
+ ```
40
+
41
+ ### Route.useParams()
42
+
43
+ Path params 접근. 타입 안전.
44
+
45
+ ```tsx
46
+ export const Route = createFileRoute('/users/$userId/posts/$postId')({
47
+ component: UserPost,
48
+ })
49
+
50
+ const UserPost = () => {
51
+ // ✅ 타입 안전: userId, postId 타입 추론됨
52
+ const { userId, postId } = Route.useParams()
53
+
54
+ return <div>User {userId}, Post {postId}</div>
55
+ }
56
+ ```
57
+
58
+ ### Route.useSearch()
59
+
60
+ Search params 접근. ValidateSearch 스키마 타입 추론.
61
+
62
+ ```tsx
63
+ export const Route = createFileRoute('/products')({
64
+ validateSearch: z.object({
65
+ page: z.number().catch(1),
66
+ sort: z.enum(['newest', 'price']).catch('newest'),
67
+ }),
68
+ component: Products,
69
+ })
70
+
71
+ const Products = () => {
72
+ // ✅ 타입 안전: page, sort 타입 추론됨
73
+ const { page, sort } = Route.useSearch()
74
+
75
+ return <div>Page {page}, Sort {sort}</div>
76
+ }
77
+ ```
78
+
79
+ ### Route.useRouteContext()
80
+
81
+ 현재 라우트나 부모 라우트의 context 접근.
82
+
83
+ ```tsx
84
+ // 부모 라우트 (_authed.tsx)
85
+ export const Route = createFileRoute('/_authed')({
86
+ beforeLoad: async () => ({
87
+ user: await getCurrentUser(),
88
+ permissions: await getPermissions(),
89
+ }),
90
+ component: () => <Outlet />,
91
+ })
92
+
93
+ // 자식 라우트 (_authed/dashboard.tsx)
94
+ export const Route = createFileRoute('/_authed/dashboard')({
95
+ component: Dashboard,
96
+ })
97
+
98
+ const Dashboard = () => {
99
+ // ✅ 부모의 context 접근
100
+ const { user, permissions } = Route.useRouteContext()
101
+
102
+ return <h1>Welcome, {user.name}!</h1>
103
+ }
104
+ ```
105
+
106
+ </route_scoped>
107
+
108
+ ---
109
+
110
+ <global_hooks>
111
+
112
+ ## Global Hooks: 수동 타입 지정
113
+
114
+ 어디서든 사용 가능. `from` 파라미터로 타입 체크 가능.
115
+
116
+ ### useNavigate()
117
+
118
+ 네비게이션 함수. 자동 타입 지정 (from 선택 사항).
119
+
120
+ ```tsx
121
+ // 일반적 사용 (타입 체크 안 함)
122
+ const Component = () => {
123
+ const navigate = useNavigate()
124
+ navigate({ to: '/posts/$postId', params: { postId: '123' } })
125
+ }
126
+
127
+ // 타입 안전 (특정 라우트 내에서만 호출)
128
+ export const Route = createFileRoute('/posts/$postId')({
129
+ component: PostDetail,
130
+ })
131
+
132
+ const PostDetail = () => {
133
+ const navigate = useNavigate({ from: '/posts/$postId' })
134
+ navigate({ to: '/posts/$postId', params: { postId: '456' } })
135
+ }
136
+ ```
137
+
138
+ ### useMatch()
139
+
140
+ 특정 라우트 매칭 확인. 조건부 렌더링에 활용.
141
+
142
+ ```tsx
143
+ const Component = () => {
144
+ // postRoute가 현재 경로와 일치하는지 확인
145
+ const postMatch = useMatch({ from: '/posts/$postId', shouldThrow: false })
146
+
147
+ if (postMatch) {
148
+ return <span>Viewing post: {postMatch.params.postId}</span>
149
+ }
150
+
151
+ return <span>Not in posts route</span>
152
+ }
153
+
154
+ // shouldThrow=true: 매칭 안 되면 에러 throw (기본값)
155
+ const StrictComponent = () => {
156
+ const match = useMatch({ from: '/dashboard', shouldThrow: true })
157
+ // /dashboard가 아니면 에러 발생
158
+ }
159
+ ```
160
+
161
+ ### useParams()
162
+
163
+ Path params 접근 (Global). from으로 타입 지정 가능.
164
+
165
+ ```tsx
166
+ // 타입 지정 없음 (any)
167
+ const Component = () => {
168
+ const params = useParams({ strict: false }) // 현재 라우트 params 모두
169
+ return <div>{JSON.stringify(params)}</div>
170
+ }
171
+
172
+ // 특정 라우트 params (타입 지정)
173
+ const RelatedComponent = () => {
174
+ const { postId } = useParams({ from: '/posts/$postId' })
175
+ return <div>Post: {postId}</div>
176
+ }
177
+
178
+ // strict=true: 라우트 파라미터만 포함
179
+ const StrictParams = () => {
180
+ const params = useParams({ from: '/posts/$postId', strict: true })
181
+ // postId만 포함
182
+ }
183
+ ```
184
+
185
+ ### useSearch()
186
+
187
+ Search params 접근 (Global). from으로 타입 지정 가능.
188
+
189
+ ```tsx
190
+ // 현재 라우트 search params
191
+ const Component = () => {
192
+ const search = useSearch({ strict: false })
193
+ return <div>{JSON.stringify(search)}</div>
194
+ }
195
+
196
+ // 특정 라우트 search params (타입 지정)
197
+ const FilteredComponent = () => {
198
+ const { page, sort } = useSearch({ from: '/products' })
199
+ return <div>Page {page}, Sort {sort}</div>
200
+ }
201
+
202
+ // strict=true: validateSearch 스키마 타입만 포함
203
+ const StrictSearch = () => {
204
+ const search = useSearch({ from: '/products', strict: true })
205
+ }
206
+ ```
207
+
208
+ ### useRouterState()
209
+
210
+ 라우터 전역 상태 접근. Select로 필요한 값만 추출.
211
+
212
+ ```tsx
213
+ const Component = () => {
214
+ // 현재 pathname
215
+ const pathname = useRouterState({ select: state => state.location.pathname })
216
+
217
+ // 로딩 상태
218
+ const isLoading = useRouterState({ select: state => state.isLoading })
219
+
220
+ // 매치된 라우트 정보
221
+ const matchedRoutes = useRouterState({ select: state => state.matches })
222
+
223
+ // 전체 라우터 상태
224
+ const status = useRouterState({ select: state => state.status })
225
+
226
+ return (
227
+ <div>
228
+ <p>Path: {pathname}</p>
229
+ <p>{isLoading ? 'Loading...' : 'Ready'}</p>
230
+ </div>
231
+ )
232
+ }
233
+ ```
234
+
235
+ ### useLocation()
236
+
237
+ 현재 위치 정보. pathname, search, hash, state.
4
238
 
5
239
  ```tsx
6
- // Route-Scoped (Type-safe)
7
- const PostPage = () => {
8
- const { post } = Route.useLoaderData() // Loader 반환값
9
- const { postId } = Route.useParams() // Path params
10
- const { page, sort } = Route.useSearch() // Search params
11
- const { user } = Route.useRouteContext() // Route context
12
- return <h1>{post.title}</h1>
240
+ const Component = () => {
241
+ const location = useLocation()
242
+
243
+ return (
244
+ <div>
245
+ <p>Pathname: {location.pathname}</p>
246
+ <p>Search: {JSON.stringify(location.search)}</p>
247
+ <p>Hash: {location.hash}</p>
248
+ <p>State: {JSON.stringify(location.state)}</p>
249
+ </div>
250
+ )
251
+ }
252
+ ```
253
+
254
+ ### useRouter()
255
+
256
+ 라우터 인스턴스 접근. invalidate, navigate, 캐시 관리 등.
257
+
258
+ ```tsx
259
+ const Component = () => {
260
+ const router = useRouter()
261
+
262
+ // loader 재실행 + 캐시 무효화
263
+ const handleRefresh = () => router.invalidate()
264
+
265
+ // 라우터 인스턴스로 네비게이션
266
+ const goTo = () => router.navigate({ to: '/posts' })
267
+
268
+ return <button onClick={handleRefresh}>Refresh</button>
269
+ }
270
+ ```
271
+
272
+ ### useMatchRoute()
273
+
274
+ 라우트 매칭 확인 함수 반환. pending 상태 체크에 유용.
275
+
276
+ ```tsx
277
+ const Component = () => {
278
+ const matchRoute = useMatchRoute()
279
+
280
+ // 프로그래매틱 매칭 체크
281
+ const isUsersRoute = matchRoute({ to: '/users' })
282
+ const isUsersPending = matchRoute({ to: '/users', pending: true })
283
+
284
+ return (
285
+ <div>
286
+ {isUsersPending && <Spinner />}
287
+ </div>
288
+ )
289
+ }
290
+ ```
291
+
292
+ ### Route.useNavigate()
293
+
294
+ 현재 라우트에서 from이 자동 설정된 네비게이션. useNavigate({ from })의 축약형.
295
+
296
+ ```tsx
297
+ export const Route = createFileRoute('/posts/$postId')({
298
+ component: PostDetail,
299
+ })
300
+
301
+ const PostDetail = () => {
302
+ // from: '/posts/$postId'가 자동 설정됨
303
+ const navigate = Route.useNavigate()
304
+
305
+ const goToRelated = (id: string) => {
306
+ navigate({
307
+ to: '/posts/$postId',
308
+ params: { postId: id }, // 타입 체크됨
309
+ })
310
+ }
311
+
312
+ return <button onClick={() => goToRelated('456')}>Related</button>
313
+ }
314
+ ```
315
+
316
+ </global_hooks>
317
+
318
+ ---
319
+
320
+ <get_route_api>
321
+
322
+ ## getRouteApi(): 파일 분리 시 타입 안전
323
+
324
+ Route-scoped 훅을 파일 분리해서 사용할 때 타입 유지.
325
+
326
+ ### 문제상황
327
+
328
+ ```tsx
329
+ // /src/routes/posts/index.tsx에서
330
+ export const Route = createFileRoute('/posts')({
331
+ validateSearch: postsSearchSchema,
332
+ component: ProductsPage,
333
+ })
334
+
335
+ // /src/routes/posts/-components/filter.tsx에서
336
+ const Filter = () => {
337
+ // 여기서 Route.useSearch()를 쓸 수 없음 (Route가 정의되지 않음)
338
+ // 수동으로 타입 지정해야 함
339
+ }
340
+ ```
341
+
342
+ ### 해결: getRouteApi()
343
+
344
+ ```tsx
345
+ // /src/routes/posts/-search-schema.ts
346
+ import { z } from 'zod'
347
+
348
+ export const postsSearchSchema = z.object({
349
+ page: z.number().catch(1),
350
+ sort: z.enum(['newest', 'price']).catch('newest'),
351
+ })
352
+
353
+ // /src/routes/posts/index.tsx
354
+ export const Route = createFileRoute('/posts')({
355
+ validateSearch: postsSearchSchema,
356
+ component: ProductsPage,
357
+ })
358
+
359
+ // /src/routes/posts/-components/filter.tsx
360
+ import { getRouteApi } from '@tanstack/react-router'
361
+ import { postsSearchSchema } from '../-search-schema'
362
+
363
+ const postsRoute = getRouteApi('/posts')
364
+
365
+ const Filter = () => {
366
+ // ✅ 타입 안전: postsSearchSchema 타입 자동 적용
367
+ const { page, sort } = postsRoute.useSearch()
368
+ const navigate = useNavigate()
369
+
370
+ return (
371
+ <select
372
+ value={sort}
373
+ onChange={e =>
374
+ navigate({
375
+ to: '/posts',
376
+ search: prev => ({ ...prev, sort: e.target.value as any }),
377
+ })
378
+ }
379
+ >
380
+ <option value="newest">Newest</option>
381
+ <option value="price">Price</option>
382
+ </select>
383
+ )
384
+ }
385
+
386
+ export default Filter
387
+ ```
388
+
389
+ ### 복잡한 예시
390
+
391
+ ```tsx
392
+ // /src/lib/route-apis.ts
393
+ import { getRouteApi } from '@tanstack/react-router'
394
+
395
+ // 모든 getRouteApi 한 파일에 정의
396
+ export const rootRoute = getRouteApi('/__root')
397
+ export const postsRoute = getRouteApi('/posts')
398
+ export const postDetailRoute = getRouteApi('/posts/$postId')
399
+ export const dashboardRoute = getRouteApi('/_authed/dashboard')
400
+
401
+ // /src/routes/posts/-components/filter.tsx
402
+ import { postsRoute } from '@/lib/route-apis'
403
+
404
+ const Filter = () => {
405
+ const search = postsRoute.useSearch()
406
+ const loaderData = postsRoute.useLoaderData()
407
+
408
+ return <div>{/* ... */}</div>
13
409
  }
410
+ ```
411
+
412
+ </get_route_api>
413
+
414
+ ---
415
+
416
+ <complete_reference>
417
+
418
+ ## 완전 참조표
419
+
420
+ | Hook | Scope | 타입 | 반환값 | 용도 |
421
+ |------|-------|------|--------|------|
422
+ | `Route.useLoaderData()` | Route | Auto | Loader 반환값 | 데이터 로드 결과 |
423
+ | `Route.useParams()` | Route | Auto | Path params | URL 파라미터 접근 |
424
+ | `Route.useSearch()` | Route | Auto | Search params | Query string 접근 |
425
+ | `Route.useRouteContext()` | Route | Auto | Route context | 라우트 context 공유 |
426
+ | `useNavigate()` | Global | Manual | function | 네비게이션 함수 |
427
+ | `useMatch({ from })` | Global | Manual | match object \| null | 라우트 매칭 확인 |
428
+ | `useParams({ from })` | Global | Manual | object | 특정 라우트 params |
429
+ | `useSearch({ from })` | Global | Manual | object | 특정 라우트 search |
430
+ | `useRouterState({ select })` | Global | Manual | state value | 라우터 전역 상태 |
431
+ | `useLocation()` | Global | Auto | location object | 현재 위치 정보 |
432
+ | `useRouter()` | Global | Auto | router instance | 라우터 인스턴스 접근 |
433
+ | `useMatchRoute()` | Global | Manual | function | 라우트 매칭 확인 함수 |
434
+ | `Route.useNavigate()` | Route | Auto | function | from 자동 설정된 네비게이션 |
435
+ | `getRouteApi(path)` | Any | Manual | route API object | 파일 분리 시 타입 지정 |
14
436
 
15
- // Global (Manual type)
16
- const navigate = useNavigate()
17
- navigate({ to: '/posts/$postId', params: { postId: '123' } })
437
+ </complete_reference>
18
438
 
19
- const postMatch = useMatch({ from: '/posts/$postId', shouldThrow: false })
20
- if (postMatch) return <span>Post: {postMatch.params.postId}</span>
439
+ ---
21
440
 
22
- const { postId } = useParams({ from: '/posts/$postId' })
23
- const params = useParams({ strict: false }) // 모든 params
441
+ <examples>
24
442
 
25
- const { page } = useSearch({ from: '/products' })
26
- const search = useSearch({ strict: false }) // 현재 search
443
+ ## 실전 예시
27
444
 
28
- const pathname = useRouterState({ select: state => state.location.pathname })
29
- const isLoading = useRouterState({ select: state => state.isLoading })
445
+ ### Route-Scoped: 상세 페이지
30
446
 
31
- const location = useLocation()
32
- console.log(location.pathname) // '/posts/123'
33
- console.log(location.search) // { page: 1 }
447
+ ```tsx
448
+ // /src/routes/posts/$postId.tsx
449
+ import { createFileRoute } from '@tanstack/react-router'
450
+
451
+ export const Route = createFileRoute('/posts/$postId')({
452
+ loader: async ({ params }) => ({
453
+ post: await getPost(params.postId),
454
+ relatedPosts: await getRelated(params.postId),
455
+ }),
456
+ component: PostDetail,
457
+ })
458
+
459
+ const PostDetail = () => {
460
+ // ✅ 모두 타입 안전
461
+ const { post, relatedPosts } = Route.useLoaderData()
462
+ const { postId } = Route.useParams()
463
+
464
+ return (
465
+ <div>
466
+ <h1>{post.title}</h1>
467
+ <p>{post.content}</p>
468
+ <h2>Related Posts</h2>
469
+ {relatedPosts.map(p => (
470
+ <Link key={p.id} to={`/posts/${p.id}`}>
471
+ {p.title}
472
+ </Link>
473
+ ))}
474
+ </div>
475
+ )
476
+ }
34
477
  ```
35
478
 
36
- </patterns>
479
+ ### Global: 탭 네비게이션
480
+
481
+ ```tsx
482
+ const TabNavigation = () => {
483
+ const location = useLocation()
484
+ const navigate = useNavigate()
485
+
486
+ const tabs = [
487
+ { label: 'Home', to: '/' },
488
+ { label: 'Posts', to: '/posts' },
489
+ { label: 'Dashboard', to: '/dashboard' },
490
+ ]
491
+
492
+ return (
493
+ <nav>
494
+ {tabs.map(tab => (
495
+ <button
496
+ key={tab.to}
497
+ onClick={() => navigate({ to: tab.to })}
498
+ className={location.pathname === tab.to ? 'active' : ''}
499
+ >
500
+ {tab.label}
501
+ </button>
502
+ ))}
503
+ </nav>
504
+ )
505
+ }
506
+ ```
507
+
508
+ ### 조건부 렌더링: useMatch
509
+
510
+ ```tsx
511
+ const Header = () => {
512
+ // /posts/$postId 라우트 확인
513
+ const postMatch = useMatch({ from: '/posts/$postId', shouldThrow: false })
514
+
515
+ return (
516
+ <header>
517
+ <h1>My Site</h1>
518
+ {postMatch && <p>Viewing post {postMatch.params.postId}</p>}
519
+ </header>
520
+ )
521
+ }
522
+ ```
523
+
524
+ ### 파일 분리: getRouteApi
525
+
526
+ ```tsx
527
+ // /src/lib/route-apis.ts
528
+ import { getRouteApi } from '@tanstack/react-router'
529
+
530
+ export const dashboardRoute = getRouteApi('/_authed/dashboard')
531
+
532
+ // /src/routes/_authed/dashboard/-components/stats.tsx
533
+ import { dashboardRoute } from '@/lib/route-apis'
534
+
535
+ const Stats = () => {
536
+ // ✅ 파일 분리되어도 타입 안전
537
+ const { stats } = dashboardRoute.useLoaderData()
538
+ const { userId } = dashboardRoute.useParams()
539
+
540
+ return <div>{/* ... */}</div>
541
+ }
542
+ ```
543
+
544
+ </examples>
545
+
546
+ ---
547
+
548
+ <dos_donts>
37
549
 
38
- <reference>
550
+ ## Do's & Don'ts
39
551
 
40
- | Hook | Scope | Type | 용도 |
41
- |------|-------|------|------|
42
- | `Route.useLoaderData()` | Route | Auto | Loader 데이터 |
43
- | `Route.useParams()` | Route | Auto | Path params |
44
- | `Route.useSearch()` | Route | Auto | Search params |
45
- | `Route.useRouteContext()` | Route | Auto | Route context |
46
- | `useParams({ from })` | Global | Manual | 다른 라우트 params |
47
- | `useSearch({ from })` | Global | Manual | 다른 라우트 search |
48
- | `useMatch({ from })` | Global | Manual | 라우트 매치 정보 |
49
- | `useNavigate()` | Global | Auto | 네비게이션 |
50
- | `useRouterState()` | Global | Manual | 라우터 상태 |
51
- | `useLocation()` | Global | Auto | 현재 location |
552
+ | Do | Don't |
553
+ |-------|---------|
554
+ | `Route.useLoaderData()` | `useLoaderData()`로 수동 타입 |
555
+ | `Route.useParams()` | `useParams()`로 수동 타입 |
556
+ | `Route.useSearch()` | `useSearch()`로 수동 타입 |
557
+ | `getRouteApi(path).useSearch()` | 파일 분리 type annotation |
558
+ | `from` 파라미터 사용 | `any` 타입 사용 |
559
+ | `select` 함수로 필요한 값만 | `useRouterState()` 전체 구독 |
560
+ | `useMatch({ shouldThrow: false })` | 에러 있게 shouldThrow 생략 |
561
+ | `getRouteApi()` 파일 분리 | Route import로 순환 참조 발생 |
562
+ | `Route.useNavigate()` 사용 | `useNavigate()` + from 수동 지정 |
563
+ | `useRouter()` + `invalidate()` | 수동 상태 동기화 |
52
564
 
53
- </reference>
565
+ </dos_donts>