09. Request Parameter

์Šคํ”„๋ง์œผ๋กœ HTTP ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

1๏ธโƒฃ ย  ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๋กœ ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‹ฌ๋ผ์งˆ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋จผ์ € ์ „๋‹ฌ ๋ฐฉ์‹์„ ์•Œ์•„๋ณด์ž. ํฌ๊ฒŒ ์•„๋ž˜ 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‚˜๋‰œ๋‹ค.

  • ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐฉ์‹๊ณผ HTML Form ์„ ์‚ฌ์šฉํ•œ ์ „๋‹ฌ๋ฐฉ์‹์€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ „๋‹ฌ ๋ฐฉ์‹์„ค๋ช…์ƒ์„ธ์กฐํšŒ ๋ฉ”์„œ๋“œ
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐURL์˜ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•ด์„œ ์ „๋‹ฌhttp://localhost:8080/request-param-v2?username=hello&age=10@RequestParam, @ModelAttribute
HTML Form๋ฉ”์‹œ์ง€ ๋ฐ”๋””์— ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹์œผ๋กœ ์ „๋‹ฌํด๋ผ์ด์–ธํŠธ๊ฐ€ HTML Form ์—์„œ ๊ฐ’์„ ์ž…๋ ฅํ•˜๊ณ  ์ „์†ก ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋„˜์–ด์˜ค๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.ไธŠๅŒ
HTTP APImessage body ์— ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์„œ ์ „๋‹ฌ์ฃผ๋กœ JSONํ˜•์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.HttpEntityยซT>T>, @RequestBody

2๏ธโƒฃ ย  ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ - @RequestParam

  • ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์œผ๋กœ ๋ฐ”์ธ๋”ฉํ•ด์ค€๋‹ค. ๋ณ€์ˆ˜๋ช…์ด ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„๊ณผ ๊ฐ™๋‹ค๋ฉด name ์†์„ฑ์„ ์ƒ๋žตํ•ด๋„ ๋œ๋‹ค.

  • ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ Map, MultiValueMap ์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋“  ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ Map ์— ๋‹ด๊ธด๋‹ค. ๋‹ค๋งŒ ํ•˜๋‚˜์˜ key์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ด๊ธธ ๊ฒฝ์šฐ๋ฅผ ์ƒ์ •ํ•œ๋‹ค๋ฉด (key=userIds, value=[id1,id2]) MultiValueMap ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

@Slf4j
@Controller
public class RequestParamController {

    @ResponseBody
    @RequestMapping("/request-param-v3")
    public String requestParamV3(@RequestParam String username,
                                 @RequestParam int age)
    {
        log.info("username = {}, age = {}", username, age);
        return "ok";
    }

    @ResponseBody
    @RequestMapping("request-param-map")
    public String requestPatamMap(@RequestParam Map<String, Object> paramMap) {
        log.info("username = {}, age = {}", paramMap.get("username"), paramMap.get("age"));
        return "ok";
    }

}

3๏ธโƒฃ ย  ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ - @ModelAttribute

  • ์‹ค์ œ ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ๊ฐ์ฒด์— ๊ทธ ๊ฐ’์„ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค. ์ด ๊ณผ์ •์„ ์ž๋™ํ™”ํ•œ ๊ฒƒ์ด @ModelAttribute ์ด๋‹ค.

  • @ModelAttribute ์–ด๋…ธํ…Œ์ด์…˜์„ ์•„์˜ˆ ์ƒ๋žตํ•ด๋„ ๋˜์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ถŒ์žฅ๋˜์ง€๋Š” ์•Š๋Š” ๋ชจ์–‘์ด๋‹ค.

  • ์šฐ์„  ํ…Œ์ŠคํŠธ๋กœ ์‚ฌ์šฉํ•  HelloData ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.


import lombok.Data;

@Data
public class HelloData {
    private String username;
    private  int age;
}

  • @ModelAttribute ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์„œ ๋ฐ”๋กœ ๊ฐ์ฒด์— ๊ฐ’์„ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค.
