์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

Spring ์ž…๋ฌธ 1์ฃผ์ฐจ : Spring MVC

KIMHYEYUN 2023. 11. 2. 16:02
๋ฐ˜์‘ํ˜•

Spring MVC

MVC ๋””์ž์ธ ํŒจํ„ด

  • MVC๋ž€ Model-View-Controller์˜ ์•ฝ์ž๋กœ, ์†Œํ”„ํŠธ์›จ์–ด ๋””์ž์ธ ํŒจํ„ด ์ค‘ ํ•˜๋‚˜
  • MVC ํŒจํ„ด์€ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์š”์†Œ๋“ค์„ Model, View, Controller๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ๊ฐ๊ฐ์˜ ์—ญํ• ์„ ๋ถ„๋ฆฌ

Model

  • ๋ฐ์ดํ„ฐ์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๋‹น
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์—ฐ๋™ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰

View

  • ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ๋‹ด๋‹น

Controller

  • Model๊ณผ View ์‚ฌ์ด์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ์กฐ์ •ํ•˜๊ณ  ์ œ์–ด
  • ์ž…๋ ฅ์„ ๋ฐ›์•„ Model์— ์ „๋‹ฌํ•˜๊ณ , Model์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ View๋ฅผ ์—…๋ฐ์ดํŠธ

MVC ํŒจํ„ด์€ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์š”์†Œ๋“ค์„ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๊ณ , ๊ฐœ๋ฐœ์ž๋“ค ๊ฐ„์˜ ํ˜‘์—…์„ ์šฉ์ดํ•˜๊ฒŒ ํ•จ.
๋”ฐ๋ผ์„œ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ฐœ๋ฐœํ• , MVC ํŒจํ„ด์„ ์ ์šฉํ•˜์—ฌ ๊ตฌ์กฐ๋ฅผ ์ž˜ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•จ

Spring MVC

Spring Web MVC๋Š” Servlet API๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ๋…์ฐฝ์ ์ธ ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ์ฒ˜์Œ๋ถ€ํ„ฐ Spring Framework์— ํฌํ•จ๋˜์–ด ์™”์Œ
์ค‘์•™์— ์žˆ๋Š” DispatcherServlet์ด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ณต์œ  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ œ๊ณตํ•˜๋Š” Front Controller ํŒจํ„ด์„ ์ค‘์‹ฌ์œผ๋กœ ์„ค๊ณ„๋˜์–ด ์žˆ์œผ๋ฉฐ ์ด ๋ชจ๋ธ์€ ์œ ์—ฐํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์›Œํฌ ํ”Œ๋กœ์šฐ๋ฅผ ์ง€์›ํ•จ

Servlet?

  • ์ž๋ฐ”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น ํŽ˜์ด์ง€๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ์„œ๋ฒ„ ์ธก ํ”„๋กœ๊ทธ๋žจ ํ˜น์€ ๊ทธ ์‚ฌ์–‘
  • ์‚ฌ์šฉ์ž๊ฐ€ API ์š”์ฒญํ–ˆ์„ ๋Œ€ ์„œ๋ฒ„์˜ ์„œ๋ธ”๋ฆฟ์ด ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹
  1. ์‚ฌ์šฉ์ž๊ฐ€ client๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— HTTP Request ์ฆ‰, API ์š”์ฒญ
  2. ์š”์ฒญ์„ ๋ฐ›์€ Servlet ์ปจํ…Œ์ด๋„ˆ๋Š” HttpServletRequest, HttpServletResponse ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
    • HTTP ๊ทœ๊ฒฉ์„ ๋งž์ถ”๋ฉด์„œ ์‰ฝ๊ฒŒ HTTP์— ๋‹ด๊ธด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด
  3. ์„ค์ •๋œ ์ •๋ณด๋ฅผ ํ†ตํ•ด ์–ด๋– ํ•œ Servlet์— ๋Œ€ํ•œ ์š”์ฒญ์ธ์ง€ ํƒ์ƒ‰
  4. ํ•ด๋‹น Servlet์—์„œ service ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๋’ค ๋ธŒ๋ผ์šฐ์ € ์š”์ฒญ Method์— ๋”ฐ๋ผ doGet ํ˜น์€ doPost๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ
  5. ํ˜ธ์ถœํ•œ ๋ฉ”์„œ๋“œ์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ๋™์  ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•œ ๋’ค HttpServletResponse ๊ฐ์ฒด์— ์‘๋‹ต์„ ๋‹ด์•„ Client์— ๋ฐ˜ํ™˜
  6. ์‘๋‹ต์ด ์™„๋ฃŒ๋˜๋ฉด ์ƒ์„ฑํ•œ HttpServletRequest, HttpServletResponse ๊ฐ์ฒด ์†Œ๋ฉธ

