응집도 λ†’μ΄λŠ” Intercepter

2023. 3. 29. 14:45ㆍSpring

μ½”λ“œμ˜ 흐름을 μœ„ν•΄ μ›λž˜ ν•΄λ‹Ή Controller의 μ£ΌκΈ°λŠ₯ μ œμ™Έν•˜κ³  λ‹€λ₯Έ 일듀을 ν•˜κ³  μžˆλŠ” κ²½μš°κ°€ 있음

μ „μ²˜λ¦¬, ν›„μ²˜λ¦¬λΌ 함.  > 응집도 떨어짐.

곡톡적인 μ „μ²˜λ¦¬ ν›„μ²˜λ¦¬λ₯Ό λ”°λ‘œ λΉΌμ„œ μ²˜λ¦¬ν•΄ 응집도λ₯Ό 높일 수 μžˆλ‹€.

κ·Έλ•Œ AOP, intercepter, filter 등을 μ‚¬μš©ν•œλ‹€.

 

Intercepter

응집도λ₯Ό 높이기 μœ„ν•΄ 인터셉터λ₯Ό ν™œμš© ν•œλ‹€.
인터셉터λ₯Ό μ‚¬μš©ν•˜λ©΄ 반볡적인 λΆˆν•„μš”ν•œ 일듀을 인터셉터가 λŒ€μ‹  처리.
μ–΄λ–€ μž‘μ—…μ„ 인터셉터가 μˆ˜ν–‰ν•  μ§€ 섀정을 ν•˜λŠ” 클래슀λ₯Ό λ§Œλ“€μ–΄μ•Ό 함.
νŠΉμ • λ©”μ†Œλ“œκ°€ 싀행될 λ•Œ μž‘μ—…ν•΄μ•Ό ν•˜λŠ” μΈν„°μ…‰ν„°μ˜ 클래슀λ₯Ό λ§Œλ“€κ³  preHandle, postHandle을 κ΅¬ν˜„ν–ˆλ‹€λ©΄
κ΅¬ν˜„ν•œ κΈ°λŠ₯을 μ‹€ν–‰μ‹œν‚€κΈ° μœ„ν•΄μ„œλŠ” μ•„λž˜μ²˜λŸΌ 인터셉터 μ„€μ • 클래슀λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•œλ‹€.
인터셉터 μ„€μ • ν΄λž˜μŠ€λŠ” λ°˜λ“œμ‹œ 'WebMvcConfigurer'λΌλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ„œ λ§Œλ“ λ‹€.

test html 3개 μƒμ„±ν•˜μ—¬ νŽ˜μ΄μ§€ μ΄λ™ν•˜κ²Œ μ„€μ •.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
t1νŽ˜μ΄μ§€<br>
<a href="/test1/t2">t2νŽ˜μ΄μ§€λ‘œ 이동</a>
</body>
</html>

-

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
t2νŽ˜μ΄μ§€<br>
<a href="/test1/t3">t3νŽ˜μ΄μ§€λ‘œ 이동</a>
</body>
</html>

-

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
t3νŽ˜μ΄μ§€
</body>
</html>

controller μž‘μ„±

package com.study.shop.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test1")
public class TestController {
	
	@GetMapping("/t1")
	public String t1() {
		System.out.println("μ „μ²˜λ¦¬ μž‘μ—… μ‹€ν–‰");
		System.out.println("t1 λ©”μ†Œλ“œ μž‘μ—… μ‹€ν–‰");
		return "t1";
	}
	
	@GetMapping("/t2")
	public String t2() {
		System.out.println("μ „μ²˜λ¦¬ μž‘μ—… μ‹€ν–‰");
		System.out.println("t2 λ©”μ†Œλ“œ μž‘μ—… μ‹€ν–‰");
		return "t2";
	}
	
	@GetMapping("/t3")
	public String t3() {
		System.out.println("μ „μ²˜λ¦¬ μž‘μ—… μ‹€ν–‰");
		System.out.println("t3 λ©”μ†Œλ“œ μž‘μ—… μ‹€ν–‰");
		return "t3";
	}
}

