SSR 방식으로 공통 레이아웃 구성부터 유저 관리까지
이번 포스트에서는 Thymeleaf를 활용한 서버 사이드 렌더링(Server Side Rendering, SSR) 방식을 직접 서버를 띄워보며 실습 중심으로 다뤄보겠습니다.
Thymeleaf는 서버에서 HTML 뷰를 렌더링한 뒤 클라이언트에 전달하는 서버 사이드 렌더링(SSR) 템플릿 엔진입니다.
이 방식은 사용자가 페이지에 접근했을 때 이미 완성된 HTML을 받아보기 때문에 초기 렌더링 속도가 빠르다는 장점이 있습니다.
하지만 페이지 내에서 동적인 클릭이나 입력 이벤트가 발생하면 전체 페이지를 다시 렌더링해야 하므로, 인터랙션에 있어 지연이 발생할 수 있는 단점도 존재합니다.
이러한 특성 때문에 관리자 페이지처럼 안정성과 정확성이 중요한 경우, SSR 기반의 Thymeleaf 방식이 자주 사용됩니다.
기존 프로젝트에 Thymeleaf 기반의 관리자 페이지를 구성해보겠습니다.
이번 실습에서는 아래 기능을 구현할 예정입니다.
spring boot로 진행합니다.
build.gradle에 Thymeleaf 관련 의존성을 추가합니다.
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
resources/ 폴더 내에 다음 구조로 디렉토리를 생성합니다:
src/
└── main/
└── resources/
├── static/
│ └── globals.css
└── templates/
├── fragments/
│ └── common.html
├── index.html
└── users.html
<!-- fragments/common.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:fragment="head(title)">
<meta charset="UTF-8" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<link href="globals.css" th:href="@{/globals.css}" rel="stylesheet" />
<title th:text="${title}">hello K-FreeMarket</title>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-dark" th:fragment="navibar">
<div class="container">
<a class="navbar-brand text-white" href="/admin">K-FreeMarket</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active text-white" th:href="@{/admin}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" th:href="@{/admin/users}">유저</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" th:href="@{/admin/products}">상품</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" th:href="@{/admin/events}">이벤트</a>
</li>
</ul>
</div>
</div>
</nav>
</body>
</html>
이제 공통 레이아웃을 실제 페이지에서 불러와 사용합니다.
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('K-FreeMarket 관리자 홈')"></head>
<body>
<nav th:replace="fragments/common :: navibar"></nav>
<main class="container p-5">
<h2>관리자 홈 페이지</h2>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
th:replace="fragments/common :: head('제목')"
→ 해당 fragment를 현재 태그에 치환(inline replace) 합니다.
index.html과 users.html에서 동일한 navbar가 렌더링된 모습:


Thymeleaf는 위와 같이 공통 레이아웃을 미리 정의하고 th:replace로 조립함으로써 코드 중복을 줄이고 유지보수를 용이하게 합니다.
정적 리소스와 잘 결합하면, 빠르고 안정적인 관리자용 SSR 페이지를 쉽게 구축할 수 있습니다.
다음 글에서는 users.html에서 유저 테이블 구현, 정렬, 검색, 삭제 기능까지 완성해보겠습니다. 🔧