본 글은 김영한님의 스프링 MVC 1편-백엔드 웹 개발 핵심 기술을 토대로 작성하였습니다.
클라이언트에서 서버로 요청 데이터를 전달할 때는 보통 다음 3가지 방법을 사용한다.
위 세 가지 방법 중 쿼리 파라미터와 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)
@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의 기능을 지원받지 않는다.