Front Controller?

  • ๋ชจ๋“  API ์š”์ฒญ์„ ์•ž์„œ ์‚ดํŽด๋ณธ ์„œ๋ธ”๋ฆฟ์˜ ๋™์ž‘ ๋ฐฉ์‹์— ๋งž์ถฐ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด ๋ฌด์ˆ˜ํžˆ ๋งŽ์€ Servlet ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ
  • ๋”ฐ๋ผ์„œ Spring์€ DispatcherServlet์„ ์‚ฌ์šฉํ•˜์—ฌ Front Controller ํŒจํ„ด ๋ฐฉ์‹์œผ๋กœ API ์š”์ฒญ์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ
  • Front Controller ํŒจํ„ด ๋™์ž‘ ๊ณผ์ •
    1. Client์—์„œ HTTP ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด DispatcherServlet ๊ฐ์ฒด๊ฐ€ ์š”์ฒญ์„ ๋ถ„์„
    2. DispatcherServlet๊ฐ์ฒด๋Š” ๋ถ„์„ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ† ๋Œ€๋กœ Handler mapping์„ ํ†ตํ•ด Controller๋ฅผ ์ฐพ์•„ ์š”์ฒญ ์ „๋‹ฌ
      • API path ์ฆ‰, URL์„ Controller์— ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ @Controller ์• ๋…ธํ…Œ์ด์…˜์ด ๋‹ฌ๋ ค์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ ๋’ค @GetMapping์ฒ˜๋Ÿผ ์š”์ฒญํ•œ HTTP Method์™€ ์ผ์น˜ํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„
        • ์ง์ ‘ Servlet์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ DispatcherServlet์— ์˜ํ•ด ๊ฐ„ํŽธํ•˜๊ฒŒ HTTP ์š”์ฒญ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
    3. Controller -> DispathcerServlet
      • ํ•ด๋‹น Controller๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์™„๋ฃŒํ•œ ํ›„ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ์ฆ‰, ๋ฐ์ดํ„ฐ(Model)์™€ View ์ •๋ณด๋ฅผ ์ „๋‹ฌ
    4. DispatcherServlet -> Client
      • ViewResolver๋ฅผ ํ†ตํ•ด View์— Model์„ ์ ์šฉํ•˜์—ฌ View๋ฅผ Client์—๊ฒŒ ์‘๋‹ต์„ ์ „๋‹ฌํ•จ

์ •์  ํŽ˜์ด์ง€์™€ ๋™์  ํŽ˜์ด์ง€

@Controller vs @RestController

  • @Controller : ์ „ํ†ต์ ์ธ Spring MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ
  • @RestController : RESTful ์›น ์„œ๋น„์Šค์˜ ์ปจํŠธ๋กค๋Ÿฌ
  • ์ฃผ์š”ํ•œ ์ฐจ์ด์ ์€ HTTP Response Body๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๋ฐฉ์‹

@RestController

  • @Controller์— @ResponseBody๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒƒ
  • ์ฃผ์šฉ๋„๋Š” Json ํ˜•ํƒœ๋กœ ๊ฐ์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ

Jackson?

Jackson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • JSON ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    • Object๋ฅผ JSON ํƒ€์ž…์˜ String์œผ๋กœ ๋ฐ˜ํ™˜ ๊ฐ€๋Šฅ
  • Spring 3 ์ดํ›„๋กœ Jackson๊ณผ ๊ด€๋ จ๋œ API๋ฅผ ์ œ๊ณตํ•จ์œผ๋กœ์จ, ์ง์ ‘ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ JSON ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์•„๋„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ณ  ์žˆ์Œ

Object To JSON

@Test
@DisplayName("Object To JSON : get Method ํ•„์š”")
void test1() throws JsonProcessingException {
    Star star = new Star("Robbie", 95);

    ObjectMapper objectMapper = new ObjectMapper();
    String json = objectMapper.writeValueAsString(star);

    System.out.println("json = " + json);

JSON To Object

@Test
@DisplayName("JSON To Object : ๊ธฐ๋ณธ ์ƒ์„ฑ์ž & (get or set) Method ํ•„์š”")
void test2() throws JsonProcessingException {
    String json = "{\"name\":\"Robbie\",\"age\":95}";

    ObjectMapper objectMapper = new ObjectMapper();

    Star star = objectMapper.readValue(json, Star.class);
    System.out.println("star.getName() = " + star.getName());

Path Variable๊ณผ Request Param

  • Path Variable

    • Client์—์„œ ์„œ๋ฒ„๋กœ HTTP ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•จ๊ป˜ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Œ
    • ์„œ๋ฒ„์—์„œ๋Š” ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๋ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์ด ํ•œ ๊ฐ€์ง€๊ฐ€ ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๋ฐฉ์‹์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ด์•ผ ํ•จ
    • Path Variable ๋ฐฉ์‹

      GET http://localhost:8080/hello/request/star/Robbie/age/95

    • ์„œ๋ฒ„์— ๋ณด๋‚ด๋ ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ URL ๊ฒฝ๋กœ์— ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
    • 'Robbie'์™€ '95' ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด URL ๊ฒฝ๋กœ์— ์ถ”๊ฐ€
      // [Request sample]
      // GET http://localhost:8080/hello/request/star/Robbie/age/95
      @GetMapping("/star/{name}/age/{age}")
      @ResponseBody
      public String helloRequestPath(@PathVariable String name, @PathVariable int age)
      {
        return String.format("Hello, @PathVariable.<br> name = %s, age = %d", name, age);
      }
  • Request Param

    GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95

    • ์„œ๋ฒ„์— ๋ณด๋‚ด๋ ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ URL ๊ฒฝ๋กœ ๋งˆ์ง€๋ง‰์— ?๊ณผ &์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ

      // [Request sample]
      // GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95
      @GetMapping("/form/param")
      @ResponseBody
      public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
            return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
      }
728x90
๋ฐ˜์‘ํ˜•