@kood/claude-code 0.2.4 → 0.3.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.
- package/dist/index.js +13 -8
- package/package.json +1 -1
- package/templates/.claude/agents/code-reviewer.md +371 -19
- package/templates/.claude/agents/dependency-manager.md +197 -0
- package/templates/.claude/agents/deployment-validator.md +136 -0
- package/templates/.claude/agents/git-operator.md +147 -0
- package/templates/.claude/agents/implementation-executor.md +202 -0
- package/templates/.claude/agents/lint-fixer.md +155 -0
- package/templates/.claude/agents/refactor-advisor.md +339 -29
- package/templates/.claude/commands/agent-creator.md +355 -0
- package/templates/.claude/commands/docs-creator.md +404 -163
- package/templates/.claude/commands/docs-refactor.md +400 -113
- package/templates/.claude/commands/execute.md +357 -185
- package/templates/.claude/commands/git-all.md +16 -70
- package/templates/.claude/commands/git-session.md +36 -68
- package/templates/.claude/commands/git.md +20 -69
- package/templates/.claude/commands/lint-fix.md +164 -107
- package/templates/.claude/commands/lint-init.md +142 -168
- package/templates/.claude/commands/plan.md +300 -84
- package/templates/.claude/commands/prd.md +613 -0
- package/templates/.claude/commands/pre-deploy.md +242 -0
- package/templates/.claude/commands/subagent-creator.md +118 -0
- package/templates/.claude/commands/version-update.md +45 -57
- package/templates/hono/CLAUDE.md +99 -54
- package/templates/hono/docs/guides/conventions.md +352 -0
- package/templates/hono/docs/guides/env-setup.md +347 -0
- package/templates/hono/docs/guides/getting-started.md +239 -0
- package/templates/hono/docs/library/hono/error-handling.md +20 -29
- package/templates/hono/docs/library/hono/index.md +25 -52
- package/templates/hono/docs/library/hono/middleware.md +16 -75
- package/templates/hono/docs/library/hono/rpc.md +7 -35
- package/templates/hono/docs/library/hono/validation.md +25 -45
- package/templates/hono/docs/library/t3-env/index.md +374 -0
- package/templates/npx/CLAUDE.md +165 -65
- package/templates/npx/docs/library/commander/index.md +10 -73
- package/templates/npx/docs/library/fs-extra/index.md +21 -113
- package/templates/npx/docs/library/prompts/index.md +30 -176
- package/templates/npx/docs/references/patterns.md +75 -48
- package/templates/tanstack-start/CLAUDE.md +101 -77
- package/templates/tanstack-start/docs/architecture.md +427 -0
- package/templates/tanstack-start/docs/design.md +558 -0
- package/templates/tanstack-start/docs/guides/conventions.md +132 -32
- package/templates/tanstack-start/docs/guides/env-setup.md +127 -62
- package/templates/tanstack-start/docs/guides/getting-started.md +81 -20
- package/templates/tanstack-start/docs/guides/hooks.md +241 -36
- package/templates/tanstack-start/docs/guides/routes.md +213 -61
- package/templates/tanstack-start/docs/guides/services.md +260 -24
- package/templates/tanstack-start/docs/library/better-auth/index.md +469 -16
- package/templates/tanstack-start/docs/library/t3-env/index.md +307 -0
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +12 -21
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +22 -35
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +7 -24
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +26 -39
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +23 -26
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +32 -147
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +25 -167
- package/templates/tanstack-start/docs/library/tanstack-router/index.md +39 -74
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +46 -116
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +35 -154
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +32 -171
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +7 -15
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +16 -23
- package/templates/tanstack-start/docs/library/zod/complex-types.md +12 -31
- package/templates/tanstack-start/docs/library/zod/index.md +18 -35
- package/templates/tanstack-start/docs/library/zod/transforms.md +11 -25
- package/templates/tanstack-start/docs/library/zod/validation.md +12 -34
- package/templates/.claude/agents/debug-detective.md +0 -37
- package/templates/.claude/agents/test-writer.md +0 -41
- package/templates/.claude/commands/feedback.md +0 -199
- package/templates/.claude/commands/ts-fix.md +0 -176
- package/templates/.claude/skills/command-creator/LICENSE.txt +0 -202
- package/templates/.claude/skills/command-creator/SKILL.md +0 -245
- package/templates/.claude/skills/command-creator/scripts/init_command.py +0 -244
- package/templates/.claude/skills/command-creator/scripts/package_command.py +0 -125
- package/templates/.claude/skills/command-creator/scripts/quick_validate.py +0 -143
- package/templates/.claude/skills/frontend-design/SKILL.md +0 -310
- package/templates/.claude/skills/frontend-design/references/animation-patterns.md +0 -446
- package/templates/.claude/skills/frontend-design/references/colors-2026.md +0 -244
- package/templates/.claude/skills/frontend-design/references/typography-2026.md +0 -302
- package/templates/.claude/skills/gemini-review/SKILL.md +0 -118
- package/templates/.claude/skills/gemini-review/references/checklists.md +0 -129
- package/templates/.claude/skills/gemini-review/references/prompt-templates.md +0 -274
- package/templates/.claude/skills/skill-creator/LICENSE.txt +0 -202
- package/templates/.claude/skills/skill-creator/SKILL.md +0 -184
- package/templates/.claude/skills/skill-creator/scripts/init_skill.py +0 -303
- package/templates/.claude/skills/skill-creator/scripts/package_skill.py +0 -110
- package/templates/.claude/skills/skill-creator/scripts/quick_validate.py +0 -65
- package/templates/hono/docs/library/ai-sdk/index.md +0 -190
- package/templates/hono/docs/library/ai-sdk/openrouter.md +0 -111
- package/templates/hono/docs/library/ai-sdk/providers.md +0 -102
- package/templates/hono/docs/library/ai-sdk/streaming.md +0 -146
- package/templates/hono/docs/library/ai-sdk/structured-output.md +0 -161
- package/templates/hono/docs/library/ai-sdk/tools.md +0 -144
- package/templates/hono/docs/library/drizzle/cloudflare-d1.md +0 -247
- package/templates/hono/docs/library/drizzle/config.md +0 -167
- package/templates/hono/docs/library/drizzle/index.md +0 -259
- package/templates/hono/docs/library/hono/env-setup.md +0 -169
- package/templates/hono/docs/library/pino/index.md +0 -146
- package/templates/tanstack-start/docs/architecture/architecture.md +0 -243
- package/templates/tanstack-start/docs/deployment/cloudflare.md +0 -132
- package/templates/tanstack-start/docs/deployment/index.md +0 -163
- package/templates/tanstack-start/docs/deployment/nitro.md +0 -110
- package/templates/tanstack-start/docs/deployment/railway.md +0 -147
- package/templates/tanstack-start/docs/deployment/vercel.md +0 -135
- package/templates/tanstack-start/docs/design/components.md +0 -175
- package/templates/tanstack-start/docs/design/index.md +0 -151
- package/templates/tanstack-start/docs/design/safe-area.md +0 -118
- package/templates/tanstack-start/docs/design/tailwind-setup.md +0 -156
- package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +0 -472
- package/templates/tanstack-start/docs/library/ai-sdk/index.md +0 -264
- package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +0 -371
- package/templates/tanstack-start/docs/library/ai-sdk/providers.md +0 -403
- package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +0 -320
- package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +0 -454
- package/templates/tanstack-start/docs/library/ai-sdk/tools.md +0 -473
- package/templates/tanstack-start/docs/library/better-auth/2fa.md +0 -48
- package/templates/tanstack-start/docs/library/better-auth/advanced.md +0 -55
- package/templates/tanstack-start/docs/library/better-auth/plugins.md +0 -34
- package/templates/tanstack-start/docs/library/better-auth/session.md +0 -47
- package/templates/tanstack-start/docs/library/better-auth/setup.md +0 -41
- package/templates/tanstack-start/docs/library/drizzle/cloudflare-d1.md +0 -147
- package/templates/tanstack-start/docs/library/drizzle/config.md +0 -118
- package/templates/tanstack-start/docs/library/drizzle/crud.md +0 -205
- package/templates/tanstack-start/docs/library/drizzle/index.md +0 -79
- package/templates/tanstack-start/docs/library/drizzle/relations.md +0 -202
- package/templates/tanstack-start/docs/library/drizzle/schema.md +0 -154
- package/templates/tanstack-start/docs/library/drizzle/setup.md +0 -96
- package/templates/tanstack-start/docs/library/drizzle/transactions.md +0 -127
- package/templates/tanstack-start/docs/library/pino/index.md +0 -320
- /package/templates/hono/docs/{architecture/architecture.md → architecture.md} +0 -0
|
@@ -1,31 +1,82 @@
|
|
|
1
1
|
# 코드 컨벤션
|
|
2
2
|
|
|
3
|
-
TanStack Start
|
|
3
|
+
> TanStack Start 프로젝트 코드 작성 규칙
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<naming>
|
|
4
8
|
|
|
5
9
|
## 파일 네이밍
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
| 타입 | 규칙 | 예시 |
|
|
12
|
+
|------|------|------|
|
|
13
|
+
| **일반 파일** | kebab-case | `user-profile.tsx`, `auth-service.ts` |
|
|
14
|
+
| **Route 파일** | TanStack Router 규칙 | `__root.tsx`, `index.tsx`, `$id.tsx` |
|
|
15
|
+
| **Hook 파일** | `use-` 접두사 | `use-user-filter.ts`, `use-auth.ts` |
|
|
16
|
+
| **Component** | PascalCase (파일은 kebab) | `UserCard` in `user-card.tsx` |
|
|
8
17
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
</naming>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<typescript>
|
|
23
|
+
|
|
24
|
+
## TypeScript 규칙
|
|
25
|
+
|
|
26
|
+
| 규칙 | 설명 | 예시 |
|
|
27
|
+
|------|------|------|
|
|
28
|
+
| **함수 선언** | const 함수, 명시적 return type | `const fn = (): ReturnType => {}` |
|
|
29
|
+
| **타입 정의** | interface (객체), type (유니온) | `interface User {}`, `type Status = 'a' \| 'b'` |
|
|
30
|
+
| **any 금지** | unknown 사용 | `const data: unknown = JSON.parse(str)` |
|
|
31
|
+
| **Import 타입** | type import 분리 | `import type { User } from '@/types'` |
|
|
32
|
+
|
|
33
|
+
## 패턴
|
|
13
34
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
```typescript
|
|
36
|
+
// ✅ const 함수, 명시적 타입
|
|
37
|
+
const getUserById = async (id: string): Promise<User> => {
|
|
38
|
+
return prisma.user.findUnique({ where: { id } })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ✅ 간단한 함수도 명시적 타입
|
|
42
|
+
const formatDate = (date: Date): string => {
|
|
43
|
+
return date.toISOString()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ✅ any 금지 → unknown 사용
|
|
47
|
+
const parseJSON = (data: string): unknown => {
|
|
48
|
+
return JSON.parse(data)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ❌ any 사용 금지
|
|
52
|
+
const badParse = (data: string): any => { // ❌
|
|
53
|
+
return JSON.parse(data)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ❌ function 키워드 금지
|
|
57
|
+
function badFunction() { // ❌
|
|
58
|
+
return 'use const arrow function'
|
|
59
|
+
}
|
|
17
60
|
```
|
|
18
61
|
|
|
62
|
+
</typescript>
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
<imports>
|
|
67
|
+
|
|
19
68
|
## Import 순서
|
|
20
69
|
|
|
21
70
|
```typescript
|
|
22
71
|
// 1. External libraries
|
|
23
72
|
import { createFileRoute } from '@tanstack/react-router'
|
|
24
73
|
import { useQuery } from '@tanstack/react-query'
|
|
74
|
+
import { z } from 'zod'
|
|
25
75
|
|
|
26
|
-
// 2. Internal packages
|
|
76
|
+
// 2. Internal packages (@/)
|
|
27
77
|
import { Button } from '@/components/ui/button'
|
|
28
|
-
import { prisma } from '@/
|
|
78
|
+
import { prisma } from '@/database/prisma'
|
|
79
|
+
import { getUsers } from '@/services/user'
|
|
29
80
|
|
|
30
81
|
// 3. Relative imports (route-specific)
|
|
31
82
|
import { UserCard } from './-components/user-card'
|
|
@@ -33,37 +84,25 @@ import { useUsers } from './-hooks/use-users'
|
|
|
33
84
|
|
|
34
85
|
// 4. Type imports
|
|
35
86
|
import type { User } from '@/types'
|
|
87
|
+
import type { UseUsersReturn } from './-hooks/use-users'
|
|
36
88
|
```
|
|
37
89
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
// ✅ const 함수
|
|
42
|
-
const getUserById = async (id: string): Promise<User> => {
|
|
43
|
-
return prisma.user.findUnique({ where: { id } })
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ✅ 명시적 반환 타입
|
|
47
|
-
const formatDate = (date: Date): string => {
|
|
48
|
-
return date.toISOString()
|
|
49
|
-
}
|
|
90
|
+
</imports>
|
|
50
91
|
|
|
51
|
-
|
|
52
|
-
const parseJSON = (data: string): unknown => {
|
|
53
|
-
return JSON.parse(data)
|
|
54
|
-
}
|
|
55
|
-
```
|
|
92
|
+
---
|
|
56
93
|
|
|
57
|
-
|
|
94
|
+
<comments>
|
|
58
95
|
|
|
59
|
-
|
|
96
|
+
## 한글 주석 (묶음 단위)
|
|
60
97
|
|
|
61
98
|
```typescript
|
|
99
|
+
// ✅ 코드 묶음 단위 주석
|
|
62
100
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
63
101
|
// 사용자 관련 상태
|
|
64
102
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
65
103
|
const [user, setUser] = useState<User | null>(null)
|
|
66
104
|
const [isLoading, setIsLoading] = useState(false)
|
|
105
|
+
const [error, setError] = useState<Error | null>(null)
|
|
67
106
|
|
|
68
107
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
69
108
|
// 데이터 조회
|
|
@@ -75,12 +114,19 @@ const { data: users } = useQuery({
|
|
|
75
114
|
```
|
|
76
115
|
|
|
77
116
|
```typescript
|
|
78
|
-
// ❌
|
|
117
|
+
// ❌ 세세한 주석 (금지)
|
|
79
118
|
const [user, setUser] = useState(null) // 사용자 상태
|
|
80
119
|
const [isLoading, setIsLoading] = useState(false) // 로딩 상태
|
|
120
|
+
const [error, setError] = useState(null) // 에러 상태
|
|
81
121
|
```
|
|
82
122
|
|
|
83
|
-
|
|
123
|
+
</comments>
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
<error_handling>
|
|
128
|
+
|
|
129
|
+
## 에러 처리 패턴
|
|
84
130
|
|
|
85
131
|
```typescript
|
|
86
132
|
// lib/errors.ts
|
|
@@ -100,4 +146,58 @@ export class NotFoundError extends AppError {
|
|
|
100
146
|
super(`${resource} not found`, 404, 'NOT_FOUND')
|
|
101
147
|
}
|
|
102
148
|
}
|
|
149
|
+
|
|
150
|
+
export class ValidationError extends AppError {
|
|
151
|
+
constructor(message: string) {
|
|
152
|
+
super(message, 400, 'VALIDATION_ERROR')
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export class UnauthorizedError extends AppError {
|
|
157
|
+
constructor() {
|
|
158
|
+
super('Unauthorized', 401, 'UNAUTHORIZED')
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## 사용 예시
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// services/user/queries.ts
|
|
167
|
+
import { NotFoundError } from '@/lib/errors'
|
|
168
|
+
|
|
169
|
+
export const getUserById = createServerFn({ method: 'GET' })
|
|
170
|
+
.handler(async ({ data: id }: { data: string }) => {
|
|
171
|
+
const user = await prisma.user.findUnique({ where: { id } })
|
|
172
|
+
if (!user) throw new NotFoundError('User')
|
|
173
|
+
return user
|
|
174
|
+
})
|
|
103
175
|
```
|
|
176
|
+
|
|
177
|
+
</error_handling>
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
<examples>
|
|
182
|
+
|
|
183
|
+
## 파일명 예시
|
|
184
|
+
|
|
185
|
+
| 타입 | ❌ 잘못된 예시 | ✅ 올바른 예시 |
|
|
186
|
+
|------|---------------|---------------|
|
|
187
|
+
| Component | `UserProfile.tsx` | `user-profile.tsx` |
|
|
188
|
+
| Service | `authService.ts` | `auth-service.ts` |
|
|
189
|
+
| Hook | `useUserFilter.ts` | `use-user-filter.ts` |
|
|
190
|
+
| Utility | `formatUtils.ts` | `format-utils.ts` |
|
|
191
|
+
| Type | `UserTypes.ts` | `user-types.ts` |
|
|
192
|
+
|
|
193
|
+
## Route 파일명
|
|
194
|
+
|
|
195
|
+
| 경로 | 파일명 | 설명 |
|
|
196
|
+
|------|--------|------|
|
|
197
|
+
| `/` | `index.tsx` | 인덱스 라우트 |
|
|
198
|
+
| `/users` | `users/index.tsx` | 사용자 목록 |
|
|
199
|
+
| `/users/:id` | `users/$id.tsx` | 동적 라우트 |
|
|
200
|
+
| `/posts/:slug` | `posts/$slug.tsx` | URL 파라미터 |
|
|
201
|
+
| Layout | `__root.tsx` | Root 레이아웃 |
|
|
202
|
+
|
|
203
|
+
</examples>
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
# 환경 변수 설정
|
|
2
2
|
|
|
3
|
-
TanStack Start (Vite 기반) 환경 변수
|
|
3
|
+
> TanStack Start (Vite 기반) 환경 변수 관리
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<instructions>
|
|
6
|
+
@../library/t3-env/index.md
|
|
7
|
+
</instructions>
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<environment_types>
|
|
12
|
+
|
|
13
|
+
| 접근 방식 | 위치 | 용도 | 노출 |
|
|
14
|
+
|-----------|------|------|------|
|
|
15
|
+
| `process.env.*` | Server Function | DB, API 키, 시크릿 | ❌ 서버만 |
|
|
16
|
+
| `import.meta.env.VITE_*` | 클라이언트 + 서버 | 공개 설정 | ✅ 브라우저 노출 |
|
|
17
|
+
|
|
18
|
+
</environment_types>
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
| `import.meta.env.VITE_*` | 클라이언트 + 서버 | 공개 설정 |
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<file_structure>
|
|
16
23
|
|
|
17
24
|
## 환경 파일 구조
|
|
18
25
|
|
|
@@ -21,17 +28,21 @@ TanStack Start (Vite 기반) 환경 변수 관리.
|
|
|
21
28
|
├── .env.development # 개발 (커밋 O)
|
|
22
29
|
├── .env.production # 프로덕션 (커밋 O)
|
|
23
30
|
├── .env.local # 로컬 오버라이드 (커밋 X)
|
|
24
|
-
└──
|
|
31
|
+
└── src/lib/env.ts # 검증 및 타입 (t3-env)
|
|
25
32
|
```
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
| 우선순위 | 파일 | 설명 |
|
|
35
|
+
|----------|------|------|
|
|
36
|
+
| 1 | `.env.{mode}.local` | 최우선 (gitignore) |
|
|
37
|
+
| 2 | `.env.local` | 로컬 오버라이드 |
|
|
38
|
+
| 3 | `.env.{mode}` | 환경별 설정 |
|
|
39
|
+
| 4 | `.env` | 기본 설정 |
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
```
|
|
41
|
+
</file_structure>
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
<patterns>
|
|
35
46
|
|
|
36
47
|
## 환경 파일 예시
|
|
37
48
|
|
|
@@ -49,45 +60,50 @@ OPENAI_API_KEY=sk-xxx
|
|
|
49
60
|
NODE_ENV=development
|
|
50
61
|
VITE_APP_NAME=My App (Dev)
|
|
51
62
|
VITE_API_URL=http://localhost:3001/api
|
|
52
|
-
DATABASE_URL=postgresql://localhost:5432/myapp_dev
|
|
53
63
|
```
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
### .env.production
|
|
66
|
+
|
|
67
|
+
```env
|
|
68
|
+
NODE_ENV=production
|
|
69
|
+
VITE_APP_NAME=My App
|
|
70
|
+
VITE_API_URL=https://api.myapp.com
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 타입 안전한 환경 변수 (t3-env)
|
|
56
74
|
|
|
57
75
|
```typescript
|
|
58
|
-
//
|
|
76
|
+
// src/lib/env.ts
|
|
77
|
+
import { createEnv } from '@t3-oss/env-core'
|
|
59
78
|
import { z } from 'zod'
|
|
60
79
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
80
|
+
export const env = createEnv({
|
|
81
|
+
server: {
|
|
82
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
83
|
+
DATABASE_URL: z.string().url(),
|
|
84
|
+
JWT_SECRET: z.string().min(32),
|
|
85
|
+
OPENAI_API_KEY: z.string().optional(),
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
client: {
|
|
89
|
+
VITE_APP_NAME: z.string(),
|
|
90
|
+
VITE_API_URL: z.string().url(),
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
runtimeEnv: {
|
|
94
|
+
// Server
|
|
95
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
96
|
+
DATABASE_URL: process.env.DATABASE_URL,
|
|
97
|
+
JWT_SECRET: process.env.JWT_SECRET,
|
|
98
|
+
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
|
|
99
|
+
|
|
100
|
+
// Client
|
|
101
|
+
VITE_APP_NAME: import.meta.env.VITE_APP_NAME,
|
|
102
|
+
VITE_API_URL: import.meta.env.VITE_API_URL,
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
clientPrefix: 'VITE_',
|
|
66
106
|
})
|
|
67
|
-
|
|
68
|
-
const clientEnvSchema = z.object({
|
|
69
|
-
VITE_APP_NAME: z.string(),
|
|
70
|
-
VITE_API_URL: z.string().url(),
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
export type ServerEnv = z.infer<typeof serverEnvSchema>
|
|
74
|
-
export type ClientEnv = z.infer<typeof clientEnvSchema>
|
|
75
|
-
|
|
76
|
-
let _serverEnv: ServerEnv | null = null
|
|
77
|
-
|
|
78
|
-
export const getServerEnv = (): ServerEnv => {
|
|
79
|
-
if (!_serverEnv) {
|
|
80
|
-
const result = serverEnvSchema.safeParse(process.env)
|
|
81
|
-
if (!result.success) {
|
|
82
|
-
console.error('❌ 서버 환경 변수 검증 실패:', result.error.format())
|
|
83
|
-
throw new Error('Server environment validation failed')
|
|
84
|
-
}
|
|
85
|
-
_serverEnv = result.data
|
|
86
|
-
}
|
|
87
|
-
return _serverEnv
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export const clientEnv = clientEnvSchema.parse(import.meta.env)
|
|
91
107
|
```
|
|
92
108
|
|
|
93
109
|
## 사용 예시
|
|
@@ -95,42 +111,64 @@ export const clientEnv = clientEnvSchema.parse(import.meta.env)
|
|
|
95
111
|
### Server Function
|
|
96
112
|
|
|
97
113
|
```typescript
|
|
114
|
+
// services/user/queries.ts
|
|
98
115
|
import { createServerFn } from '@tanstack/react-start'
|
|
99
|
-
import {
|
|
116
|
+
import { env } from '@/lib/env'
|
|
117
|
+
import { prisma } from '@/database/prisma'
|
|
100
118
|
|
|
101
119
|
export const getUsers = createServerFn({ method: 'GET' })
|
|
102
120
|
.handler(async () => {
|
|
103
|
-
|
|
104
|
-
|
|
121
|
+
// env.DATABASE_URL은 서버에서만 사용 가능
|
|
122
|
+
console.log('DB URL:', env.DATABASE_URL)
|
|
123
|
+
return prisma.user.findMany()
|
|
105
124
|
})
|
|
106
125
|
```
|
|
107
126
|
|
|
108
|
-
### 클라이언트
|
|
127
|
+
### 클라이언트 컴포넌트
|
|
109
128
|
|
|
110
129
|
```tsx
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
130
|
+
// components/app-header.tsx
|
|
131
|
+
import { env } from '@/lib/env'
|
|
132
|
+
|
|
133
|
+
export const AppHeader = (): JSX.Element => {
|
|
134
|
+
return (
|
|
135
|
+
<header>
|
|
136
|
+
<h1>{env.VITE_APP_NAME}</h1>
|
|
137
|
+
<p>API: {env.VITE_API_URL}</p>
|
|
138
|
+
</header>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
116
141
|
```
|
|
117
142
|
|
|
143
|
+
</patterns>
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
<gitignore>
|
|
148
|
+
|
|
118
149
|
## .gitignore
|
|
119
150
|
|
|
120
151
|
```gitignore
|
|
152
|
+
# 시크릿 포함 (절대 커밋 X)
|
|
121
153
|
.env.local
|
|
122
154
|
.env.*.local
|
|
123
155
|
|
|
124
|
-
#
|
|
156
|
+
# 공개 설정 (커밋 O)
|
|
125
157
|
!.env
|
|
126
158
|
!.env.development
|
|
127
159
|
!.env.production
|
|
128
160
|
```
|
|
129
161
|
|
|
130
|
-
|
|
162
|
+
</gitignore>
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
<typescript_types>
|
|
167
|
+
|
|
168
|
+
## TypeScript 타입 (Vite)
|
|
131
169
|
|
|
132
170
|
```typescript
|
|
133
|
-
//
|
|
171
|
+
// src/vite-env.d.ts
|
|
134
172
|
/// <reference types="vite/client" />
|
|
135
173
|
|
|
136
174
|
interface ImportMetaEnv {
|
|
@@ -142,3 +180,30 @@ interface ImportMeta {
|
|
|
142
180
|
readonly env: ImportMetaEnv
|
|
143
181
|
}
|
|
144
182
|
```
|
|
183
|
+
|
|
184
|
+
**참고:** t3-env 사용 시 자동으로 타입 추론됨
|
|
185
|
+
|
|
186
|
+
</typescript_types>
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
<best_practices>
|
|
191
|
+
|
|
192
|
+
| 원칙 | 설명 |
|
|
193
|
+
|------|------|
|
|
194
|
+
| **시크릿 분리** | `.env.local`에만 시크릿 저장, 커밋 금지 |
|
|
195
|
+
| **공개 변수** | `VITE_` 접두사 사용, 브라우저 노출 허용 |
|
|
196
|
+
| **타입 안전성** | t3-env 또는 Zod로 검증 |
|
|
197
|
+
| **기본값** | `.env`에 안전한 기본값 설정 |
|
|
198
|
+
| **문서화** | `.env.example` 파일로 필수 변수 목록 제공 |
|
|
199
|
+
|
|
200
|
+
</best_practices>
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
<sources>
|
|
205
|
+
|
|
206
|
+
- [Vite Environment Variables](https://vitejs.dev/guide/env-and-mode.html)
|
|
207
|
+
- [t3-env Documentation](https://env.t3.gg/docs/introduction)
|
|
208
|
+
|
|
209
|
+
</sources>
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
# Getting Started
|
|
2
2
|
|
|
3
|
-
TanStack Start 프로젝트 시작
|
|
3
|
+
> TanStack Start 프로젝트 빠른 시작
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<instructions>
|
|
6
|
+
@conventions.md
|
|
7
|
+
@routes.md
|
|
8
|
+
@services.md
|
|
9
|
+
</instructions>
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<prerequisites>
|
|
14
|
+
|
|
15
|
+
| 요구사항 | 버전 |
|
|
16
|
+
|----------|------|
|
|
17
|
+
| Node.js | 18+ |
|
|
18
|
+
| 패키지 관리자 | Yarn / npm / pnpm |
|
|
19
|
+
|
|
20
|
+
</prerequisites>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<installation>
|
|
9
25
|
|
|
10
26
|
## 프로젝트 생성
|
|
11
27
|
|
|
@@ -15,7 +31,7 @@ cd my-app
|
|
|
15
31
|
yarn install
|
|
16
32
|
```
|
|
17
33
|
|
|
18
|
-
## 필수 패키지
|
|
34
|
+
## 필수 패키지
|
|
19
35
|
|
|
20
36
|
```bash
|
|
21
37
|
# Database (Prisma 7.x)
|
|
@@ -29,9 +45,25 @@ yarn add zod
|
|
|
29
45
|
yarn add @tanstack/react-query
|
|
30
46
|
```
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
</installation>
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
<project_setup>
|
|
53
|
+
|
|
54
|
+
## 프로젝트 구조
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
src/
|
|
58
|
+
├── routes/
|
|
59
|
+
│ ├── __root.tsx # Root Layout
|
|
60
|
+
│ └── index.tsx # Home Page
|
|
61
|
+
├── lib/
|
|
62
|
+
│ └── query-client.ts # Query Client 설정
|
|
63
|
+
└── app.config.ts # TanStack Start 설정
|
|
64
|
+
```
|
|
33
65
|
|
|
34
|
-
|
|
66
|
+
## app.config.ts
|
|
35
67
|
|
|
36
68
|
```typescript
|
|
37
69
|
import { defineConfig } from '@tanstack/react-start/config'
|
|
@@ -43,7 +75,7 @@ export default defineConfig({
|
|
|
43
75
|
})
|
|
44
76
|
```
|
|
45
77
|
|
|
46
|
-
|
|
78
|
+
## Root Route
|
|
47
79
|
|
|
48
80
|
```tsx
|
|
49
81
|
// src/routes/__root.tsx
|
|
@@ -67,7 +99,7 @@ const RootComponent = (): JSX.Element => {
|
|
|
67
99
|
}
|
|
68
100
|
```
|
|
69
101
|
|
|
70
|
-
|
|
102
|
+
## Home Route
|
|
71
103
|
|
|
72
104
|
```tsx
|
|
73
105
|
// src/routes/index.tsx
|
|
@@ -80,13 +112,16 @@ export const Route = createFileRoute('/')({
|
|
|
80
112
|
const HomePage = (): JSX.Element => {
|
|
81
113
|
return (
|
|
82
114
|
<div>
|
|
83
|
-
<h1 className="text-2xl font-bold">Welcome</h1>
|
|
115
|
+
<h1 className="text-2xl font-bold">Welcome to TanStack Start</h1>
|
|
116
|
+
<p className="mt-4 text-gray-600">
|
|
117
|
+
Full-stack React framework powered by TanStack Router
|
|
118
|
+
</p>
|
|
84
119
|
</div>
|
|
85
120
|
)
|
|
86
121
|
}
|
|
87
122
|
```
|
|
88
123
|
|
|
89
|
-
|
|
124
|
+
## Query Client 설정
|
|
90
125
|
|
|
91
126
|
```typescript
|
|
92
127
|
// src/lib/query-client.ts
|
|
@@ -95,23 +130,49 @@ import { QueryClient } from '@tanstack/react-query'
|
|
|
95
130
|
export const createQueryClient = (): QueryClient => {
|
|
96
131
|
return new QueryClient({
|
|
97
132
|
defaultOptions: {
|
|
98
|
-
queries: {
|
|
133
|
+
queries: {
|
|
134
|
+
staleTime: 60 * 1000, // 1분
|
|
135
|
+
retry: 1,
|
|
136
|
+
},
|
|
99
137
|
},
|
|
100
138
|
})
|
|
101
139
|
}
|
|
102
140
|
```
|
|
103
141
|
|
|
104
|
-
|
|
142
|
+
</project_setup>
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
<commands>
|
|
105
147
|
|
|
106
148
|
| Command | Description |
|
|
107
149
|
|---------|-------------|
|
|
108
|
-
| `yarn dev` | 개발 서버 시작 |
|
|
150
|
+
| `yarn dev` | 개발 서버 시작 (http://localhost:3000) |
|
|
109
151
|
| `yarn build` | 프로덕션 빌드 |
|
|
110
|
-
| `yarn start` | 프로덕션 서버 |
|
|
152
|
+
| `yarn start` | 프로덕션 서버 실행 |
|
|
153
|
+
|
|
154
|
+
</commands>
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
<next_steps>
|
|
159
|
+
|
|
160
|
+
| 문서 | 내용 |
|
|
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 패턴 |
|
|
167
|
+
|
|
168
|
+
</next_steps>
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
<sources>
|
|
111
173
|
|
|
112
|
-
|
|
174
|
+
- [TanStack Start Server Functions](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions)
|
|
175
|
+
- [TanStack Router Data Loading](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading)
|
|
176
|
+
- [TanStack Start Middleware](https://tanstack.com/start/latest/docs/framework/react/guide/middleware)
|
|
113
177
|
|
|
114
|
-
|
|
115
|
-
- [routes.md](./routes.md) - 라우트 구조
|
|
116
|
-
- [hooks.md](./hooks.md) - Custom Hook 패턴
|
|
117
|
-
- [services.md](./services.md) - Service Layer
|
|
178
|
+
</sources>
|