Study/Spring

[Spring MVC] 03. @RequestMapping, HTTP ์š”์ฒญ ๋ฉ”์„ธ์ง€์™€ HTTP ์‘๋‹ต ๋ฉ”์„ธ์ง€

YURI๐Ÿ•๐Ÿ“๐Ÿถ 2022. 4. 19. 16:59
๋ฐ˜์‘ํ˜•

@RequestMapping

@Controller // ๋‚ด๋ถ€์— @Component ์• ๋…ธํ…Œ์ด์…˜์ด ์žˆ์–ด์„œ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์˜ ๋Œ€์ƒ์ด ๋œ๋‹ค
public class SpringMemberFormControllerV1 {
    @RequestMapping("/springmvc/v1/members/new-form") // ์š”์ฒญ์ •๋ณด๋ฅผ ๋งคํ•‘ํ•œ๋‹ค
    public ModelAndView process() { // ๋ชจ๋ธ๊ณผ ๋ทฐ์˜ ์ •๋ณด๋ฅผ ๋‹ด์•„์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค
        return new ModelAndView("new-form");
    }
}

RequestMappingHandlerMapping์€ ์Šคํ”„๋ง ๋นˆ ์ค‘์—์„œ @RequestMapping ๋˜๋Š” @Controller ๊ฐ€ ํด๋ž˜์Šค ๋ ˆ๋ฒจ์— ๋ถ™์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์— ๋งคํ•‘ ์ •๋ณด๋กœ ์ธ์‹ํ•œ๋‹ค.

 

ํด๋ž˜์Šค ๋ ˆ๋ฒจ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด @RequestMapping ์„ ๋‘๋ฉด ๋ฉ”์„œ๋“œ ๋ ˆ๋ฒจ๊ณผ ์กฐํ•ฉ์ด ๋œ๋‹ค.

@Controller
@RequestMapping("/springmvc/v2/members")
public class SpringMemberControllerV2 {}

ํด๋ž˜์Šค ๋ ˆ๋ฒจ @RequestMapping("/springmvc/v2/members")
๋ฉ”์„œ๋“œ ๋ ˆ๋ฒจ @RequestMapping("/new-form") โžก๏ธ /springmvc/v2/members/new-form

 

@RequestMapping ์†์„ฑ

โœ”๏ธ  HTTP ๋ฉ”์„œ๋“œ ๋งคํ•‘

@RequestMapping(value = "/mapping-get-v1", method = RequestMethod.GET)

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping์œผ๋กœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

โœ”๏ธ PathVariable ์‚ฌ์šฉ

@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data) { // ๋ณ€์ˆ˜๋ช…์ด ๊ฐ™์œผ๋ฉด @PathVariable ์ƒ๋žต ๊ฐ€๋Šฅ
}

// ๋‹ค์ค‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
@GetMapping("/mapping/users/{userId}/orders/{orderId}")
public String mappingPath(@PathVariable String userId, @PathVariable Long orderId) {
}

โœ”๏ธ  ํŠน์ • ํ—ค๋” ์กฐ๊ฑด ๋งคํ•‘

@GetMapping(value = "/mapping-header", headers = "mode=debug")

โœ”๏ธ  ๋ฏธ๋””์–ด ํƒ€์ž… ์กฐ๊ฑด ๋งคํ•‘ - Content-Type, consume

@PostMapping(value = "/mapping-consume", consumes = "application/json")

โœ”๏ธ  ๋ฏธ๋””์–ด ํƒ€์ž… ์กฐ๊ฑด ๋งคํ•‘ - Accept, produces

@PostMapping(value = "/mapping-produce", produces = "text/html")


 

 

HTTP ์š”์ฒญ ๋ฉ”์„ธ์ง€

@RequestParam

์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹์ด๋‚˜ POST(HTML Form)ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ ๋ฐ›์•˜์„ ๋•Œ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์œผ๋กœ input parameter์— ๋ฐ”์ธ๋”ฉํ•ด์ฃผ๋Š” ์–ด๋…ธํ…Œ์ด์…˜

