안녕하세요 코이킹입니다.
이번 포스트는 글 상세보기 기능을 구현하는 과정에 대한 내용이 되겠습니다.
1. 목표
- 스프링 부트를 사용해서 웹 어플리케이션을 만드는 흐름에 대해서 이해할 수 있다.
- 스프링 부트를 사용해서 요청 파라미터의 값을 키로 하여 추출한 DB데이터를 화면에 표시하는 웹 어플리케이션을 만들 수 있다.
2. 어떻게 구현할지에 대한 설명
글 상세보기의 핵심을 정의 해보면 글목록처럼 'DB에 저장된 데이터를 화면에 표시하는 것'입니다.
하지만 글목록 처럼 DB의 데이터를 아무 조건 없이 불러오는 것이 아닌 특정한 데이터를 가져와야 한다는 조건이 추가되었습니다.
특정한 데이터를 가져오기 위해서는 '특정한 데이터 검색에 필요한 값을 요청시에 보내는 것'역시 핵심 정의가 되겠습니다.
이제 핵심정의를 바탕으로 해야 할 일을 추려내 보겠습니다.
스스로 질문해 보기 | 스스로 추려낸 답변 |
데이터는 어떻게 표시할 것인가? | 한 화면에 표시할것이라면 페이지 템플릿이 필요할 것, 같은 화면이라면 모달창이 필요. |
별도 페이지를 만든다면 새로 추가하는 페이지로는 어떻게 이동할 것인가? | 글 목록 페이지에서 링크를 추가 |
특정 데이터를 가져오기 위한 키값을 어떻게 백엔드로 보낼 수 있을까? | 요청 파라미터나 경로 파라미터에 특정 값을 담아서 요청하거나, POST요청이라면, 요청 바디에 특정 값을 담아서 넘길 수 있겠다. |
글 상세 보기 요청은 어떤 메서드를 사용해야 할까? | 단순한 데이터 표시이니 GET방식을 사용해야 겠다. |
글 상세보기 요청은 백엔드에서 어떻게 수신해야할까? | 글 상세보기 요청과 매칭되는 메서드를 추가. |
설명은 여기서 마치고 구현하도록 하겠습니다.
3. 소스코드와 해석
1) 글목록 템플릿 : /template-springboot/src/main/resources/templates/board/list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, inital-scale=1.0"/>
</head>
<body>
<div>
<div class="nav justify-content-end px-5 pt-2">
<button class="btn btn-info text-white" id="write-board" type="button" onclick="location.href='/board/write'">
Contents Write
</button>
</div>
<hr/>
<div>
<table class="table" border="1">
<thead class="table-dark">
<tr>
<th>No</th>
<th>Contents Type</th>
<th>Title</th>
<th>CreatedTime</th>
<th>UpdatedTime</th>
<th>Likes</th>
</tr>
</thead>
<tbody>
<tr th:each="board: ${boardList}">
<td th:text="${board.boardNo}"></td>
<td th:text="${board.type}==1 ? 'Normal' : 'MemberShip'"></td>
<td><a th:href="@{/board/read/{boardNo}(boardNo=${board.boardNo})}">[[${board.title}]]</a></td>
<td th:text="${board.createdTime}"></td>
<td th:text="${board.updatedTime}"></td>
<td th:text="${board.likes}"></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
- 32행 : 글 제목을 출력하는 부분을 a태그로 감싸서 링크를 추가했습니다.
링크의 URL에서 타임리프의 문법을 활용하여 글 번호를 경로 파라미터로 설정하였고, 링크를 클릭하여 백엔드로 요청을 보내면 글 번호를 키값으로 하여 글 상세보기에서 출력할 데이터를 검색하게 될 겁니다.
2) 글 상세보기 페이지 : /template-springboot/src/main/resources/templates/board/read.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, inital-scale=1.0"/>
</head>
<body>
<div>
<article class="blog-post">
<div class="board-read-header">
<h1 class="blog-post-title">[[${board.title}]]</h1>
<hr/>
<p class="blog-post-meta mt-2">Created at [[${board.createdTime}]] / Last Updated : [[${board.updatedTime}]]</p>
</div>
<hr/>
<div class="mt-4 mb-5 px-2 py-2" style="width: 100%;">
<div th:text="${board.contents}"></div>
</div>
</article>
<div>
<button class="btn btn-info" type="button" onclick="location.href='/board/list'">Back to List</button>
</div>
</div>
</body>
</html>
- 13, 17, 22행 : 백엔드로 부터 받아온 데이터를 표시합니다. 글 목록과 크게 다른 점은 없습니다.
3) 컨트롤러 : /template-springboot/src/main/java/com/sb/template/controller/BoardController.java
package com.sb.template.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.sb.template.entity.Board;
import com.sb.template.enums.BoardType;
import com.sb.template.forms.BoardForm;
import com.sb.template.service.BoardService;
@Controller
@RequestMapping(path = "/board")
public class BoardController {
@Autowired
private BoardService boardService;
@RequestMapping(method = RequestMethod.GET, path = "list")
public String viewBoardList(Model model) {
List<Board> boardList = boardService.getAllBoard();
model.addAttribute("boardList", boardList);
return "board/list";
}
@RequestMapping(method = RequestMethod.GET, path = "write")
public String writeBoard(Model model) {
model.addAttribute("boardTypes", BoardType.getBoardTypes());
return "board/write";
}
@RequestMapping(method = RequestMethod.POST, path = "write")
public String writeCompleteBoard(BoardForm form, Model model) {
Integer boardNo = null;
boardNo = boardService.createBoard(form.toEntity()).getBoardNo();
return "redirect:/board/list";
}
@RequestMapping(method = RequestMethod.GET, path = "read/{boardNo}")
public String viewBoardOne(@PathVariable int boardNo, Model model) {
model.addAttribute("board", boardService.getBoardOne(boardNo));
return "board/read";
}
}
- 53행 : 경로 파라미터를 사용하기 위해서 '/{파라미터명}'으로 path의 값을 설정했습니다.
- 54행 : 경로 파라미터를 사용하기 위해서 @PathVariable메서드를 사용했습니다.
- 56행 : 서비스에 글 상세보기 처리를 위임한 후 리턴 값을 'board'라는 명칭을 붙여서 리퀘스트 스코프에 저장합니다.
- 58행 : board/read에 해당하는 템플릿을 브라우저로 리턴합니다.
6) 서비스 : /template-springboot/src/main/java/com/sb/template/service/BoardService.java
package com.sb.template.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.sb.template.entity.Board;
import com.sb.template.repo.BoardRepository;
@Service
public class BoardService {
@Autowired
private BoardRepository boardRepository;
public List<Board> getAllBoard() {
List<Board> res = boardRepository.findAll();
if (res == null) return null;
return res;
}
public Board createBoard(Board board) {
return boardRepository.save(board);
}
public Board getBoardOne(int boardNo) {
Optional<Board> board = boardRepository.findById(boardNo);
if (board.isEmpty()) {
return null;
}
return board.get();
}
}
- 31~40행 : 글 번호를 키 값으로 데이터를 가져온다.
4. 동작확인
5. 데이터 흐름
① 유저가 글목록 페이지에서 각 글의 타이틀을 클릭하게되면 글 상세 보기 요청이 백엔드로 보내진다.
요청이 보내질 때의 URL의 경로에는 글 번호가 들어가 있으며, 글 번호(경로 파라미터)를 컨트롤러에서 받아서 변수에 대입하고, 서비스에 글 상세보기 처리를 위임할 때 서비스의 메서드의 파라미터로 변수에 대입해둔 글 번호를 설정한다.
서비스에선 리포지토리를 통해 DB에서 데이터 가져오는데 이때 글 번호를 키값으로 하여 데이터를 가져온다. (Select SQL의 where조건을 글 번호로 설정한 것과 같음)
② DB에서 데이터 추출이 완료되면 컨트롤러까지 데이터가 리턴되고, 컨트롤러에서는 리퀘스트 스코프에 데이터를 저장한 후 템플릿을 브라우저로 리턴한다.
6. 전체 소스코드
https://github.com/leeyoungseung/template-springboot/tree/feature/04_basic_board_read
글 상세보기 구현은 이것으로 마치겠습니다.
다음 포스트는 글 수정하기 구현에 대한 내용이 되겠습니다.
'프로그래밍 > Springboot-토이프로젝트' 카테고리의 다른 글
【게시판-06】글 삭제 (0) | 2022.09.13 |
---|---|
【게시판-05】글 수정 (0) | 2022.09.11 |
【게시판-03】글작성 (1) | 2022.09.08 |
【게시판-02】글목록 (0) | 2022.09.07 |
【게시판-번외02】설계 (0) | 2022.07.09 |
댓글