비동기 방식이 아닌 동기 방식(SSR)을 이용한 페이지네이션
1. View
<!-- page navigation-->
<nav>
{{#pageDTO}}
<ul class="pagination justify-content-center">
<!-- 이전 페이지 버튼 -->
<li class="page-item {{#isFirstPage}}disabled{{/isFirstPage}}">
<a class="page-link" href="?page={{prevPage}}&size={{size}}&sortBy={{sortBy}}&searchKeyword={{searchKeyword}}"><</a>
</li>
<!-- 총 페이지 숫자만큼 링크 생성 -->
{{#pages}}
<li class="page-item {{#isCurrentPage}}active{{/isCurrentPage}}">
<a class="page-link" href="?page={{number}}&size={{size}}&sortBy={{sortBy}}&searchKeyword={{searchKeyword}}">{{number}}</a>
</li>
{{/pages}}
<!-- 다음 페이지 버튼 -->
<li class="page-item {{#isLastPage}}disabled{{/isLastPage}}">
<a class="page-link" href="?page={{nextPage}}&size={{size}}&sortBy={{sortBy}}&searchKeyword={{searchKeyword}}">></a>
</li>
</ul>
{{/pageDTO}}
</nav>
- mustache 파일이기 때문에 {{#pageDTO}}, {{#pages}} 사용 가능
2. pageDTO, pages 생성
WorldcupService.java
// main 페이지 pagination을 위한 pageDTO 생성
public WorldcupResponse.PageDTO createPageDTO(WorldcupRequest.FindAllDTO findAllDTO) {
// 총 월드컵 개수
int totalItems = worldcupRepository.countAllWorldcup(findAllDTO.getSearchKeyword());
// 총 페이지 수
int totalPages = (int) Math.ceil((double) totalItems / findAllDTO.getSize());
// 현재 페이지
int currentPage = findAllDTO.getPage();
// 페이지 리스트(pages) 생성
List<Map<String, Object>> pages = new ArrayList<>();
for (int i = 1; i <= totalPages; i++) {
Map<String, Object> page = new HashMap<>();
page.put("number", i);
page.put("isCurrentPage", currentPage == i);
pages.add(page);
}
WorldcupResponse.PageDTO pageDTO = WorldcupResponse.PageDTO.builder()
.currentPage(currentPage)
.totalPages(totalItems)
.size(findAllDTO.getSize())
.sortBy(findAllDTO.getSortBy())
.searchKeyword(findAllDTO.getSearchKeyword())
.isFirstPage(currentPage == 1)
.isLastPage(currentPage == totalPages)
.prevPage(currentPage - 1)
.nextPage(currentPage + 1)
.pages(pages)
.build();
return pageDTO;
WorldcupResponse.PageDTO
@Data
public static class PageDTO {
private Integer currentPage;
private Integer totalPages;
private Integer size;
private String sortBy;
private String searchKeyword;
private boolean isFirstPage;
private boolean isLastPage;
private Integer prevPage;
private Integer nextPage;
private List<Map<String, Object>> pages;
@Builder
public PageDTO(Integer currentPage, Integer totalPages, Integer size, String sortBy, String searchKeyword, boolean isFirstPage, boolean isLastPage, Integer prevPage, Integer nextPage, List<Map<String, Object>> pages) {
this.currentPage = currentPage;
this.totalPages = totalPages;
this.size = size; // 쿼리문에서 LIMIT
this.sortBy = sortBy; // 정렬 기준
this.searchKeyword = searchKeyword; // 검색어 있을 경우 적용
this.isFirstPage = isFirstPage;
this.isLastPage = isLastPage;
this.prevPage = prevPage;
this.nextPage = nextPage;
this.pages = pages;
}
}
3. Page 정보을 세션에 담아서 View로 전달
@GetMapping({"/main", "/"})
public String main(Model model, WorldcupRequest.FindAllDTO findAllDTO) {
// 페이지 정보 전송
WorldcupResponse.PageDTO pageDTO = worldcupService.createPageDTO(findAllDTO);
model.addAttribute("pageDTO", pageDTO);
// 이외 로직 생략
return "main";
}
Share article