클라이언트 단에서는 어떤 예외인지에 따라서 다르게 처리하는 로직이 필요하다. 그러나 해당 예외들이 전부 동일한 StatusCode를 제공한다.
이를 구별하기 위해 ErrorCode와 message를 Custom 정의하여 처리한다.
💡 사용할 ErrorCode를 정의한다.
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
@Getter
@AllArgsConstructor
public enum ErrorCode {
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "ACCOUNT-001", "사용자를 찾을 수 없습니다."),
HAS_EMAIL(HttpStatus.BAD_REQUEST, "ACCOUNT-002", "존재하는 이메일입니다."),
INVALID_PASSWORD(HttpStatus.BAD_REQUEST, "ACCOUNT-003", "비밀번호가 일치하지 않습니다."),
// ...
private final HttpStatus httpStatus; // HttpStatus
private final String code; // ACCOUNT-001
private final String message; // 설명
}
💡 ErrorCode를 담을 class 생성한다.
@Getter
@AllArgsConstructor
public class CustomException extends RuntimeException {
ErrorCode errorCode;
}
💡 Controller 전역에서 발생하는 Custom Error를 잡아줄 Handler를 생성한다.
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(CustomException.class)
protected ResponseEntity<ErrorResponseEntity> handleCustomException(CustomException e){
return ErrorResponseEntity.toResponseEntity(e.getErrorCode());
}
}
✅ 모든 @Controller 즉, 전역에서 발생할 수 있는 예외를 잡아 처리한다.
✅ 발생한 CustomException 예외를 잡아서 하나의 메소드에서 공통 처리한다.
✅ 모든 컨트롤러에서 발생하는 CustomException을 catch한다.
💡 Custom Error 내용을 담을 Response Entity를 생성한다.
@Data
@Builder
public class ErrorResponseEntity {
private int status;
private String name;
private String code;
private String message;
public static ResponseEntity<ErrorResponseEntity> toResponseEntity(ErrorCode e){
return ResponseEntity
.status(e.getHttpStatus())
.body(ErrorResponseEntity.builder()
.status(e.getHttpStatus().value())
.name(e.name())
.code(e.getCode())
.message(e.getMessage())
.build());
}
}
Response 결과 예시
{
"status": 404,
"name": "USER_NOT_FOUND",
"code": "ACCOUNT-001",
"message": "사용자를 찾을 수 없습니다."
}
userRepository.findById({userId})
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
💡 클라이언트와 소통하기 위해 ErrorCode에 대한 문서화가 필요하다.
안녕하세요 ! 게시글 너무 잘 봤고 이번 프로젝트에 적용하고 싶습니다 ㅎㅎ
혹시 이 경우 스웨거는 어떻게 적용하는지 여쭙고 싶습니다 !