일단 첫번째는 어떤 방식으로든 return할 공통 error class를 선언하면 해결될 일이었습니당
그러나, 두번째 니즈를 위해서 class에 Enum을 활용하게 되었습니다!
(application에서 공통으로 사용될 각종 코드들에도 동일하게 적용이 가능한 부분이라서 추가포스팅!)
요기서 포인트는 ErrorCode라는 Enum을 받아서 해당 class를 생성하도록 구현!
해당 Enum을 통해서 제각각 생성될 수 있는 Error를 한정된 Enum들로 한눈에 보도록 함
@Getter
@Setter
@NoArgsConstructor
public class ErrorResponse {
private String message;
private String code;
private int status;
private String detail;
public ErrorResponse(ErrorCode code) {
this.message = code.getMessage();
this.status = code.getStatus();
this.code = code.getCode();
this.detail = code.getDetail();
}
public static ErrorResponse of(ErrorCode code) {
return new ErrorResponse(code);
}
}
public interface EnumModel {
String getKey();
String getValue();
}
@RequiredArgsConstructor
@Getter
@JsonFormat(shape = Shape.OBJECT)
public enum ErrorCode implements EnumModel {
// COMMON
INVALID_CODE(400, "C001", "Invalid Code"),
RESOURCE_NOT_FOUND(204, "C002", "Resource not found"),
EXPIRED_CODE(400, "C003", "Expired Code"),
// AWS
AWS_ERROR(400, "A001", "aws client error");
private int status;
private String code;
private String message;
private String detail;
ErrorCode(int status, String code, String message) {
this.status = status;
this.message = message;
this.code = code;
}
@Override
public String getKey() {
return this.code;
}
@Override
public String getValue() {
return this.message;
}
}
@ExceptionHandler(value = Exception.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
protected ResponseEntity<ErrorResponse> handleException(Exception e) {
ErrorResponse response = ErrorResponse.of(ErrorCode.TEMPORARY_SERVER_ERROR);
response.setDetail(e.getMessage());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
Tip. 왜 RuntimeException일까요?
RuntimeException은 말그대로 실행단계에 발생하는 UncheckedException으로, 비지니스로직 상 발생 시키고 싶은 경우(=Rollback이 필요) 해당 Exception을 상속받아서 구현하는 것이 맞음!
트랜젝션 중에 Exception이 발생 시, Rollback을 수행하기 때문이죵
public class CustomException extends RuntimeException {
private ErrorCode errorCode;
public CustomException(String message, ErrorCode errorCode) {
super(message);
this.errorCode = errorCode;
}
public CustomException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
public ErrorCode getErrorCode() {
return this.errorCode;
}
}
@Transactional
public UserDto.EmailResponse sendVerification(String userId) {
Optional<User> user = this.userRepository.findByUserId(userId);
if (user.isPresent()) {
throw new CustomException("Duplicated Email", ErrorCode.USER_EXISTS);
}else{
//blah blah....
}
}
이제 기본적으로 Controller/Service단에서 일어날 수 있는 Exception들과
로직으로 정의 할 수 있는 Error들은 CustomException class를 만들어서 구조화하고
Enum을 사용해서 ErrorCode를 한눈에 관리 할 수 있는 부분까지 DONE!
다음 번에는 Filter에서 Error가 나는 경우에 대해서 다뤄보려고 합니다!
(Filter의 경우에는 RestControllerAdvice에서 처리하지 못하기 때문이죠 😟)
스프링부트 Filter에서 Exception나는 경우 공통 처리하기 😄
DB 대신 Enum으로 공통코드 처리하기 😄
글잘읽었습니다. 그럼 성공관련 코드는 SuccessCode / SuccessResponse로 만들면되겠죵?