이번 레벨2 "웹 체스" 미션을 진행하면서 Post요청에 대한 처리와 Get요청에 대한 처리, 즉 @PostMapping과 @GetMapping 둘 모두에서 @ReqeustParam
을 이용해 cient로 부터 오는 요청을 처리하였다.
그런데 어떻게 이 둘 모두에서 동일한 @RequestParam
을 사용할 수 있었던 걸까? 라는 의문에서 해당 내용을 공부하게 되었고, 이를 정리한다.
@GetMapping("/load")
public String restart(@RequestParam("game_name") String gameName) {
Long id = chessService.findIdByGameName(gameName);
return "redirect:/game/" + id;
}
@PostMapping("/delete")
public String delete(@RequestParam(value = "game_name", required = false) String gameName,
@RequestParam(value = "password", required = false) String password) {
State state = chessService.findStateByGameNameAndPassword(gameName, password);
chessService.deleteByGameNameAndPassword(state, gameName, password);
return "redirect:/";
}
HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달해줄 수 있는데, 이 때 크게 3가지 방법을 사용하게 된다.
메시지 바디 없이 URL의 쿼리 파라미터에 데이터를 포함해서 전달하는 방식으로 주로 검색, 필터, 페이징등에서 많이 사용하는 방식이다.
메시지 바디에 쿼리 파라미터 형식
으로 데이터를 전달하며, 주로 회원가입 등에서 사용하는 방식이다.
HTML Form으로 전달하는 POST Method는 PUT, PATCH가 불가하다. (HTML 스펙상 폼 데이터를 body로 전송할 때는 POST 방식만 허용)
특징으로는 content-type: application/x-www-form-urlencoded 라는 점과 message body에 쿼리 파라미터 형식으로 데이터를 전달한다는 것이다. (ex. username=hello&age=24)
HTTP API(REST API)에서 주로 사용하며, 데이터 형식은 주로 JSON을 사용한다. POST, PUT, PATCH 메소드가 가능하다.
RequestParam을 보면 다음과 같이 설명을 하고 있다.
즉 해당 어노테이션은 메소드 매개변수가 웹 요청 parameter에 바인딩되어야함을 나타내는 주석으로, Spring MVC 및 Spring WebFlux에 대해 지원이 된다.
Spring MVC에서 "요청 매개변수"는 매개 변수, 양식 데이터 및 다중 부품 요청의 부품을 매핑합니다. 이는 서블릿 API가 쿼리 파라미터와 폼 데이터를 "파라미터"라고 불리는 단일 맵으로 결합하기 때문이며, 여기에는 요청 본문의 자동 파싱이 포함된다. 라고 설명하고 있다.
여기서 중요한 내용은 "map to query parameters" 이다. 앞서 POST(HTML Form)의 경우 query parameter
형식으로 데이터를 message body에 담아 전달한다고 이야기하였다.
즉, GET방식에서 사용했던 query parameter와 "application/x-www-form-urlencoded" 형식은 동일한 형식이기 때문에 동일한 @RequestParam을 이용해서 parameter정보를 꺼낼 수 있었던 것이다.
이전에 @RequestBody
라는 어노테이션을 본 기억이 있다. 그리고 이런 RequestBody는 POST 요청 데이터를 읽는다고 생각했었다. 그런데 위에 정리한 내용으로 미루어보면 이는 잘못된 생각이라고 이야기할 수 있다.
그렇다면 @RequestBody
는 무엇일까?
메서드 매개 변수를 나타내는 어노테이션이 웹 요청 바디에 바인딩되어야 한다. 요청의 바디는 요청의 내용 유형에 따라 메서드 인수를 해결하기 위해 HttpMessageConverter를 통해 전달됩니다. 선택적으로, @Valid 인자에 주석을 달아 자동 유효성 검사를 적용할 수 있습니다.
도통 무슨말인지 알 수가 없다. 그래서 여러 블로그글을 찾아본 결과 다음과 같이 요약해볼 수 있을 것 같다.
@RequestBody
어노테이션이 붙은 parameter는 http 요청의 본문이 그대로 전달된다. 따라서 일반적인 GET/POST의 요청 파라미터라면 해당 어노테이션을 사용할일이 없다.
하지만 xml이나 json 기반의 메시지를 사용하는 경우에는 유용하며, HTTP 요청의 바디 내용을 통째로 자바 객체로 변환해서 매핑된 메소드 파라미터로 전달해준다.
(@RequestBody 어노테이션을 붙이면 HttpMessageReader가 request body를 Java Object로 역직렬화 한다.)
즉, 앞서 언급한 3가지 방법 중 HTTP message body
와 같은 요청에서 주로 사용할 것이다. 즉, HTTP를 통해서 "데이터"(JSON)를 전달할 때 사용한다고 이해할 수 있다.
물론 일반적인 form 데이터를 POST로 전송할 때도 사용할 수 있다. 예를 들어 폼 데이터로 'name=kim&age=24'라는 데이터가 바디에 담겨 @PostMapping로 매핑된 곳에서 @RequestBody로 받는다고 하자. 그럼 해당 문자열 그대로 읽혀 String으로 해당 데이터를 전달받을 수는 있다. 하지만 이 경우 우리가 직접 해당 문자열의 데이터를 파싱해주어야 한다.
하지만 우리는 이러한 경우 @RequestParam
을 이용해서 보다 편리하게 원하는 데이터를 얻을 수 있으므로 @RequestBody
는 HTTP를 통해서 JSON 형식의 데이터를 전달 받을 때 사용하는 것이 적절하다.
이해가 잘 안되네요. 예시좀 추가해주세요.