Spring | 예외 처리하기 | @ExceptionHandler , @ControllerAdvise, @RestControllerAdvise

바다·2024년 6월 5일
0

Spring

목록 보기
9/13
post-thumbnail

API 예외처리하기

코드를 작성하다보면, Exception을 throw 해야 하는 경우가 발생한다! 이 때, 예외를 제대로 처리하지 않으면 WAS까지 예외가 전달이 되고, 아래와 같은 에러가 반환된다

{
    "timestamp": "2024-06-05T10:36:30.084+00:00",
    "status": 400,
    "error": "Bad Request",
    "exception": "java.lang.IllegalArgumentException",
    "path": "/api/members/bad"
}

이런 에러를 반환하지 않고, API 단에서 바로 처리해서 정상 응답 이 될 수 있도록 하는 방법이 있다


@ExceptionHandler

스프링이 API 예외 처리 문제를 해결하기 위해 제공하는 기능으로, @ExceptionHandler 어노테이션을 통해 사용할 수 있다.

1. 예외 처리 방법

@ExceptionHandler 어노테이션을 선언하고, 해당 컨트롤러에서 처리하고 싶은 예외를 지정해주면 된다!

해당 컨트롤러 내에서 예외가 발생하면 이 메소드가 호출된다

예시 코드

@ExceptionHandler(IllegalArgumentException.class)
public ErrorResult illegalExceptionHandler(IllegalArgumentException e) {
	return new ErrorResult("BAD", e.getMessage());
}

예외 발생 시, 응답되는 값

{
    "code": "BAD",
    "message": "잘못된 입력 값"
}

2. 다양한 작성 방식

1) 여러 개의 예외 처리

@ExceptionHandler({AException.class, BException.class})
public ErrorResult illegalExceptionHandler(Exception e) {
	return new ErrorResult("BAD", e.getMessage());
}

다양한 예외를 한 번에 처리할 수 있다

2) 예외 생략

@ExceptionHandler
public ErrorResult illegalExceptionHandler(IllegalArgumentException e) {
	return new ErrorResult("BAD", e.getMessage());
}

메소드의 파라미터로 예외를 지정할 수 있기 때문에, @ExceptionHandler 어노테이션에서 예외를 생략할 수 있다

3) 다양한 응답 형식 지정 가능

@ExceptionHandler
	public ResponseEntity<ErrorResult> userHandler(UserException e) {
		ErrorResult errorResult = new ErrorResult("USER-EX", e.getMessage());
		return new ResponseEntity(errorResult, HttpStatus.BAD_REQUEST);
	}

컨트롤러의 파라미터 응답처럼 다양한 파라미터와 응답을 지정할 수 있다!
자세한 내용은 아래의 공식 문서에서 확인할 수 있다
ExceptionHandler 공식 문서 🔍

3. 예외처리 우선순위

스프링의 우선순위는 항상 자세한 것 이 우선순위를 가진다.

@ExceptionHandler(부모예외.class)
public String 부모예외처리()(부모예외 e) {}

@ExceptionHandler(자식예외.class)
public String 자식예외처리()(자식예외 e) {}

예를 들어, 위와 같이 부모 클래스자식 클래스의 예외 처리를 지정해두었고
자식 클래스 예외가 발생한다면 부모 예외처리자식 예외처리 둘 다 호출 대상이 되지만, 둘 중 더 자세한 것이 우선권을 가지기 때문에 자식 예외처리 가 호출된다!

물론, 예외처리가 작성되지 않은 자식 클래스는 부모 예외처리가 호출된다


@ControllerAdvise & @RestControllerAdvise

@ExceptionHandler를 사용하면, 예외를 깔끔하게 처리할 수는 있지만 컨트롤러 클래스 내에 정상 코드와 예외 코드가 섞여 있다. @ControllerAdvise@RestControllerAdvise를 사용한다면 정상 코드와 예외 코드를 분리할 수 있다

1. @ControllerAdvise와 @RestControllerAdvise의 차이

ControllerRestController의 차이와 같다.
@RestControllerAdvise에는 내부에 ResponseBody 어노테이션이 붙어 있다

2. 기능

  • 대상으로 지정한 여러 컨트롤러에 ExceptionHandler, InitBinder 기능을 부여해준다
  • 대상을 지정하지 않으면 모든 컨트롤러에 적용된다 (글로벌 적용)

1) 대상 컨트롤러 지정 방법

//컨트롤러 어노테이션이 붙은 클래스를 대상으로 함
@ControllerAdvise(annotations = Controller.class)
public class ExampleAdvise {}

//해당 패키지에 있는 클래스를 대상으로 함
@ControllerAdvise("com.heesue.controllers")
public class ExampldAdvise {}

//직접 컨트롤러를 지정함
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice {}

아래의 공식 문서를 통해 더 자세히 알아볼 수 있다
ControllerAdvise 공식 문서 🔍


정리

@ExceptionHandler@ControllerAdvise를 조합하여, 예외를 깔끔하게 해결할 수 있다!

profile
ᴘʜɪʟɪᴘᴘɪᴀɴs 3:14

0개의 댓글