☕️ Error와 Exception
체크 예외와 언체크 예외를 알아보기 전에 앞서 오류와 예외에 대한 차이를 먼저 알아보도록 하자.
자바 프로그래밍에서는 실행 시(runtime) 발생할 수 있는 오류는 크게 'Error'와 'Exception'이 존재한다.
Error는 프로그램 코드에 의해서 수습될 수 없는 심각한 오류를 말하며,
Exception은 프로그램 코드에 의해서 수습될 수 있는 오류를 뜻한다.
이번 포스팅에서는 Exception을 Checked Exception과 Unchecked Exception으로 분류하여 다뤄볼 예정이다.
☕️ Checked Exception과 Unchecked Exception
위에서 간단하게 살펴본 상속관계를 조금 더 구체적인 그림으로 알아보자.
Error와 RuntimeException과 그 하위 예외들은 Unchecked Exception으로 분류되며,
그 외 나머지 예외들은 Checked Exception으로 분류된다.
두 Exception의 가장 핵심적인 차이는 '반드시 예외처리를 해야 하는가?'이다.
Checked Exception은 반드시 예외를 처리해야 하며, Unchecked Exception은 명시적으로 처리를 하지 않아도 된다.
import java.io.FileWriter;
import java.io.IOException;
public class CheckedAndUnchecked {
public static void main(String[] args) {
// Checked Exception 중 하나인 IOException은 반드시 처리를 해야한다.
try {
FileWriter file = new FileWriter("data.txt");
} catch (IOException e) {
throw new RuntimeException(e);
}
// Unchecked Exception 중 하나인 NullPointerException은 반드시 처리를 할 필요는 없다.
String str = null;
str.length(); // NullPointerException 발생
}
}
그 외 차이점은 표를 통해 알아보자.
Checked Exception | Unchecked Exception | |
확인 시점 | Compile 시점 | Runtime 시점 |
처리 여부 | 반드시 예외 처리 필요 | 명시적으로 하지 않아도 무관 |
트랜잭션 롤백 여부 | 예외 발생 시, Rollback 수행 안함 | 예외 발생 시, Rollback 수행 |
☕️ Checked Exception 문제점
가장 좋은 오류는 컴파일 시점에 발견되는 오류이다.
개발을 하다 한 번씩은 들어봤을 말일 것이다. 이 말로 미루어봤을 때, Compile 시점에 알 수 있는 Checked Exception이 가장 이상적인 Exception이 아닌가 할 수 있을 것이다.
하지만, Checked Exception은 반드시 예외를 처리한다는 특성 때문에 Exception을 던지게(throw)되면, 계층 간 종속이 발생할 수 있다.
가령 DB 또는 네트워크에 연동하는 Repository나 NetworkClient 클래스에서 각 각의 Exception을 잡지 않고 throws로 던지게 되면,
이를 사용하는 Service에서는 Repository와 NetworkClient와의 종속이 생겨버리게 된다.
또한 Service에서도 더 상위 계층으로 throws를 반복하게 되면 아래의 그림처럼 모든 계층 간에 종속이 발생하게 된다.
문제는 추후 기술 변경으로 Repository를 변경하여 JDBC 대신 JPA를 사용한다고 가정했을 때,
아래와 같이 종속된 모든 계층을 수정해야 하는 아찔한 상황이 발생할 것이다.
이러한 문제로 Checked Exception을 Unchecked Exception으로 전환하는 형태로 많이 사용된다.
아래의 코드처럼 Checked Exception을 핸들링하여 Unchecked Exception으로 전환한다면, 종속성을 제거할 수 있게 된다.
static class Repository {
public void call() {
try {
runSQL();
} catch (SQLException e) {
/*
Checked Exception인 SQLException 대신에
Unchecked Exception인 RuntimeSQLException 던진다.
*/
throw new RuntimeSQLException(e);
}
}
private void runSQL() throws SQLException {
// SQL 수행 중 오류가 발생했다고 가정.
throw new SQLException("ex");
}
}
// RuntimeSQLException은 RuntimeException을 상속받았으므로 Unchecked Exception이 된다.
static class RuntimeSQLException extends RuntimeException {
public RuntimeSQLException(Throwable cause) {
super(cause);
}
}
References.
1. 김영한 님 - 스프링 DB 1편. 데이터 접근 핵심 원리
2. Inpa - 자바 에러(Error) 와 예외 클래스(Exception) 💯 이해하기
3. gil.log - [Java]Error, Exception(Checked, Unchecked)
4. 코드 연구소 - [Spring] 체크 예외(Checked Exception) vs 언체크 예외(Unchecked Exception)/런타임 예외(RuntimeException), 예외전환
'IT' 카테고리의 다른 글
[Spring] ORM, JPA, Hibernate, Spring Data JPA 개념 (1) | 2025.01.24 |
---|---|
[Spring] @Transactional (1) | 2025.01.24 |
[Java] java.time 패키지 (2) | 2025.01.22 |
[Java] Optional (1) | 2025.01.22 |
[Java] 스트림 API(Stream API) (1) | 2025.01.22 |