스프링 페이징 정리
참고한 사이트
back : Spring 블로그 만들기 - 9. 페이징(pagination)
front : [JavaScript] 페이지 처리, 페이징 처리
*페이징 코드를 구글링 해보니 코드가 정석이 없는 것 같아서(계산 식이 다 다름)
참고만 하고 내가 원하는 값으로 코드 변형했다.
prev : 이전 버튼
startPage : 페이징 첫번째 번호
endPage : 페이징 마지막 번호
next : 다음 버튼
displayPageNum : 페이지 버튼 개수
코드로 작성하기 전에 풀어서 어떻게 작성할 것인지 쓰고 그 뒤에 코드로 작성했다.
사진을 보면 displayPageNum=5로 설정해서 5페이지로 보여지는 것을 알 수 있다.
→ startPage : 1, endPage : 5 가 된다.
다음 페이지를 누르면 6 ~ 10 페이지가 띄워져야 한다.
→ startPage는 1, 6, 11, 16, ... 으로 나와야하고 endPage는 5, 10, 15, 20, ... 으로 나와야 한다.
이전 버튼은 startPage가 1이 아닌 경우에는 생성되어야 한다.
→ displayPageNum에 해당하는 페이징은 startPage가 같아야 한다.
2 ~ 5페이지 클릭 시 startPage는 1
다음 버튼은 총 페이지 수보다 endPage가 적은 경우에는 생성되어야한다.
→ endPage와 총 페이지 수가 같은 경우에는 endPage와 총 페이지 수는 같아야 한다.
총 페이지 수가 7인 경우 endPage는 7이 되야 한다.
* Page에서 기본으로 제공되는 메소드로 사용 → Spring Data JPA 페이징과 정렬
@RequiredArgsConstructor
@Service
public class RegistryService {
private final RegistryRepository registryRepository;
private static final int PAGE_POST_COUNT = 6; // 한 페이지에 존재하는 게시글 수
private int displayPageNum = 5;
private int startPage;
private int endPage;
private boolean prev;
private boolean next;
private int nowPage;
// 작성 글 페이징
public PagingResult getBoards(int curPage) {
Pageable pageable = PageRequest.of(curPage-1, PAGE_POST_COUNT);
Page<Registry> boards = registryRepository.findAllByOrderByCreatedAtDesc(pageable);
// 생성 날짜 순으로 보여주기
List<Registry> boardList = boards.getContent();
// 조회된 데이터
nowPage = (boards.getNumber()+1); // 현재 페이지
startPage = ( ((int) Math.ceil(nowPage/ (double) displayPageNum )) -1) *5 +1;
endPage = startPage+4;
prev = startPage == 1 ? false : true;
next = endPage < boards.getTotalPages()? true : false;
if(endPage >= boards.getTotalPages()) {
endPage = boards.getTotalPages();
next = false;
}
return new PagingResult(boardList, boards.getTotalPages(), startPage, endPage, prev, next);
}
}
Pageable pageable = PageRequest.of(curPage-1, PAGE_POST_COUNT);
client → server : 1부터 시작 // server → client : 0부터 시작
따라서 curpage-1 로 작성
startPage = ( ((int) Math.ceil(nowPage/ (double) displayPageNum )) -1) *5 +1;
자바 Math.ceil 을 그냥 막 쓰면 정수가 나온다.
때문에 아래와 같이 double로 형변환을 해야 소수점이 발생하여 정상적으로 ceil 을 할 수 있다.
출처 : 자바 Math.ceil 사용 방법
* Math.ceil() : 올림 // Math.floor : 내림 // Math.round : 반올림
nowPage = (boards.getNumber()+1); // 현재 페이지
nowPage도 마찬가지다. 0부터 시작해서 +1을 해줬다.
* Github : [기능 추가] 페이징 #45
front
// 작성 글 페이징
function getArticle(curpage) {
$.ajax({
type: "GET",
url: `space/${curpage}`,
contentType: 'application/json; charset=utf-8',
success: function (response) {
let list = response.data; // 조회된 데이터
let fullCount = response.count; // 전체 페이지의 수
$("#c1-posting").empty();
let startPage = response.startPage;
let endPage = response.endPage;
let prev = response.prev;
let next = response.next
//console.log(fullCount, startPage, endPage, prev, next)
// 6 1 5 false true // 6 6 6 true false
//console.log(JSON.stringify(response))
for (let i = 0; i < list.length; i++) {
num = i + 1;
makeListPost(list[i], num, curpage); // 네모 칸 리스트 출력
}
makePagination(fullCount, curpage, startPage, endPage, prev, next);
// 아래 하단 페이징
}
})
}
// 네모 칸 리스트 출력
function makeListPost(board, num) {
let title = board.title;
let content = board.main;
let modi = board.modifiedAt;
let mode = modi.substr(0, 10);
let idx = board.idx;
let tempHtml = `<div class="item"><button onclick="allRegistry(${idx})">
<div class="num">${num}</div>
<div class="title">${title}</a></div>
<div class="date">${mode}</div>
</div>
`
$("#c1-posting").append(tempHtml);
}
// 아래 하단 페이징
function makePagination(count, curpage, startPage, endPage, prev, next) {
let tempHtml = ``;
if (prev) { // 이전 버튼
tempHtml += `<li class="left-number" value="before" >
<button type="button" onclick="beforeClick(${curpage})">
<img type="button" class="paging-num" id="left-num-img" value="0" src="img/left-num.png">
</button></li>`
}
// 페이징 번호 표시
for (let i = startPage; i <= endPage; i++) {
if(curpage ==i) { // 현재 페이지 보여주는 하단 페이징 버튼
tempHtml += `<li class="page-number" value="${i}" id="curPage">
<img class="paging-num" id="page-number1-img" value="0" src="img/num.png">
</li>
`;
} else { // 현재 페이지 외 나머지 페이징 버튼
tempHtml += `<li class="page-number" value="${i}" id="otherPage">
<img class="paging-num" id="page-number1-img" value="0" onclick="getArticle(${i})" src="img/num.png"></li>
`; // value는 페이지 값 // getArticle(db 저장된 idx) 값
}
}
if (next) { // 다음 버튼
tempHtml += `<li class="right-number" value="after"><button type="button" id="nextButton" onclick="nextClick(${curpage})"><img class="paging-num" id="right-num-img" value="0" src="img/right-num.png"></button></li>`
}
$('#board-pages').html(tempHtml);
}
function beforeClick(curpage){
getArticle(curpage-1);
}
function nextClick(curpage) {
getArticle(curpage+1);
}
for (let i = startPage; i <= endPage; i++) {}
startPage ~ endPage까지 반복
if (next) {}
다음 버튼이 true이면 다음 버튼 생성
* getArticle() : 서버와 통신 후 makeListPost(), makePagination() 실행
* makePagination() : 하단 페이징 버튼
getArticle(curpage)와 makePagination()이 계속 상호작용하는 것을 포인트로 잡아서
이전 버튼과 다음 버튼을 눌렀을 때 beforeClick(curpage), nextClick(curpage)
각각의 함수가 실행되고 해당 함수가 실행되면 현재 페이지(curpage)를 담아서
getArticle(curpage+1)이 실행되게 했다.
→ 1페이지에서 다음버튼 클릭 시 2페이지로 변환
* Github - front : [add] 페이징 코드 작성 완료 [#50] #55
MySQL DB 추가하기
이제 총 페이지가 10페이지가 넘는 경우
6~10 페이지를 띄울 때 이전 버튼과 다음 버튼이 둘 다 생성되는지 test를 해봐야한다.
일일히 게시글을 작성할 수 없으니 쿼리문으로 작성했다.
작은따옴표를 쓰는 이유는 db에서 작은 따옴표로 문자 데이터를 구분하기 때문이다.
출처 : SQL Injection
INSERT
28개 데이터 작성
INSERT INTO registry(MAIN, TITLE, NICKNAME)
VALUES
('게시글 제목','게시글 내용','nic1'),
('게시글 제목','게시글 내용','nic2'),
('게시글 제목','게시글 내용','nic3'),
('게시글 제목','게시글 내용','nic4'),
('게시글 제목','게시글 내용','nic5'),
('게시글 제목','게시글 내용','nic6'),
('게시글 제목','게시글 내용','nic7'),
('게시글 제목','게시글 내용','nic8'),
('게시글 제목','게시글 내용','nic9'),
('게시글 제목','게시글 내용','nic10'),
('게시글 제목','게시글 내용','nic11'),
('게시글 제목','게시글 내용','nic12'),
('게시글 제목','게시글 내용','nic13'),
('게시글 제목','게시글 내용','nic14'),
('게시글 제목','게시글 내용','nic15'),
('게시글 제목','게시글 내용','nic16'),
('게시글 제목1','게시글 내용','nic'),
('게시글 제목2','게시글 내용','nic'),
('게시글 제목3','게시글 내용','nic'),
('게시글 제목4','게시글 내용','nic'),
('게시글 제목5','게시글 내용','nic'),
('게시글 제목6','게시글 내용','nic'),
('게시글 제목7','게시글 내용','nic'),
('게시글 제목8','게시글 내용','nic'),
('게시글 제목9','게시글 내용','nic'),
('게시글 제목','게시글 내용1','nic'),
('게시글 제목','게시글 내용2','nic'),
('게시글 제목','게시글 내용3','nic');
기존에 REGISTRY에 생성일자와 수정일자를 작성하지 않고 실행했더니
생성일자를 받는 클라이언트에서 오류가 떴다.
DELETE
그래서 다시 작성하기 위해 작성한 db를 지웠다.
DELETE FROM registry where REGISTRY_ID in (47, 48, 49, 50 ,51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74);
db를 지우고 새로 생성하면 id값이 그 전에 작성하고 지운 글에 해당하는 id값 이후로 작성된다.
AUTO_INCREMENT 재정렬
ID값이 75 이상인 DB를 지우고 AUTO_INCREMENT를 재정렬하여서 이어지게 했다.
SET @CNT=0;
UPDATE registry SET registry.REGISTRY_ID = @CNT:=@CNT+1;
# UPDATE 테이블명 SET 테이블명.컬럼이름 = @CNT:=@CNT+1;
# ALTER table 테이블명 AUTO_INCREMENT=원하는 순서;
ALTER table registry AUTO_INCREMENT=47;
ID가 이어져있는것을 확인할 수 있다.
이번엔 제대로 모든 컬럼을 넣었다.
INSERT INTO registry(TITLE, MAIN, NICKNAME, CREATED_AT, MODIFIED_AT)
VALUES
('게시글 제목','게시글 내용','nic1','2022-05-25','2022-05-25'),
('게시글 제목','게시글 내용','nic3','2022-05-25','2022-05-25'),
('게시글 제목','게시글 내용','nic2','2022-05-25','2022-05-25'),
('게시글 제목','게시글 내용','nic4','2022-05-25','2022-05-25'),
('게시글 제목','게시글 내용','nic1','2022-05-25','2022-05-25'),
('게시글 제목','게시글 내용','nic7','2022-05-25','2022-05-25');
test 해보니 6페이지일때 이전 버튼과 다음 버튼이 제대로 나왔다.
그런데 하나 문제를 발견했다.
5페이지에서 6페이지로 넘어가는 건 문제가 없는데
10페이지에서 11페이지로 넘어가는 경우와
11페이지에서 10페이지로 돌아가는 경우에 문제가 발견됐다.
총 페이지가 13페이지로 나온 상황에
10페이지에서 다음 버튼을 누르면 11페이지부터 13페이지까지 보여줘야 하는데
다음 버튼을 누르면 현재 페이지는 11페이지로 바뀌는데
페이징 버튼이 바뀌지를 않고 한번 더 눌러야 페이징 버튼이 바뀌었다.
11페이지 버튼을 누르면 6~10페이지 페이징 버튼으로 변경된다.
startPage 계산을 잘못했다.😢
1~15페이지 정도만 계산해서 이후 번호도 적용되는 걸 확인했어야했다.
올림(nowPage/5)
ex) 올림(16/5=3.2) = 4-1 (3번째 페이징)*5+1=21
ex. 24/5=5-1 4*5+1 = 21번째
startPage = ( ((int) Math.ceil(nowPage/ (double) displayPageNum )) -1) *5 +1;
위 코드로 고치니 정상적으로 실행되었다. 😂
[update] startPage 계산 변경 [#45] #49
'TIL' 카테고리의 다른 글
254일차(모험 163일차) - 프로젝트 (0) | 2022.05.27 |
---|---|
253일차(모험 162일차) - test 코드 작성해보기 (0) | 2022.05.26 |
251일차(모험 160일차) - 페이징 코드 추가 완료 (0) | 2022.05.24 |
250일차(모험 159일차) - 배달 팁 예측하기, 페이징 (0) | 2022.05.23 |
247일차(모험 156일차) - Github, 페이징 코드 수정 (0) | 2022.05.20 |