Exception 처리
- 예외가 발생할 수 있는 계층
- 모든 컨트롤러, 모든 도메인 등...
→Global package에서 제어
- In Business logic
→ 해당 도메인 내에서 예외처리 반환
Http Status 관련해서 정적, 불변으로 관리하기 위한 클래스.
public class StaticValue {
// Success Code
public static final int OK = 200;
public static final int CREATED = 201;
public static final int NO_CONTENT = 204;
// Error Code
public static final int BAD_REQUEST = 400;
public static final int UNAUTHORIZED = 401;
public static final int FORBIDDEN = 403;
public static final int NOT_FOUND = 404;
public static final int METHOD_NOT_ALLOWED = 405;
public static final int CONFLICT = 409;
public static final int INTERNAL_SERVER_ERROR = 500;
}
Front-end 와 통신하기 위하여, 만드는 Json 형태의 클래스
@Getter
@ToString
@RequiredArgsConstructor
public class BaseResponse {
private final Boolean isSuccess;
private final String code;
private final String message;
private final String timeStamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 성공 여부와 BaseResponseCode
public static BaseResponse of(Boolean isSuccess, BaseResponseCode baseResponseCode) {
return new BaseResponse(isSuccess, baseResponseCode.getCode(), baseResponseCode.getMessage());
}
// 성공 여부와 BaseResponse, 메세지
public static BaseResponse of(Boolean isSuccess, BaseResponseCode baseResponseCode, String message) {
return new BaseResponse(isSuccess, baseResponseCode.getCode(), message);
}
// custom - 성공여부, 코드, 메세지 전부
public static BaseResponse of(Boolean isSuccess, String code, String message) {
return new BaseResponse(isSuccess, code, message);
}
isSuccess : 통신 성공 여부code : Http Status 중, 어떤 상태인지 (200 OK, 403 Forbidden ...)message : 실패한 이유// Success Case
// 200 OK 응답
public static <T> SuccessResponse<T> from(T data) {
return new SuccessResponse<>(data, SuccessResponseCode.SUCCESS_OK);
}
// Error Case
// No Data
public static ErrorResponse<?> from(BaseResponseCode baseResponseCode) {
return new ErrorResponse<>(null, baseResponseCode);
}
RunTime 중에서, 터지는 예외에 대해 알맞게 분기하여 예외를 던짐.
BaseResponseCode를 상속받아서, isSuccess, code, message를 알맞게 입력해줌@RestControllerAdvice 를 통해서, 예외 발생 시, 자동으로 해당 예외를 던짐 // @RequesBody - Valid(Validated)
// like NotNull, NotBlank ...
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse<?>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error("MethodArgumentNotValidException : {}", e.getMessage(), e);
ErrorResponse<?> errorResponse = ErrorResponse.of(
ErrorResponseCode.INVALID_HTTP_MESSAGE_BODY,
e.getFieldError().getDefaultMessage());
return ResponseEntity.status(errorResponse.getHttpStatus()).body(errorResponse);
}
enum - BaseResponseCode 상속,exception - BaseException 상속// UserErrorCode
@Getter
@AllArgsConstructor
public enum UserErrorCode implements BaseResponseCode {
USER_ALREADY_EXIST_409("USER_409", CONFLICT, "이미 존재하는 사용자입니다.");
private final String code;
private final int httpStatus;
private final String message;
}
// UserAlreadyExsistException
public class UserAlreadyExistException extends BaseException {
public UserAlreadyExistException() { super(UserErrorCode.USER_ALREADY_EXIST_409); }
}
Cross-Origin-Resource-Shared : 서로 출처가 다른 자원 요구 중
이라는 뜻이다. 원래 브라우저는 같은 출처에서의 자원끼리만 공유되게끔 설정해두어서,
http://localhost:8080<->http://ANOTHER_URL
위와 같은 방식으로 자원을 공유하려고 시도할 시, CORS 에러가 발생한다.
이를 설정으로 허용해줄 수 있는데, 그 방법은 다음과 같다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
/* 위의 경우, 여러 URL의 CORS를 허용하고 싶을 때
* 현재방식의 경우, WildCard 문자인 '*'로 모든 URL 허용중이다.
* allowedOrigins() < 임의의 1개 도메인 허용
*/
.allowCredentials(true);
}
}
Spring의 MVC 패턴(Dispatcher Servlet 등)이라던가,
예외를 던졌을 때 어떻게 잡아지는지,
Front-End와 통신할 때 발생할 수 있는 여러가지 예외,
그리고 비즈니스 로직 간 예외가 발생했을 때 어떻게 대처해야 하는지?
이런 것들을 공부해서, 예외 케이스를 마음껏 설정해두고 싶다.