Custom Exception 적용하기
Custom Exception을 사용하는 이유는 단순히 404 에러 등을 보다 자세한 상황에 대해서 알려주기 위해서 Custom Exception을 만듭니다.
implementation 'net.rakugakibox.util:yaml-resource-bundle:1.1'
시작하기 전 messageSource에서 사용할 리소스를 가져오기 위해서 gradle에 yaml resourece를 적었습니다.
//exception_en
unKnown:
code: "-404"
msg: "An unknown error has occurred."
userNotFound:
code: "-403"
msg: "This member not exist."
//excepion_ko
unKnown:
code: "-404"
msg: "알 수 없는 오류가 발생하였습니다."
userNotFound:
code: "-403"
msg: "존재하지 않는 회원입니다."
@RequiredArgsConstructor
@RestControllerAdvice
public class ExceptionAdvice {
private final ResponseService responseService;
private final MessageSource messageSource;
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
protected CommonResult defaultException(HttpServletRequest request, Exception e) {
return responseService.getFailResult(Integer.valueOf(getMessage("unKnown.code")), getMessage("unKnown.msg"));
}
@ExceptionHandler(CUserNotFoundException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
protected CommonResult userNotFoundException(HttpServletRequest request, CUserNotFoundException e) {
return responseService.getFailResult(Integer.valueOf(getMessage("userNotFound.code")), getMessage("userNotFound.msg"))
}
private String getMessage(String code) {
return getMessage(code, null);
}
private String getMessage(String code, Object[] args) {
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}
public class CUserNotFoundException extends RuntimeException {
public CUserNotFoundException(String msg, Throwable t) {
super(msg, t);
}
public CUserNotFoundException(String msg) {
super(msg);
}
public CUserNotFoundException() {
super();
}
}
@RestControllerAdvice와 @ExceptionHandler를 설정하면 공통 코드로 분리하여 예외처리를 해버릴 수 있습니다.
만약 특정 Controller만 예외 처리를 하고 싶으시면 하위 Controller를 설정해서 예외처리가 적용될 것 입니다. 저 같은 경우에는 전체를 예외 처리하되, 만들 당시에 에러 로그를 읽어야 하는데 예외 처리로 넘어가져버려서 일단 주석 처리를 한 후 에러 부분을 수정한 후에 다시 예외 처리를 하는 식으로 해결을 하였는데 각자 편하신 대로 하셨으면 좋겠습니다.
@ExceptionHandler(Exception.class)는 예외 처리의 최상위를 담당하여 어떤 예외에 걸리지 않으면 이 예외를 통과
@ExceptionHandler(CUserNotFoundException.class)는 커스텀 예외 처리로 유저가 발견되지 않을 시 이 예외를 통과
messageSource는 code와 args와 LocaleContextHoler.getLocale()을 읽어 현재에 맞는 메세지를 가져옵니다.
CUserNotFoundException이라는 Custom Exception 만들어서 유저가 조회되지 않을 때 예외 상황을 알려줍니다.
@PutMapping(value = "/login")
public ResponseEntity<?> login(@RequestBody UserDTO userDTO, HttpSession session) {
UserDTO userInfo = userService.login(userDTO);
if(userInfo == null)
throw new CUserNotFoundException( messageSource.getMessage("userNotFound.msg",null, LocaleContextHolder.getLocale()));
LocaleContextHolder.getLocale()));
...생략
실제 UserController에서 Login을 하였을 때 유저의 정보가 null 값일 시 CUserNotFoundException이 실행되도록 하였습니다.
API 호출을 하였을 때 정상적으로 호출되는 것을 볼수 있습니다.
이번에 Custom 예외 처리를 하면서 이해가 안가는 부분들이 있었습니다. 공식 문서를 통해 @Controller와 @ControllerAdvice 클래스들은 Controller 메소드로부터 발생한 exception들을 처리하기 위해 @ExceptionHandler 메소드를 갖는다라고 하는데 Handler가 정확히 어떤 의미인지에 대해 궁금해져서 검색을 해보니 Controller에 @RequestMapping 어노테이션이 붙은 메서드를 의미로 사용한다라는 점을 알게 되어 흥미로웠습니다.