업데이트:

보통 Java Checked Exception, Unchecked Exception에 대해 공부하다 보면 항상 등장하는 부분이 있습니다.

Checked Exception / Unchecked Exception

1. Checked Exception
	1) 반드시 예외를 처리해야 함
	2) Rollback 하지 않음

2. Unchecked Exception
	1) 명시적인 처리를 강제하지 않음
	2) Rollback 함

이번 포스팅은 정말 이 명제가 정확한지 확인하는 포스팅입니다.

Exception


java_exception

먼저 Java의 Exception에 대해서 간단히 알아도보록 하겠습니다.

위에 그림은 Java의 오류 관련 클래스들의 계층 구조인데, 여기서 Error는 시스템에 비정상적인 상황(OutofMemoryError, StackOverflowError 등)이 발생했을 경우이기 때문에 개발자 들이 예측하기도, 처리하기도 어렵습니다.

따라서, 저는 Exception만 알아보도록 하겠습니다.

Exception은 프로그래밍 적으로 처리 가능한 오류를 뜻하는데, 위의 그림을 보면 하위에 Checked ExceptionRuntimeException을 상속받은 Unchecked Exception이 있습니다.

Checked Exception

Checked Exception은 다음과 같은 특징이 있습니다.

  1. 반드시 예외처리를 해야한다.
  2. 컴파일 단계에서 발생

위와 같은 속성에 따라 Checked ExceptionintelliJ같은 IDE에서 예외처리를 강요합니다.

즉, 컴파일 단계에서 발생한다고 알수 있죠. 따라서 Checked Exception은 반드시 try ~ catch문이나 throwsException을 처리해줘야 합니다.

그럼 대표적인 Checked Exception으로는 IOException, SQLException이 있는데 간단한 예로 다음과 같은 상황을 상상해보겠습니다.

Jdbc에서 DB와 connection을 맺고자 할때 DB가 구동중이지 않는 상황.

이때 어떤 Exception이 발생하게 될까요?

저는 MariaDB와 Connection을 맺으려고 하고 있으며 사용된 driverClass 역시 org.mariadb.jdbc.Driver입니다.

jdbc_connection_exception

위와 같이 SQLNonTransientConnectionException이 발생한 것을 확인할 수 있습니다.

발생한 ConnectionHelper 클래스의 connectSocket() 메소드로 가서 Exception이 발생한 곳으로 가보면 다음과 같이 IOExceptiontry ~ catch로 명시적으로 처리해주는것을 알 수 있습니다.

io_exception

Unchecked Exception

Unchecked Exception은 다음과 같은 특징이 있습니다.

  1. 명시적인 처리를 강제하지 않는다.
  2. 실행(Runtime) 단계에서 발생한다.

대표적인 Unchecked Exception으로는 NullPointException, IllegalArgumentException 등이 있습니다.

IllegalArgumentException를 발생시킬 때 try ~ catchthrows로 처리하지 않더라도 IDE에서 컴파일에러가 발생하지 않는것을 볼 수 있고, 이는 실행(Runtime)에서 Exception이 발생할 것임을 유추할 수 있습니다.

unchecked_exception

❗그러나 이것이 Exception 처리를 하지 않는다는 뜻은 아님을 아셔야 합니다. “명시적인 처리를 강제하지 않는다.” 전 이말을 “그럼 Exception에 대한 후 처리를 안해도 되나?”라고 바보같이 오해한적이 있습니다. 강제하지 않을 뿐이지 후 처리는 어떻게든 반드시 하셔야 합니다. 공통적인 ExceptionHandler 등을 통하여 유저 메시지를 출력한다든지, 로그를 쌓는다든지, 슬랙 등으로 알림을 보낸다든지 Exception 상황에 대처하기 위해 필요한 후 처리는 반드시 필요합니다.

클린코드 Unchecked Exception

