๐Ÿ“š ํ•„ํ„ฐ(Filter) vs ์ธํ„ฐ์…‰ํ„ฐ(Interceptor)

CodeByHanยท2025๋…„ 10์›” 10์ผ

์Šคํ”„๋ง

๋ชฉ๋ก ๋ณด๊ธฐ
30/33

๐Ÿ“Œ ํ•„ํ„ฐ(Filter)

ํ•„ํ„ฐ(Filter)๋Š” ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ(Dispatcher Servlet)์œผ๋กœ ์š”์ฒญ์ด ์ „๋‹ฌ๋˜๊ธฐ ์ „ / ํ›„์—, ํŠน์ • URL ํŒจํ„ด์— ๋งž๋Š” ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ๋ถ€๊ฐ€์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

๊ทธ๋ฆผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ํ•„ํ„ฐ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ๊ด€๋ฆฌ ๋ฒ”์œ„ ๋ฐ–์—์„œ ๋™์ž‘ํ•˜๋ฉฐ, ํ†ฐ์บฃ(Tomcat)๊ณผ ๊ฐ™์€ ์›น ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ๊ด€๋ฆฌ๋œ๋‹ค.

์ฆ‰, ์š”์ฒญ์ด ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์ด๋‚˜ ์‘๋‹ต์ด ๋ฐ˜ํ™˜๋œ ํ›„์— ์ฒ˜๋ฆฌ๋˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

๋ฉ”์„œ๋“œํ˜ธ์ถœ ์‹œ์ ์ฃผ์š” ์—ญํ• 
init(FilterConfig filterConfig)ํ•„ํ„ฐ๊ฐ€ ์ดˆ๊ธฐํ™”๋  ๋•Œ ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋ฆฌ์†Œ์Šค ๋กœ๋“œ, ์„ค์ •๊ฐ’ ์ดˆ๊ธฐํ™” ๋“ฑ
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)์š”์ฒญ์ด ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ์œผ๋กœ ์ „๋‹ฌ๋˜๊ธฐ ์ „๊ณผ ์‘๋‹ต์ด ๋Œ์•„๊ฐ€๊ธฐ ์ „์š”์ฒญ ์ „/ํ›„ ์ฒ˜๋ฆฌ, ๋‹ค์Œ ํ•„ํ„ฐ ๋˜๋Š” ์„œ๋ธ”๋ฆฟ ํ˜ธ์ถœ (chain.doFilter)
destroy()ํ•„ํ„ฐ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ, ์ข…๋ฃŒ ์ž‘์—… ๋“ฑ

์ž๋ฐ”์—์„œ ํ•„ํ„ฐ ์‚ฌ์šฉ ์˜ˆ์‹œ

import javax.servlet.*;
import java.io.IOException;

public class CustomFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // ํ•„ํ„ฐ๊ฐ€ ์ดˆ๊ธฐํ™”๋  ๋•Œ ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋จ (์˜ˆ: ๋ฆฌ์†Œ์Šค ๋กœ๋“œ)
        System.out.println("CustomFilter ์ดˆ๊ธฐํ™”");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // ์š”์ฒญ์ด ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ์œผ๋กœ ์ „๋‹ฌ๋˜๊ธฐ ์ „ ์ˆ˜ํ–‰ํ•  ์ž‘์—…
        System.out.println("์š”์ฒญ ์ „์— ์‹คํ–‰๋˜๋Š” ํ•„ํ„ฐ ๋กœ์ง");

        // ๋‹ค์Œ ํ•„ํ„ฐ ๋˜๋Š” ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ์œผ๋กœ ์š”์ฒญ์„ ์ „๋‹ฌ
        chain.doFilter(request, response);

        // ์‘๋‹ต์ด ํด๋ผ์ด์–ธํŠธ๋กœ ๋Œ์•„๊ฐ€๊ธฐ ์ „ ์ˆ˜ํ–‰ํ•  ์ž‘์—…
        System.out.println("์‘๋‹ต ํ›„์— ์‹คํ–‰๋˜๋Š” ํ•„ํ„ฐ ๋กœ์ง");
    }

    @Override
    public void destroy() {
        // ํ•„ํ„ฐ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ํ˜ธ์ถœ๋จ (์˜ˆ: ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ)
        System.out.println("CustomFilter ์ข…๋ฃŒ");
    }
}

๐Ÿ“Œ ์ธํ„ฐ์…‰ํ„ฐ(Interceptor)

์ธํ„ฐ์…‰ํ„ฐ(Interceptor)๋Š” ์Šคํ”„๋ง(Spring)์ด ์ œ๊ณตํ•˜๋Š” ๊ธฐ์ˆ ๋กœ, ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ(Dispatcher Servlet)์ด ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „๊ณผ ํ›„์— ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฐธ์กฐํ•˜๊ฑฐ๋‚˜ ๊ฐ€๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

