Checked exception unchecked exception

새벽·2023년 2월 23일

Checked exception & Unchecked exception

에러(Error)와 예외(Exception)

에러(Error)

에러(Error)는 시스템에 비정상적인 상황이 발생했을 경우에 발생한다.
주로 자바 가상 머신(JVM)을 통해 발생되며 예외와 반대로 이를 애플리케이션 코드에서 잡으려고 하면 안 된다.
메모리 부족(OutofMemoryError)이나 스택오버플로우(StackOverflowError)와 같이 복구할 수 없는 것을 말합니다.
이러한 에러는 개발자가 예측하기도 쉽지 않고 처리할 수 있는 방법도 없다.

예외(Exception)

예외(Exception)란 입력 값에 대한 처리가 불가능하거나, 프로그램 실행 중에 참조된 값이 잘못된 경우 등 정상적인 프로그램의 흐름을 어긋나는 것을 말한다. 또한, 자바에서의 예외는 개발자가 직접 처리할 수 있기 때문에 예외 상황을 미리 예측하여 다룰 수 있다.

예외는 다음 그림과 같이 Checked Exception과 Unchecked Exception으로 구분할 수 있다.
RuntimeException을 상속하지 않은 클래스는 Checked Exception, 반대로 상속한 클래스는 Unchecked Exception으로 분류할 수 있다.

Checked Exception

  • 명시적인 예외 처리를 강제하기 때문에 Checked Exception이라 한다.

  • Compile Exception으로도 불리며 반드시 예외 처리를 해줘야 한다.

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

  • 주로 예외를 활용해서 다른 작업을 할 때 사용된다.

  • 예외 발생시 트랜잭션이 롤백 해주지 않는다.

예시)
입출력 예외가 발생했을 때(IOException)
데이터베이스 액세스 오류 또는 기타 오류에 대한 정보를 제공하는 예외(SQLException)
존재하지 않는 파일의 이름을 입력(FileNotFoundException)
실수로 클래스의 이름을 잘못 적음(ClassNotFoundException)

Unchecked Exception

  • 명시적인 예외 처리를 강제하지 않기 때문에 Uncheked Exception이라고 한다.
  • RuntimeException을 상속하는 예외 클래스
    말 그대로 실행 중에(runtime) 발생할 수 있는 예외를 의미한다.
  • checked Exception과 달리 반드시 예외 처리를 해주지 않아도 된다.
    예외를 통한 기댓값이 없다.

예시)
배열의 범위를 벗어난(ArrayIndexOutOfBoundsException)
값이 null이 참조변수를 참조(NullPointerException)



체크 예외와 언체크 예외의 차이점 중에 같이 보아야 할 점은 Rollback의 여부이다.

  • 체크 예외 : Rollback이 되지 않고 트랜잭션이 commit까지 완료됩니다.
  • 언체크 예외 : Rollback이 됩니다.

Checked Exception이 Rollback되지 않는 이유

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

예외 처리

예외복구, 예외 처리 회피, 예외 전환이 있다.

예외 복구

  • 예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 방법
  • 예외를 잡아서 일정 시간, 조건만큼 대기하고 다시 재시도를 반복한다.
  • 최대 재시도 횟수를 넘기게 되는 경우 예외를 발생시킨다.
public void exceptionTest() {
    try {
        // 예외가 발생할 가능성이 있는 시도
        ...
    } catch (SomeException e) {
        // 다른 흐름으로 유도하여 정상적으로 작업이 진행되도록
        ... 
    }
}

예외 처리 회피

  • 예외 처리를 직접 담당하지 않고 호출한 쪽으로 던져 회피하는 방법
  • 그래도 예외 처리의 필요성이 있다면 어느 정도는 처리하고 던지는 것이 좋다.
  • 긴밀하게 역할을 분담하고 있는 관계가 아니라면 예외를 그냥 던지는 것은 무책임하다.
// 일반적으로 예외를 던지는 경우
public void add() throws SQLException {
    // ...생략
}

// 어느정도 처리하고 예외를 던지는 경우
public void add() throws SQLException {
    try {
        // ... 생략
    } catch(SQLException e) {
        // 로그를 출력하고 다시 날린다!
        throw e;
    }
}

예외 전환

  • 예외 회피와 비슷하게 메서드 밖으로 예외를 던지지만, 그냥 던지지 않고 적절한 예외로 전환해서 넘기는 방법
  • 조금 더 명확한 의미로 전달되기 위해 적합한 의미를 가진 예외로 변경한다.
  • 예외 처리를 단순하게 만들기 위해 포장(wrap) 할 수도 있다.
// 조금 더 명확한 예외로 던진다.
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 vs UnChecked Exception 선택하기

예외 복구 전략이 명확하고 복구가 가능하다면 Checked Excetpion을 try-catch로 잡아서 예외를 복구하는 것이 좋다.
복구가 불가능한 Checked Exception이 발생하면 더 구체적인 Unchecked Exception을 발생시키고 예외에 대한 메시지를 명확하게 전달하는 것이 좋다. 무책임하게 상위 메서드에 throw로 예외를 던지는 것은 상위 메서드의 책임이 증가하기 때문에 좋지 않은 방법이다.

또한 이런 무분별한 throws의 활용은 코드의 가독성을 떨어트림과 더불어 어떤 메서드의 어떤 부분에서 예외가 발생했는지 알기 어렵게 만드는 주원인이 된다.


참고 자료 : https://devlog-wjdrbs96.tistory.com/351
https://cocobi.tistory.com/146
https://hahahoho5915.tistory.com/67
https://madplay.github.io/post/java-checked-unchecked-exceptions
https://steady-coding.tistory.com/583

profile
⋆。˚☁。⋆。˚☾˚。⋆

0개의 댓글