켄트 벡의 Tidy First?
tidy-first
- 켄트 벡의 Tidy First?
- Ch01. Guard Clauses
- Ch02. Dead Code
- Ch03. Normalize Symmetries
- Ch04. New Interface, Old Implementation
- Ch05. Reading Order
- Ch06. Cohesion Order
- Ch07. Move Declaration and Initialization Together
- Ch08. Explaining Variables
- Ch09. Explaining Constants
- Ch10. Explicit Parameters
- Ch11. Chunk Statements
- Ch12. Extract Helper
- Ch13. One Pile
- Ch14. Explaining Comments
- Ch15. Delete Redundant Comments
- Ch16. Separate Tidying
- Ch17. Chaining
- Ch18. Batch Sizes
- Ch19. Rhythm
- Ch20. Getting Untangled
- Ch21. First, After, Later, Never
- Ch22. Beneficially Relating Elements
- Ch23. Structure and Behavior
- Ch24. Economics: Time Value and Optionality
- Ch25. A Dollar Today > A Dollar Tomorrow
- Ch26. Options
- Ch27. Options Versus Cash Flows
- Ch28. Reversible Structure Changes
- Ch29. Coupling
- Ch30. Constantine's Equivalence
- Ch31. Coupling Versus Decoupling
- Ch32. Cohesion
- Ch33. Conclusion
- ADR001. Tidy First 워크플로우 도입
- ADR002. 정리 타이밍 결정 기준
켄트 벡의 Tidy First?
Ch01. Guard Clauses
TL;DR
- 조건문 중첩 대신 Guard Clause를 사용해 빠르게 반환하면 코드가 더 읽기 쉬워진다.
- Guard Clause는 "이 조건이 아니면 여기서 끝"이라는 의도를 명확히 전달한다.
Key Ideas
- Guard Clause: 함수 시작부에서 예외 상황을 먼저 처리하고 빠르게 반환하는 패턴
- 중첩된 if-else 구조는 인지 부하를 증가시킨다
- "Happy Path"를 마지막에 두면 핵심 로직이 더 명확해진다
Open Questions
- Guard Clause가 너무 많아지면 어떻게 해야 할까?
- 5개 이상의 Guard Clause가 있다면 함수가 너무 많은 일을 하고 있을 수 있다
- 책임 분리를 고려해볼 시점이다
Ch02. Dead Code
TL;DR
- 죽은 코드는 발견하는 즉시 삭제하라.
- 버전 관리 시스템이 있으니 "나중에 필요할지 모른다"는 걱정은 불필요하다.
Key Ideas
- Dead Code: 실행되지 않는 코드, 도달할 수 없는 코드
- 죽은 코드는 읽는 사람을 혼란스럽게 만든다
- 주석 처리된 코드도 죽은 코드다
- 코드를 지우는 것이 가장 좋은 정리법이다
Open Questions
- 죽은 코드인지 확신이 없을 때는?
- 테스트 커버리지 도구 활용
- Feature Flag로 감싸서 점진적으로 확인
- 로그를 추가해서 실제 호출 여부 확인
Ch03. Normalize Symmetries
TL;DR
- 같은 일을 하는 코드는 같은 방식으로 작성하라.
- 대칭성은 코드의 예측 가능성을 높인다.
Key Ideas
- 코드의 대칭성: 유사한 작업은 유사한 구조로 표현
- 일관되지 않은 스타일은 "왜 다르게 했지?"라는 불필요한 질문을 유발한다
- 대칭성을 맞추면 패턴을 인식하기 쉬워진다
Open Questions
- 레거시 코드에서 대칭성을 맞추는 우선순위는?
- 자주 수정되는 파일부터
- 팀원들이 혼란을 느끼는 부분부터
- 새로운 기능 추가와 함께 점진적으로
Ch04. New Interface, Old Implementation
TL;DR
- 새로운 인터페이스를 먼저 만들고, 기존 구현을 그대로 유지하라.
- 인터페이스 변경과 구현 변경을 분리하면 리스크가 줄어든다.
Key Ideas
- 변경을 작은 단계로 나누는 전략
- 새 인터페이스가 기존 구현을 감싸는 방식 (Wrapper/Adapter)
- 호출하는 쪽을 먼저 개선하고, 나중에 내부를 개선한다
Open Questions
- 이 패턴은 언제 사용해야 할까?
- API 변경이 필요하지만 구현을 당장 바꾸기 어려울 때
- 점진적인 마이그레이션이 필요할 때
- 기존 구현의 테스트가 부족할 때
Ch05. Reading Order
TL;DR
- 코드를 읽는 순서대로 정렬하라.
- 위에서 아래로 자연스럽게 읽힐 수 있도록 배치한다.
Key Ideas
- 함수/메서드의 배치 순서가 가독성에 영향을 준다
- 호출하는 함수가 위에, 호출되는 함수가 아래에
- 또는 추상화 수준이 높은 것이 위에, 세부 구현이 아래에
Open Questions
- 상호 참조가 있을 때는?
- 순환 의존이 있다면 구조적 문제일 수 있다
- 관련된 함수들을 그룹으로 묶어서 배치
- 필요하다면 별도 모듈/클래스로 분리
Ch06. Cohesion Order
TL;DR
- 함께 변경되는 코드는 함께 배치하라.
- 응집도가 높으면 변경의 영향 범위가 줄어든다.
Key Ideas
- Temporal Cohesion: 동시에 변경되는 코드는 가까이 둔다
- 관련 있는 코드가 떨어져 있으면 변경 시 실수할 확률이 높아진다
- 파일 내에서도, 모듈 간에도 응집도를 고려한다
Open Questions
- 응집도와 읽기 순서가 충돌할 때는?
- 일반적으로 응집도가 우선
- 자주 함께 변경되는 코드가 가까이 있으면 실수를 줄일 수 있다
Ch07. Move Declaration and Initialization Together
TL;DR
- 변수 선언과 초기화는 가능한 한 가까이 두라.
- 선언과 사용 사이의 거리가 멀수록 코드를 이해하기 어렵다.
Key Ideas
- 변수의 스코프를 최소화
- "이 변수가 뭐였지?" 하며 위로 스크롤하는 일을 줄인다
- 필요한 시점에 선언하고 바로 초기화
Open Questions
- 언어별 제약이 있을 때는?
- C 같은 언어는 함수 시작부에 선언해야 할 수 있다
- 그래도 초기화는 사용 직전에 하도록 분리 가능
Ch08. Explaining Variables
TL;DR
- 복잡한 표현식에 이름을 붙여라.
- 중간 결과에 의미 있는 이름을 부여하면 코드가 문서화된다.
Key Ideas
- Explaining Variable: 계산의 중간 결과에 의미 있는 이름을 부여
if (user.age >= 18 && user.hasValidId)보다isEligible = ...- 디버깅할 때도 중간 값을 확인하기 쉽다
Open Questions
- 너무 많은 중간 변수는 오히려 해롭지 않을까?
- 변수가 표현식보다 명확할 때만 도입
- 한 줄짜리 단순 표현식은 그대로 두는 것이 나을 수 있다
Ch09. Explaining Constants
TL;DR
- 매직 넘버를 상수로 추출하라.
- 이름이 있는 상수는 "왜 이 값인가"를 설명한다.
Key Ideas
- Magic Number: 의미를 알 수 없는 숫자 리터럴
timeout = 30000보다timeout = THIRTY_SECONDS_MS- 상수 이름이 도메인 지식을 전달한다
Open Questions
- 모든 숫자를 상수로 만들어야 할까?
- 0, 1, -1 같은 관용적 값은 그대로 둬도 된다
- 비즈니스 규칙이나 설정값은 상수로
- "이 값이 왜 이 숫자인지" 설명이 필요하면 상수로
Ch10. Explicit Parameters
TL;DR
- 암묵적 의존성을 명시적 파라미터로 바꿔라.
- 함수가 무엇에 의존하는지 시그니처만 봐도 알 수 있어야 한다.
Key Ideas
- 전역 변수, 싱글톤 접근을 파라미터로 대체
- 함수의 순수성이 높아진다
- 테스트하기 쉬워진다
Open Questions
- 파라미터가 너무 많아지면?
- 파라미터 객체로 묶기
- 함수가 너무 많은 일을 하고 있다는 신호일 수 있다
- 의존성 주입 컨테이너 활용
Ch11. Chunk Statements
TL;DR
- 관련된 문장들을 빈 줄로 그룹화하라.
- 시각적 그룹화가 논리적 구조를 드러낸다.
Key Ideas
- 빈 줄은 "여기서 새로운 생각이 시작된다"를 표현
- 문단처럼 코드를 나눈다
- Extract Method의 전 단계로 활용 가능
Open Questions
- 청킹과 함수 추출의 기준은?
- 청킹만으로 충분히 명확하면 그대로 둔다
- 재사용이 필요하거나 이름을 붙이고 싶으면 함수로 추출
- 청킹된 부분에 주석이 필요하면 함수 추출 신호
Ch12. Extract Helper
TL;DR
- 반복되거나 복잡한 로직을 헬퍼 함수로 추출하라.
- 좋은 이름의 헬퍼 함수는 코드의 의도를 명확히 한다.
Key Ideas
- Helper Function: 특정 작업을 수행하는 작은 함수
- 추상화 수준을 맞춘다 (한 함수 내에서 추상화 수준 일관성)
- "어떻게"보다 "무엇을"이 드러나게 한다
Open Questions
- 헬퍼 함수의 적절한 크기는?
- 한 가지 일만 하는 것
- 이름으로 설명할 수 있는 것
- 너무 작으면 오히려 흐름을 끊을 수 있다
Ch13. One Pile
TL;DR
- 때로는 분리된 코드를 하나로 모으는 것이 정리의 첫 걸음이다.
- 잘못 나뉜 코드는 하나로 합친 뒤 다시 나누는 게 낫다.
Key Ideas
- 과도한 추상화, 잘못된 분리를 되돌리기
- 전체 그림을 보기 위해 먼저 모은다
- 인라인(Inline) 리팩토링
Open Questions
- 언제 합쳐야 할까?
- 추상화가 이해를 방해할 때
- 분리된 조각들을 왔다 갔다 하며 읽어야 할 때
- 각 조각이 너무 작아서 의미가 없을 때
Ch14. Explaining Comments
TL;DR
- 코드가 "왜"를 설명하지 못할 때만 주석을 달라.
- 좋은 주석은 코드가 전달할 수 없는 맥락을 제공한다.
Key Ideas
- What/How 주석보다 Why 주석
- 비즈니스 규칙의 배경
- 의도적인 설계 결정의 이유
- 임시 해결책(Workaround)의 이유
Open Questions
- 좋은 주석의 예시?
- "RFC 7231 섹션 6.5.4에 따라 404 반환"
- "레거시 시스템 호환을 위해 이 형식 유지"
- "이 순서를 바꾸면 데드락 발생 (ISSUE-123 참고)"
Ch15. Delete Redundant Comments
TL;DR
- 코드가 이미 말하고 있는 것을 반복하는 주석은 삭제하라.
- 중복 주석은 유지보수 부담이고 거짓말이 될 수 있다.
Key Ideas
- 코드와 주석이 같은 말을 하면 주석은 불필요
i++; // i를 1 증가같은 주석- 코드가 변경되면 주석이 거짓이 된다
Open Questions
- 주석을 지우기 전에 확인할 것은?
- 주석이 정말로 중복인지 (미묘한 뉘앙스가 있을 수 있다)
- 지운 후에도 코드가 명확한지
- 필요하다면 코드 자체를 더 명확하게 수정
Ch16. Separate Tidying
TL;DR
- 정리(Tidying)와 동작 변경(Behavior Change)을 별도의 커밋/PR로 분리하라.
- 분리하면 리뷰가 쉬워지고, 롤백도 안전해진다.
Key Ideas
- 정리 커밋: 동작 변경 없이 구조만 개선
- 동작 변경 커밋: 기능 추가/수정
- 두 가지가 섞이면 리뷰어가 "이게 버그인가 리팩토링인가" 구분하기 어렵다
- 정리 커밋은 테스트 변경 없이 통과해야 한다
Open Questions
- 정리와 동작 변경이 강하게 결합되어 있으면?
- 그래도 분리를 시도해볼 가치가 있다
- 정리를 먼저 하고, 그 위에 동작 변경을 적용
- 불가능하면 커밋 메시지에 명확히 표시
Ch17. Chaining
TL;DR
- 작은 정리들을 연쇄적으로 적용하라.
- 하나의 정리가 다음 정리의 기회를 만든다.
Key Ideas
- 정리는 연쇄 반응을 일으킨다
- Guard Clause -> Dead Code 삭제 -> 변수 인라인
- 작은 단계를 밟으면 큰 변화도 안전하게 달성할 수 있다
- 각 단계가 테스트를 통과하면 언제든 멈출 수 있다
Open Questions
- 연쇄 정리의 끝은 어디인가?
- 다음 정리가 보이지 않을 때
- 충분히 좋아졌다고 느낄 때
- 시간 박스를 정해놓고 그 안에서만
Ch18. Batch Sizes
TL;DR
- 정리의 배치 크기는 작게 유지하라.
- 작은 배치가 빠른 피드백과 낮은 리스크를 제공한다.
Key Ideas
- 배치 크기(Batch Size): 한 번에 정리하는 양
- 큰 리팩토링 PR은 리뷰하기 어렵다
- 작은 변경은 머지 충돌이 적다
- 점진적 개선이 빅뱅 리팩토링보다 안전하다
Open Questions
- 최적의 배치 크기는?
- 10분 ~ 1시간 정도의 작업량
- 리뷰어가 컨텍스트 스위칭 없이 이해할 수 있는 양
- "이 PR은 한 가지 정리만 한다"고 설명할 수 있는 양
Ch19. Rhythm
TL;DR
- 정리에도 리듬이 필요하다.
- 기능 개발 사이사이에 정리 시간을 확보하라.
Key Ideas
- 정리를 위한 시간을 의도적으로 만든다
- "기능 -> 정리 -> 기능 -> 정리"의 반복
- 몰아서 정리하는 것보다 꾸준히 정리하는 것이 낫다
- 보이스카우트 규칙: 캠프장을 떠날 때 왔을 때보다 깨끗하게
Open Questions
- 팀에서 정리 시간을 어떻게 확보할까?
- 스프린트에 정리 스토리 포함
- PR마다 작은 정리를 포함하는 문화
- 주기적인 "정리 데이" 운영
Ch20. Getting Untangled
TL;DR
- 코드가 엉켜있을 때, 작은 정리부터 시작해서 풀어나가라.
- 엉킨 코드도 한 올씩 풀면 정리할 수 있다.
Key Ideas
- 복잡한 코드는 한 번에 정리할 수 없다
- 가장 쉬운 정리부터 시작
- 정리하면서 다음에 할 정리가 보인다
- 인내심을 갖고 점진적으로
Open Questions
- 너무 엉켜있어서 어디서부터 시작할지 모를 때?
- 가장 자주 수정하는 파일부터
- 가장 최근에 버그가 발생한 곳부터
- 새 기능을 추가해야 하는 곳부터
Ch21. First, After, Later, Never
TL;DR
- 정리의 타이밍을 결정하라: 먼저(First), 후에(After), 나중에(Later), 안 함(Never).
- 모든 코드를 정리할 필요는 없다.
Key Ideas
- First: 기능 변경 전에 정리 (변경을 쉽게 만들기 위해)
- After: 기능 변경 후에 정리 (방금 만든 혼란 정리)
- Later: 별도의 시간에 정리 (지금 당장은 아니지만 필요함)
- Never: 정리하지 않음 (비용 대비 효과 없음)
Open Questions
- 언제 "Never"를 선택해야 할까?
- 곧 삭제될 코드
- 거의 수정되지 않는 안정적인 레거시
- 정리 비용이 효과보다 클 때
- 언제 "First"를 선택해야 할까?
- 현재 상태로는 기능 추가가 위험할 때
- 정리가 기능 변경을 크게 단순화할 때
Ch22. Beneficially Relating Elements
TL;DR
- 소프트웨어 설계는 요소들 사이의 유익한 관계를 만드는 것이다.
- 정리는 이 관계를 개선하는 활동이다.
Key Ideas
- 소프트웨어 = 요소(Elements) + 관계(Relations)
- 요소: 함수, 클래스, 모듈, 서비스
- 관계: 호출, 의존, 포함
- "유익한(Beneficial)" 관계가 핵심 - 이해하기 쉽고, 변경하기 쉬운 관계
Open Questions
- 유익한 관계란 무엇인가?
- 명확한 방향성 (A -> B, 양방향 아님)
- 최소한의 연결 (필요한 것만)
- 변경의 전파가 제한적
Ch23. Structure and Behavior
TL;DR
- 소프트웨어의 가치는 구조(Structure)와 동작(Behavior) 두 가지에서 나온다.
- 정리는 동작을 유지하면서 구조를 개선하는 것이다.
Key Ideas
- Behavior: 소프트웨어가 오늘 하는 일 (현재 가치)
- Structure: 소프트웨어를 내일 변경할 수 있게 하는 것 (미래 가치)
- 동작만 추가하면 구조가 무너진다
- 구조만 개선하면 아무것도 출시되지 않는다
- 둘 사이의 균형이 필요하다
Open Questions
- 구조와 동작 중 무엇이 더 중요한가?
- 단기적으로는 동작
- 장기적으로는 구조
- 정리는 구조에 투자하는 것
Ch24. Economics: Time Value and Optionality
TL;DR
- 소프트웨어 설계 결정은 경제적 관점에서 바라봐야 한다.
- 시간 가치(Time Value)와 선택권(Optionality)이 핵심 개념이다.
Key Ideas
- Time Value of Money: 오늘의 1달러가 내일의 1달러보다 가치있다
- Optionality: 선택할 수 있는 권리의 가치
- 정리는 미래의 선택권을 확보하는 투자
- 정리 비용 vs 정리로 인한 미래 이익
Open Questions
- 정리의 경제적 가치를 어떻게 측정할까?
- 변경 비용 감소
- 버그 발생 확률 감소
- 팀원 온보딩 시간 단축
- 직접 측정은 어렵지만 방향성은 명확하다
Ch25. A Dollar Today > A Dollar Tomorrow
TL;DR
- 오늘의 수익이 내일의 수익보다 가치있다.
- 이 원칙은 정리 타이밍 결정에도 적용된다.
Key Ideas
- 할인율(Discount Rate): 미래 가치를 현재 가치로 환산
- 빨리 출시하면 빨리 수익 발생
- 하지만 구조가 나쁘면 미래 비용이 증가
- 정리의 타이밍 = 현재 비용 vs 미래 이익의 현재 가치
Open Questions
- 정리를 미루는 것이 합리적인 경우는?
- 출시 압박이 클 때 (할인율이 높을 때)
- 요구사항이 불확실할 때
- 코드가 곧 삭제될 때
Ch26. Options
TL;DR
- 좋은 구조는 선택권(Options)을 만든다.
- 선택권은 불확실성이 클수록 가치있다.
Key Ideas
- Option: 의무 없이 행동할 수 있는 권리
- 유연한 구조 = 많은 선택권 = 높은 가치
- 선택권의 가치는 불확실성에서 온다
- 미래가 예측 불가능할수록 유연성이 중요하다
Open Questions
- 어떤 종류의 선택권이 가치있는가?
- 기술 스택 변경 가능성
- 기능 추가/수정 용이성
- 확장/축소 가능성
- 팀 구조 변경 대응
Ch27. Options Versus Cash Flows
TL;DR
- 정리는 현금 흐름(Cash Flow)을 줄이고 선택권(Options)을 늘리는 교환이다.
- 이 균형을 이해하면 정리 타이밍을 더 잘 판단할 수 있다.
Key Ideas
- Cash Flow: 당장 출시해서 얻는 수익
- Options: 미래에 더 쉽게 변경할 수 있는 가능성
- 정리에 시간을 쓰면 출시가 늦어진다 (Cash Flow ↓)
- 하지만 미래 변경이 쉬워진다 (Options ↑)
- 스타트업 초기: Cash Flow 우선
- 성숙한 제품: Options 우선
Open Questions
- 우리 팀은 어디에 있는가?
- 시장 검증 전이면 Cash Flow 우선
- 제품이 안정되었으면 Options에 투자
Ch28. Reversible Structure Changes
TL;DR
- 구조 변경은 대부분 되돌릴 수 있다.
- 되돌릴 수 있기에 정리를 두려워할 필요 없다.
Key Ideas
- 정리는 되돌릴 수 있는 변경
- 버전 관리 시스템이 안전망
- 테스트가 동작 보존을 검증
- 실패하면 롤백하면 된다
Open Questions
- 되돌리기 어려운 변경은?
- 데이터 마이그레이션
- 외부 API 변경
- 성능 최적화 (측정 필요)
- 이런 변경은 더 신중하게
Ch29. Coupling
TL;DR
- 결합(Coupling)은 한 요소의 변경이 다른 요소의 변경을 요구하는 것이다.
- 결합을 줄이는 것이 좋은 설계의 핵심이다.
Key Ideas
- Coupling: A가 변경되면 B도 변경해야 함
- 결합의 종류: 데이터 결합, 제어 결합, 내용 결합
- 결합이 높으면 변경 비용이 기하급수적으로 증가
- 정리는 결합을 줄이는 활동
Open Questions
- 결합을 완전히 없앨 수 있는가?
- 불가능하고 불필요하다
- 의미 있는 시스템은 연결되어 있다
- 목표는 불필요한 결합 제거
Ch30. Constantine's Equivalence
TL;DR
- 변경 비용 ≈ 결합도.
- 결합을 줄이면 변경 비용이 줄어든다.
Key Ideas
- Larry Constantine의 통찰
- 시스템 변경 비용 = 변경되는 요소 수에 비례
- 결합이 높으면 연쇄 변경 발생
- 결합이 낮으면 변경이 국소화됨
Open Questions
- 결합을 측정할 수 있는가?
- 변경 시 함께 수정되는 파일 수
- 의존성 그래프 분석
- 커밋 히스토리에서 동시 변경 패턴
Ch31. Coupling Versus Decoupling
TL;DR
- 결합을 줄이는 것(Decoupling)에도 비용이 든다.
- 모든 결합을 제거하려 하지 말고, 변경이 잦은 곳에 집중하라.
Key Ideas
- Decoupling 비용: 인터페이스 추가, 간접층 증가, 복잡성 증가
- 변경이 없는 곳의 결합은 문제가 아니다
- 자주 변경되는 곳의 결합이 진짜 문제
- 정리 우선순위 = 변경 빈도 × 결합도
Open Questions
- 과도한 Decoupling의 신호는?
- 간접층이 너무 많아 흐름 파악이 어려움
- 추상화가 구체적 구현보다 복잡함
- "어디서 실제로 일어나는 거지?" 질문이 자주 나옴
Ch32. Cohesion
TL;DR
- 응집(Cohesion)은 함께 변경되어야 하는 것들이 함께 있는 것이다.
- 높은 응집도는 변경을 단순하게 만든다.
Key Ideas
- Cohesion: 관련된 것들이 함께 있음
- 높은 응집도 = 하나의 변경이 한 곳에서 해결됨
- 낮은 응집도 = 하나의 변경이 여러 곳에 퍼짐
- 응집도와 결합도는 반비례 관계
Open Questions
- 응집도를 높이는 방법은?
- 함께 변경되는 코드를 가까이 배치
- 관련 함수를 같은 클래스/모듈로
- 기능 단위로 패키지 구성 (기술 단위 X)
Ch33. Conclusion
TL;DR
- Tidy First는 작은 정리를 먼저 하고, 그 다음에 기능 변경을 하자는 철학이다.
- 정리는 동작 변경과 분리하고, 작게 유지하고, 꾸준히 하라.
Key Ideas
- 정리(Tidying)는 구조 개선, 동작은 유지
- "Tidy First?" = 정리를 먼저 할까? 라는 질문을 습관화
- 작은 정리의 연쇄가 큰 개선을 만든다
- 정리의 경제학: 비용 vs 선택권
Open Questions
- 내일부터 어떻게 시작할까?
- 코드를 읽을 때마다 "Tidy First?" 질문하기
- 기능 PR에 작은 정리 하나씩 포함하기
- 팀과 정리의 가치에 대해 대화하기
ADR001. Tidy First 워크플로우 도입
Context
- 현재 팀에서는 기능 개발과 리팩토링이 혼재된 PR이 자주 발생한다.
- 리뷰어 입장에서 "이건 버그 수정인가, 리팩토링인가?" 구분이 어렵다.
- 대규모 리팩토링 PR은 리뷰가 지연되고, 머지 충돌이 빈번하다.
- Tidy First 책의 원칙을 팀 워크플로우에 적용하고자 한다.
Decision
- 정리와 동작 변경 분리: 하나의 PR에 정리(Tidying)와 기능 변경을 섞지 않는다.
- 정리 먼저 (Tidy First): 기능 변경 전에 필요한 정리를 먼저 수행하고 머지한다.
- 작은 배치: 정리 PR은 10분~1시간 분량으로 유지한다.
- 커밋 컨벤션: 정리 커밋은
tidy:프리픽스 사용 (예:tidy: extract helper for validation)
Consequences
- 장점
- PR 리뷰가 쉬워진다 (정리인지 기능인지 명확)
- 롤백이 안전해진다 (정리만 롤백 가능)
- 머지 충돌이 줄어든다 (작은 PR)
- 지속적인 코드 품질 개선
- 단점
- PR 수가 늘어날 수 있다
- "정리 먼저"에 대한 판단이 필요하다
- 팀원 교육이 필요하다
ADR002. 정리 타이밍 결정 기준
Context
- Tidy First 원칙을 도입했지만, "언제 정리해야 하는가"에 대한 기준이 필요하다.
- 모든 코드를 정리할 수는 없고, 우선순위가 필요하다.
- 책의 "First, After, Later, Never" 프레임워크를 실무에 적용한다.
Decision
First (먼저 정리)
- 현재 상태로 기능 추가가 위험하거나 어려울 때
- 같은 파일을 최근 3회 이상 수정했고, 매번 혼란을 느꼈을 때
- 정리가 기능 변경 코드량을 50% 이상 줄일 것으로 예상될 때
After (나중에 정리)
- 기능 추가 후 코드가 복잡해졌음을 인지했을 때
- 보이스카우트 규칙: 왔을 때보다 깨끗하게
Later (별도 시간에 정리)
- 지금 당장 필요하지 않지만 기술 부채로 인식된 것
- 스프린트 백로그에 정리 아이템으로 등록
Never (정리 안 함)
- 6개월 이상 수정 이력이 없는 안정된 코드
- 곧 삭제될 예정인 코드
- 정리 비용이 효과를 명확히 초과할 때
Consequences
- 정리에 대한 팀 내 공통 언어가 생긴다
- "지금 정리할까요?"에 대한 논의가 생산적이 된다
- 무분별한 리팩토링이나 방치를 방지한다