클라이언트에서 서버로 전달된 요청을 객체로 바인딩하기 위해 사용하는 여러 방법들에 대해서 정리해보겠습니다.
먼저 시작하기에 앞서 클라이언트에서 서버로 요청 데이터를 전달할 때는 주로 다음 3가지 방법을 사용합니다.
- GET - 쿼리 파라미터
/...?username=hello&age=20
- 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
- 예) 검색, 필터, 페이징등에서 많이 사용하는 방식
- POST - HTML Form
- content-type:
application/x-www-form-urlencoded
- 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello & age=20
- 예) 회원 가입, 상품 주문, HTML Form 사용
- HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에서 주로 사용, JSON, XML, TEXT
- 데이터 형식은 주로 JSON 사용
- POST, PUT, PATCH
위의 두가지는 GET 쿼리 파라미터 전송 방식이든, POST HTML Form 전송 방식이든 형식이 같아 구분 없이 조회 가능하므로 요청 파라미터 조회 라고 합니다.
→ 즉 크게 2가지로 요청 파라미터 조회 방식, 메세지 바디 방식이 있습니다.
@RequestParam
애노테이션은 클라이언트가 전송하는 파라미터를 1:1로 받아서 바인딩할때 사용합니다.
@ResponseBody
@RequestMapping("/request-param")
public String requestParam(
@RequestParam("username") String memberName,
@RequestParam("age") int memberAge) {
log.info("username={} age={}", memberName, memberAge);
return "ok";
}
위의 예시 코드에서 /request-param?username=kim&age=20
이라는 요청이 들어오면
→ getParameter("username")을 통해 memberName에 값이 바인딩됩니다
@RequestParam String username
String username
추가적으로 파라미터 필수여부(required), 기본값 적용(defaultValue)도 적용 가능합니다.
@ModelAttribute는 요청파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주는 과정 자동화시키는 애노테이션입니다.
@ResponseBody
@RequestMapping("/model-attribute")
public String modelAttribute(@ModelAttribute HelloData helloData) {
log.info("username = {} age = {}", helloData.getUsername(), helloData.getAge());
return "ok";
}
위의 코드 예시를 통해 과정을 살펴보겠습니다.
스프링 MVC는 @ModelAttribute
가 있으면 생성자를 통해 HelloData를 객체 생성
→ 요청 파라미터의 이름으로 HelloData 객체의 property
를 찾음
(객체에 getxxx, setxxx 메서드가 있으면 xxx라는 프로퍼티를 갖고있는 것)
→ setter
호출해서 파라미터의 값을 바인딩
즉 해당 애노테이션을 사용하려면 생성자와 Setter함수가 필수적으로 있어야합니다
@ModelAttribute에서는 타입이 잘못들어가면 BindException
이 발생합니다.
또한 @RequestParam과 동일하게 애노테이션 생략이 가능합니다.
@RequestBody는 Http 메시지 바디에 내용을 담아서 요청이 오면 이를 변환할 때 사용하는 애노테이션입니다.
메시지 바디로 들어온 메시지는 @RequestParam이나 @ModelAttribute로 당연히 읽을 수 없습니다.
@ResponseBody
@PostMapping("/request-body-string")
public String requestBodyString(@RequestBody String messageBody) throws IOException {
log.info("messageBody = {}", messageBody);
return "ok";
}
@ResponseBody
@PostMapping("/request-body-json")
public HelloData requestBodyJson(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return data;
}
String, JSON 타입 모두 @RequestBody
애노테이션을 통해 받을 수 있습니다.
받은 메시지 바디는 내부의 HttpMessageConverte가 알아서 String 또는 객체 타입으로 변환해줍니다.
이때 @ModelAttribute처럼 setter를 사용하는 것이 아니라 생성자를 통해 객체를 생성합니다.
주로 JSON -> 객체 타입 변환에 많이 사용됩니다.
응답의 경우에도 @ResponseBody
를 사용하면 컨버터가 자동으로 변환해줍니다.
(컨버터에 관한 내용은 추후에 자세히 써보겠습니다..!)
@RequestParam | @ModelAttribute | @RequestBody | |
---|---|---|---|
HTTP 요청 종류 | 요청 파라미터 조회 | 요청 파라미터 조회 | 메시지 바디 |
특징 | - 요청 파라미터의 1:1 바인딩 - 파라미터의 필수값 여부, 기본값 지정 가능 - 생략 가능 | - 요청 파라미터를 받고 객체 자동 생성 및 바인딩 - 생략 가능 | - http 메시지 바디 내용 자동 변환 |
사용 예시 | - 검색이나 필터링 - GET | - 검증이 필요한 상황 - GET | - HTTP API에서 주로 사용 - JSON을 전송해야하는 상황 - POST |