์ฆ‰, ์ธํ„ฐ์…‰ํ„ฐ๋Š” ์Šคํ”„๋ง ์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์—์„œ ๋™์ž‘ํ•˜๋ฉฐ, ์Šคํ”„๋ง์ด ๊ด€๋ฆฌํ•˜๋Š” ๋นˆ(Bean)์œผ๋กœ์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง๊ณผ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๋™๋œ๋‹ค.

๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ(Dispatcher Servlet)์€ ํ•ธ๋“ค๋Ÿฌ ๋งคํ•‘(Handler Mapping)์„ ํ†ตํ•ด ์š”์ฒญ์— ์•Œ๋งž์€ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํƒ์ƒ‰ํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋กœ ์‹คํ–‰ ์ฒด์ธ(HandlerExecutionChain)์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
์ด ์‹คํ–‰ ์ฒด์ธ์—๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์ธํ„ฐ์…‰ํ„ฐ(Interceptor)๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ,
๋“ฑ๋ก๋œ ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ ์ˆœ์ฐจ์ ์œผ๋กœ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ๊ฑฐ์นœ ํ›„ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
๋ฐ˜๋Œ€๋กœ ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ์—†๋‹ค๋ฉด, ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ์€ ๊ณง๋ฐ”๋กœ ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

๋ฉ”์„œ๋“œ์‹คํ–‰ ์‹œ์ ์ฃผ์š” ์—ญํ• 
preHandle()์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ์ „(before)์š”์ฒญ ์ „ ์ฒ˜๋ฆฌ (๋กœ๊ทธ, ์ธ์ฆ, ๊ถŒํ•œ ๊ฒ€์‚ฌ ๋“ฑ)
postHandle()์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ํ›„, View ๋ Œ๋”๋ง ์ „์ปจํŠธ๋กค๋Ÿฌ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๊ฐ€๊ณต, ๋ชจ๋ธ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋“ฑ
afterCompletion()View ๋ Œ๋”๋ง ์™„๋ฃŒ ํ›„๋ฆฌ์†Œ์Šค ์ •๋ฆฌ, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ๊น… ๋“ฑ

์ž๋ฐ”์—์„œ ์ธํ„ฐ์…‰ํ„ฐ ์‚ฌ์šฉ ์˜ˆ์‹œ

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CustomInterceptor implements HandlerInterceptor {

    // ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ์ „
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("preHandle: ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ์ „ ๋กœ์ง");
        return true; // false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ดํ›„ ์ฒด์ธ(๋‹ค์Œ ์ธํ„ฐ์…‰ํ„ฐ/์ปจํŠธ๋กค๋Ÿฌ)์œผ๋กœ ์ง„ํ–‰๋˜์ง€ ์•Š์Œ
    }

    // ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ํ›„, View ๋ Œ๋”๋ง ์ „
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                           Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle: ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ํ›„ ๋กœ์ง");
    }

    // View ๋ Œ๋”๋ง ์™„๋ฃŒ ํ›„ (์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ์—๋„ ํ˜ธ์ถœ)
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                                Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion: ์š”์ฒญ ์ฒ˜๋ฆฌ ์™„๋ฃŒ ํ›„ ๋กœ์ง");
    }
}

ํ•„ํ„ฐ(Filter), ์ธํ„ฐ์…‰ํ„ฐ(Interceptor) ์šฉ๋„

๋‚ด๊ฐ€ ์ด๊ฑธ ํ•„ํ„ฐ์™€ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์ •๋ฆฌํ•ด์•ผ๊ฒ ๋‹ค๊ณ  ๋งˆ์Œ ๋จน์€ ์ด์œ ๋‹ค. ํ•„ํ„ฐ์™€ ์ธํ„ฐ์…‰ํ„ฐ์˜ ์ฐจ์ด์ ์„ ์–ด๋А์ •๋„ ์•Œ๊ณ  ์žˆ์—ˆ์ง€๋งŒ ๋ณดํ†ต ์–ด๋–ค ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜๋‹ค.

ํ•„ํ„ฐ

  • ๊ณตํ†ต๋œ ๋ณด์•ˆ ๋ฐ ์ธ์ฆ/์ธ๊ฐ€ ๊ด€๋ จ ์ž‘์—…
  • ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•œ ๋กœ๊น… ๋˜๋Š” ๊ฐ์‚ฌ
  • ์ด๋ฏธ์ง€/๋ฐ์ดํ„ฐ ์••์ถ• ๋ฐ ๋ฌธ์ž์—ด ์ธ์ฝ”๋”ฉ
  • Spring๊ณผ ๋ถ„๋ฆฌ๋˜์–ด์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅ

