๐Ÿ“—Spring MVC Study [ ์š”์ฒญ ๋งคํ•‘ ]

Caruhยท2025๋…„ 3์›” 20์ผ

Spring MVC

๋ชฉ๋ก ๋ณด๊ธฐ
13/17
post-thumbnail

์š”์ฒญ ๋งคํ•‘

๋งคํ•‘ ์ •๋ณด

@RestController

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

@RequestMapping("/hello-basic")

  • /hello-basic : URL ํ˜ธ์ถœ์ด ์˜ค๋ฉด ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ๋งคํ•‘ํ•œ๋‹ค.
  • ๋Œ€๋ถ€๋ถ„์˜ ์†์„ฑ์„ ๋ฐฐ์—ด[] ๋กœ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์ค‘ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ["/hello-basic", "/hello-go"]

์ฐธ๊ณ 

์Šคํ”„๋ง ๋ถ€ํŠธ 3.0 ์ด์ „

  • ์Šคํ”„๋ง์€ ๋‹ค์Œ URL ์š”์ฒญ๋“ค์„ ๊ฐ™์€ ์š”์ฒญ์œผ๋กœ ๋งคํ•‘
  • ๋งคํ•‘ : /hello-basic
  • URL ์š”์ฒญ : /hello-basic, /hello-basic/

์Šคํ”„๋ง ๋ถ€ํŠธ 3.0 ์ดํ›„

  • ๋งˆ์ง€๋ง‰์˜ /๋ฅผ ์œ ์ง€ํ•œ๋‹ค.
  • ๋งคํ•‘ : /hello-basic -> URL ์š”์ฒญ : /hello-basic
  • ๋งคํ•‘ : /hello-basic/ -> URL ์š”์ฒญ : /hello-basic/

HTTP ๋ฉ”์„œ๋“œ

  • @RequestMapping์— method ์†์„ฑ์œผ๋กœ HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด HTTP ๋ฉ”์„œ๋“œ์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ํ˜ธ์ถœ๋œ๋‹ค.
  • ๋ชจ๋‘ํ—ˆ์šฉ : GET, HEAD, POST, PUT, PATCH, DELETE

HTTP ๋ฉ”์„œ๋“œ ๋งคํ•‘

/**
 * method ํŠน์ • HTTP ๋ฉ”์„œ๋“œ ์š”์ฒญ๋งŒ ํ—ˆ์šฉ
 * GET, HEAD, POST, PUT, PATCH, DELETE
 */
 @RequestMapping(value = "/mapping-get-v1", method = RequestMethod.GET)
 public String mappingGetV1() {
    log.info("mappingGetV1");
 	return "ok";
 }
  • ๋งŒ์•ฝ ์—ฌ๊ธฐ์— POST ์š”์ฒญ์„ ํ•˜๋ฉด ์Šคํ”„๋ง MVC๋Š” HTTP 405 ์ƒํƒœ์ฝ”๋“œ (Method Not Allowed)๋ฅผ ๋ฐ˜ํ™˜

HTTP ๋ฉ”์„œ๋“œ ๋งคํ•‘ ์ถ•์•ฝ

 /**
 * ํŽธ๋ฆฌํ•œ ์ถ•์•ฝ ์• ๋…ธํ…Œ์ด์…˜ (์ฝ”๋“œ๋ณด๊ธฐ)
 * @GetMapping
 * @PostMapping
 * @PutMapping
 * @DeleteMapping
 * @PatchMapping
 */
 @GetMapping(value = "/mapping-get-v2")
 public String mappingGetV2() {
    log.info("mapping-get-v2");
 	return "ok";
 }
  • HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์ถ•์•ฝํ•œ ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ง๊ด€์ ์ด๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด @RequestMapping๊ณผ method๋ฅผ ์ง€์ •ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

