이 글을 쓰는 시점에서 저는 아직까지 명확한 예외처리 전략을 정하지 못했습니다.
이는 Java 언어 초기 설계의 전략과 현재의 전략, 그리고 스프링의 전략이 같지 않고,
비즈니스 측면에서도 회사마다 다르리라 생각됩니다.
Spring의 Transaction rollback이 일어나는 조건은 스프링 에러처리 전략에 따라 다음과 같습니다.
Error, Unchecked Exception
: 트랜잭션 롤백
Checked Exception
: 트랜잭션 커밋
또한, 트랜잭션 전파 속성을 PROPAGATION_REQUIRED(Default)
로 준 경우 내부에서 UncheckedException
을 유발하는 메소드가 UncheckedException
을 발생시키면, try-catch
로 해당 예외를 처리했다한들 이미 rollback-only
속성이 마킹되어 최종적으로 트랜잭션 완료를 할 때, rollback을 수행합니다.
스프링의 예외처리 전략은 이렇습니다.
개발자가 코드로 처리 불가능한 SQLException
, IOException
등의 자바 초기에 구현된 클래스가 던지는 CheckedException
은 DataAccessException
와 같은 UnchekcedException
으로 포장해줍니다.
즉, 런타임에 해결이 불가능한 예외의 경우엔 쓸데없이 메소드 시그니처에 throws를 반복적으로 적거나, 의미 없는 try-catch를 하는 것을 방지하기 위함입니다.
자세한 내용은 토비의 스프링을 읽어보시는걸 추천하고, 그럼 이게 왜 고민이 되느냐라고 하실 수 있습니다.
보통의 경우 저는 RuntimeException
을 적극적으로 상속한 후 에러처리를 진행합니다.
정말 짧은 생각으로, '비즈니스 로직에서 발생하는 예외는 다 롤백되어야지!' 라는 생각이었습니다.
그런데, 비즈니스적으로 의미가 있는 예외이면서, 롤백은 시키지 않아야 하는 Exception
도 존재하지 않을까요?
아직까지 그런 경험은 하지 못했지만, 충분히 가능성이 있어 보입니다.
그런데 그럼 이 예외는 어떻게 처리할까요? @Transactional
에 일일이 적어주는것도 방법같아 보이지만, 굉장히 많은 영역에 적용해야할 수도 있어보입니다.
그러면 이 예외는 CheckedException
이면서 비즈니스 로직상에서 예외처리를 해줘야 합니다.
근데 이렇게 하면 정리가 제대로 되지 않죠?
그래서 제 나름의 전략을 세우고 정리했습니다.
발생가능성이 충분히 예측가능하고, 런타임에 복구가 가능한 경우(AND) = CheckedException
예측 불가능하거나 런타임에 복구가 불가능한 예외, 트랜잭션이 롤백되어야 하는 비즈니스 예외 = UncheckedException
예외처리는 하지 않지만, 트랜잭션은 커밋시키고 싶을 때 = @Transactional
에 표시하기
하지만, 영향 받는 메서드 영역이 많다면? CheckedException
을 그냥쓰고 예외처리 해주기
감사합니다.
생각해보니 분명히 어떤 방식으로든 데이터 접근할때 SQLException, IOException 이런 Checked Exception 이 떨어질텐데 try catch 안해준게 다 래핑해줘서 그랬던거였군요...디온 나름의 전략도 잘 보았습니다. 감사합니다 자세한건 토비에서..