본문 바로가기
MSA

스프링 웹 MVC의 아규먼트 리졸버(Argument Resolver)

by xogns93 2024. 12. 16.

스프링 웹 MVC의 아규먼트 리졸버(Argument Resolver)컨트롤러 메서드의 매개변수(Argument)에 데이터를 자동으로 주입해주는 기능을 제공하는 스프링의 핵심 컴포넌트입니다. HTTP 요청 데이터에서 필요한 정보를 추출하거나, 특정 규칙에 따라 객체를 생성하여 컨트롤러 메서드에 전달합니다.


1. 아규먼트 리졸버의 기본 역할

  • 컨트롤러 메서드에 사용자가 정의한 매개변수와 스프링이 제공하는 애노테이션을 기반으로 HTTP 요청 데이터를 적절한 타입으로 변환하여 전달합니다.
  • 요청 파라미터, 헤더, 본문 데이터 등을 다양한 방식으로 처리.
  • 스프링 MVC는 다양한 기본 아규먼트 리졸버를 제공하며, 사용자 정의(커스텀) 아규먼트 리졸버를 추가할 수도 있습니다.

2. 아규먼트 리졸버의 작동 원리

  1. 클라이언트가 요청을 보냄.
  2. 요청이 HandlerMapping을 통해 적절한 컨트롤러 메서드에 매핑.
  3. HandlerAdapter가 컨트롤러를 호출하기 전에, 매개변수의 타입과 애노테이션을 기반으로 HandlerMethodArgumentResolver를 사용해 값을 생성.
  4. 컨트롤러 메서드 호출 시 필요한 매개변수 값이 주입됨.

3. 스프링이 제공하는 기본 아규먼트 리졸버

스프링 MVC는 다양한 아규먼트 리졸버를 기본으로 제공합니다. 아래는 대표적인 리졸버와 사용하는 애노테이션입니다.

3.1 요청 파라미터 기반 리졸버

@RequestParam

  • 쿼리 스트링이나 폼 데이터에 있는 값을 매핑하여 메서드 매개변수에 주입.
    @GetMapping("/users")
    public String getUserById(@RequestParam String id) {
      return "User ID: " + id;
    }
  • 요청 예: GET /users?id=123

@PathVariable

  • URL 경로 변수 값을 매핑하여 메서드 매개변수에 주입.
    @GetMapping("/users/{id}")
    public String getUserById(@PathVariable String id) {
      return "User ID: " + id;
    }
  • 요청 예: GET /users/123

@ModelAttribute

  • 요청 데이터를 Java 객체로 매핑(폼 데이터, 쿼리 스트링 등).
    @PostMapping("/users")
    public String createUser(@ModelAttribute User user) {
      return "User Name: " + user.getName();
    }
  • 요청 예: POST /users?name=John&age=30

3.2 요청 본문 기반 리졸버

@RequestBody

  • HTTP 요청 본문 데이터를 Java 객체로 변환(JSON, XML 등).
    @PostMapping("/users")
    public String createUser(@RequestBody User user) {
      return "Created User: " + user.getName();
    }
  • 요청 예 (JSON):
    {
      "name": "John",
      "age": 30
    }

3.3 요청 메타데이터 기반 리졸버

@RequestHeader

  • HTTP 요청 헤더 값을 매핑하여 메서드 매개변수에 주입.
    @GetMapping("/users")
    public String getUserAgent(@RequestHeader("User-Agent") String userAgent) {
      return "User-Agent: " + userAgent;
    }

@CookieValue

  • 쿠키 값을 매핑하여 메서드 매개변수에 주입.
    @GetMapping("/welcome")
    public String getCookieValue(@CookieValue("sessionId") String sessionId) {
      return "Session ID: " + sessionId;
    }

3.4 기타 리졸버

HttpServletRequest / HttpServletResponse

  • 요청 객체와 응답 객체를 직접 사용.
    @GetMapping("/users")
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) {
      String id = request.getParameter("id");
      response.getWriter().write("User ID: " + id);
    }

Principal

  • 인증된 사용자 정보를 주입.
    @GetMapping("/profile")
    public String getProfile(Principal principal) {
      return "Logged-in User: " + principal.getName();
    }

4. 커스텀 아규먼트 리졸버 (Custom Argument Resolver)

스프링 MVC는 기본 리졸버 외에도 사용자 정의 리졸버를 만들어 사용할 수 있습니다.

4.1 구현 방법

  1. HandlerMethodArgumentResolver 인터페이스 구현.
  2. WebMvcConfigurer를 통해 리졸버 등록.

4.2 커스텀 리졸버 예제

1) User 객체를 HTTP 헤더에서 생성

커스텀 리졸버 구현
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // User 타입 매개변수 처리
        return parameter.getParameterType().equals(User.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        // HTTP 헤더에서 사용자 정보 추출
        String userId = webRequest.getHeader("X-User-Id");
        String userName = webRequest.getHeader("X-User-Name");

        if (userId != null && userName != null) {
            return new User(userId, userName); // User 객체 반환
        }
        return null;
    }
}
WebMvcConfigurer를 통해 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private UserArgumentResolver userArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(userArgumentResolver);
    }
}
컨트롤러에서 사용
@GetMapping("/profile")
public String getUserProfile(User user) {
    return "User ID: " + user.getId() + ", Name: " + user.getName();
}
요청 예
GET /profile HTTP/1.1
Host: example.com
X-User-Id: 123
X-User-Name: John
응답
User ID: 123, Name: John

5. 장점

  1. 매개변수 처리 코드 분리:
    • 복잡한 데이터 처리 로직을 컨트롤러 밖으로 분리하여 코드 가독성과 유지보수성을 향상.
  2. 재사용성:
    • 커스텀 리졸버는 여러 컨트롤러에서 공통적으로 사용할 수 있음.
  3. 유연성:
    • 요청 데이터를 다양한 방식으로 해석할 수 있도록 확장 가능.

6. 요약

  • 아규먼트 리졸버는 Spring MVC에서 컨트롤러 메서드 매개변수를 처리하는 강력한 도구입니다.
  • 스프링은 다양한 기본 리졸버(@RequestParam, @PathVariable 등)를 제공하며, 커스텀 리졸버를 통해 복잡한 데이터 매핑 로직을 처리할 수 있습니다.
  • 커스텀 리졸버를 사용하면 코드 재사용성과 유지보수성이 크게 향상됩니다.