Spring

Spring ๊ธฐ์ดˆ๋‹ค์ง€๊ธฐ [์ •์ ์ปจํ…์ธ  / MVC / API]

DAHLIA CHOI 2021. 6. 10. 17:18

์ €๋ฒˆ์— ์ด์–ด์„œ ์˜ค๋Š˜๋„ ๊ธฐ์ดˆ๋ฅผ ๋ฐฐ์› ๋‹ค!

์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ์€ ์ •์ ์ปจํ…์ธ , MVC, api์— ๊ด€๋ จ๋œ ๋‚ด์šฉ์ด๋‹ค.

์•„์ฃผ ์Šคํ”„๋ง ๊ฑธ์Œ๋งˆ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ฒƒ ๊ฐ™์€ ๊ธฐ๋ถ€๋‹ˆ๋‹ค ํ™งํŒ…(เน‘หƒฬตแด—ห‚ฬต)ูˆ โ™ก

 

 


1. ์ •์ ์ปจํ…์ธ 

์ •์ ์ปจํ…์ธ ๋Š” ๊ทธ๋ƒฅ ํŒŒ์ผ์„ ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค.

resources์— staticํŒŒ์ผ์— hello-static.html ํŒŒ์ผ์„ ๋งŒ๋“ค์—ˆ๋‹ค.

<!DOCTYPE HTML>
<html>
<head>
    <title>static content</title>
    <meta http-equiv="Content-Type" content="text/html; charset = UTF-8"/>
</head>
<body>
์ •์  ์ปจํ…์ธ  ์ž…๋‹ˆ๋‹ค.
</body>
</html>

์ด๊ฑธ ์›น๋ธŒ๋ผ์šฐ์ €์— ์‹คํ–‰์‹œ์ผœ๋ณด๋ฉด body๋ฌธ์— ์จ ์žˆ๋Š” ๋ฌธ์žฅ์ด ๊ทธ๋Œ€๋กœ ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

 

์‹คํ–‰๊ณผ์ •

 

- ์›น๋ธŒ๋ผ์šฐ์ €์—์„œ localhlost:8080/hello-static.html ์ฃผ์†Œ๋ฅผ ํ†ฐ์บฃ ์„œ๋ฒ„์— ๋ณด๋‚ธ๋‹ค.

- ํ†ฐ์บฃ ์„œ๋ฒ„๋Š” ์Šคํ”„๋ง์—๊ฒŒ ๋ณด๋‚ด๊ณ , ์Šคํ”„๋ง์—์„œ๋Š” hello-static ๊ด€๋ จ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋จผ์ € ์ฐพ๊ณ  ์—†์œผ๋ฉด, resources์— ์žˆ๋Š” html์„ ์ฐพ๋Š”๋‹ค. (์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ฐพ๋Š”๊ฒŒ ์šฐ์„ ์ˆœ์œ„์ด๋‹ค.)

- ๋‹ค์‹œ ์›น๋ธŒ๋ผ์šฐ์ €์— html์„ ๋ณด๋‚ด์„œ ํ™”๋ฉด์— ๋ณด์—ฌ์ค€๋‹ค.

 

 

ํ•˜์ง€๋งŒ ์ •์ ์ปจํ…์ธ ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ ์ธ ์ฝ”๋”ฉ์€ ๋ชปํ•œ๋‹ค! ๊ทธ๋ž˜์„œ mvc์™€ api๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค!

 

2. MVC

MVC๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ Model, View, Controller ๋ฐฉ์‹์œผ๋กœ ์ชผ๊ฐœ์„œ, view๋ฅผ ํ…œํ”Œ๋ฆฟ ์—”์ง„์œผ๋กœ html์„ ์ข€ ๋” ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•œ ๊ฒƒ์„ ๋ Œ๋”๋งํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ Œ๋”๋งํ•œ html์„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค.

๊ณผ๊ฑฐ์—๋Š” view๋ž‘ controller๊ฐ€ ๋ถ„๋ฅ˜๋ผ์žˆ์ง€๋Š” ์•Š์•˜๋‹ค๊ณ  ํ•œ๋‹ค.

 

@GetMapping("hello-mvc")
public String helloMvc(@RequestParam(  "name") String name, Model model){
    model.addAttribute("name", name);
    return "hello-template";
}

