1. Thymeleaf 란?
Thymeleaf 공식 홈페이지 에 따르면 타임리프는 server-side Java template engine 이라고 정의되어 있습니다.
즉, Java 기반의 웹서비스에서 사용하는 서버 단 템플릿 엔진이라는 건데요,
다양한 템플릿과 강력한 기능으로 Spring Framework의 전폭적인 지지를 받고 있으며 JSP를 완벽하게 대체하는 것을 목표로 하고 있습니다.
Thymeleaf 에 대해 더 자세히 알아보기 전에 템플릿 엔진에 대해 간단히 짚어보고 넘어가겠습니다.
2. Template Engine 이란?
Template engine 또는 template processor란 동적인 웹페이지를 구현하기 위한 기능입니다.
웹서비스가 static 한 html만 보여주던 시기에서 점차 dynamic 한 서비스를 제공하기 시작하면서 정적인 html에 동적인 data를 바인딩할 수 있는 기능이 필요해졌습니다.
고객의 계정정보를 볼 수 있는 마이페이지를 예로 들자면, 정적 html로는 어떤 고객이 들어오던지 동일한 영역(공통 페이지 구조, 로고 이미지, 회사 정보 등)을 정의하고, 어떤 고객이 접속하느냐에 따라 달리지는 고객의 아이디, 이메일 주소 등은 변수화하여, DB에서 조회해온 값을 매핑할 수 있도록 처리하는 것입니다.
이러한 데이터 바인딩을 직접 구현하던 시기에는 .html 문서 내에 html 문법과 데이터를 조회해오는 서버 단 문법이 혼재해서 가독성이 떨어지고 기능적인 분리 (퍼블리싱과 개발)가 어려웠습니다.
템플릿 엔진은 HTML을 템플릿화하여 재사용성을 높이고 쉽고 편하게 데이터 바인딩을 지원해주는 기술이며관심의 분리 측면에서 보자면 view code와 data code를 분리하는 것으로 MVC 패턴과 자연스레 함께 발전되어 왔습니다.
템플릿 엔진은 어디서 실행되느냐에 따라 server-side와 client-side로 구분하기도 하는데요,
server-side 템플릿 엔진에는 스프링을 써보신 많은 분들이 익숙하실 JSP(Java Server Pages) 뿐만 아니라, 레이아웃 템플릿을 제공하는 apache tiles, 메시지 템플릿 등을 제공하는 velocity engine 등이 있으며,
client-side 템플릿 엔진에는 javaScript 기반의 프레임워크인 Vue.js, Mustache.js 등이 있습니다.
client-side 템플릿이 발전하게 된 계기인 SPA(Single Page Application)에 관해서는 다음에 기회가 되면 다뤄보도록 하겠습니다..)
3. JSP vs Thymeleaf
Spring Framework는 차세대 프레임워크인 Spring Boot를 출시하면서 공식적으로 JSP를 더 이상 사용하지 말고 Thymeleaf를 사용할 것을 권장하고 있습니다.
Spring의 기본적인 의존성 설정을 제공하는 Spring initializer 에도 JSP는 제외되고 Thymeleaf 만 추가되어 있습니다.
그동안 Java 기반 server-side 템플릿 엔진의 대명사로 불리던 JSP를 두고 왜 Thymeleaf를 쓰게 됐을까요?
성능적인 개선 사항이나 보안 등 여러 가지 이유가 있지만, 여기서는 개발자 입장에서 실무에 도입해보면서 공감했던 기능들 위주로 공유 드려보고자 합니다.
3-1. 코드량이 줄어든다(verbosity)
많은 개발자들이 싫어하는 verbose한 코드량이 줄어듭니다. 다시말해, 핵심 기능을 수행하는 코드 앞뒤로 덕지덕지 붙은 코드가 사라지고 훨씬 간결하고 읽기 쉬워집니다.
JSP의 경우 html을 동적으로 처리하기 위해 대상 html 앞 뒤로 jsp 코드가 감싸는 구조로 wrapper 방식과 유사합니다.단순한 if-else 만 구현하려고 해도 jstl 커스텀 태그만 6줄이 추가로 생깁니다.동적인 분기처리가 많아지는 복잡한 페이지일 수록 퍼블리싱으로부터 수급받은 html 파일과 개발자가 작성한 jsp 파일은 수백줄이 넘게 차이 나기도 해, 원하는 수정 분야를 찾기도 어려워집니다.
반면 Thymeleaf의 경우 jsp 와 달리 기본적으로 태그를 추가로 만들어 감싸는 구조가 아니라, 기존 html 태그 내에 attribute 방식으로 사용합니다.
html 구조 그대로 사용하되, 동적 처리 필요한 부분만 attribute 로 추가하기 때문에 하나의 태그가 길어지기는 해도, 전체적인 코드량은 JSP에 비해 훨씬 줄어듭니다.
(예시 if-else 분기로 결과값 없을 시 문구로 대체, 있는 경우 for loop으로 데이터 노출하는 동적 화면)
3-2. HTML Prototype이 가능하다
1) 파일 단위 프로토타입
JSP
퍼블리싱과 개발자가 구분되어 있는 일반적인 업무 프로세스를 가정했을때 JSP 작업 과정은 아래처럼 이루어집니다.
(1)퍼블리싱 수급(html) → (2).jsp 파일로 변환 → (3)동적 코드 생성 및 데이터 바인딩 → (4)서버 실행 및 템플릿 렌더링 → (5)웹클라이언트 확인
아무래도 수정사항이 많은 (3) ~ (5) 단계를 자주 반복하게 되는데, 동적코드 뿐만이 아니라 HTML 구조만 바꾸는 경우에도 변경사항을 확인하기 위해서는 서버 실행 및 렌더링이 필요합니다.
JSP파일은 .jsp 확장자로 저장되며, 이를 일반적인 웹클라이언트로 열면 소스코드를 단순 텍스트 파일처럼 취급합니다.
그렇다고 이를 강제로 .html 파일로 연다고 하더라도 JSP (그리고 jstl)의 코드는 커스텀 태그 (ex <c:out>, <c:if>)를 쓰기 때문에
서버 단 템플릿 렌더링 없이 바로 html로 보게 될 경우 웹 클라이언트가 알 수 없는 html 태그로 인식 해 단순 텍스트로 출력해버리거나 html 레이아웃이 깨질 수 있습니다.
(JSP 페이지를 브라우저에서 로딩한 경우)
Thymeleaf
반대로 Thymeleaf는 위 프로세스 중 (2) 가 생략돼있는 구조입니다.
Thymeleaf 코드는 html tag의 attribute 로 사용하기 때문에 .html 파일 그대로 저장되고,
Thymeleaf가 추가된 .html 문서를 template engine의 rendering 없이 바로 html로 보게 될 때
웹 클라이언트는 정의되지 않은 attribute는 무시하는 속성이 있기 때문에 html이 깨지지 않고 Thymeleaf를 무시한 버전으로 볼 수 있습니다.
즉, Thymeleaf 는 HTML compliant 한 반면, JSP는 템플릿 렌더링이 필요해 HTML compliant 하지 않으며
잦은 html 변경으로 static html 파일로 프로토타입핑이 필요한 경우 Thymeleaf 가 훨씬 편리합니다.
(Thymeleaf 를 웹 브라우저로 로딩한 경우)
(물론 외부 CSS와 JS는 환경에 따라 로딩 안 될 수도 있습니다.)
2) 레이아웃 프로토타입
header, footer 처럼 여러 페이지가 합쳐진 레이아웃이 필요한 경우 jsp는 include를 파일 단위로 하기 때문에 각 파일에는 include될 코드만 작성할 수 있고, 최종 결과는 전체 페이지의 렌더링을 통해서만 확인할 수 있습니다.
Thymeleaf는 fragment 라는 기능을 통해 include할 파일의 일부분만 지정해서 가져올 수도 있기 때문에,다른 페이지에 include 될 html 이라도 include 될 영역 전/후는 퍼블리싱을 그대로 유지할 수 있어 각 페이지를 독립적으로 프로토타입으로 확인하기 편리합니다.
또한 최종 결과 페이지도 정적 페이지와 동적 렌더링 페이지를 비교하기도 수월합니다.
3) Element 프로토타입
HTML의 각 요소인 element에 동적 데이터를 바인딩 할 때, 퍼블리싱의 예시와 일치하는 데이터를 바인딩 했는지 확인할 때에도 차이가 있습니다.
JSP는 동적 코드를 쓰려면 퍼블리싱으로부터 수급한 html의 예시 데이터를 삭제하고 작성하는 방식으로 서버기동 후에 퍼블리싱 파일과 각각 비교했어야 했습니다.
Thymeleaf는 html의 예시는 그대로 두고, attribute를 추가해놓으면 렌더링 시점에 attribute 내용대로 태그 내용을 replace 하는 방식입니다.
따라서 서버 기동할 필요도 없이 소스코드 수준에서 데이터 바인딩 항목과 퍼블리싱의 예시를 동시 확인 가능합니다.
또한 동일 페이지를 한 탭에는 static하게 로딩하고 한 탭에는 서버 기동해서 로딩해 빠르게 비교도 가능합니다.
3-3. 퍼블리싱과 협업이 용이하다
3-1과 3-2에서 말씀드린바의 연장선상이지만, 기존 HTML의 구조가 최대한 보존되어 있는 형태라서퍼블리싱과 개발자 모두 수정사항을 발견하고 수정하기 편리해집니다.
퍼블리싱은 html 문법만 보고, 필요 시 수정을 하고, 프로토타입으로 확인이 가능합니다.
개발자는 퍼블리싱이 추가/수정한 html을 본인이 작업중인 html 파일에서 쉽게 찾고 반영할 수 있으며, html 수정만 확인하려면 static prototype으로, 동적 데이터까지 확인하려면 서버 렌더링으로 선택해서 확인할 수 있습니다.
4. Thymeleaf의 예시
Thymeleaf의 예시를 통해 어떻게 사용하는지 알아보겠습니다. 기본적인 Spring Boot 프로젝트를 설정하고 Thymeleaf를 사용하여 간단한 웹 페이지를 렌더링하는 예시입니다
프로젝트 설정
- build.gradle 파일 설정:
plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
- Spring Boot 애플리케이션 클래스:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 컨트롤러 클래스:
package com.example.demo;
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("name", "World");
return "hello";
}
}
- Thymeleaf 템플릿:
src/main/resources/templates/hello.html 파일을 생성하고 다음 내용을 추가합니다:
HTML의 콘텐츠에 데이터를 출력할 때는 다음과 같이 th:text="${...}" 를 사용하고,
HTML 테그의 속성이 아니라 HTML 콘텐츠 영역안에서 직접 데이터를 출력하고 싶으면 다음과 같이 [[...]] 를 사용하면 됩니다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello Thymeleaf</title>
</head>
<body>
<h1 th:text="'Hello, ' + ${name} + '!'">Hello, Thymeleaf!</h1>
<ul>
<li>th:text 사용 = <span th:text="${data}"></span></li>
<li>컨텐츠 안에서 직접 출력 = [[${data}]]</li>
</ul>
</body>
</html>
실행 및 확인
Spring Boot 애플리케이션을 실행하고, 브라우저에서 http://localhost:8080/hello로 접속하면 "Hello, World!"라는 메시지가 표시된 페이지를 볼 수 있습니다.
설명
- Controller: HelloController 클래스에서 /hello 경로로 GET 요청이 들어오면 hello 메서드가 호출되고, 모델에 "World"라는 이름을 추가합니다. 이 모델 데이터를 hello.html 템플릿으로 전달합니다.
- Template: hello.html 파일에서는 th:text 속성을 사용하여 모델에서 전달된 데이터를 출력합니다. ${name}은 모델에 있는 name 속성의 값을 의미합니다.
이 예시는 Thymeleaf가 어떻게 동작하는지, 그리고 Spring Boot와의 통합이 얼마나 쉬운지 보여줍니다.
정리
Thymeleaf는 server-side template engine으로 차세대 Spring Framework 인 Spring Boot의 전폭적인 지지 하에 JSP를 대체하고 있습니다.
JSP를 사용하다가 Thymeleaf를 사용해본 결과 느낀 점은 크게 2가지 입니다.
1. 개발 속도가 빨라진다
2. 잦은 변경에 유연해진다
기본적인 코드량이 줄어들고 html의 큰 구조를 헤치지 않기 때문에 수정이 필요한 소스를 찾기도, 수정하기도 편해졌습니다.
또한 퍼블리싱 수정이 발생해 html 수정이나 추가가 필요한 경우에도 상대적으로 수월하게 진행했습니다.
더불어, JSP 의 경우 텍스트 가공, 날짜 가공, 숫자 가공 등 기능에 특화된 custom tag library를 필요한 곳마다 각각 선언해서 사용해야 했는데
Thymeleaf의 경우 dependency 하나만으로 더 강력한 기능과 편리한 문법, 최신Java 버전 지원 등을 제공해서 개발하기 편했습니다.
다만, Thymeleaf의 경우 Spring Boot와 함께 발전한 기술이기에 Spring Boot가 제공하는 gradle 과 같은 빌드 툴을 통한 빠른 빌드, 내장 톰캣을 활용한 경량화된 로컬 서버 기동과 같은 지원 없이는 Thymeleaf의 장점이 퇴색할 수 있습니다.
Spring Boot가 아닌 기존의 Spring에서 JSP만 Thymeleaf로 대체한다던가 일부 페이지만 Thymeleaf로 바꿔보는 경우보다는Spring Boot로 완전한 프레임워크 전환과 Java 버전 업을 함께 병행했을 때 제대로 효과를 발휘할 수 있다고 생각합니다.
연관된 글 :
참고:
https://hstory0208.tistory.com/entry/Thmeleaf타임리프란-타임리프의-기본-기능알아보기
'개발 > front-end' 카테고리의 다른 글
[JavaScript] scroll 이벤트로 특정영역 도달시 function 호출 (0) | 2024.06.09 |
---|---|
[JavaScript] flatMap (0) | 2024.06.06 |
모노레포(Monorepo) (0) | 2023.04.23 |
프론트엔드 공부하기 (0) | 2023.03.16 |
jQuery API (0) | 2019.04.16 |