@kood/claude-code 0.5.3 → 0.5.5
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.
- package/dist/index.js +552 -340
- package/package.json +1 -1
- package/templates/.claude/agents/document-writer.md +73 -306
- package/templates/.claude/instructions/agent-patterns/index.md +7 -7
- package/templates/.claude/instructions/document-templates/ralph-templates.md +71 -0
- package/templates/.claude/instructions/index.md +14 -14
- package/templates/.claude/instructions/multi-agent/agent-roster.md +14 -14
- package/templates/.claude/instructions/multi-agent/index.md +4 -4
- package/templates/.claude/skills/docs-creator/AGENTS.md +54 -176
- package/templates/.claude/skills/docs-creator/SKILL.md +98 -464
- package/templates/.claude/skills/docs-refactor/AGENTS.md +61 -190
- package/templates/.claude/skills/docs-refactor/SKILL.md +67 -443
- package/templates/.claude/skills/execute/SKILL.md +540 -13
- package/templates/.claude/skills/plan/SKILL.md +84 -18
- package/templates/.claude/skills/ralph/SKILL.md +17 -14
- package/templates/.claude/skills/refactor/AGENTS.md +269 -0
- package/templates/.claude/skills/refactor/SKILL.md +424 -66
- package/templates/.claude/skills/stitch-design/README.md +34 -0
- package/templates/.claude/skills/stitch-design/SKILL.md +213 -0
- package/templates/.claude/skills/stitch-design/examples/DESIGN.md +154 -0
- package/templates/.claude/skills/stitch-loop/README.md +54 -0
- package/templates/.claude/skills/stitch-loop/SKILL.md +316 -0
- package/templates/.claude/skills/stitch-loop/examples/SITE.md +73 -0
- package/templates/.claude/skills/stitch-loop/examples/next-prompt.md +25 -0
- package/templates/.claude/skills/stitch-loop/resources/baton-schema.md +61 -0
- package/templates/.claude/skills/stitch-loop/resources/site-template.md +104 -0
- package/templates/.claude/skills/stitch-react/README.md +36 -0
- package/templates/.claude/skills/stitch-react/SKILL.md +323 -0
- package/templates/.claude/skills/stitch-react/examples/gold-standard-card.tsx +88 -0
- package/templates/.claude/skills/stitch-react/package-lock.json +231 -0
- package/templates/.claude/skills/stitch-react/package.json +16 -0
- package/templates/.claude/skills/stitch-react/resources/architecture-checklist.md +15 -0
- package/templates/.claude/skills/stitch-react/resources/component-template.tsx +37 -0
- package/templates/.claude/skills/stitch-react/resources/stitch-api-reference.md +14 -0
- package/templates/.claude/skills/stitch-react/resources/style-guide.json +24 -0
- package/templates/.claude/skills/stitch-react/scripts/fetch-stitch.sh +30 -0
- package/templates/.claude/skills/stitch-react/scripts/validate.js +77 -0
- package/templates/hono/CLAUDE.md +28 -28
- package/templates/hono/docs/architecture.md +24 -24
- package/templates/hono/docs/deployment/cloudflare.md +18 -18
- package/templates/hono/docs/deployment/docker.md +13 -13
- package/templates/hono/docs/deployment/index.md +19 -19
- package/templates/hono/docs/deployment/railway.md +32 -32
- package/templates/hono/docs/deployment/vercel.md +29 -29
- package/templates/hono/docs/guides/conventions.md +57 -57
- package/templates/hono/docs/guides/env-setup.md +47 -47
- package/templates/hono/docs/guides/getting-started.md +27 -27
- package/templates/hono/docs/library/hono/error-handling.md +11 -11
- package/templates/hono/docs/library/hono/index.md +4 -4
- package/templates/hono/docs/library/hono/middleware.md +18 -18
- package/templates/hono/docs/library/hono/rpc.md +7 -7
- package/templates/hono/docs/library/hono/validation.md +6 -6
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +29 -29
- package/templates/hono/docs/library/prisma/config.md +16 -16
- package/templates/hono/docs/library/prisma/index.md +32 -32
- package/templates/hono/docs/library/t3-env/index.md +22 -22
- package/templates/hono/docs/library/zod/index.md +31 -31
- package/templates/nextjs/CLAUDE.md +54 -54
- package/templates/nextjs/docs/architecture.md +146 -146
- package/templates/nextjs/docs/design.md +183 -183
- package/templates/nextjs/docs/guides/conventions.md +86 -86
- package/templates/nextjs/docs/guides/getting-started.md +28 -28
- package/templates/nextjs/docs/guides/routes.md +32 -32
- package/templates/nextjs/docs/library/better-auth/index.md +70 -70
- package/templates/nextjs/docs/library/nextjs/app-router.md +43 -43
- package/templates/nextjs/docs/library/nextjs/caching.md +73 -73
- package/templates/nextjs/docs/library/nextjs/index.md +51 -51
- package/templates/nextjs/docs/library/nextjs/middleware.md +41 -41
- package/templates/nextjs/docs/library/nextjs/route-handlers.md +31 -31
- package/templates/nextjs/docs/library/nextjs/server-actions.md +34 -34
- package/templates/nextjs/docs/library/prisma/cloudflare-d1.md +20 -20
- package/templates/nextjs/docs/library/prisma/config.md +18 -18
- package/templates/nextjs/docs/library/prisma/crud.md +17 -17
- package/templates/nextjs/docs/library/prisma/index.md +18 -18
- package/templates/nextjs/docs/library/prisma/relations.md +16 -16
- package/templates/nextjs/docs/library/prisma/schema.md +23 -23
- package/templates/nextjs/docs/library/prisma/setup.md +6 -6
- package/templates/nextjs/docs/library/prisma/transactions.md +10 -10
- package/templates/nextjs/docs/library/tanstack-query/index.md +6 -6
- package/templates/nextjs/docs/library/tanstack-query/invalidation.md +20 -20
- package/templates/nextjs/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/nextjs/docs/library/tanstack-query/use-mutation.md +15 -15
- package/templates/nextjs/docs/library/tanstack-query/use-query.md +22 -22
- package/templates/nextjs/docs/library/zod/complex-types.md +11 -11
- package/templates/nextjs/docs/library/zod/index.md +8 -8
- package/templates/nextjs/docs/library/zod/transforms.md +11 -11
- package/templates/nextjs/docs/library/zod/validation.md +9 -9
- package/templates/npx/CLAUDE.md +38 -38
- package/templates/npx/docs/library/commander/index.md +12 -12
- package/templates/npx/docs/library/fs-extra/index.md +9 -9
- package/templates/npx/docs/library/prompts/index.md +3 -3
- package/templates/npx/docs/references/patterns.md +12 -12
- package/templates/tanstack-start/CLAUDE.md +54 -54
- package/templates/tanstack-start/docs/architecture.md +128 -128
- package/templates/tanstack-start/docs/design.md +169 -169
- package/templates/tanstack-start/docs/guides/conventions.md +43 -43
- package/templates/tanstack-start/docs/guides/env-setup.md +35 -35
- package/templates/tanstack-start/docs/guides/getting-started.md +19 -19
- package/templates/tanstack-start/docs/guides/hooks.md +45 -45
- package/templates/tanstack-start/docs/guides/routes.md +54 -54
- package/templates/tanstack-start/docs/guides/services.md +45 -45
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +19 -19
- package/templates/tanstack-start/docs/library/prisma/config.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/crud.md +17 -17
- package/templates/tanstack-start/docs/library/prisma/relations.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/schema.md +23 -23
- package/templates/tanstack-start/docs/library/prisma/setup.md +6 -6
- package/templates/tanstack-start/docs/library/prisma/transactions.md +10 -10
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +19 -19
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +14 -14
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +21 -21
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +11 -11
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +17 -17
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +5 -5
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +10 -10
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +8 -8
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +6 -6
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +18 -18
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +4 -4
- package/templates/tanstack-start/docs/library/zod/complex-types.md +11 -11
- package/templates/tanstack-start/docs/library/zod/transforms.md +11 -11
- package/templates/tanstack-start/docs/library/zod/validation.md +9 -9
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 코드 컨벤션
|
|
2
2
|
|
|
3
|
-
> TanStack Start
|
|
3
|
+
> TanStack Start 프로젝트 코드 작성 규칙
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<naming>
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 파일 네이밍
|
|
10
10
|
|
|
11
|
-
> ⚠️ **
|
|
11
|
+
> ⚠️ **camelCase 파일명 금지** - 모든 파일명은 **kebab-case** 사용
|
|
12
12
|
|
|
13
|
-
|
|
|
13
|
+
| 타입 | 규칙 | 예시 |
|
|
14
14
|
|------|------|------|
|
|
15
|
-
|
|
|
16
|
-
| **Route
|
|
17
|
-
| **Hook
|
|
18
|
-
| **Component** | PascalCase
|
|
15
|
+
| **일반 파일** | kebab-case | `user-profile.tsx`, `auth-service.ts` |
|
|
16
|
+
| **Route 파일** | TanStack Router 규칙 | `__root.tsx`, `index.tsx`, `$id.tsx` |
|
|
17
|
+
| **Hook 파일** | `use-` 접두사 + kebab-case | `use-user-filter.ts`, `use-auth.ts` |
|
|
18
|
+
| **Component** | PascalCase 컴포넌트, kebab-case 파일 | `UserCard` in `user-card.tsx` |
|
|
19
19
|
| **Server Function** | kebab-case | `get-users.ts`, `create-post.ts` |
|
|
20
20
|
|
|
21
21
|
```
|
|
22
|
-
❌
|
|
23
|
-
✅ kebab-case
|
|
22
|
+
❌ camelCase 금지: getUserById.ts, authService.ts, useUserFilter.ts
|
|
23
|
+
✅ kebab-case 필수: get-user-by-id.ts, auth-service.ts, use-user-filter.ts
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
</naming>
|
|
@@ -29,39 +29,39 @@
|
|
|
29
29
|
|
|
30
30
|
<typescript>
|
|
31
31
|
|
|
32
|
-
## TypeScript
|
|
32
|
+
## TypeScript 규칙
|
|
33
33
|
|
|
34
|
-
|
|
|
34
|
+
| 규칙 | 설명 | 예시 |
|
|
35
35
|
|------|------|------|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
| **
|
|
39
|
-
| **Import
|
|
36
|
+
| **함수 선언** | const 함수, 명시적 return type | `const fn = (): ReturnType => {}` |
|
|
37
|
+
| **타입 정의** | interface (객체), type (유니온) | `interface User {}`, `type Status = 'a' \| 'b'` |
|
|
38
|
+
| **any 금지** | unknown 사용 | `const data: unknown = JSON.parse(str)` |
|
|
39
|
+
| **Import 타입** | type import 분리 | `import type { User } from '@/types'` |
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## 패턴
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
|
-
// ✅ const
|
|
44
|
+
// ✅ const 함수, 명시적 타입
|
|
45
45
|
const getUserById = async (id: string): Promise<User> => {
|
|
46
46
|
return prisma.user.findUnique({ where: { id } })
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
// ✅
|
|
49
|
+
// ✅ 간단한 함수도 명시적 타입
|
|
50
50
|
const formatDate = (date: Date): string => {
|
|
51
51
|
return date.toISOString()
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
// ✅
|
|
54
|
+
// ✅ any 금지 → unknown 사용
|
|
55
55
|
const parseJSON = (data: string): unknown => {
|
|
56
56
|
return JSON.parse(data)
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// ❌
|
|
59
|
+
// ❌ any 사용 금지
|
|
60
60
|
const badParse = (data: string): any => { // ❌
|
|
61
61
|
return JSON.parse(data)
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// ❌
|
|
64
|
+
// ❌ function 키워드 금지
|
|
65
65
|
function badFunction() { // ❌
|
|
66
66
|
return 'use const arrow function'
|
|
67
67
|
}
|
|
@@ -73,7 +73,7 @@ function badFunction() { // ❌
|
|
|
73
73
|
|
|
74
74
|
<imports>
|
|
75
75
|
|
|
76
|
-
## Import
|
|
76
|
+
## Import 순서
|
|
77
77
|
|
|
78
78
|
```typescript
|
|
79
79
|
// 1. External libraries
|
|
@@ -101,19 +101,19 @@ import type { UseUsersReturn } from './-hooks/use-users'
|
|
|
101
101
|
|
|
102
102
|
<comments>
|
|
103
103
|
|
|
104
|
-
##
|
|
104
|
+
## 한글 주석 (묶음 단위)
|
|
105
105
|
|
|
106
106
|
```typescript
|
|
107
|
-
// ✅
|
|
107
|
+
// ✅ 코드 묶음 단위 주석
|
|
108
108
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
109
|
-
//
|
|
109
|
+
// 사용자 관련 상태
|
|
110
110
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
111
111
|
const [user, setUser] = useState<User | null>(null)
|
|
112
112
|
const [isLoading, setIsLoading] = useState(false)
|
|
113
113
|
const [error, setError] = useState<Error | null>(null)
|
|
114
114
|
|
|
115
115
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
116
|
-
//
|
|
116
|
+
// 데이터 조회
|
|
117
117
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
118
118
|
const { data: users } = useQuery({
|
|
119
119
|
queryKey: ['users'],
|
|
@@ -122,10 +122,10 @@ const { data: users } = useQuery({
|
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
```typescript
|
|
125
|
-
// ❌
|
|
126
|
-
const [user, setUser] = useState(null) //
|
|
127
|
-
const [isLoading, setIsLoading] = useState(false) //
|
|
128
|
-
const [error, setError] = useState(null) //
|
|
125
|
+
// ❌ 세세한 주석 (금지)
|
|
126
|
+
const [user, setUser] = useState(null) // 사용자 상태
|
|
127
|
+
const [isLoading, setIsLoading] = useState(false) // 로딩 상태
|
|
128
|
+
const [error, setError] = useState(null) // 에러 상태
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
</comments>
|
|
@@ -134,7 +134,7 @@ const [error, setError] = useState(null) // Error state
|
|
|
134
134
|
|
|
135
135
|
<error_handling>
|
|
136
136
|
|
|
137
|
-
##
|
|
137
|
+
## 에러 처리 패턴
|
|
138
138
|
|
|
139
139
|
```typescript
|
|
140
140
|
// lib/errors.ts
|
|
@@ -168,7 +168,7 @@ export class UnauthorizedError extends AppError {
|
|
|
168
168
|
}
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
##
|
|
171
|
+
## 사용 예시
|
|
172
172
|
|
|
173
173
|
```typescript
|
|
174
174
|
// services/user/queries.ts
|
|
@@ -188,9 +188,9 @@ export const getUserById = createServerFn({ method: 'GET' })
|
|
|
188
188
|
|
|
189
189
|
<examples>
|
|
190
190
|
|
|
191
|
-
##
|
|
191
|
+
## 파일명 예시
|
|
192
192
|
|
|
193
|
-
|
|
|
193
|
+
| 타입 | ❌ 잘못된 예시 | ✅ 올바른 예시 |
|
|
194
194
|
|------|---------------|---------------|
|
|
195
195
|
| Component | `UserProfile.tsx` | `user-profile.tsx` |
|
|
196
196
|
| Service | `authService.ts` | `auth-service.ts` |
|
|
@@ -198,14 +198,14 @@ export const getUserById = createServerFn({ method: 'GET' })
|
|
|
198
198
|
| Utility | `formatUtils.ts` | `format-utils.ts` |
|
|
199
199
|
| Type | `UserTypes.ts` | `user-types.ts` |
|
|
200
200
|
|
|
201
|
-
## Route
|
|
201
|
+
## Route 파일명
|
|
202
202
|
|
|
203
|
-
|
|
|
203
|
+
| 경로 | 파일명 | 설명 |
|
|
204
204
|
|------|--------|------|
|
|
205
|
-
| `/` | `index.tsx` |
|
|
206
|
-
| `/users` | `users/index.tsx` |
|
|
207
|
-
| `/users/:id` | `users/$id.tsx` |
|
|
208
|
-
| `/posts/:slug` | `posts/$slug.tsx` | URL
|
|
209
|
-
| Layout | `__root.tsx` | Root
|
|
205
|
+
| `/` | `index.tsx` | 인덱스 라우트 |
|
|
206
|
+
| `/users` | `users/index.tsx` | 사용자 목록 |
|
|
207
|
+
| `/users/:id` | `users/$id.tsx` | 동적 라우트 |
|
|
208
|
+
| `/posts/:slug` | `posts/$slug.tsx` | URL 파라미터 |
|
|
209
|
+
| Layout | `__root.tsx` | Root 레이아웃 |
|
|
210
210
|
|
|
211
211
|
</examples>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 환경 변수 설정
|
|
2
2
|
|
|
3
|
-
> TanStack Start (Vite
|
|
3
|
+
> TanStack Start (Vite 기반) 환경 변수 관리
|
|
4
4
|
|
|
5
5
|
<instructions>
|
|
6
6
|
@../library/t3-env/index.md
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
<environment_types>
|
|
12
12
|
|
|
13
|
-
|
|
|
14
|
-
|
|
15
|
-
| `process.env.*` | Server Function | DB, API
|
|
16
|
-
| `import.meta.env.VITE_*` |
|
|
13
|
+
| 접근 방식 | 위치 | 용도 | 노출 |
|
|
14
|
+
|-----------|------|------|------|
|
|
15
|
+
| `process.env.*` | Server Function | DB, API 키, 시크릿 | ❌ 서버만 |
|
|
16
|
+
| `import.meta.env.VITE_*` | 클라이언트 + 서버 | 공개 설정 | ✅ 브라우저 노출 |
|
|
17
17
|
|
|
18
18
|
</environment_types>
|
|
19
19
|
|
|
@@ -21,22 +21,22 @@
|
|
|
21
21
|
|
|
22
22
|
<file_structure>
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## 환경 파일 구조
|
|
25
25
|
|
|
26
26
|
```
|
|
27
|
-
├── .env #
|
|
28
|
-
├── .env.development #
|
|
29
|
-
├── .env.production #
|
|
30
|
-
├── .env.local #
|
|
31
|
-
└── src/lib/env.ts #
|
|
27
|
+
├── .env # 기본 (커밋 O)
|
|
28
|
+
├── .env.development # 개발 (커밋 O)
|
|
29
|
+
├── .env.production # 프로덕션 (커밋 O)
|
|
30
|
+
├── .env.local # 로컬 오버라이드 (커밋 X)
|
|
31
|
+
└── src/lib/env.ts # 검증 및 타입 (t3-env)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
|
|
|
35
|
-
|
|
36
|
-
| 1 | `.env.{mode}.local` |
|
|
37
|
-
| 2 | `.env.local` |
|
|
38
|
-
| 3 | `.env.{mode}` |
|
|
39
|
-
| 4 | `.env` |
|
|
34
|
+
| 우선순위 | 파일 | 설명 |
|
|
35
|
+
|----------|------|------|
|
|
36
|
+
| 1 | `.env.{mode}.local` | 최우선 (gitignore) |
|
|
37
|
+
| 2 | `.env.local` | 로컬 오버라이드 |
|
|
38
|
+
| 3 | `.env.{mode}` | 환경별 설정 |
|
|
39
|
+
| 4 | `.env` | 기본 설정 |
|
|
40
40
|
|
|
41
41
|
</file_structure>
|
|
42
42
|
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
|
|
45
45
|
<patterns>
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## 환경 파일 예시
|
|
48
48
|
|
|
49
|
-
### .env.local (gitignore,
|
|
49
|
+
### .env.local (gitignore, 시크릿)
|
|
50
50
|
|
|
51
51
|
```env
|
|
52
52
|
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
|
|
@@ -70,7 +70,7 @@ VITE_APP_NAME=My App
|
|
|
70
70
|
VITE_API_URL=https://api.myapp.com
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
##
|
|
73
|
+
## 타입 안전한 환경 변수 (t3-env)
|
|
74
74
|
|
|
75
75
|
```typescript
|
|
76
76
|
// src/lib/env.ts
|
|
@@ -106,7 +106,7 @@ export const env = createEnv({
|
|
|
106
106
|
})
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
##
|
|
109
|
+
## 사용 예시
|
|
110
110
|
|
|
111
111
|
### Server Function
|
|
112
112
|
|
|
@@ -118,13 +118,13 @@ import { prisma } from '@/database/prisma'
|
|
|
118
118
|
|
|
119
119
|
export const getUsers = createServerFn({ method: 'GET' })
|
|
120
120
|
.handler(async () => {
|
|
121
|
-
// env.DATABASE_URL
|
|
121
|
+
// env.DATABASE_URL은 서버에서만 사용 가능
|
|
122
122
|
console.log('DB URL:', env.DATABASE_URL)
|
|
123
123
|
return prisma.user.findMany()
|
|
124
124
|
})
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
###
|
|
127
|
+
### 클라이언트 컴포넌트
|
|
128
128
|
|
|
129
129
|
```tsx
|
|
130
130
|
// components/app-header.tsx
|
|
@@ -149,11 +149,11 @@ export const AppHeader = (): JSX.Element => {
|
|
|
149
149
|
## .gitignore
|
|
150
150
|
|
|
151
151
|
```gitignore
|
|
152
|
-
#
|
|
152
|
+
# 시크릿 포함 (절대 커밋 X)
|
|
153
153
|
.env.local
|
|
154
154
|
.env.*.local
|
|
155
155
|
|
|
156
|
-
#
|
|
156
|
+
# 공개 설정 (커밋 O)
|
|
157
157
|
!.env
|
|
158
158
|
!.env.development
|
|
159
159
|
!.env.production
|
|
@@ -165,7 +165,7 @@ export const AppHeader = (): JSX.Element => {
|
|
|
165
165
|
|
|
166
166
|
<typescript_types>
|
|
167
167
|
|
|
168
|
-
## TypeScript
|
|
168
|
+
## TypeScript 타입 (Vite)
|
|
169
169
|
|
|
170
170
|
```typescript
|
|
171
171
|
// src/vite-env.d.ts
|
|
@@ -181,7 +181,7 @@ interface ImportMeta {
|
|
|
181
181
|
}
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
|
|
184
|
+
**참고:** t3-env 사용 시 자동으로 타입 추론됨
|
|
185
185
|
|
|
186
186
|
</typescript_types>
|
|
187
187
|
|
|
@@ -189,13 +189,13 @@ interface ImportMeta {
|
|
|
189
189
|
|
|
190
190
|
<best_practices>
|
|
191
191
|
|
|
192
|
-
|
|
|
193
|
-
|
|
194
|
-
|
|
|
195
|
-
|
|
|
196
|
-
|
|
|
197
|
-
|
|
|
198
|
-
|
|
|
192
|
+
| 원칙 | 설명 |
|
|
193
|
+
|------|------|
|
|
194
|
+
| **시크릿 분리** | `.env.local`에만 시크릿 저장, 커밋 금지 |
|
|
195
|
+
| **공개 변수** | `VITE_` 접두사 사용, 브라우저 노출 허용 |
|
|
196
|
+
| **타입 안전성** | t3-env 또는 Zod로 검증 |
|
|
197
|
+
| **기본값** | `.env`에 안전한 기본값 설정 |
|
|
198
|
+
| **문서화** | `.env.example` 파일로 필수 변수 목록 제공 |
|
|
199
199
|
|
|
200
200
|
</best_practices>
|
|
201
201
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Getting Started
|
|
2
2
|
|
|
3
|
-
> TanStack Start
|
|
3
|
+
> TanStack Start 프로젝트 빠른 시작
|
|
4
4
|
|
|
5
5
|
<instructions>
|
|
6
6
|
@conventions.md
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
<prerequisites>
|
|
14
14
|
|
|
15
|
-
|
|
|
15
|
+
| 요구사항 | 버전 |
|
|
16
16
|
|----------|------|
|
|
17
17
|
| Node.js | 18+ |
|
|
18
|
-
|
|
|
18
|
+
| 패키지 관리자 | Yarn / npm / pnpm |
|
|
19
19
|
|
|
20
20
|
</prerequisites>
|
|
21
21
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
<installation>
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## 프로젝트 생성
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
npx create-tsrouter-app@latest my-app --template start
|
|
@@ -31,7 +31,7 @@ cd my-app
|
|
|
31
31
|
yarn install
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## 필수 패키지
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
# Database (Prisma 7.x)
|
|
@@ -51,7 +51,7 @@ yarn add @tanstack/react-query
|
|
|
51
51
|
|
|
52
52
|
<project_setup>
|
|
53
53
|
|
|
54
|
-
##
|
|
54
|
+
## 프로젝트 구조
|
|
55
55
|
|
|
56
56
|
```
|
|
57
57
|
src/
|
|
@@ -59,8 +59,8 @@ src/
|
|
|
59
59
|
│ ├── __root.tsx # Root Layout
|
|
60
60
|
│ └── index.tsx # Home Page
|
|
61
61
|
├── lib/
|
|
62
|
-
│ └── query-client.ts # Query Client
|
|
63
|
-
└── app.config.ts # TanStack Start
|
|
62
|
+
│ └── query-client.ts # Query Client 설정
|
|
63
|
+
└── app.config.ts # TanStack Start 설정
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
## app.config.ts
|
|
@@ -121,7 +121,7 @@ const HomePage = (): JSX.Element => {
|
|
|
121
121
|
}
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
## Query Client
|
|
124
|
+
## Query Client 설정
|
|
125
125
|
|
|
126
126
|
```typescript
|
|
127
127
|
// src/lib/query-client.ts
|
|
@@ -131,7 +131,7 @@ export const createQueryClient = (): QueryClient => {
|
|
|
131
131
|
return new QueryClient({
|
|
132
132
|
defaultOptions: {
|
|
133
133
|
queries: {
|
|
134
|
-
staleTime: 60 * 1000, // 1
|
|
134
|
+
staleTime: 60 * 1000, // 1분
|
|
135
135
|
retry: 1,
|
|
136
136
|
},
|
|
137
137
|
},
|
|
@@ -147,9 +147,9 @@ export const createQueryClient = (): QueryClient => {
|
|
|
147
147
|
|
|
148
148
|
| Command | Description |
|
|
149
149
|
|---------|-------------|
|
|
150
|
-
| `yarn dev` |
|
|
151
|
-
| `yarn build` |
|
|
152
|
-
| `yarn start` |
|
|
150
|
+
| `yarn dev` | 개발 서버 시작 (http://localhost:3000) |
|
|
151
|
+
| `yarn build` | 프로덕션 빌드 |
|
|
152
|
+
| `yarn start` | 프로덕션 서버 실행 |
|
|
153
153
|
|
|
154
154
|
</commands>
|
|
155
155
|
|
|
@@ -157,13 +157,13 @@ export const createQueryClient = (): QueryClient => {
|
|
|
157
157
|
|
|
158
158
|
<next_steps>
|
|
159
159
|
|
|
160
|
-
|
|
|
160
|
+
| 문서 | 내용 |
|
|
161
161
|
|------|------|
|
|
162
|
-
| [conventions.md](./conventions.md) |
|
|
163
|
-
| [env-setup.md](./env-setup.md) |
|
|
164
|
-
| [routes.md](./routes.md) |
|
|
165
|
-
| [services.md](./services.md) | Server Functions,
|
|
166
|
-
| [hooks.md](./hooks.md) | Custom Hook
|
|
162
|
+
| [conventions.md](./conventions.md) | 코드 컨벤션, 파일명 규칙 |
|
|
163
|
+
| [env-setup.md](./env-setup.md) | 환경 변수 설정 |
|
|
164
|
+
| [routes.md](./routes.md) | 라우트 구조, 파일 기반 라우팅 |
|
|
165
|
+
| [services.md](./services.md) | Server Functions, 데이터 레이어 |
|
|
166
|
+
| [hooks.md](./hooks.md) | Custom Hook 패턴 |
|
|
167
167
|
|
|
168
168
|
</next_steps>
|
|
169
169
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Custom Hook
|
|
1
|
+
# Custom Hook 패턴
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 페이지/섹션의 모든 로직, 상태, 라이프사이클 중앙화
|
|
4
4
|
|
|
5
5
|
<instructions>
|
|
6
6
|
@../library/tanstack-router/hooks.md
|
|
@@ -12,26 +12,26 @@
|
|
|
12
12
|
|
|
13
13
|
<mandatory_separation>
|
|
14
14
|
|
|
15
|
-
## ⚠️
|
|
15
|
+
## ⚠️ 필수 규칙: Custom Hook 분리
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**모든 페이지는 Custom Hook을 `-hooks/` 폴더에 분리해야 합니다.**
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
19
|
+
- 페이지 크기(줄 수)와 **무관**하게 반드시 분리
|
|
20
|
+
- 10줄짜리 간단한 페이지도 Hook 분리 필수
|
|
21
|
+
- 페이지 컴포넌트는 오직 UI 렌더링만 담당
|
|
22
22
|
|
|
23
23
|
```typescript
|
|
24
|
-
// ✅
|
|
24
|
+
// ✅ 올바른 구조
|
|
25
25
|
routes/users/
|
|
26
|
-
├── index.tsx // UI
|
|
26
|
+
├── index.tsx // UI만
|
|
27
27
|
├── -hooks/
|
|
28
|
-
│ └── use-users.ts //
|
|
28
|
+
│ └── use-users.ts // 모든 로직
|
|
29
29
|
├── -components/
|
|
30
30
|
└── -functions/
|
|
31
31
|
|
|
32
|
-
// ❌
|
|
32
|
+
// ❌ 잘못된 구조
|
|
33
33
|
routes/users/
|
|
34
|
-
└── index.tsx // UI +
|
|
34
|
+
└── index.tsx // UI + 로직 혼재
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
</mandatory_separation>
|
|
@@ -40,16 +40,16 @@ routes/users/
|
|
|
40
40
|
|
|
41
41
|
<hook_order>
|
|
42
42
|
|
|
43
|
-
## Hook
|
|
43
|
+
## Hook 내부 순서 (필수)
|
|
44
44
|
|
|
45
|
-
|
|
|
46
|
-
|
|
45
|
+
| 순서 | Hook 타입 | 예시 |
|
|
46
|
+
|------|-----------|------|
|
|
47
47
|
| 1 | State | `useState`, zustand store |
|
|
48
48
|
| 2 | Global Hooks | `useParams`, `useNavigate`, `useQueryClient` |
|
|
49
49
|
| 3 | React Query | `useQuery` → `useMutation` |
|
|
50
50
|
| 4 | Event Handlers | `handleCreate`, `handleDelete` |
|
|
51
|
-
| 5 | useMemo |
|
|
52
|
-
| 6 | useEffect |
|
|
51
|
+
| 5 | useMemo | 계산된 값 |
|
|
52
|
+
| 6 | useEffect | 부수 효과 |
|
|
53
53
|
|
|
54
54
|
</hook_order>
|
|
55
55
|
|
|
@@ -57,7 +57,7 @@ routes/users/
|
|
|
57
57
|
|
|
58
58
|
<patterns>
|
|
59
59
|
|
|
60
|
-
## Page Hook
|
|
60
|
+
## Page Hook 패턴
|
|
61
61
|
|
|
62
62
|
```typescript
|
|
63
63
|
// routes/users/-hooks/use-users.ts
|
|
@@ -159,7 +159,7 @@ export const useUsers = (): UseUsersReturn => {
|
|
|
159
159
|
}
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
## Filter Hook
|
|
162
|
+
## Filter Hook 패턴
|
|
163
163
|
|
|
164
164
|
```typescript
|
|
165
165
|
// routes/users/-hooks/use-user-filter.ts
|
|
@@ -186,7 +186,7 @@ export const useUserFilter = (): UseUserFilterReturn => {
|
|
|
186
186
|
}
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
## Form Hook
|
|
189
|
+
## Form Hook 패턴
|
|
190
190
|
|
|
191
191
|
```typescript
|
|
192
192
|
// routes/users/-hooks/use-user-form.ts
|
|
@@ -255,24 +255,24 @@ export const useUserForm = (): UseUserFormReturn => {
|
|
|
255
255
|
|
|
256
256
|
<anti_patterns>
|
|
257
257
|
|
|
258
|
-
## ❌
|
|
258
|
+
## ❌ 잘못된 순서
|
|
259
259
|
|
|
260
260
|
```typescript
|
|
261
|
-
// ❌
|
|
261
|
+
// ❌ 순서가 뒤섞인 잘못된 예시
|
|
262
262
|
export const useBadHook = () => {
|
|
263
|
-
const queryClient = useQueryClient() // ❌ Global Hook
|
|
263
|
+
const queryClient = useQueryClient() // ❌ Global Hook이 먼저
|
|
264
264
|
|
|
265
|
-
useEffect(() => { /* ... */ }, []) // ❌ useEffect
|
|
265
|
+
useEffect(() => { /* ... */ }, []) // ❌ useEffect가 중간에
|
|
266
266
|
|
|
267
|
-
const [state, setState] = useState() // ❌ State
|
|
267
|
+
const [state, setState] = useState() // ❌ State가 나중에
|
|
268
268
|
|
|
269
|
-
const { data } = useQuery({ /* ... */ }) // ❌ Query
|
|
269
|
+
const { data } = useQuery({ /* ... */ }) // ❌ Query가 Effect 다음에
|
|
270
270
|
|
|
271
|
-
const computed = useMemo(() => {}, []) // ❌ useMemo
|
|
271
|
+
const computed = useMemo(() => {}, []) // ❌ useMemo 위치 잘못됨
|
|
272
272
|
}
|
|
273
273
|
```
|
|
274
274
|
|
|
275
|
-
## ✅
|
|
275
|
+
## ✅ 올바른 순서
|
|
276
276
|
|
|
277
277
|
```typescript
|
|
278
278
|
export const useGoodHook = () => {
|
|
@@ -306,12 +306,12 @@ export const useGoodHook = () => {
|
|
|
306
306
|
|
|
307
307
|
## TanStack Router Hooks
|
|
308
308
|
|
|
309
|
-
| Hook |
|
|
310
|
-
|
|
311
|
-
| `useParams` | URL
|
|
312
|
-
| `useNavigate` |
|
|
309
|
+
| Hook | 용도 | 예시 |
|
|
310
|
+
|------|------|------|
|
|
311
|
+
| `useParams` | URL 파라미터 | `const { id } = useParams({ from: '/users/$id' })` |
|
|
312
|
+
| `useNavigate` | 프로그래밍 방식 네비게이션 | `navigate({ to: '/users' })` |
|
|
313
313
|
| `useSearch` | Search params | `const { page } = useSearch({ from: '/users' })` |
|
|
314
|
-
| `useLoaderData` | Loader
|
|
314
|
+
| `useLoaderData` | Loader 데이터 | `const user = Route.useLoaderData()` |
|
|
315
315
|
| `useRouteContext` | Route context | `const { auth } = useRouteContext({ from: '__root__' })` |
|
|
316
316
|
|
|
317
317
|
```typescript
|
|
@@ -342,11 +342,11 @@ export const useUserDetail = () => {
|
|
|
342
342
|
|
|
343
343
|
## TanStack Query Hooks
|
|
344
344
|
|
|
345
|
-
| Hook |
|
|
346
|
-
|
|
347
|
-
| `useQuery` |
|
|
348
|
-
| `useMutation` |
|
|
349
|
-
| `useQueryClient` |
|
|
345
|
+
| Hook | 용도 | 특징 |
|
|
346
|
+
|------|------|------|
|
|
347
|
+
| `useQuery` | 데이터 조회 (GET) | 자동 캐싱, 재검증 |
|
|
348
|
+
| `useMutation` | 데이터 변경 (POST/PUT/DELETE) | 성공 시 캐시 무효화 |
|
|
349
|
+
| `useQueryClient` | 캐시 제어 | `invalidateQueries`, `setQueryData` |
|
|
350
350
|
|
|
351
351
|
```typescript
|
|
352
352
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
@@ -378,13 +378,13 @@ export const useUsers = () => {
|
|
|
378
378
|
|
|
379
379
|
<best_practices>
|
|
380
380
|
|
|
381
|
-
|
|
|
382
|
-
|
|
383
|
-
|
|
|
384
|
-
|
|
|
385
|
-
|
|
|
386
|
-
| **useCallback** |
|
|
387
|
-
|
|
|
381
|
+
| 원칙 | 설명 |
|
|
382
|
+
|------|------|
|
|
383
|
+
| **순서 준수** | State → Global → Query → Handlers → Memo → Effect |
|
|
384
|
+
| **타입 정의** | Return 타입 명시 (interface) |
|
|
385
|
+
| **단일 책임** | 하나의 Hook은 하나의 관심사 |
|
|
386
|
+
| **useCallback** | Event handler는 useCallback으로 메모이제이션 |
|
|
387
|
+
| **명확한 네이밍** | `use-users.ts`, `use-user-filter.ts` |
|
|
388
388
|
|
|
389
389
|
</best_practices>
|
|
390
390
|
|