PathVariable(๊ฒฝ๋กœ ๋ณ€์ˆ˜) ์‚ฌ์šฉ

 /**
 * PathVariable ์‚ฌ์šฉ
 * ๋ณ€์ˆ˜๋ช…์ด ๊ฐ™์œผ๋ฉด ์ƒ๋žต ๊ฐ€๋Šฅ
 * @PathVariable("userId") String userId -> @PathVariable String userId
 */
 @GetMapping("/mapping/{userId}")
 public String mappingPath(@PathVariable("userId") String data) {
    log.info("mappingPath userId={}", data);
 	return "ok";
 }
  • ์ตœ๊ทผ HTTP API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ์— ์‹๋ณ„์ž๋ฅผ ๋„ฃ๋Š” ์Šคํƒ€์ผ์„ ์„ ํ˜ธ
    • /mapping/userA
    • /users/1
    • @RequestMapping์€ URL ๊ฒฝ๋กœ๋ฅผ ํ…œํ”Œ๋ฆฟํ™” ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, @PathVariable์„ ์‚ฌ์šฉํ•˜๋ฉด ๋งค์นญ ๋˜๋Š” ๋ถ€๋ถ„์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.
    • @PathVariable์˜ ์ด๋ฆ„๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์ด ๊ฐ™์œผ๋ฉด ์ƒ๋žต ๊ฐ€๋Šฅ

PathVariable ์‚ฌ์šฉ - ๋‹ค์ค‘

/**
 * PathVariable ์‚ฌ์šฉ ๋‹ค์ค‘
 */
 @GetMapping("/mapping/users/{userId}/orders/{orderId}")
 public String mappingPath(@PathVariable String userId, @PathVariable Long 
orderId) {
    log.info("mappingPath userId={}, orderId={}", userId, orderId);
 	return "ok";
 }
  • url์—์„œ ๋„˜์–ด์˜จ PathVariable์„ ์œ„์™€๊ฐ™์ด ๋‹ค์ค‘์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

ํŠน์ • ํŒŒ๋ผ๋ฏธํ„ฐ ์กฐ๊ฑด ๋งคํ•‘

/**
 * ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ถ”๊ฐ€ ๋งคํ•‘
 * params="mode",
 * params="!mode"
 * params="mode=debug"
 * params="mode!=debug" (! = )
 * params = {"mode=debug","data=good"}
 */
 @GetMapping(value = "/mapping-param", params = "mode=debug")
 public String mappingParam() {
    log.info("mappingParam");
 	return "ok";
 }
  • ํŠน์ • ํŒŒ๋ผ๋ฏธํ„ฑ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์—†๋Š” ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ž˜ ์‚ฌ์šฉํ•˜์ง€๋А ์•Š์Œ -> ๊ณต๋ถ€์šฉ์œผ๋กœ ์•Œ๊ณ ๋งŒ ์žˆ์ž.

ํŠน์ • ํ—ค๋” ์กฐ๊ฑด ๋งคํ•‘

 /**
 * ํŠน์ • ํ—ค๋”๋กœ ์ถ”๊ฐ€ ๋งคํ•‘
 * headers="mode",
 * headers="!mode"
 * headers="mode=debug"
 * headers="mode!=debug" (! = )
 */
 @GetMapping(value = "/mapping-header", headers = "mode=debug")
 public String mappingHeader() {
    log.info("mappingHeader");
 	return "ok";
 }
  • ํŒŒ๋ผ๋ฏธํ„ฐ ๋งคํ•‘๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉ
  • POSTMAN์œผ๋กœ ํ…Œ์ŠคํŠธํ•  ๊ฒฝ์šฐ ํŽธํ•จ. (์•„๋ž˜์˜ ์ฝ”๋“œ๋„ ๋ชจ๋‘ postman์—์„œ ํ…Œ์ŠคํŠธ)> POSTMAN headers ์ •๋ณด์—์„œ mode > debug๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ log๊ฐ€ ์ฐํžˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฏธ๋””์–ด ํƒ€์ž… ์กฐ๊ฑด ๋งคํ•‘ - HTTP ์š”์ฒญ Content-type, consume

/**
 * Content-Type ํ—ค๋” ๊ธฐ๋ฐ˜ ์ถ”๊ฐ€ ๋งคํ•‘ Media Type
 * consumes="application/json"
 * consumes="!application/json"
 * consumes="application/*"
 * consumes="*\/*"
 * MediaType.APPLICATION_JSON_VALUE
 */
 @PostMapping(value = "/mapping-consume", consumes = "application/json")
 public String mappingConsumes() {
    log.info("mappingConsumes");
 	return "ok";
 }
  • HTTP ์š”์ฒญ์˜ Content-Type ํ—ค๋”๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฏธ๋””์–ด ํƒ€์ž…์œผ๋กœ ๋งคํ•‘ํ•œ๋‹ค.
  • ๋งŒ์•ฝ ๋งž์ง€ ์•Š์œผ๋ฉด HTTP 415 ์ƒํƒœ์ฝ”๋“œ (Unsupported Media Type)์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์˜ˆ์‹œ

