Spring 기초/Spring 기초 지식

Spring Boot: @ControllerAdvice/@RestControllerAdvice로 예외처리하기

Stark97 2023. 10. 23. 20:07
반응형
 
 

@ControllerAdvice와 @RestControllerAdvice에 대해 자세히 알아보자

📌 서론

프로그래밍에서 예외 처리는 매우 중요한 부분이며, Spring Boot에서는 @ControllerAdvice와 @RestControllerAdvice를 통해 이를 효율적으로 수행할 수 있다. 이 어노테이션들은 코드의 재사용성과 유지 보수성을 높여, 복잡한 비즈니스 로직에서도 예외 상황을 안정적으로 관리할 수 있게 해준다.

 

1. @ControllerAdvice이해

@ControllerAdvice란?

  • @ControllerAdvice는 Spring 3.2에서 도입된 어노테이션으로, 모든 @Controller 클래스가 공유하는 공통 로직을 정의할 때 사용한다. 주로 예외 처리와 바인딩 설정, 모델 객체 등에 사용된다.

 

예제 코드

  • 아래의 예제에서는 NotFoundException이 발생할 경우 "error"라는 이름의 뷰로 이동하고 메시지를 출력한다.
@ControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(NotFoundException.class)
    public ModelAndView handleNotFoundException(NotFoundException ex) {
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("message", ex.getMessage());
        return mav;
    }
}

 

2. @RestControllerAdvice  이해

@RestControllerAdvice란?

  • @RestControllerAdvice는 @ControllerAdvice와 거의 동일하지만, 한 가지 큰 차이점은 이 어노테이션을 사용하면 @ResponseBody가 암시적으로 추가된다는 것이다. 따라서 JSON 형태로 바로 응답을 보낼 수 있다.

 

예제 코드

@RestControllerAdvice
public class GlobalRestControllerAdvice {

    @ExceptionHandler(NotFoundException.class)
    public ResponseEntity<?> handleNotFoundException(NotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
    }
}

주요 용어 설명

  • ModelAndView: Spring MVC에서 모델과 뷰를 함께 전달할 수 있는 객체이다.
  • ResponseEntity: HTTP 상태 코드와, 본문, 헤더 등을 포함한 응답을 표현한다.
  • HttpStatus: HTTP 상태 코드(enum)을 나타낸다.

3. 작동 원리와 두 어노테이션의 비교

작동 원리

  • Spring의 @ControllerAdvice와 @RestControllerAdvice는 AOP(Aspect-Oriented Programming)의 원리를 기반으로 동작한다. 즉, 이러한 어노테이션은 공통 관심사(cross-cutting concerns)인 예외 처리 로직을 분리하여 관리한다. 이를 통해 코드의 중복을 줄이고 유지보수성을 향상시킨다. 또한, 스프링 부트는 내부적으로 클래스패스를 스캔하여 이러한 어노테이션을 가진 클래스를 자동으로 등록하고 적용한다.

 

두 어노테이션은 매우 유사한 기능을 수행하지만 몇 가지 차이점이 있다.

 

응답 형식

  • @ControllerAdvice:  ModelAndView 객체를 반환하여 HTML 뷰를 렌더링할 수 있다.
  • @RestControllerAdvice:   ResponseEntityPOJO 객체를 반환하여 JSON 형태로 응답할 수 있다.

 

사용처

  • @ControllerAdvice:  주로 전통적인 Spring MVC와 함께 사용된다.
  • @RestControllerAdviceRESTful 웹 서비스에서 주로 사용된다.

 

암시적 어노테이션

  • @ControllerAdvice:  @ResponseBody를 명시적으로 추가해야 JSON을 반환할 수 있다.
  • @RestControllerAdvice암시적으로 @ResponseBody가 추가되어 있어 별도로 추가할 필요가 없다.

 

어떤 것을 선택할까?

  • 전통적인 웹 애플리케이션을 구축한다면 @ControllerAdvice가, RESTful API를 만든다면 @RestControllerAdvice가 더 적합하다. 또한 응답 형식, 사용처, 암시적 어노테이션 등을 고려하여 선택해야 한다.

 

4. 일반적으로는 이렇게 사용한다.

@ControllerAdvice 예제

@ControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(Exception ex) {
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("message", ex.getMessage());
        return mav;
    }
}

@RestControllerAdvice 예제

@RestControllerAdvice
public class GlobalRestControllerAdvice {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> handleException(Exception ex) {
        Map<String, Object> errorDetails = new HashMap<>();
        errorDetails.put("message", ex.getMessage());
        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

 

5. 전략과 최적의 사례

특정 패키지나 클래스에 적용하기

  • @ControllerAdvice나 @RestControllerAdvice를 사용할 때 basePackages 속성을 사용하여 특정 패키지나 클래스에만 적용할 수 있다.
@ControllerAdvice(basePackages = "com.example.controller")
public class GlobalControllerExceptionHandler {
    // ...
}

우선순위 설정

  • @Order 어노테이션을 사용하여 여러 개의 @ControllerAdvice나 @RestControllerAdvice 클래스 중 어떤 것이 먼저 실행될지 설정할 수 있다.
@Order(1)
@ControllerAdvice
public class GlobalControllerExceptionHandler {
    // ...
}

예외 분류 및 커스터마이징

  • 여러 종류의 예외를 처리하기 위해 @ExceptionHandler에 예외 타입을 배열로 지정할 수 있다.
@ControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler({NotFoundException.class, AnotherException.class})
    public ModelAndView handleMultipleExceptions(Exception ex) {
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("message", ex.getMessage());
        return mav;
    }
    
}

비즈니스 로직과의 결합도 낮추기

  • 비즈니스 로직 내부에서 발생하는 예외는 서비스 레이어에서 캡슐화하고, 이를 Controller에서는 @ControllerAdvice나 @RestControllerAdvice를 사용하여 공통적으로 처리하는 것이 유지보수성을 높인다.

 

다른 어노테이션과의 협업

  • @ControllerAdvice나 @RestControllerAdvice는 @ExceptionHandler 외에도 @ModelAttribute, @InitBinder와 같이 사용할 수 있다.
@ControllerAdvice
public class GlobalControllerExceptionHandler {
    
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // InitBinder 로직
    }
    
    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("attribute", "value");
    }
}

에러 로깅과 모니터링 전략

  • 예외가 발생했을 때 이를 로깅하고 모니터링하는 전략도 중요하다. 예외 정보를 로그로 남기고 이를 모니터링 할 수 있는 툴을 사용하는 것이 유용하다.

 

 

controllerAdvice와 aop를 함께 사용하여 에러 로깅을 하는 방법이 궁금한다면?👇🏻👇🏻

 

Spring: @ControllerAdvice와 AOP를 함께 사용하여 에러 로깅하기

@ControllerAdvice와 AOP 를 동시에 적용하여 로깅을 해보자 📌 서론 Spring Boot에서는 일반적으로 @ControllerAdvice와 @ExceptionHandler를 사용하여 전역 에러 핸들링을 수행한다. 그러나 이러한 방식은 상세한

curiousjinan.tistory.com

반응형