[Spring Boot] Interceptor

hameeeยท2024๋…„ 1์›” 26์ผ
0

Spring Boot

๋ชฉ๋ก ๋ณด๊ธฐ
20/20

๐Ÿ“ Interceptor

  • org.springframework.web.servlet.HandlerInterceptor ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์ด๋‹ค.
  • HandlerInterceptor ์ธํ„ฐํŽ˜์ด์Šค๋Š” preHandler, postHandler, afterCompletion ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • WebMvcConfigurer๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์—์„œ Interceptor๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.(์—ฌ๊ธฐ์„œ ์ถ”๊ฐ€ํ•  ์ธํ„ฐ์…‰ํ„ฐ, ์ ์šฉ ๊ฒฝ๋กœ, ์ œ์™ธ ๊ฒฝ๋กœ ๋“ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.)
  • ์ฃผ๋กœ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ HTTP ์š”์ฒญ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ€๋กœ์ฑ„์–ด ์ฒ˜๋ฆฌ ์ „, ํ›„, ๋ฐ ์™„๋ฃŒ ํ›„์— ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

๐Ÿ“ Interceptor ์ œ๊ณต ๋ฉ”์„œ๋“œ

  • preHandler()
    • ์‹คํ–‰ ์‹œ์ : ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ์ „(โ‘ก์™€ โ‘ข ์‚ฌ์ด)
    • ๋ฐ˜ํ™˜๊ฐ’
      • true: ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰
      • false: ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ์š”์ฒญ ์ค‘๋‹จ
  • postHandler()
    • ์‹คํ–‰ ์‹œ์ : ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ ํ›„, ๋ทฐ ๋ Œ๋”๋ง ์ „(โ‘ฅ์™€ โ‘ฆ ์‚ฌ์ด)
    • ๋ฐ˜ํ™˜๊ฐ’: ์—†์Œ
  • afterCompletion()
    • ์‹คํ–‰ ์‹œ์ : ํด๋ผ์ด์–ธํŠธ ์‘๋‹ต ์ „์†ก ํ›„(โ‘ง ์ดํ›„)
    • ๋ฐ˜ํ™˜๊ฐ’: ์—†์Œ

์ด๋ฏธ์ง€ ์ถœ์ฒ˜

โ‘  DispatcherServlet์€ ์š”์ฒญ์„ ์ˆ˜์‹ ํ•œ๋‹ค.
โ‘ก DispatcherServlet์€ ์ ์ ˆํ•œ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์„ ํƒํ•˜๋Š” ์ž‘์—…์„ HandlerMapping์—๊ฒŒ ์œ„์ž„ํ•œ๋‹ค. HandlerMapping์€ ์š”์ฒญ๋œ URL์— ๋งคํ•‘๋œ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์„ ํƒํ•˜๊ณ  ์„ ํƒ๋œ ํ•ธ๋“ค๋Ÿฌ ๋ฐ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ DispatcherServlet์— ๋ฐ˜ํ™˜ํ•œ๋‹ค.
โ‘ข DispatcherServlet์€ ์ปจํŠธ๋กค๋Ÿฌ์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์‹คํ–‰ ์ž‘์—…์„ HandlerAdapter์—๊ฒŒ ์œ„์ž„ํ•œ๋‹ค.
โ‘ฃ HandlerAdapter๋Š” ์ปจํŠธ๋กค๋Ÿฌ์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ˜ธ์ถœํ•œ๋‹ค.
โ‘ค ์ปจํŠธ๋กค๋Ÿฌ๋Š” 1๏ธโƒฃ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์‹คํ–‰ํ•˜๊ณ , 2๏ธโƒฃ๊ฒฐ๊ณผ๋ฅผ ๋ชจ๋ธ์— ์„ค์ •ํ•˜๊ณ , 3๏ธโƒฃ๋ทฐ์˜ ๋…ผ๋ฆฌ์  ์ด๋ฆ„(์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๋ฌธ์ž์—ด)์„ HandlerAdapter์— ๋ฐ˜ํ™˜ํ•œ๋‹ค.
โ‘ฅ DispatcherServlet์€ ๋ทฐ์˜ ์ด๋ฆ„์— ํ•ด๋‹นํ•˜๋Š” ๋ทฐ๋ฅผ ์ฐพ์•„์ฃผ๋Š” ์ž‘์—…์„ ViewResolver์—๊ฒŒ ์œ„์ž„ํ•œ๋‹ค. ViewResolver๋Š” ๋ทฐ ์ด๋ฆ„์— ๋งคํ•‘๋œ ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
โ‘ฆ DispatcherServlet์€ ๋ฐ˜ํ™˜๋œ ๋ทฐ์— ๋ Œ๋”๋ง ์ž‘์—…์„ ์œ„์ž„ํ•œ๋‹ค.
โ‘ง ๋ทฐ๋Š” ๋ชจ๋ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๐Ÿ‘‰ Filter์™€ Interceptor์˜ ์ฐจ์ด์ 

  • Filter
    • ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ ๋ ˆ๋ฒจ์—์„œ ๋™์ž‘(Spring MVC์™€๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์—ญ ์ˆ˜์ค€์—์„œ ๋™์ž‘)
    • javax.servlet.Filter ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„
    • ๋ฉ”์„œ๋“œ: doFilter(DispatcherServlet์ด ์š”์ฒญ์„ ์ˆ˜์‹ ํ•˜๊ธฐ ์ „(โ‘  ์ด์ „)์— ์‹คํ–‰)
  • Interceptor
    • Spring MVC์˜ ์ผ๋ถ€๋กœ์„œ ์ปจํŠธ๋กค๋Ÿฌ ๋ ˆ๋ฒจ์—์„œ ๋™์ž‘(Spring Bean์œผ๋กœ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด @Component ์–ด๋…ธํ…Œ์ด์…˜ ํ•„์š”)
    • org.springframework.web.servlet.HandlerInterceptor ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„
    • ๋ฉ”์„œ๋“œ: preHandelr, postHandler, afterCompletion

