클라이언트에서 서버로 data를 전송하는 방법은 총 3가지로 정리 할 수 있다.
1. 요청 쿼리 스트링(query string) 으로 보내지는 경우
즉 localhost:8080/new/?name=최동훈&age=24 이렇게 클라이언트에서 보내는 경우이다. 이 방식은 HTTP 메세지 바디에 아무런 내용을 넣지 않는 GET 메서드 형식으로 보낸다.
이 방식을 사용했을때 HTTP 메세지의 Content/type은 Content-Type: application/x-www-form-urlencoded 이다. 그런데 메세지 바디에는 아무값도 들어가 있지 않는다.
*여기서 나는 의문점이 생겼다. HTTP 메세지의 Content/Type이 HTML 폼 태그에 post 메서드로 전송하는 사실은 같은데, 왜 메세지 바디에 아무 값도 넣어서 보내지 않는 GET 방식과 같은 것일까? 라는 의문점이 생겼다.
내가 얻은 결론은 application/x-www-form-urlencoded 이 형식으로 서버로 data를 어떻게든 보내는 것이다. 이 형식은
key=value&key=value 형태로 전달된다. 즉, 퀴리 스트링으로 보내는 GET방식이든, 메세지 바디에 이런 형태를 넣어서 서버로 전송하는 POST 방식이든 서버로 key=value&key=value 형태로 data를 전송하는 것이므로 HTTP Content/type 이 같은 것이다.
종합하자면, GET 방식은 데이터가 URL의 querystring으로 들어간다는 것과, POST 방식은 데이터가 http message-body에 들어간다는 차이가 존재한다.
2.HTTP 메세지의 바디에 data를 넣어서 보내는 경우 (POST 방식)
이 경우는 URL에 직접적으로 data의 정보가 들어나지 않는다. 위와 같은 방식의 예를 들겠다.
<form action="/submit" method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="username" value="john">
<input type="password" name="password" value="secret">
<input type="submit" value="Submit">
</form>
위와 같은 방식으로 HTTP request를 보내는 경우 HTTP 메세지 바디에 아래와 같은 형식으로 데이터에 담겨서 보낸다.
위와 같이 HTML input 태그의 속성 값으로 name 을 줘서 서버로 보내면, name 값을 key 값으로 해서 서버로 전송된다.
POST /submit HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
username=john&password=secret
즉 조금더 예시로 들자면 만약 사용자가 submit 버튼을 눌러서 위와 같은 POST 메서드로 서버에게 HTTP request 요청을 보내면 서버는 아래와 같이 data를 받을 수 있다.
@PostMapping("/submit")
public String submitForm(@RequestParam("username") String username, @RequestParam("password") String password) {
// 폼 필드 값 사용
// ...
}
위와 같이 퀴리 파라미터로 넘어온 urlencoded 방식을 키 값에 따라 String 형식으로 바꾼다. 즉, key와 value 쌍으로 넘어온 application/x-www-form-urlencoded 형식을 자바의 String으로 바꾸어 주는 것이다.
이 @RequestParam을 조금더 응용 한 것이 @ModellAttribute 이다. 이 ModelAttribute는 기존의 RequestParam의 쿼리 스트링 키 값 별로 1:1 mapping 방식이 아니라 객체 안에 자동으로 요청 파라`터의 이름으로 해당 객체의 프로퍼티의 Setter 함수를 호출하여서 값을 바인딩 해준다.
public void item(@RequestParam String name,
@RequestParam int price,
Model model){
Item item = new Item();
item.setName(name);
item.setPrice(price);
model.addAttribute("item", item);
}
즉 원래는 이렇게 하나하나 새로운 객체의 맴버에 클라이언트에서 url-encoded 형식으로 넘어온 request parameter 의 key에 해당하는 value 값을 넣어줘야 하지만 아래와 같이 @ModelAttribute를 사용하면, 요청 파라미터 이름과 일치하는 객체의 프로퍼티 안에 해당 파라미터 이름(key) 의 value 값을 넣어준다. 단 주의해야 할 점이 @ModelAttribute와 @RequestParam 방식은 xxx-url-encoded type 일때만 사용 가능하고 만약 Content/type이 json 이라면 @RequestBody를 사용 하여야 한다.
public void modelAttributeEx(@ModelAttribute Item item, Model model){
model.addAttribute("item", item);
}
@RequestParam 대신 @ModelAttribute 를 사용할 경우