Spring & SpringBoot

@ExceptionHandler를 이용한 API 오류처리

창따오 2023. 12. 8. 16:02
728x90

API 예외처리의 어려운점

  • @HandlerExceptionResolver의 경우 MolelAndView를 반환한다.
    -> 이것은 API응답에 굳이 필요하지 않음.
  • API 응답을 위해서 HttpServletResponse에 직접 응답 데이터를 넣어주는 방법
    -> 과거 서블릿을 사용하던 시절로 돌아가는 것 만큼 해주여야 할 것들이 많음.
  • 위에서 소개되는 방식들은 API 예외처리를 하기에 번거로운 방식임*

@ExceptionHandler

스프링은 API예외 처리 문제를 해결하기 위해 @ExceptionHandler라는 에노테이션을 사용하는 매우 편리한 예외 처리기능을 제공함.
-> ExceptionHandlerExceptionResolver
실무에서 API 예외처리는 대부분 이방식을 사용.

//controller
@PostMapping("create/user")
    public ApiResponse createUser(@RequestBody @Validated RequestUserDto userData, BindingResult results) {
        if (results.hasErrors()) {
            if (results.hasFieldErrors("username")) {
                throw new CreateException("이름을 잘못 입력하였습니다.");
            }
            if (results.hasFieldErrors("grade")) {
                log.info("grade is {}", results.getFieldValue("grade"));
                throw new CreateException("학점을 잘못 입력하였습니다.",
                        new Throwable(results.getFieldValue("grade").toString()));

            }
        }
        User user = User.builder().username(userData.getUsername())
                .grade(userData.getGrade())
                .build();
        userService.joinUser(user);
        return new ApiResponse(new Status(CustomStatusCode.OK.getStatusCode(), CustomStatusCode.OK.name()),
                new MetaData(1),
                new ResponseUserDto(user));
    }

위의 소스에서 필드오류 시 api 응답을 매번 정의하는 것은 번거로움.

@ExceptionHandler 예외 처리 방법
@ExceptionHandler 애노테이션을 선언하고, 해당 컨트롤러에서 처리하고 싶은 예외를 지정해주면됨. 해당 컨
트롤러에서 예외가 발생하면 이 메서드가 호출됨. 참고로 지정한 예외 또는 그 예외의 자식 클래스는 모두 잡을 수 있음.

package com.changddao.goorm_response_error.handleexception;

import com.changddao.goorm_response_error.dto.ErrorData;
import com.changddao.goorm_response_error.dto.ErrorResult;
import com.changddao.goorm_response_error.dto.Status;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice(basePackages = "com.changddao.goorm_response_error.controller")
public class ErrorControllerAdvice {

    @ExceptionHandler
    public ResponseEntity<ErrorResult> userHandler(CreateException e) {
        ErrorResult result = new ErrorResult(new Status(CustomStatusCode.USER_INPUT_ERROR.getStatusCode()
                , e.getMessage()), new ErrorData(e.getCause().getMessage()));
        return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
    }
    @ResponseStatus(HttpStatus.LENGTH_REQUIRED)
    @ExceptionHandler(CustomFindAllException.class)
    public ErrorResult findAllHandler(CustomFindAllException e) {
        return new ErrorResult(new Status(CustomStatusCode.NO_DATA_ERROR.getStatusCode(),
                e.getMessage()),
                new ErrorData("data 빵개요.."));
    }

}

Spring AOP에서 착안한 방식으로 Api Error를 해결하는 것 같다.