스프링 test를 이용해서 체크예외와 언체크 예외를 비교해보자
체크 예외 기본 이해
체크 예외는 잡아서 처리하거나, 또는 밖으로 던지도록 선언해야한다. 그렇지 않으면 컴파일 오류가 발생한다.
@Slf4j
public class CheckedTest {
@Test
void checked_catch() {
Service service = new Service();
service.callCatch();
}
/**
* Exception을 상속받은 예외는 체크 예외가 된다.
*/
static class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
/**
* Checked 예외는
* 예외를 잡아서 처리하거나, 던지거나 둘중 하나를 필수로 선택해야 한다.
*/
static class Service {
Repository repository = new Repository();
/**
* 예외를 잡아서 처리하는 코드
*/
public void callCatch() {
try {
repository.call();
} catch (MyCheckedException e) {
//예외 처리 로직
log.info("예외 처리, message={}", e.getMessage(), e);
}
}
/**
* 체크 예외를 밖으로 던지는 코드
* 체크 예외는 예외를 잡지 않고 밖으로 던지려면 throws 예외를 메서드에 필수로 선언해야한
다.
*/
public void callThrow() throws MyCheckedException {
repository.call();
}
}
static class Repository {
public void call() throws MyCheckedException {
throw new MyCheckedException("ex");
}
}
}
체크 예외 잡아서 처리
service.callCatch() 에서 예외를 처리했기 때문에 테스트 메서드까지 예외가 올라오지 않는다
실행 순서 분석
test → service.callCatch() → repository.call() [예외 발생, 던짐] → service.callCatch() [예외 처리] → test [정상 흐름]
log.info("예외 처리, message={}", e.getMessage(), e);
로그를 남길 때 로그의 마지막 인수에 예외 객체를 전달해주면 로그가 해당 예외의 스택 트레이스 를 추가로 출력해준다.

catch로 체크 예외 처리
체크 예외를 잡아서 처리하려면 catch(..) 를 사용해서 예외를 잡으면 된다.
catch에 MyCheckedException의 상위 타입인 Exception을 적어주어도 MyCehckedException을 잡을 수 있다.
catch 에 예외를 지정하면 해당 예외와 그 하위 타입 예외를 모두 잡아준다.
체크 예외 밖으로 던지기
@Test
void checked_throw() {
Service service = new Service();
assertThatThrownBy(() -> service.callThrow())
.isInstanceOf(MyCheckedException.class);
}
service.callThrow() 에서 예외를 처리하지 않고, 밖으로 던졌기 때문에 예외가 테스트 메서드까지 올라 온다.
테스트에서는 기대한 것 처럼 MyCheckedException 예외가 던져지면 성공으로 처리한다.
실행 순서 분석
test → service.callThrow() → repository.call() [예외 발생, 던짐] → service.callThrow() [예외 던짐] → test [예외 도착]
throws로 예외 던지기
체크 예외를 처리할 수 없을 때는 method() throws 예외 을 사용해서 밖으로 던질 예외를 필수로 지정해 주어야 한다.
여기서는 MyCheckedException 을 밖으로 던지도록 지정해주었다.
참고로 체크 예외를 밖으로 던지는 경우에도 해당 타입과 그 하위 타입을 모두 던질 수 있다
체크 예외의 장단점
체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는 throws 예외 를 필수로 선언해야 한다. 그렇지 않으면 컴파일 오류가 발생한다. 이것 때문에 장점과 단점이 동시에 존재한다.
장점
개발자가 실수로 예외를 누락하지 않도록 컴파일러를 통해 문제를 잡아주는 훌륭한 안전 장치이다.
단점
실제로는 개발자가 모든 체크 예외를 반드시 잡거나 던지도록 처리해야 하기 때문에, 너무 번 거로운 일이 된다. 크게 신경쓰고 싶지 않은 예외까지 모두 챙겨야 한다
언체크 예외 기본 이해
RuntimeException 과 그 하위 예외는 언체크 예외로 분류된다.
예외를 던지는 throws 를 선언하지 않고, 생략할 수 있다. 이 경우 자동으로 예외를 던진다. → 체크 예외와의 차이점
@Slf4j
public class UncheckedAppTest {
@Test
void unchecked() {
Controller controller = new Controller();
assertThatThrownBy(() -> controller.request())
.isInstanceOf(Exception.class);
}
@Test
void printEx() {
Controller controller = new Controller();
try {
controller.request();
} catch (Exception e) {
//e.printStackTrace();
log.info("ex", e);
}
}
static class Controller {
Service service = new Service();
public void request() {
service.logic();
}
}
static class Service {
Repository repository = new Repository();
NetworkClient networkClient = new NetworkClient();
public void logic() {
repository.call();
networkClient.call();
}
}
static class NetworkClient {
public void call() {
throw new RuntimeConnectException("연결 실패");
}
}
static class Repository {
public void call() {
try {
runSQL();
} catch (SQLException e) {
throw new RuntimeSQLException(e);
}
}
private void runSQL() throws SQLException {
throw new SQLException("ex");
}
}
static class RuntimeConnectException extends RuntimeException {
public RuntimeConnectException(String message) {
super(message);
}
}
static class RuntimeSQLException extends RuntimeException {
public RuntimeSQLException() {
}
public RuntimeSQLException(Throwable cause) {
super(cause);
}
}
}
public void logic() {
repository.call();
networkClient.call();
}
reqpository.call()에서 언체크 예외가 터져서 밖으로 던지므로 networkClient.call은 실행되지 않는다.
SQLException만 던지고 언체크 예외는 throws를 사용하지 않고 자동으로 던져준다.
언체크 예외의 장단점
장점
신경쓰고 싶지 않은 언체크 예외를 무시할 수 있다. 체크 예외의 경우 처리할 수 없는 예외를 밖으로 던 지려면 항상 throws 예외 를 선언해야 하지만, 언체크 예외는 이 부분을 생략할 수 있다.
단점
언체크 예외는 개발자가 실수로 예외를 누락할 수 있다. 반면에 체크 예외는 컴파일러를 통해 예외 누 락을 잡아준다.
'Spring > Spring DB' 카테고리의 다른 글
트랜잭션 AOP 이해 (0) | 2023.10.04 |
---|---|
스프링 부트의 자동 리소스 등록 (0) | 2023.10.03 |
트랜잭션 템플릿 (0) | 2023.10.03 |
트랜잭션 추상화 (0) | 2023.10.03 |
트랜잭션 동기화 (0) | 2023.10.03 |

