๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Springboot

[spring boot] ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ Thymeleaf ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

 

ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด๋ž€?

ํ…œํ”Œ๋ฆฟ ์–‘์‹๊ณผ ํŠน์ • ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์— ๋”ฐ๋ฅธ ์ž…๋ ฅ ์ž๋ฃŒ๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ ๋ฌธ์„œ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด(๋˜๋Š” ์ปดํฌ๋„ŒํŠธ)๋ฅผ ๋งํ•œ๋‹ค.

์ฃผ๋กœ View๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

๋™์  ์ปจํ…์ธ ๋ฅผ ์ƒ์„ฑํ•ด์„œ ์ œ๊ณตํ•ด์•ผํ•  ๋•Œ ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Code Generation / Email Template ๋“ฑ์— ์‚ฌ์šฉ๋œ๋‹ค.

์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ž๋™ ์„ค์ •์„ ์ง€์›ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„

FreeMarker

Groovy

Thymeleaf (์ถ”์ฒœ) ใ…ก> ๋น„๊ต์  ์ตœ๊ทผ์— ๋งŒ๋“ค์–ด์ง„ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด๋‹ค.

Mustache

JSP๋ฅผ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š” ์ด์œ 

spring boot๊ฐ€ ์ง€ํ–ฅํ•˜๋Š” ๋ฐ”๋ฅผ ์ถฉ์กฑ์‹œํ‚ค๊ธฐ ๋ชปํ•œ๋‹ค.

spring boot๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๊ฐ€๋Šฅํ•œ embeded tomcat์œผ๋กœ application์„ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด ๋ฐฐํฌํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค.

JSP๋Š” JAR ํŒจํ‚ค์ง• ํ•  ๋•Œ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š๊ณ , WAR ํŒจํ‚ค์ง• ํ•ด์•ผ ํ•œ๋‹ค.

์„œ๋ธ”๋ฆฟ ์—”์ง„ ์ค‘์— ๊ฐ€์žฅ ์ตœ๊ทผ์— ๋งŒ๋“ค์–ด์ง„, Jboss ์ง„์˜์—์„œ ๋งŒ๋“  Undertow๋Š” JSP๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋˜ํ•œ ์˜์กด์„ฑ์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๋งํฌ๋Š” ๊ณต์‹๋ฌธ์„œ๊ฐ€ ๋งํ•˜๋Š” jsp์˜ ์ œ์•ฝ์‚ฌํ•ญ์ด๋‹ค. #

Thymeleaf ์‚ฌ์šฉํ•˜๊ธฐ

์˜์กด์„ฑ ์ถ”๊ฐ€

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

@RestController๊ฐ€ ์•„๋‹Œ @Controller๋กœ, ๋ณธ๋ฌธ์˜ ๋‚ด์šฉ์ด ์•„๋‹Œ ๋ทฐ ์ด๋ฆ„์„ ์ „๋‹ฌํ•œ๋‹ค.

package com.jueun.springmvcdemo;

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

@Controller
public class SampleController {

    @GetMapping("/hello")
    public String hello(Model model){
        model.addAttribute("name", "jueun");// model์„ Map์ฒ˜๋Ÿผ ์‚ฌ์šฉ
        return "helloEveryone";
    }
}

ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ ์œ„์น˜: /src/main/resources/template/helloEveryone.html

 xmlns:th="http://www.thymeleaf.org : thymeleaf namespace๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

<h1 th:text="${name}">Name</h1> : ๋ชจ๋ธ์— name์„ ํ‚ค๋กœ ์ €์žฅํ•ด๋‘” ๋‚ด์šฉ์„ ๊บผ๋‚ด ์“ด๋‹ค.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>hello</title>
</head>
<body>
<h1 th:text="${name}">Name</h1>
</body>
</html>

 

Test ํ•ด๋ณด๊ธฐ

์š”์ฒญ "/hello"
์‘๋‹ต

- model์— ๋‹ด์€ ๋‚ด์šฉ: name : jueun
- view ์ด๋ฆ„ : helloEveryone

@RunWith(SpringRunner.class)
@WebMvcTest(SampleController.class)
public class SampleControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void hello() throws Exception {
        mockMvc.perform(get("/hello"))
                .andExpect(status().isOk())
                .andDo(print()) // ๋ Œ๋”๋ง ๋ณธ๋ฌธ ํ™•์ธ ๊ฐ€๋Šฅ
                // ํƒ€์ž„๋ฆฌํ”„ ์—”์ง„์€ ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์— ๋…๋ฆฝ์ ์ธ ์—”์ง„์ด๊ธฐ์— view์— ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๊ฐ’๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
                .andExpect(view().name("helloEveryone"))
                .andExpect(model().attribute("name", "jueun"))
                .andExpect(content().string(containsString("jueun")));
    }
}

.andDo(print()): print() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ Œ๋”๋ง ๋ณธ๋ฌธ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์„œ๋ธ”๋ฆฟ ์—”์ง„์ด ๊ฐœ์ž…์„ ํ•ด์•ผ๋งŒ ์‘๋‹ต์œผ๋กœ ๋‚ด๋ณด๋‚ผ ์ตœ์ข…์ ์ธ view๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰ ๋ Œ๋”๋งํ•œ๋‹ค.

ํƒ€์ž„๋ฆฌํ”„ ์—”์ง„์€ ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์— ๋…๋ฆฝ์ ์ธ ์—”์ง„์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— view์— ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๊ฐ’๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

 

์•„๋ž˜๋Š” hello() ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•˜๊ณ  ๊ธฐ๋ก๋œ ๋‚ด์šฉ์ด๋‹ค.

Body ์ค‘ <h1 th:text="${name}">Name</h1>์—์„œ ๊ฐ’์ด jueun์œผ๋กœ ์ž˜ ๋ Œ๋”๋ง๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /hello
       Parameters = {}
          Headers = []
             Body = null
    Session Attrs = {}

Handler:
             Type = com.jueun.springmvcdemo.SampleController
           Method = com.jueun.springmvcdemo.SampleController#hello(Model)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = helloEveryone
             View = null
        Attribute = name
            value = jueun

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Language:"en", Content-Type:"text/html;charset=UTF-8"]
     Content type = text/html;charset=UTF-8
             Body = <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hello</title>
</head>
<body>
<h1>jueun</h1>
</body>
</html>
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

 

 

Thymeleaf ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€ #

Thymeleaf 5๋ถ„ ํŠœํ† ๋ฆฌ์–ผ #

Thymeleaf ์˜ˆ์ œ #