Java

Checked Exception과 Unchecked Exception

Nick_Choi 2024. 7. 22. 08:57

주제인 Checked Exception과 Unchecked Exception에 대해 알아보기 전에 Error과 Exception에 대해 간단히 확인해보려고 한다.

 

Error

- 프로그램 실행 중 발생하는 예기치 않은 문제로, 주로 시스템 수준에서 발생한다.

- 발생 시점에 따라 3가지로 분류된다.

  • 컴파일 에러  

- 컴파일 단계에서 오류가 발견되면 컴파일러가 에러 메시지를 출력한다.

- 컴파일 에러의 대표적인 원인으로 syntax error가 있다.

- 심각한 수준의 에러는 아님

  • 런타임 에러

- 컴파일 과정에는 문제가 없었으나 프로그램 실행중 에러가 발생하여 잘못된 결과를 얻었거나 외부적 요인으로 인한 기계 결함으로 프로그램이 비정상적으로 종료된다.

- 개발 과정에서 논리적이지 못한 설계로 인한 발생이 주요 원인

- 런타임 에러 발생 시 개발자가 역추적하여 원인 파악

  • 논리적 에러

- 프로그램 실행과 작동에는 문제를 발생시키지 않지만 사용자의 의도대로 결과가 도출되지 않은 문제를 발생시킨다.

 

Exception

- 프로그램 실행 중 발생할 수 있는 예측 가능한 문제로, 주로 코드 수준에서 발생한다.

- Checked Exception과 Unchecked Exception으로 구분

=> Runtime Exception을 상속하지 않은 클래스는 Checked Exception, 상속한 클래스는 Unchecked Exception

https://madplay.github.io/post/java-checked-unchecked-exceptions

 

UnChecked Exception

- 컴파일 때 체크되지 않고 Runtime에 발생하는 예외를 의미

- 명시적인 예외 처리*를 강제하지 않기 때문에 UnChecked Exception이라 부름.

 

명시적인 예외 처리란?

try-catch로 예외를 잡거나 throw로 호출한 메소드에게 예외를 던지지 않아도 됨을 의미

 

Checked Exception

- 예외처리가 필수이며 처리하지 않으면 컴파일이 되지 않음

- JVM 외부와 통신할 때 주로 사용

- 명시적인 예외 처리를 강제하기 때문에 Checked Exception이라 부름.

- 반드시 try-catch로 예외를 잡거나 throw로 호출한 메소드에게 예외를 던져야 한다.

 
  Checked Exception Unchecked Exception
확인 시점 컴파일 시점 런타임 시점
처리 여부 반드시 예외처리 명시적으로 강제 x
트랜잭션 처리 예외 발생시 롤백 x 예외 발생시 롤백해야 함
종류 IOException,
ClassNotFoundException 등
NullPointerException,
ClassCastException 등

 

 

예외 처리 방식

예외처리를 하는 방식에는 3가지 정도가 있다.

  • 예외 복구

- 예외 상황을 파악한 후 문제를 해결하여 정상의 상태로 돌려놓음

- Exception이 발생해도 어플리케이션은 정상적으로 동작함

- 반복문을 활용하여 예외가 발생하면 일정 횟수만큼 재시도하여 예외 복구 시도 

final int MAX_RETRY = 100;

public Object someMethod() {
    int maxRetry = MAX_RETRY;
    
    while(maxRetry > 0) {
        try {
            // ...
            return; // 성공시 바로 리턴
        } catch(Exception e) {
            // 예외 발생시 로그를 출력
        } finally {
            // 리소스 반납 및 정리 작업
        }
        
        --maxRetry; // 실패하면 1000번 반복
    }
    
    // 최대 재시도 횟수를 넘기면 직접 예외를 발생
    throw new RetryFailedException();
}

 

  • 예외 처리 회피

- 예외 처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버리는 방법 ( throws )

- 호출한 쪽에서 예외를 처리하는 것이 바람직하다고 판단될 때 사용

- 무분별하게 사용되면 코드의 퀄리티가 떨어질 수 있어 추천되는 방식 x

public void add() throws SQLException {
    try {
        // ... 생략
    } catch(SQLException e) {
    	e.printStackTrace(); // 로그만 출력하고
        throw e; // 다시 날린다
    }
}

 

  • 예외 전환

- 적절한 예외로 필터링하여 자신을 호출할 쪽으로 던져버리는 방법

-  좀 더 명확한 의미를 전달하기 위해 적합한 의미를 가진 예외로 변경하여 전달

 

// 조금 더 명확한 예외로 던진다.
public void add(User user) throws DuplicateUserIdException, SQLException {
    try {
        // ...
    } catch(SQLException e) { // SQLException 예외가 발생하면
        if(e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) { // 그리고 정확히 어떠한 에러인걸 알았다면
            throw DuplicateUserIdException(); // 상위 클래스가 아닌 정확한 예외클래스를 던진다
        }
        else {
        	throw e;
        }
    }
}