[Java] Checked Exception vs Unchecked Exception

NHJ·2021년 12월 30일
0

1. Exception이란?

먼저 ErrorException이 무엇인지 알 필요가 있다.

Error는 시스템에 비정상적인 상황이 생겼을 때 발생한다. 이는 주로 자바 가상머신에서 발생시키기 때문에 애플리케이션에서 오류에 대한 처리를 신경 쓰지 않아도 된다. Error의 예로는 OutOfMemoryError, ThreadDeath, StackOverflowError등이 있다.

Exception는 개발자가 구현한 로직에서 발생한다. 예를 들어 입력 값에 대한 처리가 불가능하거나, 프로그램 실행 중에 참조된 값이 잘못된 경우 등 정상적인 프로그램의 흐름을 어긋나는 경우이다. 개발자가 처리할 수 있기 때문에 Exception을 구분하고 그에 따른 처리방법을 명확히 알고 적용하는 것이 중요하다.

2. Exception Class

위 그림은 Exception class의 구조이다. 모든 Exception class는 Throwable class를 상속받고 있으며, Throwable은 최상위 class인 Object의 하위 class이다.

3. Checked Exception vs Unchecked Exception

Checked Exception

  • RuntimeException의 하위 class가 아니면서 Exception class의 하위 class들이다.
  • 반드시 try/catch문으로 예외 처리를 해야하는 것이고 해주지 않으면 컴파일 단계에서 오류가 난다.
  • 예외 발생시 트랜잭션이 rollback되지 않고 commit까지 완료된다.

Unchecked Exception

  • RuntimeException의 하위 class들을 의미한다.
  • Checked Exception와는 달리 예외 처리를 강제하지 않고 컴파일 단계에서 확인되지 않는다.
  • 예외가 발생하면 트랜잭션이 rollback된다.

그렇다면 Unchecked Exception은 예외 처리를 강제하지 않는 이유는 무엇일까?

public class ArrayTest {
    public static void main(String[] args) {
        try {
            int[] list = {1, 2, 3, 4, 5};
            System.out.println(list[0]);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }
}

예외 처리를 강제할 경우 위와 같이 배열을 만들어 배열의 원소를 출력하고자 할 때 try/catch문을 매번 사용해주어야 한다. 이러한 RuntimeException은 개발자들에 의해 실수로 발생하는 것들이 대부분이기 때문에 에러를 강제하지 않는 것이다.

4. Checked Exception vs Unchecked Exception 선택

Oracle Java Documentation에서 다음과 같은 가이드를 제공한다.

Exception으로부터 복구할 수 있으면 Checked Exception으로 아무것도 수행할 수 없으면 Unchecked Exception으로 만들어라

예를 들어 파일을 열 때 파일 이름을 검증해야한다. 만약 유저의 input 파일이 유효하지 않은 이름을 가진다면 다음과 같이 Checked Exception을 던질 수 있다.

if (!isCorrectFileName(fileName)) {
    throw new IncorrectFileNameException("Incorrect filename : " + fileName );
}

이런 방식으로 다른 유저의 input 파일을 받으면서 시스템을 복구할 수 있다.

하지만 input 파일 이름이 null pointer거나 비어있는 문자열이라면 코드에 문제가 있는것이다. 이런 경우에는 다음과 같이 Unchecked Exception을 던진다.

if (fileName == null || fileName.isEmpty())  {
    throw new NullOrEmptyException("The filename is null or empty.");
}

임의의 Exception class를 만들어 예외 처리를 할 때 Checked Exception class를 만들고 싶으면 Exception class를 확장하고 Unchecked Exception class를 만들고 싶으면 RuntimeException class를 확장하면 된다.

5. 예외 처리 방법

1) 예외 복구

final int MAX_RETRY = 100;
public Object someMethod() {
    int maxRetry = MAX_RETRY;
    while(maxRetry > 0) {
        try {
            ...
        } catch(SomeException e) {
            // 로그 출력. 정해진 시간만큼 대기한다.
        } finally {
            // 리소스 반납 및 정리 작업
        }
    }
    // 최대 재시도 횟수를 넘기면 직접 예외를 발생시킨다.
    throw new RetryFailedException();
}
  • 예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 방법이다
  • 예외를 잡아서 일정 시간, 조건만큼 대기하고 다시 재시도를 반복한다.
  • 최대 재시도 횟수를 넘기게 되는 경우 예외를 발생시킨다.
  • 네트워크 환경이 좋지 않아 서버에 접속이 안되는 상황에 효율적이다.

2) 예외 처리 회피

// 예시 1
public void add() throws SQLException {
    // ...생략
}

// 예시 2 
public void add() throws SQLException {
    try {
        // ... 생략
    } catch(SQLException e) {
        // 로그를 출력하고 다시 날린다!
        throw e;
    }
}
  • 예외 처리를 직접 담당하지 않고 호출한 쪽으로 던져 회피하는 방법이다.
  • 그래도 예외 처리의 필요성이 있다면 어느 정도는 처리하고 던지는 것이 좋다.
  • 예외를 그냥 던지는 것은 무책임하므로 호출한 쪽에서 다시 예외를 받아 처리하도록 하거나, 해당 메소드에서 이 예외를 던지는 것이 최선의 방법이라는 확신이 있을 때만 사용해야 한다.

3) 예외 전환

// 조금 더 명확한 예외로 던진다.
public void add(User user) throws DuplicateUserIdException, SQLException {
    try {
        // ...생략
    } catch(SQLException e) {
        if(e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) {
            throw DuplicateUserIdException();
        }
        else throw e;
    }
}

// 예외를 단순하게 포장한다.
public void someMethod() {
    try {
        // ...생략
    }
    catch(NamingException ne) {
        throw new EJBException(ne);
        }
    catch(SQLException se) {
        throw new EJBException(se);
        }
    catch(RemoteException re) {
        throw new EJBException(re);
        }
}
  • 예외 회피와 비슷하게 메소드 밖으로 예외를 던지지만, 그냥 던지지 않고 적절한 예외로 전환해서 넘기는 방법이다.
  • 조금 더 명확한 의미로 전달되기 위해 적합한 의미를 가진 예외로 변경한다.
  • 예를 들어 Checked Exception 중 복구가 불가능한 Exception이 잡혔다면 Uncheckd Exception으로 전환하여 다른 계층에서 일일이 예외를 선언할 필요가 없도록 할 수도 있다.
  • 예외 처리를 단순하게 만들기 위해 포장(wrap) 할 수도 있다.

[참고]

profile
화이팅!

0개의 댓글

관련 채용 정보