클린코드에서는 Unchecked Exception 사용을 권장하고 있는데 여러 이유가 있겠지만 제일 주된 이유는 Checked ExceptionOCP(Open/Closed Principal)를 위배하기 때문입니다. 위에서 update() 메소드에서 SQLException 같은 Checked Exceptionthrows로 호출한 메소드로 던지고 있다면, 호출한 모든 메소드에 영향이 가게 되고 따라서 OCP(Open/Closed Principal)를 위배하게 됩니다.

이런 이유로 클린코드에서는 Unchecked Exception 사용을 권장하고 있습니다.

그 밖에도 클린코드에서 말하는 예외처리도 있는데, 이는 다른 포스트에서 다뤄보도록 하겠습니다.

Rollback


그럼 이번엔 이번 포스트에 핵심 내용인 Exception과 관련된 Rollback을 보도록 하겠습니다.

Checked Exception, Unchecked Exception을 공부하시는 분들이라면 한 번쯤 다음 문구를 보신적이 있으실텐데요.

예외 발생 시 트랜잭션 처리

1. Checked Exception - Rollback 하지 않음
2. Unchecked Exception - Rollback 함

저도 예전에는 구글링한 자료에서 좀 이상은 했지만 그래도 설마싶어서 그냥 외웠는데요. 백기선님의 영상을 보고 다시 공부하게 되었습니다. (반성합니다…)

결론부터 말하자면 “Java Exception의 종류와 DB 트랜잭션 Rollback은 아무 상관이 없다.” 입니다.

그럼 제대로된 내용은 무엇일까?

💡먼저 용어부터 정확히 하고 넘어가겠습니다. 보통 Exception에 종류와 Rollback에 관한 내용을 말할 때, 나오는 트랜잭션은 DB 트랜잭션을 뜻합니다.

아마 여러 블로그들에 있는 ExceptionRollback에 관련 내용들은 Spring에서의 Exception 종류에 따른 Rollback 정책으로 부터 나온 오인된 내용이 아닐까 싶습니다.

16. Transaction Management

위의 링크에서 16.5.3 Rolling back a declarative transaction을 보시면 아래와 같은 내용이 있습니다.

In its default configuration, the Spring Framework’s transaction infrastructure code only marks a transaction for rollback 
in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException. 
( Errors will also - by default - result in a rollback). 
Checked exceptions that are thrown from a transactional method do not result in rollback in the default configuration.

RuntimeException은 기본적으로 Rollback 처리하고, Checked ExceptionRollback을 하지 않는다고 적혀있습니다.

또한, Spring은 다양한 옵션을 통해 Rollback에 대한 처리를 개발자가 Optional하게 처리할 수 있도록 지원하고 있습니다.

다음은 @Transactional 어노테이션에서 지정할 수 있는 속성표이고, 빨간 박스는 Rollback과 관련된 옵션들 입니다.

spring_transactional_option

마무리


이 포스트를 보신 분들이라면 다음 내용을 확실히 기억하시기 바랍니다.

“Java Exception 종류와 DB 트랜잭션 Rollback과는 아무런 관련이 없다.”

“Spring의 Exception 발생 시 트랜잭션 기본 동작은 RuntimeException은 Rollback 처리하고, Checked Exception은 Rollback하지 않는다.”

“Spring의 Exception 발생에 대한 동작 옵션들을 지원하기 때문에 개발자가 지정할 수 있다.”

저 역시 잘못된 내용을 학습했고, 의심이 있었음에도 공식문서 등을 확인해볼 노력을 안했기 때문에 이런 내용을 답습하게 된것 같습니다.

좀 더 확실히 공부하도록 노력을 더 기울여야겠습니다.

저와 비슷한 경험을 하셨을 분들께서 이번 포스트가 도움이 되셨으면 좋겠습니다.

오늘도 긴 제 글을 읽어주셔서 감사합니다. 😀

📌참고


백기선님 예외에 대한 유튜브 영상

댓글남기기