๐ Servlet Filter, Spring Intercepter ํน์ง๊ณผ ์ฐจ์ด ์ดํดํ๊ธฐ
๊ฐ์ #
Team.Lifestyle์ด๋ผ๋ GSM์ ํ์๋ค๋ผ๋ฆฌ ๋ชจ์ธ ํ์ด ์๋ค ํํ๋์ค ์จ๋ผ์ธ ์คํฐ๋๋ฅผ ์งํํ๊ฒ ๋์๊ณ
์คํฐ๋ ์ฃผ์ ๋ก ์ด ์ฃผ์ ๋ฅผ ์ ์ ํ๊ฒ ๋์๋ค.
๋ค๋ค ์คํ๋ง ์ํ๋ฆฌํฐ๋ฅผ ๊ณต๋ถํ๋ฉด์ ํํฐ์ ์ธํฐ์ ํฐ์ ๋ํด์๋ ํ๋ฒ์ฉ ๋ค์ด๋ณด์์ ๊ฒ์ด๋ค.
๋์ด ๋ค๋ฅธ๊ฑด ์๊ฒ ์ง๋ง ๋ฌด์์ด ๋ค๋ฅธ์ง ์ ๋๋ก ์ค๋ช ๋ชปํ๋ ๋์ ๋ค๋ฅธ ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ค์ ์ํด
ํ๋ฒ์ ์ ๋ฆฌํด๋ณด๋๋ก ํ๊ฒ ๋ค. ๊ทธ๋ฆฌ๊ณ ํ๋ฒ AOP ๊ด์ ์ผ๋ก๋ ์์๋ณด์
์๋ฐ๋ก ์น ๊ฐ๋ฐ์ ํ๋ค๋ณด๋ฉด, ๊ณตํต์ ์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ ์ ๋ฌด๋ค์ด ๋ง๋ค.
์๋ธ๋ฆฟ ํํฐ (Servelt Filter) #
ํํฐ๋ ๊ฐ๋จํ ๋งํด์ HTTP์์ฒญ๊ณผ ์๋ต์ ๋ณ๊ฒฝ, ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ ์ฝ๋์ด๋ค.
๊ฐ์ฒด์ ํํ๋ก ์กด์ฌํ๋ฉฐ ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์ค๋ ์์ฒญ๊ณผ ์ต์ข ์์ ์ฌ์ด์ ์์นํด ํด๋ผ์ด์ธํธ์ ์์ฒญ ์ ๋ณด๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.
ํํฐ๋ J2EE ํ์ค ์คํ ๊ธฐ๋ฅ์ผ๋ก ๋์คํจ์ฒ ์๋ธ๋ฆฟ(Dispatcher Servlet)์ ์์ฒญ์ด ์ ๋ฌ๋๊ธฐ ์ /ํ์ url ํจํด์ ๋ง๋ ๋ชจ๋ ์์ฒญ์ ๋ํด ๋ถ๊ฐ์์ ์ ์ฒ๋ฆฌํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
๋์คํจ์ฒ ์๋ธ๋ฆฟ์ ์คํ๋ง์ ๊ฐ์ฅ ์๋จ์ ์กด์ฌํ๋ ํ๋ก ํธ ์ปจํธ๋กค๋ฌ์ด๋ฏ๋ก, ํํฐ๋ ์คํ๋ง ๋ฒ์ ๋ฐ์์ ์ฒ๋ฆฌ๋๋ค.
์ฆ, ์คํ๋ง ์ปจํ ์ด๋๊ฐ ์๋๋ผ ํฐ์บฃ๊ณผ ๊ฐ์ ์น ์ปจํ ์ด๋์ ์ํด ๊ด๋ฆฌ๊ฐ ๋๋ ๊ฒ์ด๋ค.(์คํ๋ง ๋น์ผ๋ก๋ ๋ฑ๋ก ๊ฐ๋ฅ)
๋์คํจ์ฒ ์๋ธ๋ฆฟ ์ /ํ์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด๋ค.

