클린 코드 실전 강의 교재¶
4장 — 주석¶
대상: Java/Spring 백엔드 입문~중급 수강생 형식: 개념 → 비유 → Before/After → 함정 → 체크리스트 → 퀴즈 전제 환경: Java 17+, Spring Boot 3.x
0. 이 장을 시작하기 전에¶
0.1 학습 목표¶
- "주석은 나쁜 코드를 보완하지 못한다" — 책의 가장 격한 단언을 이해한다.
- 좋은 주석 8종 vs 나쁜 주석 16종 을 구분한다.
- 3장(함수)이 대부분의 주석을 불필요하게 만든다는 연결 관계를 본다.
0.2 큰 그림¶
이 장이 다루는 내용을 원칙·좋은 주석·나쁜 주석 세 묶음으로 정리하면 다음과 같습니다.
| 원칙 | 좋은 주석 (8) | 나쁜 주석 (16) |
|---|---|---|
| 코드로 의도 표현 | 법적 | 주절거림 |
| 주석은 실패의 인정 | 정보 제공 | 중복 |
| 의도 설명 | 오해 여지 | |
| 의미 명료화 | 의무적 | |
| 결과 경고 | 이력 | |
| TODO | 잡음 | |
| 중요성 강조 | 함수·변수로 표현 가능 | |
| 공개 API Javadoc | 위치 표시·닫는 괄호 | |
| 공로·저자·HTML | ||
| 주석 처리된 코드 | ||
| 전역·과다 정보 | ||
| 모호한 관계·함수 헤더 |
비유 — 주석은 "사과문"입니다.
좋은 코드는 사과할 일이 없습니다. 주석을 달고 있다는 것은 코드가 자기 의도를 스스로 말하지 못하고 있다는 신호입니다. 그래서 4장은 사과문을 쓰지 말고 코드를 고치라고 말합니다.
0.3 현업에서 왜 중요한가¶
- 주석은 코드가 진화해도 같이 진화 안 함 → 시간이 지나면 거짓말이 됨.
- 위에서 본 "Q. 코드로 의도를 표현하라" 가 가장 강한 처방.
- Effective Java Item 56(공개 API Javadoc) 만 예외 — 그 외는 가능한 한 적게.
4.1 주석은 나쁜 코드를 보완하지 못한다¶
한 줄 정의¶
코드가 엉망이면 → 정리. 주석 추가가 답이 아님. "엉망인데 주석으로 설명" = "사과로 무마".
사례¶
// 이 줄은 정말 이상하지만 X 때문에 그렇게 둬야 함
String x = something.weird() + ".magic";
// → 함수 추출로 의도를 이름이 말하게
String x = buildMagicPath(something);
4.2 코드로 의도를 표현하라!¶
한 줄 정의¶
주석으로 설명할 만한 것은 함수·변수 이름 으로 옮길 수 있다.
Before / After¶
// Before — 주석으로 의도 설명
// 직원에게 복지 혜택을 받을 자격이 있는지 검사
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) ...
// After — 함수 추출 + 이름이 말함
if (employee.isEligibleForFullBenefits()) ...
3장 함수 추출(6.1) 의 자연스러운 연장.
4.3 좋은 주석 — 8종¶
가능한 한 적게 — 그래도 정당한 경우.
(1) 법적인 주석¶
// Copyright (C) 2008 by ObjectMentor, Inc. All rights reserved.
// Released under the terms of the GNU General Public License version 2 or later.
회사·라이선스 표시. 필수.
(2) 정보를 제공하는 주석¶
// kk:mm:ss EEE, MMM dd, yyyy 형식
Pattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
정규식의 형식 의미 등 코드로 표현하기 어려운 정보.
단 — 더 좋은 해법: 그 의미를 변수 이름으로 옮기거나 enum/상수로 정리.
(3) 의도를 설명하는 주석¶
// 스레드를 대량 생성하는 방법으로 어떻게든 경쟁 조건을 만들어보려 한다.
for (int i = 0; i < 25_000; i++) {
new ThreadHelper(...).start();
}
왜 이렇게 코드를 짰는지 (의도) — 코드 자체는 표현 못 하는 영역.
(4) 의미를 명료하게 밝히는 주석¶
assertTrue(a.compareTo(a) == 0); // a == a
assertTrue(a.compareTo(b) != 0); // a != b
assertTrue(ab.compareTo(ab) == 0); // ab == ab
비교 결과의 의미 해설. 단 — 표준 라이브러리 호출이면 보통 불필요.
(5) 결과를 경고하는 주석¶
또는 @Disabled 같은 표준 메커니즘 우선.
(6) TODO 주석¶
// TODO-MdM 현재는 필요하지 않으나 모델 다운로드 후 변경 예정
protected VersionInfo makeVersion() throws Exception { return null; }
단 — IDE가 일괄 검색해서 정기적으로 해결할 것. 영구 TODO는 죽은 약속.
(7) 중요성을 강조하는 주석¶
생략하기 쉬운 코드의 결정적 중요성 명시.
(8) 공개 API Javadoc¶
/**
* 주문 합계를 계산한다.
*
* @param order null 불가
* @return 0 이상
* @throws IllegalArgumentException order가 null
*/
public Money totalAmount(Order order) { ... }
→ Effective Java Item 56 과 동일.
4.4 나쁜 주석 — 16종 카탈로그¶
(1) 주절거리는 주석¶
→ 누구에게 하는 말? 무슨 일이 일어났다는 건지? 불완전한 의도 → 코드를 고치든 명확히 다시 쓰든.
(2) 같은 이야기를 중복하는 주석¶
이름이 이미 말함 → 주석 중복.
(3) 오해할 여지가 있는 주석¶
i = 1 부터인지 i > 1 부터인지 모호. 틀린 정보를 줄 위험.
(4) 의무적으로 다는 주석¶
/**
* @param title CD 제목
* @param author 저자
* @param tracks 트랙 수
* @param durationInMinutes 길이 (분)
*/
public void addCD(String title, String author, int tracks, int durationInMinutes) { ... }
자명한 매개변수에 의무적 Javadoc — 정보 0, 노이즈만.
(5) 이력을 기록하는 주석¶
/*
* 변경 이력 (11-Oct-2001)
* ------------------------
* 11-Oct-2001: 클래스 재작성
* 05-Nov-2001: 새로운 메서드 추가
*/
→ Git 이 기억함. 코드에서 즉시 삭제.
(6) 있으나 마나 한 주석¶
→ 자명. 노이즈.
(7) 무서운 잡음¶
위 6번의 연속 — 모든 게터/세터에 자명한 Javadoc 자동 생성.
(8) 함수나 변수로 표현할 수 있다면 주석 달지 마라¶
이 장의 핵심 메시지.
(9) 위치를 표시하는 주석¶
가끔 의미 있지만 남발하면 노이즈. IDE 사용 시 거의 필요 없음.
(10) 닫는 괄호에 다는 주석¶
함수가 작으면 필요 없음. 필요하다면 함수 추출 의 신호.
(11) 공로를 돌리거나 저자를 표시하는 주석¶
→ Git blame이 함. 코드에서 즉시 제거.
(12) 주석으로 처리한 코드¶
→ 즉시 삭제. Git에 있음. "혹시 모르니" 두지 마라.
(13) HTML 주석¶
Javadoc 생성기 외에는 가독성 떨어뜨림.
(14) 전역 정보¶
기본 포트 정보가 이 메서드 주석에 있을 이유 없음 → 다른 곳에서 변경되면 어긋남.
(15) 너무 많은 정보¶
긴 역사·표준·정책 인용은 주석 영역 아님 → 별도 문서.
(16) 모호한 관계 / 함수 헤더 / 비공개 Javadoc¶
주석과 코드의 관계가 멀거나, 모든 함수에 의무 헤더, 비공개 함수에 Javadoc — 모두 노이즈.
핵심 교훈¶
- 주석은 실패의 인정. 코드가 의도를 못 말하므로 사과문이 됨.
- 함수 추출·이름 바꾸기 가 대부분의 주석을 불필요하게 만든다.
- 좋은 주석은 왜 를 설명함 (의도·경고·중요성). 나쁜 주석은 무엇 을 중복함.
- 주석은 코드와 함께 진화하지 않는다 → 시간이 지나면 거짓.
- Git 이 기억하는 정보는 코드에 두지 마라 (이력·저자).
- 공개 API Javadoc 만 예외 — 그 외는 가능한 한 적게.
함정 / 주의¶
- "주석 = 무조건 나쁨" 도그마 위험. 왜를 설명하는 주석은 좋음.
- 회사 정책상 의무적 Javadoc은 어쩔 수 없을 때 — 최소 의미 있는 내용으로.
- TODO 는 IDE 검색으로 정기 청소. 영구 TODO 는 죽은 약속.
체크리스트 (코드 리뷰용)¶
- 주석이 왜 가 아니라 무엇 을 설명하고 있는가 (= 나쁨 신호)
- 함수·변수 이름으로 옮길 수 있는 주석인가
- 코드가 변경됐는데 주석은 옛 정보인가
- 주석으로 처리된 죽은 코드가 있는가 → 즉시 삭제
- 이력·저자 주석이 있는가 → 즉시 삭제 (Git이 기억)
- 의무적 Javadoc이 자명한 매개변수만 나열하는가
- 공개 API에 Javadoc이 누락되어 있는가 (Item 56)
퀴즈¶
Q1. "주석은 나쁜 코드를 보완하지 못한다" 의 의미는?
A. 코드가 엉망일 때 주석을 추가해서 가독성을 만회하려 하지 말고, 코드 자체를 고쳐라. 주석은 사과문일 뿐. 결국 코드가 변하면 주석은 거짓이 됨.
Q2. "왜" 와 "무엇" 중 주석이 설명해야 할 것은?
A. 왜. 무엇은 코드 자체로 보여야 함 (이름·구조). 왜는 코드가 표현 못 하는 영역 — 정책, 외부 제약, 과거 사고 회피, 결정의 배경.
Q3. Javadoc이 4장에서 거의 유일하게 살아남는 좋은 주석인 이유?
A. 공개 API는 외부 사용자에게 계약 을 명시해야 하기 때문. 함수 이름만으로는 매개변수 nullable·예외 조건·반환값 의미를 다 말할 수 없음. Effective Java Item 56과 같은 결.
Q4. "이력·저자 주석" 을 즉시 삭제해도 되는 이유?
A. Git이 더 정확하고 자동으로 기억. 코드 안 주석은 갱신 안 되어 거짓이 되기 쉬움. git log / git blame 이 답.
Q5. 주석 처리된 죽은 코드를 "혹시 모르니" 두면 안 되는 이유?
A. Git에 있어서 언제든 복구 가능. 코드 안에 남아 있으면 (1) 읽는 사람의 인지 부담, (2) "왜 주석 처리됐는지" 추적 비용, (3) 실수로 살려낼 위험.
다음 장 예고 — 5장: 형식 맞추기¶
코드의 세로·가로 형식 의 규칙. "신문 기사처럼 작성하라" — 상위 개념이 위, 세부가 아래. 짧은 장이지만 팀 일관성의 기반.