2021. 12. 20. 19:51ใBack-End ์์ ์ค/Spring Framework
์๋ ํ์ธ์? ์ฃผ๋ํ๋ ์ ๋๋ค.
์ค๋์ ์ ๋ชฉ์ ์ด๊ฑฐํ ๊ฒ๋ค์ ๋ํด ํ๋ฒ ์์๋ณด๋ ๊ฒ์ด์์.
์ฐ๋ฆฌ๊ฐ WEB์ ๋ง๋ค ๋, ์ธ์ฆ์ด๋, ํ์ผ ์ ๋ก๋ ๋ฑ์ ํ ๋ ํ์ํ ๊ฐ๋ ์ผ๋ก ์ด๋ค ์์ผ๋ก ์์ฒญ์ ๋ฐ์๋๋ฆฌ๋์ง ์์์ผ ํ๋ ๋ถ๋ถ์ด๋ผ ์ ๋ฆฌ๋ฅผ ํด ๋ณด์์ต๋๋ค.
๊ทธ๋ผ ๋ฐ๋ก ์์ ํด ๋ณผ๊ฒ์!
๐ Interceptor, Servlet Filter
Spring Filter์ Intercptor๋ ์ด๋ค ์ฐจ์ด์ ์ด ์์๊น์?
Filter๋ Servlet Container์ ์ด ์ ์ ๊ณตํต์ ์ผ๋ก ์ฒ๋ฆฌํด์ผ ๋๋ ๋ถ๋ถ์ ์ฒ๋ฆฌํ ์ ์๋ ๊ฒ์ด๊ณ , Interceptor๋ AOP์ฒ๋ผ ํน์ ์์ ์ ๊ฐ๋ก์ฑ๊ธฐ ํ์ฌ ์ด๋ค ํ์๋ฅผ ํ ์ ์๋๋ก ํ๋ ๊ฒ์ด์์.
Spring ๋๋ Spring Boot ํ๋ ์์ํฌ๋ก Web Application์ ๊ฐ๋ฐํ๋ค ๋ณด๋ฉด ์๋์ ๊ฐ์ ์๊ตฌ์ฌํญ์ด ์๊ธฐ๊ธฐ ๋ง๋ จ์ธ ๊ฒ์ด์์.
1. ํน์ URL ์ง์
์ Login(์ธ๊ฐ)๋ ์ด์ฉ์๋ง ์ ๊ทผ ๊ฐ๋ฅ
2. ํน์ URL ์ง์
์ JWT์ ๊ฐ์ Token๊ฐ ๊ฒ์ฌ
3. ํน์ URL ์ง์
์ ๊ณ์ ์ ๊ถํ์ ๋ฐ๋ผ ์ ๊ทผ ํ์ฉ ๋ฐ ์ฐจ๋จ(์ธ๊ฐ)
์ด ๋ถ๋ถ์ View(Front End)์์๋ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
์ธํฐ์ ํฐ๋ ๋ฌด์ธ๊ฐ๋ฅผ ์งํํ๊ธฐ ์ ํน์ ์์ ์ ์ํํ ๋ ์ฌ์ฉํ๋ ๊ฒ์ด์์.
JAVA WEB Programming์์๋ ์ด๋ฐ ์์ ์ ํ๋ ๊ธฐ์ ๋ก Servlet Filter, Interceptor, AOP๋ฑ์ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด์์.
์์ ์ฌ์ง์ Spring Request Life Cycle์ ๋์ํํ ์๋ฃ์ธ ๊ฒ์ด์์.
์ฌ์ง์ ๋ณด๋ฉด ์ด์ฉ์์ ์์ฒญ ๋ค์ Filter์ DispatcherServlet์ด ๋ณด์ด๋ ๊ฒ์ด์์.
Interceptor๋ Dispatcher Servlet ๋ค์ Handler ์์ญ์์ ์์ฒญ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๋ ์น๊ตฌ ์ธ ๊ฒ์ด์์.
Servlet Filter์ ๊ฒฝ์ฐ J2EE์ ํ์ค ์คํ์ ์ ์๋์ด ์์ง๋ง, Interceptor๋ Spring ํ๋ ์์ํฌ์์ ์์ฒด ์ ๊ณตํ๋ ๊ธฐ๋ฅ ์ด๋๋๋ค.
1. Contoller์ ๋ค์ด์ค๋ HttpRequest์ ์๋ตํ๋ HttpResponse ๊ฐ์ ๊ฐ๋ก์ฑ์ด ์ฒ๋ฆฌ๋ฅผ ํ๋ ์ญํ
2. ๊ด๋ฆฌ์๋ง ์ ๊ทผํ ์ ์๋ ๊ด๋ฆฌ์ ์ธ์ฆ์ ์ฉ๋๋ก ๋ง์ด ํ์ฉ
3. Filter๋ DispatcherServlet์ด ์คํ๋๊ธฐ ์ ์ ํธ์ถ๋๋, Interceptor๋ DispatcherServlet์ด ์คํ๋ ๋ค ํธ์ถ
4. Filter๋ web.xml์์ ๊ด๋ฆฌํ๊ณ , Interceptor๋ spring-servlet.xml์์ ๊ด๋ฆฌ
Servlet Filter๋ Dispatcher Servlet ์๋จ์์ ๋ค์ด์ค๋ ์์ฒญ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๊ณ , Dispatcher Servle ์ ์ ํธ์ถ๋๊ธฐ ๋๋ฌธ์ Spring๊ณผ ๋ฌด๊ดํ ์์ ๋ค์ ์ฒ๋ฆฌ ํ ์ ์๋ ๊ฒ์ด์์.
์ด์ฉ์ ์์ฒญ(Request) -> Servlet Filter -> Dispatcher Servlet -> Interceptor -> Controller
๐ฝ Filter, Interceptor, AOP
๐ฆ ๊ธฐ๋ฅ๋ณ ์์น
Filter์ Interceptor๋ ์์ ๊ทธ๋ฆผ์์ ๋์ค๋ ์์น์ ์์ด์.
AOP๋ ์์ ์์น์ ์๋ค๊ณ ๋ณผ ์ ์์ด์.
๐ฆ Filter
Filter๋ Web Application(์น ์ ํ๋ฆฌ์ผ์ด์
)์ ๋ฑ๋กํด์. ์ฆ, Request Thread๊ฐ Servlet Container์ ๋์ฐฉํ๊ธฐ ์ ์ ์ํ ๋๋ต๋๋ค. Filter๋ ์ด์ฉ์์ ์์ฒญ ์ ๋ณด์ ๋ํ ๊ฒ์ฆ์ ํ ์ ์๊ณ , ํ์์ ๋ฐ๋ผ Data๋ฅผ ์ถ๊ฐํ๊ฑฐ๋, ๋ณ์กฐํ ์ ์๋๋ก ํด ์ฃผ๋ ์ญํ ์ ํด์.
์๋ต ์ ๋ณด์ ๋ํ ๋ณ๊ฒฝ๋ ๋น์ฐํ ๊ฐ๋ฅํ๋ต๋๋ค.
์ฃผ๋ก ์ ์ญ์ ์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ๋ ์ธ์ฝ๋ฉ, ๋ณด์ ๊ด๋ จ๋ ์ผ์ ์ด๊ฒ์ ํตํด ์ํํ๋ค๊ณ ๋ณผ ์ ์์ด์.
Filter ์ฌ์ฉ ์์
โ ์ค๋ฅ ์ฒ๋ฆฌ ๊ธฐ๋ฅ
โ ์ธ์ฝ๋ฉ ์ฒ๋ฆฌ ๊ธฐ๋ฅ
โ ์น ๋ณด์ ๊ด๋ จ ๊ธฐ๋ฅ
โ Data ์์ถ ๋ฐ ๋ณํ ๊ธฐ๋ฅ
โ ์์ฒญ, ์๋ต์ ๋ํ Loging
โ Login ์ฌ๋ถ ํ์ธ ๋ฐ ๊ถํ ๊ฒ์ฌ์ ๊ฐ์ ์ธ์ฆ, ์ธ๊ฐ ๊ธฐ๋ฅ
Filter Method
โ init() : Filter ์ธ์คํด์ค ์ด๊ธฐํ
โ doFilter() - ์ /ํ ์ฒ๋ฆฌ
โ destroy() : Filter ์ธ์คํด์ค ์ข
๋ฃ
Filet ๊ตฌํ ์์
โ Filter ๊ตฌํ
โ doFilter() ์ฌ์ ์
โ init(), destroy()๋ Default Method์ด๊ธฐ ๋๋ฌธ์ ํ์์ ๋ฐ๋ผ ๊ตฌํ ์ฆ, ํ์ ์ฌํญ ์๋
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import lombok.extern.log4j.Log4j2;
@Slf4j
public class JunyHarangFilter implements Filter {
private final String value;
public JunyHarangFilter(String value) {
this.value = value;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("==========\t" + value + " init filter");
}
@Override
public void destroy() {
log.info("==========\t" + value + " destroy filter");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("==========\t" + value + " before doFilter");
chain.doFilter(request, response);
log.info("==========\t" + value + " after doFilter");
}
}
WebMvcConfiguration Class
โ Spring Boot์์๋ web.xml์ด ์๊ธฐ ๋๋ฌธ์ FilterRegistrationBean์ ์ ์ํ์ฌ Filter๋ฅผ ๋ฑ๋ก
โ Filter๊ฐ ์ฒ๋ฆฌํ Path ์ง์
โ WebMvcConfigurer ์ธํฐํ์ด์ค ์์๊ณผ๋ ๋ฌด๊ด
import junyhararang.in.action.filters.BlogFilter;
import junyhararang.in.action.interceptor.BlogHandlerInterceptor;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
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 WebMvcConfiguration implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new BlogFilter(BlogFilter.class.getSimpleName()));
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new BlogHandlerInterceptor())
.addPathPatterns("/**");
}
}
๐ฆ Interceptor
์ธํฐ์
ํฐ๋ Spring Context์ ๋ฑ๋กํด์.
Servlet Container๋ฅผ ์ง๋ ๋ค Controller์ ์์ฒญ์ด ์ ๋ฌ๋๊ธฐ ์ง์ ๊ณผ ์งํ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ๋ด๋นํ๋ ์น๊ตฌ์์.
Spring Context ์์ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ Bean ๊ฐ์ฒด์ ์ ๊ทผํ ์ ์๋ต๋๋ค.
์ฌ๋ฌ ๊ฐ์ ์ธํฐ์
ํฐ๋ฅผ ์ฌ์ฉํ ์ ์๊ณ , Session ์ฒ๋ฆฌ, Login ์ฒ๋ฆฌ, ๊ถํ ์ฒ๋ฆฌ, Program ์คํ ์๊ฐ ๊ณ์ฐ๋ฑ์ ์ํํ ์ ์์ด์.
Filter์ ๋ค๋ฅด๊ฒ handlerMethod Parameter๋ฅผ ์ด์ฉํ์ฌ AOP์ ๊ฐ์ ๊ธฐ๋ฅ ์ํ๋ ๊ฐ๋ฅํ๋ต๋๋ค.
์ธํฐ์
ํฐ Method
โ preHandler() - Controller ์คํ๋๊ธฐ ์ ์์
์ฒ๋ฆฌ
โ postHandler() - Controller ์คํ ๋ค View Page Randering ์ ์์
์ฒ๋ฆฌ
โ afterCompletion() - View Page Randering ๋ค ์์
์ฒ๋ฆฌ
์ธํฐ์
ํฐ ๊ตฌํ ์์
โ HandlerInterceptor Interface ๊ตฌํ์ฒด
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Slf4j
public class JunyHarangHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("==========\tinterceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("==========\tinterceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("==========\tinterceptor afterCompletion");
}
}
WebMvcConfiguration Class
โ WebMvcConfigurer Interface ๊ตฌํ
โ addInterceptors() ์ฌ ๊ตฌํ์ ํตํด ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ตฌํํ Interceptor ๋ฑ๋ก
โ Interceptor ์ฒ๋ฆฌ Path ์ง์
import junyharang.in.action.filters.JunyHarangFilter;
import junyharang.in.action.interceptor.BlogHandlerInterceptor;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
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 WebMvcConfiguration implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new BlogFilter(BlogFilter.class.getSimpleName()));
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new BlogHandlerInterceptor())
.addPathPatterns("/**");
}
}
๐ฆ AOP(Aspect Oriented Programming)
๋น์ฆ๋์ค ๋ก์ง ์ํ์ ์์ด ์ค๋ณต๋๋ Code๋ฅผ ์ค์ด๊ธฐ ์ํ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ด์์.
๋น์ฆ๋์ค ๋ก์ง์ ํน์ ์์ ์ ๋ฐ๋ผ๋ณด๊ณ , ํด๋น ์์ ์ด ์ํ๋๋ ์๊ฐ์ ๊ฐ๋ก์ฑ์ด ์ , ํ ๊ธฐ๋ฅ์ ์ฒ๋ฆฌ ํ๋ต๋๋ค.
์ฃผ๋ก Loging, ํธ๋์ญ์
์ฒ๋ฆฌ, Exception ์ฒ๋ฆฌ ๊ฐ์ ๊ธฐ๋ฅ์ ๋ด๋นํ๊ฒ ๋์.
AOP ๊ธฐ๋ฅ์ ๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค๋ ์ ์ ์์ผ๋ฉด ์๋์.
AOP ๊ตฌํ ์์
โ Service Bean์ด ์ํํ๋ Method ๋์ ์์ ์์ ์ ๊ฐ๋ก์ฑ์ด ์ , ํ ๋์ ์ํ
โ Controller Bean์ด ์ํํ๋ Method ๋์ ์์ ์์ ์ ๊ฐ๋ก์ฑ์ด ์ , ํ ๋์ ์ํ
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Slf4j
@Aspect
@Component
public class JunyHarangAop {
@Around("execution(* blog.in.action.service.BlogService.*(..))")
public Object aroundServiceFoo(ProceedingJoinPoint pjp) throws Throwable {
log.info("==========\taround service before foo");
Object result = pjp.proceed();
log.info("==========\taround service after foo");
return result;
}
@Around("execution(* blog.in.action.controller.BlogController.*(..))")
public Object aroundControllerFoo(ProceedingJoinPoint pjp) throws Throwable {
log.info("==========\taround controller before foo");
Object result = pjp.proceed();
log.info("==========\taround controller after foo");
return result;
}
}
๐ Resource Handler
1. Servlet Container๊ฐ ์ ๊ณตํ๋ DefaultServlet์ผ๋ก Resource ์์ญ์ ์กด์ฌํ๋ ํ์ผ(/Images, /css, /js, /html ๋ฑ)์ ์ฒ๋ฆฌ
2. ๋ชจ๋ ํฐ์ผ์ ๋ฑ๋ก
3. $CATALINA_BASE/conf/web.xml์ ์ ์ญ์ ์ผ๋ก ๋ฑ๋ก
4. DefaultServlet์ ์์ฒญ์ '์์'ํ์ฌ Resource ์์ฒญ ์ฒ๋ฆฌ
'Back-End ์์ ์ค > Spring Framework' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring boot - Gradle] JPA ์ฐ๊ฒฐ ์ ๋ณด ์ํธํ(jasypt) (0) | 2021.12.31 |
---|---|
[Spring Boot] @Order (0) | 2021.12.21 |
[Spring] Spring MVC๋? (0) | 2021.12.20 |
[Spring] @Builder (Builder Patter) (0) | 2021.10.11 |
[Spring] Bean Scope (0) | 2021.10.10 |