필요 없는 검사 예외 사용은 피하라

이진호·2022년 9월 5일
0

Effective Java

목록 보기
2/11
post-thumbnail

Item 71. 필요 없는 검사 예외 사용은 피하라

검사 예외(checked Exception)를 제대로만 활용한다면 API와 프로그램의 질을 높일 수 있습니다. 결과를 코드로 반환하거나 비검사 예외를 던지는 것과 달리, 검사 예외는 발생한 문제를 프로그래머가 처리하여 안전성을 높이게끔 해줍니다.

하지만 검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 되게 됩니다. 이를 호출하는 코드에서 catch 블록을 두어 예외 처리가 강제되거나, 더 바깥으로 던져 문제를 전파해야만 합니다. 어느 쪽이든 API 사용자에게 부담을 주며, Java8 부터는 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없기 때문에(Item 45~48) 부담이 더욱 커졌습니다.

API를 제대로 사용해도 발생할 수 있는 예외이거나, 프로그래머가 의미 있는 조치를 취할 수 있는 경우라면 이 정도 부담쯤은 받아들일 수 있을 것입니다. 하지만 둘 중 어디에도 해당하지 않는 경우에는 비검사 예외를 사용하는 것이 좋습니다.

검사 예외를 회피하는 가장 쉬운 방법은 적절한 결과 타입을 담은 옵셔널을 반환하는 것입니다(Item 55). 이 방식의 단점은 예외가 발생한 이유를 알려주는 부가 정보를 담을 수 없다는 것입니다. 반면 예외를 사용하면 구체적인 예외 타입과 그 타입이 제공하는 메서드들을 활용해 부가 정보를 제공할 수 있습니다(Item 70).

또 다른 방법으로, 검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 바꿀 수 있습니다. 이 방식에서 첫 번째 메서드는 예외가 던져질지 여부를 boolean값으로 반환합니다.

// 검사 예외를 던지는 메서드 - 리팩터링 전
try {
    obj.action(args);
} catch (TheCheckedException e) {
    ... // 예외 상황에 대처한다.
}
// 리팩터링 후
if (obj.actionPermitted(args)) {
    obj.action(args);
} else {
    ... // 예외 상황에 대처한다.
}

이 리팩터링은 모든 상황에 적용할 수는 없습니다. 그래도 적용할 수만 있다면 더 유연하고 쓰기 편한 API를 제공할 수 있습니다. 프로그래머가 이 메서드가 성공하리라는 걸 알거나, 실패 시 스레드를 중단하길 원한다면 다음과 같이 한 줄로 작성해도 무방합니다.

obj.action(args);

한편 actionPermitted는 상태 검사 메서드에 해당하므로 Item 69에서 말한 단점도 그대로 적용되니 주의해야 합니다.

핵심 정리

꼭 필요한 곳에만 사용한다면 검사 예외는 프로그램의 안전성을 높여주지만, 남용하면 쓰기 고통스러운 API를 낳는다. API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지자. 복구가 가능하고 호출자가 그 처리를 해주길 바란다면, 우선 옵셔널을 반환해도 될지 고민하자. 옵셔널만으로 상황을 처리하기에 충분한 정보를 제공할 수 없을 때만 검사 예외를 던지자.

출처

0개의 댓글