
Request(요청)이 들어오면 Filter을 거치고 DispatcherServlet에서 도달한다Handler Mapping과 함께 어떤 주소를 가진 컨트롤러에 매핑할지 결정을 한다Intercepteor을 거쳐 Controller,Service,DB측에 도착한다Interceptor, DispatcherServlet, Filter 순을 거쳐 Response(응답)이 된다🤔그런데 만약 컨트롤러,서비스 즉 비즈니스 로직을 처리하는 구간에서 예외가 발생한다면???
- 예외를
Exception Handler에게 던진다- Exception Handler는 그 예외를 잡아서(catch), 예외에 대한 응답을 만들어 응답을 내려준다
- 그 후에는 동일하게 작동한다
그러기엔 우리가 예상치 못한 예외가 발생할 수 있다! -> 예상치 못한 예외를 Exception Handler로 잡는다
SRP원칙을 지키기 위해서!
@Slf4j
@RestController
@RequestMapping(path = "/api")
public class RestApiController {
@GetMapping(path = "")
public void hello(){
List<String> list = List.of("hello");
String element = list.get(1);
log.info("element : {}",element);
}
}


🤔우리는 global하게 이런 예외처리를 할 필요가 있다!
- Exception Handler을 이용해 처리해 보자!
ExceptionHandler가 붙은 메서드에 해당 예외처리를 해주면 된다!@Slf4j
@RestControllerAdvice
public class RestApiExceptionHandler {
@ExceptionHandler(value = {Exception.class})
public ResponseEntity exception(
Exception e
){
log.error("RestApiExceptionHandler",e);
return ResponseEntity.status(200).build();
}
@ExceptionHandler(value = {IndexOutOfBoundsException.class})
public ResponseEntity outOfBound(
IndexOutOfBoundsException e
){
log.error("IndexOutOfBoundsException",e);
return ResponseEntity.status(200).build();
}
}

- 🤔 RestApiExceptionHandler 의 IndexOutOfBoundsException에 error 로그가 찍혔다!
- 즉,
IndexOutOfBoundsException을 잡기 위해 해당 예외가 지정된 @ExceptionHandler가 있는outOfBound메서드가 실행된 것을 알 수 있다- 또한 예외를 잡은 곳이
RestApiController라는 사실 또한 알 수 있다

@RestControllerAdvice를 통해 처리하였다
@Slf4j
@RestControllerAdvice(basePackages = "com.example.exception.controller")
// 이 클래스는 Rest Api가 사용하는 곳에 예외가 일어나는 것을 감지 하게 된다
public class RestApiExceptionHandler {
@ExceptionHandler(value = {Exception.class})
public ResponseEntity exception(
Exception e
){
log.error("RestApiExceptionHandler",e);
return ResponseEntity.status(200).build();
}
}

@RestControllerAdvice에는 클래스를 입력 받을 수도 있다
@RestControllerAdvice(basePackageClasses = {RestApiBController.class})
public class RestApiExceptionHandler {
@ExceptionHandler(value = {Exception.class})
public ResponseEntity exception(
Exception e
){
log.error("RestApiExceptionHandler",e);
return ResponseEntity.status(200).build();
}
그렇기에 우리는 웹 서버를 만들 때
- exception handler 즉 advice handle을 통해
- 항상 우리 서버가 👌동일한 응답을 내려줄 수 있게 예외 처리를 해줘야 한다
ExceptionHandler를 이용하는 이유이기도 하다
@Slf4j
@RestControllerAdvice
@Order(value = Integer.MAX_VALUE) // 작을 수록 우선 실행된다, 최대값을 두어 가장 마지막에 최후의 보류의 예외 처리하는 곳!
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ResponseEntity<Api> exception(
Exception e
){
log.error("exception",e);
Api<Object> response = Api.builder()
.resultCode(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()))
.resultMessage(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase())
.build();
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(response);
}
}


- 즉, 우리는 이제 성공이든, 예외든 모두 공통된 형식으로 http 응답을 할 수 있고
- 모든 오류에 대해, 처리할 수 있게 된 것이다!

@Order로 정함
@Order(value = Integer.MAX_VALUE)
@Order의 매개변수를 통해서, 잘 적용할 수 있게 되었다!