1. Thymeleaf 란

Thymeleaf는 View Template Engine입니다. 그리고 컨트롤러에서 전달받은 데이터를 이용해 동적인 페이지를 만들 수 있습니다.
태그의 속성으로 thymeleaf 명령어를 사용할 수 있으며 html 파일 내에서 사용이 가능합니다. 

 

2. Thymeleaf 적용

spring boot 2.2.2.RELEASE 버전에서 테스트한 내용입니다.

thymeleaf의 default prefix는 src/main/resources/templates이며 suffix는 .html입니다.

1) dependency (pom.xml)

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

2) Controller

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value = "/")
public class HomeController {

    @GetMapping("/")
    public ModelAndView indexPage() {
    	//view name으로 page 파일 명을 입력한다.
        //prefix + 파일명 + suffix
        ModelAndView modelAndView = new ModelAndView("index");

        Map<String, Object> info = new HashMap<>();
        info.put("name", "kim");
        info.put("age", 29);

        List<String> datas = new ArrayList<>();
        datas.add("red");
        datas.add("orange");
        datas.add("yellow");

        modelAndView.addObject("info", info);
        modelAndView.addObject("datas", datas);

        return modelAndView;
    }
}

3) src/main/resources/templates/index.html

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Thymeleaf Test</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <th:block th:each="data:${datas}">
            <h1 th:text="${data}"></h1>
        </th:block>

        <span th:text="${info.name}"></span>
        <span th:text="${info.age}"></span>
    </body>
</html>
Controller에서 전달받은 datas와 info를 화면에 출력합니다.

 

4. thymeleaf 문법 정리

1) ${...} 표현식

${...} 표현식을 이용해 컨트롤러에서 전달받은 변수에 접근할 수 있으며 th:속성명 내에서만 사용할 수 있습니다.

 

2) @{...} 표현식

@{...} 표현식은 서버의 contextPath를 의미하며 @{/} 는 "/contextPath/" 를 의미합니다.

 

3) 문자 합치기

합치고 싶은 문자열을 "|" 으로 감싸거나 + 연산자를 이용해 문자를 합칠 수 있습니다.
<div th:text="|My name is ${info.name} !! |"></div>
<div th:text="'My name is '+ ${info.name} + ' !! '"></div>

 

4) 비교 연산자

<!-- 이항 연산자 -->
<div th:text="${info.name != 'kim'}"></div>
<div th:text="${info.age >= 30}"></div>

<!-- 삼항 연산자 -->
<div th:text="${info.name == 'kim' ? 'ok' : 'no'}"></div>

 

5) th:text

태그 내에 text를 수정합니다.
<div th:text="${info.name}"></div>
 <!--<div>kim</div>-->

 

6) th:value

태그 내에 value를 수정합니다.
<input type='text' th:value="${info.name}">

 

7) th:if, th:unless

if else 속성을 이용해 조건문을 표현합니다.
<th:block th:if="${info.age < 30}">당신은 30대가 아닙니다.</th:block>
<th:block th:unless="${info.age >= 30}">당신은 30대입니다.</th:block>

 

8) th:switch, th:case

switch문을 이용해 조건문을 표현합니다.
<th:block th:switch="${info.name}">
  <div th:case="lee"> 당신은 이씨 입니다.</div>
  <div th:case="kim"> 당신은 김씨 입니다.</div>
</th:block>

 

9) th:each

each문을 이용해 반복문을 표현합니다.
<th:block th:each="data:${datas}">
	<h1 th:text="${data}"></h1>
</th:block>

 

변수명 앞에 status 변수를 추가해 row에 대한 추가정보를 얻을 수 있습니다.
<th:block th:each="data,status:${datas}">
	<h1 th:text="|${status.count} ${data}|"></h1>
</th:block>    
status 속성

index :
0부터 시작
count : 1부터 시작
size : 총 개수
current : 현재 index의 변수
event/odd :
짝수/홀수 여부
first/last :
처음/마지막 여부

thymeleaf template layout은 thymeleaf를 이용하여 공통 page를 fragment, layout형식으로 조립할 수 있는 template engine입니다.

thymeleaf template layout을 사용하는 간단한 예제 프로젝트를 진행해보도록 하겠습니다.


1. Maven dependency 및 프로젝트 구조

   1) pom.xml

        ...
   <version>2.2.2.RELEASE</version>
   <!-- Spring Boot Version -->
        ...
            
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        
        <dependency>
            <groupId>nz.net.ultraq.thymeleaf</groupId>
            <artifactId>thymeleaf-layout-dialect</artifactId>
        </dependency>
    </dependencies>
    
        ...
        

 

   2) 프로젝트 구조


2. header.html (공통 fragment)

<html lagn="ko" 
      xmlns:th="http://www.thymeleaf.org">
       
    <!--headerFragment 선언-->
    <div th:fragment="headerFragment">
        <h1>HEADER</h1>
    </div>
    
</html>

3. footer.html (공통 fragment)

<html lagn="ko" 
      xmlns:th="http://www.thymeleaf.org">
      
    <!--footerFragment 선언-->
    <div th:fragment="footerFragment">
        <h1>FOOTER</h1>
    </div>
    
</html>

4. config.html (공통 fragment)

<html lagn="ko" 
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

    <!--configFragment 선언-->
    <th:block th:fragment="configFragment">

          
        <!-- 이 영역에 공통으로 사용할 css, js library를 선언한다. -->
        <link rel="stylesheet" th:href="@{/css/common/common.css}" >
        
        <script th:src="@{/js/common/common.js}"></script>

        <!-- Content Page의 CSS fragment 삽입 -->
        <th:block layout:fragment="css"></th:block>

        <!-- Content Page의 script fragment 삽입 -->
        <th:block layout:fragment="script"></th:block>
        
    </th:block>
