인생을 코딩하다.

[토비의 스프링 4장] 예외처리 본문

Spring

[토비의 스프링 4장] 예외처리

Hyung1 2021. 8. 28. 03:19
728x90
반응형

4장, 예외처리

p.281)

  • 예외를 처리할 때 반드시 지켜야 할 핵심 원칙은 한 가지다. 모든 예외는 적절하게 복구되든지 아니면 작업을 중단시키고 운영자 또는 개발자에게 분명하게 통보돼야 한다.
  • SQLException이 발생하는 이유는 SQL에 문법 에러가 있거나 DB에서 처리할 수 없을 정도로 데이터 엑세스 로직에 심각한 버그가 있거나, 서버가 죽거나 네트워크가 끊기는 등의 심각한 상황이 벌어졌기 대문이다.

p 283)

예외의 종류와 특징

 

자바에서 throw를 통해 발생시킬 수 있는 예외는 크게 세 가지가 있다.

  • Error
    • 첫째는 java,lang.Error 클래스의 서브클래스들이다. 에러는 시스템에 뭔가 비정상적인 상황이 발생했을 경우에 사용된다.
    • 주로 자바 VM에서 발생시키는 것이고 애플리케이션 코드에서 잡으려고 하면 안된다. (OutOfMemoryError, ThreadDeath)
    • 따라서 시스템 레벨에서 특별한 작업을 하는 게 아니라면 애플리케이션에서는 이런 에러에 대한 처리는 신경 쓰지 않아도 된다.
  • Exception과 체그 예외
    • java.lang.Exception 클래스와 그 서브클래스로 정의되는 예외들은 에러와 달리 개발자들이 만든 애플리케이션 코드의 작업 중에 예외상황이 발생했을 경우에 사용된다.
    • Exception 클래스는 다시 체크 예외언체크 예외로 구분된다.
    • 전자는 Exception 클래스의 서브 클래스이면서 RuntimeException 클래스를 상속하지 않은 것들이고, 후자는 RuntimeException을 상속한 클래스들을 말한다.
    • 일반적으로 예외라고 하면 Exception 클래스의 서브 클래스 중에서 RuntimeException을 상속하지 않은 것만을 말하는 체크 예외라고 생각해도 된다. 체크 예외가 발생할 수 있는 메소드를 사용할 경우 반드시 예외를 처리하는 코드를 함께 작성해야 한다.
  • RuntimeException과 언체크/런타임 예외
    • java.lang.RuntimeException 클래스를 상속한 예외들은 명시적인 예외처리를 강제하지 않기 때문에 언체크 예외라고 불린다. 런타임 예외라고도 한다.
    • 에러와 마찬가지로 이 런타임 예외는 catch 문으로 잡거나 threows로 선언하지 않아도 된다. 물론 명시적으로 잡거나 throws로 선언해줘도 상관없다.
    • 런타임 예외는 주로 프로그램의 오류가 있을 때 발생하도록 의도된 것들이다. 대표적으로 오브젝트를 할당하지 않은 레퍼런스 변수를 사용하려고 시도했을 때 발생하는 NullPointerException이나, 하용되지 않는 값을 사용해서 메소드를 호출할 때 발생하는 IllegalArgumentException 등이 있다.
    • 런타임 예외는 예상하지 못했던 예외상황에서 발생하는게 아니기 떄문에 굳이 catch나 threows를 사용하지 않아도 되도록 만든 것이다.

p. 285)

예외처리 방법

 

예외 복구

  • 첫 번쨰 예외처리 방법은 예외상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것이다.

예외처리 회피

  • 두 번 째 방법은 예외처리를 자신이 담장하지 않고 자신을 호출한 쪽으로 던져버리는 것이다.

예외 전환

  • 예외 회피와 비슷하게 예외를 복구해서 장상적인 상태로는 만들 수 없기 떄문에 예외를 메소드 밖으로 던지는 것이다. 하지만 예외 회피와 달리, 발생한 예외를 그대로 넘기는 게 아니라 적절한 예외로 전환해서 던진다는 특징이 있다.
  • 내부에서 발생한 예외를 그대로 던지는 것이 그 예외상황에 대한 적절한 의미를 부여해주지 못하는 경우에, 의미를 분명하게 해줄 수 있는 예외로 바꿔주기 위해서다. API가 발생하는 기술적인 로우레벨을 상황에 적합한 의미를 가진 예외로 변경하는 것이다.

p. 289)

  • 보통 전환하는 예외에 원래 발생한 예외를 담아서 중첩 예외로 만드는 것이 좋다.
    • 중첩 예외는 새로운 예외를 만들면서 생성자나 initCause() 메소드로 근본 원인이 되는 예외를 넣어주면 된다.
  • 두번째 전환 방법은 예외를 처리하기 쉽고 단순하게 만들기 위해 포장하는 것이다.
    • 주로 예외처리를 강제하는 체크 예외를 언체크 예외인 런타임 예외로 바꾸는 경우에 사용한다.

