SpringBoot @ControllerAdvice
이번 포스팅은 Springboot에서 예외 처리를 간편하게 만들어주는 @ControllerAdvice에 대해 알아보고자 합니다.
Overview
이번에 소개할 @ControllerAdvice는 클래스의 경로를 검색해서 오류를 캐치할 구현 클래스를 만들게 도와줍니다. 일반적으로 @Controller 또는 @RestController가 선언된 클래스들에서 발생한 예외를 감지하고 적절한 응답을 만들어 낼 때 사용합니다.
개인적으로 Springboot 사용시 @RestController를 활용한 RESTful API를 만듭니다. 하지만 예외 처리를 안할 수는 없죠. 간단한 Springboot 프로젝트를 만들어 봅시다.
Create Project
Springboot 프로젝트를 하나 만든 뒤에 테스트 용도로 사용할 아래의 클래스들을 만들어 줍니다.
RuntimeException
우선 만들것은 기존의 예외 클래스도 좋지만 별도의 예외 클래스를 만들어 가시적인 효과를 주는 것도 괜찮습니다. 따라서 런타임 실행 오류 클래스를 하나 만들어줍니다.
public class TestException extends RuntimeException { private static final long serialVersionUID = 1L; private String message; public TestException(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
Controller
컨트롤러도 하나 만듭니다. 간단하게 루트 패스/로 접근시 아까전 만들어뒀던 TestException 오류를 던져주는 코드를 넣었습니다.
@RestController public class TestController { @RequestMapping(value="/") public void ExecuteException(){ throw new TestException("TEST"); } }
ErrorMessage
에러 메시지를 담을 POJO 클래스를 하나 만듭니다. 이 클래스는 추후 에러 메시지 JSON으로 반환할 때 사용합니다.
public class ErrorMessage { private String status; private String message; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
ControllerAdvice
이 클래스가 이번 포스트에서 가장 중요합니다. 간단하게 설명드리면 @ControllerAdvice 어노테이션을 선언하는 클래스는 추후 생기는 예외Exception를 catch해서 처리합니다. 따라서 지금 작성된 클래스는 아까전 만들어 뒀던 TestException 예외가 발생했을 경우 해당 예외를 처리하는 코드가 담겨 있습니다.
@ControllerAdvice public class TestAdvice { @ExceptionHandler(value = { TestException.class }) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody protected ErrorMessage handleConflict(RuntimeException ex, WebRequest request) { ErrorMessage em = new ErrorMessage(); em.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.toString()); em.setMessage(ex.getMessage()); return em; } }
코드를 보면 TestException 예외 발생시 내부 서버 오류INTERNAL_SERVER_ERROR를 발생시키고 ErrorMessage 클래스에 적절한 데이터를 넣고 응답을 반환하고 있습니다. 만약 http://localhost:8080으로 접속한다면 다음과 같은 결과를 받을 수 있습니다.
{"status":"500","message":"TEST"}
물론 이 클래스에서 ModelAndView 타입의 응답을 만들어내는 것도 가능합니다.
@ExceptionHandler(value = { TestException.class }) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) protected ModelAndView handleConflict(RuntimeException ex, WebRequest request) { ModelAndView mav = new ModelAndView(); mav.addObject("message", ex.getMessage()); // ... return mav; }
위처럼 처리도 가능하긴 합니다만, 이번 포스트에서는 이런 방법도 있구나 정도로만 알아두시면 될 것 같네요.
Closing Remarks
간단하게 예외 처리를 한 곳으로 모아 처리할 수 있는 @ControllerAdvice에 대해 알아봤습니다. :D