로그인을 제외하고 다른 부분은 spring이나 spring boot나 뒷단의 코드는 거의 똑같다.
JSP에서 thymeleaf로 변환하는게 정말 무진장 어려웠다...ㅠㅠ
시간을 갖고 문법을 하나하나 바꾸면 되긴 시간은 없고 아는것이 별로 없으니 더 어렵게 느껴졌던 것 같다.
이번 포스팅에서는 [일정] 메뉴의 소스코드를 복기하고 특히 jsp에서 thymeleaf로 바꾼 부분을 위주로 적겠다.

화면은 지난번 spring때와 동일하다.
바로 소스코드를 보겠다.
import com.multi.hodooScheduler.task.model.dto.TaskDTO;
import com.multi.hodooScheduler.task.service.TaskService;
import com.multi.hodooScheduler.user.model.dto.UserDTO;
import com.multi.hodooScheduler.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Map;
import java.util.UUID;
@Controller
@RequestMapping("/task")
public class TaskController {
private TaskService taskService;
private UserService userService;
@Autowired
public TaskController(TaskService taskService, UserService userService) {
super();
this.taskService = taskService;
this.userService = userService;
}
@RequestMapping("/list")
public String taskMain() {
return "task/taskMain";
}
@PostMapping("/insert")
public String insertTask(TaskDTO taskDTO, Model model, Principal principal) {
taskDTO.setUserId(principal.getName());
taskDTO.setTaskId(UUID.randomUUID().toString());
String page = "";
try {
int result = taskService.insertTask(taskDTO);
if (result > 0) {
page = "redirect:/task/list";
} else {
model.addAttribute("msg", "할일 저장 실패");
page = "redirect:/task/list";
}
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("msg", "할일 저장 실패");
page = "redirect:/task/list";
}
return page;
}
@RequestMapping("/taskList")
public void selectTaskList(Model model, Principal principal) {
try {
UserDTO loginUser = userService.findUserById(principal.getName());
ArrayList<TaskDTO> list = taskService.selectTaskList(loginUser);
model.addAttribute("list", list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@PostMapping("/taskComplete")
public String updateTask(@RequestBody Map<String, String> data, Model model, Principal principal) {
TaskDTO taskDTO = new TaskDTO();
String complete = data.get("btn").contains("완료") ? "Y" : "N";
String page = "";
taskDTO.setComplete(complete);
taskDTO.setTaskId(data.get("taskId"));
try {
UserDTO loginUser = userService.findUserById(principal.getName());
ArrayList<TaskDTO> list = taskService.updateTask(taskDTO, loginUser);
model.addAttribute("list", list);
page = "task/taskList";
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("msg", "할일 업데이트 실패");
page = "redirect:/task/list";
}
return page;
}
@PostMapping("/taskDelete")
public String deleteTask(@RequestBody Map<String, String> data, Model model, Principal principal) {
TaskDTO taskDTO = new TaskDTO();
System.out.println(data.get("btn"));
String page = "";
taskDTO.setTaskId(data.get("taskId"));
try {
UserDTO loginUser = userService.findUserById(principal.getName());
ArrayList<TaskDTO> list = taskService.deleteTask(taskDTO, loginUser);
model.addAttribute("list", list);
page = "task/taskList";
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("msg", "할일 삭제 실패");
page = "redirect:/task/list";
}
return page;
}
}
import com.multi.hodooScheduler.task.model.dao.TaskDAO;
import com.multi.hodooScheduler.task.model.dto.TaskDTO;
import com.multi.hodooScheduler.user.model.dto.UserDTO;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
@Service
public class TaskServiceImpl implements TaskService {
private TaskDAO taskDAO = new TaskDAO();
private SqlSessionTemplate sqlSession;
@Autowired
public TaskServiceImpl(TaskDAO taskDAO, SqlSessionTemplate sqlSession) {
super();
this.taskDAO = taskDAO;
this.sqlSession = sqlSession;
}
@Override
public int insertTask(TaskDTO taskDTO) {
int reult = taskDAO.insertTask(sqlSession, taskDTO);
return reult;
}
@Override
public ArrayList<TaskDTO> selectTaskList(UserDTO loginUser) throws Exception {
ArrayList<TaskDTO> list = taskDAO.selectTaskList(sqlSession, loginUser);
return list;
}
@Transactional(rollbackFor = Exception.class)
@Override
public ArrayList<TaskDTO> updateTask(TaskDTO taskDTO, UserDTO loginUser) throws Exception {
int result = taskDAO.updateTask(sqlSession, taskDTO);
if (result <= 0) {
throw new Exception("task 업데이트 실패!");
}
ArrayList<TaskDTO> list = taskDAO.selectTaskList(sqlSession, loginUser);
return list;
}
@Transactional(rollbackFor = Exception.class)
@Override
public ArrayList<TaskDTO> deleteTask(TaskDTO taskDTO, UserDTO loginUser) throws Exception {
int result = taskDAO.deleteTask(sqlSession, taskDTO);
if (result <= 0) {
throw new Exception("task 업데이트 실패!");
}
ArrayList<TaskDTO> list = taskDAO.selectTaskList(sqlSession, loginUser);
return list;
}
}
import java.util.ArrayList;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;
import com.multi.hodooScheduler.task.model.dto.TaskDTO;
import com.multi.hodooScheduler.user.model.dto.UserDTO;
@Repository
public class TaskDAO {
public ArrayList<TaskDTO> selectTaskList(SqlSession sqlSession, UserDTO loginUser) throws Exception {
return (ArrayList) sqlSession.selectList("taskMapper.selectTaskList", loginUser);
}
public int insertTask(SqlSessionTemplate sqlSession, TaskDTO taskDTO) {
return sqlSession.insert("taskMapper.insertTask", taskDTO);
}
public int updateTask(SqlSessionTemplate sqlSession, TaskDTO taskDTO) {
return sqlSession.update("taskMapper.updateTask", taskDTO);
}
public int deleteTask(SqlSessionTemplate sqlSession, TaskDTO taskDTO) {
return sqlSession.delete("taskMapper.deleteTask", taskDTO);
}
}
import java.sql.Date;
public class TaskDTO {
private String userId;
private String taskId;
private String content;
private String complete;
private Date createdDate;
public TaskDTO() {
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getComplete() {
return complete;
}
public void setComplete(String complete) {
this.complete = complete;
}
@Override
public String toString() {
return "TaskDTO [userId=" + userId + ", taskId=" + taskId + ", content=" + content
+ ", complete=" + complete + "]";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="taskMapper">
<resultMap type="taskDTO" id="taskResultSet">
<!-- 언더바가 들어가는 쿼리문에 한하여 매핑을 해줘야함 -->
<id property="userId" column="user_id" />
<result property="taskId" column="task_id" />
<result property="content" column="content" />
<result property="complete" column="complete" />
<result property="createdDate" column="create_date" />
</resultMap>
<select id="selectTaskList" parameterType="userDTO"
resultMap="taskResultSet">
SELECT *
FROM TASK
WHERE user_id = #{userId}
order by
create_date
</select>
<insert id="insertTask" parameterType="taskDTO">
insert into task
(user_id,
task_id, content)
values
(#{userId}, #{taskId},#{content})
</insert>
<update id="updateTask" parameterType="taskDTO">
update task
set complete =
#{complete}
where task_id = #{taskId}
</update>
<delete id="deleteTask" parameterType="taskDTO">
delete from task
where task_id =
#{taskId}
</delete>
</mapper>
사실 여기까지는 똑같다!
이제 작성할 코드가 이 포스팅을 작성한 이유인 jsp를 thymeleaf로 변환하는 부분이다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet">
</head>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$.ajax({
url : "taskList",
type : "get",
success : function(result) {
$("#taskArea").html(result);
},
error : function() {
alert("일정 불러오기 실패!");
}
})
})
</script>
<body>
<div th:replace="~{common/menubar :: #menubar}"></div>
<h2 class="mt-5 container" style="text-align: center;">
<label>To Do List</label>
</h2>
<div class="container mt-5">
<form class="row g-3" action="insert" method="post">
<div class="col-3" style="text-align: right;">
<label class="col-form-label">오늘의 할일</label>
</div>
<div class="col-6">
<input type="text" class="form-control" name="content"
placeholder="할일을 입력하세요.">
</div>
<div class="col-3">
<button id="submitBtn" class="btn btn-primary mb-3">저장</button>
</div>
</form>
</div>
<div id="taskArea">
<div th:replace="~{task/taskList :: #task}"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="container mt-5 col-8" id="task">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$("button").click(function() {
let btn = $(this).text();
let taskId = $(this).attr("name");
console.log(taskId);
console.log(btn.includes("취소"));
if (btn.includes("완료") || btn.includes("취소")) {
$.ajax({
url : "taskComplete",
type : "post",
contentType : 'application/json',
data : JSON.stringify({
btn : btn,
taskId : taskId
}),
success : function(result) {
$("#taskArea").html(result);
},
error : function() {
alert("일정 불러오기 실패!");
}
})
} else if (btn.includes("삭제")) {
$.ajax({
url : "taskDelete",
type : "post",
contentType : 'application/json',
data : JSON.stringify({
btn : btn,
taskId : taskId
}),
success : function(result) {
$("#taskArea").html(result);
},
error : function() {
alert("일정 불러오기 실패!");
}
})
}
})
})
</script>
<div th:each="one : ${list}">
<input name="taskId" type="hidden" th:value="${one.taskId}">
<div id="${one.taskId}" class=" mb-1" style="display: flex;">
<th:block th:if="${one.complete == 'N'}">
<input class="form-control " type="text" th:value="${one.content}"
readonly style="margin-right: 5px;">
<div class="col-auto">
<button th:name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: green;">완료
</button>
</div>
</th:block>
<th:block th:unless="${one.complete == 'N'}">
<input class="form-control " type="text" th:value="${one.content}"
readonly style="margin-right: 5px; background-color: lightgray;">
<div class="col-auto">
<button th:name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: gray;">취소
</button>
</div>
</th:block>
<div class="col-auto">
<button th:name="${one.taskId}" class="btn btn-primary"
style="background-color: red;">삭제
</button>
</div>
</div>
</div>
</div>
spring에서 작업했던 taskMain.jsp 도 함께 적어본다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$.ajax({
url : "taskList",
type : "get",
success : function(result) {
$("#taskArea").html(result);
},
error : function() {
alert("일정 불러오기 실패!");
}
})
})
</script>
<body>
<jsp:include page="../common/menubar.jsp"></jsp:include>
<h2 class="mt-5 container" style="text-align: center;">
<label>To Do List</label>
</h2>
<div class="container mt-5">
<form class="row g-3" action="insert" method="post">
<div class="col-3" style="text-align: right;">
<label for="staticEmail2" class="col-form-label">오늘의 할일</label>
</div>
<div class="col-6">
<input type="text" class="form-control" name="content"
placeholder="할일을 입력하세요.">
</div>
<div class="col-3">
<button id="submitBtn" class="btn btn-primary mb-3">저장</button>
</div>
</form>
</div>
<div id="taskArea">
<jsp:include page="../task/taskList.jsp"></jsp:include>
</div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<div class="container mt-5 col-8" id="task">
<c:forEach items="${list}" var="one">
<%-- <input name="taskId" type="hidden" value="${one.taskId}"> --%>
<div id="${one.taskId}" class=" mb-1" style="display: flex;">
<c:choose>
<c:when test="${one.complete == 'N'}">
<input class="form-control " type="text" value="${one.content}"
readonly style="margin-right: 5px;">
<div class="col-auto">
<button name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: green;">완료</button></div>
</c:when>
<c:otherwise>
<input class="form-control " type="text" value="${one.content}"
readonly style="margin-right: 5px; background-color: lightgray;">
<div class="col-auto">
<button name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: gray;">취소</button></div>
</c:otherwise>
</c:choose>
</div>
<div class="col-auto">
<button name="${one.taskId}" class="btn btn-primary"
style="background-color: red;">삭제</button>
</div>
</c:forEach>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
<script type="text/javascript">
$(function() {
$("button").click(function() {
let btn = $(this).text();
let taskId = $(this).attr("name");
console.log(taskId);
console.log(btn);
if (btn == "완료" || btn == "취소") {
$.ajax({
url : "taskComplete",
type : "post",
contentType : 'application/json',
data : JSON.stringify({
btn : btn,
taskId : taskId
}),
success : function(result) {
$("#taskArea").html(result);
},
error : function() {
alert("일정 불러오기 실패!");
}
})
} else if (btn == "삭제") {
$.ajax({
url : "taskDelete",
type : "post",
contentType : 'application/json',
data : JSON.stringify({
btn : btn,
taskId : taskId
}),
success : function(result) {
$("#taskArea").html(result);
},
error : function() {
alert("일정 불러오기 실패!");
}
})
}
})
})
</script>
// jsp
<jsp:include page="../common/menubar.jsp"></jsp:include>
<jsp:include page="../task/taskList.jsp"></jsp:include>
// thymeleaf
<div th:replace="~{common/menubar :: #menubar}"></div>
<div th:replace="~{task/taskList :: #task}"></div>
// jsp
<c:forEach items="${list}" var="one">
// thymeleaf
<div th:each="one : ${list}">
// jsp
<c:choose>
<c:when test="${one.complete == 'N'}">
<input class="form-control " type="text" value="${one.content}"
readonly style="margin-right: 5px;">
<div class="col-auto">
<button name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: green;">완료</button></div>
</c:when>
<c:otherwise>
<input class="form-control " type="text" value="${one.content}"
readonly style="margin-right: 5px; background-color: lightgray;">
<div class="col-auto">
<button name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: gray;">취소</button></div>
</c:otherwise>
</c:choose>
// thymeleaf
<th:block th:if="${one.complete == 'N'}">
<input class="form-control " type="text" th:value="${one.content}"
readonly style="margin-right: 5px;">
<div class="col-auto">
<button th:name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: green;">완료
</button>
</div>
</th:block>
<th:block th:unless="${one.complete == 'N'}">
<input class="form-control " type="text" th:value="${one.content}"
readonly style="margin-right: 5px; background-color: lightgray;">
<div class="col-auto">
<button th:name="${one.taskId}" class="btn btn-primary"
style="margin-right: 5px; background-color: gray;">취소
</button>
</div>
</th:block>
지금 정리해보면 많이 어렵지도 않은데 처음 할때에는 왜이렇게 어렵게 느껴지던지... ㅠㅠ
그래도 나 좀 성장한듯...! 뿌듯뿌듯 😆
본 포스팅은 멀티캠퍼스의 멀티잇 백엔드 개발(Java)의 교육을 수강하고 작성되었습니다.