๊ธฐ์กด์— ์žˆ๋˜ HelloController ์ž๋ฐ” ํŒŒ์ผ์— ์žˆ๋Š” ํด๋ž˜์Šค์— ์ € ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์ด๊ฑธ ์›น๋ธŒ๋ผ์šฐ์ €์— ๋ณด์—ฌ์ค„ view ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

<html xmlns:th="http://www.thymeleaf.org">
<!-- template์—”์ง„ ๊ผญ ์จ์ค˜์•ผ ๋ฐ‘์— ์žˆ๋Š” ํƒ€์ž„๋ฆฌํ”„th๊ฐ€ ์ž‘๋™๋จ-->
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>

html์ฝ”๋“œ๋Š” templatesํŒŒ์ผ์— hello-tamplate.html์— ์ž‘์„ฑํ•ด์คฌ๋‹ค.

 

์—ฌ๊ธฐ์„œ hello! empty๋ผ๊ณ  ๋ฏธ๋ฆฌ ์จ๋‘” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค! ๊ฐœ๋ฐœ์„ ํ•  ๋•Œ ๊ทธ๋ƒฅ ์ด๊ฒŒ ๋ฌด์Šจ ํŒŒ์ผ์ธ์ง€๋งŒ ์„ค๋ช…? ํ•˜๋Š” ์šฉ๋„๋ผ๊ณ  ํ•œ๋‹ค. ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด ์ž‘๋™ํ•˜๋ฉด ์ด ๋‚ด์šฉ์€ ์—†์–ด์ง€๊ณ  ์•ž์— ์žˆ๋Š” ์ฝ”๋“œ๋กœ ์น˜ํ™˜์ด ๋œ๋‹ค๊ณ  ํ•œ๋‹คใ…Žใ…Ž

 

์•„ ๊ทธ๋ฆฌ๊ณ  ์‹ ๊ธฐํ•œ ์‚ฌ์‹ค!

thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋ฒ„ ์—†์ด ๊ทธ ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

htmlํŒŒ์ผ์„ ์šฐํด๋ฆญํ•˜๊ณ , Copy Path -> Absolute Path ํ•œ ๋‹ค์Œ์— ์ฃผ์†Œ์ฐฝ์— ๋ถ™์—ฌ๋„ฃ๊ธฐ๋ฅผ ํ•˜๋ฉด ์น˜ํ™˜๋˜์ง€ ์•Š์€ hello! empty๊ฐ€ ํŽ˜์ด์ง€์— ๋ณด์ธ๋‹ค ์‹ ๊ธฐํ•˜๊ตฐ

 

๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ ์‹คํ–‰์‹œํ‚ค๊ณ  localhost:8080/hello-mvc๋ฅผ ์ฃผ์†Œ์ฐฝ์— ์น˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ €๋ ‡๊ฒŒ ์น˜๋ฉด ์•ˆ๋˜๊ณ , name์„ ์„ค์ •ํ•ด์ค˜์•ผํ•œ๋‹ค.

์ฃผ์†Œ์ฐฝ์— ์ƒˆ๋กœ localhost:8080/hello-mvc?name=spring์ด๋ผ๊ณ  ์นœ๋‹ค. 

์—ฌ๊ธฐ์„œ spring์€ ์ด๋ฆ„์ด๋‹ค! ์ € 'name=' ๋’ค์— ์›ํ•˜๋Š” ๊ฒƒ์„ ์น˜๋ฉด ๊ทธ๊ฒŒ ์น˜ํ™˜๋ผ์„œ ๋ฐ”๋€๋‹ค.

์›น๋ธŒ๋ผ์šฐ์ € ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋ฐ”๋€ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค!

 

์‹คํ–‰๊ณผ์ •

 

- localhost:8080/hello-mvc๋กœ ์ ‘์†์„ ํ•˜๋ฉด ๋‚ด์žฅ ํ†ฐ์ผ“ ์„œ๋ฒ„๊ฐ€ ์Šคํ”„๋งํ•œํ…Œ ๋„˜๊ฒจ์ค€๋‹ค. ์—ฌ๊ธฐ์„œ hello-mvc์— ๋งž๋Š” ๊ฒƒ์„ ์ฐพ์•„์„œ name๊ณผ ํ•จ๊ป˜ model์„ ๋งŒ๋“ค์–ด์„œ ๋„˜๊ธด๋‹ค.