consumes = "text/plain"
consumes = {"text/plain" "application/*"}
consumes = MediaType.TEXT_PLAIN_VALUE

๋ฏธ๋””์–ด ํƒ€์ž… ์กฐ๊ฑด ๋งคํ•‘ - HTTP ์š”์ฒญ Accept, produce

 /**
 * Accept ํ—ค๋” ๊ธฐ๋ฐ˜ Media Type
 * produces = "text/html"
 * produces = "!text/html"
 * produces = "text/*"
 * produces = "*\/*"
 */
 @PostMapping(value = "/mapping-produce", produces = "text/html")
 public String mappingProduces() {
    log.info("mappingProduces");
 	return "ok";
 }
  • HTTP ์š”์ฒญ์˜ Accept ํ—ค๋”๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฏธ๋””์–ด ํƒ€์ž…์œผ๋กœ ๋งคํ•‘ํ•œ๋‹ค.
  • ๋งŒ์•ฝ ๋งž์ง€ ์•Š์œผ๋ฉด HTTP 406 ์ƒํƒœ์ฝ”๋“œ (Not Acceptable)์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์˜ˆ์‹œ

produces = "text/plain"
produces = {"text/plain", "application/*"}
produces = MediaType.TEXT_PLAIN_VALUE
produces = "text/plain;charset=UTF-8"


์š”์ฒญ ๋งคํ•‘ - API ์˜ˆ์‹œ

  • ํšŒ์› ๊ด€๋ฆฌ API(์˜ˆ์‹œ)
API ๋ชฉ๋กHTTP METHODURL
ํšŒ์› ๋ชฉ๋ก ์กฐํšŒGET/users
ํšŒ์› ๋“ฑ๋กPOST/users
ํšŒ์› ์กฐํšŒGET/users/{userId}
ํšŒ์› ์ˆ˜์ •PATCH/users/{userId}
ํšŒ์› ์‚ญ์ œDELETE/users/{userId}
@RestController
@RequestMapping("/mapping/users")
public class MappingClassController {

    @GetMapping
    public String user() {
        return "get users";
    }

    @PostMapping
    public String addUser() {
        return "post user";
    }

    @GetMapping("/{userId}")
    public String findUser(@PathVariable String userId) {
        return "get userId = " + userId;
    }

    @PatchMapping("/{userId}")
    public String updateUser(@PathVariable String userId) {
        return "update userId = " + userId;
    }

    @DeleteMapping("/{userId}")
    public String deleteUser(@PathVariable String userId) {
        return "delete userId = " + userId;
    }
}

์ด๋ ‡๊ฒŒ Spring์—์„œ http ์š”์ฒญ์„ ๋ฐ›์•˜์„๋•Œ ์–ด๋–ป๊ฒŒ request์š”์ฒญ์„ ๋ฐ›๋Š”์ง€ ๊ทธ๋ฆฌ๊ณ  request์— ์–ด๋– ํ•œ ์ œ์•ฝ์„ ๋ถ€์—ฌํ•˜๊ณ  ์ œ์•ฝ์ด ๋งž์•˜์„ ๊ฒฝ์šฐ์—๋งŒ ์š”์ฒญ์„ ๋ฐ›์•„๋“ค์ผ์ˆ˜ ์žˆ๋Š”์ง€, ๊ธฐ๋ณธ์ ์ธ ํ˜•ํƒœ์˜ HTTP METHOD ์š”์ฒญ์ด ์˜ค๋ฉด ์ž‘๋™ํ•˜๋Š” API๋ฅผ ๊ฐ€๋ณ๊ฒŒ ๋งŒ๋“ค์–ด ๋ณด์•˜๋‹ค.

๐Ÿ“ญ Reference

profile
Backend Developer

0๊ฐœ์˜ ๋Œ“๊ธ€