p.290)

  • 애플리케이션 로직상에서 예외조거이 발견되거나 예외상황이 발생할 수도 있다. 이런 것은 API가 던지는 예외가 아니라 애플라케이션 코드에서 의도적으로 던지는 예외다. 이때는 체크 예외를 사용하느 는것이 적절하다. 비즈니스적인 의미가 있는 예외는 이에 대한 적절한 대응이나 복구 작업이 필요하기 떄문이다.
  • 어차피 복구가 불가능한 예외라면 가능한 한 빨리 런타임 예외로 포장해 던지게 해서 다른 계층의 메소드를 작성할 때 불필요한 throws 선언이 들어가지 않도록 해줘야 한다.
  • 어차피 복구하지 못할 예외라면 애플리케이션 코드에서는 러나임 예외로 포장해서 던져버리고, 예외처리 서비스 등을 이용해 자세한 로그를 남기고, 관리자에게는 메일 등으로 통보해주고, 사용자에게는 치넞ㄹ한 안내 메시지를 보여주는 식으로 처리하는게 바람직하다.

p.291)

런티임 예외의 보편화

  • 일반적으로 체크 예외가 일반적인 예외를 다루고 있고, 언체크 예외는 시스템 장애나 프포그램상의 오류에 사용한다고 헀다.
  • 이렇게 예외처리를 강제하는 것은 예외가 발생할 가능성이 있는 API 메소드를 사용하는 개발자의 실수를 방지하기 위한 배려라고 볼 수도 있곘지만, 실제로는 예외를 제대로 다루지 싶지 않을 만큼 짜증나게 만드는 원인이 되기도 한다.

p.294)

애플리케이션 예외

  • 런타임 예외 중심의 전략은 굳이 이름을 붙이자면 낙관적인 예외처리 기법이라고 할 수 있다. 일단 복구할 수 있는 예외는 없다고 가정하고 예외가 생겨도 어차피 런타임 예외이므로 시스템 레벨에서 알아서 처리해 줄 것이고, 꼭 필요한 경우는 런타임 예외라도 잡아서 복구하거나 대응해줄 수 있으니 문제 될 것이 없다는 낙관적인 태도를 기반으로 하고 있다.
  • 반면에 시스템 또는 외부의 예외상횡이 원인이 아니라 애플리케이션 자체의 로직에 의해 의도적으로 발생시키고, 반드시 catch해서 무엇인가 조치를 취하도록 요구하는 예외도 있다. 이런 예외들을 애플리케이션 예외라고 한다.

p.297)

예외를 다른 것으로 바꿔서 던지는 예외 전환의 목적은 두 가지라고 설명했다. 하나는 앞에서 적용해 본 것처럼 런타임 예외로 포장해서 굳이 필요하지 않은 catch/throws를 줄여주느 ㄴ것이고, 다른 하나는 로우레벨의 예외를 좀 더 의미있고 추상화된 예외로 바꿔서 던져주는 것이다.

p.306)

JDO, JPA, 하이버네이트처럼 오브젝트/엔티티 단위로 정보를 업데이트하는 경우에는 낙관적인 락킹이 발생할 수 있다. 이 낙관적인 락킹은 같은 정보를 두 명 이상의 사용자가 동시에 조회하고 순차적으로 업데이트를 할 떄, 뒤늦게 업데이트 한 것이 먼저 업데이트 한 것을 덮어쓰지 않도록 막아주는 데 쓸 수 있는 편리한 기능이다.

p.310

@Autowired는 스프링의 컨텍스트 내에서 정의된 빈 중에 인스턴스 변수에 주입 가능한 타입의 빈을 찾아준다.

정리

  • 예외를 잡아서 아무런 조취를 취하지 않거나 의미 없는 throws 선언을 남발하는 것은 위험하다.
  • 예외는 복구하거나 예외처리 오브젝트로 의도적으로 전달하거나 적절한 예외로 전환해야 한다.
  • 좀 더 의미있는 예외로 변경하거나, 불필요한 catch/throws를 피하기 위해 런타임 예외로 포장하는 두 가지 방법의 예외 전환이 있다.
  • 복구할 수 없는 예외는 간으한 빨리 런타임 예외로 전환하느 는것이 바람직하다.
  • 애플리케이션의 로직을 담기 위한 예외는 체크 예외로 만든다.
  • SQLException의 에러 코드는 DB에 종속되기 떄문에 DB에 독립적인 예외로 전환될 필요가 있다.
  • 스프링은 DataAccessException을 통해 DB에 독립적으로 적용 가능한 추상화된 런티임 예외 계층을 제공한다.
  • DA를 데이터 엑세스 기술에서 독립시키려면 인터페이스 도입과 런티임 예외 전환, 기술에 독립적인 추상화된 예외로 전환이 필요하다.
728x90
반응형
Comments