@Transaction 어노테이션은 모든 예외를 롤백하지 않는다

신연우·2023년 11월 12일
0

WIL

목록 보기
7/13

배경

다른 사람의 코드 리뷰를 보던 도중 작성한 코드대로라면 정상적으로 롤백될 것 같지 않아 @Transaction 어노테이션의 롤백 옵션에 대해 알아보게 되었습니다.

@Transaction 어노테이션 롤백 설정

Defines zero (0) or more exception types, which must be subclasses of Throwable, indicating which exception types must cause a transaction rollback.

By default, a transaction will be rolled back on RuntimeException and Error but not on checked exceptions (business exceptions). See DefaultTransactionAttribute.rollbackOn(Throwable) for a detailed explanation.

This is the preferred way to construct a rollback rule (in contrast to rollbackForClassName()), matching the exception type and its subclasses in a type-safe manner. See the class-level javadocs for further details on rollback rule semantics.
공식문서

rollbackFor 옵션을 별도로 설정하지 않으면 RuntimeExceptionError가 발생했을 때는 롤백을 하지만 checked exception이 발생했을 때는 롤백을 하지 않는다고 합니다.

이때 checked exception에 대해서 처음 들어보게 되어서 어떤 예외인지 조금 더 살펴보고 싶었습니다.

Throwable 종류

kotlin에서는 throwable을 확장해 사용자에게 문제 상황을 알리는 종류 세 가지가 존재합니다.

  • 에러
  • 검사 예외
  • 비검사 예외

에러

프로그램 실행 중 비정상적인 상황이 발생했음을 알려줍니다.
대표적인 예로 StackOverflowError, OutOfMemoryError가 있습니다.
모두 Error 클래스를 확장합니다.
프로그래머가 catch 구문을 통해 별도의 핸들링을 할 수 없는 상황에서 발생하게 됩니다.

비검사 예외

더 이상 프로그램을 실행해도 무의미하거나 더 안 좋은 상황으로 이어질 수 있을 때 발생합니다.
대표적인 예로 IllegalArgumentException, IllegalStateException이 있습니다.
모두 RuntimeException을 확장합니다.
에러와의 차이점은 프로그래머가 문제 상황이 발생했음을 인지한 구간에서 직접 예외를 던질 수 있다는 점입니다.

검사 예외

대표적인 예로 IOException, SQLException이 있습니다.
비검사 예외와 거의 동일하나 Exception 클래스를 확장합니다. 정확히 얘기하면 RuntimeException을 확장하지 않습니다.
해당 예외를 핸들링 해 복구 전략을 수행할 수 있을 때 사용합니다. 호출하는 쪽에 반드시 해당 예외에 대한 복구 전략을 세워놓는 것을 강제한다고 볼 수 있습니다.

결론

기본적으로 Transactional에서 문제가 발생했을 때 Error와 RuntimeException과 이의 하위 클래스들에 해당하는 것들만 롤백의 대상으로 취급하는 이유는 호출하는 쪽에서 복구 전략을 세울 수 없는 상황이기 때문입니다.

반대로 검사 예외의 경우, 호출하는 쪽에서 충분히 문제 상황에 대해 복구할 수 있는 상황에 던져지는 예외이기 때문에 롤백의 대상으로 삼지 않고 호출하는 쪽에 예외의 핸들링 책임을 전담합니다.

profile
남들과 함께하기 위해서는 혼자 나아갈 수 있는 힘이 있어야 한다.

0개의 댓글