@ControllerAdvice

코딩냥이·2024년 9월 10일

Annotation

목록 보기
26/34

@ControllerAdvice

@ControllerAdvice는 스프링 MVC에서 전역적으로 예외를 처리하고, 전체 애플리케이션에서 일관된 응답을 제공하기 위해 사용되는 어노테이션입니다.

기능

  • 전역 예외 처리: 애플리케이션 전체에서 발생하는 예외를 일괄적으로 처리합니다.
  • 바인딩 설정: 전역적으로 데이터 바인딩 및 검증 규칙을 적용할 수 있습니다.
  • 모델 속성 추가: 모든 컨트롤러에서 공통으로 사용할 모델 속성을 정의할 수 있습니다.

사용 방법

기본적인 사용 방법은 다음과 같습니다:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.ResponseEntity;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handleUserNotFound(UserNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleAllExceptions(Exception ex) {
        return new ResponseEntity<>("An unexpected error occurred", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

주요 특징

  1. 전역 예외 처리: 모든 컨트롤러에 적용되는 예외 처리 로직을 구현할 수 있습니다.
  2. 중앙 집중화: 예외 처리 로직을 한 곳에 모아 관리할 수 있습니다.
  3. 특정 패키지/클래스 대상: 특정 패키지나 클래스에만 적용되도록 설정할 수 있습니다.
  4. AOP 기반: AOP(Aspect-Oriented Programming) 개념을 활용하여 구현됩니다.

고급 사용법

1. 특정 패키지에만 적용

@ControllerAdvice("com.example.controllers")
public class SpecificPackageExceptionHandler {
    // 예외 처리 메서드들...
}

2. 특정 어노테이션이 붙은 컨트롤러에만 적용

@ControllerAdvice(annotations = RestController.class)
public class RestControllerExceptionHandler {
    // 예외 처리 메서드들...
}

3. 모델 속성 추가

@ControllerAdvice
public class GlobalModelAttributes {

    @ModelAttribute("globalAttribute")
    public String addGlobalAttribute() {
        return "This is a global attribute";
    }
}

4. 바인딩/검증 설정

@ControllerAdvice
public class GlobalBindingInitializer {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(new MyCustomValidator());
    }
}

@RestControllerAdvice

@RestControllerAdvice@ControllerAdvice@ResponseBody를 결합한 어노테이션입니다. REST API에서 사용하기 적합합니다:

@RestControllerAdvice
public class GlobalRestExceptionHandler {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {
        ErrorResponse error = new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }
}

예외 처리 우선순위

  1. 컨트롤러 내부의 @ExceptionHandler
  2. @ControllerAdvice 클래스 내부의 @ExceptionHandler
  3. 기본 예외 처리기

테스트

@ControllerAdvice가 적용된 예외 처리를 테스트할 때:

@SpringBootTest
@AutoConfigureMockMvc
class GlobalExceptionHandlerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void testHandleUserNotFound() throws Exception {
        mockMvc.perform(get("/users/999"))
               .andExpect(status().isNotFound())
               .andExpect(content().string("User not found with id: 999"));
    }
}

주의사항

  1. 과도한 사용: 너무 많은 로직을 @ControllerAdvice에 넣으면 코드가 복잡해질 수 있습니다.
  2. 예외의 구체성: 더 구체적인 예외를 먼저 처리하도록 순서를 고려해야 합니다.
  3. 성능 고려: 전역 설정이 애플리케이션 전체 성능에 영향을 줄 수 있음을 인지해야 합니다.

베스트 프랙티스

  1. 명확한 책임 분리: 각 @ControllerAdvice 클래스의 책임을 명확히 분리하세요.
  2. 일관된 응답 형식: 예외 응답의 형식을 일관되게 유지하여 클라이언트 측의 처리를 용이하게 하세요.
  3. 로깅: 예외 처리 시 적절한 로깅을 포함하세요.
  4. 보안 고려: 민감한 정보가 예외 메시지를 통해 노출되지 않도록 주의하세요.
  5. 문서화: 전역적으로 처리되는 예외와 그에 대한 응답을 API 문서에 명확히 기술하세요.

결론

@ControllerAdvice는 스프링 MVC 애플리케이션에서 전역적인 예외 처리와 공통 설정을 구현하는 데 매우 유용한 도구입니다. 이를 통해 애플리케이션 전체에 일관된 예외 처리 로직을 적용할 수 있으며, 코드의 중복을 줄이고 유지보수성을 향상시킬 수 있습니다. 다만, 과도한 사용은 오히려 복잡성을 증가시킬 수 있으므로, 적절한 균형을 유지하는 것이 중요합니다. 전역 예외 처리, 공통 모델 속성 추가, 바인딩/검증 규칙 설정 등 다양한 용도로 활용할 수 있어, 스프링 MVC 애플리케이션의 구조를 개선하는 데 큰 도움이 됩니다.

연관 포스팅

@ExceptionHandler
@RestController
@ResponseBody
@InitBinder
@ModelAttribute

profile
HelloMeow~!

0개의 댓글