페이지네이션은 크게 2가지로 나뉜다
1. 프론트엔드에서 모든 데이터를 받아와 페이징하는 방법
2. 모델로부터 데이터를 페이지에 맞게 가져오는 방법
2가지가 있다
나는 2번 방법으로 제작해 보았다
먼저 페이징 처리를 하기 위해선
// 쪽지 목록 (회원)
private static final String SELECTALL_LETTER_LIST = "SELECT LETTER_ID, SENDER, TITLE, LETTER_CONTENTS, LETTER_DATE, "
+ "LETTER_STATUS FROM LETTER WHERE LOGIN_ID=? ORDER BY LETTER_DATE DESC LIMIT ?, ?";
LIMIT를 사용해야합니다
LIMIT 은 범위를 지정할수 있는 함수로서
첫 번째 매개변수는 반환할 행의 시작 위치
두 번째 매개변수는 반환할 최대 수를 지정합니다
그럼 범위를 지정할수 있는 SQL이 있으므로
행의 시작위치를 구하는 메서드를 제작하게 됩니다
// 페이지 번호에 따른 offset 계산
public int calculateOffset(PageInfoDTO pDTO) {
//(현재 페이지 -1) * 몇개씩 자를 건지
//ex) (1 -1)*10 = 0 - 0~9
//(2-1)*10 = 10 - 10~19
pDTO.setOffset((pDTO.getCurrentPage() - 1) * pDTO.getPasingnationSize());
return pDTO.getOffset();
}
그럼 이제 컨트롤러를 제작해보면
package com.jarvis.BalanceGame.controller.user.page;
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.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.gson.Gson;
import com.jarvis.BalanceGame.model.dto.LetterDTO;
import com.jarvis.BalanceGame.model.dto.PageInfoDTO;
import com.jarvis.BalanceGame.model.dto.QuestionDTO;
import com.jarvis.BalanceGame.service.LetterService;
import com.jarvis.BalanceGame.service.PageInfoService;
import jakarta.servlet.http.HttpSession;
import kotlinx.serialization.json.Json;
@Controller
@RequestMapping("/user")
public class LetterListPageController {
@Autowired
private LetterService letterService;
@Autowired
private PageInfoService pageInfoService;
@GetMapping("/letterListPage")
public String letterListPageController(LetterDTO lDTO, PageInfoDTO pDTO, Model model, HttpSession session, Gson gson) {
// 페이징 처리 해야한다
// 뷰에서 데이터를 받는다 몇페이지 클릭하는지 데이터 받음
// 그걸 모델에 보내준다
String loginId = (String)session.getAttribute("loginId");
if(pDTO.getCurrentPage() == 0) {
//처음 진입 시 어떤 페이지인지 모르기 때문에
//현재 페이지를 1로 설정
System.out.println(">>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<");
pDTO.setCurrentPage(1);
}
//해당 유저의 우편을 가져오기위해 설정
pDTO.setLoginId(loginId);
//10개씩 우편을 가져오기 위해 10으로 설정
pDTO.setPasingnationSize(10);
//몇번째의 데이터를 가져올지 설정
//ex) 1페이지면 0~9 - offset 0
// 2페이지면 10~19 - offset 10
pDTO.setOffset(pageInfoService.calculateOffset(pDTO));
System.out.println(pDTO.getOffset());
//서치 컨디션으로 어떤 데이터를 가져올 것인지 설정
pDTO.setSearchCondition("viewAllMessage");
System.out.println("pDTO" + pDTO);
//10개 씩 끊어서 데이터를 가져옴
List<PageInfoDTO> datas = pageInfoService.selectAll(pDTO);
//총패이지 수를 가져오기 위해 메세지 총 개수 를 가져옴
lDTO.setSearchCondition("messageCntMember");
lDTO = letterService.selectOne(lDTO);
System.out.println(lDTO);
//가져온 우편 개수
pDTO.setTotalRows(lDTO.getCnt());
int totalPage = pageInfoService.calcTotalPages(pDTO); // 총페이지 수
System.out.println(totalPage);
if(datas != null) {
model.addAttribute("letterDatas", datas);
model.addAttribute("totalPage", totalPage);
model.addAttribute("page", pDTO.getCurrentPage());
}else {
model.addAttribute("status", "fail");
model.addAttribute("msg", "등록된 문제가 없습니다.");
model.addAttribute("redirect", "");
return "alert";
}
return "/user/letterList";
}
}
위에서 총 페이지 개수를 프론트 쪽으로 반환해주는데 이 부분은
// 토탈 페이지 계산
public int calcTotalPages(PageInfoDTO pDTO) {
if (pDTO.getTotalRows() <= 0) { // 데이터가 없다면
pDTO.setTotalPages(0); // 토탈페이지는 0
}
pDTO.setTotalPages(pDTO.getTotalRows() / pDTO.getPasingnationSize()); // 토탈 페이지 개수
if (pDTO.getTotalRows()>10 && pDTO.getTotalRows() % pDTO.getPasingnationSize() > 0) { // 토탈 페이지 계산했을 때 나머지가 0보다 크다면
pDTO.setTotalPages(pDTO.getTotalPages() + 1); // 페이지 개수 1 증가
}
return pDTO.getTotalPages();
}
이 메서드를 사용해서 총 페이지 개수 또한 받아옵니다
// 페이지 번호 노출 범위 설정 (5개씩)
var paginationRange = 5;
// 페이지 번호 목록 생성 함수
function generatePagination() {
var paginationHTML = '<nav class="blog-pagination justify-content-center d-flex"><ul class="pagination">';
// 이전 페이지 링크 추가
paginationHTML += '<li class="page-item"><a onclick="beforeData();" class="page-link" aria-label="Previous"><i class="ti-angle-left"></i></a></li>';
// 페이지 번호 목록 추가
for (var i = Math.max(1, Math.min(currentPage - Math.floor(paginationRange / 2), totalPage - paginationRange + 1)); i <= Math.min(totalPage, Math.max(currentPage + Math.floor(paginationRange / 2), paginationRange)); i++) {
if (i === currentPage) {
paginationHTML += '<li class="page-item active"><a onclick="'+pageName+'('+i+')"'+ ' class="page-link">' + i + '</a></li>';
} else {
paginationHTML += '<li class="page-item"><a onclick="'+pageName+'('+i+')"'+ 'class="page-link">' + i + '</a></li>';
}
}
// 다음 페이지 링크 추가
paginationHTML += '<li class="page-item"><a onclick="nextData();" class="page-link" aria-label="Next"><i class="ti-angle-right"></i></a></li>';
paginationHTML += '</ul></nav>';
return paginationHTML;
}
// 페이지 목록 업데이트 함수
function updatePagination() {
var paginationContainer = document.querySelector('.blog-pagination');
if (paginationContainer) {
paginationContainer.innerHTML = generatePagination();
}
}
function nextData() {
var commentBox = document.getElementById('comments-area');
if (commentBox) {
// comment-box로 이동
commentBox.scrollIntoView({ behavior: 'smooth' });
}
if ((currentPage + 1) <= totalPage) {
currentPage=currentPage+1;
commentAll();
}
}
function beforeData() {
var commentBox = document.getElementById('comments-area');
if (commentBox) {
// comment-box로 이동
commentBox.scrollIntoView({ behavior: 'smooth' });
}
if ((currentPage - 1) >= 1) {
currentPage=currentPage-1;
commentAll();
}
}
function commentPage(id){
console.log("다음 번호 클릭");
currentPage = id;
console.log("해당 번호"+currentPage);
var commentBox = document.getElementById('comments-area');
if (commentBox) {
// comment-box로 이동
commentBox.scrollIntoView({ behavior: 'smooth' });
}
commentAll();
}
위 페이징 번호를 생성하는 js를 통해 페이징 처리를 성공적으로 할 수 있습니다