๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŒฑSpring Boot

[Spring]Filter์™€ Interceptor, ๊ณตํ†ต ์—…๋ฌด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋น„์Šทํ•˜์ง€๋งŒ ๋‹ค๋ฅธ

by ๋นˆ์„ฑ_ 2021. 12. 31.
๋ฐ˜์‘ํ˜•

Intro

์˜ค๋Š˜์€ Filter์™€ Interceptor์˜ ์ด์•ผ๊ธฐ์ž…๋‹ˆ๋‹ค. Spring์˜ ์ค‘์š”ํ•œ ์š”์†Œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—…๋ฌด ํŠน์„ฑ ๋•Œ๋ฌธ์ธ์ง€ ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ž์ฃผ ์ ‘ํ•˜์งˆ ๋ชปํ•ด ๋งค๋ฒˆ ๊นŒ๋จน๋Š” ๋ถ€๋ถ„์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

...์ƒ๊ฐํ•ด๋ณด๋ฉด ์ ‘ํ–ˆ๋˜ ๊ฒŒ ์†์— ๊ผฝ์„ ๋งŒํผ ๋ณด์ง€ ๋ชปํ•œ ๊ฑฐ ๊ฐ™๋„ค์š”.

Filter & Interceptor

Filter์™€ Interceptor๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์—๋Š” ์ค‘๋ณต ์ฝ”๋“œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์›น ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๋ณด๋ฉด ๊ณตํ†ต ์—…๋ฌด(ํ˜น์€ ๊ณตํ†ต ๊ด€์‹ฌ์‚ฌ)์— ๊ด€๋ จ๋œ ๊ฒƒ๋“ค์ด ์ƒ๊น๋‹ˆ๋‹ค. ์ด๋ฅผํ…Œ๋ฉด ๋กœ๊ทธ์ธ ๊ด€๋ จ ์ฒ˜๋ฆฌ๋‚˜ ๊ถŒํ•œ ํ™•์ธ๊ณผ ๊ฐ™์€ ๋ถ€๋ถ„์ด์ฃ . ์ด๋Ÿฐ ๊ณตํ†ต ์—…๋ฌด๋Š” ๋‹ค์ˆ˜์˜ ํŽ˜์ด์ง€(ํ˜น์€ ์š”์ฒญ)์— ๋˜‘๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ์ƒ๊ธฐ๋Š”๊ฑฐ์ฃ .

์ด๋Ÿฐ ๊ณตํ†ต ์—…๋ฌด๋“ค์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ๋ฐ”๋กœ Filter์™€ Interceptor์ž…๋‹ˆ๋‹ค.

**AOP๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฑด ๋‹ค์Œ ๊ธ€์—์„œ

Filter

Filter, ์ •ํ™•ํ•˜๊ฒŒ๋Š” Servlet Filter๋Š” Servlet ์ปจํ…Œ์ด๋„ˆ์™€ Servlet ์‚ฌ์ด๋ฅผ ์˜ค๊ฐ€๋Š” ์š”์ฒญ๊ณผ ์‘๋‹ต์— ์ถ”๊ฐ€๋กœ ๋ถ€๊ฐ€ ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

https://docs.oracle.com/cd/A97329_03/web.902/a95878/filters.htm

 

์กฐ๊ธˆ ์˜ค๋ž˜๋œ ๋ฌธ์„œ์ง€๋งŒ ์ฐธ๊ณ ์šฉ์œผ๋กœ ์ ํ•ฉํ•œ ๊ฑฐ ๊ฐ™์•„์„œ ๊ฐ€์ ธ์™€๋ดค์Šต๋‹ˆ๋‹ค. (Oracle์ด๋‹ˆ๊นŒ ๊ดœ์ฐฎ์•„!)

๋˜ํ•œ Filter๋Š” J2EE(Java 2 Enterprise Edition)์˜ ํ‘œ์ค€ ์ŠคํŽ™ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.(์œ„์—์„œ ์ฐธ๊ณ ํ•œ ๋ฌธ์„œ์˜ ํƒ€์ดํ‹€๋„ ‘Oracle9iAS Containers for J2EE Servlet Developer’s Guide’์ž…๋‹ˆ๋‹ค.)

์ฆ‰, Filter๋Š” Spring๋งŒ์˜ ๊ธฐ๋Šฅ์ด ์•„๋‹Œ Web ์ปจํ…Œ์ด๋„ˆ(ํ˜น์€ Servlet ์ปจํ…Œ์ด๋„ˆ)์—์„œ๋„ ๋™์ž‘ ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Šฅ์ด๋ผ๋Š” ์ ์ด์ฃ . ๊ทธ๋ฆฌ๊ณ  ์ด ๋ถ€๋ถ„์ด Interceptor์™€ Filter๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ค‘์š”ํ•œ ๊ตฌ๋ถ„์ ์ด ๋ฉ๋‹ˆ๋‹ค.

