[Effective Java]표준 예외를 사용하라

예외, 네 번째 아이템

Posted by SungBeom on May 19, 2020 · 2 mins read

표준 예외 재사용의 장점

표준 예외를 재사용하면 얻는 게 많다. 그중 최고는 여러분의 API가 다른 사람이 익히고 사용하기 쉬워진다는 것인데, 많은 프로그래머에게 이미 익숙해진 규약을 그대로 따르기 때문이다. 여러분의 API를 사용한 프로그램도 낯선 예외를 사용하지 않게 되어 읽기 쉽게 된다는 장점도 크다. 마지막으로, 예외 클래스 수가 적을수록 메모리 사용량도 줄고 클래스를 적재하는 시간도 적게 걸린다.

널리 사용되는 예외

재사용하기 좋은 널리 사용되는 예외는 다음과 같다.

IllegalArgumentException: 허용되지 않는 값이 인수로 건네졌을 때(null은 따로 NullPointerException으로 처리)
IllegalStateException: 객체가 메소드를 수행하기에 적절하지 않은 상태일 때
NullPointerException: null을 허용하지 않는 메소드에 null을 건넸을 때
IndexOutOfBoundsException: 인덱스가 범위를 넘어섰을 때
ConcurrentModificationException: 허용하지 않는 동시 수정이 발견됐을 때
UnsupportedOperationException: 호출한 메소드를 지원하지 않을 때

이상이 확실히 가장 흔하게 재사용되는 예외지만, 다른 상황에서는 다른 예외도 재사용할 수 있다. 예컨대 복소수나 유리수를 다루는 객체를 작성한다면 ArithmeticException이나 NumberFormatException을 재사용할 수 있을 것이다.

그 밖에 조언

Exception, RuntimeException, Throwable, Error는 직접 재사용하지 말자. 이 클래스들은 추상 클래스라고 생각하길 바란다. 이 예외들은 다른 예외들의 상위 클래스이므로, 즉 여러 성격의 예외들을 포괄하는 클래스이므로 안정적으로 테스트할 수 없다.

상황에 부합한다면 항상 표준 예외를 재사용하자. 이때 API 문서를 참고해 그 예외가 어떤 상황에서 던져지는지 꼭 확인해야 한다. 예외의 이름뿐 아니라 예외가 던져지는 맥락도 부합할 때만 재사용한다. 더 많은 정보를 제공하길 원한다면 표준 예외를 확장해도 좋다. 단, 예외는 직렬화할 수 있는데, 직렬화에는 많은 부담이 따르니 이 사실만으로도 나만의 예외를 새로 만들지 않아야 할 근거로 충분할 수 있다.

예외의 '주요 쓰임'이 상호 베타적이지 않은 탓에, 종종 재사용할 예외를 선택하기 어려울 때도 있다. 예를 들어 IllegalArgumentException과 IllegalStateException이 헷갈릴 수도 있다. 두 예외 사이의 일반적인 규칙은 인수 값이 무엇이었든 어차피 실패했을 거라면 IllegalStateException을, 그렇지 않으면 IllegalArgumentException을 던지자.


핵심 정리

표준 예외를 재사용하면 여러 장점을 얻을 수 있으므로, 상황에 부합한다면 항상 표준 예외를 재사용하거나, 표준 예외를 확장해서 사용하자. 주로 사용되는 예외로는 IllegalArgumentException, IllegalStateException, NullPointerException, IndexOutOfBoundsException, ConcurrentModificationException, UnsupportedOperationException 등이 있다. Exception, RuntimeException, Throwable, Error는 직접 재사용하지 말아야 한다. IllegalStateException과 IllegalArgumentException이 헷갈린다면 인수 값에 상관없이 실패했을 상황에는 IllegalStateException을, 그렇지 않은 상황에는 IllegalArgumentException을 사용하자.