Files
gh-wasabeef-claude-code-coo…/commands/refactor.md
2025-11-30 09:05:40 +08:00

306 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Refactor
안전하고 단계적인 코드 리팩터링을 실시하며, SOLID 원칙의 준수 상황을 정량적으로 평가합니다. 기술적 부채를 가시화하고, 개선의 우선순위를 명확히 합니다.
### 사용법
```bash
# 복잡한 코드의 특정과 리팩터링 계획
find . -name "*.js" -exec wc -l {} + | sort -rn | head -10
「큰 파일을 리팩터링해서 복잡도를 삭감해 주세요」
# 중복 코드의 검출과 통합
grep -r "function processUser" . --include="*.js"
「중복된 함수를 Extract Method로 공통화해 주세요」
# SOLID 원칙 위반의 검출
grep -r "class.*Service" . --include="*.js" | head -10
「이러한 클래스가 단일 책임의 원칙에 따르고 있는지 평가해 주세요」
```
### 기본 예
```bash
# 긴 메서드의 검출
grep -A 50 "function" src/*.js | grep -B 50 -A 50 "return" | wc -l
"50 행 이상의 메서드를 Extract Method로 분할해 주세요"
# 조건 분기의 복잡도
grep -r "if.*if.*if" . --include="*.js"
"중첩된 조건문을 Strategy 패턴으로 개선해 주세요"
# 코드의 냄새 검출
grep -r "TODO\|FIXME\|HACK" . --exclude-dir=node_modules
"기술적 부채가 되고 있는 코멘트를 해결해 주세요"
```
### 리팩터링 기법
#### Extract Method(메서드 추출)
```javascript
// Before: 장대한 메서드
function processOrder(order) {
// 50 행의 복잡한 처리
}
// After: 책임 분리
function processOrder(order) {
validateOrder(order);
calculateTotal(order);
saveOrder(order);
}
```
#### Replace Conditional with Polymorphism
```javascript
// Before: switch 문
function getPrice(user) {
switch (user.type) {
case "premium":
return basePrice * 0.8;
case "regular":
return basePrice;
}
}
// After: Strategy 패턴
class PremiumPricing {
calculate(basePrice) {
return basePrice * 0.8;
}
}
```
### SOLID 원칙 스코어링(0-100 점)
#### 평가 기준과 배점
```text
S - Single Responsibility(20 점)
├─ 클래스의 책임 수: 1 개(20 점) | 2 개(15 점) | 3 개(10 점) | 4 개 이상(5 점)
├─ 메서드 수: <7 개(+5 점) | 7-15 개(+3 점) | >15 개(0 점)
├─ 변경 이유의 명확성: 명확(+5 점) | 모호(0 점)
└─ 스코어 예: UserService(인증+데이터 처리) = 10 점
O - Open/Closed(20 점)
├─ 확장 포인트: Strategy/Template Method(20 점) | 상속만(10 점) | 없음(5 점)
├─ 신기능 추가 시의 기존 코드 변경: 불필요(+5 점) | 최소한(+3 점) | 필요(0 점)
├─ 인터페이스 이용: 적절(+5 점) | 부분적(+3 점) | 없음(0 점)
└─ 스코어 예: PaymentProcessor(Strategy) = 20 점
L - Liskov Substitution(20 점)
├─ 파생 클래스의 계약 준수: 완전(20 점) | 부분적(10 점) | 위반(0 점)
├─ 사전 조건의 강화: 없음(+5 점) | 있음(-5 점)
├─ 사후 조건의 약화: 없음(+5 점) | 있음(-5 점)
└─ 스코어 예: Square extends Rectangle = 0 점(위반)
I - Interface Segregation(20 점)
├─ 인터페이스 크기: 1-3 메서드(20 점) | 4-7(15 점) | 8+(5 점)
├─ 미사용 메서드 구현: 없음(+5 점) | 1-2 개(+2 점) | 3 개 이상(0 점)
├─ 역할의 명확성: 단일 역할(+5 점) | 복수 역할(0 점)
└─ 스코어 예: Readable/Writable 분리 = 20 점
D - Dependency Inversion(20 점)
├─ 의존 방향: 추상만(20 점) | 혼재(10 점) | 구상만(5 점)
├─ DI 이용: Constructor Injection(+5 점) | Setter(+3 점) | 없음(0 점)
├─ 테스트 가능성: Mock 가능(+5 점) | 곤란(0 점)
└─ 스코어 예: Repository Pattern = 20 점
총합 스코어 = S + O + L + I + D
├─ 90-100 점: Excellent(SOLID 완전 준수)
├─ 70-89 점: Good(경미한 개선 여지)
├─ 50-69 점: Fair(리팩터링 권장)
├─ 30-49 점: Poor(대규모 개선 필요)
└─ 0-29 점: Critical(설계 재검토 필수)
```
### 기술적 부채의 정량화
#### 부채 계산식
```text
기술적 부채(시간) = 복잡도 스코어 × 영향 범위 × 수정 난이도
복잡도 스코어:
├─ 순환적 복잡도: 1-5(낮음) | 6-10(중간) | 11-20(높음) | 21+(위험)
├─ 인지적 복잡도: 중첩 깊이 × 조건 분기 수
├─ 코드 행수: <50(1 점) | 50-200(2 점) | 200-500(3 점) | 500+(5 점)
└─ 중복률: 0-10%(1 점) | 10-30%(2 점) | 30-50%(3 점) | 50%+(5 점)
영향 범위:
├─ 의존 모듈 수: 직접 의존 + 간접 의존 × 0.5
├─ 이용 빈도: API 호출 횟수/일
├─ 비즈니스 중요도: Critical(×3) | High(×2) | Medium(×1) | Low(×0.5)
└─ 팀 지식: 이해자 1 명(×3) | 2-3 명(×2) | 4 명 이상(×1)
수정 난이도:
├─ 테스트 커버리지: 0%(×3) | <50%(×2) | 50-80%(×1.5) | >80%(×1)
├─ 문서: 없음(×2) | 불충분(×1.5) | 충분(×1)
├─ 의존 관계: 밀결합(×3) | 중간 정도(×2) | 소결합(×1)
└─ 변경 위험: Breaking Change(×3) | 호환성 고려(×2) | 안전(×1)
비용 환산:
├─ 시간 비용: 부채 시간 × 개발자 시급
├─ 기회 손실: 신기능 개발 지연 일수 × 일차 매출 영향
├─ 품질 비용: 버그 발생 확률 × 수정 비용 × 발생 빈도
└─ 총 비용: 시간 + 기회 손실 + 품질 비용
```
#### 우선순위 매트릭스
| 우선도 | 영향도 | 수정 비용 | 대응 기한 | 구체예 | 권장 액션 |
| -------------------------- | ------ | --------- | ----------- | ------------------------------- | --------------------------- |
| **Critical(즉시 대응)** | 높음 | 낮음 | 1 주일 이내 | God Object、순환 의존 | 즉시 리팩터링 시작 |
| **Important(계획적 대응)** | 높음 | 높음 | 1 개월 이내 | 대규모 책임 분리、아키텍처 변경 | 스프린트 계획에 포함 |
| **Watch(감시 대상)** | 낮음 | 높음 | 3 개월 이내 | 복잡도가 높은 내부 처리 | 메트릭스 감시、악화 시 대응 |
| **Acceptable(허용 범위)** | 낮음 | 낮음 | 대응 불요 | 경미한 코드의 냄새 | 통상 리팩터링으로 대응 |
### 리팩터링 수순
1. **현상 분석과 측정**
- 복잡도 측정(순환적・인지적)
- SOLID 스코어 산출(0-100 점)
- 기술적 부채의 정량화(시간/비용)
- 우선순위 매트릭스 작성
2. **단계적 실행**
- 작은 스텝(15-30 분 단위)
- 각 변경 후의 테스트 실행
- 빈번한 커밋
- SOLID 스코어의 계속 측정
3. **품질 확인**
- 테스트 커버리지 유지
- 퍼포먼스 측정
- 기술적 부채의 삭감 확인
- 코드 리뷰
### 자주 있는 코드의 냄새와 부채 스코어
| 코드의 냄새 | 검출 기준 | 부채 스코어 | 개선 기법 |
| ----------------------- | --------------------------- | ------------- | ----------------------- |
| **God Object** | 책임 >3, 메서드 >20 | 높음 (15-20h) | Extract Class, SRP 적용 |
| **Long Method** | 행수 >50, 복잡도 >10 | 중간 (5-10h) | Extract Method |
| **Duplicate Code** | 중복률 >30% | 높음 (10-15h) | Extract Method/Class |
| **Large Class** | 행수 >300, 메서드 >15 | 높음 (10-20h) | Extract Class |
| **Long Parameter List** | 파라미터 >4 | 낮음 (2-5h) | Parameter Object |
| **Feature Envy** | 다른 클래스 참조 >5 | 중간 (5-10h) | Move Method |
| **Data Clumps** | 같은 인수군의 반복 | 낮음 (3-5h) | Extract Class |
| **Primitive Obsession** | 프리미티브 타입의 과도 사용 | 중간 (5-8h) | Replace with Object |
| **Switch Statements** | case >5 | 중간 (5-10h) | Strategy Pattern |
| **Shotgun Surgery** | 변경 시의 영향 개소 >3 | 높음 (10-15h) | Move Method/Field |
### 실천 예SOLID 스코어 평가
```javascript
// 평가 대상: UserService 클래스
class UserService {
constructor(db, cache, logger, emailService) { // 4 개의 의존
this.db = db;
this.cache = cache;
this.logger = logger;
this.emailService = emailService;
}
// 책임 1: 인증
authenticate(username, password) { /* ... */ }
refreshToken(token) { /* ... */ }
// 책임 2: 사용자 관리
createUser(data) { /* ... */ }
updateUser(id, data) { /* ... */ }
deleteUser(id) { /* ... */ }
// 책임 3: 알림
sendWelcomeEmail(user) { /* ... */ }
sendPasswordReset(email) { /* ... */ }
}
// SOLID 스코어 평가 결과
S: 10 (책임 3 : 인증CRUD알림)
O: 5 (확장 포인트 없음직접 구현)
L: 15 (상속 없음해당 없음)
I: 10 (인터페이스 미분리)
D: 10 (구상 클래스 의존)
총합: 50 (Fair - 리팩터링 권장)
// 기술적 부채
복잡도: 15 (메서드 7 책임 3 )
영향 범위: 8 (인증은 기능에서 사용)
수정 난이도: 2 (테스트 있음문서 부족)
부채 시간: 15 × 8 × 2 = 240 시간
우선도: Critical (인증계는 즉시 대응)
```
### 개선 후의 구현 예
```javascript
// SOLID 원칙 적용 후 (스코어: 90 점)
// S: 단일 책임 (20 점)
class AuthenticationService {
authenticate(credentials) { /* ... */ }
refreshToken(token) { /* ... */ }
}
// O: 개방 폐쇄 (20 점)
class UserRepository {
constructor(storage) { // Strategy Pattern
this.storage = storage;
}
save(user) { return this.storage.save(user); }
}
// I: 인터페이스 분리 (20 점)
interface Readable {
find(id);
findAll();
}
interface Writable {
save(entity);
delete(id);
}
// D: 의존성 역전 (20 점)
class UserService {
constructor(
private auth: IAuthService,
private repo: IUserRepository,
private notifier: INotificationService
) {}
}
// 부채 삭감: 240 시간 → 20 시간 (92% 삭감)
```
### 자동화 지원
```bash
# SOLID 스코어 측정
npx solid-analyzer src/ --output report.json
# 복잡도 분석
npx complexity-report src/ --format json
sonar-scanner -Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
# 기술적 부채의 가시화
npx code-debt-analyzer --config .debt.yml
# 코드 포맷
npm run lint:fix
prettier --write src/
# 테스트 실행과 커버리지
npm test -- --coverage
npm run test:mutation # 변이 테스트
```
### 주의사항
- **기능 변경의 금지**: 외부 동작을 바꾸지 않음
- **테스트 퍼스트**: 리팩터링 전에 테스트 추가
- **단계적 접근**: 한번에 큰 변경을 하지 않음
- **계속적 검증**: 각 스텝에서의 테스트 실행