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

2023. 10. 23. 20:07·Spring/Spring 기초 지식
반응형
 
 

@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:   ResponseEntity나 POJO 객체를 반환하여 JSON 형태로 응답할 수 있다.

 

사용처

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

 

암시적 어노테이션

  • @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

반응형

'Spring > Spring 기초 지식' 카테고리의 다른 글

[Spring] 스프링과 자바의 동시성과 병렬 처리  (1) 2023.10.31
Spring: @ControllerAdvice와 AOP를 함께 사용하여 에러 로깅하기  (0) 2023.10.24
Spring: Maven과 Gradle의 차이  (0) 2023.08.17
SpringBoot: 인터셉터(interceptor)의 동작원리  (0) 2023.08.13
Spring MVC의 Model, ModelAndView, ModelMap 비교  (0) 2023.08.13
'Spring/Spring 기초 지식' 카테고리의 다른 글
  • [Spring] 스프링과 자바의 동시성과 병렬 처리
  • Spring: @ControllerAdvice와 AOP를 함께 사용하여 에러 로깅하기
  • Spring: Maven과 Gradle의 차이
  • SpringBoot: 인터셉터(interceptor)의 동작원리
Stark97
Stark97
문의사항 또는 커피챗 요청은 링크드인 메신저를 보내주세요! : https://www.linkedin.com/in/writedev/
  • Stark97
    오늘도 개발중입니다
    Stark97
  • 전체
    오늘
    어제
    • 분류 전체보기 (241) N
      • 개발지식 (20)
        • 스레드(Thread) (8)
        • WEB, DB, GIT (3)
        • 디자인패턴 (8)
      • JAVA (21)
      • Spring (88)
        • Spring 기초 지식 (35)
        • Spring 설정 (6)
        • JPA (7)
        • Spring Security (17)
        • Spring에서 Java 활용하기 (8)
        • 테스트 코드 (15)
      • 아키텍처 (6) N
      • MSA (14)
      • DDD (7)
      • gRPC (9)
      • Apache Kafka (18)
      • DevOps (23)
        • nGrinder (4)
        • Docker (1)
        • k8s (1)
        • 테라폼(Terraform) (12)
      • AWS (32)
        • ECS, ECR (14)
        • EC2 (2)
        • CodePipeline, CICD (8)
        • SNS, SQS (5)
        • RDS (2)
      • notion&obsidian (3)
  • 링크

    • notion기록
    • 깃허브
    • 링크드인
  • hELLO· Designed By정상우.v4.10.0
Stark97
Spring Boot: @ControllerAdvice/@RestControllerAdvice로 예외처리하기
상단으로

티스토리툴바