토비의 스프링

1 minute read

[4장] 예외

[4.1] 사라진 SQLException

  • 예외 블랙홀: try/catch 구문
    ```java try { //.. } catch(SqlException e) {

} ```
예외를 잡아 catch하는 것은 좋지만 아무문제 없이 넘어가는 것이 더 위험하다.
모든 예외는 적절하게 복구되든지 프로그램을 중단해야 한다.
예외를 잡아서 취할 조치가 없다면 잡지 않도록 하자.

  • 무의미하고 무책임한 throws
    예외 일일히 catch로 잡아서 처리하기 귀찮아서 throws 쓰기 시작하면 이걸 쓰는 메서드까지도 throws를 써야함을 기억하자.

  • 예외의 종류
    • Error
      시스템에 비정상적인 상황 발생, javaVM이 발생
      대체적으로 잡을 필요 없음
    • Exception과 checked Exception
      컴파일러가 이미 check한 예외!! 알고 있는 예외, 일어날거라고 명시해주는 데에 의미가 있다.
      개발자가 만든 코드 실행 중 발생한 예외상황
      checked는 Exception 상속, Runtime 상속하지 않음
      반드시 catch로 잡아 처리해야함, 아니면 컴파일 에러 발생해서 프로그램 뻗음
      IOException, SQLException 등의 상황
    • RuntimeException과 unchecked Exception
      프로그램에 오류가 있을 때 발생하는 것
      catch로 잡거나, throws 선언까지는 필요하지 않다.
      명시적으로 잡을 수는 있다.
      NullPointer, IllegalArgument ..
      예외 상황을 미리 예상하고 잘 잡아두면 예방할 수 있다.
  • 예외처리 방법
    • 예외 복구
      예외상황을 파악하고 문제를 해결해 정상으로 돌려둔다.
      checked는 대체로 이거를 하는 의미가 없다. -> 접속이 안되는 경우 몇번 재시도를 하는 것과 같은 행위를 할 수는 있다.
      unchecked는 잡아서 올바른 예외 메시지로 반환해 재입력 받는 데에 의미가 있다.
    • 예외처리 회피
      catch문으로 잡은 다음에 다시 throw로 예외를 던지는 경우를 의미한다.
      콜백 템플릿이 아니라면 무책임한 일일 수 있다. (실제 JdbcContext, JdbcTemplate은 이 구조를 사용)
    • 예외전환
      예외를 잡아 적절한 예외로 반환한다.
      예를 들어 checked를 unchecked로 바꾸어 사용자에게 적절한 메시지를 줄 수도 있고,
      의미를 분명하게 해주는 예외로 바꿔주기 위해서 사용할 수도 있다(그냥 SqlException이면은 정확히 무엇 때문인지 알기 어려우니)
      보통은 전환하는 예외에 기존에 발생한 예외를 담아 중첩 예외로 던지는 것이 좋다.
  • 예외처리 전략
    런타임 예외의 보편화
    요청 중에 예외가 발생하면 그 작업만 죽이면 되지 전부 죽일 필요가 없다.
    그보다, 예외 상황을 미리 예측하고 예외가 발생하지 않도록 차단하는 것이 더 좋다.
    외부의 환경으로 인한 예외이더라도 그 작업을 취소하고 개발자에게 알려주는 것이 낫지 checked로 throws, catch하는 것은 좋지 않다.

예외전환과 예외중첩을 적절히 사용해서 checked 보다는 unchecked로 처리하도록 하자.

  • 예외전환
    불필요한 catch/throws를 줄이고, 의미있고 추상화된 예외로 바꿔서 던져주기 위해 사용
    • JDBC의 한계
      jdbc는 db에 접근하는 방법을 추상화해서 정의하고 db가 Connection, Statement, ResultSet 등의 기능을 제공해준다.
      하지만 SQLException은 복구가 어려워 RuntimeException으로 포장해야한다.
      SQLException의 에러코드는 DB에 종속적이라 독립적으로 바꿔줄 필요가 있다.
      스프링은 이를 위해 DataAccessException을 통해 독립적으로 적용 가능한 추상화된 런타임 예외 계층을 제공한다.