IT 성장일기

[Thymeleaf] 템플릿 상속을 시식해보자. 본문

Mark up/Thymeleaf

[Thymeleaf] 템플릿 상속을 시식해보자.

고 양 2023. 9. 11. 11:31
반응형
템플릿 상속을 시식해보자.

모든 HTML 문서는 정규화된 폼이 있습니다.

웹 어플리케이션의 수많은 템플릿을 모두 표준 HTML 문서 폼으로 작성한다면 그만큼 많은 중복 코드가 발생합니다.
CSS 파일이라도 하나 더 선언하려면 모든 템플릿 파일에 <link> 태그를 달아야 할지도 모릅니다.

어쩌면 <header> 태그나 <footer> 태그를 수십개씩 복붙해야 할지도 모릅니다.

 

이 문제를 해소하기 위해 Thymeleaf 엔진에서 기본적으로 제공하는 템플릿 상속을 시식해보도록 하겠습니다.

Thymeleaf의 템플릿 상속은 바탕과 조각들로 이루어집니다.

 

(JSP의 경우 Apache Tiles 라이브러리를 활용해 비슷하게 구현할 수 있습니다. ☺)

 

바탕 만들기

가장 먼저 할 일은 바탕 템플릿이 될 layout 파일을 만들어주는 것입니다.
layout 파일은 HTML문서의 정규폼을 따르면서 바탕 템플릿으로서의 역할을 수행합니다.
저는 이렇게 아주 간단한 layout 파일을 만들어봤습니다.

<!--layout.html-->

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width", initial-scale=1, shrink-to-fit="no">
        <link rel="stylesheet" type="text/css" th:ref="@{/style.css}">
        <link rel="stylesheet" type="text/css" th:ref="@{/bootstrap.min.css}">
    </head>
    <body>
        <div>layout.html</div>
        <th:block layout:fragment="content"></th:block>
    </body>
</html>

<th:block layout:fragment="content"></th:block>
이 부분에 조각 템플릿이 삽입됩니다.

 

조각 넣기

다음은 조각 템플릿을 만들어보았습니다.

<!--content.html-->

<html layout:decorate="~{layout}">
    <div layout:fragment="content">
        <div>content.html</div>
    </div>
</html>

<html layout:decorate="~{layout}">
바탕 템플릿을 상속하기 위해 사용해주었습니다.

<div layout:fragment="content">
바탕 템플릿에 삽입 될 조각이라는 의미입니다.
이제 바탕 템플릿의 <th:block layout:fragment="content"></th:block> 부분이 조각 템플릿으로 대체되고
조각 템플릿은 바탕 템플릿을 완전히 상속받아 표준 HTML 구조의 문서로 취급됩니다.

 

결과 확인하기

이제 content 페이지가 layout을 제대로 상속했는지 확인해보겠습니다.

조각 템플릿에는 존재하지 않는 바탕 템플릿의 <div>layout.html<div> 엘리먼트가 포함된 것이 보입니다.😊

 

조각에 또 다른 조각 넣기

조각 템플릿은 th:replace 속성을 사용하여 또 다른 템플릿을 가져올 수 있습니다.
예를 들면 입력 페이지에서 활용되는 <form> 라던가 에러메시지를 띄워줄 토스트용 <div> 등 활용 가능성은 무궁무진합니다.

다음은 공통 템플릿으로 사용될 파일입니다 (아주 간단하게 만들었어요!)

<!--common.html-->

<div th:fragment="commonTemplate">
    <div style="color:cornflowerblue">common.html</div>
</div>

 

<div th:fragment="commonTemplate">

commonTemplate 이라는 이름으로 사용될 조각이라는 의미입니다.

 

그리고 이 공통 템플릿을 상속하기 위해 앞서 만들었던 조각 템플릿을 아래처럼 수정해주었습니다.

<!--content.html-->

<html layout:decorate="~{layout}">
    <div layout:fragment="content">
        <div>content.html</div>
        <div th:replace="~{common :: commonTemplate}"></div> <!--새롭게 추가된 엘리먼트-->
    </div>
</html>

<div th:replace="~{common :: commonTemplate}">common.html</div>
해당 div 엘리먼트를 common 파일의 commonTemplate 속성명을 가진 엘리먼트로 대체한다는 의미입니다.

 

 

결과 확인하기

이제 관리자모드를 열고 content 페이지를 확인해보면 새로운 엘리먼트가 추가된 것을 볼 수 있습니다.

공통 템플릿의 요소 선택해서 가져오기

만약 공통 템플릿에 "commonTemplate"말고, 다른 속성명을 가진 엘리먼트가 있다면, 그 속성명을 적으면 어떻게 될까요?

 

의문점을 해결하기 위해 공통 템플릿을 아래 처럼 수정했습니다.

<!--common.html-->

<div th:fragment="commonTemplate">
    <div style="color:cornflowerblue">common.html</div>
</div>

<!--새롭게 추가된 엘리먼트-->
<div th:fragment="commonRed">
    <div style="color:tomato">common.html - red</div>
</div>

<!--새롭게 추가된 엘리먼트-->
<div th:fragment="commonGreen">
    <div style="color:lightgreen">common.html - green</div>
</div>

 

조각 템플릿에서는 공통 템플릿의 모든 엘리먼트를 불러올 수 있도록 코드를 추가했습니다.

<!--content.html-->

<html layout:decorate="~{layout}">
	<div layout:fragment="content">
		<div>content.html</div>
		<div th:replace="~{common :: commonTemplate}"></div>
		<div th:replace="~{common :: commonTomato}"></div> <!--새롭게 추가된 엘리먼트-->
		<div th:replace="~{common :: commonGreen}"></div>  <!--새롭게 추가된 엘리먼트-->
	</div>
</html>

 

이제 content 페이지를 확인해 볼 시간입니다.

 

결과 확인하기

성공적으로 공통 템플릿의 모든 엘리먼트를 불러올 수 있었습니다.

이를 잘 활용한다면 여러 템플릿에서 사용하게 될 다양한 엘리먼트들을 한 파일에서 간단하게 관리할 수 있을 것 같습니다.

 

도움이 되어드렸다면 구독 / 좋아요 부탁드립니다.👏🏻

감사합니다.🙂

반응형