멀티캠퍼스

[2026.07.07] - TIL 67일차 (JSP 게시판을 Thymeleaf로 전환하기)

buckwheat 2026. 7. 7. 17:37

StartBoot02_Thymeleaf 프로젝트에서 기존 JSP 게시판 화면을 Thymeleaf 템플릿으로 바꾸는 작업을 했다.
기존 Controller, Biz, Dao, Mapper 구조는 유지하고, View 영역만 JSP에서 Thymeleaf HTML로 전환하는 흐름이었다.


1. JSP와 Thymeleaf의 차이

JSP에서는 데이터를 출력할 때 ${}를 HTML 안에 직접 작성했다.

${dto.mytitle}

Thymeleaf에서는 HTML 태그의 th:* 속성을 사용한다.

<td th:text="${dto.mytitle}">제목</td>

Thymeleaf의 장점은 HTML 파일 자체가 브라우저에서도 어느 정도 자연스럽게 보인다는 점이다.
제목 같은 기본 텍스트를 넣어두면 서버 없이 열었을 때도 화면 구조를 확인할 수 있다.


2. Thymeleaf 기본 선언

Thymeleaf 문법을 사용하려면 HTML 태그에 네임스페이스를 선언한다.

<html xmlns:th="http://www.thymeleaf.org">

이 선언을 해야 th:text, th:href, th:action, th:onclick 같은 Thymeleaf 속성을 명확하게 사용할 수 있다.


3. 목록 페이지 구현

게시글 목록은 Controller에서 list라는 이름으로 전달된다.

model.addAttribute("list", biz.selectList());
return "myboardlist";

Thymeleaf에서는 th:each로 목록을 반복 출력한다.

<tr th:each="dto : ${list}">
    <td th:text="${dto.myno}">번호</td>
    <td th:text="${dto.myname}">작성자</td>
    <td>
        <a th:text="${dto.mytitle}" th:href="@{/myboard/detail(myno=${dto.myno})}">
            제목
        </a>
    </td>
    <td th:text="${dto.mydate}">날짜</td>
</tr>

여기서 ${list}는 Model에 담긴 게시글 목록이고, dto는 반복 중인 게시글 하나를 의미한다.


4. ${}@{} 차이

Thymeleaf에서 자주 쓰는 표현식은 ${}@{}이다.

${} : Model에 담긴 데이터 꺼내기
@{} : URL 만들기

예를 들어:

<td th:text="${dto.myname}">작성자</td>

이 코드는 dto 객체의 myname 값을 화면에 출력한다.

반면:

<a th:href="@{/myboard/detail(myno=${dto.myno})}">상세</a>

이 코드는 다음과 같은 URL을 만든다.

/myboard/detail?myno=1

즉, $는 데이터, @는 주소라고 생각하면 이해하기 쉽다.


5. 상세 페이지 구현

상세 페이지에서는 Controller에서 dto 하나만 전달한다.

model.addAttribute("dto", biz.selectOne(myno));
return "myboarddetail";

따라서 반복문 없이 ${dto.필드명}으로 출력하면 된다.

<td th:text="${dto.myno}">번호</td>
<td th:text="${dto.myname}">작성자</td>
<td th:text="${dto.mytitle}">제목</td>
<td>
    <textarea rows="10" cols="40" readonly="readonly" th:text="${dto.mycontent}">
        내용
    </textarea>
</td>

수정, 삭제 버튼은 해당 글 번호를 URL에 붙여 이동한다.

<input type="button" value="수정"
    th:onclick="|location.href='@{/myboard/updateform(myno=${dto.myno})}'|">

<input type="button" value="삭제"
    th:onclick="|location.href='@{/myboard/delete(myno=${dto.myno})}'|">

6. 등록 페이지 구현

등록 페이지는 새 글을 입력하는 화면이므로 기존 데이터가 필요 없다.

<form th:action="@{/myboard/insert}" method="post">
    <table border="1">
        <tr>
            <th>작성자</th>
            <td><input type="text" name="myname"></td>
        </tr>
        <tr>
            <th>제목</th>
            <td><input type="text" name="mytitle"></td>
        </tr>
        <tr>
            <th>내용</th>
            <td><textarea rows="10" cols="40" name="mycontent"></textarea></td>
        </tr>
    </table>
</form>

name 값은 DTO 필드명과 맞춰야 한다.

name="myname"    -> dto.setMyname()
name="mytitle"   -> dto.setMytitle()
name="mycontent" -> dto.setMycontent()

7. 수정 페이지 구현

수정 페이지는 기존 글 정보를 화면에 먼저 출력한 뒤, 사용자가 제목과 내용을 바꿀 수 있게 한다.

<form th:action="@{/myboard/update}" method="post">
    <input type="hidden" name="myno" th:value="${dto.myno}">

    <input type="text" name="mytitle" th:value="${dto.mytitle}">
    <textarea name="mycontent" th:text="${dto.mycontent}">내용</textarea>
</form>

수정 요청을 보낼 때는 어떤 글을 수정할지 알아야 하므로 myno를 hidden input으로 함께 보낸다.

<input type="hidden" name="myno" th:value="${dto.myno}">

8. JavaScript에서 Thymeleaf 값 사용

상세 페이지에서 버튼 클릭 시 alert를 띄우는 예제도 다뤘다.

<input type="button" value="확인" onclick="test();">

<script type="text/javascript" th:inline="javascript">
    function test(){
        let myno = [[${dto.myno}]];
        let myname = [[${dto.myname}]];
        alert(myno + myname);
    }
</script>

JavaScript 안에서 Thymeleaf 값을 사용할 때는 th:inline="javascript"를 추가하고, [[...]] 문법을 사용한다.

실수했던 부분도 있었다.

onlcick="test();"

이렇게 쓰면 오타 때문에 클릭 이벤트가 실행되지 않는다.
정확히는 아래처럼 써야 한다.

onclick="test();"

정리

오늘은 기존 JSP 게시판 화면을 Thymeleaf 템플릿으로 바꾸면서 View 영역의 문법을 집중적으로 학습했다.

핵심은 다음과 같다.

th:text
- 태그 안의 텍스트를 서버 데이터로 바꿈

th:each
- 리스트 반복 출력

th:href
- 링크 URL 생성

th:action
- form 요청 URL 생성

th:onclick
- 버튼 클릭 시 이동 경로 생성

${}
- Model 데이터 출력

@{}
- URL 생성

[[...]]
- JavaScript 안에서 Thymeleaf 값 사용

JSP에서 하던 게시판 화면 처리를 Thymeleaf 방식으로 바꾸면서, Spring Boot에서는 HTML 템플릿을 더 자연스럽게 사용할 수 있다는 점을 확인했다.