@ControllerAdvice 적용

노성웅·2025년 5월 13일
post-thumbnail

@ControllerAdvice

@ControllerAdvice는 전역적으로 컨트롤러에서 발생하는 예외를 처리하거나 공통 로직을 적용하기 위해 사용되는 어노테이션이다. (AOP를 기반으로 한다)

1. 속성

기본적으로 속성을 지정하지 않으면 애플리케이션 모든 컨트롤러에 적용된다.

1) basePackages
- 특정 패키지 및 그 하위 패키지인 컨트롤러에만 @ControllerAdvice를 적용.
- 여러 패키지 지정 가능
2) basePackageClasses
- 패키지 이름을 문자열로 지정하는 대신, 특정 클래스의 패키지를 참조.
3) assignableTypes
- 특정 클래스 또는 그 하위 클래스에만 적용
4) annotations
- 특정 어노테이션이 붙은 컨트롤러에만 적용.
- Spring 5.3 이상에서 HTTP 메서드별 어노테이션(예: @PostMapping, @DeleteMapping도 사용 가능)
5) value
- basePackages와 동일한 역할을 하며, 패키지 이름을 지정
- 예: @ControllerAdvice("okestro.third.domain.openstack.ctr")

2) 사용 예시

PPP에 ControllerAdvice를 적용해보았다.

  • 주의 사항으로는 ControllerAdvice를 Controller 별로 나눌 경우 Order에 Global 부분이 가장 늦도록 설정 해주어야 한다.

Global Exception

@Slf4j  
@Order(Ordered.LOWEST_PRECEDENCE)  
@RestControllerAdvice  
@RequiredArgsConstructor  
public class GlobalExceptionHandler {

		/**  
		 * 나머지 예외 발생  
		 */  
		@ExceptionHandler(Exception.class)  
		protected ResponseEntity<ErrorResponse> handleException(Exception e) {  
		    log.error("Exception", e);  
		    ErrorResponse errorResponse = ErrorResponse.of(HttpStatus.INTERNAL_SERVER_ERROR.toString(),  
		            e.getMessage());  
		    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);  
		}
}

Controller Exception

@Slf4j  
@Order(Ordered.HIGHEST_PRECEDENCE)  
@RestControllerAdvice(basePackageClasses = LoadbalancerController.class)  
@RequiredArgsConstructor
public class LbExceptionHandler {

		@ExceptionHandler(value = {LoadBalancerCertDeleteException.class})  
		protected ResponseEntity<ErrorResponse> deleteCertException(LoadBalancerCertDeleteException e) {  
		    log.error("==== LoadBalancer 인증서 삭제 실패: 이미 바인딩된 인증서입니다. 로드밸런서명: {}", e.getVServerName());  
		  
		    String message = String.format("%s 로드밸런서에 바인딩되어 있는 인증서입니다. 해제 후 삭제 해주세요.", e.getVServerName());  
		  
		    return ResponseEntity  
		            .badRequest()  
		            .body(  
		                    ErrorResponse.of(e.getErrorCode().getErrorCode(), message)  
		            );  
		}
}

AI가 추천해준 다른 방식

  • Controller의 어노테이션으로도 구분할 수 있다.
package okestro.third.domain.openstack.exception;

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

@ControllerAdvice(basePackages = "okestro.third.domain.openstack.ctr", annotations = PostMapping.class)
public class PostExceptionHandler {

    @ExceptionHandler(OsNetworkCreateException.class)
    public ResponseEntity<String> handleOsNetworkCreateException(OsNetworkCreateException ex) {
        return new ResponseEntity<>("POST request failed: " + ex.getMessage(), HttpStatus.BAD_REQUEST);
    }
}

0개의 댓글