Filter ๊ตฌํ˜„

Filter๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” javax.servlet์˜ Filter ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ implements ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.(org.springframework.boot:spring-boot-starter-web ์˜์กด์„ฑ ์ถ”๊ฐ€ํ•˜์‹œ๋ฉด ์žˆ์Šต๋‹ˆ๋‹ค.)

Filter ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์•„๋ž˜์˜ 3๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

package javax.servlet;

import java.io.IOException;

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

Filter๋ฅผ ์„œ๋น„์Šค์— ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. init ๋ฉ”์„œ๋“œ๋Š” web ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

 

โ—ฝdoFilter

FilterChain์„ ํ†ตํ•ด ์š”์ฒญ/์‘๋‹ต์ด ์ „๋‹ฌ๋  ๋•Œ๋งˆ๋‹ค ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋œ FilterChain์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค ์ง„ํ–‰ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

โ—ฝdestroy

Filter์— ์„œ๋น„์Šค๊ฐ€ ์ค‘๋‹จ๋˜๊ณ  ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. web ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ํ˜ธ์ถœ๋˜๊ณ  ๊ทธ ํ›„์—๋Š” ํ•ด๋‹น Filter ์ธ์Šคํ„ด์Šค์˜ doFilter ๋ฉ”์„œ๋“œ๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Interceptor

Interceptor๋Š” ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•ด์„œ ์ถ”๊ฐ€๋กœ ๋ถ€๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. Filter์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•˜์ฃ . ํ•˜์ง€๋งŒ Filter์™€ ๋‹ฌ๋ฆฌ Interceptor๋Š” Spring์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. Filter์˜ ๊ฒฝ์šฐ์—๋Š” javax.servlet ํŒจํ‚ค์ง€ ์•„๋ž˜์— ์œ„์น˜ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, Interceptor๋Š” org.springframework.web.servlet ์•„๋ž˜์— ์œ„์น˜ํ•˜๊ณ  ์žˆ์ฃ .

๋•Œ๋ฌธ์— ๋‘˜์˜ ์‹คํ–‰ ์œ„์น˜๋Š” ์ฐจ์ด๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฑธ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Interceptor ๊ตฌํ˜„

Filter๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ Filter ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•ด์•ผ ํ–ˆ๋‹ค๋ฉด Interceptor์˜ ๊ฒฝ์šฐ์—๋Š” HandlerInterceptor๋ฅผ implements ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. HandlerInterceptor๋Š” 3๊ฐœ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

package org.springframework.web.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;

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

HandlerMapping์ด ์ ์ ˆํ•œ ํ•ธ๋“ค๋Ÿฌ(ํ˜น์€ ์ปจํŠธ๋กค๋Ÿฌ) ๊ฐ์ฒด๋ฅผ ๊ฒฐ์ •ํ•œ ํ›„ ๊ทธ๋ฆฌ๊ณ  ์•„์ง HandlerAdapter๊ฐ€ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ Handler์—๋Š” HandlerMapping์ด ๊ฒฐ์ •ํ•œ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋งคํ•‘๋œ HandlerMethod๊ฐ€ ๋‹ด๊ฒจ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ preHandle์˜ return type์€ Booolean์ž…๋‹ˆ๋‹ค. true๊ฐ€ ๋ฆฌํ„ด๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰์ด ๋˜์ง€๋งŒ, false๋ผ๋ฉด ์ดํ›„์˜ ์ž‘์—…์ด ์ง„ํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

โ—ฝpostHandle

HandlerAdapter๊ฐ€ ์‹ค์ œ๋กœ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•œ ํ›„(ํ˜น์€ Dispatcher Servlet์ด ๋ทฐ๋ฅผ ๋žœ๋”๋งํ•˜๊ธฐ ์ „)์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ฃผ์–ด์ง€๋Š” ModelAndView๋ฅผ ํ†ตํ•ด ๋ทฐ์— ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

โ—ฝafterCompletion

์š”์ฒญ ์ฒ˜๋ฆฌ ์™„๋ฃŒ ํ›„, ์ฆ‰ ๋ทฐ๋ฅผ ๋žœ๋”๋งํ•œ ํ›„ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

