@kood/claude-code 0.1.4 → 0.1.6
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 +1 -1
- package/package.json +1 -1
- package/templates/hono/docs/commands/git.md +23 -153
- package/templates/npx/docs/commands/git.md +23 -153
- package/templates/tanstack-start/CLAUDE.md +6 -8
- package/templates/tanstack-start/docs/commands/git.md +23 -153
- package/templates/tanstack-start/docs/guides/best-practices.md +3 -8
- package/templates/tanstack-start/docs/guides/env-setup.md +3 -3
- package/templates/tanstack-start/docs/library/better-auth/2fa.md +1 -1
- package/templates/tanstack-start/docs/library/better-auth/setup.md +1 -1
- package/templates/tanstack-start/docs/library/prisma/setup.md +1 -1
- package/templates/tanstack-start/docs/library/tanstack-query/setup.md +2 -5
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +1 -1
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +90 -9
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +1 -1
package/dist/index.js
CHANGED
|
@@ -460,7 +460,7 @@ var installAllCommands = async (templates, targetDir) => {
|
|
|
460
460
|
|
|
461
461
|
// src/index.ts
|
|
462
462
|
var program = new Command();
|
|
463
|
-
program.name("claude-code").description("Claude Code documentation installer for projects").version("0.1.
|
|
463
|
+
program.name("claude-code").description("Claude Code documentation installer for projects").version("0.1.5");
|
|
464
464
|
program.option(
|
|
465
465
|
"-t, --template <names>",
|
|
466
466
|
"template names (comma-separated: tanstack-start,hono)"
|
package/package.json
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
현재 git 상태를 확인하고, 아래 규칙에 따라 작업을 진행해주세요.
|
|
2
|
+
|
|
3
|
+
**추가 지시사항**: $ARGUMENTS
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 실행 절차
|
|
8
|
+
|
|
9
|
+
### 추가 지시사항이 없는 경우 (기본 동작)
|
|
10
|
+
1. `git status`로 현재 상태 확인
|
|
11
|
+
2. `git diff`로 변경 내용 분석
|
|
12
|
+
3. 스테이징 안 된 변경사항 → `git add`
|
|
13
|
+
4. 커밋 안 된 변경사항 → 논리적 단위로 분리하여 `git commit`
|
|
14
|
+
5. 최종 `git status`로 완료 확인
|
|
15
|
+
|
|
16
|
+
### 추가 지시사항이 있는 경우
|
|
17
|
+
- 사용자의 지시사항을 우선적으로 따름
|
|
18
|
+
- 예: `/git push` → push 진행, `/git 특정파일만 커밋` → 해당 파일만 처리
|
|
2
19
|
|
|
3
20
|
---
|
|
4
21
|
|
|
@@ -19,12 +36,13 @@
|
|
|
19
36
|
|
|
20
37
|
## ✅ ALWAYS (필수)
|
|
21
38
|
|
|
22
|
-
###
|
|
39
|
+
### 커밋 형식
|
|
23
40
|
|
|
24
|
-
```bash
|
|
25
|
-
git add <관련 파일들>
|
|
26
|
-
git commit -m "<prefix>: <설명>"
|
|
27
41
|
```
|
|
42
|
+
<prefix>: <설명>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**한 줄로 간결하게** 작성합니다. 본문이나 푸터는 작성하지 않습니다.
|
|
28
46
|
|
|
29
47
|
### ⭐ 커밋 분리 원칙
|
|
30
48
|
|
|
@@ -48,16 +66,6 @@ git commit -m "docs: API 문서 업데이트"
|
|
|
48
66
|
|
|
49
67
|
---
|
|
50
68
|
|
|
51
|
-
## 📝 커밋 형식
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
<prefix>: <설명>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**한 줄로 간결하게** 작성합니다. 본문이나 푸터는 작성하지 않습니다.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
69
|
## 🏷 Prefix 목록
|
|
62
70
|
|
|
63
71
|
| Prefix | 용도 | 예시 |
|
|
@@ -123,30 +131,6 @@ feat: 로그인, 회원가입, 프로필 기능 추가
|
|
|
123
131
|
|
|
124
132
|
---
|
|
125
133
|
|
|
126
|
-
## 🔄 작업 흐름
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
# 1. 작업 전 최신 코드 동기화
|
|
130
|
-
git pull origin main
|
|
131
|
-
|
|
132
|
-
# 2. 기능 A 작업 완료 → 커밋
|
|
133
|
-
git add src/feature-a/
|
|
134
|
-
git commit -m "feat: 기능 A 구현"
|
|
135
|
-
|
|
136
|
-
# 3. 기능 B 작업 완료 → 커밋
|
|
137
|
-
git add src/feature-b/
|
|
138
|
-
git commit -m "feat: 기능 B 구현"
|
|
139
|
-
|
|
140
|
-
# 4. 문서 작업 완료 → 커밋
|
|
141
|
-
git add docs/
|
|
142
|
-
git commit -m "docs: 기능 문서 추가"
|
|
143
|
-
|
|
144
|
-
# 5. 푸시
|
|
145
|
-
git push origin main
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
134
|
## 📦 커밋 분리 가이드
|
|
151
135
|
|
|
152
136
|
### 언제 커밋을 분리해야 하나요?
|
|
@@ -159,117 +143,3 @@ git push origin main
|
|
|
159
143
|
| 리팩토링 + 기능 추가 | ✅ 분리 |
|
|
160
144
|
| 동일 기능의 관련 파일들 | 🔄 묶어도 됨 |
|
|
161
145
|
| 동일 기능의 타입 + 구현 | 🔄 묶어도 됨 |
|
|
162
|
-
|
|
163
|
-
### 예시: 사용자 관리 기능 개발
|
|
164
|
-
|
|
165
|
-
```bash
|
|
166
|
-
# 1. 인증 기능 커밋
|
|
167
|
-
git add src/auth/
|
|
168
|
-
git commit -m "feat: 사용자 인증 기능 추가"
|
|
169
|
-
|
|
170
|
-
# 2. 사용자 관리 커밋
|
|
171
|
-
git add src/users/
|
|
172
|
-
git commit -m "feat: 사용자 CRUD 기능 추가"
|
|
173
|
-
|
|
174
|
-
# 3. 유효성 검사 커밋
|
|
175
|
-
git add src/validators/
|
|
176
|
-
git commit -m "feat: 입력값 유효성 검사 추가"
|
|
177
|
-
|
|
178
|
-
# 4. 테스트 커밋
|
|
179
|
-
git add tests/
|
|
180
|
-
git commit -m "test: 사용자 관리 테스트 추가"
|
|
181
|
-
|
|
182
|
-
# 5. 문서 커밋
|
|
183
|
-
git add docs/
|
|
184
|
-
git commit -m "docs: 사용자 API 문서 추가"
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 🌿 브랜치 전략
|
|
190
|
-
|
|
191
|
-
### 간단한 프로젝트
|
|
192
|
-
```
|
|
193
|
-
main ← 모든 작업 직접 커밋
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 팀 프로젝트
|
|
197
|
-
```
|
|
198
|
-
main
|
|
199
|
-
└── feature/기능명
|
|
200
|
-
└── fix/버그명
|
|
201
|
-
└── hotfix/긴급수정
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### 브랜치 명명
|
|
205
|
-
```bash
|
|
206
|
-
feature/user-authentication
|
|
207
|
-
feature/payment-integration
|
|
208
|
-
fix/session-error
|
|
209
|
-
hotfix/security-patch
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## 📋 자주 사용하는 명령어
|
|
215
|
-
|
|
216
|
-
```bash
|
|
217
|
-
# 상태 확인
|
|
218
|
-
git status
|
|
219
|
-
|
|
220
|
-
# 변경 내용 확인
|
|
221
|
-
git diff
|
|
222
|
-
|
|
223
|
-
# 최근 커밋 로그
|
|
224
|
-
git log --oneline -10
|
|
225
|
-
|
|
226
|
-
# 커밋 취소 (작업 내용 유지)
|
|
227
|
-
git reset --soft HEAD~1
|
|
228
|
-
|
|
229
|
-
# 스테이징 취소
|
|
230
|
-
git restore --staged .
|
|
231
|
-
|
|
232
|
-
# 변경사항 임시 저장
|
|
233
|
-
git stash
|
|
234
|
-
git stash pop
|
|
235
|
-
|
|
236
|
-
# 특정 파일만 스테이징
|
|
237
|
-
git add <파일경로>
|
|
238
|
-
|
|
239
|
-
# 대화형 스테이징 (부분 커밋용)
|
|
240
|
-
git add -p
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## 📚 .gitignore
|
|
246
|
-
|
|
247
|
-
```gitignore
|
|
248
|
-
# Dependencies
|
|
249
|
-
node_modules/
|
|
250
|
-
|
|
251
|
-
# Build
|
|
252
|
-
dist/
|
|
253
|
-
.output/
|
|
254
|
-
build/
|
|
255
|
-
|
|
256
|
-
# Environment
|
|
257
|
-
.env
|
|
258
|
-
.env.local
|
|
259
|
-
.env.*.local
|
|
260
|
-
|
|
261
|
-
# IDE
|
|
262
|
-
.idea/
|
|
263
|
-
.vscode/
|
|
264
|
-
*.swp
|
|
265
|
-
|
|
266
|
-
# OS
|
|
267
|
-
.DS_Store
|
|
268
|
-
|
|
269
|
-
# Cache
|
|
270
|
-
.cache/
|
|
271
|
-
.turbo/
|
|
272
|
-
|
|
273
|
-
# Logs
|
|
274
|
-
*.log
|
|
275
|
-
```
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
현재 git 상태를 확인하고, 아래 규칙에 따라 작업을 진행해주세요.
|
|
2
|
+
|
|
3
|
+
**추가 지시사항**: $ARGUMENTS
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 실행 절차
|
|
8
|
+
|
|
9
|
+
### 추가 지시사항이 없는 경우 (기본 동작)
|
|
10
|
+
1. `git status`로 현재 상태 확인
|
|
11
|
+
2. `git diff`로 변경 내용 분석
|
|
12
|
+
3. 스테이징 안 된 변경사항 → `git add`
|
|
13
|
+
4. 커밋 안 된 변경사항 → 논리적 단위로 분리하여 `git commit`
|
|
14
|
+
5. 최종 `git status`로 완료 확인
|
|
15
|
+
|
|
16
|
+
### 추가 지시사항이 있는 경우
|
|
17
|
+
- 사용자의 지시사항을 우선적으로 따름
|
|
18
|
+
- 예: `/git push` → push 진행, `/git 특정파일만 커밋` → 해당 파일만 처리
|
|
2
19
|
|
|
3
20
|
---
|
|
4
21
|
|
|
@@ -19,12 +36,13 @@
|
|
|
19
36
|
|
|
20
37
|
## ✅ ALWAYS (필수)
|
|
21
38
|
|
|
22
|
-
###
|
|
39
|
+
### 커밋 형식
|
|
23
40
|
|
|
24
|
-
```bash
|
|
25
|
-
git add <관련 파일들>
|
|
26
|
-
git commit -m "<prefix>: <설명>"
|
|
27
41
|
```
|
|
42
|
+
<prefix>: <설명>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**한 줄로 간결하게** 작성합니다. 본문이나 푸터는 작성하지 않습니다.
|
|
28
46
|
|
|
29
47
|
### ⭐ 커밋 분리 원칙
|
|
30
48
|
|
|
@@ -48,16 +66,6 @@ git commit -m "docs: API 문서 업데이트"
|
|
|
48
66
|
|
|
49
67
|
---
|
|
50
68
|
|
|
51
|
-
## 📝 커밋 형식
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
<prefix>: <설명>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**한 줄로 간결하게** 작성합니다. 본문이나 푸터는 작성하지 않습니다.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
69
|
## 🏷 Prefix 목록
|
|
62
70
|
|
|
63
71
|
| Prefix | 용도 | 예시 |
|
|
@@ -123,30 +131,6 @@ feat: 로그인, 회원가입, 프로필 기능 추가
|
|
|
123
131
|
|
|
124
132
|
---
|
|
125
133
|
|
|
126
|
-
## 🔄 작업 흐름
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
# 1. 작업 전 최신 코드 동기화
|
|
130
|
-
git pull origin main
|
|
131
|
-
|
|
132
|
-
# 2. 기능 A 작업 완료 → 커밋
|
|
133
|
-
git add src/feature-a/
|
|
134
|
-
git commit -m "feat: 기능 A 구현"
|
|
135
|
-
|
|
136
|
-
# 3. 기능 B 작업 완료 → 커밋
|
|
137
|
-
git add src/feature-b/
|
|
138
|
-
git commit -m "feat: 기능 B 구현"
|
|
139
|
-
|
|
140
|
-
# 4. 문서 작업 완료 → 커밋
|
|
141
|
-
git add docs/
|
|
142
|
-
git commit -m "docs: 기능 문서 추가"
|
|
143
|
-
|
|
144
|
-
# 5. 푸시
|
|
145
|
-
git push origin main
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
134
|
## 📦 커밋 분리 가이드
|
|
151
135
|
|
|
152
136
|
### 언제 커밋을 분리해야 하나요?
|
|
@@ -159,117 +143,3 @@ git push origin main
|
|
|
159
143
|
| 리팩토링 + 기능 추가 | ✅ 분리 |
|
|
160
144
|
| 동일 기능의 관련 파일들 | 🔄 묶어도 됨 |
|
|
161
145
|
| 동일 기능의 타입 + 구현 | 🔄 묶어도 됨 |
|
|
162
|
-
|
|
163
|
-
### 예시: 사용자 관리 기능 개발
|
|
164
|
-
|
|
165
|
-
```bash
|
|
166
|
-
# 1. 인증 기능 커밋
|
|
167
|
-
git add src/auth/
|
|
168
|
-
git commit -m "feat: 사용자 인증 기능 추가"
|
|
169
|
-
|
|
170
|
-
# 2. 사용자 관리 커밋
|
|
171
|
-
git add src/users/
|
|
172
|
-
git commit -m "feat: 사용자 CRUD 기능 추가"
|
|
173
|
-
|
|
174
|
-
# 3. 유효성 검사 커밋
|
|
175
|
-
git add src/validators/
|
|
176
|
-
git commit -m "feat: 입력값 유효성 검사 추가"
|
|
177
|
-
|
|
178
|
-
# 4. 테스트 커밋
|
|
179
|
-
git add tests/
|
|
180
|
-
git commit -m "test: 사용자 관리 테스트 추가"
|
|
181
|
-
|
|
182
|
-
# 5. 문서 커밋
|
|
183
|
-
git add docs/
|
|
184
|
-
git commit -m "docs: 사용자 API 문서 추가"
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 🌿 브랜치 전략
|
|
190
|
-
|
|
191
|
-
### 간단한 프로젝트
|
|
192
|
-
```
|
|
193
|
-
main ← 모든 작업 직접 커밋
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 팀 프로젝트
|
|
197
|
-
```
|
|
198
|
-
main
|
|
199
|
-
└── feature/기능명
|
|
200
|
-
└── fix/버그명
|
|
201
|
-
└── hotfix/긴급수정
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### 브랜치 명명
|
|
205
|
-
```bash
|
|
206
|
-
feature/user-authentication
|
|
207
|
-
feature/payment-integration
|
|
208
|
-
fix/session-error
|
|
209
|
-
hotfix/security-patch
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## 📋 자주 사용하는 명령어
|
|
215
|
-
|
|
216
|
-
```bash
|
|
217
|
-
# 상태 확인
|
|
218
|
-
git status
|
|
219
|
-
|
|
220
|
-
# 변경 내용 확인
|
|
221
|
-
git diff
|
|
222
|
-
|
|
223
|
-
# 최근 커밋 로그
|
|
224
|
-
git log --oneline -10
|
|
225
|
-
|
|
226
|
-
# 커밋 취소 (작업 내용 유지)
|
|
227
|
-
git reset --soft HEAD~1
|
|
228
|
-
|
|
229
|
-
# 스테이징 취소
|
|
230
|
-
git restore --staged .
|
|
231
|
-
|
|
232
|
-
# 변경사항 임시 저장
|
|
233
|
-
git stash
|
|
234
|
-
git stash pop
|
|
235
|
-
|
|
236
|
-
# 특정 파일만 스테이징
|
|
237
|
-
git add <파일경로>
|
|
238
|
-
|
|
239
|
-
# 대화형 스테이징 (부분 커밋용)
|
|
240
|
-
git add -p
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## 📚 .gitignore
|
|
246
|
-
|
|
247
|
-
```gitignore
|
|
248
|
-
# Dependencies
|
|
249
|
-
node_modules/
|
|
250
|
-
|
|
251
|
-
# Build
|
|
252
|
-
dist/
|
|
253
|
-
.output/
|
|
254
|
-
build/
|
|
255
|
-
|
|
256
|
-
# Environment
|
|
257
|
-
.env
|
|
258
|
-
.env.local
|
|
259
|
-
.env.*.local
|
|
260
|
-
|
|
261
|
-
# IDE
|
|
262
|
-
.idea/
|
|
263
|
-
.vscode/
|
|
264
|
-
*.swp
|
|
265
|
-
|
|
266
|
-
# OS
|
|
267
|
-
.DS_Store
|
|
268
|
-
|
|
269
|
-
# Cache
|
|
270
|
-
.cache/
|
|
271
|
-
.turbo/
|
|
272
|
-
|
|
273
|
-
# Logs
|
|
274
|
-
*.log
|
|
275
|
-
```
|
|
@@ -277,21 +277,19 @@ export const Route = createFileRoute('/users')({
|
|
|
277
277
|
### TanStack Query (서버 연동 시 필수)
|
|
278
278
|
```tsx
|
|
279
279
|
// ✅ 데이터 조회: useQuery 필수
|
|
280
|
-
const getPosts = useServerFn(getServerPosts)
|
|
281
280
|
const { data } = useQuery({
|
|
282
|
-
queryKey: ['
|
|
283
|
-
queryFn: () =>
|
|
281
|
+
queryKey: ['posts'],
|
|
282
|
+
queryFn: () => getServerPosts(),
|
|
284
283
|
})
|
|
285
284
|
|
|
286
285
|
// ✅ 데이터 변경: useMutation 필수
|
|
287
|
-
const createPostFn = useServerFn(createPost)
|
|
288
286
|
const mutation = useMutation({
|
|
289
|
-
mutationFn:
|
|
290
|
-
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['
|
|
287
|
+
mutationFn: createPost,
|
|
288
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['posts'] }),
|
|
291
289
|
})
|
|
292
290
|
|
|
293
|
-
// ❌ 금지: Server Function 직접 호출
|
|
294
|
-
// useEffect(() => {
|
|
291
|
+
// ❌ 금지: Server Function을 TanStack Query 없이 직접 호출
|
|
292
|
+
// useEffect(() => { getServerPosts().then(setData) }, [])
|
|
295
293
|
```
|
|
296
294
|
|
|
297
295
|
---
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
현재 git 상태를 확인하고, 아래 규칙에 따라 작업을 진행해주세요.
|
|
2
|
+
|
|
3
|
+
**추가 지시사항**: $ARGUMENTS
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 실행 절차
|
|
8
|
+
|
|
9
|
+
### 추가 지시사항이 없는 경우 (기본 동작)
|
|
10
|
+
1. `git status`로 현재 상태 확인
|
|
11
|
+
2. `git diff`로 변경 내용 분석
|
|
12
|
+
3. 스테이징 안 된 변경사항 → `git add`
|
|
13
|
+
4. 커밋 안 된 변경사항 → 논리적 단위로 분리하여 `git commit`
|
|
14
|
+
5. 최종 `git status`로 완료 확인
|
|
15
|
+
|
|
16
|
+
### 추가 지시사항이 있는 경우
|
|
17
|
+
- 사용자의 지시사항을 우선적으로 따름
|
|
18
|
+
- 예: `/git push` → push 진행, `/git 특정파일만 커밋` → 해당 파일만 처리
|
|
2
19
|
|
|
3
20
|
---
|
|
4
21
|
|
|
@@ -19,12 +36,13 @@
|
|
|
19
36
|
|
|
20
37
|
## ✅ ALWAYS (필수)
|
|
21
38
|
|
|
22
|
-
###
|
|
39
|
+
### 커밋 형식
|
|
23
40
|
|
|
24
|
-
```bash
|
|
25
|
-
git add <관련 파일들>
|
|
26
|
-
git commit -m "<prefix>: <설명>"
|
|
27
41
|
```
|
|
42
|
+
<prefix>: <설명>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**한 줄로 간결하게** 작성합니다. 본문이나 푸터는 작성하지 않습니다.
|
|
28
46
|
|
|
29
47
|
### ⭐ 커밋 분리 원칙
|
|
30
48
|
|
|
@@ -48,16 +66,6 @@ git commit -m "docs: API 문서 업데이트"
|
|
|
48
66
|
|
|
49
67
|
---
|
|
50
68
|
|
|
51
|
-
## 📝 커밋 형식
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
<prefix>: <설명>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**한 줄로 간결하게** 작성합니다. 본문이나 푸터는 작성하지 않습니다.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
69
|
## 🏷 Prefix 목록
|
|
62
70
|
|
|
63
71
|
| Prefix | 용도 | 예시 |
|
|
@@ -123,30 +131,6 @@ feat: 로그인, 회원가입, 프로필 기능 추가
|
|
|
123
131
|
|
|
124
132
|
---
|
|
125
133
|
|
|
126
|
-
## 🔄 작업 흐름
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
# 1. 작업 전 최신 코드 동기화
|
|
130
|
-
git pull origin main
|
|
131
|
-
|
|
132
|
-
# 2. 기능 A 작업 완료 → 커밋
|
|
133
|
-
git add src/feature-a/
|
|
134
|
-
git commit -m "feat: 기능 A 구현"
|
|
135
|
-
|
|
136
|
-
# 3. 기능 B 작업 완료 → 커밋
|
|
137
|
-
git add src/feature-b/
|
|
138
|
-
git commit -m "feat: 기능 B 구현"
|
|
139
|
-
|
|
140
|
-
# 4. 문서 작업 완료 → 커밋
|
|
141
|
-
git add docs/
|
|
142
|
-
git commit -m "docs: 기능 문서 추가"
|
|
143
|
-
|
|
144
|
-
# 5. 푸시
|
|
145
|
-
git push origin main
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
134
|
## 📦 커밋 분리 가이드
|
|
151
135
|
|
|
152
136
|
### 언제 커밋을 분리해야 하나요?
|
|
@@ -159,117 +143,3 @@ git push origin main
|
|
|
159
143
|
| 리팩토링 + 기능 추가 | ✅ 분리 |
|
|
160
144
|
| 동일 기능의 관련 파일들 | 🔄 묶어도 됨 |
|
|
161
145
|
| 동일 기능의 타입 + 구현 | 🔄 묶어도 됨 |
|
|
162
|
-
|
|
163
|
-
### 예시: 사용자 관리 기능 개발
|
|
164
|
-
|
|
165
|
-
```bash
|
|
166
|
-
# 1. 인증 기능 커밋
|
|
167
|
-
git add src/auth/
|
|
168
|
-
git commit -m "feat: 사용자 인증 기능 추가"
|
|
169
|
-
|
|
170
|
-
# 2. 사용자 관리 커밋
|
|
171
|
-
git add src/users/
|
|
172
|
-
git commit -m "feat: 사용자 CRUD 기능 추가"
|
|
173
|
-
|
|
174
|
-
# 3. 유효성 검사 커밋
|
|
175
|
-
git add src/validators/
|
|
176
|
-
git commit -m "feat: 입력값 유효성 검사 추가"
|
|
177
|
-
|
|
178
|
-
# 4. 테스트 커밋
|
|
179
|
-
git add tests/
|
|
180
|
-
git commit -m "test: 사용자 관리 테스트 추가"
|
|
181
|
-
|
|
182
|
-
# 5. 문서 커밋
|
|
183
|
-
git add docs/
|
|
184
|
-
git commit -m "docs: 사용자 API 문서 추가"
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 🌿 브랜치 전략
|
|
190
|
-
|
|
191
|
-
### 간단한 프로젝트
|
|
192
|
-
```
|
|
193
|
-
main ← 모든 작업 직접 커밋
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 팀 프로젝트
|
|
197
|
-
```
|
|
198
|
-
main
|
|
199
|
-
└── feature/기능명
|
|
200
|
-
└── fix/버그명
|
|
201
|
-
└── hotfix/긴급수정
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### 브랜치 명명
|
|
205
|
-
```bash
|
|
206
|
-
feature/user-authentication
|
|
207
|
-
feature/payment-integration
|
|
208
|
-
fix/session-error
|
|
209
|
-
hotfix/security-patch
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## 📋 자주 사용하는 명령어
|
|
215
|
-
|
|
216
|
-
```bash
|
|
217
|
-
# 상태 확인
|
|
218
|
-
git status
|
|
219
|
-
|
|
220
|
-
# 변경 내용 확인
|
|
221
|
-
git diff
|
|
222
|
-
|
|
223
|
-
# 최근 커밋 로그
|
|
224
|
-
git log --oneline -10
|
|
225
|
-
|
|
226
|
-
# 커밋 취소 (작업 내용 유지)
|
|
227
|
-
git reset --soft HEAD~1
|
|
228
|
-
|
|
229
|
-
# 스테이징 취소
|
|
230
|
-
git restore --staged .
|
|
231
|
-
|
|
232
|
-
# 변경사항 임시 저장
|
|
233
|
-
git stash
|
|
234
|
-
git stash pop
|
|
235
|
-
|
|
236
|
-
# 특정 파일만 스테이징
|
|
237
|
-
git add <파일경로>
|
|
238
|
-
|
|
239
|
-
# 대화형 스테이징 (부분 커밋용)
|
|
240
|
-
git add -p
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## 📚 .gitignore
|
|
246
|
-
|
|
247
|
-
```gitignore
|
|
248
|
-
# Dependencies
|
|
249
|
-
node_modules/
|
|
250
|
-
|
|
251
|
-
# Build
|
|
252
|
-
dist/
|
|
253
|
-
.output/
|
|
254
|
-
build/
|
|
255
|
-
|
|
256
|
-
# Environment
|
|
257
|
-
.env
|
|
258
|
-
.env.local
|
|
259
|
-
.env.*.local
|
|
260
|
-
|
|
261
|
-
# IDE
|
|
262
|
-
.idea/
|
|
263
|
-
.vscode/
|
|
264
|
-
*.swp
|
|
265
|
-
|
|
266
|
-
# OS
|
|
267
|
-
.DS_Store
|
|
268
|
-
|
|
269
|
-
# Cache
|
|
270
|
-
.cache/
|
|
271
|
-
.turbo/
|
|
272
|
-
|
|
273
|
-
# Logs
|
|
274
|
-
*.log
|
|
275
|
-
```
|
|
@@ -304,7 +304,6 @@ const UsersPage = (): JSX.Element => {
|
|
|
304
304
|
import { useState, useMemo, useEffect, useCallback } from 'react'
|
|
305
305
|
import { useParams, useNavigate } from '@tanstack/react-router'
|
|
306
306
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
307
|
-
import { useServerFn } from '@tanstack/react-start'
|
|
308
307
|
import { useAuthStore } from '@/stores/auth'
|
|
309
308
|
import { getUsers, createUser, deleteUser } from '@/services/user'
|
|
310
309
|
import type { User } from '@/types'
|
|
@@ -339,24 +338,20 @@ export const useUsers = (): UseUsersReturn => {
|
|
|
339
338
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
340
339
|
// 3. React Query (useQuery → useMutation)
|
|
341
340
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
342
|
-
const getUsersFn = useServerFn(getUsers)
|
|
343
|
-
const createUserFn = useServerFn(createUser)
|
|
344
|
-
const deleteUserFn = useServerFn(deleteUser)
|
|
345
|
-
|
|
346
341
|
const { data: users, isLoading, error } = useQuery({
|
|
347
342
|
queryKey: ['users'],
|
|
348
|
-
queryFn: () =>
|
|
343
|
+
queryFn: () => getUsers(),
|
|
349
344
|
})
|
|
350
345
|
|
|
351
346
|
const createMutation = useMutation({
|
|
352
|
-
mutationFn:
|
|
347
|
+
mutationFn: createUser,
|
|
353
348
|
onSuccess: () => {
|
|
354
349
|
queryClient.invalidateQueries({ queryKey: ['users'] })
|
|
355
350
|
},
|
|
356
351
|
})
|
|
357
352
|
|
|
358
353
|
const deleteMutation = useMutation({
|
|
359
|
-
mutationFn:
|
|
354
|
+
mutationFn: deleteUser,
|
|
360
355
|
onSuccess: () => {
|
|
361
356
|
queryClient.invalidateQueries({ queryKey: ['users'] })
|
|
362
357
|
},
|
|
@@ -226,7 +226,7 @@ export const clientEnv = parseClientEnv()
|
|
|
226
226
|
```typescript
|
|
227
227
|
// app/server-functions/users.ts
|
|
228
228
|
import { createServerFn } from '@tanstack/react-start'
|
|
229
|
-
import { getServerEnv } from '
|
|
229
|
+
import { getServerEnv } from '@/config/env'
|
|
230
230
|
|
|
231
231
|
export const getUsers = createServerFn({ method: 'GET' })
|
|
232
232
|
.handler(async () => {
|
|
@@ -248,7 +248,7 @@ export const getUsers = createServerFn({ method: 'GET' })
|
|
|
248
248
|
|
|
249
249
|
```tsx
|
|
250
250
|
// app/components/AppHeader.tsx
|
|
251
|
-
import { clientEnv } from '
|
|
251
|
+
import { clientEnv } from '@/config/env'
|
|
252
252
|
|
|
253
253
|
export const AppHeader = () => {
|
|
254
254
|
return (
|
|
@@ -282,7 +282,7 @@ const appName = import.meta.env.VITE_APP_NAME // ✅ VITE_ 접두사만
|
|
|
282
282
|
|
|
283
283
|
```typescript
|
|
284
284
|
// app/lib/auth.ts
|
|
285
|
-
import { getServerEnv } from '
|
|
285
|
+
import { getServerEnv } from '@/config/env'
|
|
286
286
|
|
|
287
287
|
export const getAuthConfig = () => {
|
|
288
288
|
const env = getServerEnv()
|
|
@@ -103,7 +103,7 @@ await authClient.twoFactor.disable({
|
|
|
103
103
|
```tsx
|
|
104
104
|
// pages/two-factor.tsx
|
|
105
105
|
import { useState } from 'react'
|
|
106
|
-
import { authClient } from '
|
|
106
|
+
import { authClient } from '@/lib/auth-client'
|
|
107
107
|
|
|
108
108
|
export default function TwoFactorPage() {
|
|
109
109
|
const [code, setCode] = useState('')
|
|
@@ -111,7 +111,7 @@ export const auth = betterAuth({
|
|
|
111
111
|
|
|
112
112
|
// Server Function에서 사용
|
|
113
113
|
import { createServerFn } from '@tanstack/react-start'
|
|
114
|
-
import { auth } from '
|
|
114
|
+
import { auth } from '@/lib/auth'
|
|
115
115
|
|
|
116
116
|
export const getSession = createServerFn({ method: 'GET' })
|
|
117
117
|
.handler(async ({ request }) => {
|
|
@@ -113,7 +113,7 @@ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
|
|
113
113
|
|
|
114
114
|
// Server Function에서 사용
|
|
115
115
|
import { createServerFn } from '@tanstack/react-start'
|
|
116
|
-
import { prisma } from '
|
|
116
|
+
import { prisma } from '@/lib/prisma'
|
|
117
117
|
|
|
118
118
|
export const getUsers = createServerFn({ method: 'GET' })
|
|
119
119
|
.handler(async () => {
|
|
@@ -52,15 +52,12 @@ const queryClient = new QueryClient({
|
|
|
52
52
|
|
|
53
53
|
```tsx
|
|
54
54
|
import { useQuery } from '@tanstack/react-query'
|
|
55
|
-
import {
|
|
56
|
-
import { getServerPosts } from '~/lib/server-functions'
|
|
55
|
+
import { getServerPosts } from '@/lib/server-functions'
|
|
57
56
|
|
|
58
57
|
function PostList() {
|
|
59
|
-
const getPosts = useServerFn(getServerPosts)
|
|
60
|
-
|
|
61
58
|
const { data, isLoading, error } = useQuery({
|
|
62
59
|
queryKey: ['posts'],
|
|
63
|
-
queryFn: () =>
|
|
60
|
+
queryFn: () => getServerPosts(),
|
|
64
61
|
})
|
|
65
62
|
|
|
66
63
|
if (isLoading) return <div>Loading...</div>
|
|
@@ -159,7 +159,7 @@ export const auth = betterAuth({
|
|
|
159
159
|
|
|
160
160
|
// Server Function에서 사용
|
|
161
161
|
import { createServerFn } from '@tanstack/react-start'
|
|
162
|
-
import { auth } from '
|
|
162
|
+
import { auth } from '@/lib/auth'
|
|
163
163
|
|
|
164
164
|
export const getSession = createServerFn({ method: 'GET' })
|
|
165
165
|
.handler(async ({ request }) => {
|
|
@@ -93,16 +93,13 @@ export const submitForm = createServerFn({ method: 'POST' })
|
|
|
93
93
|
### ✅ 올바른 패턴: useQuery 사용 (데이터 조회)
|
|
94
94
|
|
|
95
95
|
```tsx
|
|
96
|
-
import { useServerFn } from '@tanstack/react-start'
|
|
97
96
|
import { useQuery } from '@tanstack/react-query'
|
|
98
|
-
import { getServerPosts } from '
|
|
97
|
+
import { getServerPosts } from '@/lib/server-functions'
|
|
99
98
|
|
|
100
99
|
function PostList() {
|
|
101
|
-
const getPosts = useServerFn(getServerPosts)
|
|
102
|
-
|
|
103
100
|
const { data, isLoading, error } = useQuery({
|
|
104
101
|
queryKey: ['posts'],
|
|
105
|
-
queryFn: () =>
|
|
102
|
+
queryFn: () => getServerPosts(),
|
|
106
103
|
})
|
|
107
104
|
|
|
108
105
|
if (isLoading) return <div>Loading...</div>
|
|
@@ -121,16 +118,14 @@ function PostList() {
|
|
|
121
118
|
### ✅ 올바른 패턴: useMutation 사용 (데이터 변경)
|
|
122
119
|
|
|
123
120
|
```tsx
|
|
124
|
-
import { useServerFn } from '@tanstack/react-start'
|
|
125
121
|
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
|
126
|
-
import { createPost, deletePost } from '
|
|
122
|
+
import { createPost, deletePost } from '@/lib/server-functions'
|
|
127
123
|
|
|
128
124
|
function PostForm() {
|
|
129
125
|
const queryClient = useQueryClient()
|
|
130
|
-
const createPostFn = useServerFn(createPost)
|
|
131
126
|
|
|
132
127
|
const mutation = useMutation({
|
|
133
|
-
mutationFn: (data: { title: string; content: string }) =>
|
|
128
|
+
mutationFn: (data: { title: string; content: string }) => createPost({ data }),
|
|
134
129
|
onSuccess: () => {
|
|
135
130
|
// 관련 쿼리 무효화로 데이터 동기화
|
|
136
131
|
queryClient.invalidateQueries({ queryKey: ['posts'] })
|
|
@@ -181,6 +176,92 @@ function BadExample() {
|
|
|
181
176
|
}
|
|
182
177
|
```
|
|
183
178
|
|
|
179
|
+
## ⚠️ 함수 분리 시 유의사항
|
|
180
|
+
|
|
181
|
+
Server Function 내부 로직을 별도 함수로 분리할 때 반드시 아래 규칙을 따르세요.
|
|
182
|
+
|
|
183
|
+
### 규칙
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
1. 분리한 함수는 createServerFn 내부에서만 호출
|
|
187
|
+
2. 분리한 함수는 createServerFn으로 감싸지 않음
|
|
188
|
+
3. 분리한 함수는 index.ts에서 export 금지 (프론트엔드 import 방지)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### ✅ 올바른 패턴
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// services/user/mutations.ts
|
|
195
|
+
|
|
196
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
197
|
+
// 내부 헬퍼 함수 (export 금지!)
|
|
198
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
199
|
+
const validateUserData = async (email: string) => {
|
|
200
|
+
const existing = await prisma.user.findUnique({ where: { email } })
|
|
201
|
+
if (existing) throw new Error('Email already exists')
|
|
202
|
+
return true
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const sendWelcomeEmail = async (userId: string, email: string) => {
|
|
206
|
+
await emailService.send({
|
|
207
|
+
to: email,
|
|
208
|
+
template: 'welcome',
|
|
209
|
+
data: { userId },
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
214
|
+
// Server Function (export 가능)
|
|
215
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
216
|
+
export const createUser = createServerFn({ method: 'POST' })
|
|
217
|
+
.inputValidator(createUserSchema)
|
|
218
|
+
.handler(async ({ data }) => {
|
|
219
|
+
// 내부 헬퍼 함수 호출
|
|
220
|
+
await validateUserData(data.email)
|
|
221
|
+
|
|
222
|
+
const user = await prisma.user.create({ data })
|
|
223
|
+
|
|
224
|
+
// 내부 헬퍼 함수 호출
|
|
225
|
+
await sendWelcomeEmail(user.id, user.email)
|
|
226
|
+
|
|
227
|
+
return user
|
|
228
|
+
})
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// services/user/index.ts
|
|
233
|
+
|
|
234
|
+
// ✅ Server Function만 export
|
|
235
|
+
export { createUser, updateUser, deleteUser } from './mutations'
|
|
236
|
+
export { getUsers, getUserById } from './queries'
|
|
237
|
+
|
|
238
|
+
// ❌ 내부 헬퍼 함수는 export 금지!
|
|
239
|
+
// export { validateUserData, sendWelcomeEmail } from './mutations'
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### ❌ 잘못된 패턴
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// ❌ 분리한 함수를 createServerFn으로 감싸지 마세요
|
|
246
|
+
export const validateUserData = createServerFn({ method: 'POST' })
|
|
247
|
+
.handler(async ({ data }) => {
|
|
248
|
+
// ...
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
// ❌ 내부 헬퍼 함수를 export 하지 마세요
|
|
252
|
+
export const sendWelcomeEmail = async (userId: string) => {
|
|
253
|
+
// 프론트엔드에서 import 가능해져 보안 위험!
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 이유
|
|
258
|
+
|
|
259
|
+
- **보안**: 내부 로직이 프론트엔드 번들에 포함되지 않음
|
|
260
|
+
- **명확한 API**: Server Function만 외부에 노출되어 API 경계가 명확함
|
|
261
|
+
- **트리 쉐이킹**: export하지 않은 함수는 번들에서 제거됨
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
184
265
|
## 보안 패턴
|
|
185
266
|
|
|
186
267
|
### 서버 전용 데이터 보호
|