@RequestParam("username") String memberName โžก๏ธ request.getParameter("username")

  • HTTP ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์ด ๋ณ€์ˆ˜ ์ด๋ฆ„๊ณผ ๊ฐ™์œผ๋ฉด @RequestParam(name="xx") ์ƒ๋žต ๊ฐ€๋Šฅ
  • String , int , Integer ๋“ฑ์˜ ๋‹จ์ˆœ ํƒ€์ž…์ด๋ฉด @RequestParam ๋„ ์ƒ๋žต ๊ฐ€๋Šฅ
    • @RequestParam ์• ๋…ธํ…Œ์ด์…˜์„ ์ƒ๋žตํ•˜๋ฉด ์Šคํ”„๋ง MVC๋Š” ๋‚ด๋ถ€์—์„œ required=false ๋ฅผ ์ ์šฉํ•œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ true์ด๋‹ค.
    • ์ด๋ ‡๊ฒŒ ์• ๋…ธํ…Œ์ด์…˜์„ ์™„์ „ํžˆ ์ƒ๋žตํ•ด๋„ ๋˜๋Š”๋ฐ, ๋„ˆ๋ฌด ์—†๋Š” ๊ฒƒ๋„ ์•ฝ๊ฐ„ ๊ณผํ•˜๋‹ค๋Š” ์ด์•ผ๊ธฐ๋„ ์žˆ๋‹ค.

 

โœ”๏ธ @RequestParam.required

  • ๊ธฐ๋ณธ๊ฐ’์€ true
  • /request-param?username=์ฒ˜๋Ÿผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์€ ์žˆ๊ณ  ๊ฐ’์€ ์—†๋Š”๊ฒฝ์šฐ ๋นˆ๋ฌธ์ž๋กœ ์ทจ๊ธ‰ํ•ด์„œ required๊ฐ€ true์—ฌ๋„ ํ†ต๊ณผ๋œ๋‹ค
  • ๊ธฐ๋ณธํ˜•(primitive)์— null์„ ์ž…๋ ฅํ•˜๋Š” ๊ฒฝ์šฐ required๊ฐ€ false์—ฌ๋„ null์„ ๊ธฐ๋ณธํ˜•์— ์ž…๋ ฅํ•˜๋Š”๊ฑด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ˆ์™ธ ๋ฐœ์ƒ

โœ”๏ธ @RequestParam.defaultValue

ํŒŒ๋ผ๋ฏธํ„ฐ์— ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ defaultValue ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ๋ณธ ๊ฐ’์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฏธ ๊ธฐ๋ณธ ๊ฐ’์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— required ๋Š” ์˜๋ฏธ๊ฐ€ ์—†๋‹ค. defaultValue ๋Š” ๋นˆ ๋ฌธ์ž์˜ ๊ฒฝ์šฐ์—๋„ ์„ค์ •ํ•œ ๊ธฐ๋ณธ ๊ฐ’์ด ์ ์šฉ๋œ๋‹ค.

โœ”๏ธ @RequestParam Map<String, Object> paramMap

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

 

 

@ModelAttribute

@ModelAttribute HelloData helloData

์Šคํ”„๋งMVC๋Š” @ModelAttribute ๊ฐ€ ์žˆ์œผ๋ฉด ๋‹ค์Œ์„ ์‹คํ–‰ํ•œ๋‹ค.

  1. HelloData ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  2. ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ด๋ฆ„์œผ๋กœ HelloData ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐพ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์˜ setter๋ฅผ ํ˜ธ์ถœํ•ด์„œ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ฐ’์„ ์ž…๋ ฅ(๋ฐ”์ธ๋”ฉ) ํ•œ๋‹ค.
    1. ์˜ˆ) ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์ด username ์ด๋ฉด setUsername() ๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์•„์„œ ํ˜ธ์ถœํ•˜๋ฉด์„œ ๊ฐ’์„ ์ž…๋ ฅํ•œ๋‹ค.

 

