[Spring] 일관적인 예외처리를 위한 @ControllerAdvice 사용

Dobi·2024년 5월 26일

Spring

목록 보기
6/6

들어가며

일관적인 응답을 보내려면 어떻게 해야할까? 정상적인 응답은 프로젝트에서 정의한 대로 응답 객체를 생성해서 보내면 될 것 이다. 물론 예외처리도 마찬가지겠지만 매번 Java의 try-catch 문을 이용해 예외를 감지하고 응답객체를 보내야할까? 그렇게된다면 코드 가독성이 엄청 떨어질 것 같다.

스프링에서는 어노테이션을 이용한 예외처리 방법을 제공하고 있는데 바로 AOP를 이용한 방법이다. @ControllerAdvice@RestControllerAdvice 어노테이션을 이용한 방법인데, 모든 컨트롤러에 대해 전역으로 예외를 처리할 수 있다.

추가적으로 @ControllerAdvice는 Spring 3.2, @RestControllerAdvice는 Spring4.3 부터 제공하고 있다.

@ControllerAdvice 와 @RestControllerAdvice ?

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
	..
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
	..
}

두 어노테이션의 차이는 @Controller@RestController의 차이와 동일하다. @ResponseBody 가 붙어있는 것을 보면 확실히 알 수 있는데 응답을 객체로 리턴하는 경우 (대부분 json) @RestControllerAdice 를 사용하면 된다.

@ExceptionHandler

일관적인 예외처리를 하기위해 해야할 것이 있는데, 바로 예외를 지정하는 것이다. 모든 곳에서 발생하는 A라는 예외는 B라는 객체를 보낼꺼야라고 미리 정의를 하는 것인데 @ExceptionHandler 어노테이션을 통해 예외를 지정할 수 있다.

@ExceptionHandler({IllegalStateException.class, IllegalArgumentException.class})
public ResponseEntity<?> handleBadRequestException(Exception e) {
	...
}

@ExceptionHandler(ServiceRuntimeException.class)
  public ResponseEntity<?> handleBusinessException(ServiceRuntimeException e) {
		...
}

예외를 전역적으로 처리하기 위해 @ControllerAdvice 어노테이션을 사용한 클래스에서 위와같이 @ExceptionHandler(처리할 예외)를 사용해서 정의하면 된다.

우선순위?

@ControllerAdvice를 사용한 에러처리 클래스는 하나만 두는게 바람직해 보이지만 상황에 따라 여러개로 관리할 수도 있을 것이다. 이 때 어떤 클래스의 예외를 우선적으로 처리해야할까?

다들 잘 아는 어노테이션인 @Order을 사용하면 순서지정이 가능하다. 하지만 일관적인 예외처리를 위해 되도록이면 한 프로젝트당 하나의 @ControllerAdvice를 사용하는게 바람직해 보인다.



출처
ControllerAdvice - spring 공식문서
RestControllerAdvice - spring 공식문서

profile
양말 받을 때까지 공부하는 개발자 도비

0개의 댓글