Framework/Spring Framework

@RequestBody, @RequestParam, @PathVariable, @ModelAttribute์˜ ์ฐจ์ด

ํ”„๋กœ๊ทธ๋ž˜๋จธ ์˜ค์›” 2024. 6. 30.

์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ HTTP ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ๋กœ ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•˜๋‹ค. ๊ฐ๊ฐ์˜ ์• ๋…ธํ…Œ์ด์…˜์€ ๋‹ค๋ฅธ ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. ๋‹ค์Œ์€ @RequestBody, @RequestParam, @PathVariable, @ModelAttribute์˜ ์ฐจ์ด์™€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•๊ณผ ๋‚ด๋ถ€์  ์ž‘๋™ ๋ฐฉ์‹์— ๋Œ€ํ•ด์„œ ๋‹ค๋ค„๋ณด์•˜๋‹ค.

@RequestBody

์„ค๋ช…

  • @RequestBody๋Š” HTTP ์š”์ฒญ ๋ณธ๋ฌธ์„ ๊ฐ์ฒด์— ๋งคํ•‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • ์ฃผ๋กœ JSON, XML ๋“ฑ์˜ ํฌ๋งท์œผ๋กœ ์ „์†ก๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
  • JSON ๋ฐ์ดํ„ฐ ๊ฒฝ์šฐ HttpMessageConverter ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด MappingJackson2HttpMessageConverter ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์š”์ฒญ ๋ณธ๋ฌธ์„ ์ฝ๊ณ , ํ•ด๋‹น ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. MappingJackson2HttpMessageConverter ํด๋ž˜์Šค์•ˆ์—์„  ObjectMapper๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

์ด๋ฏธ์น˜ ์ถœ์ฒ˜ : https://tecoble.techcourse.co.kr/post/2021-05-11-requestbody-modelattribute/

์‚ฌ์šฉ ์˜ˆ

์ปค์Šคํ…€ ์ปจํŠธ๋กค๋Ÿฌ

import org.springframework.web.bind.annotation.*;

@RestController
public class MyController {

    @PostMapping("/users")
    public String createUser(@RequestBody User user) {
        // ์š”์ฒญ ๋ณธ๋ฌธ(JSON)์„ User ๊ฐ์ฒด๋กœ ๋งคํ•‘
        return "User is created with name: " + user.getName();
    }
}

User ํด๋ž˜์Šค

public class User {
    private String name;
    private String email;

    // getters and setters
}

์š”์ฒญ ์˜ˆ์‹œ (JSON)

{
    "name": "John Doe",
    "email": "john.doe@example.com"
}

@RequestParam

์„ค๋ช…

  • @RequestParam์€ HTTP ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋งคํ•‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • ์ฃผ๋กœ ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง ํŒŒ๋ผ๋ฏธํ„ฐ๋‚˜ ํผ ๋ฐ์ดํ„ฐ์˜ ๋‹จ์ผ ๊ฐ’์„ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
  • HandlerMethodArgumentResolver ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด์ธ RequestParamMethodArgumentResolver ํด๋ž˜์Šค๋กœ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ์ถ”์ถœํ•˜๊ณ  WebDataBinder๋ฅผ ํ†ตํ•ด ์ถ”์ถœ๋œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค.

์‚ฌ์šฉ ์˜ˆ

์ปค์Šคํ…€ ์ปจํŠธ๋กค๋Ÿฌ

import org.springframework.web.bind.annotation.*;

@RestController
public class MyController {

    @GetMapping("/greeting")
    public String greeting(@RequestParam(name = "name", defaultValue = "World") String name) {
        // ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋งคํ•‘
        return "Hello, " + name;
    }
}

์š”์ฒญ ์˜ˆ์‹œ

GET /greeting?name=John

@PathVariable

์„ค๋ช…

  • @PathVariable์€ URL ๊ฒฝ๋กœ์˜ ์ผ๋ถ€๋ฅผ ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋งคํ•‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • ์ฃผ๋กœ RESTful ์›น ์„œ๋น„์Šค์—์„œ ์ž์›์˜ ์‹๋ณ„์ž๋ฅผ ๊ฒฝ๋กœ ๋ณ€์ˆ˜๋กœ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
  • HandlerMethodArgumentResolver ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด์ธ PathVariableMethodArgumentResolver ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ @ PathVariable ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๊ฒฝ๋กœ ๋ณ€์ˆ˜๋ฅผ ์ถ”์ถœํ•˜๊ณ , WebDataBinder๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ’์„ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค.

์‚ฌ์šฉ ์˜ˆ

์ปค์Šคํ…€ ์ปจํŠธ๋กค๋Ÿฌ

