스프링 interceptor afterCompletion 메소드 이용 시 참고할 사항

프로그래밍|2013. 2. 26. 15:55

프로젝트를 완료하고, 상용에 배포를 하면 버그가 발생하는 일이 많다.

하지만 이런 버그들이 대부분 고객에 의해 발견 되고, 고객 불만으로 접수가 되어서야 문제의 원인을 찾은 후 대처 하는 경우가 많다.


또한, 버그가 발생하고 있는 상태로 방치되어 있다가 결국 고객 민원까지 가서야 발견되는 경우도 비일비재했다.


그래서 이런 예외들을 인터셉터의 afterCompletion 메소드를 이용하여 DB에 저장 후 이를 개발자의 메일로 하루에 한번씩 전송하는 방법을 생각했다.


아래와 같이 메소드 오버라이드 후 예외를 확인하기 위해 로그로 남겨 테스트를 진행해 보았다.

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

System.out.println("ex : " + ex);

}


http://localhost:8080/log1 을 호출하면 예외를 발생시키고, 이를 Controller 밖으로 던지는 테스트 핸들러이다.

@RequestMapping(value = "/log1", method = RequestMethod.GET)

public void log1(HttpServletRequest req) {

throw new NullPointerException("null 포인트 에러");

}


위의 핸들러 메소드 실행 시 발생되는 예외는 상위로 던져지고 DispatcherServlet이 받게 된다.


try {

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

} catch (Exception ex) {

Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);

mv = processHandlerException(processedRequest, response, handler, ex);

errorView = (mv != null);

}


헌데, HandlerExceptionResolver가 정의되어 있는 경우 afterCompletion 메소드의 Exception 매개 변수에 null이 들어온다.


일단 DispatcherServlet의 설계 구조 자체가 HandlerExceptionResolver가 선언되어 있는 경우에는 Exception을 null로 셋팅하여 던진다. 

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);


위와 같이 설계상의 이유로 문제를 해결할 수 없는 상황이 발생했다.

물론 HandlerExceptionResolver를 삭제한 후 web.xml의 error-page 태그를 이용하여 500 에러를 한 곳에서 처리할 수 있다.

하지만 난 각 에러에 따라 다른 에러 페이지를 사용자에게 노출하고 싶었다.

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

<property name="order" value="1" />

<property name="defaultErrorView" value="common/error/defaultError" />

<property name="exceptionMappings">

<props>

<prop key="BusinessLogicException">common/error/businessLogicError</prop>

<prop key="RuntimeException">common/error/runtimeError</prop>

<prop key="TypeMismatchException">common/error/defaultError</prop>

<prop key="NoSuchRequestHandlingMethodException">common/error/defaultError</prop>

</props>

</property>

</bean>


결국 에러에 대한 로그는 따로 기록하도록 로깅 프레임워크 설정을 바꾸는 것으로 방향을 바꿨다.


만약 클라이언트 화면이 없고, 서버 로직만 있는 웹 애플리케이션을 개발한다면 HandlerExceptionResolver가 필요 없을 것이다.

이럴 때에는 afterCompletion 메소드를 적절히 활용하여 예외를 방치하는 오류를 범하지 말자.

댓글()