프로젝트를 진행하면서 나타나는 대부분의 예외들은 Java에서 지원해주는 Exception으로 처리할 수 있고 무슨 예외인지 파악할 수 있습니다.
Enum
과 함께 사용하여 예외에 대한 응집도를 높일 수 있습니다.@ControllerAdvice
, @RestControllerAdvice
에서 해당 Custom Exception에 대한 자세한 후처리가 가능합니다.우리는 Java에서 지원해주는 Exception으로도 어느정도 해당 Exception에 대한 정보를 제공할 수 있습니다.
new NoSuchElementException("존재하지 않는 상품입니다.")
하지만, 때때로 에러와 관련된 더 자세한 내용을 전달해야 할 경우가 존재합니다. 해당 에러로 인해 특정 HttpStatus
를 응답으로 보내주어야 하는 경우를 예로 들 수 있습니다.
@Getter
public class CustomException extends RuntimeException {
private HttpStatus httpStatus;
private String message;
public CustomException(HttpStatus httpStatus, String message) {
this.httpStatus = httpStatus;
this.message = message;
}
}
이렇게 CustomException
을 제작한다면 해당 에러와 관련된 메세지에 추가로 HttpStatus
또한 전달할 수 있게 됩니다.
Java의 Enum
은 여러 장점을 가지고 있습니다.
이런 장점을 가지고 있는 Enum
을 사용하여 에러 코드들을 한 곳에서 관리해보겠습니다.
@Getter
@RequiredArgsConstructor
public enum ErrorCode {
//== 200 ==//
SUCCESS(HttpStatus.OK, "OK"),
//== 400 ==//
NOT_SUPPORTED_HTTP_METHOD(HttpStatus.BAD_REQUEST,"지원하지 않는 Http Method 방식입니다."),
NOT_VALID_METHOD_ARGUMENT(HttpStatus.BAD_REQUEST,"유효하지 않은 Request Body 혹은 Argument입니다."),
USER_NOT_FOUND(HttpStatus.BAD_REQUEST, "해당 사용자를 찾을 수 없습니다."),
ITEM_NOT_FOUND(HttpStatus.BAD_REQUEST, "해당 상품을 찾을 수 없습니다."),
private final HttpStatus status;
private final String message;
}
이제 ErrorCode
를 CustomException
에 적용해보겠습니다.
@Getter
public class CustomException extends RuntimeException {
private ErrorCode errorCode;
public CustomException(ErrorCode errorCode) {
this.errorCode = errorCode;
}
}
ErrorCode
가 HttpStatus
와 전달할 메세지(String
)를 가지고 있기 때문에 CustomException
의 기존 필드를 완전히 대체하였습니다. 또한, ErrorCode
로 에러들에 대한 추가, 수정, 삭제가 한 곳에서 이루어지기 때문에 변경의 범위가 최소화되는 것을 알 수 있습니다.
이제 CustomException
을 통해 에러에 관련된 내용을 전달하는 Custom한 Response를 만들어보겠습니다.
@Getter
@Builder
@RequiredArgsConstructor
public class ErrorResponse {
private final HttpStatus status;
private final String code;
private final String message;
public ErrorResponse(ErrorCode errorCode) {
this.status = errorCode.getStatus();
this.code = errorCode.name();
this.message = errorCode.getMessage();
}
public static ResponseEntity<ErrorResponse> error(CustomException e) {
return ResponseEntity
.status(e.getErrorCode().getStatus())
.body(ErrorResponse.builder()
.status(e.getErrorCode().getStatus())
.code(e.getErrorCode().name())
.message(e.getErrorCode().getMessage())
.build());
}
}
이제 만든 ErrorResponse
와 @RestControllerAdvice
를 사용해봅시다.
@Slf4j
@RestControllerAdvice
public class ApiExceptionHandler {
@ExceptionHandler(value = CustomException.class)
public ResponseEntity<ErrorResponse> handleCustomException(CustomException e) {
// 에러에 대한 후처리를 할 수 있습니다. 본 예시에서는 로깅만 진행하였습니다.
log.error("[handleCustomException] {} : {}",e.getErrorCode().name(), e.getErrorCode().getMessage());
return ErrorResponse.error(e);
}
}
이렇게 CustomException
을 만들어 상세한 예외 정보를 제공해보고, Enum
과 함께 예외에 대한 응집도도 높여보았으며, @RestControllerAdvice
와 함께 자세한 후처리도 진행해봤습니다.
물론, Java에서 제공해주는 기본 Exception들로 굉장히 많은 에러들을 처리할 수 있습니다. 하지만, 저는 HttpStatus
를 비롯해 예외에 대한 더 자세한 정보를 제공할 수 있고, Enum
과 함께 사용하여 에러들을 한 곳에서 상태 관리를 할 수 있다는 장점으로 CustomException
을 만들어 사용하고 있습니다. Custom한 Exception을 사용하셨던 분들 중에 Enum
으로 에러 코드들을 관리하지 않고 여러 개를 생성해보셨던 분들도 본 예시를 보면서 활용해보시면 좋을 것 같습니다. 긴 글 읽어주셔서 감사합니다 😊
이거 따라해서 한번에 했습니다. 감사합니다,.