study-toby-spring / dongheon.shin

MIT License
0 stars 0 forks source link

Exception #3

Open XDXO opened 7 years ago

XDXO commented 7 years ago

개요

예외에 대해서 잘 설명해 둔 것 같은 블로그가 있어 신입 교육때에도 참고했으나 여전히 명확하게 기억에 남는 것은 아니라서 따로 정리하는 시간을 가지려 한다.

구분

크게 예외는 아래와 같이 구분 가능하다

└── Throwable
    ├── Error : 시스템 레벨의 예외 사항
    └── Exception : 애플리케이션 레벨의 예외 사항
        ├── CheckedException
        └── RuntimeException

계층

ErrorException은 구분의 기준이 명확하다. Error는 주석에서 다음과 같이 설명하고 있다.

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch

심각한 문제를 발생할 수 있는 상황에 발생하며, 에러를 잡아도 코드 레벨에서 처리할 방법이 없다. 때문에 이런 에러가 발생한다면 구태여 잡을 것이 아니라 비정상적으로 동작하지 못하도록 죽게 냅두는 것이 낫다. 대부분 이런 문제는 시스템 레벨에서 발생하는데 애플리케이션 레벨에서 발생하는 Exception과 명확하게 대비된다.

Exception의 회피 가능성

그러나 CheckedExceptionRuntimeException는 언뜻 이해가 될 것 같으면서도 이해가 쉽지 않다.

우선 CheckedException는 문법적으로 try ~ catch로 감싸 처리하거나 throws를 명시하도록 강제한다. 때문에 올바른 소프트웨어를 작성하려는 개발자라면 해당 예외 사항에 대해서 적절한 대응을 할 것이다.

역으로 CheckedException을 던지는 함수는 관련 예외를 발생시키는 조건이나 사항이 코드를 작성하는 시점에서 예측 가능하다는 것을 알 수 있다. 아마도 해당 함수를 설계하는 사람이라면 '이런 조건에서는 문제가 발생할 수 있으니 예외를 던져야겠다'는 것이 명확하기 때문일 것이다.

한편, RuntimeException는 Connection Timeout이나 Constraint Violation과 같이 외부의 변경에 의해서, 즉 코드를 작성하는 시점이 아닌 코드가 배포되어 동작하는 시점에서도 환경에 의해서 동작 여부가 결정될 수 있다는 것이다. RuntimeException으로 이름이 지어진 이유는 이 때문일 것이다. 그 때문인지 RuntimeException은 예측 시점이 명확하지 않기 때문에 try ~ catch를 강제하지 않는다.

CheckedException vs RuntimeException

책에서 설명하는 CheckedExceptionRuntimeException은 어찌 보면 비슷한 것이 많다.

크게 보면 이 두 공통점의 기준이 모호해서 둘을 어떻게 명확하게 나눠야 좋을지 고민이 된다. 그래서 내가 고민해서 내린 나름의 기준은 다음과 같다.

Spring Tx를 사용하면 트랜잭션을 아주 간편하게 사용할 수 있는데 대부분 RuntimeException에만 자동으로 롤백을 수행하도록 한다. 그 이유는 예측하지 못한 상황에 대응하도록 하기 위함이며, CheckedException이 발생하는 경우라면 미리 코드 레벨에서 수정되었어야 함을 의미하는 건 아닐까 싶다.