면접 준비

[Java] 체크 예외 vs 언체크 예외

꾸준함. 2023. 4. 3. 23:23

https://www.java4coding.com/contents/java/checked-exceptions-vs-unchecked-exceptions

 

 

예외 계층

  • 예외도 객체이기 때문에 Object가 최상위 부모
  • Throwable이 최상위 예외이며 하위에는 Exception과 Error가 존재
  • Error는 Out of Memory 혹은 시스템 오류와 같이 애플리케이션 내 복구 불가능한 시스템 예외
    • 이러한 예외는 잡아도 별도로 처리할 수 있는 방법이 없으므로 언체크 예외
    • 가끔 귀찮다고 try catch문을 Throwable로 잡는 경우가 있는데 이럴 경우 Error 예외도 함께 잡을 수 있기 때문에 이러한 코드는 안 좋은 안티 패턴
  • Exception은 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외이며 잡아서 처리해줘야 하는 체크 예외
    • Exception의 하위 예외는 모두 컴파일러가 체크하는 체크 예외이지만 RuntimeException의 경우 언체크 예외
    • 따라서 귀찮다고 try catch문을 Exception으로 잡는 것도 RuntimeException을 예외로 함께 잡을 수 있기 때문에 안 좋은 습관

 

예외의 기본 규칙

예외에 대해서는 아래와 같이 두 가지 기본 규칙 존재

  • 예외를 try catch문으로 잡아서 처리하거나 던져야 함
  • 예외를 잡거나 던질 때 지정한 예외뿐만 아니라 그 예외의 자식들도 함께 처리가 됨
    • ex) Throwable로 잡을 경우 Exception과 Error가 함께 잡힘
    • ex) Exception으로 잡을 경우 RuntimeException과 SQLException이 함께 잡힘

 

* 스프링의 경우 예외를 잡지 않고 계속 던질 경우 결국 WAS에서 예외를 받아서 오류 페이지를 보여줌

  • 별도 처리가 없을 경우 에러 메시지가 다 보이는 기본 500 에러 페이지를 보여줌
  • 위와 같은 케이스를 방지하기 위해 보통 ControllerAdvice를 정의하여 커스텀 에러 페이지를 보여줌

 

체크 예외의 특징 및 장단점

체크 예외의 경우 잡아서 처리할 수 없을 경우 메서드에 무조건 예외를 처리하는 구문이 추가되어야 합니다.

구문이 추가가 되지 않을 경우 컴파일 에러가 발생합니다.

또한, 별도 설정이 없는 상태에서 트랜잭션을 적용할 경우 예외가 발생하더라도 롤백이 안되고 commit 처리가 됩니다.

 

장점

  • 개발자가 실수로 예외를 누락하지 않도록 방지
  • 가장 효율적인 컴파일 에러를 발생시키는 훌륭한 안전장치
  • SOLID 원칙인 OCP와 DI를 통해 클라이언트 코드의 변경 없이 대상 구현체를 변경할 수 있음

 

단점

  • 상속과 같이 계층 구조를 가지는 코드의 경우 모든 체크 예외를 반드시 잡거나 처리해야 하기 때문에 번거로움
  • 특정 계층에서는 별로 신경 쓰지 않아도 되는 예외 또한 모두 챙겨야 함
  • 인터페이스 구현체 중 하나가 체크 에러를 던질 경우 다른 구현체도 반드시 체크 에러를 던지도록 구현해야 하는 번거로움
  • 대부분의 예외는 복구가 불가능하기 때문에 던져도 처리할 수 있는 방법이 없음 ex) SQLException, ConnectException

 

public interface SampleInterface {

    void func() throws IOException;
}

 

* 위와 같이 인터페이스가 정의되어 있을 경우 SampleInterface 구현체는 무조건 IOException을 잡아서 처리하거나 던져야 함

 

// 체크 예외인 FileNotFoundException 발생할 경우 롤백하도록 속성 적용
@Transactional(rollbackFor = FileNotFoundException.class)

 

* 스프링에서 @Transactional 애노테이션을 적용할 때 체크 예외에 대해서 롤백 처리를 하기 위해서는 rollbackfor 속성을 적용해줘야 합니다.

 

언체크 예외의 특징 및 장단점

언체크 예외는 체크 예외와 반대로 컴파일러가 예외를 체크하지 않기 때문에 예외를 처리하는 구문이 추가되지 않더라도 컴파일 에러가 발생하지 않습니다.

예외를 던지는 구문이 없더라도 내부적으로 자동으로 예외를 던지기 때문에 동작 자체는 체크 예외와 동일하게 처리됩니다.

또한, 별도 설정이 없는 상태에서 트랜잭션을 적용할 경우 예외가 발생할 경우 Rollback 처리가 됩니다.

 

장점

  • 신경 쓰고 싶지 않은 언체크 예외를 무시할 수 있음
  • 신경 쓰고 싶지 않은 언체크 예외의 경우 굳이 던질 필요가 없기 때문에 체크 예외의 interface 예시와 다르게 의존 관계를 참조하지 않아도 됨
  • 코드가 깔끔해짐
  • 트랜잭션 처리 시 Rollback

 

단점

  • 컴파일러 에러가 발생하지 않기 때문에 개발자가 실수로 예외를 누락할 수 있음
    • 이 경우 명시적으로 런타임 에러를 던져줌에 따라 다른 개발자가 어떤 예외가 발생하는지 파악할 수 있도록 하는 것이 하나의 해결책
    • 또한, 문서화를 잘해놓는 것도 누락 방지에 효과적

 

결론

체크 예외와 언체크 예외의 장단점 정리를 통해 아래와 같이 정리가 가능합니다.

  • 기본적으로 언체크 예외를 사용 (RuntimeException)
  • 체크 예외는 비즈니스 로직상 의도적으로 던지는 예외에만 사용
    • 즉, 계좌 이체 실패와 같이 개발자가 반드시 처리해야 하는 문제일 경우 컴파일러 에러를 야기하는 체크 예외 사용

 

참고

스프링 DB 1편 - 데이터 접근 핵심 원리 (김영한 강사님)

 

https://kangyb.tistory.com/17

 

[Spring] @Transactional과(와) Checked, Unchecked Exception 간략정리

@Transactional과(와) Checked Exception, Unchecked Exception 간략 정리 @Transactional에 대해선 기존에 정리하였기 때문에 기존 글을 확인하시면 좋습니다. 2022.07.20 - [IT/JAVA | Spring] - [Spring] @Transactional 간략 정리

kangyb.tistory.com

 

반응형