API를 유용하게 활용하려면 명확하고 완성도 높은 문서 작성이 필요합니다.
일반적으로 API는 직접 작성되기 때문에 코드 수정 시 문서도 함께 업데이트해야 합니다.
이러한 불편한 작업을 피하기 위해 Java에서는 JavaDoc이라는 유틸리티가 도움을 줍니다.
문서화 주석을 작성하는 규칙은 공식 언어 명세에 속하진 않지만 자바 개발자라면 반드시 알아야 하는 업계 표준 API라 할 수 있습니다.
- 문서화 주석을 작성하는 규칙은 Oracle 홈페이지에 잘 정리되어 있지만
- 자바 4 버전 이후로 갱신되어 있지 않기 때문에 자바 5의 @literal과 @code, 자바 8의 @implSpec, 자바 9의 @index 관련 내용은 별도로 기재되어 있지 않음
모든 공개된 리소스에 문서화 주석을 달자
- API를 올바로 문서화하기 위해서는 공개된 모든 클래스, 인터페이스, 메서드 및 필드 선언에 문서화 주석을 달아야 함
- 직렬화할 수 있는 클래스라면 직렬화된 형태에 대해 주석을 달아야 함
- 직렬화 주석은 데이터를 이동하거나 저장하기 위해 객체를 바이트 스트림으로 변환할 때 발생하는 프로세스에 대한 설명을 제공
- 이는 개발자들이 객체를 올바르게 직렬화하고 역직렬화할 수 있도록 돕는 역할
- 문서화 주석이 없다면 JavaDoc은 그저 공개 API 요소들의 선언만 나열해 주는 것이 전부
- 문서가 잘 가춰지지 않은 API는 쓰기 헷갈려서 오류의 원인이 되기도 함
- 기본 생성자에는 문서화 주석을 달 방법이 없으므로 공개 클래스는 절대 기본 생성자를 사용하면 안 됨
- 유지보수까지 고려한다면 공개되지 않은 클래스, 인터페이스, 메서드 및 필드 선언에도 문서화 주석을 다는 것을 권장
- 공개 API만큼 상세하고 친절하게 달 필요는 없지만 기본적인 로직 흐름은 작성하는 것을 권장
메서드용 문서화 주석에는 규약을 명료하게 기술하자
- 메서드가 어떻게 동작하는지를 적는 게 아니라 무엇을 하는지 기술
- 목적과 기능에 집중
- how가 아닌 what
- 클라이언트가 해당 메서드를 호출하기 위한 전제 조건을 모두 작성
- 메서드가 성공적으로 수행된 후 만족해야 하는 사후 조건도 모두 작성
- 일반적으로 전제 조건은 @Throw 태그로 Unchecked Exception을 선언하여 암시적으로 기술
- 비검사 예외 하나가 전제 조건 하나와 연결되는 것
- @param 태그를 이용해 그 조건에 영향받는 매개변수에 기술할 수도 있음
- 메서드에 전달되는 매개변수 중 전제 조건에 영향을 주는 경우, @param 태그를 사용하여 해당 매개변수에 대한 조건을 설명
전제 조건과 사후 조건뿐만 아니라 그 외 부작용도 문서화하자
- 부작용이란 사후 조건으로 명확히 나타나지는 않지만 시스템의 상태에 어떠한 변화를 가져오는 것
- ex) 메서드가 실행됨에 따라 시스템의 상태가 변경되거나, 외부 리소스에 접근하거나, 백그라운드 쓰레드를 실행하는 경우 해당 사실을 문서에 고지해야 함
문서화 태그 소개 및 주석 가이드
1. @param
- 메서드의 파라미터에 대한 정보
- 관례상 반환값을 설명하는 명사구로 작성
- 관례상 설명에는 마침표를 붙이지 않음
2. @return
- 메서드의 반환 타입이 void가 아니라면 반환 타입을 명시
- 관례상 반환값을 설명하는 명사구로 작성
- 관례상 설명에는 마침표를 붙이지 않음
- 드물게는 산술 표현식으로 작성하기도 하며 이는 BigInteger의 API 문서를 참고
3. @throws
- 발생 가능한 모든 예외를 명시
- if로 시작해 해당 예외를 던질 조건을 설명하는 절이 뒤따름
- 관례상 설명에는 마침표를 붙이지 않음
4. @code
- 태그로 감싼 내용을 코드용 폰트로 렌더링
- 태그로 감싼 내용에 포함된 HTML 요소나 다른 자바독 태그를 무시
- HTML 메타 문자인 < 기호 등을 별다른 처리 없이 바로 사용 가능
- MyBatis의 CDATA 섹션과 유사
- 문서화 주석에 여러 줄로 된 코드 예시를 넣으려면 {@code} 태그를 다시 <pre> 태그로 감싸면 됨
- <pre>{@code ... 코드 ...}</pre>와 같은 형태
- 위와 같이 작성하면 HTML의 탈출 메타문자를 쓰지 않고도 코드의 줄 바꿈이 그대로 유지
- 단, @기호에는 무조건 탈출문자를 붙여야 함 (어노테이션 작성 시 주의)
부연 설명
- 문서화 주석에 HTML 태그인 <p>와 <i>를 쓰는데 이는 자바독이 문서화 주석을 HTML로 변환하므로 문서화 주석 안의 HTML 요소들이 최종 HTML 문서에 반영되기 때문
- 가끔 자바독 설명에 HTML 표(table)까지 삽입하는 개발자도 있음
5. @implSpec
- 클래스를 상속용으로 설계할 때는 자기 사용 패턴(self-use pattern)에 대해서도 문서에 남겨 다른 개발자에게 해당 메서드를 올바르게 재정의하는 방법을 알려야 하며 이는 자바 8+ 버전부터 도입된 @implSpec 태그로 문서화
- 일반적인 문서화 주석은 해당 메서드와 클라이언트 사이의 계약을 설명하는 반면, @implSpec 주석은 해당 메서드와 하위 클래스 사이의 계약을 설명
- 하위 클래스들이 해당 메서드를 상속하거나 super 키워드를 이용해 호출할 때 그 메서드가 어떻게 동작하는지를 명확히 인지하고 사용하도록 지원
- 다만, -tag "implSpec:a:Implementation Requirements:" 명령어를 작성하지 않으면 @implSpec을 무시하기 때문에 자바독에 명시하기 위해서는 명령어를 작성하자
- ex) javadoc -d doc -tag "implSpec:a:Implementation Requirements:" -subpackages com.tistory.jaimemin.effectivejava.ch08.item56
6. @literal
- 해당 태그는 <, >와 같은 HTML 태그를 무시하게 해 줌
- MyBatis의 CDATA 섹션과 유사
- @code와 유사하지만, 코드 폰트로 렌더링 하지 않는 것이 차이점
- API 문서에서 가독성을 높이기 위해 사용
7. 요약 설명 (Summary Description)
- 각 문서화 주석의 첫 번째 문장은 해당 요소의 요약 설명으로 간주
- ex) E get 메서드의 `Returns the element at the specified position in this list.`
- 첫 번째 마침표가 나타나기 전까지의 문장을 첫 번째 문장으로 간주
- ex) `머스터드 대령이나 Mrs.피콕 같은 용의자`라고 작성할 때 `머스터드 대령이나 Mrs.`까지를 첫 번째 문장으로 간주
- 이를 우회하기 위해서는 @literal 태그를 써야하며 다음과 같이 작성
- 머스터드 대령이나 {@literal Mrs. 피콕} 같은 용의자
- Java 10+ 버전부터는 {@summary}라는 요약 설명 전용 태그가 추가되어 한번에 사용 가능
- ex) {@summary 머스터드 대령이나 Mrs.피콕 같은 용의자}
- `요약 설명이란, 문서화 주석의 첫 문장이다.`라고 말하면 살짝 오해의 소지가 존재
- 주석 작성 규약에 따르면 요약 설명은 완전한 문장이 되는 경우가 드묾
- 메서드와 생성자의 요약 설명은 해당 메서드와 생성자의 동작을 설명하는 (주어가 없는) 동사구여야 함
- 반면, 클래스나 인터페이스, 필드의 요약설명은 대상을 설명하는 명사절이어야 함
- 클래스나 인터페이스의 대상은 this
- 필드의 대상은 필드 자신
8. 색인 기능
- 자바 9+ 버전부터 JavaDoc이 생성한 HTML 문서에 대해 검색(색인) 기능이 추가되어 광대한 API 문서에서 원하는 정보를 쉽게 찾을 수 있게 됨
- @index 태그를 사용해 API에서 중요한 용어를 추가로 색인화 가능
9. 제네릭 주석은 꼭 달자
- 제네릭 타입이나 제네릭 메서드를 문서화할 때는 모든 타입 매개변수에 주석을 달아야 함
10. 열거 타입에는 상수별로 주석을 달자
- Enum 타입을 문서화할 때는 상수들에도 주석을 달아야 함
- 열거 타입 자체와 열거 타입의 public 메서드 포함
11. 어노테이션 타입을 문서화 할 때는 멤버에도 주석을 달자
- 어노테이션 타입을 문서화할 때는 멤버들에도 모두 주석을 달아야 함
- 어노테이션 타입 자체도 물론
- 필드 설명은 명사구로 작성
- 어노테이션 타입의 요약 설명은 프로그램 요소에 이 어노테이션을 단다는 것이 어떤 의미인지를 설명하는 동사구
12. 패키지를 설명하는 문서화 주석은 package-info.java에 작성하자
- 패키지를 설명하는 문서화 주석은 package-info.java에 명시
- 패키지 선언을 반드시 포함해야 하며 패키지 선언 관련 어노테이션을 추가로 포함 가능
- 모듈 시스템을 사용한다면, module-info.java 파일에 작성
13. thread-safe 여부를 반드시 API 설명에 포함해야 함
- 클래스 혹은 정적 메서드가 thread-safe하든 그렇지 않든, thread-safe 수준을 반드시 API 설명에 포함해야 함
- 직렬화할 수 있는 클래스라면 직렬화 형태도 API 설명에 기술해야 함
14. JavaDoc은 메서드 주석을 상속시킬 수 있음
- 문서화 주석이 없는 API 요소를 발견하면 JavaDoc이 가장 가까운 문서화 주석을 찾아줌
- 상위 클래스보다 구현한 인터페이스 주석을 더 먼저 찾음
- @inheritedDoc 태그를 사용해 상위 타입의 문서화 주석 일부를 상속
- 클래스는 자신이 구현한 인터페이스의 문서화 주석을 재사용 가능
정리
이번 아이템에서 설명한 지침을 잘 따른다면 API를 깔끔히 설명할 수 있는 문서를 작성할 수 있을 것입니다.
하지만 정말 잘 쓰인 문서인지를 확인하는 유일한 방법은 자바독 유틸리티가 생성한 웹페이지를 읽어보는 길 뿐입니다.
참고
이펙티브 자바
반응형
'JAVA > Effective Java' 카테고리의 다른 글
[아이템 58] 전통적인 for 문보다는 for-each 문을 사용하라 (0) | 2024.03.16 |
---|---|
[아이템 57] 지역변수의 범위를 최소화하라 (0) | 2024.03.16 |
[아이템 55] 옵셔널 반환은 신중히 하라 (0) | 2024.03.12 |
[아이템 54] null이 아닌, 빈 컬렉션이나 배열을 반환하라 (0) | 2024.03.11 |
[아이템 53] 가변인수는 신중히 사용하라 (0) | 2024.03.11 |