프로젝트를 완료하고, 상용에 배포를 하면 버그가 발생하는 일이 많다.
하지만 이런 버그들이 대부분 고객에 의해 발견 되고, 고객 불만으로 접수가 되어서야 문제의 원인을 찾은 후 대처 하는 경우가 많다.
또한, 버그가 발생하고 있는 상태로 방치되어 있다가 결국 고객 민원까지 가서야 발견되는 경우도 비일비재했다.
그래서 이런 예외들을 인터셉터의 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 메소드를 적절히 활용하여 예외를 방치하는 오류를 범하지 말자.