ํ•„ํ„ฐ(Filter)๋Š” ์Šคํ”„๋ง๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ „์—ญ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…์— ์ ํ•ฉํ•˜๋‹ค.
๋Œ€ํ‘œ์ ์œผ๋กœ ๋ณด์•ˆ ๊ณตํ†ต ์ž‘์—…์ด ์žˆ์œผ๋ฉฐ, ์ธํ„ฐ์…‰ํ„ฐ๋ณด๋‹ค ์•ž๋‹จ์—์„œ ๋™์ž‘ํ•˜๋ฏ€๋กœ XSS ๋ฐฉ์–ด ๋“ฑ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ์š”์ฒญ์„ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊นŒ์ง€ ์š”์ฒญ์ด ์ „๋‹ฌ๋˜์ง€ ์•Š์•„ ์•ˆ์ •์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

๋˜ํ•œ ์ด๋ฏธ์ง€๋‚˜ ๋ฐ์ดํ„ฐ ์••์ถ•, ๋ฌธ์ž์—ด ์ธ์ฝ”๋”ฉ ๋“ฑ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „๋ฐ˜์— ๊ฑธ์นœ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ์—๋„ ์ ํ•ฉํ•˜๋‹ค.
Filter๋Š” ๋‹ค์Œ ์ฒด์ธ์œผ๋กœ ๋„˜๊ธฐ๋Š” ServletRequest์™€ ServletResponse ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์กฐ์ž‘ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, Interceptor๋ณด๋‹ค ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

ํ•„ํ„ฐ(Filter)๋ฅผ ์ธ์ฆ, ์ธ๊ฐ€์— ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ์—๋Š” ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ(Spring Security)๊ฐ€ ์žˆ๋‹ค. ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ(Spring Security)๋Š” Spring MVC์— ์ข…์†์ ์ด์ง€ ์•Š๋‹ค.

์ธํ„ฐ์…‰ํ„ฐ

  • ์„ธ๋ถ€์ ์ธ ๋ณด์•ˆ ๋ฐ ์ธ์ฆ/์ธ๊ฐ€ ๊ณตํ†ต ์ž‘์—…
  • API ํ˜ธ์ถœ์— ๋Œ€ํ•œ ๋กœ๊น… ๋˜๋Š” ๊ฐ์‚ฌ
  • Controller๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ์ •๋ณด(๋ฐ์ดํ„ฐ)์˜ ๊ฐ€๊ณต

์ธํ„ฐ์…‰ํ„ฐ๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ๊ณผ ๊ด€๋ จ๋œ ์ „์—ญ์ ์ธ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ ํ•ฉํ•˜๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ๊ทธ๋ฃน์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๊ธฐ๋Šฅ์„ ์ œํ•œํ•˜๋Š” ์ธ์ฆ์ด๋‚˜ ์ธ๊ฐ€ ์ž‘์—…์€ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์š”์ฒญ์ด ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ๊ฒ€์‚ฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ธํ„ฐ์…‰ํ„ฐ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋˜ํ•œ ์ธํ„ฐ์…‰ํ„ฐ๋Š” HttpServletRequest์™€ HttpServletResponse ๊ฐ์ฒด๋ฅผ ์ œ๊ณต๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ์ฒด ์ž์ฒด๋ฅผ ๋ฐ”๊พธ๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋‚ด๋ถ€ ๊ฐ’์€ ์กฐ์ž‘ ๊ฐ€๋Šฅํ•˜์—ฌ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๊ธฐ์— ์šฉ์ดํ•˜๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž์˜ ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์กฐํšŒํ•œ ์ •๋ณด๋ฅผ ์š”์ฒญ ๊ฐ์ฒด์— ๋‹ด์•„ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ์™ธ์—๋„ API ํ˜ธ์ถœ์— ๋Œ€ํ•œ ๋กœ๊น…์ด๋‚˜ ํด๋ผ์ด์–ธํŠธ ์ •๋ณด ๊ธฐ๋ก ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์—๋„ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ์˜ IP, ์š”์ฒญ URL, ํ—ค๋” ์ •๋ณด ๋“ฑ์„ ๊ธฐ๋กํ•˜๋Š” ๋ฐ ๋งค์šฐ ํŽธ๋ฆฌํ•˜๋‹ค.

์ฆ‰, ์ธํ„ฐ์…‰ํ„ฐ๋Š” ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ์ „ํ›„์— ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ํ™œ์šฉํ•ด ์„ธ๋ฐ€ํ•œ ์ œ์–ด, ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต, ๋กœ๊น…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋‹ค.

์ฐธ๊ณ 

profile
๋…ธ๋ ฅ์€ ๋ฐฐ์‹ ํ•˜์ง€ ์•Š์•„ ๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€