[Java] Checked Exception, Unchecked Exception

홍정완·2022년 9월 18일
0

Java

목록 보기
25/25
post-thumbnail

에러(Error)와 예외(Exception)


프로그래밍에서 예외란 입력 값에 대한 처리가 불가능하거나, 프로그램 실행 중에 참조된 값이 잘못된 경우 등 정상적인 프로그램의 흐름을 어긋나는 경우를 말한다.

자바에서 예외는 개발자가 예외 처리(Exception Handling)를 통해 직접 처리할 수 있기 때문에 예외 상황을 미리 예측하여 핸들링할 수 있다.


에러는 시스템에 무엇인가 비정상적인 상황이 발생한 경우를 말한다. 주로 자바 가상 머신에서 발생하는 것이며, 예외와 반대로 이를 애플리케이션 코드에서 잡을 수 없다. 개발자가 로직 구현 단계에서 미리 예측할 수 없기 때문에 따로 처리할 방안도 존재하지 않는다.

에러의 예시로는 OutOfMemoryError, ThreadDeath, StackOverflowError 등이 있다.



예외 구분


예외는 아래 그림과 같이 Checked ExceptionUnchecked Exception으로 구분할 수 있다.


RuntimeException

  • 상속하지 않은 클래스는 Checked Exception
  • 상속한 클래스는 Unchecked Exception


CheckedExceptionCompileException이라고도 하며 Exception을 바로 상속받는다.

컴파일 시점에 예외를 catch 하는지 정적으로 확인하며, 컴파일 시점에서 예외에 대한 처리를 하지 않으면 컴파일 에러가 발생한다. 예외가 발생하는 메서드에서 throws 예약어를 사용하여 예외를 호출한 메서드에 전달하는 방법으로도 처리가 가능하며, Transaction Rollback이 안 된다는 특징이 있다.

FileNotFoundException, ClassNotFoundException, DataFormatException



UncheckedExceptionRuntimeException을 상속받는다.

CheckedException과 반대로 컴파일 시점에서 예외를 catch 하는지를 확인하지 않는다. 컴파일 시점에서 예외가 발생했는지를 판단할 수 없고, Transaction Rollback이 된다는 특징이 있다.

IndexOutOfBoundsException, NullPointerException, ClassCastException



RuntimeException은 주로 코드 로직에 의해 발생할 수 있는 예외다. 예외가 발생할 가능성이 있는 코드들은 try-catch 문을 사용하여 처리하기 보다 제대로 코드를 작성하도록 하자.



정리

구분Checked ExceptionUnchecked Exception
확인 시점컴파일(Compile) 시점런타임(Runtime) 시점
처리 여부반드시 예외 처리해야 한다.명시적으로 하지 않아도 된다.
트랜잭션 처리예외 발생 시 롤백(rollback) 하지 않음예외 발생 시 롤백(rollback) 해야 함
종류IOException,
ClassNotFoundException 등
NullPointerException,
ClassCastException 등



Checked Exception이 Rollback 되지 않는 이유

기본적으로 Checked Exception은 복구가 가능하다는 메커니즘을 가지고 있다. 예를 들어, 특정 이미지 파일을 찾아서 전송해 주는 함수에서 이미지를 찾지 못했을 경우 기본 이미지를 전송한다는 복구 전략을 가질 수 있다. 정리하자면, 복구가 가능하니 Rollback은 진행하지 않는다는 의미이다.



예외 처리


예외를 처리하는 방법에는 예외 복구, 예외 처리 회피, 예외 전환이 있다.



예외 복구

예외 상황을 파악하고 문제를 해결하여 정상 상태로 돌려놓는 방법이다.

public sendFile() {
     try {
        // 예외 발생 가능성이 있는 시도
     } catch (FileNotFoundException e) { 
        // 정상적으로 작업이 진행되도록 다른 흐름으로 유도
     }
}

예외 복구는 예외가 발생했을 때 다른 작업 흐름으로 유도한다. (try - catch - finally)
예외 복구의 핵심은 예외가 발행하여도 애플리케이션은 정상적인 흐름으로 진행된다.
그러나 대부분의 상황에서 예외를 복구할 수 있는 경우는 거의 없기 때문에 자주 사용되지 않는다. 예를 들어, 유니크해야 하는 전화번호 값이 중복되어 SQLException이 발생한다고 해도 복구할 수 있는 방법이 없다. 이런 경우에는 RuntimeException을 발생시키고 입력을 다시 유도하는 것이 현실적이다.



예외 처리 회피

예외 처리를 직접 담당하지 않고 호출한 쪽으로 던져 회피하는 방법이다. 예외 처리 회피에서는 무책임하게 상위 메서드로 throw를 던지는 행위는 상위 메서드의 책임이 그만큼 증가하기 때문에 적절한 경우에만 사용하는 것이 좋다.

// 일방적으로 예외를 던지는 경우
public Object someMethod() throws IOException {
        ...
}



예외 전환

예외 처리 회피와 비슷하게 메서드 밖으로 예외를 던지지만, 그냥 던지지 않고 적절한 예외로 전환해서 넘기는 방법이다. 명확한 의미로 전달되기 위해 적합한 의미를 가진 예외로 변경해야 한다. 호출한 쪽에서 예외를 받아서 처리할 때 좀 더 명확하게 인지할 수 있도록 돕기 위한 방법이다.

public Object method() {
        try {
                ...
        } catch (IOException e) {
                throw new CustomException ("IOException 발생");
        }
}

public class CustomException extends RuntimeException{
    public CustomException(String message) {
        super(message);
    }
}

보통 예외 처리를 하기 위해서 위와 같이 RuntimeException을 상속받은 클래스로 전환하여 던진다.



결론

  • 예외 복구 전략이 명확하고 복구가 가능하면 Checked Exception을 try-catch로 잡아서 예외 복구를 하거나, 코드의 흐름으로 제어하자

  • 그러나 Checked Exception이 발생하면 더 구체적인 UnChecked Exception을 발생시켜 예외에 대한 메시지를 명확하게 전달하는 것이 효과적이다.

  • 무책임하게 상위 메서드에 throw로 예외를 던지는 행위를 하지 말자. 상위 메서드들의 책임이 그만큼 증가한다.

  • Checked Exception은 기본 트랜잭션 속성에서 Rollback을 진행하지 않는다.

profile
습관이 전부다.

0개의 댓글