책/토비의 스프링 3.1(1권, 완)
4장 예외
sami355
2023. 11. 2. 16:02
4.1 사라진 SQLException
- 예외를 catch 했다고 해도 다시 밖으로 예외를 던져줘야 한다.
try {
...
}
catch(SQLException e){
// 예외를 잡고는 아무것도 하지 않는다. 예외 발생을 무시해버리고 정상적인 상황인 것처럼
//다음 라인으로 넘어가겠다는 분명한 의도가 있는 게 아니라면 연습 중에도 절대 만들어서는 안되는 코드이다.
}
- 만약 catch를 하고 다시 던져주지 않으면 시스템 오류나 이상한 결과의 원인이 무엇인지 찾아내기가 매우 힘들다
System.out.println(e)
이나e.printStackTrace()
를 통해 메시지를 출력하는 것은 다음과 같은 문제가 존재한다.- 다른 로그나 메시지에 금방 묻혀버려 놓칠수 있다.
- 출력을 하는 것은 예외를 처리하는 것이 아니다.
- 모든 예외는 적절하게 복구되든지 작업을 중단시키고 운영자 또는 개발자에게 분명하게 통보돼야 한다.
- 예외를 잡아서 조치를 취할 방법이 없다면 잡지 말아야 한다.
- 메서드 밖으로 throws Exception하는 것 역시 다음과 같은 문제점이 존재한다.
- 정말로 예외적인 상황이 발생할 수 있다는 것인지 알 수 없다.
- 적절한 처리를 통해 복구될 수 있는 예외상황도 제대로 다루지 못한다.
- 예외는 다음과 나눌수 있다.
- Error
- 주로 VM에서 다루는 예외이다. 어플리케이션 단에서 신경쓰지 않아도 된다.
- checkedException
- RuntimException을 상속하지 않은 예외들로 만약 checkedException이 발생할 가능성이 존재한다면 throws혹은 catch문을 추가해줘야 한다. → 예외 처리 코드가 남용될 수 있다는 단점이 존재
- unCheckedException
- RuntimeException을 상속한 클래스로 프로그램의 오류가 있을 때 발생하도록 의도된 것이다.
- Error
- 예외처리를 하는 방법은 다음과 같다.
- 예외 복구
- 예외로 인해 기본 작업 흐름이 불가능하면 다른 작업 흐름으로 자연스럽게 유도해주는 것이다.
- 예외상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것이다.
- 예외 처리 회피
- 예외처리를 회피하려면 반드시 다른 오브젝트나 메소드가 예외를 대신 처리할 수 있도록 해야 한다.
- 예외를 회피하는 것은 예외를 복구하는 것 처럼 의도가 분명해야 한다.
- 예외처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버리는 것
- 예외 전환
- 예외를 전환할때 DAO메소드에서 기술에 독립적이며 의미가 분명한 예외로 전환해서 던져줘야 한다.
- ex)
SQLException
→DuplicateUserIdException
- 전환하는 예외에 원래 발생한 예외를 담아서 중첩 예외(Nest Exception)로 만드는 것이 좋다.
- 중첩 예외는 새로운 예외를 만들면서 생성자나 initCause() 메소드로 근본 원인이 되는 예외를 넣어주면 된다.
- 예외처리를 강제하는 체크 예외를 언체크 예외인 런타임 예외로 바꾸는 경우에 사용한다.→ 언체크 예외로 던질 경우 throws 혹은 try-catch문을 작성하지 않아도 된다.
- → 대응이 불가능한 체크 예외라면 가능한 빨리 언체크 예외로 변경하면 좋다
- 발생한 예외를 그대로 넘기는 게 아니라 적절한 예외로 전환해서 던진다
- 예외 복구
- 어디서든 checkedException을 다룰수 있다면 런타인 예외로 만드는게 낫다
- 애플리케이션 자체의 로직에 의해 의도적으로 발생시키고, 반드시 catch 해서 무엇인가 조치를 취하도록 요구하는 예외도 있다. → 애플리케이션 예외라고 한다.
- 애플리케이션 예외를 설계하는 방법은 두 가지가 존재한다.
- 다른 종류의 리턴 값을 돌려주는 것이다.
- 리턴 값을 명확하게 하지 않으면 혼란이 생길수 있다는 단점이 존재한다
- 리턴 값에 따라 로직이 변경되므로 if문이 남발될 수 있다.
- 예외상황에서 비즈니스적인 의미를 띈 예외를 던지도록 만든다.
- 다른 종류의 리턴 값을 돌려주는 것이다.
➕ 만약 예외 발생시 RunTimeException
을 상속받은 사용자 정의 예외를 던지고 @ControllerAdvice
와 @ExceptionHandler
로 관리하면 깔끔하게 코드 관리 할 수 있다.