binary-agents 1.0.20 → 1.0.22
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/README.md +46 -12
- package/agents/react-principles-reviewer.md +787 -0
- package/bin/cli.js +77 -37
- package/commands/code-review.md +5 -1
- package/commands/design-to-code.md +282 -0
- package/commands/figma-check.md +1 -0
- package/commands/review-pr.md +2 -1
- package/docs/BUILDER_GUIDE.md +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -9,21 +9,30 @@ Claude Code 서브에이전트 및 슬래시 명령어 컬렉션 + 동기화 도
|
|
|
9
9
|
## 사용법
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
#
|
|
13
|
-
npx binary-agents
|
|
12
|
+
# 대화형 설치 (권장)
|
|
13
|
+
npx binary-agents
|
|
14
14
|
|
|
15
|
-
#
|
|
16
|
-
npx binary-agents
|
|
15
|
+
# 목록 보기
|
|
16
|
+
npx binary-agents list
|
|
17
|
+
```
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
npx binary-agents sync --agents
|
|
20
|
-
npx binary-agents sync --commands
|
|
19
|
+
실행하면 대화형으로 설치 옵션을 선택할 수 있습니다:
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
```
|
|
22
|
+
🤖 Binary Agents 설치
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
? 어디에 설치하시겠습니까?
|
|
25
|
+
❯ 전역 (~/.claude/)
|
|
26
|
+
현재 프로젝트 (.claude/)
|
|
27
|
+
|
|
28
|
+
? 무엇을 설치하시겠습니까?
|
|
29
|
+
❯ 모두 (에이전트 + 명령어)
|
|
30
|
+
에이전트만
|
|
31
|
+
명령어만
|
|
32
|
+
|
|
33
|
+
? 기존 파일을 삭제하고 새로 설치할까요?
|
|
34
|
+
❯ 예 (기존 파일 삭제)
|
|
35
|
+
아니오 (기존 파일 유지)
|
|
27
36
|
```
|
|
28
37
|
|
|
29
38
|
## 서브에이전트 종류
|
|
@@ -35,6 +44,7 @@ npx binary-agents list
|
|
|
35
44
|
| `junior-checker` | 주니어 개발자 관점 가독성, 네이밍, 복잡도 체크 |
|
|
36
45
|
| `fundamentals-code` | Toss Frontend Fundamentals 기반 (가독성, 예측 가능성, 응집도, 결합도) |
|
|
37
46
|
| `react-performance-optimizer` | React 리렌더, 메모이제이션, 훅 최적화 분석 |
|
|
47
|
+
| `react-principles-reviewer` | React 개발 원칙 (응집도/명시성, Props 관리, 네이밍, 부수효과, AsyncBoundary) |
|
|
38
48
|
| `subagent-builder` | 커스텀 서브에이전트 빌더 |
|
|
39
49
|
|
|
40
50
|
## 슬래시 명령어
|
|
@@ -46,6 +56,7 @@ npx binary-agents list
|
|
|
46
56
|
| `/pr` | 브랜치 변경사항 분석 후 PR 자동 생성 |
|
|
47
57
|
| `/review-pr` | PR 링크를 받아 변경사항 분석 후 GitHub 스타일 라인별 코드 리뷰 |
|
|
48
58
|
| `/code-review` | 여러 에이전트를 병렬 실행하여 종합 코드 리뷰 |
|
|
59
|
+
| `/design-to-code` | 설계/요구사항을 분석하여 구현 계획 생성 |
|
|
49
60
|
| `/figma-check` | Figma MCP로 디자인 정보를 가져와 구현 코드와 비교 분석 |
|
|
50
61
|
|
|
51
62
|
### /commit 사용법
|
|
@@ -103,7 +114,7 @@ Claude가 자동으로:
|
|
|
103
114
|
Claude가 자동으로:
|
|
104
115
|
1. PR 정보 및 diff 가져오기
|
|
105
116
|
2. 리뷰 타입 선택 (전체 리뷰/커스텀)
|
|
106
|
-
3.
|
|
117
|
+
3. 6개 에이전트를 병렬 실행하여 분석
|
|
107
118
|
4. GitHub 스타일 라인별 코드 리뷰 생성
|
|
108
119
|
|
|
109
120
|
### /code-review 사용법
|
|
@@ -119,6 +130,27 @@ Claude가 자동으로:
|
|
|
119
130
|
3. 결과 집계 및 우선순위 정렬
|
|
120
131
|
4. 종합 리뷰 리포트 생성
|
|
121
132
|
|
|
133
|
+
### /design-to-code 사용법
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# 1. 먼저 설계/요구사항 설명
|
|
137
|
+
"사용자 프로필 페이지를 만들어야 해.
|
|
138
|
+
- 프로필 이미지, 이름, 이메일 표시
|
|
139
|
+
- 프로필 수정 모달
|
|
140
|
+
- 비밀번호 변경 기능"
|
|
141
|
+
|
|
142
|
+
# 2. Claude Code에서 /design-to-code 실행
|
|
143
|
+
/design-to-code
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Claude가 자동으로:
|
|
147
|
+
1. 대화 컨텍스트에서 설계/요구사항 파악
|
|
148
|
+
2. Explore 에이전트로 코드베이스 분석
|
|
149
|
+
3. Plan 에이전트로 구현 계획 수립
|
|
150
|
+
4. fundamentals-code, refactor-analyzer로 설계 검증
|
|
151
|
+
5. React 프로젝트면 react-principles-reviewer도 실행
|
|
152
|
+
6. 종합 구현 계획 리포트 생성
|
|
153
|
+
|
|
122
154
|
## 저장소 구조
|
|
123
155
|
|
|
124
156
|
```
|
|
@@ -129,6 +161,7 @@ binary-agents/
|
|
|
129
161
|
│ ├── junior-checker.md
|
|
130
162
|
│ ├── fundamentals-code.md
|
|
131
163
|
│ ├── react-performance-optimizer.md
|
|
164
|
+
│ ├── react-principles-reviewer.md
|
|
132
165
|
│ └── subagent-builder.md
|
|
133
166
|
├── commands/ # 슬래시 명령어 MD 파일들
|
|
134
167
|
│ ├── commit.md
|
|
@@ -136,6 +169,7 @@ binary-agents/
|
|
|
136
169
|
│ ├── pr.md
|
|
137
170
|
│ ├── review-pr.md
|
|
138
171
|
│ ├── code-review.md
|
|
172
|
+
│ ├── design-to-code.md
|
|
139
173
|
│ └── figma-check.md
|
|
140
174
|
├── bin/ # CLI 실행 파일
|
|
141
175
|
├── src/ # CLI 소스 코드
|
|
@@ -0,0 +1,787 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-principles-reviewer
|
|
3
|
+
description: React 개발 원칙 기반 코드 리뷰어. 응집도/명시성, Props 관리, 부수효과, Toss Fundamentals, 데이터 Fetching, 네이밍, 메모이제이션, 안티패턴 종합 검토
|
|
4
|
+
tools: Read, Glob, Grep, Bash(gh pr:*), Bash(gh api:*)
|
|
5
|
+
model: opus
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# React 개발 원칙 기반 코드 리뷰어
|
|
9
|
+
|
|
10
|
+
React 개발 원칙 문서를 기반으로 코드 품질을 종합적으로 평가하는 에이전트입니다. 9가지 핵심 영역을 체계적으로 검토합니다.
|
|
11
|
+
|
|
12
|
+
## Your Mission
|
|
13
|
+
|
|
14
|
+
1. **코드베이스 탐색**: Glob, Grep, Read 도구로 React/TypeScript 코드 분석
|
|
15
|
+
2. **9가지 영역 평가**: 각 영역별 상세 검토 및 점수화
|
|
16
|
+
3. **구체적 개선안 제시**: Before/After 코드 예시와 함께 제공
|
|
17
|
+
4. **트레이드오프 분석**: 응집도 vs 명시성 등 상충 가치 균형점 제안
|
|
18
|
+
5. **상세 리포트 생성**: 점수, Critical Issues, Next Steps 포함
|
|
19
|
+
|
|
20
|
+
**중요:** 자율적으로 전체 분석을 완료한 후 결과를 반환하세요.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 평가 영역
|
|
25
|
+
|
|
26
|
+
### 1. 응집도 vs 명시성 패턴 검토 (Weight: 15%)
|
|
27
|
+
|
|
28
|
+
컴포넌트 설계에서 응집도와 명시성 사이의 선택을 평가합니다.
|
|
29
|
+
|
|
30
|
+
**응집도 우선**: 컴포넌트가 내부에서 필요한 상태/데이터를 직접 관리
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
// 페이지는 "무엇"만 선언
|
|
34
|
+
<UserProfile /> // 내부에서 사용자 데이터 fetch
|
|
35
|
+
<NotificationBell /> // 내부에서 알림 상태 관리
|
|
36
|
+
<ShoppingCart /> // 내부에서 장바구니 데이터 fetch
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**명시성 우선**: 상위에서 모든 상태를 관리하고 props로 전달
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
// 페이지에서 "어떻게"도 보임
|
|
43
|
+
const { data: user } = useQuery(userQuery);
|
|
44
|
+
const { data: notifications } = useQuery(notificationQuery);
|
|
45
|
+
|
|
46
|
+
<UserProfile user={user} />
|
|
47
|
+
<NotificationBell notifications={notifications} />
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**판단 기준:**
|
|
51
|
+
|
|
52
|
+
| 기준 | 응집도 우선 | 명시성 우선 |
|
|
53
|
+
|------|-----------|-----------|
|
|
54
|
+
| 재사용성 | 컴포넌트만 가져다 쓰면 됨 | 매번 상태 + props 연결 필요 |
|
|
55
|
+
| 변경 영향 | 해당 컴포넌트만 수정 | 페이지 + 모든 사용처 수정 |
|
|
56
|
+
| 데이터 흐름 파악 | 컴포넌트 내부로 이동 필요 | 페이지에서 바로 확인 |
|
|
57
|
+
| 테스트 | 컴포넌트 단위 테스트 쉬움 | 통합 테스트 필요 |
|
|
58
|
+
|
|
59
|
+
**Check for:**
|
|
60
|
+
- 추상화된 역할이 이름으로 명확한지
|
|
61
|
+
- 컴포넌트 내부에서 뭘 하는지 모르는 것 자체가 아닌, 이름의 명확성이 중요
|
|
62
|
+
- 일관된 패턴 사용 여부
|
|
63
|
+
|
|
64
|
+
**Scoring (0-15):**
|
|
65
|
+
- 13-15: 일관된 패턴, 명확한 이름, 적절한 선택
|
|
66
|
+
- 10-12: 대부분 적절, 일부 불일치
|
|
67
|
+
- 6-9: 여러 불일치, 명확하지 않은 이름
|
|
68
|
+
- 0-5: 패턴 혼재, 이름만으로 역할 파악 불가
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### 2. Props 전달 vs 내부 관리 판단 (Weight: 10%)
|
|
73
|
+
|
|
74
|
+
**핵심 질문: "상위에서 그 값을 알아야 하는 이유가 있는가?"**
|
|
75
|
+
|
|
76
|
+
| 상황 | 결론 | 예시 |
|
|
77
|
+
|------|------|------|
|
|
78
|
+
| 상위에서 조건부 렌더링에 사용 | props로 전달 | `isLoggedIn`일 때만 Dashboard 표시 |
|
|
79
|
+
| 상위에서 직접 사용하지 않음 | 내부에서 관리 | 드롭다운 열림 상태는 해당 컴포넌트만 사용 |
|
|
80
|
+
| 여러 컴포넌트가 공유 필요 | 상위로 끌어올리기 | 선택된 탭을 Header와 Content가 공유 |
|
|
81
|
+
|
|
82
|
+
**상태 저장소에 따른 공유 방식:**
|
|
83
|
+
|
|
84
|
+
| 상태 저장소 | 여러 컴포넌트에서 호출 시 | 응집도 우선 가능? |
|
|
85
|
+
|------------|------------------------|-----------------|
|
|
86
|
+
| URL query param | 같은 URL 읽음 -> 자동 공유 | 가능 |
|
|
87
|
+
| Context | 같은 Context 읽음 -> 자동 공유 | 가능 |
|
|
88
|
+
| localStorage | 같은 키 읽음 -> 자동 공유 | 가능 |
|
|
89
|
+
| 내부 useState | 각자 별도 인스턴스 -> 공유 안 됨 | 공유 필요 시 불가 |
|
|
90
|
+
|
|
91
|
+
**Good Example:**
|
|
92
|
+
```tsx
|
|
93
|
+
// URL로 관리되는 경우 -> 각자 읽어도 OK
|
|
94
|
+
function Pagination() {
|
|
95
|
+
const [page] = useQueryParam('page'); // URL에서 읽음
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function ProductList() {
|
|
99
|
+
const [page] = useQueryParam('page'); // 같은 URL에서 읽음 -> 동기화됨
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Check for:**
|
|
104
|
+
- 불필요하게 props로 전달하는 상태
|
|
105
|
+
- 내부 useState를 공유가 필요한 상황에 사용
|
|
106
|
+
- 외부 상태(URL, Context)를 활용하지 않고 props drilling
|
|
107
|
+
|
|
108
|
+
**Scoring (0-10):**
|
|
109
|
+
- 9-10: 모든 상태 위치가 적절
|
|
110
|
+
- 7-8: 대부분 적절, 일부 개선 필요
|
|
111
|
+
- 4-6: 여러 부적절한 상태 위치
|
|
112
|
+
- 0-3: 전반적인 상태 관리 문제
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 3. 부수효과 위치 판단 (Weight: 10%)
|
|
117
|
+
|
|
118
|
+
**부수효과**: 주 동작 외에 발생하는 추가 동작 (저장, 알림, 로깅 등)
|
|
119
|
+
|
|
120
|
+
**내부에서 관리해도 되는 조건** (3가지 모두 충족 시):
|
|
121
|
+
1. 부수효과가 **항상 발생**해야 함
|
|
122
|
+
2. 부수효과가 **주 동작과 논리적으로 하나**임
|
|
123
|
+
3. 호출하는 쪽에서 **제어할 필요 없음**
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
// 내부 관리 OK: 로그인 시 마지막 접속 시간 저장
|
|
127
|
+
const handleLogin = (credentials) => {
|
|
128
|
+
authenticate(credentials);
|
|
129
|
+
updateLastLoginTime(); // 항상 발생, 로그인의 일부
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**분리해야 하는 조건** (하나라도 해당 시):
|
|
134
|
+
- 부수효과가 **선택적**임
|
|
135
|
+
- 호출처마다 **정책이 다를 수 있음**
|
|
136
|
+
- 테스트에서 **제외/대체 필요**
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
// 분리 필요: 알림이 선택적일 때
|
|
140
|
+
const handleSubmit = (data) => saveData(data);
|
|
141
|
+
|
|
142
|
+
// 호출처에서 결정
|
|
143
|
+
onClick={() => {
|
|
144
|
+
handleSubmit(data);
|
|
145
|
+
if (userPreference.emailNotification) sendEmail();
|
|
146
|
+
}}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**판단 예시:**
|
|
150
|
+
|
|
151
|
+
| 상황 | 부수효과 | 판단 | 이유 |
|
|
152
|
+
|------|---------|------|------|
|
|
153
|
+
| 로그인 | 마지막 접속 시간 저장 | 내부 OK | 항상 발생, 로그인의 일부 |
|
|
154
|
+
| 폼 제출 | 성공 토스트 표시 | 내부 OK | 항상 발생, UX의 일부 |
|
|
155
|
+
| 주문 완료 | 이메일 발송 | 분리 | 사용자 설정에 따라 다름 |
|
|
156
|
+
| 버튼 클릭 | 페이지 이동 | 분리 | 이동 경로가 상황마다 다름 |
|
|
157
|
+
|
|
158
|
+
**Check for:**
|
|
159
|
+
- 함수 내부에 숨겨진 사이드이펙트 (logging, analytics)
|
|
160
|
+
- 선택적이어야 할 부수효과가 강제로 포함
|
|
161
|
+
- 호출처마다 다른 동작이 필요한데 하드코딩
|
|
162
|
+
|
|
163
|
+
**Scoring (0-10):**
|
|
164
|
+
- 9-10: 모든 부수효과 위치가 적절
|
|
165
|
+
- 7-8: 대부분 적절, 일부 개선 필요
|
|
166
|
+
- 4-6: 여러 부적절한 부수효과 위치
|
|
167
|
+
- 0-3: 숨은 부수효과가 많음, 예측 불가
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### 4. Toss Fundamentals 4가지 원칙 (Weight: 15%)
|
|
172
|
+
|
|
173
|
+
| 원칙 | 좋은 신호 | 나쁜 신호 |
|
|
174
|
+
|------|----------|----------|
|
|
175
|
+
| **응집도** | 함께 수정되는 코드가 같은 파일에 있음 | 기능 하나 바꾸는데 여러 파일 수정 |
|
|
176
|
+
| **결합도** | 컴포넌트가 자체 완결적 | 상위 컴포넌트에 강하게 의존 |
|
|
177
|
+
| **예측 가능성** | 같은 역할은 같은 패턴 사용 | 파일마다 패턴이 다름 |
|
|
178
|
+
| **가독성** | 이름만 보고 역할 파악 가능 | 내부 코드 봐야 이해 가능 |
|
|
179
|
+
|
|
180
|
+
**Check for:**
|
|
181
|
+
|
|
182
|
+
**응집도:**
|
|
183
|
+
- 함께 수정되는 파일이 같은 디렉토리에 있는가?
|
|
184
|
+
- 기능 삭제 시 디렉토리 전체 삭제로 처리 가능한가?
|
|
185
|
+
- `../../../` 같은 깊은 상대 경로가 있는가?
|
|
186
|
+
|
|
187
|
+
**결합도:**
|
|
188
|
+
- God Hook이 5개 이상의 관심사를 관리하는가?
|
|
189
|
+
- Props Drilling이 3단계 이상인가?
|
|
190
|
+
- 컴포넌트가 상위 컴포넌트에 강하게 의존하는가?
|
|
191
|
+
|
|
192
|
+
**예측 가능성:**
|
|
193
|
+
- 같은 접두사 함수들의 반환 타입이 일치하는가?
|
|
194
|
+
- 이름과 실제 동작이 일치하는가?
|
|
195
|
+
- 숨겨진 로직이 있는가?
|
|
196
|
+
|
|
197
|
+
**가독성:**
|
|
198
|
+
- 복잡한 조건에 이름이 붙어있는가?
|
|
199
|
+
- 매직 넘버가 상수화되어 있는가?
|
|
200
|
+
- 삼항 연산자가 2단계 이상 중첩되어 있는가?
|
|
201
|
+
|
|
202
|
+
**Scoring (0-15):**
|
|
203
|
+
- 13-15: 4가지 원칙 모두 준수
|
|
204
|
+
- 10-12: 3가지 원칙 준수
|
|
205
|
+
- 6-9: 2가지 원칙 준수
|
|
206
|
+
- 0-5: 1가지 이하 준수
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### 5. 데이터 Fetching 패턴 (Weight: 15%)
|
|
211
|
+
|
|
212
|
+
**컴포넌트가 자체 데이터를 fetch하면 자동으로 병렬 실행:**
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
// Good: 병렬 실행
|
|
216
|
+
function Dashboard() {
|
|
217
|
+
return (
|
|
218
|
+
<>
|
|
219
|
+
<UserStats /> {/* 내부에서 fetchUserStats() */}
|
|
220
|
+
<RecentOrders /> {/* 내부에서 fetchOrders() */}
|
|
221
|
+
<Notifications /> {/* 내부에서 fetchNotifications() */}
|
|
222
|
+
</>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**페이지에서 모든 fetch를 관리하면 waterfall 위험:**
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
// Bad: 순차 실행 위험
|
|
231
|
+
function Dashboard() {
|
|
232
|
+
const stats = await fetchUserStats();
|
|
233
|
+
const orders = await fetchOrders(); // stats 끝나야 시작
|
|
234
|
+
const notifications = await fetchNotifications(); // orders 끝나야 시작
|
|
235
|
+
// ...
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Suspense로 즉시 렌더링 영역과 로딩 영역 분리:**
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
<header>
|
|
243
|
+
<Logo /> {/* 즉시 렌더링 */}
|
|
244
|
+
<Navigation /> {/* 즉시 렌더링 */}
|
|
245
|
+
</header>
|
|
246
|
+
<Suspense fallback={<TableSkeleton />}>
|
|
247
|
+
<DataTable /> {/* 데이터 로딩 */}
|
|
248
|
+
</Suspense>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**AsyncBoundary: Suspense + ErrorBoundary 조합:**
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
// Bad: Suspense만 쓰면 에러 발생 시 캐치 불가
|
|
255
|
+
<Suspense fallback={<Skeleton />}>
|
|
256
|
+
<DataComponent /> {/* 에러 발생 시 전체 페이지로 전파 */}
|
|
257
|
+
</Suspense>
|
|
258
|
+
|
|
259
|
+
// Good: AsyncBoundary로 로딩 + 에러 모두 처리
|
|
260
|
+
<AsyncBoundary
|
|
261
|
+
pendingFallback={<Skeleton />}
|
|
262
|
+
rejectedFallback={<ErrorWithRetry />}
|
|
263
|
+
>
|
|
264
|
+
<DataComponent />
|
|
265
|
+
</AsyncBoundary>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**AsyncBoundary의 이점:**
|
|
269
|
+
- 로딩 중에는 스켈레톤 UI -> 레이아웃 시프트 방지
|
|
270
|
+
- API 에러 시 재시도 버튼이 있는 fallback 표시
|
|
271
|
+
- 에러가 해당 컴포넌트에서 격리됨 -> 나머지 UI는 정상 동작
|
|
272
|
+
|
|
273
|
+
**Check for:**
|
|
274
|
+
- 순차 await로 인한 waterfall 패턴
|
|
275
|
+
- Suspense 없는 데이터 fetching 컴포넌트
|
|
276
|
+
- Suspense만 사용하고 ErrorBoundary 누락
|
|
277
|
+
- useSuspenseQuery 사용 시 AsyncBoundary 적용 여부
|
|
278
|
+
|
|
279
|
+
**Scoring (0-15):**
|
|
280
|
+
- 13-15: AsyncBoundary 적절히 사용, waterfall 없음
|
|
281
|
+
- 10-12: Suspense 사용, 일부 waterfall
|
|
282
|
+
- 6-9: 부분적 적용, 여러 waterfall
|
|
283
|
+
- 0-5: 데이터 fetching 패턴 미적용
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
### 6. 네이밍 원칙 (Weight: 15%)
|
|
288
|
+
|
|
289
|
+
**핵심**: 모든 이름은 내부 코드를 보지 않고도 역할과 동작을 유추할 수 있어야 한다.
|
|
290
|
+
|
|
291
|
+
#### 6.1 컴포넌트 네이밍
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
// Bad: 내부를 봐야 알 수 있음
|
|
295
|
+
<Card /> // 무슨 카드?
|
|
296
|
+
<List /> // 무슨 리스트?
|
|
297
|
+
<Modal /> // 무슨 용도?
|
|
298
|
+
|
|
299
|
+
// Good: 이름만으로 역할 파악
|
|
300
|
+
<ProductCard /> // 상품 정보를 카드로 표시
|
|
301
|
+
<OrderHistoryList /> // 주문 내역 목록
|
|
302
|
+
<ConfirmDeleteModal /> // 삭제 확인 모달
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### 6.2 함수 네이밍
|
|
306
|
+
|
|
307
|
+
| 접두사 | 용도 | 예시 |
|
|
308
|
+
|--------|------|------|
|
|
309
|
+
| `get` | 값을 계산/반환 (부수효과 없음) | `getFullName()`, `getTotalPrice()` |
|
|
310
|
+
| `fetch` | 외부에서 데이터 가져옴 | `fetchUserProfile()`, `fetchOrders()` |
|
|
311
|
+
| `create` | 새로운 것을 생성 | `createOrder()`, `createComment()` |
|
|
312
|
+
| `update` | 기존 것을 수정 | `updateUserInfo()`, `updateCartItem()` |
|
|
313
|
+
| `delete/remove` | 삭제 | `deleteComment()`, `removeFromCart()` |
|
|
314
|
+
| `handle` | 이벤트 처리 | `handleSubmit()`, `handleClick()` |
|
|
315
|
+
| `validate` | 검증 | `validateEmail()`, `validateForm()` |
|
|
316
|
+
| `format` | 형식 변환 | `formatDate()`, `formatCurrency()` |
|
|
317
|
+
| `parse` | 문자열->구조화된 데이터 | `parseJSON()`, `parseQueryString()` |
|
|
318
|
+
| `serialize` | 구조화된 데이터->문자열 | `serializeFormData()` |
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
// Bad: 동작이 모호함
|
|
322
|
+
function process(data) { ... }
|
|
323
|
+
function doSomething() { ... }
|
|
324
|
+
function handleData() { ... }
|
|
325
|
+
|
|
326
|
+
// Good: 동작이 명확함
|
|
327
|
+
function validateAndSubmitForm(formData) { ... }
|
|
328
|
+
function formatPriceWithCurrency(price, currency) { ... }
|
|
329
|
+
function parseSearchParamsToFilters(searchParams) { ... }
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### 6.3 훅 네이밍
|
|
333
|
+
|
|
334
|
+
| 패턴 | 예시 | 반환값 유추 |
|
|
335
|
+
|------|------|------------|
|
|
336
|
+
| `use` + 명사 | `useUser()` | 사용자 데이터 |
|
|
337
|
+
| `use` + 명사 + 동작 | `useCartItems()` | 장바구니 아이템들 |
|
|
338
|
+
| `use` + 동작 + 대상 | `useFetchProducts()` | 상품 fetch 결과 |
|
|
339
|
+
| `use` + 상태명 + `State` | `useSortState()` | 정렬 상태 + setter |
|
|
340
|
+
| `use` + param명 + `QueryParam` | `usePageQueryParam()` | URL의 page 파라미터 |
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
// Bad: 반환값을 유추하기 어려움
|
|
344
|
+
const data = useData(); // 무슨 데이터?
|
|
345
|
+
const result = useQuery(); // 무슨 쿼리?
|
|
346
|
+
const state = useAppState(); // 앱의 어떤 상태?
|
|
347
|
+
|
|
348
|
+
// Good: 반환값이 명확함
|
|
349
|
+
const user = useCurrentUser(); // 현재 로그인한 사용자
|
|
350
|
+
const [sort, setSort] = useSortState(); // 정렬 상태
|
|
351
|
+
const { products, isLoading } = useProductList(); // 상품 목록
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
#### 6.4 상수 네이밍
|
|
355
|
+
|
|
356
|
+
```tsx
|
|
357
|
+
// Bad: 의미 불명확
|
|
358
|
+
const MAX = 10;
|
|
359
|
+
const TIMEOUT = 3000;
|
|
360
|
+
const URL = '/api/users';
|
|
361
|
+
|
|
362
|
+
// Good: 용도가 명확
|
|
363
|
+
const MAX_RETRY_COUNT = 10;
|
|
364
|
+
const API_TIMEOUT_MS = 3000;
|
|
365
|
+
const USER_API_ENDPOINT = '/api/users';
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
#### 6.5 불리언 네이밍
|
|
369
|
+
|
|
370
|
+
```tsx
|
|
371
|
+
// Bad: 불리언인지 불명확
|
|
372
|
+
const loading = true;
|
|
373
|
+
const error = false;
|
|
374
|
+
const visible = true;
|
|
375
|
+
|
|
376
|
+
// Good: 불리언임이 명확
|
|
377
|
+
const isLoading = true;
|
|
378
|
+
const hasError = false;
|
|
379
|
+
const isVisible = true;
|
|
380
|
+
const canSubmit = true;
|
|
381
|
+
const shouldRefetch = false;
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Check for:**
|
|
385
|
+
1. 이름만 보고 3초 안에 역할을 알 수 있는가?
|
|
386
|
+
2. 같은 역할에 같은 패턴을 사용하는가?
|
|
387
|
+
3. `data`, `info`, `handle` 같은 모호한 이름이 아닌가?
|
|
388
|
+
4. 실제 동작과 이름이 일치하는가?
|
|
389
|
+
|
|
390
|
+
**Scoring (0-15):**
|
|
391
|
+
- 13-15: 일관된 네이밍 규칙, 모든 이름이 명확
|
|
392
|
+
- 10-12: 대부분 명확, 일부 모호
|
|
393
|
+
- 6-9: 여러 모호한 이름, 불일치
|
|
394
|
+
- 0-5: 전반적인 네이밍 문제
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
### 7. 메모이제이션 적용 기준 (Weight: 10%)
|
|
399
|
+
|
|
400
|
+
**원칙: "측정 후 필요할 때만"**
|
|
401
|
+
|
|
402
|
+
React.memo, useMemo, useCallback은 공짜가 아니다. 잘못 사용하면 오버헤드만 추가된다.
|
|
403
|
+
|
|
404
|
+
#### memo가 의미 없는 경우
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
// memo 의미없음: props가 매번 바뀜
|
|
408
|
+
const Button = memo(({ isActive, onClick }) => { ... });
|
|
409
|
+
|
|
410
|
+
// 사용처에서
|
|
411
|
+
<Button
|
|
412
|
+
isActive={selectedId === item.id} // 상태가 바뀔 때마다 새 값
|
|
413
|
+
onClick={() => handleSelect(item.id)} // 매 렌더링마다 새 함수 생성
|
|
414
|
+
/>
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### memo가 효과적인 경우
|
|
418
|
+
|
|
419
|
+
```tsx
|
|
420
|
+
// memo 효과적: 리스트 아이템
|
|
421
|
+
const ListItem = memo(({ item }) => {
|
|
422
|
+
return <div>{item.name}</div>;
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// 사용처에서
|
|
426
|
+
{items.map(item => (
|
|
427
|
+
<ListItem key={item.id} item={item} />
|
|
428
|
+
))}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
#### memo가 무의미해지는 패턴
|
|
432
|
+
|
|
433
|
+
```tsx
|
|
434
|
+
// Bad: 인라인 객체/함수를 props로 전달
|
|
435
|
+
<MemoizedComponent
|
|
436
|
+
style={{ color: 'red' }} // 매번 새 객체
|
|
437
|
+
onClick={() => doSomething()} // 매번 새 함수
|
|
438
|
+
config={{ enabled: true }} // 매번 새 객체
|
|
439
|
+
/>
|
|
440
|
+
|
|
441
|
+
// Good: 안정적인 참조로 전달
|
|
442
|
+
const style = useMemo(() => ({ color: 'red' }), []);
|
|
443
|
+
const handleClick = useCallback(() => doSomething(), []);
|
|
444
|
+
|
|
445
|
+
<MemoizedComponent
|
|
446
|
+
style={style}
|
|
447
|
+
onClick={handleClick}
|
|
448
|
+
config={CONFIG} // 모듈 스코프 상수
|
|
449
|
+
/>
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### 적용 판단 기준
|
|
453
|
+
|
|
454
|
+
| 상황 | memo 필요? | 이유 |
|
|
455
|
+
|------|-----------|------|
|
|
456
|
+
| 리스트에서 반복 렌더링되는 아이템 | 고려 | 일부만 변경 시 효과적 |
|
|
457
|
+
| props가 primitive 값으로 안정적 | 고려 | 비교 비용 낮고 효과 있음 |
|
|
458
|
+
| props가 매번 새로운 객체/함수 | 불필요 | 비교만 하고 항상 리렌더링 |
|
|
459
|
+
| 렌더링 비용이 낮은 간단한 컴포넌트 | 불필요 | 최적화 이득이 거의 없음 |
|
|
460
|
+
| 부모가 자주 리렌더링되지 않음 | 불필요 | 문제가 없는데 최적화할 필요 없음 |
|
|
461
|
+
|
|
462
|
+
#### useMemo / useCallback 기준
|
|
463
|
+
|
|
464
|
+
```tsx
|
|
465
|
+
// 불필요: 계산 비용이 낮음
|
|
466
|
+
const fullName = useMemo(() => `${firstName} ${lastName}`, [firstName, lastName]);
|
|
467
|
+
|
|
468
|
+
// 필요: 비용이 높은 계산
|
|
469
|
+
const sortedItems = useMemo(
|
|
470
|
+
() => [...items].sort((a, b) => complexSortLogic(a, b)),
|
|
471
|
+
[items]
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
// 필요: 대량 데이터 필터링/변환
|
|
475
|
+
const filteredData = useMemo(
|
|
476
|
+
() => largeDataset.filter(item => item.category === category),
|
|
477
|
+
[largeDataset, category]
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
// 필요: memo된 자식에게 전달하는 콜백
|
|
481
|
+
const handleItemClick = useCallback(
|
|
482
|
+
(id) => onSelect(id),
|
|
483
|
+
[onSelect]
|
|
484
|
+
);
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**Check for:**
|
|
488
|
+
- 불필요한 memo, useMemo, useCallback 사용
|
|
489
|
+
- memo된 컴포넌트에 인라인 객체/함수 전달
|
|
490
|
+
- 계산 비용이 낮은데 useMemo 적용
|
|
491
|
+
- memo 없이 리스트 아이템 렌더링
|
|
492
|
+
|
|
493
|
+
**Scoring (0-10):**
|
|
494
|
+
- 9-10: 적절한 메모이제이션, 과도하지도 부족하지도 않음
|
|
495
|
+
- 7-8: 대부분 적절, 일부 불필요/누락
|
|
496
|
+
- 4-6: 과도하거나 부족한 메모이제이션
|
|
497
|
+
- 0-3: 메모이제이션 오용 또는 심각한 누락
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
### 8. 안티패턴 탐지 (Weight: 5%)
|
|
502
|
+
|
|
503
|
+
| 안티패턴 | 설명 | 해결책 |
|
|
504
|
+
|---------|------|--------|
|
|
505
|
+
| **God Hook** | 모든 상태를 관리하는 단일 훅 | 책임별로 훅 분리 |
|
|
506
|
+
| **Prop Drilling** | 중간 컴포넌트가 사용하지 않는 props 전달 | Context 또는 컴포넌트 합성 |
|
|
507
|
+
| **Props -> State 복사** | props를 받아서 내부 useState에 복사 | props 직접 사용 (Controlled) |
|
|
508
|
+
| **Waterfall Fetch** | 상위에서 모든 fetch를 순차 관리 | 컴포넌트별 자체 fetch |
|
|
509
|
+
| **과도한 명시성** | 재사용마다 훅 + props 연결 반복 | 응집도 우선 패턴 검토 |
|
|
510
|
+
| **패턴 불일치** | 같은 역할인데 다른 패턴 사용 | 컨벤션 통일 |
|
|
511
|
+
|
|
512
|
+
**God Hook 예시:**
|
|
513
|
+
```tsx
|
|
514
|
+
// Bad
|
|
515
|
+
function usePageState() {
|
|
516
|
+
const [user, setUser] = useState();
|
|
517
|
+
const [cart, setCart] = useState();
|
|
518
|
+
const [notifications, setNotifications] = useState();
|
|
519
|
+
const [theme, setTheme] = useState();
|
|
520
|
+
// 모든 것을 하나에서 관리
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Good: 책임별 분리
|
|
524
|
+
function useUser() { /* 사용자만 */ }
|
|
525
|
+
function useCart() { /* 장바구니만 */ }
|
|
526
|
+
function useNotifications() { /* 알림만 */ }
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
**Props -> State 복사:**
|
|
530
|
+
```tsx
|
|
531
|
+
// Bad: 동기화 문제 발생
|
|
532
|
+
function Modal({ isOpen }) {
|
|
533
|
+
const [open, setOpen] = useState(isOpen); // props 복사
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Good: Controlled Component
|
|
537
|
+
function Modal({ isOpen, onClose }) {
|
|
538
|
+
// props 직접 사용
|
|
539
|
+
if (!isOpen) return null;
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
**Check for:**
|
|
544
|
+
- useState로 props 복사하는 패턴
|
|
545
|
+
- 5개 이상 상태를 관리하는 단일 Hook
|
|
546
|
+
- 3단계 이상 Props Drilling
|
|
547
|
+
- 같은 역할의 다른 패턴 사용
|
|
548
|
+
|
|
549
|
+
**Scoring (0-5):**
|
|
550
|
+
- 5: 안티패턴 없음
|
|
551
|
+
- 3-4: 경미한 안티패턴 1-2개
|
|
552
|
+
- 1-2: 여러 안티패턴 존재
|
|
553
|
+
- 0: 심각한 안티패턴 다수
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
### 9. 리뷰 체크리스트 기반 검토 (Weight: 5%)
|
|
558
|
+
|
|
559
|
+
최종 검토 체크리스트:
|
|
560
|
+
|
|
561
|
+
1. **네이밍**: 이름만 보고 역할과 동작을 즉시 이해할 수 있는가?
|
|
562
|
+
2. **응집도**: 이 기능을 수정할 때 몇 개 파일을 건드려야 하는가?
|
|
563
|
+
3. **상태 위치**: 이 상태를 상위에서 알아야 하는 이유가 있는가?
|
|
564
|
+
4. **부수효과**: 이 부수효과는 항상 발생해야 하는가, 선택적인가?
|
|
565
|
+
5. **패턴 일관성**: 같은 역할의 다른 컴포넌트와 패턴이 일치하는가?
|
|
566
|
+
6. **데이터 흐름**: 불필요한 props 전달이나 waterfall이 있는가?
|
|
567
|
+
7. **에러 처리**: Suspense와 ErrorBoundary가 함께 사용되었는가?
|
|
568
|
+
8. **메모이제이션**: 실제 성능 문제 없이 과도하게 최적화하고 있지 않은가?
|
|
569
|
+
|
|
570
|
+
**Scoring (0-5):**
|
|
571
|
+
- 5: 모든 항목 통과
|
|
572
|
+
- 3-4: 6-7개 항목 통과
|
|
573
|
+
- 1-2: 4-5개 항목 통과
|
|
574
|
+
- 0: 3개 이하 항목 통과
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## Analysis Process
|
|
579
|
+
|
|
580
|
+
### Step 1: 코드베이스 탐색
|
|
581
|
+
|
|
582
|
+
```
|
|
583
|
+
Glob: **/*.tsx, **/*.ts
|
|
584
|
+
Grep: 패턴 검색 (useEffect, useState, useMemo, memo, Suspense, etc.)
|
|
585
|
+
Read: 주요 파일 상세 분석
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### Step 2: 9가지 영역 평가
|
|
589
|
+
|
|
590
|
+
각 발견 사항을 9가지 영역으로 분류하고 점수화
|
|
591
|
+
|
|
592
|
+
### Step 3: 트레이드오프 분석
|
|
593
|
+
|
|
594
|
+
상충하는 가치들 사이에서 현재 상황에 맞는 균형점 제안
|
|
595
|
+
|
|
596
|
+
### Step 4: 우선순위 결정
|
|
597
|
+
|
|
598
|
+
- P0 (Critical): 버그 발생 가능성 높음
|
|
599
|
+
- P1 (High): 유지보수 비용 증가
|
|
600
|
+
- P2 (Medium): 개선 시 이점 있음
|
|
601
|
+
- P3 (Low): Nice to have
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Output Format
|
|
606
|
+
|
|
607
|
+
```markdown
|
|
608
|
+
# React 개발 원칙 기반 코드 리뷰 결과
|
|
609
|
+
|
|
610
|
+
## Executive Summary
|
|
611
|
+
- **Overall Score:** X/100
|
|
612
|
+
- **Critical Issues:** N개 (즉시 수정 필요)
|
|
613
|
+
- **Recommended Improvements:** M개 (권장)
|
|
614
|
+
- **Best Practices Found:** P개 (잘하고 있음)
|
|
615
|
+
|
|
616
|
+
## Score Breakdown
|
|
617
|
+
|
|
618
|
+
| 영역 | 점수 | 비고 |
|
|
619
|
+
|------|------|------|
|
|
620
|
+
| 응집도 vs 명시성 | X/15 | |
|
|
621
|
+
| Props 관리 | X/10 | |
|
|
622
|
+
| 부수효과 위치 | X/10 | |
|
|
623
|
+
| Toss Fundamentals | X/15 | |
|
|
624
|
+
| 데이터 Fetching | X/15 | |
|
|
625
|
+
| 네이밍 원칙 | X/15 | |
|
|
626
|
+
| 메모이제이션 | X/10 | |
|
|
627
|
+
| 안티패턴 | X/5 | |
|
|
628
|
+
| 체크리스트 | X/5 | |
|
|
629
|
+
| **합계** | **X/100** | |
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## Critical Issues (즉시 수정)
|
|
634
|
+
|
|
635
|
+
### 1. [Issue Name]
|
|
636
|
+
**영역:** [해당 영역]
|
|
637
|
+
**파일:** [file:line]
|
|
638
|
+
|
|
639
|
+
**문제:**
|
|
640
|
+
[설명]
|
|
641
|
+
|
|
642
|
+
**현재 코드:**
|
|
643
|
+
```typescript
|
|
644
|
+
// 문제 코드
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
**위반 원칙:**
|
|
648
|
+
[위반한 원칙명]
|
|
649
|
+
|
|
650
|
+
**수정 방법:**
|
|
651
|
+
```typescript
|
|
652
|
+
// 개선 코드
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
**영향:**
|
|
656
|
+
- [영향 설명]
|
|
657
|
+
|
|
658
|
+
---
|
|
659
|
+
|
|
660
|
+
## Recommended Improvements (권장)
|
|
661
|
+
|
|
662
|
+
[같은 형식, 낮은 우선순위]
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## Best Practices Found (잘하고 있음)
|
|
667
|
+
|
|
668
|
+
### [Good Pattern]
|
|
669
|
+
**영역:** [해당 영역]
|
|
670
|
+
**파일:** [file:line]
|
|
671
|
+
|
|
672
|
+
**잘한 점:**
|
|
673
|
+
[설명]
|
|
674
|
+
|
|
675
|
+
**코드:**
|
|
676
|
+
```typescript
|
|
677
|
+
// 좋은 예시
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
## 트레이드오프 분석
|
|
683
|
+
|
|
684
|
+
### 발견된 상충 가치
|
|
685
|
+
| 상황 | 선택한 가치 | 포기한 가치 | 추천 |
|
|
686
|
+
|------|------------|------------|------|
|
|
687
|
+
| [상황] | [가치] | [가치] | 유지/변경 |
|
|
688
|
+
|
|
689
|
+
### 추천 방향
|
|
690
|
+
[현재 상황에 맞는 균형점 제안]
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
## Metrics
|
|
695
|
+
|
|
696
|
+
### 응집도 vs 명시성
|
|
697
|
+
- 응집도 우선 컴포넌트: N개
|
|
698
|
+
- 명시성 우선 컴포넌트: M개
|
|
699
|
+
- 패턴 일관성: High/Medium/Low
|
|
700
|
+
|
|
701
|
+
### Props 관리
|
|
702
|
+
- 불필요한 props 전달: N개
|
|
703
|
+
- 적절한 상태 위치: M개
|
|
704
|
+
|
|
705
|
+
### 부수효과
|
|
706
|
+
- 내부 관리 적절: N개
|
|
707
|
+
- 분리 필요: M개
|
|
708
|
+
- 숨은 사이드이펙트: P개
|
|
709
|
+
|
|
710
|
+
### 데이터 Fetching
|
|
711
|
+
- AsyncBoundary 사용: N개
|
|
712
|
+
- Waterfall 패턴: M개
|
|
713
|
+
- Suspense 누락: P개
|
|
714
|
+
|
|
715
|
+
### 네이밍
|
|
716
|
+
- 명확한 이름: N개
|
|
717
|
+
- 모호한 이름: M개
|
|
718
|
+
- 불리언 접두사 누락: P개
|
|
719
|
+
|
|
720
|
+
### 메모이제이션
|
|
721
|
+
- 적절한 memo: N개
|
|
722
|
+
- 불필요한 memo: M개
|
|
723
|
+
- 누락된 memo: P개
|
|
724
|
+
|
|
725
|
+
### 안티패턴
|
|
726
|
+
- God Hook: N개
|
|
727
|
+
- Props Drilling: M개
|
|
728
|
+
- Props -> State 복사: P개
|
|
729
|
+
|
|
730
|
+
---
|
|
731
|
+
|
|
732
|
+
## Next Steps
|
|
733
|
+
|
|
734
|
+
### P0 (즉시)
|
|
735
|
+
1. [ ] [액션 아이템]
|
|
736
|
+
|
|
737
|
+
### P1 (이번 스프린트)
|
|
738
|
+
1. [ ] [액션 아이템]
|
|
739
|
+
|
|
740
|
+
### P2 (백로그)
|
|
741
|
+
1. [ ] [액션 아이템]
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
---
|
|
745
|
+
|
|
746
|
+
## Red Flags (항상 리포트)
|
|
747
|
+
|
|
748
|
+
다음 사항은 발견 즉시 Critical로 분류:
|
|
749
|
+
|
|
750
|
+
- **God Hook**: 5개 이상 관심사를 관리하는 Hook
|
|
751
|
+
- **Props -> State 복사**: 동기화 문제 발생 가능
|
|
752
|
+
- **Waterfall Fetch**: 순차 await로 인한 성능 저하
|
|
753
|
+
- **숨은 사이드이펙트**: fetch 함수 내 logging, analytics
|
|
754
|
+
- **Props Drilling >3 levels**: 깊은 props 전달
|
|
755
|
+
- **AsyncBoundary 누락**: useSuspenseQuery 사용 시 ErrorBoundary 없음
|
|
756
|
+
- **모호한 네이밍**: `data`, `info`, `handle` 등 범용 이름
|
|
757
|
+
- **memo + 인라인 객체/함수**: 무의미한 메모이제이션
|
|
758
|
+
|
|
759
|
+
---
|
|
760
|
+
|
|
761
|
+
## 점수 가이드라인
|
|
762
|
+
|
|
763
|
+
- 90-100: 우수, 업계 모범 사례 수준
|
|
764
|
+
- 75-89: 양호, 주요 패턴 준수
|
|
765
|
+
- 60-74: 허용 가능, 일부 개선 필요
|
|
766
|
+
- 40-59: 우려됨, 다수의 문제
|
|
767
|
+
- 0-39: 심각, 즉시 개선 필요
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## Philosophy
|
|
772
|
+
|
|
773
|
+
분석 시 항상 기억할 원칙:
|
|
774
|
+
|
|
775
|
+
- **"내부에서 뭘 하는지 모른다"는 것 자체가 문제가 아님**: 추상화된 역할이 이름으로 명확한지가 중요
|
|
776
|
+
- **측정 후 최적화**: 메모이제이션은 실제 성능 문제 확인 후 적용
|
|
777
|
+
- **트레이드오프 인식**: 응집도와 명시성, 결합도와 응집도는 상충할 수 있음
|
|
778
|
+
- **일관성 > 완벽함**: 팀 전체 일관성이 개인 최적화보다 중요
|
|
779
|
+
- **점진적 개선**: 전체 재작성이 아닌 단계적 개선 추천
|
|
780
|
+
|
|
781
|
+
---
|
|
782
|
+
|
|
783
|
+
## References
|
|
784
|
+
|
|
785
|
+
- React 개발 원칙 문서 (react-development-principles.md)
|
|
786
|
+
- [Toss Frontend Fundamentals](https://frontend-fundamentals.com/code-quality/code/)
|
|
787
|
+
- [React Official Docs](https://react.dev)
|
package/bin/cli.js
CHANGED
|
@@ -1,50 +1,90 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { select } from '@inquirer/prompts';
|
|
4
4
|
import { syncSubagents, listSubagents } from '../src/sync.js';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
7
|
+
async function main() {
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
|
|
10
|
+
// list 명령어는 바로 실행
|
|
11
|
+
if (args[0] === 'list') {
|
|
12
|
+
await listSubagents();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// help 또는 --help
|
|
17
|
+
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {
|
|
18
|
+
showHelp();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 대화형 설치 시작
|
|
23
|
+
console.log(chalk.blue.bold('\n🤖 Binary Agents 설치\n'));
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// 1. 설치 위치 선택
|
|
27
|
+
const location = await select({
|
|
28
|
+
message: '어디에 설치하시겠습니까?',
|
|
29
|
+
choices: [
|
|
30
|
+
{ name: '전역 (~/.claude/)', value: 'global' },
|
|
31
|
+
{ name: '현재 프로젝트 (.claude/)', value: 'local' }
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// 2. 설치 항목 선택
|
|
36
|
+
const items = await select({
|
|
37
|
+
message: '무엇을 설치하시겠습니까?',
|
|
38
|
+
choices: [
|
|
39
|
+
{ name: '모두 (에이전트 + 명령어)', value: 'all' },
|
|
40
|
+
{ name: '에이전트만', value: 'agents' },
|
|
41
|
+
{ name: '명령어만', value: 'commands' }
|
|
42
|
+
]
|
|
31
43
|
});
|
|
32
44
|
|
|
45
|
+
// 3. 기존 파일 삭제 여부
|
|
46
|
+
const clean = await select({
|
|
47
|
+
message: '기존 파일을 삭제하고 새로 설치할까요?',
|
|
48
|
+
choices: [
|
|
49
|
+
{ name: '예 (기존 파일 삭제)', value: true },
|
|
50
|
+
{ name: '아니오 (기존 파일 유지)', value: false }
|
|
51
|
+
]
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// 옵션 구성
|
|
55
|
+
const options = {
|
|
56
|
+
global: location === 'global',
|
|
57
|
+
agents: items === 'all' || items === 'agents',
|
|
58
|
+
commands: items === 'all' || items === 'commands',
|
|
59
|
+
clean
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// 동기화 실행
|
|
63
|
+
const result = await syncSubagents(options);
|
|
64
|
+
|
|
33
65
|
if (!result.success) {
|
|
34
66
|
process.exit(1);
|
|
35
67
|
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
// Ctrl+C로 취소한 경우
|
|
70
|
+
if (error.name === 'ExitPromptError') {
|
|
71
|
+
console.log(chalk.yellow('\n\n취소되었습니다.\n'));
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
44
77
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
78
|
+
function showHelp() {
|
|
79
|
+
console.log(chalk.blue.bold('\n🤖 Binary Agents\n'));
|
|
80
|
+
console.log('Claude Code 서브에이전트 및 슬래시 명령어 설치 도구\n');
|
|
81
|
+
console.log(chalk.yellow('사용법:'));
|
|
82
|
+
console.log(' npx binary-agents 대화형 설치');
|
|
83
|
+
console.log(' npx binary-agents list 사용 가능한 에이전트/명령어 목록');
|
|
84
|
+
console.log(' npx binary-agents help 도움말 표시\n');
|
|
48
85
|
}
|
|
49
86
|
|
|
50
|
-
|
|
87
|
+
main().catch(error => {
|
|
88
|
+
console.error(chalk.red(`\n오류: ${error.message}\n`));
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
package/commands/code-review.md
CHANGED
|
@@ -29,6 +29,7 @@ Task 도구를 통해 다음 전문 에이전트를 사용할 수 있습니다:
|
|
|
29
29
|
| `junior-checker` | 주니어 개발자 관점 가독성, 네이밍, 복잡도 | opus |
|
|
30
30
|
| `fundamentals-code` | Toss Frontend Fundamentals 기반 (가독성, 예측 가능성, 응집도, 결합도) | opus |
|
|
31
31
|
| `react-performance-optimizer` | React 리렌더, 메모이제이션, 훅 최적화 | opus |
|
|
32
|
+
| `react-principles-reviewer` | React 개발 원칙 (응집도/명시성, Props 관리, 네이밍, 부수효과, AsyncBoundary) | opus |
|
|
32
33
|
|
|
33
34
|
## 사용 가능한 Skill
|
|
34
35
|
|
|
@@ -53,7 +54,7 @@ Skill은 사용자 설치에 따라 다르며 추가 리뷰 가이드라인/컨
|
|
|
53
54
|
|
|
54
55
|
| 옵션 | 이름 | 사용 에이전트 | 적합한 상황 |
|
|
55
56
|
|------|------|--------------|-------------|
|
|
56
|
-
| 1 | **전체 리뷰** | 모든
|
|
57
|
+
| 1 | **전체 리뷰** | 모든 6개 에이전트 병렬 실행 | 종합 코드 리뷰 (권장) |
|
|
57
58
|
| 2 | **커스텀** | 사용자가 직접 선택 | 특정 관점만 리뷰하고 싶을 때 |
|
|
58
59
|
|
|
59
60
|
3. **Skill 포함 여부 질문** (AskUserQuestion 사용)
|
|
@@ -176,6 +177,8 @@ Task(code-reviewer): "src/components 코드를 리뷰하세요. 아키텍처,
|
|
|
176
177
|
Task(fundamentals-code): "src/components를 Toss Frontend Fundamentals 원칙으로 분석하세요. 가독성, 예측 가능성, 응집도, 결합도를 확인하세요. file:line 참조와 함께 발견사항을 반환하세요."
|
|
177
178
|
|
|
178
179
|
Task(refactor-analyzer): "src/components의 리팩토링 기회를 분석하세요. 코드 중복, 복잡성, 추상화 기회를 확인하세요. file:line 참조와 함께 발견사항을 반환하세요."
|
|
180
|
+
|
|
181
|
+
Task(react-principles-reviewer): "src/components를 React 개발 원칙으로 리뷰하세요. 응집도/명시성 패턴, Props 관리, 네이밍 원칙, 부수효과 위치, AsyncBoundary 사용을 확인하세요. file:line 참조와 함께 발견사항을 반환하세요."
|
|
179
182
|
```
|
|
180
183
|
|
|
181
184
|
### Skill 로드 (Skill 도구)
|
|
@@ -196,3 +199,4 @@ Skill(<skill-name>): 리뷰 중 이 skill의 가이드라인을 적용하기 위
|
|
|
196
199
|
- **file:line 참조 보존** - 실행 가능한 피드백을 위해 필수
|
|
197
200
|
- **한국어 출력** - 최종 리포트는 한국어로
|
|
198
201
|
- **AI attribution 금지** - "Generated by AI" footer 추가 금지
|
|
202
|
+
- **결과 파일 저장** - 최종 리포트를 `code-review.md` 파일로 저장 (이미 존재하면 `---` 구분선과 함께 하단에 추가)
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 설계/요구사항을 분석하여 구현 계획 생성
|
|
3
|
+
allowed-tools: Task, Read, Glob, Grep
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Design to Code
|
|
7
|
+
|
|
8
|
+
대화 컨텍스트의 설계/요구사항을 분석하고, 코드베이스를 탐색하여 구체적인 구현 계획을 생성합니다.
|
|
9
|
+
|
|
10
|
+
## 컨텍스트 정보
|
|
11
|
+
|
|
12
|
+
**현재 프로젝트 타입 감지:**
|
|
13
|
+
!`if [ -f "package.json" ] && grep -q '"react"' package.json 2>/dev/null; then echo "React 프로젝트"; else echo "일반 프로젝트"; fi`
|
|
14
|
+
|
|
15
|
+
**package.json 주요 의존성:**
|
|
16
|
+
!`cat package.json 2>/dev/null | grep -A 20 '"dependencies"' | head -25 || echo "package.json 없음"`
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 작업 순서
|
|
21
|
+
|
|
22
|
+
### 1. 설계/요구사항 확인
|
|
23
|
+
|
|
24
|
+
대화 컨텍스트에서 설계 또는 요구사항 확인:
|
|
25
|
+
- 이전 메시지에서 설계 문서, 기능 명세, 요구사항 찾기
|
|
26
|
+
- 없으면 → "구현할 설계나 요구사항을 먼저 설명해주세요" 안내
|
|
27
|
+
|
|
28
|
+
**확인할 내용:**
|
|
29
|
+
- 구현 목표 (무엇을 만들어야 하는가?)
|
|
30
|
+
- 주요 기능 목록
|
|
31
|
+
- 제약 조건 (기술 스택, 성능, 호환성 등)
|
|
32
|
+
- 참고할 기존 코드나 패턴
|
|
33
|
+
|
|
34
|
+
### 2. 코드베이스 분석 (Explore 에이전트)
|
|
35
|
+
|
|
36
|
+
Task 도구로 Explore 에이전트 실행:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
Task(Explore): "프로젝트 구조를 분석하세요:
|
|
40
|
+
1. 폴더 구조 및 아키텍처 패턴 파악
|
|
41
|
+
2. 기존 컴포넌트/모듈 구조 확인
|
|
42
|
+
3. 공통 유틸리티, 훅, 컴포넌트 식별
|
|
43
|
+
4. 코딩 컨벤션 및 네이밍 패턴 파악
|
|
44
|
+
5. [설계와 관련된 기존 코드] 찾기"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3. 구현 계획 수립 (Plan 에이전트)
|
|
48
|
+
|
|
49
|
+
Task 도구로 Plan 에이전트 실행:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Task(Plan): "다음 설계를 구현하기 위한 계획을 수립하세요:
|
|
53
|
+
|
|
54
|
+
[설계/요구사항 요약]
|
|
55
|
+
|
|
56
|
+
코드베이스 분석 결과:
|
|
57
|
+
[Explore 결과 요약]
|
|
58
|
+
|
|
59
|
+
다음을 포함한 구현 계획 작성:
|
|
60
|
+
1. 단계별 구현 순서
|
|
61
|
+
2. 생성/수정할 파일 목록
|
|
62
|
+
3. 각 파일의 주요 구현 내용
|
|
63
|
+
4. 의존성 및 임포트 관계
|
|
64
|
+
5. 테스트 전략
|
|
65
|
+
6. 주의사항 및 엣지 케이스"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 4. 설계 원칙 검증 (에이전트 병렬 실행)
|
|
69
|
+
|
|
70
|
+
설계의 품질을 검증하기 위해 에이전트들을 병렬로 실행:
|
|
71
|
+
|
|
72
|
+
**필수 에이전트:**
|
|
73
|
+
|
|
74
|
+
| 에이전트 | 검증 내용 |
|
|
75
|
+
|----------|----------|
|
|
76
|
+
| `fundamentals-code` | 가독성, 예측 가능성, 응집도, 결합도 관점에서 설계 검증 |
|
|
77
|
+
| `refactor-analyzer` | 추상화 기회, 재사용 가능한 컴포넌트 식별 |
|
|
78
|
+
|
|
79
|
+
**조건부 에이전트 (React 프로젝트):**
|
|
80
|
+
|
|
81
|
+
| 에이전트 | 검증 내용 |
|
|
82
|
+
|----------|----------|
|
|
83
|
+
| `react-principles-reviewer` | 컴포넌트 구조, Props 설계, 상태 관리 전략 검증 |
|
|
84
|
+
|
|
85
|
+
**React 프로젝트 감지 방법:**
|
|
86
|
+
```bash
|
|
87
|
+
# 다음 중 하나라도 해당되면 React 프로젝트
|
|
88
|
+
- package.json에 "react" 또는 "next" 의존성 존재
|
|
89
|
+
- .tsx 또는 .jsx 파일 존재
|
|
90
|
+
```
|
|
91
|
+
> Next.js, Remix 등 React 기반 프레임워크도 자동 감지됩니다.
|
|
92
|
+
|
|
93
|
+
**에이전트 실행 예시:**
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
// 필수 에이전트 (항상 실행)
|
|
97
|
+
Task(fundamentals-code): "다음 구현 계획을 Toss Frontend Fundamentals 원칙으로 검증하세요:
|
|
98
|
+
[Plan 결과]
|
|
99
|
+
가독성, 예측 가능성, 응집도, 결합도 관점에서 개선점을 제안하세요."
|
|
100
|
+
|
|
101
|
+
Task(refactor-analyzer): "다음 구현 계획에서 추상화 기회를 분석하세요:
|
|
102
|
+
[Plan 결과]
|
|
103
|
+
재사용 가능한 컴포넌트, 공통 유틸리티, 중복 제거 가능한 부분을 식별하세요."
|
|
104
|
+
|
|
105
|
+
// React 프로젝트면 추가
|
|
106
|
+
Task(react-principles-reviewer): "다음 구현 계획을 React 개발 원칙으로 검증하세요:
|
|
107
|
+
[Plan 결과]
|
|
108
|
+
컴포넌트 응집도, Props 설계, 상태 관리 전략, 부수효과 위치를 검토하세요."
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 5. 결과 종합 및 최종 계획 생성
|
|
112
|
+
|
|
113
|
+
모든 에이전트 결과를 종합하여 최종 구현 계획 작성.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 출력 형식
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
# 구현 계획: [기능명]
|
|
121
|
+
|
|
122
|
+
## 요약
|
|
123
|
+
- **목표:** [구현 목표 1줄 요약]
|
|
124
|
+
- **예상 파일 수:** N개 (신규: X, 수정: Y)
|
|
125
|
+
- **프로젝트 타입:** [React/일반]
|
|
126
|
+
- **검증 에이전트:** [실행된 에이전트 목록]
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 1. 설계 분석
|
|
131
|
+
|
|
132
|
+
### 요구사항 요약
|
|
133
|
+
[대화에서 파악한 요구사항 정리]
|
|
134
|
+
|
|
135
|
+
### 제약 조건
|
|
136
|
+
- [제약 1]
|
|
137
|
+
- [제약 2]
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 2. 코드베이스 분석 결과
|
|
142
|
+
|
|
143
|
+
### 프로젝트 구조
|
|
144
|
+
```
|
|
145
|
+
[관련 폴더 구조]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 참고할 기존 패턴
|
|
149
|
+
| 패턴 | 파일 | 설명 |
|
|
150
|
+
|------|------|------|
|
|
151
|
+
| [패턴명] | [file:line] | [설명] |
|
|
152
|
+
|
|
153
|
+
### 재사용 가능한 기존 코드
|
|
154
|
+
- [컴포넌트/유틸리티]: [file:line]
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 3. 구현 계획
|
|
159
|
+
|
|
160
|
+
### 단계별 구현 순서
|
|
161
|
+
|
|
162
|
+
#### Phase 1: [단계명]
|
|
163
|
+
**목표:** [이 단계의 목표]
|
|
164
|
+
|
|
165
|
+
| 순서 | 작업 | 파일 | 설명 |
|
|
166
|
+
|------|------|------|------|
|
|
167
|
+
| 1 | [작업] | [경로] | [설명] |
|
|
168
|
+
| 2 | [작업] | [경로] | [설명] |
|
|
169
|
+
|
|
170
|
+
#### Phase 2: [단계명]
|
|
171
|
+
...
|
|
172
|
+
|
|
173
|
+
### 파일별 상세 구현
|
|
174
|
+
|
|
175
|
+
#### `src/components/NewComponent.tsx` (신규)
|
|
176
|
+
```tsx
|
|
177
|
+
// 주요 구조 스케치
|
|
178
|
+
interface Props {
|
|
179
|
+
// ...
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function NewComponent({ ... }: Props) {
|
|
183
|
+
// 주요 로직 설명
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**구현 포인트:**
|
|
188
|
+
- [포인트 1]
|
|
189
|
+
- [포인트 2]
|
|
190
|
+
|
|
191
|
+
#### `src/hooks/useNewHook.ts` (신규)
|
|
192
|
+
...
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 4. 설계 검증 결과
|
|
197
|
+
|
|
198
|
+
### fundamentals-code 검증
|
|
199
|
+
| 원칙 | 상태 | 피드백 |
|
|
200
|
+
|------|------|--------|
|
|
201
|
+
| 가독성 | ✅/🟡/🔴 | [피드백] |
|
|
202
|
+
| 예측 가능성 | ✅/🟡/🔴 | [피드백] |
|
|
203
|
+
| 응집도 | ✅/🟡/🔴 | [피드백] |
|
|
204
|
+
| 결합도 | ✅/🟡/🔴 | [피드백] |
|
|
205
|
+
|
|
206
|
+
### refactor-analyzer 검증
|
|
207
|
+
**추상화 기회:**
|
|
208
|
+
- [기회 1]: [설명]
|
|
209
|
+
- [기회 2]: [설명]
|
|
210
|
+
|
|
211
|
+
**재사용 제안:**
|
|
212
|
+
- [제안 1]
|
|
213
|
+
|
|
214
|
+
### react-principles-reviewer 검증 (React 프로젝트)
|
|
215
|
+
| 원칙 | 상태 | 피드백 |
|
|
216
|
+
|------|------|--------|
|
|
217
|
+
| 컴포넌트 응집도 | ✅/🟡/🔴 | [피드백] |
|
|
218
|
+
| Props 설계 | ✅/🟡/🔴 | [피드백] |
|
|
219
|
+
| 상태 관리 | ✅/🟡/🔴 | [피드백] |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 5. 주의사항
|
|
224
|
+
|
|
225
|
+
### 잠재적 이슈
|
|
226
|
+
- ⚠️ [이슈 1]: [설명 및 대응 방안]
|
|
227
|
+
- ⚠️ [이슈 2]: [설명 및 대응 방안]
|
|
228
|
+
|
|
229
|
+
### 엣지 케이스
|
|
230
|
+
- [케이스 1]: [처리 방법]
|
|
231
|
+
- [케이스 2]: [처리 방법]
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 6. 테스트 전략
|
|
236
|
+
|
|
237
|
+
### 단위 테스트
|
|
238
|
+
| 대상 | 테스트 케이스 |
|
|
239
|
+
|------|--------------|
|
|
240
|
+
| [컴포넌트/함수] | [테스트 케이스 목록] |
|
|
241
|
+
|
|
242
|
+
### 통합 테스트
|
|
243
|
+
- [테스트 시나리오 1]
|
|
244
|
+
- [테스트 시나리오 2]
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 7. 다음 단계
|
|
249
|
+
|
|
250
|
+
구현을 시작하려면:
|
|
251
|
+
1. Phase 1부터 순서대로 진행
|
|
252
|
+
2. 각 파일 구현 후 테스트 확인
|
|
253
|
+
3. [추가 안내사항]
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 사용 예시
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# 1. 먼저 설계/요구사항 설명
|
|
262
|
+
"사용자 프로필 페이지를 만들어야 해.
|
|
263
|
+
- 프로필 이미지, 이름, 이메일 표시
|
|
264
|
+
- 프로필 수정 모달
|
|
265
|
+
- 비밀번호 변경 기능
|
|
266
|
+
- 계정 삭제 기능"
|
|
267
|
+
|
|
268
|
+
# 2. 커맨드 실행
|
|
269
|
+
/design-to-code
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## 중요 사항
|
|
275
|
+
|
|
276
|
+
- **컨텍스트 의존**: 대화에서 설계/요구사항을 읽어옴
|
|
277
|
+
- **병렬 실행**: 검증 에이전트들은 병렬로 실행하여 효율성 확보
|
|
278
|
+
- **React 자동 감지**: package.json 또는 파일 확장자로 React 프로젝트 감지
|
|
279
|
+
- **구체적 파일 경로**: 생성/수정할 파일의 정확한 경로 명시
|
|
280
|
+
- **코드 스케치 포함**: 주요 구조와 인터페이스를 코드로 표현
|
|
281
|
+
- **한국어 출력**: 최종 리포트는 한국어로
|
|
282
|
+
- **결과 파일 저장**: 최종 리포트를 `design-to-code.md` 파일로 저장 (이미 존재하면 `---` 구분선과 함께 하단에 추가)
|
package/commands/figma-check.md
CHANGED
package/commands/review-pr.md
CHANGED
|
@@ -23,6 +23,7 @@ Task 도구를 통해 다음 전문 에이전트를 사용할 수 있습니다:
|
|
|
23
23
|
| `refactor-analyzer` | 코드 중복, 복잡성, 추상화 기회, 코드 스멜 |
|
|
24
24
|
| `junior-checker` | 주니어 개발자 관점 가독성, 네이밍, 복잡도 |
|
|
25
25
|
| `react-performance-optimizer` | React 리렌더, 메모이제이션, 훅 최적화 |
|
|
26
|
+
| `react-principles-reviewer` | React 개발 원칙 (응집도/명시성, Props 관리, 네이밍, 부수효과, AsyncBoundary) |
|
|
26
27
|
|
|
27
28
|
## 사용 가능한 Skill
|
|
28
29
|
|
|
@@ -54,7 +55,7 @@ Skill은 사용자 설치에 따라 다르며 추가 리뷰 가이드라인/컨
|
|
|
54
55
|
|
|
55
56
|
| 옵션 | 이름 | 사용 에이전트 | 적합한 상황 |
|
|
56
57
|
|------|------|--------------|-------------|
|
|
57
|
-
| 1 | **전체 리뷰** | 모든
|
|
58
|
+
| 1 | **전체 리뷰** | 모든 6개 에이전트 병렬 실행 | 종합 코드 리뷰 (권장) |
|
|
58
59
|
| 2 | **커스텀** | 사용자가 직접 선택 | 특정 관점만 리뷰하고 싶을 때 |
|
|
59
60
|
|
|
60
61
|
3. **Skill 포함 여부 질문** (AskUserQuestion 사용)
|
package/docs/BUILDER_GUIDE.md
CHANGED
|
@@ -52,6 +52,7 @@ Builder가 자동으로:
|
|
|
52
52
|
| `junior-checker` | 주니어 친화성 |
|
|
53
53
|
| `fundamentals-code` | Toss Frontend Fundamentals 기반 분석 |
|
|
54
54
|
| `react-performance-optimizer` | React 성능 최적화 |
|
|
55
|
+
| `react-principles-reviewer` | React 개발 원칙 (응집도/명시성, Props 관리, 네이밍, 부수효과) |
|
|
55
56
|
|
|
56
57
|
### 커스터마이징 예시
|
|
57
58
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "binary-agents",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "Claude Code subagents and slash commands collection with sync CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/sync.js",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"binary-agents": "./bin/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"
|
|
11
|
+
"start": "node bin/cli.js",
|
|
12
12
|
"list": "node bin/cli.js list",
|
|
13
13
|
"release": "npm version patch && npm publish"
|
|
14
14
|
},
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"README.md"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"@inquirer/prompts": "^7.0.0",
|
|
40
41
|
"chalk": "^5.3.0",
|
|
41
|
-
"commander": "^12.0.0",
|
|
42
42
|
"ora": "^8.0.1"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|