๐Ÿ“‚ ์Šคํ”„๋ง/๊ธฐ๋ณธ ๊ฐœ๋…

HTTP ์š”์ฒญ(ํ—ค๋”, ํŒŒ๋ผ๋ฏธํ„ฐ, ๋ฉ”์‹œ์ง€) ์ฒ˜๋ฆฌ

Amenable 2023. 4. 20. 22:54

  ์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ์Šคํ”„๋ง ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๋‹ค์–‘ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์›ํ•œ๋‹ค.

  1. ํ—ค๋” ์ •๋ณด ์กฐํšŒ
  2. ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ์กฐํšŒ
    (1) ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ์ง์ ‘ ์กฐํšŒ(@RequestParam)
    (2) ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•œ ์กฐํšŒ(@ModelAttribute)
  3. ์š”์ฒญ ๋ฉ”์‹œ์ง€ ์กฐํšŒ
    (1) ๋‹จ์ˆœ ํ…์ŠคํŠธ (@RequestBody)
    (2) JSON

  ํ•˜๋‚˜์”ฉ ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž.

 

1. ํ—ค๋” ์ •๋ณด ์กฐํšŒ ๐Ÿ•

  HTTP ํ—ค๋” ์ •๋ณด๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

@RequestMapping("/headers")
public String headers(HttpServletRequest request,
                      HttpServletRequest response,
                      HttpMethod httpMethod,
                      Locale locale,
                      @RequestHeader MultiValueMap<String, String> headerMap,
                      @RequestHeader("host") String host,
                      @CookieValue(value = "myCookie", required = false) String cookie
) {
    return "home";
}
  • HttpServletRequest
  • HttpServletResponse
  • HttpMethod
  • Locale
    Locale ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ๋‹ค.
    Locale ์ •๋ณด๋ž€ 'ko_KR'๊ณผ ๊ฐ™์ด ์–ธ์–ด์ •๋ณด๋ฅผ ๋œปํ•œ๋‹ค.
  • @RequestHeader MultiValueMap<String, String> headerMap
    ๋ชจ๋“  HTTP ํ—ค๋”๋ฅผ MultiValueMap ํ˜•์‹์œผ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค.
    MultiValueMap์ด๋ž€ ํ•˜๋‚˜์˜ ํ‚ค์— ์—ฌ๋Ÿฌ ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. 
  • @RequestHeader("host") String host
    ํŠน์ • HTTP ํ—ค๋”๋ฅผ ์กฐํšŒํ•œ๋‹ค.
  • @CookieValue(value = "myCookie", required = false) String cookie
    ํŠน์ • ์ฟ ํ‚ค ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ๋‹ค.

 

2. ํŒŒ๋ผ๋ฏธํ„ฐ ์กฐํšŒ - ์ง์ ‘ ์กฐํšŒ(@RequestParam) ๐Ÿ”

  ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 2๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

  • ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ(GET)
    ๋ฉ”์‹œ์ง€ ๋ฐ”๋”” ์—†์ด, URL์˜ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•ด์„œ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ
    /url?username=amenable&age=20
  • HTML Form(POST)
    ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์— ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ (username=amenable&age=20)
    content-type: application/x-www-form-urlencoded

  ๋‘ ๊ฐ€์ง€ ๋ชจ๋‘ ์•„๋ž˜์˜ ๋ฐฉ์‹๋“ค๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

V1. HttpServletRequest์˜ request.getParameter()

@RequestMapping("/request-param-v1")
public String requestParamV1(HttpServletRequest request, 
                             HttpServletResponse response) throws IOException {

    String username = request.getParameter("username");
    int age = Integer.parseInt(request.getParameter("age"));

    return "home";
}

V2. @RequestParam

@RequestMapping("/request-param-v2")
public String requestParamV2(@RequestParam("username") String memberName,
                             @RequestParam("age") int memberAge) {
    return "home";
}

  ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์œผ๋กœ ๋ฐ”์ธ๋”ฉ์„ ํ•œ๋‹ค.

V3. @RequestParam ์ธ์ˆ˜ ์ƒ๋žต

@RequestMapping("/request-param-v3")
public String requestParamV3(@RequestParam String username,
                             @RequestParam int age) {
    return "home";
}

  HTTP ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์ด ๋ณ€์ˆ˜ ์ด๋ฆ„๊ณผ ๊ฐ™์œผ๋ฉด @RequestParam์˜ ์ธ์ˆ˜๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค. ์›๋ž˜๋Š” @RequestParam("username")์ธ๋ฐ ๋ณ€์ˆ˜ ์ด๋ฆ„์„ username์œผ๋กœ ํ•ด์คฌ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋žต์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด๋‹ค.

