자바 프로그래밍에서 예외 처리에 대한 이해는 매우 중요하다. 예외는 프로그램 실행 중 발생할 수 있는 오류를 의미하며, 이를 적절히 처리하지 않으면 프로그램이 비정상적으로 종료될 수 있다. 이번 포스팅에서는 Checked Exception과 Unchecked Exception에 대해 자세히 알아보겠다.
먼저, Error와 Exception의 차이를 이해해야 한다. Error는 시스템의 심각한 문제로, 애플리케이션에서 복구할 수 없는 상황을 의미한다. 반면, Exception은 프로그램 실행 중 발생할 수 있는 예외적인 상황으로, 적절한 처리를 통해 해결할 수 있다.
예를 들어, 파일을 열려고 할 때 해당 파일이 존재하지 않는 경우는 Exception에 해당하며, 이를 적절히 처리하면 프로그램의 안정성을 높일 수 있다.
또한, Checked Exception과 Unchecked Exception은 모두 Exception
의 하위 개념이지, Error
에 속하지 않는다는 점을 명확히 이해해야 한다.
🔎 Error : 프로그램 코드 및 애플리케이션에서 처리할 수 없는 문제, 복구 ❌
🔎 Exception : 프로그램 코드나 애플리케이션에서 처리할 수 있는 문제, 복구 ⭕
CheckedException은 Exception
클래스와 하위 클래스 중 RuntimeException
을 제외한 모든 예외를 의미하며, 컴파일 타임에 반드시 처리해야 하는 예외다. 이러한 예외를 코드에서 처리하지 않으면 컴파일 오류가 발생한다.
대표적인 CheckedException으로는 IOException
, SQLException
, ClassNotFoundException
등이 있으며, 주로 외부 시스템과의 상호작용에서 발생하는 오류를 나타낸다.
예를 들어:
FileNotFoundException
→ 파일을 읽으려 할 때 해당 파일이 존재하지 않는 경우SQLException
→ 데이터베이스에 연결할 수 없는 경우CheckedException은 보통 try-catch
문을 사용하거나 throws
키워드를 활용하여 예외를 처리해야 한다.
UnCheckedException은 RuntimeException
클래스와 그 하위 예외를 의미하며, 컴파일 타임에 체크되지 않는 예외이다. 즉, 컴파일러가 예외 처리를 강제하지 않으며, 예외 처리를 하지 않아도 코드가 정상적으로 컴파일된다.
이러한 예외는 주로 프로그래밍 오류로 인해 발생하며, 대표적인 예로는 다음과 같은 예외가 있다.
NullPointerException
→ null
값을 참조할 때 발생ArrayIndexOutOfBoundsException
→ 배열의 범위를 벗어난 인덱스를 참조할 때 발생ArithmeticException
→ 0으로 나누는 연산을 수행할 때 발생UncheckedException은 프로그램 실행 중, 즉 런타임에 발생하며, 적절한 예외 처리를 하지 않으면 프로그램이 비정상적으로 종료될 수 있다. 이러한 예외는 대부분 프로그래머의 실수로 인해 발생하므로, 사전에 방지할 수 있도록 코드 작성 시 주의가 필요하다.
결론부터 말하면, CheckedException과 UnCheckedException의 차이를 이해하는 것은 예외를 효과적으로 처리하는 기준이 되기 때문이다. 이 차이를 모르면 불필요한 try-catch를 남발하거나, 꼭 예외 처리가 필요한 부분을 놓칠 위험이 있다. 또한, 트랜잭션의 Rollback 여부에도 영향을 미치므로 주의해야 한다.
Scanner scanner = new Scanner(new File("test.txt")); // FileNotFoundException 발생 가능
test.txt
라는 파일이 없을 경우, CheckedException을 통해 컴파일 오류에 대한 가능성을 제시해준다.
// UnCheckedException을 try-catch로 예외 처리 => ❌
try {
String str = null;
System.out.println(str.length()); // NullPointerException 발생 가능
} catch (NullPointerException e) {
System.out.println("NullPotintException!");
}
// 예외 발생 방지 => ⭕
String str = null;
if (str != null) {
System.out.println(str.length()); // NullPointerException 방지
}
위 코드처럼 try-catch로 예외를 처리하기보다는 애초에 예외가 발생하지 않도록 코드를 작성하는 것이 중요하다. 이를 통해 가독성, 유지보수성, 성능을 전반적으로 향상시킬 수 있다.
@Transactional
public void processTransaction() throws IOException { // CheckedException
userRepository.save(new User("John")); // save()가 실행됨
if (true) {
throw new IOException("CheckedException 발생!");
}
}
@Transactional
public void processTransaction() {
userRepository.save(new User("John")); // save()가 실행되지 않음
throw new RuntimeException("UncheckedException 발생!"); // 자동 Rollback
}
CheckedException과 UnCheckedException의 차이를 이해하는 것은 효율적인 예외 처리와 안정적인 코드 작성의 핵심이다.
이 개념을 잘 활용하면 불필요한 예외 처리를 줄이고, 가독성과 유지보수성이 뛰어난 코드를 작성할 수 있다. 실제 개발에서도 예외를 언제, 어떻게 처리할지 신중히 고민하며 코드를 작성해보자.