[spring]스프링의 다양한 예외 처리 방법..(1/n)

eunhye_·2023년 4월 1일
0

Spring

목록 보기
5/5

@ExecptionHandler

@ExceptionHandler는 Controller계층에서 발생하는 에러를 잡아서 메서드로 처리해주는 기능이다.
Service, Repository에서 발생하는 에러는 제외한다.

Controller계층에서 발생하는 에러

@Controller
public class TestController {

    // ...

    @ExceptionHandler
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }
}

이렇게 @Controller로 선언된 클래스 안에서 @ExceptionHandler 어노테이션으로 메서드 안에서 발생할 수 있는 에러를 처리할 수 있다.

여러개의 Exception 처리

@ExceptionHandler의 value 값으로 어떤 Exception을 처리할 것인지 넘겨줄 수 있는데, value를 설정하지 않으면 모든 Exception을 잡게 되기 때문에 Exception을 구체적으로 적어주는 것이 좋다고 한다.

여러 개의 Exception이 발생할 수 있는 코드가 있다고 하자.

@Controller
public class TestController {

    // ...

    @ExceptionHandler({FileSystemException.class, RemoteException.class})
    public ResponseEntity<String> handle(Exception ex) {
        // ...
    }
}

메서드의 인자로 Exception ex를 받고 있고 @ExceptionHandler의 value값으로 특정 Exception들을 설정해주고 있다.
여러개의 Exception을 잡아야한다면, @ExceptionHandler({IOException.class})처럼 포괄적인게 아닌 @ExceptionHandler({FileSystemException.class, RemoteException.class})로 구체적으로 명시해주는 것을 권장한다고 한다.

We generally recommend that you be as specific as possible in the argument signature, reducing the potential for mismatches between root and cause exception types. Consider breaking a multi-matching method into individual @ExceptionHandler methods, each matching a single specific exception type through its signature.
출처 - 스프링 공식 문서

@ControllerAdvice

@ControllerAdvice에서 @ExceptionHandler 사용

@ControllerAdvice는 @Controller와 handler에서 발생하는 에러들을 모두 잡아준다.
@ControllerAdvice안에서 @ExceptionHandler를 사용하여 에러를 잡을 수 있다.

@ControllerAdvice
public class ExceptionHandlers {

    @ExceptionHandler(FileNotFoundException.class)
    public ResponseEntity handleFileException() {
        return new ResponseEntity(HttpStatus.BAD_REQUEST);
    }
}

범위 설정

@ControllerAdvice는 모든 에러를 잡아주기 때문에 일부 에러만 처리하고 싶을 경우에는 따로 설정을 해주면 된다. 방법은 아래와 같다.

  • 어노테이션
  • basePackages (+basepackagesClasses)
  • assignableTypes
// 어노테이션
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}

// basePackages
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

// assignableTypes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}

주의 사항
어노테이션, basePackages 등 설정자들은 runtime시 수행되기 때문에 너무 많은 설정자들을 사용하면 성능이 떨어질 수 있다!
스프링 공식 문서

@RestControllerAdvice

@RestControllerAdvice는 @ControllerAdvice와 @ResponseBody을 가지고 있다.
@Controller처럼 작동하며 @ResponseBody를 통해 객체를 리턴할 수 있다.

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

@ControllerAdvice vs @RestControllerAdvice

@ControllerAdvice는 @Componenet 어노테이션을 가지고 있어 컴포넌트 스캔을 통해 스프링 빈으로 등록된다.

@RestControllerAdvice는 @Controlleradvice와 @ResponseBody 어노테이션으로 이루어져있고 HTML 뷰 보다는 Response body로 값을 리턴할 수 있다.

주의 사항❗❗

ExceptionHandler가 붙은 함수는 꼭 protected / private 처리를 해줘야 한다.
외부에서 함수를 부르게 되면 그대로 에러 객체를 리턴하기 때문이다.

0개의 댓글