V4. @RequestParam ์ƒ๋žต

@RequestMapping("/request-param-v4")
public String requestParamV4(String username,
                             int age) {
    return "home";
}

  String, int, Integer ๋“ฑ์˜ ๋‹จ์ˆœ ํƒ€์ž…์ด๋ฉด @RequestParam ์ž์ฒด๋„ ์ƒ๋žต์ด ๊ฐ€๋Šฅํ•œ๋‹ค.

  ํ•˜์ง€๋งŒ @RequestParam์ด ์ƒ๋žตํ•˜์ง€ ์•Š์œผ๋ฉด, ๋ช…ํ™•ํ•˜๊ฒŒ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธด ํ•˜๋‹ค.

+ฮฑ. Map์„ ์ด์šฉํ•œ ์กฐํšŒ

@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap) {

    Object username = paramMap.get("username");
    Object age = paramMap.get("age");

    return "home";
}

  ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ Map๊ณผ MultiValueMap์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

3. ํŒŒ๋ผ๋ฏธํ„ฐ ์กฐํšŒ - ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•œ ์กฐํšŒ(@ModelAttribute) ๐ŸŸ

  ์ง€๊ธˆ๊นŒ์ง€๋Š” ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง์ ‘ ๋ฐ›๋Š” ๊ฒƒ์„ ์•Œ์•„๋ณด์•˜๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ”๋กœ ์“ฐ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ํ•„์š”ํ•œ ๊ฐ์ฒด์— ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๋„ฃ์–ด์„œ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๊ฒƒ์„ ์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” @ModelAttribute๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉํ•ด ๋ณด์ž.

V1. @ModelAttribute

@Data
public class Person {

    private String name;
    private int age;
}

----------

@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute Person person) {
    return "home";
}

  ์‚ฌ์šฉ๋ฒ•์€ ์ƒ๋‹นํžˆ ๊ฐ„๋‹จํ•˜๋‹ค. ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•ด ์ฃผ๋ฉด ์Šคํ”„๋ง์ด Person ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ๊ฐ์ฒด์˜ setter๋ฅผ ์ด์šฉํ•˜์—ฌ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ์ž…๋ ฅ(๋ฐ”์ธ๋”ฉ)ํ•œ๋‹ค.

V2. @ModelAttribute ์ƒ๋žต

@RequestMapping("/model-attribute-v2")
public String modelAttributeV2(Person person) {
    return "home";
}

  @ModelAttribute์„ ์œ„์™€ ๊ฐ™์ด ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

์•ž์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ๊ณผ ๊ฐ™์ด @RequestParam๋„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ์ƒ๋žต๊ณผ ๊ด€๋ จํ•ด์„œ ์Šคํ”„๋ง์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทœ์น™์„ ๋”ฐ๋ฅธ๋‹ค.

  1. String, int, Integer ๊ฐ™์€ ๋‹จ์ˆœ ํƒ€์ž…์ธ ๊ฒฝ์šฐ โ†’ @RequestParam
  2. ๋‚˜๋จธ์ง€ โ†’ @ModelAttribute

 

4. ๋ฉ”์‹œ์ง€ ์กฐํšŒ - ๋‹จ์ˆœ ํ…์ŠคํŠธ(@RequestBody) ๐ŸŒญ

  ์š”์ฒญ ๋ฉ”์‹œ์ง€๋ž€ HTTP message body์— ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋‹ด์•„์„œ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด๋‹ค. HTTP API์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๊ณ , ์ข…๋ฅ˜๋กœ๋Š” JSON, XML, TEXT ๋“ฑ์ด ์žˆ๋‹ค. ๋จผ์ € ๋‹จ์ˆœ ํ…์ŠคํŠธ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

V1. HttpServletResponse + InputStream

@PostMapping("/request-body-string-v1")
public String requestBodyStringV1(HttpServletRequest request,
                                  HttpServletResponse response) throws IOException {
    ServletInputStream inputStream = request.getInputStream();
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

    return "home";
}

  HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์˜ ๋ฐ์ดํ„ฐ๋ฅผ InputStream์„ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค.

V2. InputStream

@PostMapping("/request-body-string-v2")
public String requestBodyStringV2(InputStream inputStream) throws IOException {
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

    return "home";
}

  ์Šคํ”„๋ง MVC์—์„œ ์ œ๊ณตํ•˜๋Š” InputStream ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ HTTP ์š”์ฒญ ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์˜ ๋‚ด์šฉ์„ ์ง์ ‘ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. (OutputStream์„ ์ด์šฉํ•ด์„œ ์ง์ ‘ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•  ์ˆ˜๋„ ์žˆ๋‹ค.)

