우선 글을 시작하기에 앞서, java의 checked/unchecked 예외가 적힌 아래의 표를 보자.
위의 표를 보고 "뭐야, 다 아는 내용이잖아?" 라는 생각이 들었다면, 그것은 잘못 공부한 것이다.
위의 표에서는 "예외 발생 시 트랜잭션 처리" 라는 부분이 잘못되었다.
온전히 "자바"의 관점에서만 본다면, rollback 여부와 예외의 종류는 전혀 무관하고, rollback을 할지, 말지는 우리가 정하는 거다.
이러한 오해의 기원은 Spring의 DB 트랜잭션 처리에 있다.
Spring DB 트랜잭션 처리
chkecked 예외: 복구 가능성이 존재하기에 try catch로 잡아서 따로 복구로 직을 수행하도록하고 롤백하지 않는 것이 보통이다.
unchecked 예외: 복구할 가능성이 없거나 적은 divide 0, index 에러 와 같은 에러일 가능성이 높다. 따라서 이 경우 보통 롤백해야할 것이다.
이러한 생각에서 Spring DB 트랜잭션은 아래와 같은 디폴트 설정을 가진다.
디폴트 설정을 기준으로, 스프링 프레임워크의 DB 트랜잭션은 runtime, unchecked exception인 경우(RuntimeException의 인스턴스 or subclass)에만 rollback을 마크하고, 롤백을 수행한다.
따라서 설정을 바꿔서 Runtime 중 특정 예외는 롤백하지 않게 설정하거나, 반대로 언체크 예외 중 특정 예외는 롤백하지 않도록 바꿀 수 도 있다. 그렇기에 예외의 종류 == 롤백 유무로 생각하는 것은 잘못 된생각이다.
요약
스프링의 DB 트랜잭션 처리에서 체크/언체크에 따라 디폴트 롤백 설정이 나뉘는 것으로 인해 java 자체에서 체크/ 언체크를 기준으로 롤백 유무가 나뉜다고 오인하는 경우가 많지만, 전혀 상관없다.
자바, 스프링 예외 처리에 대해 더 알고 싶다면 아래 글을 참고하자.
자바 예외 처리 기본
https://codenme.tistory.com/94
스프링 예외 처리 기본
https://codenme.tistory.com/95
그럼 Check, Unchecked 예외, 어떤 차이가 있고 언제 써야할까?
Java 프로그래밍 언어에는 unchecked 예외(RuntimeException, Error 및 해당 하위 클래스)를 포착하거나 지정하는 메서드가 필요하지 않기 때문에 프로그래머는 unchecked 예외만 throw하는 코드를 작성하거나 모든 예외 하위 클래스가 RuntimeException에서 상속되도록 만드는 방향으로 가기 쉽다.하지만 이는 catch와 specify의 의도를 무시하고 클래스를 사용하는 다른 사람에게 문제를 일으킬 수 있다.
java의 설계자가 checked 예외는 try catch로 처리하고, 메소드에서 해당 예외를 throws하여 지정하도록 하는 이유는 뭘까? 그것은 메서드에서 발생하는 예외 자체가 해당 메소드를 나타내는 정보이기 때문이다. 이는 타인이 해당 메소드를 사용하거나, API 문서를 확인할 때 리턴 타입, 매개변수 만큼이나 많은 정보를 제공한다.
그러면 왜 런타임 예외는 메소드에서 지정하지 않아도 될까? 그 이유는 런타임에러는 보통 복구하기 어려운 문제들이기 때문이다. 0으로 나누는 것과 같은 산술 예외, null 참조를 통해 개체에 액세스하려는 것과 같은 포인터 예외, 너무 크거나 너무 작은 인덱스를 통해 배열 요소에 액세스하려는 인덱싱 예외 등등이 이러한 '복구 불가' 한 예외 들이다. 이 경우는 어차피 복구가 불가능한 치명적 문제들이기에, 해당 메소드를 만든 본인이 해결해야하는 문제이다. 따라서 특별하게 알리고 싶은 에러는 throws를 통해 메소드에 지정하고, 그 외에는 지정하지 않으면 된다.
RuntimeException을 던지는 일반적인 케이스 중 하나는 유저가 메소드를 잘못 호출한 경우이다.
예를 들어, 메소드는 어떠한 argument가 null로 들어온 것을 감지하고, NullPointerException을 throw하는 경우가 많은데, 이게 RuntimeException 하위의 에러, 즉 언체크 예외이다.
체크, 언체크 예외는 위와 같은 이유로 각각의 장점이 있기에, 단순히 귀찮다는 이유로 모든걸 언체크로 두고 메소드에 지정하지 않고 컨트롤 되지 않도록 내버려 둬서는 안된다.
결론
- 만약 어떠한 예외가 복구 가능해 보인다면, 체크 예외로 던지자.
- 만약 복구 불가능 해보인다면, 언체크 예외로 던지자.
'java' 카테고리의 다른 글
java의 동작 원리 및 구조 [JVM의 구조] (0) | 2023.08.02 |
---|---|
[effective java] 생성자에 매개변수가 많다면 빌더를 고려하자 (0) | 2023.07.18 |
[이펙티브 자바] 정적 팩토리 메소드 (0) | 2023.07.16 |
[이펙티브 자바] ENUM (0) | 2023.07.15 |