๐Ÿ‘‰ Filter์™€ Interceptor ์‹คํ–‰ ์ˆœ์„œ ์š”์•ฝ

  • doFilter() -> preHandle() -> ์ปจํŠธ๋กค๋Ÿฌ ์‹คํ–‰ -> postHandle() -> ๋ทฐ ๋ Œ๋”๋ง -> ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต ์ „์†ก -> afterCompletion()

๐Ÿ“ ์˜ˆ์‹œ ์ฝ”๋“œ

1) HandlerInterceptor ๊ตฌํ˜„ ํด๋ž˜์Šค(์ธํ„ฐ์…‰ํ„ฐ ํด๋ž˜์Šค)

  • @Component ์–ด๋…ธํ…Œ์ด์…˜ ํ•„์š”
  • HandlerInterceptor ๊ตฌํ˜„
  • preHandle, postHandler, afterCompletion ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œ
// ๐ŸŸข /src/main/java/com/memo/interceptor/PermissionInterceptor.java

package com.memo.interceptor;

import java.io.IOException;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class PermissionInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(
			HttpServletRequest request, 
			HttpServletResponse response, 
			Object handler) throws IOException {

		String uri = request.getRequestURI();
		
		HttpSession session = request.getSession();
		Integer userId = (Integer)session.getAttribute("userId");
		
		log.info("[@@@@@@@@@@@ preHandle] uri:{}", uri);
		
		// ๋น„๋กœ๊ทธ์ธ && /post => ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™, ์ปจํŠธ๋กค๋Ÿฌ ์ˆ˜ํ–‰ ๋ฐฉ์ง€
		if(userId == null && uri.startsWith("/post")) {
			response.sendRedirect("/user/sign-in-view");
			return false; // ์›๋ž˜ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ ์ปจํŠธ๋กค๋Ÿฌ ์ˆ˜ํ–‰ ์•ˆํ•จ
		} 
		
		// ๋กœ๊ทธ์ธ && /user => ๊ธ€๋ชฉ๋ก ํŽ˜์ด์ง€๋กœ ์ด๋™, ์ปจํŠธ๋กค๋Ÿฌ ์ˆ˜ํ–‰ ๋ฐฉ์ง€
		if(userId != null && uri.startsWith("/user")) {
			response.sendRedirect("/post/post-list-view");
			return false; // ์›๋ž˜ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ ์ปจํŠธ๋กค๋Ÿฌ ์ˆ˜ํ–‰ ์•ˆํ•จ
		}

		return true; // ์ปจํŠธ๋กค๋Ÿฌ ์ˆ˜ํ–‰
	}
	
	@Override
	public void postHandle(
			HttpServletRequest request, 
			HttpServletResponse response, 
			Object handler, 
			ModelAndView mav) {
            
		log.info("[########### postHandle]");
	}
	
	@Override
	public void afterCompletion(
			HttpServletRequest request, 
			HttpServletResponse response, 
			Object handler,
			Exception ex) {
		
		log.info("[$$$$$$$$$$$ afterCompletion]");
	}
	
}

2) WebMvcConfigurer ๊ตฌํ˜„ ํด๋ž˜์Šค(๊ฒฝ๋กœ ์„ค์ • ํด๋ž˜์Šค)

  • @Configuration ์–ด๋…ธํ…Œ์ด์…˜ ํ•„์š”
  • WebMvcConfigurer ๊ตฌํ˜„
  • ๊ตฌํ˜„ํ•œ ์ธํ„ฐ์…‰ํ„ฐ autowired
  • addInterceptors ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œ
// ๐ŸŸข /src/main/java/com/memo/config/WebMvcConfig.java

package com.memo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.memo.interceptor.PermissionInterceptor;

@Configuration // ์„ค์ •์„ ์œ„ํ•œ spring bean
public class WebMvcConfig implements WebMvcConfigurer {

	@Autowired
	private PermissionInterceptor interceptor;
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry
		.addInterceptor(interceptor)
		.addPathPatterns("/**")
		.excludePathPatterns("/static/**", "/error", "/user/sign-out");
	}
	
}

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