ํํฐ์ ํ๋ฆ
HTTP ์์ฒญ -> WAS -> Filter -> Servlet -> Controller
ํํฐ๋ฅผ ์ ์ฉํ๋ฉด ํํฐ๊ฐ ํธ์ถ๋ ํ ๋ค์์ ์๋ธ๋ฆฟ์ด ํธ์ถ๋๋ค.
ํํฐ ์ ํ
HTTP ์์ฒญ -> WAS -> Filter -> Servlet -> Controller // ๋ก๊ทธ์ธ ์ฌ์ฉ์
HTTP ์์ฒญ -> WAS -> Filter(์ ์ ํ์ง ์์ ์์ฒญ์ด๋ผ ์๊ฐํ๋ฉด ์๋ธ๋ฆฟ ํธ์ถ x) //๋น ๋ก๊ทธ์ธ ์ฌ์ฉ์
ํํฐ์์ ์ ์ ํ์ง ์์ ์์ฒญ์ด๋ผ๊ณ ํ๋จ๋๋ฉด ๊ทธ๊ณณ์์ ๋๋ผ ์ ์๋ค.
ํํฐ ์ฒด์ธ
HTTP ์์ฒญ -> WAS -> Filter1 -> Filter2 -> Filter3 -> Servlet -> Controller
ํํฐ๋ ์ด๋ฐ์์ผ๋ก ์ฒด์ด๋์ ํ ์ ์๋ค.
์๋ฅผ ๋ค์ด ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ํํฐ๋ฅผ ์ ์ฉ ํ ๋ก๊ทธ์ธ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ๋ ํํฐ๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
ํํฐ์ ์ธํฐํ์ด์ค, ๋ฉ์๋ #
ํํฐ๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํด์๋ javax.servlet์ Filter ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ผํ๋ฉฐ ์ด๋ ๋ค์ 3๊ฐ์ง ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
init()
doFilter()
destroy()
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
public default void destroy() {}
}
init()
- init๋ฉ์๋๋ ํํฐ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํ์ํค๊ณ ์๋น์ค๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํ ๋ฉ์๋๋ค.
- ์น ์ปจํ ์ด๋๊ฐ 1ํ์ init ๋ฉ์๋๋ฅผ ํธ์ถํด ํํฐ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ๋ฉด ์ดํ ์์ฒญ๋ค์ doFilter๋ฅผ ํตํด ์ฒ๋ฆฌ๋๋ค.
doFilter()
- doFilter๋ url ํจํด์ ๋ง๋ ๋ชจ๋ HTTP ์์ฒญ์ด ๋์คํจ์ฒ ์๋ธ๋ฆฟ์ผ๋ก ์ ๋ฌ๋๊ธฐ์ ์ ์น ์ปจํ ์ด๋์ ์ํด ์คํ๋๋ ๋ฉ์๋๋ค.
- doFilter์ ์ธ์๋ก๋ FilterChain์ด ์๋ค. FilterChain์ doFilter๋ฅผ ํตํด ๋ค์ ๋์์ผ๋ก ์์ฒญ์ ์ ๋ฌํ๊ฒ ๋๋ค.
- chain.doFilter() ์ /ํ์ ์ฐ๋ฆฌ๊ฐ ํ์ํ ์ฒ๋ฆฌ ๊ณผ์ ์ ๋ฃ์ด์ค์ผ๋ก์จ ์ํ๋ ์ฒ๋ฆฌ๋ฅผ ์งํํ ์ ์๋ค.
destroy()
- destroy๋ฉ์๋๋ ํํฐ ๊ฐ์ฒด๋ฅผ ์๋น์ค์์ ์ ๊ฑฐํ๋ฉฐ ์ฌ์ฉํ๋ ์์์ ๋ฐํํ๋ ๋ฉ์๋๋ค.
- ์ด๋ ์น ์ปจํ ์ด๋์ ์ํด 1๋ฒ๋ง ํธ์ถ๋๋ฉฐ ์ดํ์๋ doFilter๊ฐ ์ฌ์ฉ๋์ง ์๋๋ค.
์์ ์ฝ๋ : HTTP ์์ฒญ์ผ๋ก ์ค๋ ์ ์ ์ ์ ๋ณด๋ฅผ ๋ก๊ทธ๋ก ์ฐ๋ ํํฐ๋ฅผ ๋ง๋ค์ด๋ณด์
@Slf4j
public class LogFilter implements Filter {
@Override
public void doFilter(ServletReqeust req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
log.info("Run LogFilter.doFilter()");
// ServletRequest๋ ๊ธฐ๋ฅ์ด ๋ง์ง ์๋ค ๊ทธ๋์ ๋ค์ด์บ์คํ
์ ์ฌ์ฉํ๋ค.
// HTTP ์์ฒญ์ด ์๋ ๊ฒฝ์ฐ๊น์ง ๊ณ ๋ คํด ๋ง๋ ์ธํฐํ์ด์ค๊ธฐ ๋๋ฌธ.
HttpServletRequest request = (HttpServletRequest) req;
String requestURI = request.getRequestURI();
String uuid = UUID.randomUUID().toString();
try{
log.info("๋ก๊ทธํํฐ Request {} , {}",uuid,requestURI);
// ๋ค์ ํํฐ๊ฐ ์์ผ๋ฉด ํธ์ถ ์์ผ๋ฉด ์๋ธ๋ฆฟ ํธ์ถ ์ด ๋ถ๋ถ์ด ์์ผ๋ฉด ๋ค์ ๋จ๊ณ๊ฐ ์งํ์ด ๋์ง ์๋๋ค.
chain.doFilter(request, response);
} catch(Exception e) {
throw e;
} finally{
log.info("๋ก๊ทธํํฐ ์ข
๋ฃ");
}
}
}
UUID.randomUUID().toString(): ์์ฒญ์ ๊ตฌ๋ถ ์ง๊ธฐ ์ํจ์ด๋ค.
Filter๋ฅผ ๋ง๋ค์์ผ๋ฉด FilterRegisterBean์ ์ฌ์ฉํด ํํฐ๋ฅผ ๋น์ผ๋ก ๋ฑ๋กํด์ผํ๋ค.
์ธํฐ์ ํฐ (Interceptor) #
Spring์ด ์ ๊ณตํ๋ ๊ธฐ์ ๋ก์จ, ๋์คํจ์ฒ ์๋ธ๋ฆฟ์ด ์ปจํธ๋กค๋ฌ์ ํธ๋ค๋ฌ(์ฌ์ฉ์๊ฐ ์์ฒญํ url์ ๋ฐ๋ผ ์คํ๋์ด์ผ ํ ๋ฉ์๋, ์ดํ ํธ๋ค๋ฌ)๋ฅผ ํธ์ถํ๊ธฐ ์ ๊ณผ ํ์ ์์ฒญ๊ณผ ์๋ต์ ์ฐธ์กฐํ๊ฑฐ๋ ๊ฐ๊ณตํ ์ ์๋ ์ผ์ข ์ ํํฐ๋ค.
Intercept๋ผ๋ ๋จ์ด๋ '๋์์ฑ๋ค'๋ผ๋ ์๋ฏธ์ด๋ฉฐ ํด๋น ๋จ์ด์ ์๋ฏธ์ ๊ฐ์ด ์ฌ์ฉ์ ์์ฒญ์ ์ํด ์๋ฒ์ ๋ค์ด์จ Request๊ฐ์ฒด๋ฅผ
์ปจํธ๋กค๋ฌ์ ํธ๋ค๋ฌ๋ก ๋๋ฌํ๊ธฐ์ ์ ๋์์ฑ ๊ฐ๋ฐ์๊ฐ ์ํ๋ ์ถ๊ฐ์ ์ธ ์์ ์ ํ ํ ํธ๋ค๋ฌ๋ก ๋ณด๋ผ ์ ์๋๋ก ํด์ฃผ๋๊ฒ์ด ์ธํฐ์ ํฐ๋ค.
์น ์ปจํ ์ด๋์์ ๋์ํ๋ ํํฐ์ ๋ฌ๋ฆฌ ์ธํฐ์ ํฐ๋ ์คํ๋ง ์ปจํ ์คํธ์์ ๋์ํ๋ค.
๋์คํจ์ฒ ์๋ธ๋ฆฟ์ ํธ๋ค๋ฌ ๋งคํ์ ํตํด ์ ์ ํ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฐพ๋๋ก ์์ฒญํ๋๋ฐ ๊ทธ ๊ฒฐ๊ณผ๋ก ์ํ ์ฒด์ธ(Handler ExecutionChain)์ ๋๋ ค์ค๋ค. ๊ทธ๋์ ์ด ์คํ ์ฒด์ธ์ 1๊ฐ ์ด์์ ์ธํฐ์ ํฐ๊ฐ ๋ฑ๋ก๋์ด ์๋ค๋ฉด ์์ฐจ์ ์ผ๋ก ์ธํฐ์ ํฐ๋ค์ ๊ฑฐ์ณ ์ปจํธ๋กค๋ฌ๊ฐ ์คํ๋๋๋ก ํ๊ณ , ์๋ค๋ฉด ๋ฐ๋ก ์ปจํธ๋กค๋ฌ๋ฅผ ์คํ์ํจ๋ค.
์ธํฐ์ ํฐ๋ ์คํ๋ง ์ปจํ ์คํธ๋ด์์ ๋์ํ๋ฏ๋ก ์น ์ปจํ ์คํธ์ ์๋ ํํฐ๋ฅผ ๊ฑฐ์ณ ํ๋ก ํธ์ปจํธ๋กค๋ฌ์ธ ๋์คํจ์ฒ ์๋ธ๋ฆฟ์ด ์์ฒญ์ ๋ฐ์ ํ ๋์ํ๊ฒ ๋๋ค.
์ฌ์ฉํ๋ ์ด์ ?
ํน์ ์ปจํธ๋กค๋ฌ์ ํธ๋ค๋ฌ๊ฐ ์คํ๋๊ธฐ ์ ์ด๋ ํ์ ์ถ๊ฐ์ ์ธ ์์ ์ ์ํด ์ธํฐ์ ํฐ๋ฅผ ์ฌ์ฉํ๋๋ฐ
(์ถ๊ฐ์ ์ธ ์์ ์ผ๋ก๋ ๋ก๊ทธ์ธ์ฒดํฌ, ๊ถํ ์ฒดํฌ ๋ฑ์ด ์๋ค.)
์์๋ฅผ ๋ค์ด๋ณด๊ฒ ๋ค.
์ค์ง ๊ฐ๋ฐ์๋ง ์ฌ์ฉํ ์ ์๋ ๊ด๋ฆฌ์ ์ปจํธ๋กค๋ฌ ํธ๋ค๋ฌ๋ฅผ ์์ฑํ๋ค๊ณ ํด๋ณด์.
๊ฐ๋ฐ์๋ ์ค์ง ๊ด๋ฆฌ์ ๊ณ์ ๋ง ์คํํ ์ ์๋๋ก ํ๊ธฐ ์ํด ํธ๋ค๋ฌ์ ์ ๊ทผํ๋ ์ฌ์ฉ์๊ฐ ๊ด๋ฆฌ์์ธ์ง ํ์ธํ๋ ์ธ์ ์ฒดํฌ ์ฝ๋๋ค์
๊ฐ ํธ๋ค๋ฌ๋ค์๊ฒ ํ๋ํ๋์ฉ ์์ฑํด์ฃผ์ด์ผํ๋ค. ์์ฑํด์ฃผ๋ ํธ๋ค๋ฌ์ ์๊ฐ ๋ง์ฝ ๋ง์์ง๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
1.ย ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น, ์๋ฒ์ ๋ถํ
์ ์ฉํด์ผํ ํธ๋ค๋ฌ ์๋งํผ ์ธ์ ์ฒดํฌ ์ฝ๋๋ค์ ์์ฑํจ์ผ๋ก์จ ๋ฐ๋ณต๋๋ ์ฝ๋๋ค์ด ๋ง์์ ธ์๋ค.
2.์ฝ๋์ ๋๋ฝ์ ๋ํ ๊ฑฑ์
์ฌ๋์ด ์์ฑํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ฝ๊ณผ ๊ฐ์ ์ค์๊ฐ ๋ฐ์ํ ์ ์๋ค. ๋ง์ฝ ํ์์ ๋ณด์ ์ ๊ทผํ๋ ํธ๋ค๋ฌ์ ์ธ์ ์ฒดํฌ๊ฐ ๋๋ฝ๋๋ค๋ฉด?
์์๋งํด๋ ๋์ฐํ๋ค.

์ ๊ทธ๋ฆผ์ ์์๋ฅผ ๋์ํํ ๊ฒ์ด๋ฏ๋ก ์ธํฐ์ ํฐ๊ฐ ์ปจํธ๋กค๋ฌ์๊ฒ ์์ฒญ์ ์์ํ์ง๋ ์๋๋ค.
์ธํฐ์ ํฐ์ ์ธํฐํ์ด์ค,๋ฉ์๋ #
์ธํฐ์ ํฐ๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํด์๋ org.springframework.web.servlet์ HandlerInterceptor ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํ(implements)ํด์ผ ํ๋ฉฐ, ์ด๋ ๋ค์์ 3๊ฐ์ง ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
preHandle()
postHandle()
afterCompletion()
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
preHandle()
- ์ปจํธ๋กค๋ฌ๊ฐ ํธ์ถ๋๊ธฐ ์ ์ ์คํ๋๋ค.
- ์ปจํธ๋กค๋ฌ ์ด์ ์ ์ฒ๋ฆฌํด์ผํ๋ ์ ์ฒ๋ฆฌ ์์ , ์์ฒญ ์ ๋ณด๋ฅผ ๊ฐ๊ณตํ๊ฑฐ๋ ์ถ๊ฐํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉํ ์ ์๋ค.
- preHandle์ 3๋ฒ์งธ ํ๋ผ๋ฏธํฐ์ธ handler ํ๋ผ๋ฏธํฐ๋ ํธ๋ค๋ฌ ๋งคํ์ด ์ฐพ์์ค ์ปจํธ๋กค๋ฌ ๋น์ ๋งคํ๋๋ HandlerMethod๋ผ๋ ์๋ก์ด ํ์ ์ ๊ฐ์ฒด๋ก์จ, @RequestMapping์ด ๋ถ์ ๋ฉ์๋์ ์ ๋ณด๋ฅผ ์ถ์ํํ ๊ฐ์ฒด์ด๋ค
- ์คํ๋์ด์ผ ํ ํธ๋ค๋ฌ์ ๋ํ ์ ๋ณด๋ฅผ ์ธ์๊ฐ์ผ๋ก ๋ฐ๊ธฐ ๋๋ฌธ์ '์๋ธ๋ฆฟ ํํฐ'์ ๋นํด ์ธ๋ฐํ๊ณ ๋ก์ง์ ๊ตฌ์ฑํ ์ ์๋ค.
- ๋ฆฌํด๊ฐ์ด boolean์ด๋ค. ๋ฆฌํด์ true์ผ ๊ฒฝ์ฐ preHandle()์ ์คํํ ํ ํธ๋ค๋ฌ์ ์ ๊ทผํ๋ค
- false์ผ ๊ฒฝ์ฐ ์์ ์ ์ค๋จํ๊ธฐ ๋๋ฌธ์ ์ปจํธ๋กค๋ฌ์ ๋จ์ ์ธํฐ์ ํฐ๊ฐ ์คํ๋์ง ์๋๋ค.
postHandle()
- ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถ๋ ํ์ ์คํ๋๋ค.
- ํธ๋ค๋ฌ๊ฐ ์คํ์ ์๋ฃ๋์์ง๋ง ์์ง ๋ทฐ๊ฐ ์์ฑ๋๊ธฐ ์ด์ ์ ํธ์ถ๋๋ค.
- ModelAndView ํ์ ์ ์ ๋ณด๊ฐ ์ธ์๊ฐ์ผ๋ก ๋ฐ๋๋ค. ๋ฐ๋ผ์ ์ปจํธ๋กค๋ฌ์์ ๋ทฐ ์ ๋ณด๋ฅผ ์ ๋ฌํ๊ธฐ ์ํด ์์ ํ ๋ชจ๋ธ์ ๊ฐ์ฒด์ ์ ๋ณด๋ฅผ ์ฐธ์กฐํ๊ฑฐ๋ ์กฐ์ํ ์ ์๋ค. ์ต๊ทผ์๋ JSONํํ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ RestAPI๊ธฐ๋ฐ์ ์ปจํธ๋กค๋ฌ(@RestController)๋ฅผ ๋ง๋ค๋ฉด์ ์์ฃผ ์ฌ์ฉ๋์ง๋ ์๋๋ค.
- preHandle()์์ false๋ฅผ ๋ฆฌํดํ ๊ฒฝ์ฐ ์คํ๋์ง ์๋๋ค.
- ์ ์ฉ์ค์ธ ์ธํฐ์ ํฐ๊ฐ ์ฌ๋ฌ๊ฐ์ธ ๊ฒฝ์ฐ์๋ preHandle()์ ์ญ์์ผ๋ก ํธ์ถ๋๋ค.
- ๋น๋๊ธฐ์ ์ธ ์์ฒญ์ฒ๋ฆฌ์์๋ ์ฒ๋ฆฌ๋์ง ์๋๋ค.
- ์ปจํธ๋กค๋ฌ ํ์ ๊ณ์ธต์์ ์์ ์ ์งํํ๋ค๊ฐ ์ค๊ฐ์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด postHandle์ ํธ์ถ๋์ง ์๋๋ค.
afterCompletion()
- ๋ชจ๋ View์์ ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๋ ์ผ์ ํฌํจํ ๋ชจ๋ ์์ ์ด ์๋ฃ๋ ํ์ ์คํ๋๋ค.
- ์์ฒญ ์ฒ๋ฆฌ์ค ์ฌ์ฉํ ๋ฆฌ์์ค๋ฅผ ๋ฐํํด์ฃผ๊ธฐ ์ ๋นํ ๋ฉ์๋๋ค.
- preHandle()์์ false๋ฅผ ๋ฆฌํดํ ๊ฒฝ์ฐ ์คํ๋์ง ์๋๋ค.
- ์ ์ฉ์ค์ธ ์ธํฐ์ ํฐ๊ฐ ์ฌ๋ฌ๊ฐ์ธ๊ฒฝ์ฐ preHandle()๋ ์ญ์์ผ๋ก ํธ์ถ๋๋ค.
- ๋น๋๊ธฐ์ ์์ฒญ ์ฒ๋ฆฌ์์ ํธ์ถ๋์ง์๋๋ค.
- postHandle()๊ณผ ๋ฌ๋ฆฌ ์ปจํธ๋กค๋ฌ ํ์ ๊ณ์ธต์์ ์์ ์ ์งํํ๋ค๊ฐ ์ค๊ฐ์ ์์ธ๊ฐ ๋ฐ์ํ๋๋ผ๋ afterCompletion์ ๋ฐ๋์ ํธ์ถ๋๋ค.
HandlerInterceptor์์ ์ ๋ก๊ทธ๋ฅผ ์ฐ๋ ์ธํฐ์ ํฐ๋ฅผ ๊ตฌํํด๋ณด์๋ค.
@Slf4j
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
log.info("preHandle1");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
log.info("postHandle1");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("afterCompletion1");
}
}
์ธํฐ์ ํฐ vs AOP #
์ธํฐ์ ํฐ ๋์ ์ ์ปจํธ๋กค๋ฌ๋ค์ ์ ์ฉํ ๋ถ๊ฐ๊ธฐ๋ฅ์ ์ด๋๋ฐ์ด์ค๋ก ๋ง๋ค์ด AOP๋ฅผ ์ ์ฉํ ์๋ ์๋ค.
ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ค๋ก ์ปจํธ๋กค๋ฌ์ ํธ์ถ ๊ณผ์ ์ ์ ์ฉ๋๋ ๋ถ๊ฐ๊ธฐ๋ฅ๋ค์ ์ธํฐ์ ํฐ๋ฅผ ์ฌ์ฉํ๋ ํธ์ด ๋ซ๋ค.
์ปจํธ๋กค๋ฌ ํ์ ๊ณผ ์คํ ๋ฉ์๋๊ฐ ๋ชจ๋ ์ ๊ฐ๊ฐ์ด๋ผ ํฌ์ธํธ์ปท(์ ์ฉํ ๋ฉ์๋ ์ ๋ณ)์ ์์ฑ์ด ์ด๋ ต๋ค.
์ปจํธ๋กค๋ฌ๋ ํ๋ผ๋ฏธํฐ๋ ๋ฆฌํด ๊ฐ์ด ์ผ์ ํ์ง ์๋ค.
AOP์์๋ HttpServletRequest,Response ๊ฐ์ฒด๋ฅผ ์ป๊ธฐ ์ด๋ ต์ง๋ง ์ธํฐ์ ํฐ๋ ํ๋ผ๋ฏธํฐ๋ก ๋์ด์จ๋ค.
ํํฐ(FIlter) vs ์ธํฐ์ ํฐ(Interceptor) ์ฐจ์ด #
ํํฐ์ ์ธํฐ์ ํฐ๋ ๊ฐ๊ฐ์ด ๊ด๋ฆฌ๋๋ ์ปจํ ์ด๋์ Request/Response์ ์กฐ์ ๊ฐ๋ฅ์ฌ๋ถ๊ฐ ๋ค๋ฅด๊ณ , ๊ทธ์ ๋ฐ๋ผ ์ฉ๋๊ฐ ๋ค๋ฅด๋ค.

