콘텐츠로 이동

클린 코드 실전 강의 교재

14장 — 점진적인 개선 (Args 사례)

대상: Java/Spring 백엔드 입문~중급 수강생 형식: 사례 워크스루 — 1차 초안 → 정련 → 결과 전제 환경: Java 17+


0. 이 장을 시작하기 전에

0.1 학습 목표

  • 초안이 추한 건 정상, 정련이 본업.
  • 점진적 개선의 실제 단계 를 사례로 본다.
  • "TDD + 작은 단계 + 테스트 안전망 = 자유로운 정련" 의 살아있는 증명.

0.2 사례 — Args 라이브러리

명령줄 인수 파서. -l (boolean), -p 8080 (int), -d /tmp (String) 같은 옵션을 자바 API 로 변환.

Args args = new Args("l,p#,d*", argv);
boolean logging = args.getBoolean('l');
int port = args.getInt('p');
String directory = args.getString('d');

0.3 현업에서 왜 중요한가

  • 초보의 두려움 "처음부터 깨끗하게 짜야지" 를 깨뜨림.
  • 1차 초안 → 점진 정련의 사이클이 모든 클린 코드의 본질.

14.1 Args 1차 초안 — 추한 코드

진행

  • 1차 초안: 약 100줄짜리 한 함수, 거대한 switch, 가변 상태, 중복 처리.
  • 작동은 함. 테스트 80+ 통과.

그래서 멈췄다

코드가 커지면서 새 옵션 추가 = 거대 함수 곳곳 수정. 다음 기능 추가가 두려워짐 = 멈춰야 할 신호.

"변경이 두렵다" = 리팩터링 시점.


14.2 점진적으로 개선하다

핵심 결정 — 처음부터 다시?

아니오. 처음부터 다시 짜면 (1) 옛 시스템과 새 시스템 동시 유지, (2) 새 시스템도 다시 추해질 가능성.

점진적 변환 — 테스트가 안전망.

단계

  1. 각 인수 타입별 클래스 추출 (BooleanArgumentMarshaler, IntegerArgumentMarshaler, ...)
  2. switch 제거 — 다형성으로 (entity-refactoring 10.4)
  3. 공통 인터페이스 추출 (ArgumentMarshaler)
  4. Map 로 옵션 관리
  5. 각 단계마다 모든 테스트 통과 확인

Before / After 개요

// Before — 한 함수에 모든 분기
private void parseArgument(char argChar) {
    if (isBooleanArg(argChar)) parseBooleanArg(argChar);
    else if (isIntegerArg(argChar)) parseIntegerArg(argChar);
    else if (isStringArg(argChar)) parseStringArg(argChar);
    // ... 새 타입 추가마다 분기 추가
}

// After — 다형성
private void parseArgument(char argChar) {
    ArgumentMarshaler m = marshalers.get(argChar);
    m.set(currentArgument);   // 다형성
}

새 타입 추가 = 새 클래스 1개 + Map 등록.


14.3 결론

책의 교훈

  1. 초안이 추한 건 정상. 부끄러워하지 마라.
  2. 테스트 안전망 위에서 작은 단계로 정련.
  3. 다시 짜고 싶은 유혹 을 견뎌라 — 점진이 더 빠름.
  4. 변경이 두렵다 = 리팩터링 시점.

리팩터링 책 전체의 정신과 동일.


핵심 교훈

  1. 초안이 추하다 = 정상. 부끄러워 멈추지 마라.
  2. 다시 짜기 vs 점진 개선 — 거의 항상 점진이 답.
  3. 매 단계 모든 테스트 통과 = 작은 단계의 자유.
  4. switch + 분기 폭증 = 다형성 신호 (entity-refactoring 10.4).

함정 / 주의

  • 점진 개선이 "한 단계가 너무 큼" 이면 더 작은 단계로 분해.
  • 테스트 없이 정련 = 도박. 1단계는 항상 테스트 부터.
  • "1차 초안" 자체가 너무 거대해지면 (1,000+ 줄) 다시 짜는 게 답일 때도.

체크리스트

  • 1차 초안 후 멈추고 정련하는 습관이 있는가
  • 매 정련 단계 후 모든 테스트 통과 확인하는가
  • switch + 분기가 폭증하기 전에 다형성 적용하는가
  • "이 코드 다시 짜고 싶다" 가 점진 개선보다 빠른가 의심하는가

퀴즈

Q1. "처음부터 깨끗하게 짜는 게 어려운" 이유?

A. 요구사항·도메인을 모르면서 추상화부터 만들면 잘못된 추상화가 됨. 1차 초안 = 도메인 탐색, 2차 정련 = 좋은 추상화 발견. 코드가 진화하면서 알게 됨.

Q2. "변경이 두렵다" 가 무엇의 신호?

A. 리팩터링 시점. 두려움은 구조 문제 (결합도·중복·거대 함수) 의 증상. 그대로 두면 점점 더 두려워짐. 작게 정련하면 다시 자유.

Q3. switch + 분기 폭증을 다형성으로 옮기는 효과?

A. 새 타입 추가 = 새 클래스 1개. switch 모든 위치 수정 안 함 (산탄총 수술 회피). OCP 충족.

Q4. "다시 짜기" 가 거의 항상 답이 아닌 이유?

A. (1) 옛 시스템도 유지해야 함, (2) 옛 사용자 요구 다 잊혀짐, (3) 새 시스템도 추해질 가능성, (4) 시간 폭증. 오브젝트 의 "원대한 재설계의 꿈" 도 같은 메시지.

Q5. 14장이 책 전체에 주는 메시지?

A. 클린 코드 = 점진 정련의 결과. 1~13장의 권고는 모두 정련 단계의 도구. 처음부터 완벽한 코드 X, 추한 초안 + 정련 사이클이 본업.


다음 장 예고 — 15장: JUnit 들여다보기

JUnit 의 한 클래스를 함께 정련. 같은 패턴 — 작동하는 코드에서 시작 → 단계별 깨끗하게.