[Spring]@RequestParam, @ModelAttribute에 대하여

김용현·2023년 9월 28일
0

Spring

목록 보기
5/13

본 글은 김영한님의 스프링 MVC 1편-백엔드 웹 개발 핵심 기술을 토대로 작성하였습니다.

서버 요청 방법

클라이언트에서 서버로 요청 데이터를 전달할 때는 보통 다음 3가지 방법을 사용한다.

  • Get - 쿼리 파라미터
    -> /{url}?username=hello&age=20
    -> 메세지 바디에 담지 않고 쿼리 스트링으로 데이터 전달
  • Post - HTML Form
    -> content-type: application/x-www-form-urlencoded
    -> 메시지 바디에 쿼리 파라미터 형식으로 전달
  • HTTP message body
    -> HTTP API에서 주로 사용 JSON, XML, TEXT
    -> 주로 Json을 사용한다.

@RequestParam

위 세 가지 방법 중 쿼리 파라미터와 HTML Form 방식으로 데이터를 요청할 때 스프링에서는 @RequestParam 어노테이션을 이용해 넘어온 값을 쉽게 컨트롤할 수 있다.

지금부터 단계별로 알아보자.

가장 먼저 HttpServlet을 이용하는 방법이다(@RequestParam X)

@RequestMapping("/request-param-v1")
      public void requestParamV1(HttpServletRequest request, HttpServletResponse
  response) throws IOException {
          String username = request.getParameter("username");
          int age = Integer.parseInt(request.getParameter("age"));
          log.info("username={}, age={}", username, age);
          response.getWriter().write("ok");
      }

다음과 같이 request, response 객체를 획득하여 넘어온 값들을 확인할 수 있다.

다음은 @RequestParam을 사용하는 기본 방법이다.

@ResponseBody
    @RequestMapping("/request-param-v2")
    public String requestParamV2(
            @RequestParam("username") String memberName,
            @RequestParam("age") int memberAge) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
  }

다음과 같이 인자를 받을 때 앞에 @RequestParam을 붙이고 해당 key값을 넣어주면 뒤에 선언한 변수에 그 key에 해당하는 value 값이 들어간다.

@ResponseBody란?
코드에는 없지만 현재 클래스에서 @Controller를 사용하고 있다. 따라서 return 값을 가지고 view를 찾는데 여기서는 그냥 response 바디에 값을 그대로 넣고 싶어서 @ResponseBody 어노테이션을 붙여 그냥 반환했다.

또한 파라미터 key 값과 그 값을 담는 변수명이 같으면 파라미터 key값을 생략할 수 있다.

@ResponseBody
  @RequestMapping("/request-param-v3")
  public String requestParamV3(
          @RequestParam String username,
          @RequestParam int age) {
      log.info("username={}, age={}", username, age);
      return "ok";
}

게다가 이 상황에서 @RequestParam을 생락하는 것도 가능하다.

/**
* @RequestParam 사용
* String, int 등의 단순 타입이면 @RequestParam 도 생략 가능 */
  @ResponseBody
  @RequestMapping("/request-param-v4")
  public String requestParamV4(String username, int age) {
  log.info("username={}, age={}", username, age);
        return "ok";
    }

여기서 주의할 점은 파라미터의 값을 담는 변수의 자료형이 단순 자료형이어야 생락 가능하다.(ex) int, String, Integer etc)

@ModelAttribute

@RequestParam은 단순 자료형에 대해 편리한 기능을 제공했다면 @ModelAttribute는 넘어온 데이터들로 객체를 생성할 때 편리한 기능을 제공한다.

@ResponseBody
  @RequestMapping("/model-attribute-v1")
  public String modelAttributeV1(@ModelAttribute HelloData helloData) {
      log.info("username={}, age={}", helloData.getUsername(),
  helloData.getAge());
      return "ok";
  }

다음과 같이 HelloData라는 모델이 정의되어있고, 프로퍼티로 username과 age를 가지고 있다. 이 상황에서 localhost:8080/model-attribute-v1?username=kim&age=20라는 url 요청이 들어오면 해당 modelAttributeV1() 함수가 실행되어 넘어온 값들을 가지고 HelloData 객체를 생성하여 값들을 모두 바인딩해준다.

이 때 @ModelAttribute도 생략이 가능한데, 그냥 앞에 @ModelAttribute를 지우기만 하면 된다.

여기서 의문이 드는 것은 앞서 말한 @RequestParam도 생략하고 @ModelAttribute도 생략이 가능하면 스프링은 이를 어떻게 구분하는 것일까?

답은 앞서 말한 자료형에 있다. @RequestParam은 단순 타입(int, String, Integer 등)일 때 동작하고 그 외에(argument resolver로 지정해둔 타입 외)는 @ModelAttribute를 적용한다.
❗️argument resolver라는 것에 등록된 것들은 두 어노테이션 모두 적용받지 않고 순수 인자로 적용된다.
ex) HttpServletRequest는 argument resolver에 등록되어 있어 따로 @ModelAttribute의 기능을 지원받지 않는다.

profile
평생 여행 다니는게 꿈 💭 👊 😁 🏋️‍♀️ 🦦 🔥

0개의 댓글

관련 채용 정보