1. Thymeleaf를 사용하는 프로젝트 생성

  • 스프링 부트에서는 기본적으로 JSP 대신에 Thymeleaf나 FreeMarker, Mustache 등을 이용해서 화면을 처리함.
  • 프로젝트 생성시 Thymeleaf 의존성 추가
    image
  • Thymeleaf는 기본적으로 templates 폴더를 기본으로 사용함.
    image

Thymeleaf 코드 예시

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1 th:text="${'Hello World'}"></h1>
</body>
</html>
  • 기본적인 사용 방법은 기존의 속성 앞에 `‘th:’를 붙여주고 속성값을 지정하는 것.
  • JSP와 달리 별도의 태그를 이용하지 않고 HTML을 그대로 유지한 상태에서 필요한 동작이나 값을 추가하는 방식임.

2. Thymeleaf의 기본 사용법

1
2
3
4
5
6
7
8
9
@Data   //Getter/Setter, toString(), equals(), hashCode() 자동 생성
@Builder(toBuilder = true)
public class SampleDTO {

    private Long sno;
    private String first;
    private String last;
    private LocalDateTime regTime;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Controller
@RequestMapping("/sample")
@Log4j2
public class SampleController {

    @GetMapping("/ex1")
    public void ex1() {
        log.info("ex1...........");
    }

    @GetMapping({"/ex2"})
    public void exModel(Model model) {
        List<SampleDTO> list = IntStream.rangeClosed(1,20).asLongStream().mapToObj(i -> {
            SampleDTO dto = SampleDTO.builder()
                    .sno(i)
                    .first("First.."+i)
                    .last("Last.."+i)
                    .regTime(LocalDateTime.now())
                    .build();
            return dto;
        }).collect(Collectors.toList());

        model.addAttribute("list", list);
    }
}
  • SampleDTO 타입의 객체를 20개 추가하고 이를 Model에 담아서 전송.

3. 반복문 처리

1) 기본 코드

th:each = "변수 : ${목록}"

1
2
3
4
5
6
7
<ul>
    <li th:each="dto : ${list}">
        <!-- [[]] : 인라인 표현식. 
        별도의 태그 속성으로 지정하지 않고 사용하고자 할 때 유용 -->
        [[${dto}]]
    </li>
</ul>

image

2) 반복문의 상태(state) 객체

* 상태변수 종류

  • index : 0부터 시작하는 인덱스
  • count : 1부터 시작하는 인덱스
  • size : 리스트에 저장된 요소의 개수
  • even : 현재 반복이 짝수인지 확인. true/false 반환
  • odd : 현재 반복이 홀수인지 확인. true/false 반환
  • first : 현재 반복이 첫번째인지 확인. true/false 반환
  • last : 현재 반복이 마지막인지 확인. true/false 반환
1
2
3
<li th:each="dto, state : ${list}">
    [[${state.index}]] --- [[${dto}]]
</li>

image

4. 제어문 처리

1) th:if ~ th:unless

↓ sno의 값이 5의 배수인 것들만 출력

1
2
3
<li th:each="dto, state : ${list}" th:if="${dto.sno % 5 == 0}">
    [[${dto}]]
</li>


↓ sno가 5로 나눈 나머지가 0인 경우에는 sno만을 출력하고(if)
↓ 그렇지 않다면(unless) first를 출력

1
2
3
4
  <li th:each="dto, state : ${list}">
    <span th:if="${dto.sno % 5 == 0}" th:text="${'-----------------------' + dto.sno}"></span>
    <span th:unless="${dto.sno % 5 == 0}" th:text="${dto.first}"></span>
  </li>


image

2) 삼항연산자

↓ Thymeleaf는 특이하게도 단순 if와 같이 2개의 항만으로도 처리할 수 있음.

1
<li th:each="dto, state : ${list}" th:text="${dto.sno % 5 == 0} ? ${dto.sno}"></li>

image


sno가 5로 나눈 나머지가 0인 경우 sno만을 출력, 나머지는 first출력.

1
<li th:each="dto, state : ${list}" th:text="${dto.sno % 5 == 0} ? ${dto.sno} : ${dto.first}"></li>

image


sno를 5로 나눈 나머지가 0인 경우에만 특정한 css를 적용.

1
2
3
4
5
6
7
8
9
<style>
    .target {
        background-color: red;
    }
</style>

<ul>
    <li th:each="dto, state : ${list}" th:class="${dto.sno % 5 == 0} ? 'target'" th:text="${dto}"></li>
</ul>

image

5. inline 속성

  • inline 속성은 주로 자바스크립트 처리에서 유용함.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@GetMapping({"/exInline"})
    public String exInline(RedirectAttributes redirectAttributes) {
        log.info("exInline................");

        SampleDTO dto = SampleDTO.builder()
                .sno(100L)
                .first("First...100")
                .last("Last...100")
                .regTime(LocalDateTime.now())
                .build();
        redirectAttributes.addFlashAttribute("result", "success");
        redirectAttributes.addFlashAttribute("dto", dto);

        return "redirect:/sample/ex3";
    }

    @GetMapping("/ex3")
    public void ex3() {
        log.info("ex3");
    }


1
2
3
4
5
6
7
8
9
<body>
  <h1 th:text="${result}"></h1>
  <h1 th:text="${dto}"></h1>

  <script th:inline="javascript">
    var msg = [[${result}]];
    var dto = [[${dto}]];
  </script>
</body>


image /sample/exInline

⇒ 자바스크립트 부분을 살펴보면 별도의 처리를 안했음에도 불구하고 문자열은 자동으로 ““이 추가되어 문자열이 되는 것을 볼 수 있고, 같이 전송된 dto는 JSON 포맷의 문자열이 된 것을 볼 수 있음.


th:block

  • 별도의 태그가 필요하지 않음.
  • th:block은 실제 화면에서는 html로 처리되지 않음.
    ⇒ 아래와 같이 루프 등을 별도로 처리하는 용도로 많이 사용함.
1
2
3
<th:block th:each="dto : ${list}">
    <li th:text="${dto.sno % 5 == 0} ? ${dto.sno} : ${dto.first}"></li>
</th:block>

6. 링크 처리

  • @{} 를 이용해서 사용.
  • SampleControllerexModel() 메서드 수정
    @GetMapping()에는 배열을 이용해 하나 이상의 URL을 처리할 수 있음.
1
2
3
4
@GetMapping({"/ex2", "/exLink"})
public void exModel(Model model) {
    ...
}

1) 링크에 파라미터 추가

1
2
3
4
5
<ul>
    <li th:each="dto : ${list}">
        <a th:href="@{/sample/exView(sno=${dto.sno})}">[[${dto}]]</a>
    </li>
</ul>  

image
image


2) sno를 path로 이용하기

1
2
3
<li th:each="dto : ${list}">
    <a th:href="@{/sample/exView/{sno}(sno = ${dto.sno})}">[[${dto}]]</a>
</li>

image