WebConfig
_WebConfig_๋ ์น ๊ตฌ์ฑ์ ๋ํด ์ง์ ํ๋ ๋ด์ฉ์ด ๋ด๊ฒจ์๋ ์ค์ ํ์ผ์ ๋งํ๋ค.
_WebConfig_๋ ๊ตฌํ์ฒด์ด๊ณ _WebMvcConfigure_ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ฌ ์์ฑํ ์ ์๋ค. ์ด _WebConfig_๋ฅผ ๋ค๋ฃจ๋ฉด ์ข์ ์ ์ Controller ๋จ์ผ๋ก ์ค๊ธฐ ์ ์ด๋ ์ค๊ณ ๋ ํ, ํน์ ๊ทธ ์ฌ์ด์ ์ธํฐ์ ํฐ๋ฅผ ๋๋ ๋ฑ ๋ค์ํ ๋ฐฉ์์ผ๋ก ์ปค์คํ ํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
์ฃผ๋ก ์์ฃผ ์ฌ์ฉํ๋ ๊ฒ์ _View Controller_, _interceptors_, _ArgumentResolvers_์ธ๋ฐ, ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ด ์ ๋ง์ ๋ง๋๋ก ๋ค๋ฃฐ ์ ์๋ ์ง ํ๋ฒ ์ดํด๋ณด์.
View Controller
_View Controller_๋ URL ๋งคํ์ ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ๋ค. ์ฌ์ฉํจ์ผ๋ก์จ ์ป์ ์ ์๋ ์ด์ ์ ๊ฐ๋ฐ ์๊ฐ์ ๋จ์ถ ์ํฌ ์ ์์ผ๋ฉฐ URL๊ณผ ๋ทฐ ์ด๋ฆ์ ๋งคํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
}
- _@Configuration_
- ์คํ๋ง IoC ์ปจํ ์ด๋๊ฐ ์ด๊ธฐํ ๋ ๋ ์คํ๋๋ค.
- Bean์ผ๋ก ๋ฑ๋กํ๋ค.
- _@EnableWebMvc_
- ์คํ๋ง MVC๋ฅผ ์ฌ์ฉํ ๋ ์ค์ ์ ์๋์ผ๋ก ํ์ฑํ ํด์ค๋ค.
- ์ฌ์ฉ ๋ชฉ์ ์ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฐ๊ณ ๋ทฐ๋ฅผ ๋งคํํด์ฃผ๊ธฐ ์ํจ์ด๋ค.
registry.addViewController("/login").setViewName("login").setStatusCode(HttpStatus.OK);
์ฌ์ฉ ๋ฐฉ๋ฒ์ ์์ฒ๋ผ, ๊ฒฝ๋ก์ ๋ทฐ ์ด๋ฆ, ๊ทธ๋ฆฌ๊ณ ์ํ ์ฝ๋๋ฅผ ์ค์ ํด ์ฃผ๋ฉด ๋๋ค.
Interceptor
_Intercepter_๋ ํด๋ผ์ด์ธํธ์ ์์ฒญ๊ณผ ์๋ฒ์ ์๋ต ์ฌ์ด, ํน์ ๊ทธ ์ ํ์ ์์นํ์ฌ ์์ฒญ๊ณผ ์๋ต์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ํ๋ค. ์ผ๋ฐ์ ์ผ๋ก๋ ํค๋ ์ ๋ณด๋ฅผ ์์ ํ๊ฑฐ๋ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ์ผ์ ํ๋ค.
์ฌ์ฉ๋๋ ๋ฉ์๋๋ _preHandle_, _postHandle_, _afterCompletion_์ด ์๋ค. ๋ง๊ทธ๋๋ก ์์ฒญ์ด Controller๋ก ๋๋ฌํ๊ธฐ ์ด์ , Controller๊ฐ ์คํ๋ ํ์ด์ง๋ง, View๊ฐ ๋ ๋๋ง ๋๊ธฐ ์ด์ , View๊ฐ ๋ ๋๋ง ๋ ํ์ด๋ค.
์ปค์คํ Interceptor๋ฅผ ์์ฑํ๊ธฐ ์ํด์๋ _HandlerInterceptor_์ ์ ์๋ ํด๋น ํจ์๋ค์ ๊ตฌํํ๋ฉด ๋๋ค.
```java
@Component
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
...
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
...
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
...
}
}
์ ์ํ Interceptor๋ _WebConfig_์์ ๋ฑ๋กํ ์ ์๋ค.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Autowired
private CustomInterceptor customInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor).addPathPatterns("/**");
}
}
Argument Resolver
_ArgumentResolver_๋ HTTP ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์ปจํธ๋กค๋ฌ ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ๋ก ๋ณํ์ํค๋๋ก ๋์์ฃผ๋ ์คํ์ ๋น์ด๋ค.
์ปค์คํ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด์๋ _HanlderMethodArgumentResolver_๋ฅผ ์์๋ฐ์์ ํน์ ๋ฉ์๋๋ค์ ์ค๋ฒ๋ผ์ด๋ ํด์ผ ํ๋ค.
์ค์ ๋ก JWT์ ๊ฐ์ ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ ๋ฐฉ์์ ์ฌ์ฉํ ๋ ํนํ๋ ์ฌ์ฉํ๋ฉด ์ข๋ค. ์๋ํ๋ฉด ์ด๋ ธํ ์ด์ ์ผ๋ก ์ธ๊ฐ ๊ณผ์ ์ ๋ฑ๋กํ๋ค๋ฉด, ๋ฐ๋ณต์ ์ผ๋ก ํ ํฐ์ ๊ฒ์ฌํ์ฌ ID ๊ฐ์ ๊บผ๋ด์ค๋ ๊ณผ์ ์ ํ์ง ์์๋ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
public class CustomArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
String name = request.getParameter("name");
String email = request.getParameter("email");
User user = new User(name, email);
return user;
}
}
- _supportsParameter_
- true๋ฅผ ๋ฐํํ๋ค๋ฉด ResolveArgument๋ฅผ ํตํด ๋ฐ์ธ๋ฉ ๋๋ค.
- false๋ฅผ ๋ฐํํ๋ค๋ฉด, ResolveArgument๋ ์คํ๋์ง ์๋๋ค.
- ์ฆ, Controller ๋ฉ์๋์ ์ธ์๊ฐ Argument Resolver์์ ์ฒ๋ฆฌ๊ฐ๋ฅํ ์ง ํ๋จํ๋ค.
- _MethodParameter_
- Controller ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ ์ ๋ณด๋ฅผ ๋ด๋๋ค.
- ์ด๊ฑธ ํตํด ํ๋ผ๋ฏธํฐ์ ํ์ ์ด๋ ์ด๋ ธํ ์ด์ ์ ๊ฐ์ ธ์ฌ ์ ์๋ค.
๋ค์์ JWT ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ๊ณผ์ ์ ์์ด _@Auth_๋ผ๋ ์ด๋ ธํ ์ด์ ํ๋๋ก ํ ํฐ ์ถ์ถ์ ์ฝ๊ฒ ๊ฐ๋ฅํ๊ฒ ํ๋๋ก ์ปค์คํ ํ๋ ์ฝ๋์ด๋ค.
@RequiredArgsConstructor
@Component
public class AuthArgumentResolver implements HandlerMethodArgumentResolver {
private final JwtService jwtService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(Auth.class) && parameter.getParameterType().equals(Long.class);
}
@Override
public Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory
) {
Auth authAt = parameter.getParameterAnnotation(Auth.class);
requireNonNull(authAt);
String accessToken = extractAccessToken(webRequest);
return jwtService.extractMemberId(accessToken);
}
private static String extractAccessToken(NativeWebRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
throw new UnAuthorizedException("๋ก๊ทธ์ธ ํ ์ ๊ทผํ ์ ์์ต๋๋ค.");
}
}
์ด์ ๋ง๋ค์ด์ง ์ปค์คํ _ArgumentResolver_๋ฅผ ๋ฑ๋ก์์ผ๋ณด์.
@RequiredArgsConstructor
@Configuration
public class AuthConfig implements WebMvcConfigurer {
@Autowired
private final AuthArgumentResolver authArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(authArgumentResolver);
}
}
_WebMvcConfigure_๋ฅผ ์ดํด๋ณด๋ฉด, _addArgumentResolvers()_ ๋ฅผ ๊ตฌํํ ์ ์๋๋ก ํด๋์๋ค.
๋ง์ง๋ง์ผ๋ก ์ด๋ ธํ ์ด์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋ _@Auth_๋ฅผ ๋ง๋ค๋ฉด ๋๋ค.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
}
References
- https://engineerinsight.tistory.com/80
- https://hudi.blog/spring-argument-resolver/
- https://blog.advenoh.pe.kr/spring/HandlerMethodArgumentResolver-%EC%9D%B4%EB%9E%80/#google_vignette
- https://engineerinsight.tistory.com/79#google_vignette
'๐ฃ Spring > Spring ๊ธฐ๋ณธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] ์คํ๋ง ์์ธ ์ฒ๋ฆฌํ๊ธฐ (1) | 2024.02.12 |
---|---|
[Spring] Dispatcher-Servlet์ ๋์ ๊ณผ์ ์ ์์๋ณด์. (0) | 2024.02.05 |