잘못 알려진 (Un)Checked Exception 트랜잭션
Checked Exception 과 Unchecked Exception 차이를 알아볼때 다음과 같이 정리된 포스팅을 많이 봤을 것이다.
만일 코드에서 예외가 발생했는데 Checked Exception 이면 롤백을 하지않고 그대로 진행되고, 만일 Unchecked Exception 이면 롤백을 한다는 것이다.
그러나 이는 반은 맞고 반은 틀린 정의이다.
백기선님의 강의에서도 이 부분에 대해서 따끔하게 혼내주시기도 한다. 지금부터 그 이유를 알아보자.
자바의 트랜잭션 다루기
트랜잭은 데이터베이스에서도 쓰이는 개념으로서, 하나의 작업 단위를 뜻한다.
예를들어 쇼핑몰의 "상품발송"이라는 트랜잭션을 가정해 보자.
"상품발송" 이라는 트랜잭션에는 "포장" → "영수증발행" → "발송" 순으로 처리가 된다.
만일 이 3가지 작업 중간에 하나라도 실패한다면 3가지 작업을 모두 취소하고 "상품발송" 전 상태로 되돌려야 한다. 왜냐하면 모두 취소하지 않으면 배송 처리 과정에서 문제가 생겨 꼬일 수 있기 때문이다.
프로그램이 다음과 같이 작성되어 있다고 가정 해 보자.
아래는 실제 코드가 아니라 어떻게 동작하는지를 간략하게 표현한 의사 코드이다.
public void 상품발송() {
포장();
영수증발행();
발송();
}
public void 포장() {
...
}
public void 영수증발행() {
...
}
public void 발송() {
...
}
쇼핑몰 운영자는 포장, 영수증발행, 발송이라는 세가지 중 1가지라도 실패하면 모두 취소하고 싶어한다.
이런경우, 각 작업 메서드에서 예외가 발생하면 상위 메서드인 상품발송() 에서 처리하도록 throws 를 설정해주고, 상품발송() 메서드에서 try - catch 문으로 작업들을 감싸주면 된다.
그러면, 포장, 영수증발행, 발송 메서드 에서 하나의 작업에서 예외가 발생하면, 예외를 상위 메서드로 throw하고, 상품발송 메서드에서 throw된 예외를 처리하여, 예외가 발생한 작업 그 뒤로는 작업이 진행되지 않으며, catch문에서 모두 취소하는 작업 메서드를 실행한다면, 완벽한 트랜잭션 처리 로직이 완성된다.
public void 상품발송() {
try {
포장();
영수증발행();
발송();
}catch(예외) {
모두취소(); // 하나라도 실패하면 모두 취소한다.
}
}
public void 포장() throws 예외 {
...
}
public void 영수증발행() throws 예외 {
...
}
public void 발송() throws 예외 {
...
}
반대로 각 작업 메서드 내에서 일일히 try - catch 예외 처리를 해준다면, 만일 3가지 작업중 하나가 예외가 발생하더라도 작업 메서드 실행 자체에는 영향을 주지 않아 3가지 작업이 상품발송 메서드에서 제약 없이 모두 실행되게 된다.
public void 상품발송() {
포장();
영수증발행(); // 민일 영수증 발행 과정에서 예외가 발생해도, 메서드 내에서 자체적으로 예외 처리를 해주었기 때문에
발송(); // 영수증발행취소를 했지만 결국 발송 작업 메서드는 실행되게 되어버린다.
}
public void 포장(){
try {
...
}catch(예외) {
포장취소();
}
}
public void 영수증발행() {
try {
...
}catch(예외) {
영수증발행취소();
}
}
public void 발송() {
try {
...
}catch(예외) {
발송취소();
}
}
이렇게 예외처리를 어느 작업 메소드에 하느냐에 따라, 작업을 취소하고 롤백을 할지, 아니면 롤백을 하지 않고 그냥 진행할지 개발자가 직접 정할수 있는 것이다.
💡(Un)Checked Exception과 트랜잭션은 아무 상관 없다
본문 초반에 나와있는 표에서 지적한 것 처럼, 결론부터 말하자면 트랜잭션 규칙과 예외처리는 전혀 상관이 없다.
위에서 상품발송 처리를 의사 코드로 확인해봤듯이 롤백을 하든 안하든 그것은 전적으로 개발자 마음이다.
또한 트랜잭션이란 용어는 사용 범위가 다양하다. 위에서 말한 트랜잭션이, 메세지 트랜잭션을 말하는 건지, 데이터베이스 트랜잭션을 말하는 건지도 애매하다.
만일 데이터베이스의 트랜잭션을 말하는 것이라도 checked exceptoin이든 unchecked exceptoin이든 에 따라 롤백(rollback)을 할지 안할지는 전적으로 개발자에게 달려 있다.
즉, 자바 프로그래밍 언어에서는 위와 같은 규칙은 없다.
하지만 저렇게 Exception 종류에 따라 롤백 유무가 다르다고 정리된 이유는, 자바의 유명한 프레임워크 Spring Framework 의 트랜잭션 처리에서 비롯 됐기 때문이다.
스프링에서는 기본적으로는 런타임 예외 같은 경우 바로 롤백을 한다.
그러나 이 상황도 개발자가 옵션을 어떻게 설정하느냐에 따라 충분히 바꿀 수 있는 요소이다. 예를들어 런타임 자식 예외클래스 중에 몇몇을 골라서 롤백을 하지 않도록 설정이 가능하다.
정리하자면, 자바를 스프링과 동일시 한다면 위와 같이 정리하는 것이 맞을 수 있다. 그러나 자바 프로그래밍에서만 생각한다면 checked exceptoin과 unchecked exceptoin과 트랜잭션 롤백 유무는 연관이 없는 것이다. 그리고 예외발생이 트랜잭션 처리에 대해서는 checked 든 unchecked 든 전적으로 개발자 마음에 달려있다고 볼 수 있다.
참고