예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적(stack trace)
정보를 자동으로 출력한다. 스택 추적은 예외 객체의 toString
메서드를 호출해 얻은 문자열이다. 이는 보통 예외 클래스 이름 뒤에 상세 메시지가 붙는 형태다.
이 정보는 실패 원인을 분석해야 하는 프로그래머 혹은 사이트 신뢰성 엔지니어(site reliability engineer, SRE)가 얻을 수 있는 유일한 정보인 경우가 많다. 따라서 예외의 toString
메서드에 실패 원인에 관한 정보를 가능한 한 많이 담아 반환하는 일은 아주 중요하다.
실패 순간을 포착하려면 발생한 예외에 관여된 모든 매개변수와 필드의 값을 실패 메시지에 담아야 한다. 단, 보안과 관련된 정보는 주의하자. 스택 추적 정보는 많은 사람이 볼 수 있으므로 상세 메시지에 비밀번호나 암호 키 같은 정보까지 담아서는 안 된다.
또한, 문서와 소스코드에서 얻을 수 있는 정보까지 장황하게 담을 필요는 없다. 스택 추적에는 예외가 발생한 파일 이름과 줄번호, 호출한 다른 메서드들의 파일 이름과 줄번호까지 정확히 기록되어 있기 때문이다.
실패를 적절히 포착하기 위해, 필요한 정보를 예외 생성자에서 모두 받아서 상세 메시지까지 미리 생성해놓는 방법도 괜찮다. 예를 들어 IndexOutOfBoundsException
생성자는 다음과 같이 구현해도 좋았을 것이다.
public class IndexOutOfBoundsException extends RuntimeException {
private final int lowerBound;
private final int upperBound;
private final int index;
/**
* IndexOutOfBoundsException을 생성한다.
*
* @param lowerBound 인덱스의 최솟값
* @param upperBound 인덱스의 최댓값 + 1
* @param index 인덱스의 실젯값
*/
public IndexOutOfBoundsException(int lowerBound, int upperBound,
int index) {
// 실패를 포착하는 상세 메시지를 생성한다.
super(String.format("최솟값: %d, 최댓값: %d, 인덱스: %d",
lowerBound, upperBound, index));
// 프로그램에서 이용할 수 있도록 실패 정보를 저장해둔다.
this.lowerBound = lowerBound;
this.upperBound = upperBound;
this.index = index;
}
}
이렇게 해두면 프로그래머가 던지는 예는 자연스럽게 실패를 더 잘 포착한다.
또한, 클래스 사용자가 메시지를 만드는 작업을 중복하지 않아도 된다.
예외는 실패와 관련된 정보를 얻을 수 있는 접근자 메서드를 적절히 제공하는 것이 좋다. 포착한 실패 정보는 예외 상황을 복구하는 데 유용할 수 잇으므로 접근자 메서드는 비검사 예외보다는 검사 예외에서 더 빛을 발한다.
하지만 'toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자'라는 일반 원칙(아이템 12)을 따른다는 관점에서, 책의 저자는 비검사 예외라도 상세 정보를 알려주는 접근자 메서드를 제공하라고 권장한다.