스프링부트, 타임리프(Thymeleaf)로 파일게시판 만들기
#7 Thymeleaf로 HTML페이지 작성 - 게시글 상세, 수정, 삭제
Detail(게시글 상세) 작성
바로 진행하겠습니다. 지난번처럼 컨트롤러를 참고하며 작성하겠습니다. 우선, list.html에서 DB에서 자료를 가져와 출력하는 코드를 작성했습니다.
<tbody>
<tr th:each="data : ${testlist}" th:onclick="'window.location.href
= \'' + @{/fileBoard/detail/{bno}(bno=${data.b_no})} + '\''">
<td th:text="${data.b_no}" style="cursor: pointer; text-align: center;"></td>
<td th:text="${data.writer}" style="cursor: pointer; text-align: center;"></td>
<td th:text="${data.title}" style="cursor: pointer; text-align: center;"></td>
<td th:text="${data.reg_date}" style="cursor: pointer; text-align: center;"></td>
</tr>
</tbody>
상세내용을 보기 위해 게시글을 클릭했을 때, 해당 게시글의 'b_no'를 가져오고 /fileBoard/detail/{bno} 이 URL에 'b_no'를 달아 'b_no'로 테이블을 조회해 작업을 요청하도록 코드를 작성했습니다. 그래서 컨트롤러를 다음과 같이 작성했습니다.
@RequestMapping("/detail/{b_no}")
private String fileBoardDetail(@PathVariable("b_no") int b_no, Model model) {
model.addAttribute("detail", fboardService.fileBoardDetail(b_no));
return "fileBoard/detail";
}
요청 작업을 controller에서 작업한 후 detail페이지를 출력하도록 작성했습니다. 이제 detail.html을 작성해볼까요?
detail.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>파일게시판 - 상세페이지</title>
</head>
<body>
<div>
<div style="padding: 10px; text-align: center;">
<h1><a th:href="@{/fileBoard/list}" style="text-decoration: none;">CrazyAcade - 자료실</a></h1>
</div>
<div>
<div>
<h4 style="font-weight: bolder;">상세내용</h4>
<br/>
<form role="form" th:object=${fileBoardVO}
th:action="@{/fileBoard/list}" method="post">
<div>
<label style="font-weight: bolder;">제목</label>
<p th:text="${detail.title}"></p>
<input type="hidden" th:field="${detail.title}">
</div>
<div>
<label style="font-weight: bolder;">작성자</label>
<p th:text="${detail.writer}"></p>
<input type="hidden" th:field="${detail.writer}">
</div>
<div>
<label style="font-weight: bolder;">작성일자</label>
<p th:text="${detail.reg_date}"></p>
</div>
<div>
<label style="font-weight: bolder;">첨부파일</label>
</div>
<div>
<label for="" style="font-weight: bolder;">내용</label>
<p th:text="${detail.content}"></p>
<input type="hidden" th:field="${detail.content}">
</div>
<div style="text-align: right;">
<input type="submit" th:value="목록"
th:formaction="@{/fileBoard/list}">
<input type="submit" th:value="수정"
th:formaction="@{/fileBoard/update/{bno}(bno=${detail.b_no})}">
<input type="submit" th:value="삭제"
th:formaction="@{/fileBoard/delete/{bno}(bno=${detail.b_no})}">
</div>
</form>
</div>
</div>
<br/><br/><br/>
</div>
</body>
</html>
이제 게시글을 클릭해 상세내용이 잘 출력되는지 확인해보세요. 이상이 없다면 아래 사진과 같이 화면이 출력됩니다.
이 페이지에서 '목록' 버튼을 누르면 list페이지로 이동합니다. 이제 '수정' 버튼을 작업할 차례입니다 detail.html에서 '수정' 버튼의 코드를 이렇게 작성했습니다.
<input type="submit" ... th:formaction="@{/fileBoard/update/{bno}(bno=${detail.b_no})}">
이 버튼도 역시 해당 게시글의 'b_no'를 url에 붙여 컨트롤러로 이동하도록 작성했습니다. 우리가 컨트롤로에서 이 요청을 수행할 코드를 아래와 같이 작성했습니다.
@RequestMapping("/update/{b_no}")
private String fileBoardUpdateForm(@PathVariable("b_no") int b_no, Model model) {
model.addAttribute("detail", fboardService.fileBoardDetail(b_no));
return "fileBoard/update";
}
fboardService.fileBoardDetail(b_no) 메서드로 파라미터 값으로 b_no를 받아 @mapper를 통해 MyBatis에서 쿼리문을 실행해 결과값을 가져옵니다. 그리고 update페이지로 이동하도록 작성했습니다. 이제 update.html을 작성해볼까요?
Update(수정) 작성
update.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>파일게시판 - 내용수정</title>
</head>
<body>
<div>
<div style="padding: 10px; text-align: center;">
<h1><a th:href="@{/fileBoard/list}" style="text-decoration: none;">게시글 수정</a></h1>
</div>
<div>
<form role="form" th:object="${fileBoardVO}"
th:action="@{/fileBoard/updateProc}" method="post">
<div>
<label for="title" style="font-weight: bolder;">제목</label>
<input type="text" id="title" name="title"
th:value="${detail.title}">
</div>
<div>
<label for="writer" style="font-weight: bolder;">작성자</label>
<input type="text" id="writer" name="writer"
th:value="${detail.writer}" disabled="disabled">
</div>
<div>
<label for="content" style="font-weight: bolder;">내용</label><br>
<textarea id="content" name="content" rows="15" cols="50">
[[${detail.content}]]
</textarea>
</div>
<div style="text-align: right;">
<input type="hidden" name="b_no" th:value="${detail.b_no}">
<input type="submit" th:value="목록" th:formaction="@{/fileBoard/list}">
<input type="submit" th:value="저장">
<input type="submit" th:value="삭제"
th:formaction="@{/fileBoard/delete/{bno}(bno=${detail.b_no})}">
</div>
</form>
</div>
<br/><br/><br/>
</div>
</body>
</html>
다 작성했다면 detail.html 페이지에서 '수정' 버튼을 눌러보세요. 잘 작동하나요? 이상이 없으면 아래 사진처럼 화면이 출력됩니다.
내용을 수정한 후 '저장' 버튼을 눌러 update 작업을 처리하고 다시 해당 번호의 detail 페이지로 돌아와 제대로 수정이 되었는지 확인하는 작업을 수행해야 합니다. update.html에서 '저장' 버튼을 눌렀을 때 다음 경로로 요청하도록 작성했습니다.
<form role="form" th:object="${fileBoardVO}" th:action="@{/fileBoard/updateProc}" method="post">
컨트롤러에서 이를 요청받아 수행해야 합니다. 그래서 컨트롤러에서 이렇게 작성했습니다.
@RequestMapping("/updateProc")
private String fileBoardUpdateProc(@ModelAttribute FileBoardVO board) {
fboardService.fileBoardUpdate(board);
int bno = board.getB_no();
String b_no = Integer.toString(bno);
return "redirect:/fileBoard/detail/"+b_no;
}
위 화면에서 내용을 수정하고 '저장' 버튼을 눌러 잘 작동되는지 확인해볼까요?
Delete(삭제) 작성
이번에는 '삭제' 버튼을 눌렀을 때 삭제가 진행되도록 코드를 작성하겠습니다. detail.html 파일에서 '삭제 버튼을 눌렀을 때 아래 경로로 이동해 작업을 하도록 작성했습니다.
<input type="submit" ... th:formaction="@{/fileBoard/delete/{bno}(bno=${detail.b_no})}">
해당 컨트롤러 내용을 확인해볼까요?
@RequestMapping("/delete/{b_no}")
private String fileBoardDelete(@PathVariable("b_no") int b_no) {
fboardService.fileBoardDelete(b_no);
return "redirect:/fileBoard/list";
}
명령을 수행하고 다시 list페이지로 가도록 작성했습니다. delete는 따로 페이지가 필요 없이 해당 내용만 수행해주면 됩니다.
이렇게 Thymeleaf를 활용한 기본 게시판 만들기를 완성했습니다. 게시판의 기본인 CRUD를 완성했지만, 아직 뭔가 부족해보입니다. '파일'게시판을 만들기로 했으니, 이제 파일첨부도 가능해야겠죠? 게다가 게시글이 100개, 1,000개가 있다고 생각해보세요. 이 모든 게시글을 list 페이지 하나에 다 띄우면 화면이 엉망진창이 될겁니다. 그래서 페이지처리(Pagination)가 필요합니다. 또한 모양이 너무 보기 안좋으니 CSS(부트스트랩으로 작성할 예정입니다.)도 넣어야겠죠? 다음 글부터 이 3가지를 작성하려합니다. 일단 여기까지 작성하시느라 고생 많으셨습니다! 하지만 아직 끝이 아니라는 것~
댓글