- viewResolver๊ฐ€ ๋™์ž‘์„ ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๊ฒƒ์€ ํ™”๋ฉด๊ณผ ๊ด€๋ จ๋œ ํ•ด๊ฒฐ์ž๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. view๋ฅผ ์ฐพ์•„์ฃผ๊ณ  template ์—”์ง„์„ ์—ฐ๊ฒฐ์‹œ์ผœ์ค€๋‹ค.

- viewResolver๊ฐ€ hello-template.html์„ ์ฐพ๊ณ  thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ๊ณ  ๋ Œ๋”๋ง์„ ํ•œ๋‹ค. ์ด ๋ณ€ํ™˜๋œ html์„ ์›น๋ธŒ๋ผ์šฐ์ €์— ๋‹ค์‹œ ๋„˜๊ฒจ์ฃผ๋ฉด ๋์ด๋‹ค. (์—ฌ๊ธฐ์„œ ์ •์ ํ™”๋ฉด์ผ ๋•Œ๋Š” ๋ณ€ํ™˜์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค)

 

3. API

API๋Š” ๋Œ€๋ถ€๋ถ„ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

API๋Š” MVC์ฒ˜๋Ÿผ ๋ง‰ ๋ณต์žกํ•œ ๊ณผ์ •์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋Š” ์•Š์•„์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

 

API ์—์„œ๋Š” ๋ฌธ์žฅ์„ ๋„์›Œ์ฃผ๊ฑฐ๋‚˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ, ๋จผ์ € ๋ฌธ์žฅ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์˜ˆ์ œ๋ถ€ํ„ฐ ์จ ๋ณผ ๊ฒƒ์ด๋‹ค.

 

@GetMapping("hello-string")
@ResponseBody //http์—์„œ body๋ถ€์— ๋ฐ‘์— ๋‚ด์šฉ์„ ์ง์ ‘ ๋„ฃ์–ด์ฃผ๊ฒ ๋‹ค๋Š” ๋œป
public String helloString(@RequestParam("name") String name){
    return "hello " + name; //name์„ spring์œผ๋กœ ์š”์ฒญํ•˜๋ฉด name์ด ๊ทธ๋Œ€๋กœ ๋ฐ”๋€œ
}

API๋Š” viewResolver๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— @ResponseBody๋ฅผ ๊ผญ ์จ์ค˜์•ผ๋œ๋‹ค!! ์ €๊ฑธ ์“ฐ๋ฉด http์—์„œ body๋ถ€๋ถ„์— ์ง์ ‘ ๋ฐ”๋กœ ๋‚ด์šฉ์„ ๋„ฃ๊ฒ ๋‹ค๋Š” ๋œป์ด๋‹ค.

์ด๊ฒƒ๋„ ์œ„์— ?name=spring์„ ํ•ด์•ผ ๋‚˜์˜จ๋‹ค!

mvc๋ฐฉ์‹๊ณผ ์›น๋ธŒ๋ผ์šฐ์ €์—๋Š” ๋ชจ์–‘์ด ๋˜‘๊ฐ™์ด ๋‚˜์˜ค์ง€๋งŒ ์ด ์›นํŽ˜์ด์ง€์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ํ™•์—ฐํžˆ ๋‹ค๋ฅด๋‹ค.

์ •๋ง ์„ค๋ช…ํ•ด์ฃผ์‹  ๋Œ€๋กœ ์ €๋ ‡๊ฒŒ ๋ฐ”๋กœ ์ž‘์„ฑ์ด ๋˜์–ด์žˆ์—ˆ๋‹ค..(เน‘โ€ขฬoโ€ขฬ€เน‘)

 

์ด๋ฒˆ์—๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด๋ดค๋‹ค!

    @GetMapping("hello-api")
    @ResponseBody
    public Hello helloApi(@RequestParam("name") String name){
        Hello hello = new Hello();
        hello.setName(name);
        return hello;
    }

    static class Hello{
        private String name;

        public String getName(){
            return name;
        }
        public void setName(String name){
            this.name = name;
        }
    }

์ด๋ฒˆ์—๋Š” ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜์„ ํ–ˆ๋Š”๋ฐ, ์ด๋ฒˆ์—๋„ @ResponseBody๋ฅผ ๊ผญ ์จ์ค˜์•ผ๋œ๋‹ค!

๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜๋ฉด ๊ฐ์ฒด๊ฐ€ json์œผ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

json์€ ํ•™๊ต์—์„œ ๊ฐ„๋‹จํžˆ ๋ฐฐ์šด ์ ์ด ์žˆ์—ˆ๋‹ค, key์™€ value๋กœ ํ‘œ๊ธฐ๋œ๋‹ค. 

 