클래슀 TestIntercepter1, IntercepterConfig 생성

각각 μ•„λž˜ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„

 

TestIntercepter1 : μ–΄λ–€ κΈ°λŠ₯을 ν•  μ§€ μ •μ˜ν•˜λŠ” 클래슀

HandlerInterceptor κ΅¬ν˜„.

μ˜€λ²„λΌμ΄λ”©

package com.study.shop.intercepter;

import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class TestIntercepter1 implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle() λ©”μ†Œλ“œ μ‹€ν–‰~");
		
		return true;
	}
	
}

 

IntercepterConfig : μš°λ¦¬κ°€ λ§Œλ“  인터셉터λ₯Ό μ–Έμ œ μ“Έ μ§€ μ„€μ •ν•˜λŠ” 클래슀

섀정을 μœ„ν•΄ WebMvcConfigurer κ΅¬ν˜„.

μ˜€λ²„λΌμ΄λ”©

package com.study.shop.intercepter;

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


@Configuration          //Config : μ„€μ • μž‘μ—…ν•˜λŠ” ν΄λž˜μŠ€μ— λΆ™μ—¬μ€Œ.
public class IntercepterConfig implements WebMvcConfigurer{

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
								//객체 생성
		registry.addInterceptor(new TestIntercepter1())
				.addPathPatterns("/test1/t1")
				.addPathPatterns("/test1/t2"); //t1,t2둜 갈 λ•Œ TestIntercepter1의 preHandle() λ©”μ†Œλ“œκ°€ 계속 μ‹€ν–‰ 됨.
	}

νŽ˜μ΄μ§€ μ΄λ™ν•˜λ©΄ preHandle() λ©”μ†Œλ“œ 싀행됨.

μ½˜μ†”μ„ 보면 νŠΉμ • λ©”μ†Œλ“œκ°€ μ‹€ν–‰λ˜κΈ° 전에 preHandle() λ©”μ†Œλ“œ 싀행됨.

preHandle은 κ²€λ¬Έμ†Œλ₯Ό λ©”μ†Œλ“œ μ•ž(pre)에 μ„€μ •ν•œ 것.

postHandle() λ©”μ†Œλ“œ μ‹€ν–‰

μ½˜μ†”μ„ 보면 νŠΉμ • λ©”μ†Œλ“œκ°€ μ‹€ν–‰λ˜κΈ° 전에 postHandle() λ©”μ†Œλ“œ 싀행됨.

postHandle은 κ²€λ¬Έμ†Œλ₯Ό λ©”μ†Œλ“œ 뒀에 μ„€μ •ν•œ 것.

public class TestIntercepter1 implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle() λ©”μ†Œλ“œ μ‹€ν–‰~");
		
		return true;
		
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		System.out.println("postHandle() λ©”μ†Œλ“œ μ‹€ν–‰~");
	}
	
}

 

μ—¬λŸ¬κ°œμ˜ 인터셉터도 μ‚¬μš© κ°€λŠ₯.

인터셉터 κ΄€λ ¨ κΈ°λŠ₯ ν΄λž˜μŠ€λŠ” μ—¬λŸ¬κ°œ μƒμ„±ν•˜κ³  IntercepterConfig μ„€μ • ν΄λž˜μŠ€λŠ” ν•˜λ‚˜λ‘œ μž‘μ—…

TestIntercepter2 클래슀 μƒμ„±ν•˜μ—¬ HandlerInterceptor κ΅¬ν˜„

preHandle, postHandle μ˜€λ²„λΌμ΄λ”©

package com.study.shop.intercepter;

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

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class TestIntercepter2 implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("λ‘λ²ˆμ§Έ 인터셉터 preHandle μ‹€ν–‰");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("λ‘λ²ˆμ§Έ 인터셉터 postHandle μ‹€ν–‰");

	}
}

