IT 성장일기
[Thymeleaf] 템플릿 상속을 시식해보자. 본문
템플릿 상속을 시식해보자.
모든 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 페이지를 확인해 볼 시간입니다.
결과 확인하기
성공적으로 공통 템플릿의 모든 엘리먼트를 불러올 수 있었습니다.
이를 잘 활용한다면 여러 템플릿에서 사용하게 될 다양한 엘리먼트들을 한 파일에서 간단하게 관리할 수 있을 것 같습니다.
도움이 되어드렸다면 구독 / 좋아요 부탁드립니다.👏🏻
감사합니다.🙂