@Slf4j
@Controller
public class RequestParamController {

    @ResponseBody
    @RequestMapping("/model-attribute-v1")
    public String modelAttributeV1(@ModelAttribute HelloData helloData) {
        log.info("username = {}, age = {}", helloData.getUsername(), helloData.getAge());
        log.info("heloData = {}", helloData);
        return "ok";
    }

}

โšก๏ธ ย  @ModelAttribute ์˜ ํŠน๋ณ„ํ•œ ์‚ฌ์šฉ๋ฒ• !

  • @ModelAttribute ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ฉ”์†Œ๋“œ ๋‹จ์œ„์— ์‚ฌ์šฉํ•˜๋ฉด, ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์š”์ฒญํ•  ๋•Œ, ๋ฉ”์†Œ๋“œ์˜ return ๊ฐ’์ด Model์— ์ž๋™์œผ๋กœ ๋‹ด๊ธฐ๊ฒŒ ๋œ๋‹ค.
@Controller
public class FormItemController {

    @ModelAttribute("regions")
    public Map<String, String> regions() {
        Map<String, String> regions = new LinkedHashMap<>();
        regions.put("SEOUL", "์„œ์šธ");
        regions.put("BUSAN", "๋ถ€์‚ฐ");
        regions.put("JEJU", "์ œ์ฃผ");
        return regions;
    }

}

4๏ธโƒฃ ย  HTTP API (๋‹จ์ˆœ ํ…์ŠคํŠธ) - HttpEntityยซT>T>

  • ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๋‹ค๋ฅด๊ฒŒ HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋””๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๊ฐ€ ์ง์ ‘ ๋„˜์–ด์˜ค๋Š” ๊ฒฝ์šฐ๋Š” @RequestParam, @ModelAttribute ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

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

  • HttpEntity ๊ฐ€ ์ œ๊ณตํ•˜๋Š” getBody, getHeader ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด HTTP ์ •๋ณด๋ฅผ ์–ป์–ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

  • ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๊ฐ€ HTTP header ์˜ Content-Type ์„ ๋ณด๊ณ  ํ•ด๋‹นํ•˜๋Š” ํƒ€์ž…์œผ๋กœ ์ž๋™์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค.

@Slf4j
@Controller
public class RequestBodyStringController {

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

        String messageBody = httpEntity.getBody();
        log.info("messagebody = {}", messageBody);

        return new HttpEntity<>("ok");
    }

}

5๏ธโƒฃ ย  HTTP API (๋‹จ์ˆœ ํ…์ŠคํŠธ) - @RequestBody

  • HttpEntity ๋ฅผ ๋” ๋‹จ์ˆœํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ๋‹ค.

  • @RequestBody ๋Š” HTTP ์˜ ๋ฐ”๋”” ์ •๋ณด๋งŒ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

@Slf4j
@Controller
public class RequestBodyStringController {

    @ResponseBody
    @PostMapping("request-body-string-v4")
    public String requestBodyStringV4(@RequestBody String messageBody) {
        log.info("messagebody = {}", messageBody);
        return "ok";
    }

}

6๏ธโƒฃ ย  HTTP API (JSON)

  • JSON Type ์œผ๋กœ ๋„˜์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ ์—ญ์‹œ HttpEntityยซT>T>, @RequestBody ๋ฐฉ์‹์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.
@Slf4j
@Controller
public class RequestBodyJsonController {

    @ResponseBody
    @PostMapping("request-body-json-v4")
    public String requestBodyJsonV4(HttpEntity<HelloData> helloData) {
        HelloData data = helloData.getBody();
        log.info("username = {}, age = {}", data.getUsername(), data.getAge());
        return "ok";
    }

    @ResponseBody
    @PostMapping("/request-body-json-v3")
    public String requestBodyJsonV3(@RequestBody HelloData helloData) {
        log.info("username = {}, age = {}", helloData.getUsername(), helloData.getAge());
        return "ok";
    }

}