[SpringBoot] Custom Exception Response 만들기

이정음·2022년 4월 19일
4

SpringBoot

목록 보기
7/7

API를 작성할 때 따로 Exception Handler를 만들어주지 않으면,
Runtime Error시 모두 500 Error로 Response가 가게 된다.
FE는 이 에러 코드에서 에러에 원인을 알 수 없다.
이를 해결하기 위해 Custome Exception을 추가하여 FE에게 내용을 전달하도록 해보자!

ErrorCode 만들기

💡 다양한 상황에서 쓰일 Error Code를 만든다.

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@AllArgsConstructor
@Getter
public enum ErrorCode {
    /* 400 BAD_REQUEST : 잘못된 요청 */
    /* 401 UNAUTHORIZED : 인증되지 않은 사용자 */
    INVALID_AUTH_TOKEN(HttpStatus.UNAUTHORIZED, "권한 정보가 없는 토큰입니다."),

    /* 404 NOT_FOUND : Resource를 찾을 수 없음 */
    USER_NOT_FOUND(HttpStatus.NOT_FOUND, "해당하는 정보의 사용자를 찾을 수 없습니다."),

    /* 409 : CONFLICT : Resource의 현재 상태와 충돌. 보통 중복된 데이터 존재 */
    DUPLICATE_RESOURCE(HttpStatus.CONFLICT, "데이터가 이미 존재합니다."),
    ;


    private final HttpStatus httpStatus;
    private final String message;
}
  • 상태를 담을 HttpStatus와 메세지를 담을 String 속성을 추가
  • 이에 맞는 다양한 Enum 타입의 Error Code들을 만들어주었다.

    이때, HttpStatus를 따르지 않고 USER_NOT_FOUND(901, "유저 없음") 와 같이 custom해서 만들어도 된다.
    다만 이럴 경우에는 HttpStatus타입이 아닌 Integer타입으로 바꿔야 한다!

CustomException 추가

💡 ErrorCode를 담을 class를 만들자.

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public class CustomException extends RuntimeException{
    ErrorCode errorCode;
}
  • RuntimeException을 상속
  • ErrorCode만 속성으로 추가 > 상태와 메세지 정보 모두 담겨있으므로!

Custom Exception Handler 추가

💡 컨트롤러 전역에서 발생하는 Custom에러를 잡아줄 Handler를 만들자

import com.ovcors.godlife.api.exception.CustomException;
import com.ovcors.godlife.api.exception.ErrorResponseEntity;
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());
    }
}

@ExceptionHandler(CustomException.class)

✅ 발생한 CustomException 예외를 잡아서 하나의 메소드에서 공통 처리할 수 있게 해준다.

  • Controller에만 등록이 가능하다. (Service영역은 놉!)
  • 등록한 Controller 영역 안에서만 작동한다.
  • @ExceptionHandler({ Exception1.class, Exception2.class}) 이런식으로 두 개 이상 등록도 가능하다.

@ControllerAdvice + @ExceptionHandler

✅ 모든 컨트롤러에서 발생하는 CustomException을 캐치한다.

ErrorResponseEntity

✅ Error내용을 담을 Response Entity를 만들어주었다.

@Data
@Builder
public class ErrorResponseEntity {
    private int status;
    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())
                        .code(e.name())
                        .message(e.getMessage())
                        .build()
                );
    }
}
  • CustomException을 toResponseEntity로 보내면, ErrorCode e안에 내용을 가지고 Response를 만든다.

사용

userRepository.findById({id}).orElseThrow(
	()->new CustomeException(USER_NOT_FOUND)
);

💡 userRepository에서 id에 맞는 유저가 없을 경우 Exception이 발생하여 Response로 전달 될 것이다


이러한 처리를 통해, FE는 에러에 대한 status, code, message를 보고 원인을 정확히 파악할 수 있다.


참고블로그
🔗 https://bcp0109.tistory.com/303
🔗 https://jeong-pro.tistory.com/195

profile
코드먹는 하마

1개의 댓글

comment-user-thumbnail
2023년 11월 24일

안녕하세요 블로그 잘보고있어요! 혹시 쫌 배울수 있는 기회가 있을까요?

답글 달기