</html>
  • config fragment에 공통으로 사용할 css, js를 선언하고 Content Page의 css, js를 선언합니다.
  • @{/js/common/common.js} 는 src/main/resources/static이 생략되어있습니다.

5. default_layout.html (Layout)

<!DOCTYPE html>

<html lagn="ko" 
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

    <head>
        <meta charset="UTF-8" />
        <title>Bamdule</title>
        
        <!-- config fragment 사용 -->
        <th:block th:replace="fragment/config :: configFragment" ></th:block>
    </head>
    
    <body>
        <!-- header fragment 사용 -->
        <th:block th:replace="fragment/header :: headerFragment"></th:block>
        
        <!-- 
            content fragment 사용 
            현재 layout을 사용하는 content fragment의 내용을 삽입한다.
        -->
        <th:block layout:fragment="content"></th:block>
        
        <!-- footer fragment 사용 -->
        <th:block th:replace="fragment/footer :: footerFragment"> </th:block>
    </body>

</html>
  • Layout은 fragment들이 조합된 html입니다.
  • th:replace="frament경로 :: fragment이름" 속성은 해당 영역을 fragment로 치환하겠다는 의미입니다.
  • layout:fragment="content"는 해당 layout을 사용하는 content의 내용을 불러오겠다는 의미입니다.

6. home.html (Content Page - fragment )

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/my-layout}">

    <!-- index.html 고유 CSS 추가 -->
    <th:block layout:fragment="css">
        <link rel="stylesheet" th:href="@{/css/page/home.css}" >
    </th:block>
    
    <!-- index.html 고유 스크립트 추가 -->
    <th:block layout:fragment="script">
        <script th:src="@{/js/page/home.js}"></script>
    </th:block>

    <div layout:fragment="content">
        <h1>content</h1>
    </div>
</html>
  • 여기서 유심히 볼 코드는 layout:decorate="~{layouts/my-layout}" 입니다. 
  • layout:decorate="layout path" 속성을 입력해 layout을 사용할 수 있습니다.
  • layout:fragment="content" 속성을 통해 content fragment를 선언합니다.

1. Spring Boot란

Spring Boot는 Spring 프레임워크를 간편하게 설정하고, 별도에 어려운 설정 없이 바로 개발에 들어갈 수 있도록 만든 프레임 워크입니다.

강력한 기능을 가진 라이브러리들을 Spring Boot 라이브러리에 내장하였고, 내장형 톰캣 등을 탑재하여 단독 실행이 가능해졌습니다.

그리고 프로젝트 생성 시 기존 Spring은 복잡한 설정 파일을 요구했는데, Spring boot는 aplication.yml 설정 파일로 간단하게 설정이 가능하게 되었습니다,

2. 사용하는 라이브러리

...
<!--Spring Boot Version-->	
  <version>2.2.2.RELEASE</version>
...
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <scope>provided</scope>
</dependency>

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

3. 프로젝트 생성

아래 주소에서 Spring Boot 프로젝트를 생성합니다.

https://start.spring.io/

src 폴더와 pom.xml을 제외한 나머지 파일은 사용하지 않으니 삭제해주세요.


4. application.yml 설정

application.yml 파일은 스프링의 설정 정보를 저장하는 파일입니다.

기본적으로 application.profiles파일이 저장되어 있습니다. yml, profiles 두가지 타입의 파일로 설정이 가능합니다.

이번에는 조금 더 보기좋고 설정하기 편한 yml 파일로 설정해보겠습니다. 

파일 경로는 src/main/resources/ 입니다.

spring:
    thymeleaf:
        prefix : classpath:templates/
        suffix : .html
        cache : false

우선 기본적인 thymeleaf 설정만 하였습니다.

html 파일의 위치와 확장자 명, 캐시 유무를 설정하였습니다.


5. HomeController 생성

@SpringBootApplication를 선언한 클래스 패키지의 하위 패키지에 HomeController를 생성합니다.

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value = "/")
public class HomeController {

    @GetMapping(value = "/")
    public ModelAndView home() {
        ModelAndView modelAndView = new ModelAndView();
        
        modelAndView.setViewName("home");
        
        Map<String, Object> map = new HashMap<>();
        map.put("name", "Bamdule");
        map.put("date", LocalDateTime.now());
        
        modelAndView.addObject("data", map);
        
        return modelAndView;
    }
}

modelAndView.setViewName("home"); 은 application.yml에서 설정한 "src/main/resources/" 값이 생략되어있고, 
확장자 .html 또한 생략되어있습니다. 이 값을 통해 ViewResolver는 view를 생성합니다.

그리고 modelAndView.addObject("data",map); 를 통해 화면에 데이터를 렌더링합니다.


6. home.html 생성

src/main/resources/templates/ 경로에 home.html을 생성해줍니다.

<!DOCTYPE html>
<html>
    <head>
        <title>title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <div th:text="${data.name}"></div>
        <th:block th:text="${data.date}"/>
    </body>
</html>

"th:" 가 포함된 tag attribute는 thymeleaf 문법입니다.

data.name과 data.date 값을 화면에 뿌려줍니다.


7. 결과

위와 같이 하셨나면 톰캣을 실행해 줍니다. 

build하면 target 폴더에 war 파일이 생성되고, war파일을 설치한 톰캣 또는 IDE툴을 통해서 실행하면 다음과 같은 화면이 보여집니다.


도움이 되셨다면 공감 한번씩 눌러주시면 감사하겠습니다.

+ Recent posts