import org.springframework.web.bind.annotation.*;

@RestController
public class MyController {

    @GetMapping("/users/{userId}")
    public String getUser(@PathVariable String userId) {
        // URL ๊ฒฝ๋กœ ๋ณ€์ˆ˜(userId)๋ฅผ ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋งคํ•‘
        return "User ID: " + userId;
    }
}

์š”์ฒญ ์˜ˆ์‹œ

GET /users/123

@ModelAttribute

์„ค๋ช…

  • @ModelAttribute๋Š” ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ์ฒด์— ๋งคํ•‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • ์ฃผ๋กœ ํผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ๋ชจ๋ธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
  • ๊ฐ์ฒด์˜ ํ•„๋“œ์™€ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์„ ๋งคํ•‘ํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • HandlerMethodArgumentResolver ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด์ธ ModelAttributeMethodProcessor ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด,  @ModelAttribute๊ฐ€ ์ ์šฉ๋œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”์ถœํ•œ๋‹ค. WebDataBinder ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”์ถœ๋œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ƒ์„ฑ๋œ ๊ฐ์ฒด์˜ ํ•„๋“œ์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค.

์‚ฌ์šฉ ์˜ˆ

์ปค์Šคํ…€ ์ปจํŠธ๋กค๋Ÿฌ

import org.springframework.web.bind.annotation.*;
import org.springframework.ui.Model;

@Controller
public class MyController {
	
    // ์ด ๋ฉ”์„œ๋“œ๋Š” MyController ๋‚ด์˜ ๋ชจ๋“  ์š”์ฒญ ์ „์— ์‹คํ–‰๋˜๋ฉฐ ๋ชจ๋ธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("globalAttribute", "This is a global attribute");
    }

    @PostMapping("/form")
    public String submitForm(@ModelAttribute User user) {
        // ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ User ๊ฐ์ฒด๋กœ ๋งคํ•‘
        return "Submitted user with name: " + user.getName();
    }
}

@ModelAttribute ์–ด๋…ธํ…Œ์ด์…˜์€ ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ์— ์ ์šฉ๋˜์–ด, @ModelAttribute ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์— ์ถ”๊ฐ€๋œ ๋ฐ์ดํ„ฐ๋Š” ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ ๋‚ด์˜ ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ๋ชจ๋ธ์— ์ž๋™์œผ๋กœ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค . ์ด ๋ฐฉ๋ฒ•์€ ์ฃผ๋กœ ๋ชจ๋ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜, ๋ทฐ์— ๊ณตํ†ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด @ModelAttribute ์–ด๋…ธํ…Œ์ด์…˜ ์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๋Š” MyController์˜ ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ๋ชจ๋ธ์— globalAttribute๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

User ํด๋ž˜์Šค

public class User {
    private String name;
    private String email;

    // getters and setters
}

์š”์ฒญ ์˜ˆ์‹œ (ํผ ๋ฐ์ดํ„ฐ)

POST /form
Content-Type: application/x-www-form-urlencoded

name=John&email=john.doe@example.com

์ฃผ์š” ์ฐจ์ด์  ์š”์•ฝ

์–ด๋…ธํ…Œ์ด์…˜ ์„ค๋ช… ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€
@RequestBody HTTP ์š”์ฒญ ๋ณธ๋ฌธ์„ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ JSON, XML ๋“ฑ์œผ๋กœ ์ „์†ก๋œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
@RequestParam HTTP ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋งคํ•‘ ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง, ํผ ๋ฐ์ดํ„ฐ์˜ ๋‹จ์ผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ฒ˜๋ฆฌ
@ModelAttribute HTTP ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ ๋ฐ ๋ชจ๋ธ์— ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ํผ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด ๋ณ€ํ™˜, ๋ชจ๋ธ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€, ๋ณต์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์˜  Query String ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅ
@PathVariable URL ๊ฒฝ๋กœ์˜ ์ผ๋ถ€๋ฅผ ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋งคํ•‘ ๊ฒฝ๋กœ ๋ณ€์ˆ˜๋กœ ์ž์› ์‹๋ณ„์ž ์ „๋‹ฌ

๊ฒฐ๋ก 

@RequestBody, @RequestParam, @ModelAttribute, @PathVariable๋Š” ๊ฐ๊ฐ HTTP ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค. @RequestBody๋Š” ์š”์ฒญ ๋ณธ๋ฌธ์„ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ, @RequestParam์€ ๋‹จ์ผ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. @ModelAttribute๋Š” ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๋ชจ๋ธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. @PathVariable์€ URL ๊ฒฝ๋กœ์˜ ์ผ๋ถ€๋ฅผ ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋งคํ•‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

๋Œ“๊ธ€