WEB/Server

[์Šคํ”„๋ง๋ถ€ํŠธ ์ž…๋ฌธ] 2. ์Šคํ”„๋ง ์›น ๊ฐœ๋ฐœ ๊ธฐ์ดˆ

kite707 2024. 4. 25. 01:03

๊ฐœ๋ฐœ์„ ํ•˜๊ธฐ ์ „ ์Šคํ”„๋ง์—์„œ ์›น์„ ๊ฐœ๋ฐœํ•˜๋Š” 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž. ํฌ๊ฒŒ ์ •์ ์ปจํ…์ธ , MVC์™€ ํ…œํ”Œ๋ฆฟ์—”์ง„, API ๋ฐฉ์‹์œผ๋กœ ๋‚˜๋‰œ๋‹ค.

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

์‹ค์Šต

์ •์ ์ปจํ…์ธ ๋ž€ ์„œ๋ฒ„์—์„œ ๋”ฐ๋กœ ์ž‘์—…์„ ํ•˜์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ํŒŒ์ผ์„ ์›น ๋ธŒ๋ผ์šฐ์ €์— ๋‚ด๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ์ •์ ์ด๋ผ๋Š” ๋ง ๊ทธ๋Œ€๋กœ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ์ปจํ…์ธ ์ด๋‹ค.

 

main/resources/staticํด๋”์— hello-static.htmlํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ (cmd+n) ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด๋ณด์ž.

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

์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•œ ๋’ค localhost:8080/hello-static.html๋กœ ์ ‘์†ํ•˜๋ฉด ์ •์ ์ปจํ…์ธ ์ž…๋‹ˆ๋‹ค.๋ผ๋Š” ํ™”๋ฉด์ด ๋ณด์ผ ๊ฒƒ์ด๋‹ค.

๋™์ž‘ ์›๋ฆฌ

๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ localhost:8080/hello-static.html์š”์ฒญ์ด ์˜จ ๊ฒƒ์„ ๋ณด๊ณ  ๋‚ด์žฅ๋œ Tomcat์„œ๋ฒ„์—์„œ ์Šคํ”„๋ง์—๊ฒŒ hello-static.html์ด๋ผ๋Š” ์š”์ฒญ์ด ์™”์Œ์„ ์•Œ๋ ค์ค€๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์Šคํ”„๋ง์€ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ hello-static์ด ์žˆ๋Š”์ง€ ๋จผ์ € ์‚ดํŽด๋ณธ๋‹ค. ๋‘˜ ๋‹ค ์žˆ์„ ๊ฒฝ์šฐ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง์— ์œ ์˜ํ•˜์ž. ๋งคํ•‘๋œ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์—†์œผ๋‹ˆ ์Šคํ”„๋ง์€ resourcesํด๋”์—์„œ hello-static.htmlํŒŒ์ผ์„ ์ฐพ๋Š”๋‹ค. ๊ทธ๋ ‡๊ฒŒํ•ด์„œ ์žˆ์œผ๋ฉด ์ด ํŒŒ์ผ์„ ๋ฆฌํ„ดํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

ํ…œํ”Œ๋ฆฟ ์—”์ง„

์‹ค์Šต

main/resources/templatesํด๋”์— hello.htmlํŒŒ์ผ์„ ํ•˜๋‚˜ ์ƒ์„ฑํ•˜๊ณ (cmd+n) ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋„ฃ๋„๋ก ํ•˜์ž.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'์•ˆ๋…•ํ•˜์„ธ์š”. ' + ${data}" >์•ˆ๋…•ํ•˜์„ธ์š”. ์†๋‹˜</p>
</body>
</html>

๊ทธ๋ฆฌ๊ณ  com.example.hello์— controller ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๊ณ  HelloControllerํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋„๋ก ํ•˜์ž.

package com.example.hello.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HelloController {
    @GetMapping("hello")
    public String hello(Model model){
        model.addAttribute("data","hello");
        return "hello";
    }
}

๊ทธ๋ ‡๊ฒŒ ํ•˜๊ณ  localhost:8080/hello ๋กœ ์ ‘์†ํ•˜๋ฉด ์•ˆ๋…•ํ•˜์„ธ์š”. hello๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. ์ด์ œ ์ด๋ ‡๊ฒŒ ์ž‘๋™ํ•œ ์›๋ฆฌ๋ฅผ ํŒŒ์•…ํ•ด๋ณด๋„๋ก ํ•˜์ž.

๋™์ž‘ ์›๋ฆฌ

์›น๋ธŒ๋ผ์šฐ์ €์—์„œ localhost:8080/hello๋ผ๋Š” ์š”์ฒญ์ด ์˜ค๋ฉด (๋ธŒ๋ผ์šฐ์ €๋กœ๋ถ€ํ„ฐ ์™”์œผ๋‹ˆ ๋‹น์—ฐํžˆ GET์š”์ฒญ์ด๋‹ค.) Spring Boot์— ๋‚ด์žฅ๋œ Tomcat์„œ๋ฒ„์—์„œ Spring์—๊ฒŒ ํ•ด๋‹น ์š”์ฒญ๊ณผ ๋งคํ•‘๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š”์ง€ ๋ฌผ์–ด๋ณธ๋‹ค. ์Šคํ”„๋ง์€ @GetMapping(”hello”)๋•๋ถ„์— hello์™€ ๋งคํ•‘๋œ hello๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๊ณ , ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

 public String hello(Model model){
        model.addAttribute("data","hello");
        return "hello";
    }

๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ model์— data๋ผ๋Š” ํ‚ค์™€ hello๋ผ๋Š” ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  hello๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. ์Šคํ”„๋ง๋ถ€ํŠธ ๊ณต์‹ ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ return๊ฐ’์œผ๋กœ ๋ฌธ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด viewResolver๊ฐ€ ํ™”๋ฉด์„ ์ฐพ์•„์„œ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค. ์ฆ‰ templatesํด๋”์—์„œ hello.html์„ ์ฐพ์•„ ํ™”๋ฉด์— ๋„์›Œ์ฃผ๊ฒŒ ๋˜๋Š”๋ฐ, ๊ทธ ์ „์— Thymeleaf๊ฐ€ ${data}๋ถ€๋ถ„์„ ์•ž์„œ ์ €์žฅํ•œ hello๋ผ๋Š” ๊ฐ’์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

API

์‹ค์Šต

์•ž์„œ ๋งŒ๋“  HelloController์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก ํ•˜์ž.

   @GetMapping("hello-string")
    @ResponseBody
    public String helloString(@RequestParam(value = "name", required = false)String name){
        return "hello " + name;
    }

    @GetMapping("hello-object")
    @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;
        }
    }

๊ทธ๋ฆฌ๊ณ  http://localhost:8080/hello-string?name=kite๋ฅผ ๋ธŒ๋ผ์šฐ์ €์— ๊ฒ€์ƒ‰ํ•˜๋ฉด ๊ธฐ๋Œ€ํ–ˆ๋˜๋Œ€๋กœ hello kite๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ http://localhost:8080/hello-object?name=kite๋ผ๊ณ  ์น˜๋ฉด
{"name":"kite"} ์ด ์ถœ๋ ฅ๋  ๊ฒƒ์ด๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ ์ผ์–ด๋‚˜๋Š” ์ผ์„ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

๋™์ž‘ ์›๋ฆฌ

๋จผ์ € ์ฃผ๋ชฉํ•ด์•ผ ํ•  ์ ์€ @ResponseBody๋ผ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค. hello-string์š”์ฒญ์ด ์™”์Œ์„ ํ†ฐ์บฃ ์„œ๋ฒ„๊ฐ€ ์Šคํ”„๋ง์—๊ฒŒ ์•Œ๋ ค์ฃผ๋ฉด ์•ž์„œ ๋ดค๋˜๋Œ€๋กœ ์Šคํ”„๋ง์€ Controller์— hello-string์ด ์žˆ๋Š”์ง€๋ฅผ ์ฐพ๋Š”๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ์—๋Š” @ResponseBody์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ์˜ body๋Š” http ํ—ค๋”-๋ฐ”๋”” ํ• ๋•Œ ๊ทธ body์ด๋‹ค. ๊ทธ body๊ฐ’์„ ์กฐ์ž‘ํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ HttpMessageConverter์ด ๋™์ž‘ํ•œ๋‹ค. ์ด๋•Œ ๋ฆฌํ„ด๊ฐ’์ด ๋ฌธ์ž๋ผ๋ฉด StringConverter์ด ๋™์ž‘ํ•˜๊ณ  ๊ฐ์ฒด๋ฉด JsonConverter๊ฐ€ ๋™์ž‘ํ•œ๋‹ค.

 

์ฐธ๊ณ ๋กœ httpํ—ค๋”์—๋Š” Accept๋ผ๋Š” ํ•„๋“œ๊ฐ€ ์žˆ๋Š”๋ฐ ๊ทธ๊ณณ์—์„œ json์ด๋ผ๋Š” ์š”์ฒญ์ด ์˜ค๋ฉด json์ด๋ผ๊ณ  ๋ณด๋‚ด๊ณ  xml๋กœ ๋ณด๋‚ด๋ฉด xml๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ณด๋‚ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์•„๋ฌด๊ฒƒ๋„ ์—†์œผ๋ฉด ์Šคํ”„๋ง์ด ์•Œ์•„์„œ ๋ณ€ํ™˜ํ•ด์„œ ๋ณด๋‚ธ๋‹ค. ์ฆ‰ HTTP acceptํ•„๋“œ์™€ ์„œ๋ฒ„ ์ปจํŠธ๋กค๋Ÿฌ ๋ฐ˜ํ™˜ ํƒ€์ž…์˜ ์ •๋ณด๋ฅผ ์กฐํ•ฉํ•ด์„œ ์ ์ ˆํ•œ HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๊ฐ€ ์„ ํƒ๋˜๊ณ , ์ปจํŠธ๋กค๋Ÿฌ ๊ฐ’์„ ๋ณ€ํ™˜ํ•ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.