백엔드에서 개발 중 발생하는 에러들을 특정 코드로 정리하여 공통으로 에러 응답을 내려주는 것을 적용해보려고 한다.
ErrorResponse
@Data
public class ErrorResponse {
private boolean result;
private String code;
private String message;
public ErrorResponse(String code, String message) {
this.setResult(false);
this.setCode(code);
this.setMessage(message);
}
}
예외가 발생했을 때 응답할 DTO를 생성하고 code와 message를 받는 생성자를 추가했다.
ErrorCode
@Getter
@AllArgsConstructor
public enum ErrorCode {
SYSTEM_ERROR("0000", "시스템 에러입니다."),
EMPTY_DATA("0001", "데이터가 없습니다."),
LOGIN_FAIL("1000", "ID 혹은 비밀번호가 일치하지 않습니다. 입력한 내용을 다시 확인해 주세요."),
DUPLICATE_ID("2000", "중복된 ID가 있습니다."),
;
private String errorCode;
private String errorMessage;
public static ErrorCode getErrorCode(ResponseStatusException responseStatusException) {
if (!StringUtils.hasText(responseStatusException.getReason())) {
return ErrorCode.SYSTEM_ERROR;
}
try {
return ErrorCode.valueOf(responseStatusException.getReason());
} catch (IllegalArgumentException e) {
return ErrorCode.SYSTEM_ERROR;
}
}
}
ErrorCode Enum에 1000, 2000 등 개발 중 발생한 예외들을 정리한다.
getErrorCode() : ResponseStatusException을 인자로 받아서 ErrorCode Enum에 정의된 enum이 있으면 해당 enum을 반환하고, 없는 경우 공통으로 SYSTEM_ERROR를 반환한다.
CustomExceptionHandler 구현
@Slf4j
@RestControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
/**
* 404 Not Found Error Handling
* @param ex the exception to handle
* @param headers the headers to use for the response
* @param status the status code to use for the response
* @param request the current request
* @return
*/
@Override
protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex,
HttpHeaders headers, HttpStatusCode status, WebRequest request) {
log.info(ex.getMessage(), ex);
return new ResponseEntity<>(new ErrorResponse(String.valueOf(ex.getStatusCode()), ex.getMessage()), HttpStatus.NOT_FOUND);
}
/**
* 405 Method Not Allowed Error Handling
* @param ex the exception to handle
* @param headers the headers to use for the response
* @param status the status code to use for the response
* @param request the current request
* @return
*/
@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(
HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatusCode status,
WebRequest request) {
log.info(ex.getMessage(), ex);
return new ResponseEntity<>(new ErrorResponse(String.valueOf(ex.getStatusCode()), ex.getMessage()), HttpStatus.METHOD_NOT_ALLOWED);
}
/**
* ResponseStatusException 처리
* @param e
* @return
*/
@ExceptionHandler(ResponseStatusException.class)
public ResponseEntity handleResponseStatusException(ResponseStatusException e) {
ErrorCode errorCode = ErrorCode.getErrorCode(e);
return new ResponseEntity<>(new ErrorResponse(errorCode.getErrorCode(), errorCode.getErrorMessage()), e.getStatusCode());
}
}
ResponseEntityExceptionHandler를 상속받아 404, 405 에러를 오버라이드하여 처리하고,
@ExceptionHandler 어노테이션을 적용해 ResponseStatusException이 발생했을 때 만든 에러 응답 DTO를 반환한다.
if (memberRepository.existsByUserId(memberJoinDto.getUserId())) {
throw new ResponseStatusException(HttpStatus.OK, ErrorCode.DUPLICATE_ID.name());
}
이제 ResponseStatusException에 ErrorCode를 넣어 던져주면 아래와 같이 공통 에러 응답을 반환할 수 있다.
{
"result": false,
"code": "0001",
"message": "데이터가 없습니다."
}
{
"result": false,
"code": "405 METHOD_NOT_ALLOWED",
"message": "Request method 'PATCH' is not supported"
}
-끝-
'Spring Boot' 카테고리의 다른 글
[SpringBoot] @Secured, @PreAuthorize, @PostAuthorize (0) | 2023.12.24 |
---|---|
[Spring Boot] @RestControllerAdvice를 사용한 공통 응답 처리 (0) | 2023.11.26 |
[SpringBoot] 공통 응답 DTO (0) | 2023.11.10 |