ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ Spring Boot + JPA + Thymeleaf ] 페이징 기능 구현
    Spring Boot 2021. 3. 4. 21:24

    Pageable


    Pageable은 Spring에서 페이징 기능을 위한 파라미터들을 추상화 시킨 인터페이스이다.
    (인터페이스 자체는 매우 간단하고 메서드명도 직관적이기 때문에 소스를 까보는 것도 좋다)
    이 Pageable을 아래와 같이 Controller의 RequestMapping 메서드 인자로 넣을 수 있다.

     

    1. Controller

    - BoardController.java

    @Controller
    @RequestMapping("/board")
    public class BoardController {
    
        @Autowired
        private BoardRepository boardRepository;
    
        @Autowired
        private BoardValidator boardValidator;
    
        // 리스트 출력
        @GetMapping("/list")
        public String list(Model model, @PageableDefault(size = 2) Pageable pageable,
                           @RequestParam(required = false, defaultValue = "") String searchText){
            //Page<Board> boards = boardRepository.findAll(pageable);
            Page<Board> boards = boardRepository.findByTitleContainingOrContentContaining(searchText,searchText,pageable);
    
            int startPage = Math.max(1,boards.getPageable().getPageNumber() - 4);
            int endPage = Math.min(boards.getTotalPages(),boards.getPageable().getPageNumber() + 4);
    
            model.addAttribute("startPage",startPage);
            model.addAttribute("endPage",endPage);
            model.addAttribute("boards", boards);
            return "board/list";
        }
    }

     

    - Pageable 객체를 생성하기 위해서 사용되는 요청 파라미터

    • page : 가져올 페이지 (기본값 : 0)
    • size : 페이지의 크기 (기본값 : 20)
    • sort : 정렬 기준으로 사용할 속성으로 기본적으로 오름차순으로 한다. 정렬 기준 속성이 2개 이상인 경우에는 sort 파라미터를 2개 이상 넣어주면된다. 예) sort=firstname&sort=lastname,asc.

    Pageable 파라미터에 @PageableDefault 어노테이션을 사용하면 디폴트 값을 변경할 수 있다.


    위의 코드를 보면 우선 페이징 처리하기위해 인자로 pagealbe를 넣어주었다. 페이지 디폴트 사이즈는 우선 size=2로 주었고. 한 화면에 페이지 리스트가 4개씩 보여지게 하기 위해서 보여지는 시작페이지와 마지막페이지를 계산해주기 위해

    현재 페이지에서 각각 -4,+4를 하였다 만약 현재 페이지가 4보다 작다면 마이너스값이 나올 수 있기때문에 Math.max()를 이용하여 계산결과 값이 마이너스일때는 1이 뽑히도록 해주었고 마지막 페이지에도 똑같은 방법으로 처리해주었다.

     

    이제 가공된 데이터를 가지고 화면에 표시를 해볼 것이다.

     

    2. View

    - list.html

     

    <!doctype html>
    <html xmlns:th="http://www.thymelef.org">
    <head th:replace="fragments/common :: head('게시판')">
    </head>
    <body>
    <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:replace="fragments/common :: menu('list')">
    </nav>
    
    <div class="container">
        <h2>게시판</h2>
        <div>총 건수 : <span th:text="${boards.totalElements}"></span></div>
        <form class="row g-3 align-items-center d-flex justify-content-end" method="GET" th:action="@{/board/list}">
            <div class="col-auto">
                <label for="searchText" class="col-form-label">검색</label>
            </div>
            <div class="col-auto">
                <input type="text" id="searchText" class="form-control" name="searchText" th:value="${param.searchText}">
            </div>
            <div class="col-auto">
                <button type="submit" class="btn btn-light">검색</button>
            </div>
    
        </form>
        <table class="table">
            <thead>
            <tr>
                <th scope="col">번호</th>
                <th scope="col">제목</th>
    
            </tr>
            </thead>
            <tbody>
            <tr th:each="board : ${boards}">
                <th th:text="${board.id}">1</th>
                <td><a th:text="${board.title}" th:href="@{/board/form(id=${board.id})}" >Mark</a></td>
    
            </tr>
            </tbody>
        </table>
        <nav aria-label="Page navigation example">
            <ul class="pagination">
                <li class="page-item" th:classappend="${1 == boards.pageable.pageNumber+1} ? 'disabled' ">
                    <a class="page-link" href="#" th:href="@{/board/list(page=${boards.pageable.pageNumber-1},searchText=${param.searchText})}">Previous</a>
                </li>
                <li class="page-item" th:classappend="${i == boards.pageable.pageNumber+1} ? 'disabled' " th:each="i : ${#numbers.sequence(startPage,endPage)}">
                    <a class="page-link" href="#" th:text="${i}" th:href="@{/board/list(page=${i-1},searchText=${param.searchText})}">1</a>
                </li>
                <li class="page-item" th:classappend="${boards.totalPages == boards.pageable.pageNumber+1} ? 'disabled' ">
                    <a class="page-link" href="#" th:href="@{/board/list(page=${boards.pageable.pageNumber+1},searchText=${param.searchText})}">Next</a>
                </li>
            </ul>
        </nav>
        <div class="text-right">
            <a type="button" class="btn btn-primary" th:href="@{/board/form}">글쓰기</a>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
    </body>
    </html>

     

     

    boards.pageable.pageNumber의 값은 인덱스 값이 넘어와서 +1을 해주어 계산해주었고, 만약 첫 페이지의 경우 Previous버튼을 비활성화 시켜주었다. 마찬가지로 Next버튼도 동일하게 처리해주었고. 각 버튼을 클릭했을때 파라미터를 이용하여 이동 페이지값을 넘겨주었다. 이때도 마찬가지로 페이지표현상 +1 처리가 되어있기때문에 컨트롤러에서는 인덱스값으로 계산되어야 하므로 -1해주어 값을 넘겨주어야한다.

Designed by Tistory.