Back-end/java

게시판 페이징 기능 완료

Nellie Kim 2023. 9. 24. 19:58
728x90

페이징 처리는 막상 해보니, 크게 어려움은 없었는데 변수가 많아서 헷갈렸다.

 

가장 중요한 변수는 세가지 정도이다. 

 

총 게시물 (boards),

페이지 사이즈 (한 페이지에 담기는 게시물 수, pageSize),

총 페이지 수(총 게시물을 페이지사이즈로 나눈 수, totalPages)

 

기본적으로 페이지 사이즈는 10으로 잡는다. 나도 10으로 잡았다. 

1. BoardController

// 게시판 글 조회 (페이징 처리 된)
@GetMapping
public String getAllBoards(Model model, @RequestParam(defaultValue = "1") int currentPage) {
    
    int pageSize = 10; // 페이지당 게시물 수
    List<BoardDto> boards = boardService.getBoardsByPage(currentPage, pageSize);
    int totalPages = boardService.getTotalPages(pageSize);

    model.addAttribute("boards", boards);
    model.addAttribute("totalPages", totalPages);
    model.addAttribute("currentPage", currentPage);

    return "board"; 
}

 

2. BoardServiceImpl

// 페이지 별 게시판 글목록 조회
@Override
public List<BoardDto> getBoardsByPage(int currentPage, int pageSize) {

    int offset = (currentPage - 1) * pageSize; // 현재 2페이지고 페이지사이즈가 10이면 offset은 10

    Map<String, Integer> params = new HashMap<>();
    params.put("pageSize", pageSize);
    params.put("offset", offset);
    return boardMapper.getBoardsByPage(params);
}

// 총 페이지 수 조회
@Override
public int getTotalPages(int pageSize) {
    return boardMapper.getTotalPages(pageSize); // 총 게시물 수가 101이고, 페이지사이즈가 10이면 -> 총 페이지 수는 11
}

offset (현재까지 보여진 페이지 수) 를 사용했다. 

boardMapper.getBoardsByPage(param) 이 메소드에는 map을 파라미터로 넣어주었다. 

 

offset과 페이지사이즈를 넘겨주어 현재 보여줄 페이지 범위에 맞는 게시물을 불러오도록 했다. 

 

예를 들어, offset이 10이고, 페이지사이즈가 10이면 매퍼가 불러올 페이지리스트는 11~20번의 게시물이 되는 것이다.

 

3. BoardMapper 인터페이스

// 페이지 별 게시판 글목록 조회
List<BoardDto> getBoardsByPage(Map<String, Integer> params);

// 총 페이지 수 조회
int getTotalPages(int pageSize);

 

4. BoardMapper.xml

<!--    페이지 별 게시판 글목록 조회-->
    <select id="getBoardsByPage" parameterType="map" resultType="com.example.first.dto.BoardDto" resultMap="boardResultMap">
        SELECT *
        FROM postgres.first_project.boards
        ORDER BY created_at DESC
        LIMIT #{pageSize} OFFSET #{offset};
    </select>

<!--    총 페이지 수 조회-->
    <select id="getTotalPages" parameterType="int" resultType="int">
        SELECT CEIL(COUNT(*)::NUMERIC / #{pageSize})
        FROM postgres.first_project.boards;
    </select>

총 페이지 수를 조회하는 쿼리에서는 CEIL을 사용하여 총 페이지 수가 올림처리 되도록 했다.

 

예를 들어, 

총 게시글이 101개이고, 페이지사이즈가 10이면 101/10 으로 계산하여 10인데, 올림처리를 해서 11의 페이지 수가 반환되는 것이다.

 

5. board.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시판</title>

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <!-- Your custom styles -->
    <style>
        .center-title {
            text-align: center;
        }
        .pagination {
            margin: 20px auto;
        }
        .current-page {
            border: 1px solid #ccc; /* 테두리 스타일 설정 */
            box-shadow: 2px 2px 5px #888; /* 그림자 설정 */
            padding: 5px 10px; /* 내부 여백 설정 */
            border-radius: 5px; /* 모서리를 둥글게 만들기 위한 설정 */
        }
    </style>
</head>

<body>
<div class="container">
    <!-- 마이페이지 버튼 -->
    <div class="text-right mt-2">
        <a href="/logout" class="btn btn-danger mr-2">로그아웃</a>
        <a href="/mypage" class="btn btn-primary mr-2">마이페이지</a>
    </div>
    <br>
    <h2 class="center-title">게시판</h2>

    <!-- 글 작성 버튼 -->
    <a href="/boards/create" class="btn btn-primary mb-3">글 작성</a>

    <!-- 글 목록 -->
    <table class="table">
        <thead>
        <tr>
            <th scope="col" >제목</th>
            <th scope="col">작성자</th>
            <th scope="col">작성일</th>
        </tr>
        </thead>
        <tbody>
        <c:forEach items="${boards}" var="board">
            <tr>
                <td><a href="/boards/${board.boardId}">${board.title}</a></td>
                <td>${board.nickname}</td>
                <td>${board.createdAt}</td>
            </tr>
        </c:forEach>
        </tbody>
    </table>

    <!-- 글 목록 아래 검색창 -->
    <form action="/boards/search" method="GET" style="max-width: 300px; margin: 0 auto;">
        <div class="input-group mb-3">
            <input type="text" class="form-control" placeholder="검색어를 입력하세요" name="keyword" aria-label="검색어" aria-describedby="basic-addon2">
            <div class="input-group-append">
                <button class="btn btn-primary" type="submit">검색</button>
            </div>
        </div>
    </form>

    <br>
    <br>

    <!-- 페이징 처리 -->
    <div class="text-center">
        <ul class="pagination justify-content-center">
            <li class="page-item">
                <c:choose>
                    <c:when test="${currentPage > 1}">
                        <a class="page-link" href="/boards?currentPage=${currentPage - 1}">이전</a>
                    </c:when>
                    <c:otherwise>
                        <span class="page-link">이전</span>
                    </c:otherwise>
                </c:choose>
            </li>
            <c:forEach begin="1" end="${totalPages}" var="pageNumber">
                <li class="page-item">
                    <c:choose>
                        <c:when test="${pageNumber == currentPage}">
                            <span class="page-link  current-page">${pageNumber}</span>
                        </c:when>
                        <c:otherwise>
                            <a class="page-link" href="/boards?currentPage=${pageNumber}">${pageNumber}</a>
                        </c:otherwise>
                    </c:choose>
                </li>
            </c:forEach>
            <li class="page-item">
                <c:choose>
                    <c:when test="${currentPage < totalPages}">
                        <a class="page-link" href="/boards?currentPage=${currentPage + 1}">다음</a>
                    </c:when>
                    <c:otherwise>
                        <span class="page-link">다음</span>
                    </c:otherwise>
                </c:choose>
            </li>
        </ul>
    </div>
</div>
<script>
</script>
</body>
</html>

 

페이징 처리가 잘 된다!