@ModelAttribute ๋Š” ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ @RequestParam ๋„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ํ˜ผ๋ž€์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์Šคํ”„๋ง์€ ์ƒ๋žต์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทœ์น™์„ ์ ์šฉํ•œ๋‹ค.

String , int , Integer ๊ฐ™์€ ๋‹จ์ˆœ ํƒ€์ž… = @RequestParam
๋‚˜๋จธ์ง€ = @ModelAttribute (argument resolver ๋กœ ์ง€์ •ํ•ด๋‘” ํƒ€์ž… ์™ธ)

 

์ถ”๊ฐ€ ๊ธฐ๋Šฅ

  • Model์— @ModelAttribute๋กœ ์ง€์ •ํ•œ ๊ฐ์ฒด๋ฅผ ์ž๋™์œผ๋กœ ๋„ฃ์–ด์ค€๋‹ค. 
  • ๋งŒ์•ฝ @ModelAttribute์˜ ์ด๋ฆ„์„ ์ƒ๋žตํ•˜๋ฉด ๋ชจ๋ธ์— ์ €์žฅ๋  ๋•Œ ํด๋ž˜์Šค๋ช…์„ ์‚ฌ์šฉํ•ด ์ €์žฅํ•œ๋‹ค(ํด๋ž˜์Šค์˜ ์ฒซ๊ธ€์ž๋งŒ ์†Œ๋ฌธ์ž๋กœ ๋ณ€๊ฒฝ)
/*
	@ModelAttribute("item") Item item
	model.addAtribute("item", item);  ์ž๋™์ถ”๊ฐ€
*/

/*
	@ModelAttribute HelloData hd
	model.addAtribute("helloData", hd);  ์ž๋™์ถ”๊ฐ€
*/

 

@RequestBody

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

@PostMapping("/request-body-json-v1")
public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 1. ServletInputStream์„ ์ด์šฉํ•ด์„œ ์ง์ ‘ ์ฝ๋Š” ๋ฐฉ๋ฒ•
    ServletInputStream inputStream = request.getInputStream();
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

    // ๋ฌธ์ž๋กœ ๋œ JSON ๋ฐ์ดํ„ฐ๋ฅผ Jackson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ objectMapper ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
    HelloData data = objectMapper.readValue(messageBody, HelloData.class);
}

@PostMapping("/request-body-string-v3")
// HttpEntity: HTTP header, body ์ •๋ณด๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด
// 3. HttpEntity<String>๋ฅผ ์ด์šฉํ•ด์„œ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
    String messageBody = httpEntity.getBody();
    return new HttpEntity<>("ok");
}

@ResponseBody // ๋ฉ”์‹œ์ง€ ๋ฐ”๋”” ์ •๋ณด ์ง์ ‘ ๋ฐ˜ํ™˜
@PostMapping("/request-body-json-v2")
// 4. @RequestBody`๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ”๋”” ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
    HelloData data = objectMapper.readValue(messageBody, HelloData.class);
    return "ok";
}
  1. ServletInputStream
  2. InputStream(input parameter๋กœ ๋ฐ”๋กœ ๋ฐ›์Œ)
  3. HttpEntity<String>
  4. @RequestBody
์ฐธ๊ณ 
@RequestBody๋Š” ์ƒ๋žต ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

์Šคํ”„๋ง์€ @ModelAttribute , @RequestParam ์ƒ๋žต์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทœ์น™์„ ์ ์šฉํ•œ๋‹ค

String , int , Integer ๊ฐ™์€ ๋‹จ์ˆœ ํƒ€์ž… = @RequestParam
๋‚˜๋จธ์ง€ = @ModelAttribute (argument resolver ๋กœ ์ง€์ •ํ•ด๋‘” ํƒ€์ž… ์™ธ)
๋”ฐ๋ผ์„œ ์ด ๊ฒฝ์šฐ HelloData์— @RequestBody ๋ฅผ ์ƒ๋žตํ•˜๋ฉด @ModelAttribute ๊ฐ€ ์ ์šฉ๋˜์–ด๋ฒ„๋ฆฐ๋‹ค.