V3. HttpEntity

@PostMapping("/request-body-string-v3")
public String requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException {
    String messageBody = httpEntity.getBody();

    return "home";
}

  ์Šคํ”„๋ง MVC์—์„œ ์ œ๊ณตํ•˜๋Š” HttpEntity ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ HTTP header, body ์ •๋ณด๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. HttpEntity๋Š” ๋ฉ”์‹œ์ง€ ๋ฐ”๋”” ์ •๋ณด๋ฅผ ์ง์ ‘ ์กฐํšŒํ•œ๋‹ค. 

  ์ด๋Š” ์œ„์—์„œ ์‚ดํŽด๋ณธ @RequestParam๊ณผ @ModelAttribute์™€๋Š” ๊ด€๋ จ์ด ์—†๋‹ค.

V4. @RequestBody

@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) throws IOException {
    return "home";
}

  @RequestBody๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋”” ์ •๋ณด๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ๋ฐ”๋””๊ฐ€ ์•„๋‹Œ ํ—ค๋” ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด HttpEntity๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ @RequestHeader๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  ์ด๊ฒƒ ๋˜ํ•œ @RequestParam๊ณผ @ModelAttribute์™€๋Š” ๊ด€๋ จ์ด ์—†๋‹ค.

 

5. ๋ฉ”์‹œ์ง€ ์กฐํšŒ - JSON(@RequestBody) ๐Ÿฟ

  ์ด๋ฒˆ์—๋Š” ์š”์ฒญ ๋ฉ”์‹œ์ง€ ์ค‘์—์„œ HTTP API์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” JSON ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ์กฐํšŒํ•ด ๋ณด์ž.

V1. HttpServletRequest + JSON ๋ณ€ํ™˜

private ObjectMapper objectMapper = new ObjectMapper();

@PostMapping("/request-body-json-v1")
public String requestBodyJsonV1(HttpServletRequest request,
                                HttpServletResponse response) throws IOException {

    ServletInputStream inputStream = request.getInputStream();
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

    Person person = objectMapper.readValue(messageBody, Person.class);

    return "home";
}

  HttpServletRequest๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์™€์„œ ๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•˜์˜€๋‹ค. ๋ฌธ์ž๋กœ ๋œ JSON ๋ฐ์ดํ„ฐ๋ฅผ Jackson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ ObjectMapper๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜์˜€๋‹ค.

V2. @RequestBody + JSON ๋ณ€ํ™˜

private ObjectMapper objectMapper = new ObjectMapper();

@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {

    Person person = objectMapper.readValue(messageBody, Person.class);

    return "home";
}

  ์ด์ „์— ์‚ดํŽด๋ดค๋˜ @RequestBody๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ HTTP ๋ฉ”์‹œ์ง€์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด๊ณ  messageBody์— ์ €์žฅํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฌธ์ž๋กœ ๋œ JSON ๋ฐ์ดํ„ฐ์ธ messageBody๋ฅผ objectMapper๋ฅผ ํ†ตํ•ด์„œ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

V3. @RequestBody

@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody Person person) throws IOException {

    return "home";
}

  @RequestBody์— ์ง์ ‘ ๊ฐ์ฒด๋ฅผ ์ง€์ •ํ•˜์—ฌ HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์˜ ๋‚ด์šฉ์„ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

  @RequestBody๋Š” '@RequestParam๊ณผ @ModelAttribute'์™€ ๋‹ฌ๋ฆฌ ์ƒ๋žต์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ทธ ์ด์œ ๋Š” @RequestBody๊ฐ€ ์ƒ๋žต๋œ๋‹ค๊ณ  ํ•˜๋ฉด @ModelAttribute๊ฐ€ ์ ์šฉ๋˜์–ด ๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

+ฮฑ. HttpEntity

@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<Person> httpEntity) throws IOException {
    Person person = httpEntity.getBody();

    return "home";
}

  ๋ฌผ๋ก  JSON์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋‹จ์ˆœ ํ…์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ HttpEntity๋ฅผ ์ด์šฉํ•ด๋„ ๋œ๋‹ค.

 

ํ•ด๋‹น ๊ธ€์€ ๊น€์˜ํ•œ ๋‹˜์˜ '์Šคํ”„๋ง MVC 1ํŽธ - ๋ฐฑ์—”๋“œ ์›น ๊ฐœ๋ฐœ ํ•ต์‹ฌ ๊ธฐ์ˆ '์„ ์ฐธ๊ณ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
๋Œ“๊ธ€์ˆ˜0