ㅅㅇ

[Spring Boot] 예외 처리 ExceptionHandler 개념 본문

SW_STUDY/SpringBoot

[Spring Boot] 예외 처리 ExceptionHandler 개념

SO__OS 2023. 1. 31. 19:55

Exception 

  • 스프링 부트의 예외 처리방식은 크게 2가지가 존재
    • @ControllerAdvice 를 통한 모든 Controller 에서 발생할 수 있는 예외처리
    • @ExceptionHandler 를 통한 특정 Controller 의 예외처리

⇒ @ControllerException 로 모든 컨크롤러에서 발생한 예외를 정의하고,

@ExceptionHandler 를 통한 발생하는 예외 마다 처리할 메소드를 정의

 

1. 예외 클래스

  • 크게 말하면 로직 상 문제가 있어보인다와 없어보인다의 차이
  Checked Exception (그 외 Exception) UnChecked Exception(RuntimeException)
처리 여부 반드시 예외 처리 필요 명시적 처리 강제하지 않음
확인 시점 컴파일 단계 문법적으로 이미 명백하게 오류가 범해질 것 그래서 반드시 이뤄져야 하는 것 => try-catch 로 잡아서 예외 처리하거나 상위 메소드로 넘겨주기 실행 중 단계 어플리케이션이 가동 실행 중에 발생할 수 있는 에러. 예측 불가능하기에 필수 처리가 불가능
예외 발생 시 트랙잭션 롤백하지 않음 롤백
대표 예외 IQException SQLException NullPointerException Illegal ArgumentException IndexOutOfBoundException SystemException

 

2. 스프링 부트 예외처리 방법

  • @ControllerAdvice, @RestControllerAdvice
    • 스프링에서 제공하는 어노테이션
    • @controller, @RestController 에서 발생하는 예외를 한 곳에서 관리하고 처리할 수있게 하는 어노테이션
    • 설정을 통해 범위 지정이 가능하며, Default 값으로 모든 Controller 에 대해 예외 처리를 관리함
      • @RestControllerAdvice(basePackages = “io.csy”) 와 같이 패키지 범위를 설정할 수 있음
    • 예외 발생 시 json 의 형태로 결과를 반환하기 위해서는 @RestControllerAdvice 를 사용하면 됨.
  • @ExceptionHandler
    • 예외 처리 상황이 발생하며 해당 Handler 로 처리하겠다고 명시하는 어노테이션
    • 어노테이션 뒤에 괄호를 붙여 어떤 ExceptionClass 를 처리할지 설정할 수 있음
      • @ExceptionHandler(00Exception.class)
    • Exception.class는 최상위 클래스로 하위 세부 예외처리 클래스로 설정한 핸들러가 존재하면, 그 핸들러가 우선처리하게 되며, 처리 되지 못하는 예외처리에 대해 ExceptionClass 에서 핸들링함.
    • @ControllerAdvice 안에 설정된 클래스 내에서 메소드로 정의할 수 있지만, 각 Controller 안에 설정도 가능함.
    • @ExceptionHandler 는 메소드로 기반으로 어노테이션이기 때문에 메소드가 어느 클래스에 배치되냐에 따라 우선순위를 가지게 된다. 그래서 전역 설정을 하기 위해서는 @ControllerAdvice 쪽에 정의되야 하지만, 지역설정으로 Controller 에 한다면 전역설정보다 지역설정이 더 우선순위를 가진다.

** 스프링 부트 예외 처리의 우선순위 

  • 글로벌 예외처리 보다 컨트롤러 예외처리가 우선 순위가 더 높다.
  • @ExceptionHandler(Exception.class) 보다 @ExceptionHandler(NullPointerException.class) 가 우선순위가 더 높다.
    • NullPointerException 는 Exception 에 포함되는 자식 클래스이기 때문에 자식 클래스가 우선순위를 갖는다.

 

[ 정리 ]
예외처리는 우리가 처리할 수 있는 예외처리가 있고 없는 예외처리가 있다.

이때 우리가 처리할 수 있는 예외처리는 try - catch 를 사용할 수 있다. 예를 들어 데이터가 어긋나 대체 데이터를 넣을 수 있는 상황이라면 우리가 원하는 결과가 나오게 처리 로직을 짜면 되는 것이다.

 

그러나 우리가 지금까지 다룬 예외처리는 에러 메시지를 어떻게 통합적으로 관리 할 것이냐의 문제이다.
우리가 예외를 예상해 처리하는 로직을 짜는 것이 아니라, 오류가 발생했다고 클라이언트에게 보내는 작업인 것이다. 이 두 부분의 차이를 알고 있어야 한다.

 

물론 이 핸들러를 통해 오류가 발생하는 것들에 대한 처리도 가능하지만 그렇게 하기에는 각각의 상황에 따라 디테일하게 예외처리를 해줘야 하는데, 사실상 그렇게 한다면 이 통합적 처리라는 것 자체가 무의미하다.

 

그리고 우리는 자바에서 제공해주는 Exception 처리로 진행하고 있는데, 보통 어프리케이션을 만들 때 자바에서 제공하는 것으로 처리할 수 있는 부분은 처리해주고


그 외의 것 우리가 조금 더 미세 포인트를 잡아야 하는 경우, 우리가 Custom Exception 을 만들어 그것으로 관리해주면 되는 것이다.

 

3. 에러 응답 예시

  • error type, error code, message 를 응답함으로써 Client 에 정확히 어떤 에러가 발생했는지 공유
{

“errorType”:"BadRequest”

“statusCode”:400 

“message”:”잘못된 요청입니다.” 

}

 

4. HttpStatus

- HttpStatus 는 Enum 클래스임.
- Enum Class
- 서로 관련있는 상수들을 모아 심볼릭한 명칭의 집합으로 정의한 것
- 클래스 처럼 보이게 하는 상수

HttpStauts(int value, Series series String reasonPhrase) {
    this.value = value;
    this.series = series; // 이 타입의 에러는 어떤 시리즈에 포함되어 있는지를 의미, 예를 들어 400대는 CLIENT_ERROR 시리즈
    this.reasonPhrase = reasonPhrase;
}

 

EX )

EAD_REQUEST(400, SeriesCLIENT_ERROR, "Bad Request")

 

 

HttpStatus(org.springframework.http.HttpStatus) 아래 url 확인


[spring-framework/HttpStatus.java at 4.3.x · spring-projects/spring-framework](https://github.com/spring-projects/spring-framework/blob/4.3.x/spring-web/src/main/java/org/springframework/http/HttpStatus.java#L505)