Keep calm and code on
Spring MVC Custom Annotation 활용한 부가기능 추가하기 본문
스프링 MVC를 사용한다고 한다면 모든 웹 요청은 기본적으로 DispatcherServlet
을 통해서 들어오게 된다.이 DispatcherServlet
은 자바의 표준 Servlet
을 확장(혹은 상속. extends키워드는 확장이 더 옳은 표현이라고 본다.)한 클래스로 핸들러 매핑 메서드와의 연결과 에러처리, 뷰 렌더링 등 수많은 작업들이 일어나는 곳이다.
아주아주 역사가 깊은(또는 복잡한…) 자바 표준 Servlet을 잘 감싸준 이DispatcherServlet
덕분에 우리는 아래와 같이 간결하게 URL매핑 코드를 만들어줄 수 있다.
@Controller
컨트롤러에서는 @RequestMapping
이라는 어노테이션을 이용해 우리는 URL이나 method등에 따라 처리하는 핸들러메서드를 구현할 수 있다. 컨트롤러를 보면 알겠지만 어노테이션은 가독성이 매우 뛰어나다. 어노테이션을 활용한 코드는 한눈에 해당 메서드가 어떠한 역할을 하는지를 쉽사리 파악할 수 있도록 만들어주며, 코드에 간접적으로 영향을 끼치게 되므로 추가가 비교적 자유롭다.
여기서 한발만 더 나아가 보도록 하자. 권한을 체크하여야 한다던지 로깅을 한다던지와 같은 다양한 부가작업들을 커스텀 어노테이션을 통해서 표기할 수 있다면 가독성있는 코드와 간결함이라는 두마리 토끼를 동시에 잡아낼 수 있을것이다. 특정 페이지에 접속할때마다 시간을 로그에 출력해야 한다는 요구사항이 있는 경우, @AccessLogging
이라는 커스텀 어노테이션을 통해서 이를 구현해보도록 하자.
이를 코드로 정리하면 아래와 같다.
@RestController
DispatcherServlet
에서 요청은 위와 같은 순서로 처리되게 된다. 여기서HandlerInterceptor
는 서블릿의 필터와 유사하게 요청과 응답에 부가적인 로직을 삽입해 줄 수 있도록 해준다. 스프링에서 요청을 할때나 응답을 받을때마다 HandlerInterceptor
가 정의된 순서대로 처리하여 부가적인 작업을 처리하도록 해준다.
HandlerInterceptor
는 총 3개의 메서드를 가지고 있다. 첫번째 preHandle
는 요청이 들어올 경우 수행되며, 두번째 postHandle
은 응답을 할 때 부가적인 로직을, 세번째afterCompletion
는 요청이 전부 종료되었을때 수행되는 메서드이다.
이제 이를 활용하여 요청에 특정 어노테이션이 있는지 체크하고, 있을경우 로깅을 하는 로직을 구현해 보도록 하자. 요청이 들어올 때 마다 어떠한 값을 찍는게 목표이므로,preHandle
이 해당 로직을 구현해야 할 지점으로 볼 수 있다.
위의 구현체에서 preHandle
메서드의 3번째 파라미터로 입력되는 핸들러를 가져올 수 있다. 우리는 지금 HandlerMethod
만을 체크할 것이므로 Object가 해당 타입으로 변환가능한지 확인하여야 한다. 그 다음 타입이 맞다면 변환을 수행한다.
HandlerMethod 객체에서 해당 핸들러의 다양한 속성들을 가져올 수 있다. 어노테이션의 선언여부 또한 알 수 있다. AccessLogging
어노테이션이 있는지 확인한 다음 만약 값이 존재한다면, 로그를 출력하도록 처리하도록 처리할 수 있다.
마지막으로 작성된 HandlerInterceptor
를 추가해 주어야 한다. Spring Boot에서는 다음과 같이 설정이 가능하다.
@Configuration
WebMvcConfigurerAdapter
는 웹과 관련된 설정을 재정의할 수 있는 확장포인트이다. 그리고 해당 설정 컨피그의 addInterceptors
를 이용하여 우리가 정의한 interceptor를 추가할 수 있다. 그리고 서버를 실행시킨 다음 해당 URL을 호출하면 console에 요구사항이였던 시간과 메서드명이 찍히는 모습을 확인할 수 있을 것이다.
2016-11-19 14:53:14.905 INFO 39698 --- [ main] net.chandol.study.Application : Started Application in 6.38 seconds (JVM running for 7.282) 2016-11-19 14:53:24.353 INFO 39698 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet' 2016-11-19 14:53:24.354 INFO 39698 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2016-11-19 14:53:24.382 INFO 39698 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 28 ms methodName : simpleHandler1 accessTime : 2016-11-19T14:53:24.436 methodName : simpleHandler1 accessTime : 2016-11-19T14:53:25.293 methodName : simpleHandler1 accessTime : 2016-11-19T14:53:25.553
'Spring' 카테고리의 다른 글
Spring Scheduling 작동 주기 동적으로 설정하기 (0) | 2016.11.16 |
---|