Spring 7기 프로젝트/일정관리 프로젝트
Spring 컨트롤러 메서드의 파라미터에 자동으로 바인딩해주는 기능
JuNo_12
2025. 5. 21. 19:16
과제를 진행하던 중에 코드 리펙토링을 하려고 쭉 돌아보는데
컨트롤러 레이어에서 로그인 여부에 대한 로직이 각 메핑마다 반복되는 걸 보았다.
이에 불편함을 느껴서 이를 해결할 방법을 찾아보다가, Spring ArgumentResolver라는 개념을 알게 되었다.
Spring ArgumentResolver란?
스프링 MVC에서는 컨트롤러 메서드의 파라미터에 값을 자동으로 바인딩해주는 기능이 있다.
예를 들어, @RequestParam, @PathVariable, @RequestBody 등은 모두 내부적으로 ArgumentResolver에 의해 처리된다.
HandlerMethodArgumentResolve
는 스프링에서 컨트롤러 메서드의 파라미터를 어떻게 처리할지를 결정하고, 필요한 값을 주입해주는 인터페이스다.
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter); // 지원 여부 판단
Object resolveArgument(...); // 실제 파라미터 주입
}
커스텀 ArgumentResolver 만들기 예시
컨트롤러에서 로그인한 유저 정보를 편리하게 받기 위해, 다음과 같이 사용하고 싶다고 가정:
@GetMapping("/profile")
public String profile(@LoginUser User user) {
// 로그인 유저 정보 사용
}
1. 어노테이션 만들기
어노테이션 패키지를 따로 생성해주어서 이 인터페이스를 만들어주면 된다.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {}
2. ArgumentResolver 구현
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// ArgumentResolver가 어떤 파라미터를 처리할 수 있는지 판단하는 메서드
return parameter.hasParameterAnnotation(LoginUser.class)
&& parameter.getParameterType().equals(User.class);
// 해당 파라미터에 @LoginUser 어노테이션이 붙어 있고
// 파라미터의 타입이 User.class일 경우에만 이 resolver가 동작하도록 조건을 지정
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {
// supportsParameter()가 true를 반환했을 때,
// 스프링이 이 메서드를 호출해서 해당 파라미터에 어떤 값을 넣을지 결정
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
// 세션에 접근해주고
return request.getSession().getAttribute("loginUser");
// 로그인 시 세션에 저장된 "loginUser"라는 이름의 속성을 꺼내주어서
// User 객체를 컨트롤러 메서드의 파라미터에 자동으로 주입해준다.
}
}
3. WebMvcConfigurer에 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final LoginUserArgumentResolver loginUserArgumentResolver;
public WebConfig(LoginUserArgumentResolver loginUserArgumentResolver) {
this.loginUserArgumentResolver = loginUserArgumentResolver;
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginUserArgumentResolver);
}
}
4. 컨트롤러에서 사용
@GetMapping("/profile")
public String profile(@LoginUser User user) {
// @LoginUser 어노테이션이 붙은 User user 파라미터는,
// 앞서 만든 LoginUserArgumentResolver 덕분에 세션에서 자동으로
// 로그인 사용자 정보를 꺼내서 주입받는 것
System.out.println("로그인 유저: " + user.getName());
return "profile";
}
실제 프로젝트에서 유저 인증, 세션 정보, 커스텀 객체 바인딩 등을 자동화할 때 매우 유용하다고 생각한다.