| name | clean-code |
| version | 1.0.0 |
| description | Robert C. Martin의 클린 코드 원칙을 기반으로 코드를 분석하고 리팩토링합니다.
의미 있는 이름, 작은 함수, 단일 책임 원칙, SOLID 원칙, 주석 최소화, 오류 처리
등 클린 코드의 핵심 원칙을 적용합니다.
Use when asked to "클린코드", "clean-code", "clean code", "리팩토링", "코드 정리",
"클린 코드 원칙 적용", "clean code refactor". (gstack)
|
| allowed-tools | ["Bash","Read","Edit","Write","Grep","Glob","Agent","AskUserQuestion"] |
/clean-code — Robert C. Martin 클린 코드 리팩토링
로버트 C. 마틴의 클린 코드 원칙에 따라 코드를 분석하고 리팩토링합니다.
echo "=== Clean Code Refactoring Skill ==="
echo "Analyzing target: ${SKILL_ARGS:-'(no target specified)'}"
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "Branch: $_BRANCH"
분석 모드 결정
/clean-code 명령어 뒤에 파일 경로나 범위를 지정할 수 있습니다:
/clean-code — 현재 브랜치의 변경된 파일 전체 분석
/clean-code src/Foo.java — 특정 파일 분석 및 리팩토링
/clean-code --review — 리팩토링 없이 검토 보고서만 출력
/clean-code --fix — 검토 후 자동으로 수정 적용
인수가 없으면 git diff로 변경된 파일을 대상으로 합니다.
_ARGS="${SKILL_ARGS:-}"
if [ -z "$_ARGS" ]; then
echo "No target specified — using git diff"
git diff --name-only HEAD 2>/dev/null | head -20 || echo "(no changes)"
else
echo "Target: $_ARGS"
fi
분석 단계 (순서대로 실행)
1단계: 대상 파일 수집
인수가 없으면 git diff --name-only HEAD 로 변경 파일을 수집합니다.
--fix 플래그가 있으면 수정을 적용하고, 없으면 보고서만 출력합니다.
2단계: 각 파일에 대해 아래 클린 코드 체크리스트를 적용
클린 코드 체크리스트
각 파일을 읽고 아래 원칙들을 검토합니다. 위반 사항은 파일:라인 형식으로 기록합니다.
Chapter 2 — 의미 있는 이름 (Meaningful Names)
| # | 규칙 | 나쁜 예 | 좋은 예 |
|---|
| N1 | 의도를 드러내는 이름 | d, tmp, data | elapsedTimeInDays, userList |
| N2 | 그릇된 정보 피하기 | accountList (List가 아닐 때) | accounts, accountGroup |
| N3 | 의미 있게 구분하기 | a1, a2, theMessage | source, destination, message |
| N4 | 발음하기 쉬운 이름 | genymdhms | generationTimestamp |
| N5 | 검색하기 쉬운 이름 | 매직 넘버 7, 86400 | 상수 MAX_CLASSES_PER_STUDENT, SECONDS_PER_DAY |
| N6 | 인코딩 피하기 | m_name, IShapeFactory | name, ShapeFactory |
| N7 | 클래스명은 명사 | Manager, Processor (너무 모호) | Customer, WikiPage, Account |
| N8 | 메서드명은 동사 | name() | getName(), postPayment(), deletePage() |
| N9 | 한 개념에 한 단어 | fetch, retrieve, get 혼용 | 일관된 어휘 사용 |
Chapter 3 — 함수 (Functions)
| # | 규칙 | 기준 |
|---|
| F1 | 함수는 작게 | 20줄 이하 권장, 중첩 1~2단계 |
| F2 | 한 가지만 해야 한다 | 함수 이름을 한 문장으로 설명 가능해야 함 |
| F3 | 위에서 아래로 읽기 (신문 기사처럼) | 호출하는 함수가 먼저, 호출되는 함수가 아래 |
| F4 | Switch 문 최소화 | 다형성(Polymorphism)으로 대체 |
| F5 | 인수 최소화 | 3개 이하 권장; 4개 이상이면 객체로 묶기 |
| F6 | 부수 효과(Side Effect) 없애기 | 함수 이름에 없는 일을 하지 않음 |
| F7 | 명령과 조회 분리 (CQS) | set()은 값을 바꾸거나 bool을 반환하지 않음 |
| F8 | 오류 코드보다 예외 사용 | if (err != OK) → throw new Exception() |
| F9 | 반복하지 마라 (DRY) | 중복 코드 → 공통 함수 추출 |
Chapter 4 — 주석 (Comments)
| # | 규칙 |
|---|
| C1 | 코드로 표현할 수 있으면 주석 삭제 |
| C2 | TODO 주석은 곧바로 처리하거나 티켓으로 남기기 |
| C3 | 의무적으로 다는 Javadoc/JSDoc 피하기 |
| C4 | 이력이나 저작권 주석 피하기 (git이 대신) |
| C5 | 주석 처리된 코드 즉시 삭제 |
| C6 | 정말 필요한 주석: 법적 주석, 의도 설명, 경고, 공개 API 문서 |
Chapter 5 — 형식 맞추기 (Formatting)
| # | 규칙 |
|---|
| FM1 | 개념은 빈 줄로 구분 |
| FM2 | 관련 코드는 서로 붙이기 |
| FM3 | 변수 선언은 사용 위치 가까이 |
| FM4 | 인스턴스 변수는 클래스 최상단 |
| FM5 | 종속 함수는 호출하는 함수 직후 배치 |
Chapter 6 — 객체와 자료 구조 (Objects & Data Structures)
| # | 규칙 |
|---|
| O1 | 자료를 세부적으로 공개하지 않기 (캡슐화) |
| O2 | 디미터 법칙: a.b().c().d() 체이닝 금지 |
| O3 | DTO/Value Object는 public 필드 또는 getter만, 비즈니스 로직 없음 |
| O4 | 하이브리드 구조(절반은 객체, 절반은 자료구조) 피하기 |
Chapter 7 — 오류 처리 (Error Handling)
| # | 규칙 |
|---|
| E1 | 오류 코드 대신 예외 사용 |
| E2 | try-catch-finally 블록 먼저 작성 |
| E3 | 확인된 예외(Checked Exception) 남발 금지 |
| E4 | 예외 메시지에 충분한 정보 담기 |
| E5 | null 반환 금지 (빈 컬렉션, Optional 사용) |
| E6 | null 인수 전달 금지 |
Chapter 9 — 단위 테스트 (Unit Tests / FIRST)
| # | 규칙 |
|---|
| T1 | Fast — 테스트는 빨라야 한다 |
| T2 | Independent — 각 테스트는 독립적 |
| T3 | Repeatable — 어느 환경에서나 반복 가능 |
| T4 | Self-Validating — 테스트는 bool로 성공/실패 |
| T5 | Timely — 프로덕션 코드 직전에 작성 |
| T6 | 테스트당 assert 최소화, 개념 하나만 검증 |
Chapter 10 — 클래스 (Classes)
| # | 규칙 |
|---|
| CL1 | 단일 책임 원칙 (SRP): 클래스가 변경되는 이유는 하나뿐 |
| CL2 | 응집도(Cohesion) 높게: 메서드가 인스턴스 변수를 많이 사용 |
| CL3 | 개방-폐쇄 원칙 (OCP): 확장에 열려 있고, 변경에 닫혀 있음 |
| CL4 | 의존 역전 원칙 (DIP): 구체 클래스보다 추상화에 의존 |
Chapter 17 — 냄새와 휴리스틱 (Code Smells)
| # | 냄새 |
|---|
| S1 | 너무 긴 메서드 (Long Method) |
| S2 | 거대한 클래스 (Large Class) |
| S3 | 긴 매개변수 목록 (Long Parameter List) |
| S4 | 뒤엉킨 변경 (Divergent Change) |
| S5 | 산탄총 수술 (Shotgun Surgery) |
| S6 | 기능 편애 (Feature Envy) |
| S7 | 데이터 뭉치 (Data Clumps) |
| S8 | 기본형 집착 (Primitive Obsession) |
| S9 | Switch 문 남발 |
| S10 | 중복 코드 (Duplicated Code) |
| S11 | 죽은 코드 (Dead Code) |
| S12 | 과도한 주석 (Excessive Comments) |
출력 형식
분석 결과는 다음 형식으로 출력합니다:
## Clean Code 분석 보고서
### 파일: src/main/java/com/.../Foo.java
#### 심각도: 높음 🔴
- [F2] foo() 메서드가 여러 책임을 가짐 (L45-89): 데이터 조회, 변환, 저장을 한 메서드에서 처리
→ 리팩토링: fetchData(), transformData(), saveData()로 분리
#### 심각도: 중간 🟡
- [N1] 변수명 `d`가 의도 불명확 (L23): 어떤 데이터인지 알 수 없음
→ 리팩토링: `elapsedTimeInDays` 또는 `processingDate`로 변경
- [E5] null 반환 (L67): Optional이나 빈 컬렉션 반환 권장
#### 심각도: 낮음 🟢
- [C5] 주석 처리된 코드 존재 (L102-108)
→ 리팩토링: 삭제 (git history에 보존됨)
### 요약
- 🔴 높음: 2건
- 🟡 중간: 5건
- 🟢 낮음: 3건
- 총 10건의 클린 코드 위반 발견
실행 지침
--review 플래그가 있거나 플래그 없이 호출 시: 보고서만 출력, 파일 수정 없음
--fix 플래그가 있으면: 보고서 출력 후 AskUserQuestion으로 수정할 항목 확인, 승인된 항목만 Edit
- 특정 파일 경로가 인수로 주어지면 해당 파일만 분석
- 인수 없으면
git diff --name-only HEAD로 변경된 파일 목록을 구한 후 분석
- 한 번에 최대 10개 파일까지 처리 (너무 많으면 경고 후 우선순위 높은 파일부터)
우선순위
같은 심각도 내에서 아래 순으로 우선 처리합니다:
- 단일 책임 원칙 위반 (가장 큰 영향)
- null 반환 / null 인수 (런타임 오류 위험)
- 중복 코드 (DRY 위반)
- 의미 없는 이름
- 긴 함수 / 많은 인수
- 불필요한 주석