본문 바로가기
프로그래밍

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

by 탁구치는 개발자 2013. 2. 26.

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

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


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


그래서 이런 예외들을 인터셉터의 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 메소드를 적절히 활용하여 예외를 방치하는 오류를 범하지 말자.