์ผ๋ถ์์ย ํํฐ(Filter)๊ฐ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก๋์ง ๋ชปํ๋ฉฐ, ๋น์ ์ฃผ์ ๋ฐ์ ์๋ ์๋ค๊ณ ํ๋๋ฐ, ์ด๋ ์๋ชป๋ ์ค๋ช ์ด๋ค. ์ด๋ ๋งค์ฐ ์๋ ์ ์ด์ผ๊ธฐ์ด๋ฉฐ, ํํฐ๋ ํ์ฌ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก์ด ๊ฐ๋ฅํ๋ฉฐ, ๋ค๋ฅธ ๊ณณ์ ์ฃผ์ ๋๊ฑฐ๋ ๋ค๋ฅธ ๋น์ ์ฃผ์ ๋ฐ์ ์๋ ์๋ค.
Request,Response ๊ฐ์ฒด ์กฐ์ ์ฌ๋ถ
ํํฐ๋ Request,Response๋ฅผ ์กฐ์ํ ์ ์์ง๋ง ์ธํฐ์ ํฐ๋ ์กฐ์ํ ์ ์๋ค.
์ฌ๊ธฐ์ ์กฐ์์ ๋ด๋ถ ์ํ ๋ณ๊ฒฝ์ด ์๋๋ผ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๋ฐ๊ฟ์น๋ค๋ ์๋ฏธ์ด๋ค.
ํํฐ๊ฐ ๋ค์ ํํฐ๋ฅผ ํธ์ถํ๊ธฐ ์ํด์๋ ํํฐ ์ฒด์ด๋์ ํด์ฃผ์ด์ผํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ Request/Response๊ฐ์ฒด๋ฅผ ๋๊ฒจ์ค๋ค.
์ฆ ์ฐ๋ฆฌ๊ฐ ์ํ๋ Request/Response๊ฐ์ฒด๋ฅผ ๋๊ฒจ์ค ์ ์๋ค. NPE(NullPointException)๊ฐ ๋๊ฒ ์ง๋ง null๋ก๋ ๋ฃ์ ์ ์๋๊ฒ์ด๋ค.
public MyFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// ๊ฐ๋ฐ์๊ฐ ๋ค๋ฅธ request์ response๋ฅผ ๋ฃ์ด์ค ์ ์์
chain.doFilter(request, response);
}
}
ํ์ง๋ง ์ธํฐ์ ํฐ๋ ์ฒ๋ฆฌ ๊ณผ์ ์ด ํํฐ์๋ ๋ค๋ฅด๋ค.
๋์คํจ์ฒ ์๋ธ๋ฆฟ์ด ์ฌ๋ฌ ์ธํฐ์ ํฐ ๋ชฉ๋ก์ ๊ฐ์ง๊ณ ์๊ณ ๋ฐ๋ณต๋ฌธ์ผ๋ก ์์ฐจ์ ์ผ๋ก ์คํ์ํจ๋ค.
๊ทธ๋ฆฌ๊ณ true๋ฅผ ๋ฐํํด์ผ ๋ค์ ์ธํฐ์ ํฐ๊ฐ ์คํ๋๊ฑฐ๋ ์ปจํธ๋กค๋ฌ๋ก ์์ฒญ์ด ์ ๋ฌ๋๋ฉฐ false๋ ์์ฒญ์ด ์ค๋จ๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก ์ฐ๋ฆฌ๊ฐ ๋ค๋ฅธ Request/Response ๊ฐ์ฒด๋ฅผ ๋๊ฒจ์ค ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฌํ ๋ถ๋ถ์ด ํํฐ์ ํ์คํ ๋ค๋ฅธ์ ์ด๋ค.
public class MyInterceptor implements HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// Request/Response๋ฅผ ๊ต์ฒดํ ์ ์๊ณ boolean ๊ฐ๋ง ๋ฐํํ ์ ์๋ค.
return true;
}
}
ํํฐ(Filter)์ ์ธํฐ์ ํฐ(Interceptor)์ ์ฉ๋ ๋ฐ ์์ #
ํํฐ์ ์ฉ๋ ๋ฐ ์์
- ๊ณตํต๋ ๋ณด์ ๋ฐ ์ธ์ฆ/์ธ๊ฐ ๊ด๋ จ ์์
- ๋ชจ๋ ์์ฒญ์ ๋ํ ๋ก๊น ๊ณผ ๊ฒ์ฌ
- ์ด๋ฏธ์ง/๋ฐ์ดํฐ ์์ถ ๋ฐ ๋ฌธ์์ด ์ธ์ฝ๋ฉ
- ์คํ๋ง๊ณผ ๋ถ๋ฆฌ๋์ด์ผ ํ๋ ๊ธฐ๋ฅ๋ค
ํํฐ์์๋ ๊ธฐ๋ณธ์ ์ผ๋กย ์คํ๋ง๊ณผ ๋ฌด๊ดํ๊ฒ ์ ์ญ์ ์ผ๋ก ์ฒ๋ฆฌํด์ผํ๋ ์์ ๋ค์ ์ฒ๋ฆฌํ ์ ์๋ค.
๋ํ์ ์ผ๋ก ๋ณด์ ๊ณตํต ์์ ์ด ์๊ณ ํํฐ๋ ์ธํฐ์ ํฐ๋ณด๋ค ์๋จ์์ ๋์ํ๋ฏ๋ก ์ ์ญ์ ์ผ๋ก ํด์ผํ๋ ๋ณด์๊ฒ์ฌ(XSS ๋ฐฉ์ด ๋ฑ)๋ฅผ ํ์ฌ ์ฌ๋ฐ๋ฅธ ์์ฒญ์ด ์๋ ๊ฒฝ์ฐ์ ์ฐจ๋จ์ ํ ์ ์๋ค. ๊ทธ๋ฌ๋ฉด ์คํ๋ง ์ปจํ ์ด๋๊น์ง ์์ฒญ์ด ์ ๋ฌ๋์ง ๋ชปํ๊ณ ์ฐจ๋จ๋๋ฏ๋ก ์์ ์ฑ์ ๋์ผ ์ ์๋ค.
๋ํ ์ด๋ฏธ์ง ํํฐ๋ ์ด๋ฏธ์ง๋ ๋ฐ์ดํฐ ์์ถ์ด๋ ๋ฌธ์์ด ์ธ์ฝ๋ฉ๊ณผ ๊ฐ์ดย ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ์ ์ ๋นํ๋ค. ํํฐ๋ ๋ค์ ์ฒด์ธ์ผ๋ก ๋๊ธฐ๋ ServletRequest/ServletResponse ๊ฐ์ฒด๋ฅผ ์กฐ์ํ ์ ์๋ค๋ ์ ์์ ์ธํฐ์ ํฐ๋ณด๋ค ํจ์ฌ ๊ฐ๋ ฅํ ๊ธฐ์ ์ด๋ค.
์ธํฐ์ ํฐ์ ์ฉ๋ ๋ฐ ์์
- ์ธ๋ถ์ ์ธ ๋ณด์ ๋ฐ ์ธ์ฆ/์ธ๊ฐ ๊ณตํต ์์
- API ํธ์ถ์ ๋ํ ๋ก๊น ๋๋ ๊ฒ์ฌ
- ์ปจํธ๋กค๋ฌ๋ก ๋๊ฒจ์ฃผ๋ ๋ฐ์ดํฐ๊ฐ๊ณต
์ธํฐ์ ํฐ๋ย ํด๋ผ์ด์ธํธ์ ์์ฒญ๊ณผ ๊ด๋ จ๋์ด ์ ์ญ์ ์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ๋ ์์ ๋ค์ ์ฒ๋ฆฌํ ์ ์๋ค.
๋ํ์ ์ผ๋ก ์ธ๋ถ์ ์ผ๋ก ์ ์ฉํด์ผ ํ๋ ์ธ์ฆ๊ณผ ์ธ๊ฐ์ ๊ฐ์ด ํด๋ผ์ด์ธํธ ์์ฒญ๊ณผ ๊ด๋ จ๋ ์์ ๋ฑ์ด ์๋ค.
์๋ฅผ ๋ค์ด ํน์ ๊ทธ๋ฃน์ ์ฌ์ฉ์๋ ์ด๋ค ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ด๋ฌํ ์์ ๋ค์ ์ปจํธ๋กค๋ฌ๋ก ๋์ด๊ฐ๊ธฐ ์ ์ ๊ฒ์ฌํด์ผ ํ๋ฏ๋ก ์ธํฐ์ ํฐ๊ฐ ์ฒ๋ฆฌํ๊ธฐ ์ ํฉํ๋ค.
๋ํ ์ธํฐ์ ํฐ๋ ํํฐ์ ๋ค๋ฅด๊ฒ HttpServletRequest/HttpServletResponse ๋ฑ๊ณผ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์ ๊ณต๋ฐ์ผ๋ฏ๋ก
๊ฐ์ฒด ์์ฒด๋ฅผ ์กฐ์ํ ์๋ ์๋ค. ๋์ ํด๋น ๊ฐ์ฒด์ ๋ด๋ถ์ ์ผ๋ก ๊ฐ๋ ์ฑ์ง์ ์กฐ์ํ ์ ์์ผ๋ฏ๋กย ์ปจํธ๋กค๋ฌ๋ก ๋๊ฒจ์ฃผ๊ธฐ ์ํ ์ ๋ณด๋ฅผ ๊ฐ๊ณตํ๊ธฐ์๋ ์ฉ์ดํ๋ค. ์๋ฅผ ๋ค์ด์ ์ฌ์ฉ์ ID๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์กฐํํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ HttpServletRequest์ ๋ฃ์ด์ค ์ ์๋ค.
๊ทธ ์ธ์๋ ์ฐ๋ฆฌ๋ ๋ค์ํ ๋ชฉ์ ์ผ๋ก api ํธ์ถ์ ๋ํ ์ ๋ณด๋ค์ ๊ธฐ๋กํด์ผ ํ ์ ์๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ์ HttpServletRequest, Response๋ฅผ ์ ๊ณตํด์ฃผ๋ ์ธํฐ์ ํฐ๋ ํด๋ผ์ด์ธํธ์ IP๋ ์์ฒญ ์ ๋ณด๋ค์ ํฌํจํด ๊ธฐ๋กํ๊ธฐ ์ฉ์ดํ๋ค.
๋ํ์ ์ผ๋ก ํํฐ(Filter)๋ฅผ ์ธ์ฆ๊ณผ ์ธ๊ฐ์ ์ฌ์ฉํ๋ ๋๊ตฌ๋ก๋ SpringSecurity๊ฐ ์๋ค. SpringSecurity์ ํน์ง ์ค ํ๋๋ Spring MVC์ ์ข ์์ ์ด์ง ์๋ค๋ ๊ฒ์ธ๋ฐ, ์ด๋ฌํ ์ด์ ๋ก๋ ํํฐ ๊ธฐ๋ฐ์ผ๋ก ์ธ์ฆ/์ธ๊ฐ ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.