스프링 test를 이용해서 체크예외와 언체크 예외를 비교해보자
체크 예외 기본 이해
체크 예외는 잡아서 처리하거나, 또는 밖으로 던지도록 선언해야한다. 그렇지 않으면 컴파일 오류가 발생한다.
@Slf4j public class CheckedTest { @Test void checked_catch() { Service service = new Service(); service.callCatch(); } /** * Exception을 상속받은 예외는 체크 예외가 된다. */ static class MyCheckedException extends Exception { public MyCheckedException(String message) { super(message); } } /** * Checked 예외는 * 예외를 잡아서 처리하거나, 던지거나 둘중 하나를 필수로 선택해야 한다. */ static class Service { Repository repository = new Repository(); /** * 예외를 잡아서 처리하는 코드 */ public void callCatch() { try { repository.call(); } catch (MyCheckedException e) { //예외 처리 로직 log.info("예외 처리, message={}", e.getMessage(), e); } } /** * 체크 예외를 밖으로 던지는 코드 * 체크 예외는 예외를 잡지 않고 밖으로 던지려면 throws 예외를 메서드에 필수로 선언해야한 다. */ public void callThrow() throws MyCheckedException { repository.call(); } } static class Repository { public void call() throws MyCheckedException { throw new MyCheckedException("ex"); } } }
체크 예외 잡아서 처리
service.callCatch() 에서 예외를 처리했기 때문에 테스트 메서드까지 예외가 올라오지 않는다
실행 순서 분석
test → service.callCatch() → repository.call() [예외 발생, 던짐] → service.callCatch() [예외 처리] → test [정상 흐름]
log.info("예외 처리, message={}", e.getMessage(), e);
로그를 남길 때 로그의 마지막 인수에 예외 객체를 전달해주면 로그가 해당 예외의 스택 트레이스 를 추가로 출력해준다.

catch로 체크 예외 처리
체크 예외를 잡아서 처리하려면 catch(..) 를 사용해서 예외를 잡으면 된다.
catch에 MyCheckedException의 상위 타입인 Exception을 적어주어도 MyCehckedException을 잡을 수 있다.
catch 에 예외를 지정하면 해당 예외와 그 하위 타입 예외를 모두 잡아준다.
체크 예외 밖으로 던지기
@Test void checked_throw() { Service service = new Service(); assertThatThrownBy(() -> service.callThrow()) .isInstanceOf(MyCheckedException.class); }
service.callThrow() 에서 예외를 처리하지 않고, 밖으로 던졌기 때문에 예외가 테스트 메서드까지 올라 온다.
테스트에서는 기대한 것 처럼 MyCheckedException 예외가 던져지면 성공으로 처리한다.
실행 순서 분석
test → service.callThrow() → repository.call() [예외 발생, 던짐] → service.callThrow() [예외 던짐] → test [예외 도착]
throws로 예외 던지기
체크 예외를 처리할 수 없을 때는 method() throws 예외 을 사용해서 밖으로 던질 예외를 필수로 지정해 주어야 한다.
여기서는 MyCheckedException 을 밖으로 던지도록 지정해주었다.
참고로 체크 예외를 밖으로 던지는 경우에도 해당 타입과 그 하위 타입을 모두 던질 수 있다
체크 예외의 장단점
체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는 throws 예외 를 필수로 선언해야 한다. 그렇지 않으면 컴파일 오류가 발생한다. 이것 때문에 장점과 단점이 동시에 존재한다.
장점
개발자가 실수로 예외를 누락하지 않도록 컴파일러를 통해 문제를 잡아주는 훌륭한 안전 장치이다.
단점
실제로는 개발자가 모든 체크 예외를 반드시 잡거나 던지도록 처리해야 하기 때문에, 너무 번 거로운 일이 된다. 크게 신경쓰고 싶지 않은 예외까지 모두 챙겨야 한다
언체크 예외 기본 이해
RuntimeException 과 그 하위 예외는 언체크 예외로 분류된다.
예외를 던지는 throws 를 선언하지 않고, 생략할 수 있다. 이 경우 자동으로 예외를 던진다. → 체크 예외와의 차이점
@Slf4j public class UncheckedAppTest { @Test void unchecked() { Controller controller = new Controller(); assertThatThrownBy(() -> controller.request()) .isInstanceOf(Exception.class); } @Test void printEx() { Controller controller = new Controller(); try { controller.request(); } catch (Exception e) { //e.printStackTrace(); log.info("ex", e); } } static class Controller { Service service = new Service(); public void request() { service.logic(); } } static class Service { Repository repository = new Repository(); NetworkClient networkClient = new NetworkClient(); public void logic() { repository.call(); networkClient.call(); } } static class NetworkClient { public void call() { throw new RuntimeConnectException("연결 실패"); } } static class Repository { public void call() { try { runSQL(); } catch (SQLException e) { throw new RuntimeSQLException(e); } } private void runSQL() throws SQLException { throw new SQLException("ex"); } } static class RuntimeConnectException extends RuntimeException { public RuntimeConnectException(String message) { super(message); } } static class RuntimeSQLException extends RuntimeException { public RuntimeSQLException() { } public RuntimeSQLException(Throwable cause) { super(cause); } } }
public void logic() {
repository.call();
networkClient.call();
}
reqpository.call()에서 언체크 예외가 터져서 밖으로 던지므로 networkClient.call은 실행되지 않는다.
SQLException만 던지고 언체크 예외는 throws를 사용하지 않고 자동으로 던져준다.
언체크 예외의 장단점
장점
신경쓰고 싶지 않은 언체크 예외를 무시할 수 있다. 체크 예외의 경우 처리할 수 없는 예외를 밖으로 던 지려면 항상 throws 예외 를 선언해야 하지만, 언체크 예외는 이 부분을 생략할 수 있다.
단점
언체크 예외는 개발자가 실수로 예외를 누락할 수 있다. 반면에 체크 예외는 컴파일러를 통해 예외 누 락을 잡아준다.
'Spring > Spring DB' 카테고리의 다른 글
트랜잭션 AOP 이해 (0) | 2023.10.04 |
---|---|
스프링 부트의 자동 리소스 등록 (0) | 2023.10.03 |
트랜잭션 템플릿 (0) | 2023.10.03 |
트랜잭션 추상화 (0) | 2023.10.03 |
트랜잭션 동기화 (0) | 2023.10.03 |