item 71 : 필요 없는 검사 예외 사용은 피하라
검사 예외의 활용과 리팩터링 전략
검사 예외를 싫어하는 자바 프로그래머가 많지만, 제대로 활용하면 API와 프로그램의 질을 높일 수 있다. 검사 예외는 프로그래머가 문제를 직접 처리하여 안전성을 높인다. 하지만 과도한 사용은 불편한 API를 만들어내므로, 필요에 따라 적절하게 사용해야 한다.
1. 검사 예외와 비검사 예외의 차이
1) 검사 예외의 장단점
검사 예외는 메서드에서 발생할 수 있는 예외를 명시하고, 호출하는 코드에서 이를 처리하도록 강제한다. 이로 인해 프로그램의 안정성이 높아진다.
반면에, 검사 예외는 API 사용자에게 부담을 줄 수 있다. 예외를 처리하기 위해 catch 블록을 추가해야 하며, 스트림 API와 같은 기능과 결합하기 어려운 경우도 있다.
검사 예외와 비검사 예외 중 어느 것을 선택할지는 프로그래머가 그 예외를 어떻게 다룰지 생각해보면 알 수 있다.
2) 예외 처리의 예
이러한 방식으로 검사 예외를 처리해야 하며, 이는 API 사용자에게 부담을 줄 수 있다.
2. 검사 예외 대신 사용할 수 있는 대안
1) 옵셔널(Optional) 사용
검사 예외를 회피하는 가장 쉬운 방법은 적절한 결과 타입을 담은 옵셔널을 반환하는 것이다.
검사 예외 대신 빈 옵셔널을 반환하면, 예외 발생 시 부가 정보를 제공하기 어렵지만, 예외 처리의 부담을 줄일 수 있다.
단점: 옵셔널은 예외 발생 이유에 대한 부가 정보를 제공할 수 없다. 반면 예외를 사용하면 구체적인 예외 타입과 그 타입이 제공하는 메서드를 통해 부가 정보를 전달할 수 있다.
옵셔널을 굳이 사용해야 하는 이유
코드 가독성 향상: 옵셔널을 사용하면 예외 처리 코드의 중복을 줄이고 가독성을 높일 수 있다. 예외를 던지는 대신 빈 옵셔널을 반환하면 코드의 흐름이 깔끔해진다.
불필요한 예외 방지: 옵셔널을 사용함으로써, 예외적인 상황이 아닌 경우에도 불필요하게 예외를 던지는 것을 방지할 수 있다. 예외는 실제로 프로그램의 흐름을 방해하므로, 예외적인 상황이 아닌 경우에는 옵셔널을 사용하는 것이 더 적절하다.
스트림 API와의 호환성: 자바 8부터는 스트림 API가 널리 사용되며, 옵셔널을 사용하면 스트림에서 처리하기가 훨씬 수월하다. 검사 예외는 스트림과 잘 호환되지 않기 때문에 옵셔널을 사용하여 더 직관적이고 효율적인 처리가 가능하다
2) 상태 검사 메서드로 리팩터링
검사 예외를 던지는 메서드를 두 개로 쪼개어 비검사 예외로 바꿀 수 있다.
첫 번째 메서드는 상태 검사 메서드로 예외 발생 가능 여부를 boolean 값으로 반환한다.
두 번째 메서드는 실제 작업을 수행하는 메서드이다.
이렇게 리팩터링하면 API가 더 유연해지지만, 모든 상황에서 적용할 수 있는 것은 아니다. 특히 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있는 경우에는 적절하지 않다.
3) 리팩터링 예시
리팩터링 전 (검사 예외 사용)
리팩터링 후 (상태 검사 메서드와 비검사 예외 사용)
이 리팩터링은 모든 상황에 적용할 수 있는 것은 아니다. 외부 동기화 없이 여러 스레드가 동시에 접근하거나 외부 요인에 의해 상태가 변할 수 있는 경우에는 이 리팩터링이 적절하지 않다.
3. 검사 예외의 남용 방지
검사 예외는 프로그램의 안전성을 높여주는 장점이 있지만, 남용하면 사용하기 불편한 API를 만들 수 있다.
API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지는 것이 좋다.
복구가 가능하고 호출자가 그 처리를 해주길 바란다면, 우선 옵셔널을 반환할 수 있는지 고민해야 한다.
옵셔널만으로 충분한 정보를 제공할 수 없을 때만 검사 예외를 던져야 한다.
💡 핵심 정리
검사 예외는 꼭 필요한 곳에만 사용해야 한다. 그렇지 않으면 사용자가 부담을 느끼고 API 사용성을 저하시킬 수 있다.
API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 사용해야 한다.
복구가 가능하다면 옵셔널을 먼저 고려하고, 옵셔널만으로는 충분하지 않을 때 검사 예외를 던지도록 한다.
올바른 예외 처리는 프로그램의 안전성과 유연성을 모두 향상시키는 중요한 요소이다.
Last updated
Was this helpful?