HelloData data โžก๏ธ @ModelAttribute HelloData data

๋”ฐ๋ผ์„œ ์ƒ๋žตํ•˜๋ฉด HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋””๊ฐ€ ์•„๋‹ˆ๋ผ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค.

 

 

HTTP ์‘๋‹ต ๋ฉ”์„ธ์ง€

์ •์  ๋ฆฌ์†Œ์Šค

ํ•ด๋‹น ํŒŒ์ผ์„ ๋ณ€๊ฒฝ ์—†์ด ๊ทธ๋Œ€๋กœ ์„œ๋น„์Šคํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ํด๋ž˜์ŠคํŒจ์Šค์˜ ๋‹ค์Œ ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ๋Š” ์ •์  ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
/static , /public , /resources , /META-INF/resources

๋‹ค์Œ ๊ฒฝ๋กœ์— ํŒŒ์ผ์ด ๋“ค์–ด์žˆ์œผ๋ฉด src/main/resources/static/basic/hello-form.html
์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค. http://localhost:8080/basic/hello-form.html

๋ทฐ ํ…œํ”Œ๋ฆฟ

๋ทฐ ํ…œํ”Œ๋ฆฟ์„ ๊ฑฐ์ณ์„œ HTML์ด ์ƒ์„ฑ๋˜๊ณ , ๋ทฐ๊ฐ€ ์‘๋‹ต์„ ๋งŒ๋“ค์–ด์„œ ์ „๋‹ฌํ•œ๋‹ค.

๋ทฐ ํ…œํ”Œ๋ฆฟ ๊ฒฝ๋กœ : src/main/resources/templates

// ์ง์ ‘ modelAndView๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ 
@RequestMapping("/response-view-v1")
public ModelAndView responseViewV1() {
    ModelAndView mav = new ModelAndView("response/hello").addObject("data", "hello!");
    return mav;
}

// @ResponseBody ๊ฐ€ ์—†์œผ๋ฉด response/hello ๋กœ ๋ทฐ ๋ฆฌ์กธ๋ฒ„๊ฐ€ ์‹คํ–‰๋˜์–ด์„œ ๋ทฐ๋ฅผ ์ฐพ๊ณ , ๋ Œ๋”๋ง ํ•œ๋‹ค
// ์—ฌ๊ธฐ์„œ๋Š” ๋ทฐ์˜ ๋…ผ๋ฆฌ ์ด๋ฆ„์ธ response/hello ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋‹ค์Œ ๊ฒฝ๋กœ์˜ ๋ทฐ ํ…œํ”Œ๋ฆฟ์ด ๋ Œ๋”๋ง ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
// ์‹คํ–‰: templates/response/hello.html
@RequestMapping("/response-view-v2")
public String responseViewV2(Model model) {
    model.addAttribute("data", "hello!!");
    return "response/hello";
}

๋ฉ”์‹œ์ง€ ๋ฐ”๋””์— ์ง์ ‘ ์‘๋‹ต

@ResponseBody ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด view๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ํ†ตํ•ด์„œ HTTP ๋ฉ”์‹œ์ง€๋ฅผ ์ง์ ‘ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

@RestController

@Controller ๋Œ€์‹ ์— @RestController ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด, ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ์— ๋ชจ๋‘ @ResponseBody ๊ฐ€ ์ ์šฉ๋˜๋Š” ํšจ๊ณผ๊ฐ€ ์žˆ๋‹ค
@Controller ๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์ด String ์ด๋ฉด ๋ทฐ ์ด๋ฆ„์œผ๋กœ ์ธ์‹๋œ๋‹ค. ๊ทธ๋ž˜์„œ ๋ทฐ๋ฅผ ์ฐพ๊ณ  ๋ทฐ๊ฐ€ ๋žœ๋”๋ง ๋œ๋‹ค. @RestController ๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ๋ทฐ๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์— ๋ฐ”๋กœ ์ž…๋ ฅํ•œ๋‹ค.

 

๐Ÿ‘ Reference

 

๋ฐ˜์‘ํ˜•