Exception과 Error의 차이
Exception과 Error는 모두 Java에서 예외와 오류의 최상위 클래스인 Throwable 클래스를 상속하며, 프로그램 실행 중 발생하는 예외적인 상황을 나타냅니다. 하지만 Exception과 Error는 그 의미와 목적에서 큰 차이가 있습니다.
Error는 애플리케이션 코드로 처리할 수 없는 시스템적 문제를 나타내며, 대부분 JVM 레벨에서 발생합니다. Error는 발생할 경우 프로그램이 즉시 종료될 가능성이 높고, 일반적으로 try-catch 구문으로 처리하지 않습니다. Error는 메모리 부족, 스택 오버플로우와 같은 시스템 자원 문제로 인해 발생하며, 개발자가 해결할 수 없는 경우가 대부분입니다.
Error의 대표 예시
- OutOfMemoryError
메모리가 부족할 때 발생하는 오류로, 주로 객체를 너무 많이 생성하거나 메모리 리소스를 과도하게 사용했을 때 발생합니다. - StackOverflowError
재귀 호출이 무한히 반복될 때 발생하는 오류입니다. - VirtualMachineError
가상 머신의 심각한 문제가 발생했을 때 발생합니다.
Exception은 프로그램 실행 중에 발생할 수 있는 예상 가능한 예외 상황을 나타냅니다. 주로 사용자 입력 오류, 파일 입출력 오류 등 프로그램이 처리할 수 있는 문제들로, Java에서는 try-catch 구문을 통해 Exception을 처리할 수 있습니다. Exception을 처리함으로써 프로그램이 강제 종료되지 않고 정상 흐름을 유지할 수 있게 합니다.
구분 | Exception | Error |
의미 | 예상 가능한 예외 상황 | 시스템 수준의 심각한 문제 |
처리 방법 | try-catch로 처리 가능 | 일반적으로 처리하지 않음 |
대표 예시 | IOException, SQLException | OutOfMemoryError, StackOverflowError |
복구 가능성 | 복구 가능성이 있음 | 복구 불가능, 프로그램 종료 가능성 큼 |
개발을 하다 보면 다양한 예외 상황을 만나게 됩니다. Java에서는 이러한 예외를 체크 예외와 언체크 예외로 구분하며, 예외를 적절히 처리하는 방법으로 예외 복구, 예외 회피, 예외 전환이 있습니다. 이어서 예외의 종류와 효과적인 처리 방법을 정리해 보겠습니다.
Exception
Exception 클래스는 체크 예외와 언체크 예외로 구분되는데 체크 예외는 Exception 클래스의 서브클래스이면서 RuntimeException 클래스를 상속하지 않은 것들이고, 언체크 예외는 RuntimeException 클래스를 상속한 클래스들을 말합니다.
체크 예외 (Checked Exception)
일반적으로 예외라고 하면 RuntimeException 클래스를 상속 받지 않은 체크 예외를 의미하며 체크 예외가 발생할 수 있는 메소드를 사용할 경우 반드시 예외를 처리하는 코드를 함께 작성해 주어야 합니다. 만약 예외 처리를 해주지 않으면 컴파일 에러가 발생합니다.
체크 예외의 예시
- IOException: 파일 입출력 시 파일이 없거나 접근할 수 없을 때 발생
- SQLException: SQL 문법 에러, DB 접근 실패, 서버나 네트워크 문제로 발생
체크 예외의 장단점
- 장점: 컴파일 단계에서 예외를 강제하기 때문에, 놓치기 쉬운 예외를 미리 잡을 수 있는 안전장치 역할을 합니다.
- 단점: 모든 체크 예외를 잡거나 던져야 하기 때문에 번거로워질 수 있습니다.
언체크 예외 (Unchecked Exception)
언체크 예외는 런타임 예외라고도 불리며 RuntimeException 클래스를 상속한 예외가 여기에 속합니다. 명시적인 예외처리를 강제하지 않기 때문에 catch 문으로 잡거나 throws로 선언하지 않아도 되며 선언하지 않을 경우 자동으로 예외를 던집니다. 주로 프로그램의 로직 오류나 예측 불가능한 상황에서 발생합니다.
언체크 예외의 예시
- NullPointerException: 할당되지 않은 객체를 사용하려고 할 때 발생
- IllegalArgumentException: 허용되지 않는 값으로 메서드를 호출할 때 발생
언체크 예외의 장단점
- 장점: 신경 쓰고 싶지 않은 예외를 무시할 수 있어 코드 작성이 간편합니다.
- 단점: 컴파일 단계에서 오류를 잡아주지 않아 예외가 발생할 가능성을 쉽게 놓칠 수 있습니다.
예외처리 방법
체크 예외와 언체크 예외를 구분해도 실제로 예외가 발생했을 때는 이를 어떻게 처리할지 고민해야 합니다. Java에서는 크게 세 가지 방식(예외 복구, 예외처리 회피, 예외 전환)으로 예외를 처리할 수 있습니다.
예외 복구
첫 번째로 예외상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 방법이 있습니다. 예외가 발생하더라도 정상 상태로 복구할 수 있다면 이 방법을 사용합니다. 예외 상황에 따라 특정 횟수까지 재시도를 하거나, 대체 로직을 통해 정상 상태로 돌려놓을 수 있습니다.
int maxretry = MAX_RETRY
int cnt = 0
while (cnt < MAX_RETRY) {
cnt++
try {
... // 예외가 발생할 가능성이 있는 시도
return; // 작업 성공
} catch (SomeException e) {
// 로그 출력 후 정해진 시간만큼 대기
} finally {
// 리소스 반납. 정리 작업
}
}
throw new RetryFailedException(); // 최대 재시도 횟수를 넘기면 직접 예외 발생
예외처리 회피
두 번째로 예외처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 전달하는 방법이 있습니다. 예외를 회피하는 것은 예외를 복구하는 것처럼 의도가 분명해야 합니다. 다른 오브젝트에게 예외처리 책임을 지게 하거나, 자신을 사용하는 쪽에서 예외를 다루는 게 최선의 방법이라는 확신이 있을때만 사용해야 합니다.
// 예외처리 회피 1
public void add() throws SQLException {
...
}
// 예외처리 회피 2
public void add() throws SQLException {
try {
...
} catch (SQLException e) {
throw e;
}
}
예외 전환
마지막으로 발생한 예외를 그대로 던지는 대신 의미를 부여한 새로운 예외로 전환하여 던지는 방법입니다.
예외 전환 사용 목적
1. 내부에서 발생한 예외를 그대로 던지는 것이 그 예외상황에 대한 적절한 의미를 부여해주지 못하는 경우, 의미를 분명하게 해줄 수 있는 예외로 바꿔주기 위해 사용합니다.
예를 들어 앞서 말했듯이 SQLException경우 문법 문제이거나 로직 문제 또는 서버 쪽에 문제가 생겼을 때도 발생할 수 있는데 이 모든 경우에 단순히 SQLException으로 throw를 하면 개발자 입장에서는 원인을 찾기가 쉽지 않습니다. 그렇기 때문에 같은 SQLException이라도 원인을 세분화해서 다른 Exception으로 전환 후 보내준다면 보다 쉽게 에러를 해결할 수 있게 됩니다.
2. 예외를 처리하기 쉽고 단순하게 만들기 위해서 사용합니다.
주로 예외처리를 강제하는 체크 예외를 언체크 예외인 런타임 예외로 바꾸는 경우에 사용한다.
// 회원가입시 id가 중복되어 에러가 발생한 경우
public void add(User user) throws DuplicateUserIdException, SQLException {
try {
...
} catch (SQLException e) {
// ErrorCode가 MySQL의 "Duplicate Entry(1062)"이면 예외 전환
// ErrorCode는 데이터베이스 종류에 따라 다름
if (e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) {
throw DuplicateUserIdException();
} else {
throw e; // 그 외의 경우는 SQlException 그대로 전달
}
}
}
'Java' 카테고리의 다른 글
[Java] Garbage Collection이란? (0) | 2024.11.11 |
---|---|
[Java] String, StringBuilder, StringBuffer (0) | 2024.11.05 |
[Java] 스트림(Stream)이란 (0) | 2024.11.04 |
[Java] 제네릭이란? (0) | 2024.11.03 |
[Java] final 필드, 메소드, 클래스 (0) | 2024.10.30 |