WebMvcConfigurer를 사용하면 개발자가 Spring MVC 설정을 유연하게 커스터마이징할 수 있다.
이 글에서는 다음 세 가지 항목을 다룬다:
컨트롤러 로직 없이 단순히 뷰만 반환해야 하는 경우, addViewControllers()를 통해 간단히 매핑할 수 있다.
ParameterizableViewController를 내부적으로 사용하며, 로직 없이 뷰 이름만 반환할 때만 사용해야 한다.
예시로는 정적 페이지, 로그인 화면, 홈 화면 리다이렉트 등에 적합하다.
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("hello");
}
}
단순 뷰 매핑을 위해 굳이 @Controller를 만드는 게 과하다고 느껴질 때 간단히 설정 가능.
하지만 이 설정은 스프링을 모르는 개발자에겐 직관적이지 않기 때문에 한시적으로만 사용하는 게 좋다. 일반적인 경우엔 그냥 @Controller를 쓰자.
👉 공식 문서 링크
인터셉터는 HTTP 요청의 전후 처리에 사용할 수 있다. 예를 들어:
등의 기능을 구현할 수 있다.
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
아래와 같이 사용할 수 있다.
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CheckLoginInterceptor())
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/login");
}
}
public class CheckLoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String accessToken = request.getHeader("Authorization");
if (accessToken == null) {
throw new AuthorizationException();
}
return true;
}
}
| 패턴 | 설명 |
|---|---|
/admin/* | /admin/ 하위 한 단계만 매핑 (예: /admin/user) |
/admin/** | /admin/ 하위 모든 경로 매핑 (예: /admin/user/edit) |
/** | 전체 요청 경로 매핑 |
/static/**.css | /static/ 하위 .css 파일들 |
/*.html | 루트 경로의 .html 파일 (예: /index.html) |
| 항목 | Filter | Interceptor |
|---|---|---|
| 위치 | ServletContainer 수준 | Spring DispatcherServlet 내부 |
| 대상 | 모든 요청 (정적 리소스 포함) | Spring MVC 처리 요청만 |
| 용도 | 보안, 로깅 등 전역 기능 | 컨트롤러 전후 처리 |
| API | Servlet 표준 | Spring 전용 |
⚠️ 보안 목적이라면 Interceptor가 아니라 Spring Security나 Filter를 써야 한다.
(아예 DispatcherServlet까지 도달하지 않은 요청에 대해선 아무런 제어권이 없기 때문)
컨트롤러 메서드의 파라미터로 직접 값을 주입하고 싶을 때 사용하는 방식이다.
예를 들어 @Login이라는 커스텀 애노테이션을 만들고, 로그인한 사용자 ID를 자동으로 주입하고 싶을 때 유용하다.
인터페이스를 다음과 같이 구현할 수 있다.
supportsParameter()와 resolveArgument()를 오버라이딩해서 구현 가능하다.
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(Login.class)
&& parameter.getParameterType().equals(Long.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {
String memberId = webRequest.getHeader("X-MEMBER-ID");
return memberId != null ? Long.parseLong(memberId) : null;
}
}
위에서 구현한 Argument Resolver를 SpringMVC 구성에 추가한다.
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginMemberArgumentResolver());
}
}
프로덕션 코드에서 다음과 같이 활용 가능하다.
@GetMapping("/profile")
public String getProfile(@Login Long memberId) {
return "Profile for memberId: " + memberId;
}
| 항목 | 설명 |
|---|---|
| 인터페이스 | HandlerMethodArgumentResolver |
| 메서드 | supportsParameter(), resolveArgument() |
| 등록 위치 | addArgumentResolvers() in WebMvcConfigurer |
| 사용 예 | 로그인 유저 정보, 공통 파라미터 처리 등 |
| 장점 | 관심사 분리, 컨트롤러 코드 단순화 |
ViewController: 로직 없이 뷰만 응답할 때 유용. 설정은 간단하지만 가독성이 떨어질 수 있어 일반적으로는 @Controller가 더 나음.Interceptor: 요청 전후 공통 로직 실행에 사용. 인증, 접근 제한 등. 단, 보안 용도로는 사용 X.ArgumentResolver: 공통 파라미터 주입. 커스텀 애노테이션과 조합해 쓰면 매우 깔끔함.