❏ ErrorCode
ErrorCode는 Enum 타입으로, 반복적으로 사용되는 Error 상태와 메시지를 포함합니다. Enum 타입으로 미리 에러코드와 메시지를 정의해두며, 편리하게 활용합니다.
@Getter
@RequiredArgsConstructor
public enum ErrorCode {
INVALID_TOKEN(401, "Token이 유효하지 않습니다."),
ACCESS_DENIED(403, "접근 권한이 없습니다."),
MEMBER_NOT_FOUND(404, "존재하지 않는 회원입니다."),
AUTHENTICATION_FAILED(400, "아이디 또는 비밀번호가 옳지 않습니다."),
BOARD_NOT_FOUND(404, "존재하지 않는 게시물입니다."),
BOARD_AUTHOR_MISMATCH(403, "해당 게시물에 접근 권한이 없습니다.");
private final int status;
private final String msg;
}
❏ CustomException
위에서 생성해준 Errorcode를 사용하여, RuntimeException을 상속받는 CustomException을 생성해줍니다. 이제 해당 클래스는 다양한 예외 클래스에 상속시켜 status와 msg를 담아 사용될 수 있습니다.
@Getter
public class CustomException extends RuntimeException {
private final ErrorCode errorCode;
public CustomException(ErrorCode errorCode) {
this.errorCode = errorCode;
}
}
예를 들면, Member라는 도메인에서 발생하는 예외 처리를 위한 MemberException에 CustomException을 상속 받도록 하여 사용해줄 수 있습니다.
public class MemberException extends CustomException{
public MemberException(ErrorCode errorCode) {
super(errorCode);
}
}
Service에서 예외 처리를 해줄 때, 다음과 같이 MemberException을 사용하여 Member 도메인에서 발생한 예외임을 클래스명으로 명시해줄 수 있으며, ErrorCode를 통해 반복적으로 사용되는 에러 상태와 메시지를 담아 표현해줄 수 있습니다.
Member member = memberRepository.findByRefreshToken(token)
.orElseThrow(() -> new MemberException(ErrorCode.INVALID_TOKEN));
❏ ControllerAdvice
이제 위에서 만들어준 도메인별 Exception을 처리해주기 위해 전역 예외 핸들러를 생성해줍니다.
@Slf4j
@RestControllerAdvice
public class ExceptionControllerAdvice {
@ExceptionHandler({MemberException.class, BoardException.class})
public ResponseEntity<RsData<Object>> handleCustomException(CustomException e) {
**log.error("Error Message {} ", e.getErrorCode().getMsg());
return ResponseEntity.status(e.getErrorCode().getStatus())
.body(e.getErrorCode().getMsg());
}
}
@RestControllerAdvice를 붙여주었습니다.
@RestControllerAdvice는 @ControllerAdivce에 @ResponseBody를 더해 응답을 json 형태로 사용자 정의가 가능합니다.
@ExceptionHandler를 적용해주어, 설정해둔 Exception들을 처리해줄 수 있도록 합니다.
그러면, 해당 Exception에 대해 http status와 body를 정의하여 응답될 수 있도록 할 수 있습니다.