프로젝트를 작업하다보면 runtimeException이든 Exception이든 코드내에 작성시켜야 하는 경우가 있다. 하지만 서버를 관리하는 사람으로써 기존에 존재하는 Exception에 형태로는 직관적으로 어떤 오류가 발생했는지 알아차리는게 더 좋을 수 있고 추가적으로 오류 발생지점에서 알고싶던 변수들을 디버깅 용도로 넣고 싶을수도 있다.
exception에서 주되게 사용되는 필드는 세가지이다.
status (HTTP 상태 코드), code (예외 식별 코드), message (예외 메시지)
예외처리를 하는 형태에따라 상속받는 Exception이 달라진다.
나는 다른 코드에 영향을 주지 않기 위해 실행시 오류가 발생하는 runtimeException을 사용했다.
또한 해당 클래스를 추상클래스로 만들어 도메인 별로 사용할 수 있도록 했다.
public abstract class BusinessException extends RuntimeException {
protected HttpStatus status;
private final String code;
private final String message;
public BusinessException(HttpStatus status, String code, String message) {
super(message);
this.status = status;
this.code = code;
this.message = message;
}
생성자를 통해 runtimeException에 생성자를 호출하도록 했다 .
1.예외처리를 할때 발생하는 경우들을 따로 enum으로 저장할 수 있도록 한다.
(새로운 경우들이 추가될때 관리하기에 용이하다.)
2. 만든 enum을 타입으로 하는 필드를 가지는 클래스를 custom한 exception을 상속받아 사용한다.
메뉴를 조회하는 경우 해당하는 메뉴가 없을 때 런타임에러를 원하는 메세지로 표현하고 싶었기에 enum 내 NOT_EXIST를 추가했다.
아까 제작한 추상 클래스 customException을 상속받아 메뉴 도메인에 맞는 exception class를 만들었다.
public class MenuException extends BusinessException {
private final MenuErrorCode code;
public MenuException(MenuErrorCode code, Object... args) {
super(code.getStatus(), code.toString(), code.getMessage(), args);
this.code = code;
}
}
public enum MenuErrorCode {
NOT_EXIST(NOT_FOUND, "요청에 해당하는 메뉴가 존재하지 않습니다. : [%s]");
private final HttpStatus status;
private final String message;
MenuErrorCode(HttpStatus status, String message) {
this.status = status;
this.message = message;
}
}
public FindMenuResponse findOneMenu(String menuId) {
Menu menu = menuRepo.findById(UUID.fromString(menuId)).orElseThrow(
() -> new MenuException(MenuErrorCode.NOT_EXIST, menuId)
);
return FindMenuResponse.from(menu);
}
요청한 메뉴Id가 db내 존재하지 않는경우 (Null) 인 경우 NPE를 커스텀하여
입력한 메뉴Id 값이 없다는 예외처리를 발생시켰다.
예외처리를 입맛대로 쓰기 위해서 기존에 예외를 처리하는 클래스를 상속받아 추상클래스로 만든다.
추상클래스로 만들어진 것을 도메인 별로 구체적 구현을 통해 사용해보자.
예외의 경우의 수들을 enum으로 관리하면 훨씬 용이하다.