본문 바로가기
문제&해결

JSP를 Thymeleaf로 바꾸기

by moonstal 2022. 8. 7.

드디어 JSP를 Thymeleaf로 다 바꿨다! 처음에 들었던 강의를 따라 jsp를 사용했었는데 김영한님 스프링 강의를 들으며 타임리프를 알게 되었고 스프링과 통합이 잘 되어있다는 점과 jsp는 거의 사용하지 않는 추세여서 바꿔야겠다고 생각했다. 미루고 미루다 검증로직에서 에러메세지를 보여주는 기능을 적용하고 싶어서 바꾸기 시작했다. 바꾸면서 에러페이지만 엄청봤다. th를 하나씩 빠뜨리기도하고 문법을 잘 몰랐던 부분도 있어서 생각보다 쉽지 않았다. 덕분에 타임리프에 익숙해 질 수 있었다.

의존성

jsp

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
</dependency>

thymeleaf

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>nz.net.ultraq.thymeleaf</groupId>
    <artifactId>thymeleaf-layout-dialect</artifactId>
    <version>3.0.0</version>
</dependency>

템플릿 레이아웃

jsp

헤더와 푸터를 include해서 사용했었다.

<%@ include file="layout/header.jsp"%>
<h2>안녕하세요</h2>
<%@ include file="layout/footer.jsp"%>

thymeleaf

템플릿 조각을 사용한다

<!-- 레이아웃 -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
</head>
<body>
<div th:replace="fragments/header::header"></div>
<div layout:fragment="content" class="content">
</div>
<div th:replace="fragments/footer::footer"></div>
</body>
</html> 

레이아웃 적용

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/layout}">
<div layout:fragment="content">
    <h2>컨텐츠 부분</h2>
</div>
</html> 

Spring Security에서 사용자 정보 가져오기

가장 헤맸던 부분😭

jsp

헤더에 박아두고 어디서든 principal로 접근해서 가져와 사용했었다.

<sec:authorize access="isAuthenticated()">
    <sec:authentication property="principal" var="principal" />
</sec:authorize>

<c:choose>
    <c:when test="${empty principal}">
            <li class="nav-item"><a class="nav-link" href="/auth/loginForm">로그인</a></li>
    </c:when>
    <c:otherwise>
        <li class="nav-item"><a class="nav-link" href="/user/${principal.user.id}">마이페이지</a></li>
    </c:otherwise>
</c:choose>

thymeleaf

권한은 sec:authorize로, 사용자 정보를 ${#authentication.getPrincipal().user.id})}로 가져오면 된다.

<ul class="navbar-nav" sec:authorize="isAnonymous()">
    <li class="nav-item"><a class="nav-link" href="/auth/loginForm">로그인</a></li>
</ul>
<ul class="navbar-nav" sec:authorize="isAuthenticated()">
    <li class="nav-item"><a class="nav-link" th:href="@{/user/{id}(id=${#authentication.getPrincipal().user.id})}">마이페이지</a></li>
    <li class="nav-item" sec:authorize="hasAnyAuthority('ROLE_ADMIN')"><a class="nav-link"href="/admin/item new">상품 등록</a>
</ul>

반복문과 경로변수

jsp

<c:forEach var="board" items="${boards.content}">
    <div class="card m-2" >
        <div class="card-body ">
            <h4 class="card-title">${board.title}</h4>
            <a href="/board/${board.id}" class="btn btn-success ">상세보기</a>
        </div>
    </div>
</c:forEach>

thymeleaf

<div class="card m-2" th:each="board : ${boards.content}">
    <div class="card-body ">
        <h4 class="card-title">[[${board.title}]]</h4>
        <a th:href="@{/board/{id}(id=${board.id})}" class="btn btn-success ">상세보기</a>
    </div>
</div>

조건문과 onclick

jsp

<c:choose>
    <c:when test="${board.likeState}">
        <i class="fas fa-heart" id="likeIcon" onclick="toggleLike(${board.id})"></i>
    </c:when>
    <c:otherwise>
        <i class="far fa-heart" id="likeIcon" onclick="toggleLike(${board.id})"></i>
    </c:otherwise>
</c:choose>

thymeleaf

<i class="fas fa-heart" th:if="${board.likeState}" th:onclick="|toggleLike(${board.id})|"></i>
<i class="far fa-heart" th:unless="${board.likeState}" th:onclick="|toggleLike(${board.id})|"></i>

자바스트립트

jsp

<script src="/js/board.js"></script>

thymeleaf

<script type="text/javascript" th:src="@{/js/board.js}"></script>

타임리프 썸머노트 태그 제거

[(${board.content})] 또는 th:utext="${board.content}"를 사용하면 된다.


그외 기본 문법들은 여기를 참고
바뀐 코드 깃허브 링크

refactor: jsp를 thymeleaf로 변경 · moonstal1506/NongSaJikSsul@9d6ff7c

Show file tree Showing 36 changed files with 700 additions and 497 deletions.

github.com