IntercepterConfig에 μ–Έμ œ κΈ°λŠ₯ μ‹€ν–‰ν•  μ§€ μ§€μ •.

package com.study.shop.intercepter;

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


@Configuration //ν΄λž˜μŠ€μ— λŒ€ν•œ 객체 + μ„€μ • νŒŒμΌμž„μ„ κ°œλ°œμžμ—κ²Œ μΈμ‹μ‹œμΌœμ£ΌλŠ” μ–΄λ…Έν…Œμ΄μ…˜
public class IntercepterConfig implements WebMvcConfigurer{
	
	//ν•΄λ‹Ή λ©”μ†Œλ“œμ—μ„œ μš°λ¦¬κ°€ λ§Œλ“  인터셉터 클래슀의 κΈ°λŠ₯을 μ–Έμ œ μ‹€ν–‰ν•  μ§€ μ§€μ •
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		
		registry.addInterceptor(new TestIntercepter2())
				.addPathPatterns("/**/**"); //λͺ¨λ“  컨트둀러 λͺ¨λ“  λ©”μ†Œλ“œμ— 적용
		
		
		//TestIntercepter1 인터셉터 클래슀의 κΈ°λŠ₯을 μ‚¬μš©ν•˜κ² λ‹€.
								//객체 생성
		registry.addInterceptor(new TestIntercepter1())
				//각각의 λ©”μ†Œλ“œμ— μ§€μ •
				.addPathPatterns("/test1/t1")
				.addPathPatterns("/test1/t2") //t1,t2둜 갈 λ•Œ TestIntercepter1의 preHandle() λ©”μ†Œλ“œκ°€ 계속 μ‹€ν–‰ 됨.
				.addPathPatterns("/test1/t3");
                
               	 		//이 μ™Έμ˜ λ©”μ†Œλ“œ μ–Έμ œ μ‹€ν–‰ν•  μ§€ μ§€μ •ν•˜λŠ” 법
                		//μœ„ 각각의 λ©”μ†Œλ“œ μ§€μ •κ³Ό 같은 μ½”λ“œ
				.addPathPatterns("/test/t1", "/test1/t2", "/test1/t3") // ,둜 λ‚˜μ—΄ κ°€λŠ₯
				
				//ν•˜λ‚˜μ˜ μ»¨νŠΈλ‘€λŸ¬μ—μ„œ λͺ¨λ“  λ§€μ†Œλ“œμ— μ μš©ν•˜λŠ” 방법
				.addPathPatterns("/test1/**") ///test1/**에 μžˆλŠ” λͺ¨λ“  λ©”μ†Œλ“œλΌλŠ” 의미
				
				//νŠΉμ • λ©”μ†Œλ“œλ§Œ μ œμ™Έν•˜κ³  싢을 λ•Œ
				.addPathPatterns("/test1/**")
				.excludePathPatterns("/test1/t3") //λͺ¨λ“  λ©”μ†Œλ“œμ— λ‹€ μ μš©ν•˜μ§€λ§Œ t3 μ œμ™Έ. μ œμ™Έλ„ ,둜 λ‚˜μ—΄ κ°€λŠ₯
				
				//νŠΉμ • 단어가 λ“€μ–΄κ°„ λ©”μ†Œλ“œλ§Œ μ‹€ν–‰
				.addPathPatterns("/test1/*List") //test1 컨트둀러 μ•ˆμ— url νŒ¨ν„΄μ΄ /~List둜 λλ‚˜λŠ” λ©”μ†Œλ“œλ§Œ μ‹€ν–‰
                
	}
}

 

μ½˜μ†”μ°½μ„ 확인해보면 인터셉터가 μ—¬λŸ¬κ°œμ—¬λ„ 잘 μž‘λ™ν•¨.

**μ°Έκ³ 

