티스토리 뷰
예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적 정보를 자동으로 출력합니다.
스택 추적은 예외 객체의 toString 메서드를 호출해 얻는 문자열로, 보통은 예외의 클래스 이름 뒤에 상세 메시지가 붙는 형태입니다.
이 정보가 실패 원인을 분석해야 하는 프로그래머 혹은 사이트 신뢰성 엔지니어(SRE)가 얻을 수 있는 유일한 정보인 경우가 많습니다.
더구나 그 실패를 재현하기 어렵다면 더 자세한 정보를 얻기가 어렵거나 불가능합니다.
따라서 예외의 toString 메서드에 실패 원인에 관한 정보를 가능한 한 많이 담아 반환하는 일은 아주 중요합니다.
달리 말하면, 사후 분석을 위해 실패 순간의 상황을 정확히 포착해 예외의 상세 메시지에 담아야 합니다.
실패 순간을 포착하려면 발생한 예외에 관여된 모든 매개변수와 필드의 값을 실패 메시지에 담아야 합니다.
예컨대 IndexOutOfBoundsException의 상세 미시지는 범위의 최솟값과 최댓값, 그리고 그 범위를 벗어났다는 인덱스의 값을 담아야 합니다.
이 정보는 실패에 관한 많은 것을 알려줍니다.
셋 중 한 두 개 혹은 셋 모두가 잘못됐을 수 있습니다.
예컨대 인덱스가 최솟값보다 1만큼 작거나 최댓값과 같을 수도 있습니다.
혹은 범위를 크게 벗어났을 수도 있습니다.
심지어 최솟값이 최댓값보다 클 수도 있습니다. ⇒ 내부의 불변식이 심각히 깨진 경우
이상의 현상들은 모두 원인이 다르므로, 현상을 보면 무엇을 고쳐야 할지를 분석하는 데 큰 도움이 됩니다.
관련 데이터를 모두 담아야 하지만 장황할 필요는 없습니다.
문제를 분석하는 사람은 스택 추적뿐 아니라 관련 문서와 소스코드를 함께 봅니다.
스택 추적에는 예외가 발생한 파일 이름과 줄번호는 물론 스택에서 호출한 다른 메서드들의 파일 이름과 줄번호까지 정확히 기록되어 있는 게 보통입니다.
그러니 문서와 소스코드에서 얻을 수 있는 정보는 길게 늘어놔봐야 군더더기가 될 뿐입니다.
예외의 상세 메시지와 최종 사용자에게 보여줄 오류 메시지를 혼동해서는 안 됩니다.
최종 사용자에게는 친절한 안내 메시지를 보여줘야 하는 반면, 예외 메시지는 가독성보다는 담긴 내용이 훨씬 중요합니다.
예외 메시지의 주 소비층은 문제를 분석해야 할 프로그래머와 SRE이기 때문입니다.
또한 최종 사용자용 메시지는 현지어로 번역해주기도 하지만, 예외 메시지는 그런 일이 거의 없습니다.
실패를 적절히 포착하려면 필요한 정보를 예외 생성자에서 모두 받아서 상세 메시지까지 미리 생성해놓는 방법도 괜찮습니다.
예를 들어 현재의 IndexOutOfBoundsException 생성자는 String을 받지만, 다음과 같이 구현했어도 좋았을 겁니다.
/**
* IndexOutOfBoundsExcepiont을 생성한다.
*
* @param lowerBound 인덱스의 최솟값
* @param upperBound 인덱스의 최댓값 + 1
* @param index 인덱스의 실젯값
*/
public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) {
// 실패를 포착하는 상세 메시지를 생성한다.
super(String.format(
"최솟값: %d, 최댓값: %d, 인덱스: %d",
lowBound, upperBound, index
));
// 프로그램에서 이용할 수 있도록 실패 정보를 저장해둔다.
this.lowerBound = lowerBound;
this.upperBound = upperBound;
this.index = index;
}
자바 9에서는 IndexOfBoundsException에 드디어 정수 인덱스 값을 받는 생성자가 추가되었습니다.
하지만 아쉽게도 최솟값과 최댓값까지 받지는 않습니다.
이처럼 자바 라이브러리에서는 이 조언을 적극 수용하지는 않지만, 나는 강력히 권장하는 바입니다.
이렇게 해두면 프로그래머가 던지는 예외는 자연스럽게 실패를 더 잘 포착합니다.
실패를 포착하지 못하게 만드는 게 오히려 더 어려울 것입니다.
또한 고품질의 상세 메시지를 만들어내는 코드를 예외 클래스 안으로 모아주는 효과도 있어, 클래스 사용자가 메시지를 만드는 작업을 중복하지 않아도 됩니다.
아이템 70에서 제안하였듯, 예외는 실패와 관련한 정보를 얻을 수 있는 접근자 메서드를 적절히 제공하는 것이 좋습니다.
포착한 실패 정보는 예외 상황을 복구하는 데 유용할 수 있으므로 접근자 메서드는 UnCheckedException보다는 CheckedException에서 더 빛을 발합니다.
UnCheckedException의 상세 정보에 프로그램적으로 접근하길 원하는 프로그래머는 드물 것입니다.
하지만 'toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자'하는 일반 원칙을 따른다는 관점에서, UnCheckedException이라도 상세 정보를 알려주는 접근자 메서드를 제공하라고 권하고 싶습니다.
'JAVA > 이펙티브 자바' 카테고리의 다른 글
아이템[77]. 예외를 무시하지 마라 (0) | 2022.05.22 |
---|---|
아이템[76]. 가능한 한 실패 원자적으로 만들라 (0) | 2022.05.22 |
아이템[74]. 메서드가 던지는 모든 예외를 문서화하라 (0) | 2022.05.22 |
아이템[73]. 추상화 수준에 맞는 예외를 던져라 (0) | 2022.05.22 |
아이템[72]. 표준 예외를 사용하라 (0) | 2022.05.19 |
- Total
- Today
- Yesterday
- 디자인 패턴
- Kotlin
- node.js
- Effective Java
- 알고리즘
- 이팩티브 자바
- Algorithm
- 객체지향
- 이펙티브 자바
- 코테
- MSA
- 백준
- kotest
- 디자인패턴
- kkoon9
- BOJ
- Olympiad
- 정규표현식
- 테라폼
- 클린 코드
- BAEKJOON
- AWS
- Spring Boot
- JPA
- C++
- 프로그래머스
- Java
- Spring
- programmers
- 클린 아키텍처
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |