참고!!
[Spring] 스프링의 다양한 예외 처리 방법(ExceptionHandler, ControllerAdvice 등) 완벽하게 이해하기 - (1/2)
WAS(톰캣) → 필터 → 서블릿 → 인터셉터 → 컨트롤러
결국 컨트롤러를 2번 호출 하는 꼴
WAS(톰캣) -> 필터 -> 서블릿(디스패처 서블릿) -> 인터셉터 -> 컨트롤러
-> 컨트롤러(예외발생) -> 인터셉터 -> 서블릿(디스패처 서블릿) -> 필터 -> WAS(톰캣)
-> WAS(톰캣) -> 필터 -> 서블릿(디스패처 서블릿) -> 인터셉터 -> 컨트롤러(BasicErrorController)
모든 코드에 예외 처리를 위해 try-catch 를 붙이는 건 비효율적!!
Spring 에서는 Exception 처리를 메인 로직으로부터 분리하여 HandlerExceptionResolver 사용 권장!!
HandlerExceptionResolver 는 발생한 Exception 을 catch 하고 HTTP 상태, 응답 메시지 등을 설정
WAS 입장에서는 해당 요청이 정상적인 응답으로 인식되며, WAS 의 에러 전달 발생 X
DefaultErrorAttributes : 에러 속성을 저장하며 직접 예외를 처리하지는 않는다.
ExceptionHandlerExceptionResolver : 에러 응답을 위한 Controller나 ControllerAdvice에 있는 ExceptionHandler를 처리한다.
DefaultHandlerExceptionResolver : 스프링 내부의 기본 예외들을 처리한다.
ResponseStatusExceptionResolver : Http 상태 코드를 지정하는 @ResponseStatus 또는 ResponseStatusException를 처리한다.
4개 중 DefaultErrorAttributes 는 직접 예외처리X, 속성만 관리하므로 성격이 다르다. 나머지 3개는 ExceptionResolver 들은 HandlerExceptionResolverComposite 로 모아서 관리한다.
Spring 에서는 아래와 같은 도구를 이용해서 ExceptionResolver 를 동작시켜 에러를 처리한다.
Spring 에서 ExceptionResolver 를 동작시킬 때, 사용하는 도구는 아래와 같다.
ResponseStatus, ResponseStatusException, ExceptionHandler, RestControllerAdvice
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class NoSuchElementFoundException extends RuntimeException {
...
}
{
"timestamp": "2021-12-31T03:35:44.675+00:00",
"status": 404,
"error": "Not Found",
"path": "/product/5000"
}
@GetMapping("/product/{id}")
public ResponseEntity<Product> getProduct(@PathVariable String id) {
try {
return ResponseEntity.ok(productService.getProduct(id));
} catch (NoSuchElementFoundException e) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Item Not Found");
}
}
code: 어떠한 종류의 에러가 발생하는지에 대한 에러 코드
message: 왜 에러가 발생했는지에 대한 설명
erros: 어느 값이 잘못되어 @Valid에 의한 검증이 실패한 것인지를 위한 에러 목록
@RestController
@RequiredArgsConstructor
public class ProductController {
private final ProductService productService;
@GetMapping("/product/{id}")
public Response getProduct(@PathVariable String id){
return productService.getProduct(id);
}
@ExceptionHandler(NoSuchElementFoundException.class)
public ResponseEntity<String> handleNoSuchElementFoundException(NoSuchElementFoundException exception) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage());
}
}
./
├── DemoApplication.java
├── code/
│ └── UserErrorCode.java
├── controller/
│ └── UserApiController.java
├── dto/
│ ├── UserCreateRequestDto.java
│ └── UserUpdateRequestDto.java
├── exception/
│ ├── GlobalExceptionHandler.java
│ └── UserException.java
├── model/
│ └── UserEntity.java
├── repository/
│ └── UserRepository.java
├── response/
│ ├── ErrorResponse.java
│ └── SuccessResponse.java
└── service/
└── UserService.java