์ด๋ฒˆ์—๋„ ์‹คํ–‰์„ ํ•ด๋ดค๋‹ค!

์ด๋ฒˆ์—๋„ ๋˜‘๊ฐ™์ด name์„ spring์œผ๋กœ ์„ค์ •ํ•ด์„œ ์ฃผ์†Œ์ฐฝ์— ์ ์—ˆ๋‹ค. 

์•„๊นŒ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ๋‚˜์™”๋‹ค! ์ € ํ‘œ๊ธฐ ๋ฐฉ์‹์ด json ๋ฐฉ์‹์ด๋‹ค. name์ด key๊ฐ’์ด๊ณ , spring์ด value๊ฐ’์ด๋‹ค!!

 

์‹คํ–‰๊ณผ์ •

 

- localholst:8080/hello-api๋ฅผ ํ†ฐ์บฃ ๋‚ด์žฅ ์„œ๋ฒ„์— ๋ณด๋‚ด๊ณ  ํ†ฐ์บฃ์—์„œ ์Šคํ”„๋ง์œผ๋กœ ๋˜์ง„๋‹ค. 

- ์Šคํ”„๋ง์—์„œ helloController์—์„œ ์ฐพ์€๋‹ค์Œ์— @ResponseBody๋ฅผ ํ™•์ธํ•œ๋‹ค. 

- ๋งŒ์•ฝ ์ด๊ฒŒ ๊ฐ์ฒด์ด๋ฉด MappingJackson2HttpMessageConverter๊ฐ€ ๋™์ž‘ํ•˜๊ณ , ๋ฌธ์ž๋ฉด StringHttpMessageConverter๊ฐ€ ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

- ๊ฐ์ฒด๋ฉด json ์Šคํƒ€์ผ๋กœ ๋ฐ”๊พธ๊ณ , ๋ฌธ์ž๋ฉด ๊ทธ๋Œ€๋กœ ์›น๋ธŒ๋ผ์šฐ์ €์— ๋„˜๊ฒจ์ค€๋‹ค.

 

// @ResponseBody

์ด ํ‘œ๊ธฐ๊ฐ€ ์•ˆ ๋ถ™์–ด์žˆ์œผ๋ฉด mvc์—์„œ์ฒ˜๋Ÿผ viewResolver์—๊ฒŒ ๋˜์ง„๋‹ค. ํ•˜์ง€๋งŒ ๋ถ™์–ด์žˆ์œผ๋ฉด http์‘๋‹ต์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค.

๋ฌธ์ž๋ฉด ๊ทธ๋ƒฅ ๋„˜๊ฒจ์„œ ์ฃผ๋Š”๋ฐ ๊ฐ์ฒด์ผ๋•Œ๋Š” ๊ธฐ๋ณธ ๋””ํดํŠธ๊ฐ€ json๋ฐฉ์‹์œผ๋กœ data๋ฅผ ๋งŒ๋“ค์–ด์„œ http์‘๋‹ต์— ๋ฐ˜ํ™˜์„ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 

 

๊ฐ์ฒด๋ฅผ json์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ Jackson์ด๋ž‘ Gson์ด ์žˆ๋Š”๋ฐ, ์Šคํ”„๋ง์—์„œ๋Š” Jackson์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ํƒ‘์žฌ๋˜์–ด์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. 

 


๊ฐ•์‚ฌ๋‹˜์ด ์„ค๋ช…์„ ์ž˜ ํ•ด์ฃผ์…จ๋Š”๋ฐ ๋‚ด๊ฐ€ ์ž˜ ๋ชป์•Œ์•„ ๋“ค์€ ๊ฒƒ์ด ์•„๋‹๊นŒ ๊ฑฑ์ •์ด๋œ๋‹ค...( โ€ขฬ ฬฏโ€ขฬ€ )

 

๊ทธ๋ž˜๋„ ์—ด์‹ฌํžˆ ๋”ฐ๋ผ๊ฐ€์•ผ์ง€! 

 

# ์ด ํฌ์ŠคํŒ…์€ ์ธํ”„๋Ÿฐ์—์„œ ๊น€์˜ํ•œ๋‹˜ ์Šคํ”„๋ง๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์ž‘์„ฑ๋œ ๋ณต์Šต ํฌ์ŠคํŒ…์ž…๋‹ˆ๋‹น