ν•˜λ‚˜μ˜ μ»¨νŠΈλ‘€λŸ¬μ—μ„œ λͺ¨λ“  λ§€μ†Œλ“œμ— μ μš©ν•˜λŠ” 방법
.addPathPatterns("/test1/**") ///test1/**에 μžˆλŠ” λͺ¨λ“  λ©”μ†Œλ“œλΌλŠ” μ˜λ―Έ

νŠΉμ • λ©”μ†Œλ“œλ§Œ μ œμ™Έν•˜κ³  싢을 λ•Œ
.addPathPatterns("/test1/**")
.excludePathPatterns("/test1/t3") //λͺ¨λ“  λ©”μ†Œλ“œμ— λ‹€ μ μš©ν•˜μ§€λ§Œ t3 μ œμ™Έ. μ œμ™Έλ„ ,둜 λ‚˜μ—΄ κ°€λŠ₯

νŠΉμ • 단어가 λ“€μ–΄κ°„ λ©”μ†Œλ“œλ§Œ μ‹€ν–‰
.addPathPatterns("/test1/*List") //test1 컨트둀러 μ•ˆμ— url νŒ¨ν„΄μ΄ /~List둜 λλ‚˜λŠ” λ©”μ†Œλ“œλ§Œ μ‹€ν–‰

 

μΈν„°μ…‰ν„°λ‘œ 데이터 λ„˜κΈ°κ³  λ°›μ•„μ„œ νŽ˜μ΄μ§€λ₯Ό λ‹€λ₯΄κ²Œ 컨트둀 κ°€λŠ₯

preHandle()둜 controller κ°€κΈ° 전에 κ²€λ¬Έμ†Œμ—μ„œ νŽ˜μ΄μ§€ λ‹€λ₯΄κ²Œ 보낼 수 μžˆλ‹€.

if문으둜 쑰건에 따라 νŽ˜μ΄μ§€ λ‹€λ₯΄κ²Œ 이동.

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle() λ©”μ†Œλ“œ μ‹€ν–‰~");
		
		String name = request.getParameter("name");
		String age = request.getParameter("age");
		
		System.out.println(name);
		System.out.println(age);
		
		//쑰건에 따라 νŽ˜μ΄μ§€ λ‹€λ₯΄κ²Œ 이동
		if(name.equals("java")) {
			response.sendRedirect("/test1/t3");
			return false;
		}
		
		return true;
		//return true > μ›λž˜ κ°€λ €λ˜ λ©”μ†Œλ“œλ‘œ μ§„μž… (λŒ€λΆ€λΆ„ true)
		//return false > μ›λž˜ κ°€λ €λ˜ λ©”μ†Œλ“œλ‘œμ˜ μ§„μž…μ„ λ§‰μ•„μ€Œ.
		
	}

컨트둀러 λ‹€ μ‹€ν–‰λ˜λ©΄ postHandle() 싀행됨.

postHandle()은 html κ°€κΈ° 전에 데이터 더 μΆ”κ°€ν•΄μ„œ κ°€μ Έκ°ˆ 수 μžˆλ‹€.

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		System.out.println("postHandle() λ©”μ†Œλ“œ μ‹€ν–‰~");
		
		//postHandleμ—λŠ” ModelAndView λ§€κ°œλ³€μˆ˜κ°€ 있음 (데이터 λ„˜κΈΈ λ•Œ μ‚¬μš© κ°€λŠ₯, νŽ˜μ΄μ§€ 이동도 κ°€λŠ₯)
		modelAndView.addObject("addr", "μšΈμ‚°μ‹œ");
	}

htmlμ—μ„œ 데이터 뽑아보면

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
t2νŽ˜μ΄μ§€<br>						<!-- postHandleμ—μ„œ μ „λ‹¬ν•œ 데이터 -->
λ„˜μ–΄μ˜¨ 데이터 : [[${name}]], [[${age}]], [[${addr}]] <br>
<a href="/test1/t3">t3νŽ˜μ΄μ§€λ‘œ 이동</a>
</body>
</html>

μ•„λž˜μ²˜λŸΌ 데이터 잘 λ°›μ•„μ˜΄.