본문 바로가기

프로그래밍/Spring

[Spring] 예외처리 (@ExceptionHandler, @ControllerAdvice)

 프로그래밍을 하며 예외처리를 하기 위해서 매번 try-catch를 사용하게 되면 코드가 지저분해지고, 메소드마다 반복적으로 사용하기 때문에 중복, 불편함을 느낄 수 있다.

 

 대신 Spring MVC에서 제공하는 @ExceptionHandler, @ControllerAdvice를 사용하여 일괄적으로 예외처리를 한다면 이러한 불편함을 해결할 수있다.

@ExceptionHandler

 @ExceptionHandler란 @Controller, @RestController 어노테이션이 적용 된 빈에서 발생하는 예외를 캐치하여 하나의 메소드에서 처리할 수 있도록 해주는 어노테이션이다.

즉, 특정 Controller 범위에서 발생하는 예외처리를 전역적으로 처리할 수 있게 해준다.

 

코드 예제)

@Controller
public class SimpleController {

    // ...

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handle(Exception e) {
        // ...
    }
}

 위 코드와 같이 Controller에서 @ExceptionHandler 어노테이션을 적용한 메소드를 하나 추가해주게 되면, 이후 해당 컨트롤러에서 발생하는 모든 예외는 저 메소드에서 처리할 수있게 된다.

예제 코드처럼 ResponsEntity타입으로 return 할 수도있고, 특정 view로 이동하게 할 수도있다.

CustomException와 같은 특정 예외에 대해서만 처리를 하고싶다면, @ExceptionHandler(CustomException.class)와 같이 따로 처리하고싶은 Exception을 명시해주면 된다.

 

@ControllerAdvice

 @ExceptionHandler 어노테이션이 특정 컨트롤러에서만 적용이 되었다면, @ControllerAdvice는 모든 컨트롤러에서 발생하는 예외를 하나의 클래스에서 처리할 수있도록 해준다. 그렇기 때문에 @ExceptionHandler보다 더 넓은 범위의 예외처리를 해 줄 수 있게된다.

 

코드 예제)

@ControllerAdvice
public class CommonExceptionAdvice {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> common(Exception e) {
        // ...
    }
    
    @ExceptionHandler(CustomException.class)
    public ResponseEntity<String> custom(CustomException e) {
        // ...
    }
    
   // ...
}

 모든 컨트롤러에서 발생하는 예외를 처리하기 위한 클래스를 하나 만들고 @ControllerAdvice 어노테이션을 적용한다. 이후 메서드에 @ExceptionHandler 어노테이션을 적용하여 메소드를 통해 예외처리를 한다.

 마찬가지로 ResponsEntity타입으로 return 할 수도있고, 특정 view로 이동하게 할 수도있다. 또한 CustomException와 같은 특정 예외에 대해서만 처리를 하고싶다면, @ExceptionHandler(CustomException.class)와 같이 따로 처리하고싶은 Exception을 명시해주면 된다.

 

 @ControllerAdvice에서 전역적으로 처리되는 예외를 좀 더 세분화 시키기 위해서 아래와 같이 클래스별, 또는 패키지별로 구분하여 사용할 수도있다.

// @RestController어노테이션이 붙은 컨트롤러에서만 적용
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}

// 특정 패키지에 속한 컨트롤러만 적용
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

// 특정 컨트롤러에서만 적용
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}

'프로그래밍 > Spring' 카테고리의 다른 글

[Spring] AOP  (0) 2023.03.21
[Spring] @Valid @Validated와 유효성 검사 Annotation  (0) 2023.01.03
[Spring] (SpringBoot) SQL 로그 남기기  (0) 2022.03.29
[Spring] log4j  (0) 2022.03.28
[Spring] @Transactional  (0) 2022.03.28