ํŠน์ดํ•œ ์ ์€ ํ•ธ๋“ค๋Ÿฌ ์‹คํ–‰ ์ค‘์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒ๋˜์–ด๋„ afterCompletion์€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.(postHandle์€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

Filter vs Interceptor

Filter์™€ Interceptor๋Š” ๊ฒฐ๊ตญ ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•ด์„œ ์ถ”๊ฐ€๋กœ ๋ถ€๊ฐ€ ์ž‘์—…์„ ์ง„ํ–‰ํ•œ๋‹ค๋ผ๋Š” ์ธก๋ฉด์—์„œ ๋˜‘๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์„ธ๋ถ€์ ์œผ๋ก  ์กฐ๊ธˆ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

Filter๋Š” doFilter ํ•˜๋‚˜๋งŒ ์ œ๊ณต๋˜๊ณ , Interceptor์—์„œ๋Š” ์ง„ํ–‰ ๋‹จ๊ณ„์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ pre, post, after๋กœ ์„ธ๋ถ„ํ™”๋œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ฃ .

ํ•˜์ง€๋งŒ Filter์™€ Interceptor์˜ ์ฐจ์ด์ ์„ ์กฐ๊ธˆ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋Š๋ผ๋ ค๋ฉด ๋‘˜์˜ ์‹คํ–‰ ์œ„์น˜๋ฅผ ๋ˆˆ์—ฌ๊ฒจ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

โ—ฝFilter

๋Š” web ์ปจํ…Œ์ด๋„ˆ ์˜์—ญ์—์„œ Dispatcher Servlet ์•ž์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด ๋ณด์•ˆ์ด๋‚˜ ๋กœ๊ทธ์ธ ๊ด€๋ จ ๊ณตํ†ต ์—…๋ฌด๋Š” Filter๊ฐ€ Interceptor๋ณด๋‹ค ๋” ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ธ์ฆ๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๋ฅผ ํ•œ ๋‹จ๊ณ„๋ผ๋„ ๋ฐ–(์•ž)์—์„œ ๊ฑธ๋Ÿฌ๋‚ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ Filter๋Š” Servlet(Dispatcher Servlet)์— ๋„์ฐฉํ•˜๊ธฐ ์ „์— ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Servlet ๋ฐ”๊ฟ”์น˜๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

โ—ฝInterceptor

๋Š” Spring ์˜์—ญ์—์„œ Dispatcher Servlet ๋’ค์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์•ž์„œ ์–˜๊ธฐํ–ˆ๋˜ ๋กœ๊ทธ์ธ ๊ด€๋ จ ๊ณตํ†ต ์—…๋ฌด์™€ ๋น„์Šทํ•˜์ง€๋งŒ ์กฐ๊ธˆ ๋‹ค๋ฅธ ๊ถŒํ•œ ๊ด€๋ จ ์—…๋ฌด๋Š” Filter๋ณด๋‹จ Interceptor๊ฐ€ ๋” ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๊ถŒํ•œ์— ๋”ฐ๋ผ ํ™”๋ฉด์— ๋…ธ์ถœ๋˜๋Š” ํ•ญ๋ชฉ์„ ๋‹ค๋ฅด๊ฒŒ ํ•˜๊ธฐ์—๋Š” Interceptor์˜ postHandle์ด ์ ํ•ฉํ•˜์ฃ .

๋˜ํ•œ ๊ฐ ๊ถŒํ•œ์— ๋”ฐ๋ฅธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ Spring ์˜์—ญ์—์„œ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ด€๋ฆฌ๊ฐ€ ์‰ฌ์›Œ์ง€๋Š” ์ธก๋ฉด๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ถŒํ•œ ๊ด€๋ จ ์—…๋ฌด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋งŒ์•ฝ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์ „์—ญ(๊ณตํ†ต)์œผ๋กœ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Interceptor๊ฐ€ ์œ ์šฉํ•˜๊ฒ ์ฃ .

Ending

Filter์™€ Interceptor. ์ฐจ์ด์ ์ด ์žˆ๊ธด ํ•˜์ง€๋งŒ ํฌ์ง„ ์•Š์Šต๋‹ˆ๋‹ค. ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ์„œ๋Š” ๋ฌด์—‡์„ ์จ๋„ ๋ฌด๋ฐฉํ•œ ๊ฒฝ์šฐ๋„ ์žˆ์„ ๊ฑฐ๋ผ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์–ด๋Š ๋•Œ์—๋Š” ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์กฐ๊ธˆ ๋” ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋•Œ๊ฐ€ ์˜ค๋ฉด ์ œ๊ฐ€ ์ด ๊ธ€์„ ์ž‘์„ฑํ•˜๋ฉฐ ์–ป์—ˆ๋˜ ๊ฒƒ๋“ค์ด ์กฐ๊ธˆ์ด๋ผ๋„ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

 

(์ด ๊ธ€์—์„œ ํ™œ์šฉํ–ˆ๋˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” ์ด๊ณณ์—์„œ ํ™•์ธ ๊ฐ€๋Šฅํ•˜์‹ญ๋‹ˆ๋‹ค.)

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€