Spring boot 게시판 목록 페이징(feat. JPA)
by 볼빵빵오춘기게시판에서 페이징 처리를 하지않고 리스트를 보여지게 되면 모든 데이터를 한 번에 가져오기 때문에 가져와야할 데이터가 적은 양이면 문제가 되지않지만 가독성이 떨어질 뿐만아니라 많은 리스트를 가져오게 된다면 서버와 데이터베이스에 부하가 되며, 로딩 시간도 길어지므로 페이징 처리를 했다.
Controller
코드 설명
- @PageableDefault를 이용하여 구현하였다.
- @PageableDefault을 이용하지 않고 Repository에서 List타입으로 가져올 수도 있지만 @PageableDefault을 사용함으로써 페이징처리에 정렬기준, 페이징의 사이즈 등 각각 구현하지않고 가져올 수 있다.
@GetMapping("/communityL") public String list(Model model, @PageableDefault(page = 0, size = 15,sort = "id",direction = Sort.Direction.DESC) Pageable pageable, String searchKeyword){ Page<CommunityEntity> list = null; if(searchKeyword == null) { // 검색어가 없을 경우 list = commnunityService.list(pageable); }else { // 검색어가 있을 경우 list = commnunityService.searchList(searchKeyword, pageable); } // 페이징 처리에 필요 int nowPage = list.getPageable().getPageNumber() + 1; // 현재 페이지를 알려주는 숫자 int startPage = Math.max(nowPage - 4, 1); // 페이지가 시작되는 페이지 숫자 int endPage = Math.min(nowPage + 5, list.getTotalPages()); // 페이지의 마지막 페이지의 숫자 model.addAttribute("list", list); model.addAttribute("nowPage", nowPage); model.addAttribute("startPage", startPage); model.addAttribute("endPage", endPage); return "community/list"; }
@PageableDefault
- Spring Data JPA에서 페이징을 처리할 때 기본값을 설정하는 데 사용되는 어노테이션이다.
- 클라이언트가 페이지 요청을 하지 않은 경우에도 기본적인 페이징 및 정렬 설정을 적용할 수 있다.
@PageableDefault 속성
- page
- 기본 페이지 번호를 설정한다.
- 인덱스는 0부터 시작한다.
- @PageableDefault(page = 0)는 첫 번째 페이지를 의미한다.
- size
- 한 페이지에 포함될 기본 항목 수를 설정한다.
- @PageableDefault(size = 15)는 한 페이지에 15개의 항목을 포함한다는 의미이다.
- sort
- 정렬 기준 필드를 설정한다.
- @PageableDefault(sort = "id")는 id 필드를 기준으로 정렬한다.
- direction
- 정렬 방향을 설정한다.
- Sort.Direction.ASC는 오름차순, Sort.Direction.DESC는 내림차순 정렬을 의미한다. @PageableDefault(direction = Sort.Direction.DESC)는 내림차순 정렬을 의미한다.
Service
- Page<T> 을 타입으로 지정하면, 파라미터에 Pageable을 받아야한다.
- Spring Data JPA에서 findAll() 메소드를 사용하였다.
public Page<CommunityEntity> list(Pageable pageable){ return commnunityRepository.findAll(pageable); }
HTML
리스트
controller에서 model에 담겨온 list를 tymeleaf에 th:each를 사용하여 리스트를 보여준다.
<div class="col-12 mb-15"> <table class="list-group"> <th> <tr class="list-group-item list-group-item-action active"> <th>no</th> <th >제목</th> </tr> </th> <tbody> <tr th:each="board: ${list}" class="list-group-item list-group-item-action"> <td th:text="${board.id}"></td> <td > <a th:text="${board.title}" th:href="@{${'/communityV/'+board.id}}"></a> </td> </tr> </tbody> </table> <div th:if="${endPage == 0}" class="text-center"> 등록되어있는 글이 없습니다. </div> </div>
페이징
paging 처리에서 th:if를 넣어 현재 페이지와 페이지 숫자가 같으면 비활성화, 현재 페이지와 페이징의 나타나는 숫자가 다르면 링크를 걸어 넘어가도록 처리하였다.
<div class="col-12 mb-30"> <div class="d-flex justify-content-center" th:if="${endPage > 0}"> <ul class="pagination"> <th:block th:each="page : ${#numbers.sequence(startPage, endPage)}"> <li class="page-item"> <a class="page-link" th:if="${page != nowPage}" th:href="@{/communityL(page = ${page - 1}, searchKeyword = ${param.searchKeyword})}" th:text="${page}"></a> <strong class="page-link" th:if="${page == nowPage}" th:text="${page}" style="color : red" ></strong> </li> </th:block> </ul> </div> <form th:action="@{/communityL}" method="get" class="c-searchForm d-flex"> <input type="text" name="searchKeyword" placeholder="제목으로 검색해보세요." class="width100p"> <button type="submit" class="btn btn-primary" >검색</button> </form> </div>
결과화면


블로그의 정보
Hello 춘기's world
볼빵빵오춘기