! 타임리프와 마이바티스, MySQL로 작성한 페이징 예제
동작 방식
맨 아래에 요약 있음
DTO, domain, Entity 구성
@Data
public class PageDTO {
private int limitNoticeList = 10; // 가져올 게시판의 글을 몇 개로 제한시켜 보여줄건지 (10개 씩)
private int limitNoticeNowPage; // 가져올 게시판의 현재 페이지 첫번째 게시물 위치
private int page = 1; // 현재 페이지 / GET 형식으로 쿼리스트링으로 받아오기 위해 준비
private int slicePage = 10; // 몇 페이지로 구성할건지 (10페이지 씩)
}
1. 페이징에 필요한 것들
// 전체 게시물 수
totalList
// DB에서 현재 페이지가 시작하는 행(row)
// 게시물 가져올 때 Limit n, m 에서 n 부분 설정
// (현재 페이지 -1) * 몇 개로 나눠 보여줄건지
// 계산식: (nowPage -1) * limitNoticeList
limitNoticeNowPage
// DB에서 게시물 나눌 수
// 게시물 가져올 때 Limit n, m 에서 m 부분 설정
limitNoticeList
// 총 페이지 수
// 계산식: (전체 게시물 수량(totalList) / 나눌 페이지 수(slicePage)) + 1
totalPage
// 현재 페이지
nowPage
// 페이지를 몇 으로 나눌건지
slicePage
// 페이지를 나눴을 때 시작점
// n = nowPage m = slicePage
// 계산식: (n-1)/m * m + 1
startPage
// 페이지를 나눴을 때 끝점
// 페이지 끝점
// startPage + (m-1)
endPage
// 마지막 페이지 번호 구하기
// ((총 컨텐츠 수 -1 )/ m) + 1;
// 계산식: ((totalList -1) / slicePage) + 1;
lastPage
// 마지막 페이지 번호 이후 안나오게 해야해서 min으로 더 작은 수가 나오게 처리
endPage = Math.min(endPage, lastPage);
2. DB쪽에서 가져올 리스트 목록을 어떻게 LIMIT 할건지 정한다
3. 목록을 만약 10개씩 끊어서 보여주고 싶다면 (maria, mysql 기준) LIMIT을 이용해 작성
SELECT 칼럼명
FROM 테이블명
WHERE 조건식 LIMIT 현재 페이지(nowPage), 보여줄 목록 수(limitNoticeList);
4. LIMIT 한 게시물들을 model에 담아 view로 넘겨준다
5. 총 페이지 수를 구하기 위해 전체 게시물 수를 구한다
6. 몇 페이지씩 나눌 건지 결정한다. (나는 dto에 값을 줌)
7. 정했으면 총 페이지 수가 몇 페이지 나오는지 구한다.
8. 그럼 이제 페이지의 시작점 수와 페이지의 끝점의 수를 구한다
9. 마지막 페이지 번호의 숫자도 알아야 하니 구해준다.
10. 그리고 마지막 페이지 번호 이후 번호가 계속 나오면 안되니깐 Math.min 함수로 처리 해준다.
11. 필요한 재료들이 다 만들어 졌으니 model 을 통해 view로 넘겨준다.
참고로 현재 페이지도 알아야 하니 따로 변수 생성해 model에 넣어줬다.
12. 페이징 처리를 위한 영역을 만들어준다.
13. 우선 페이지번호가 나오는 몸통 영역을 만든다.
페이지의 시작 점 부터 페이지의 끝 점이 나와야 하니 반복문을 사용해야한다.
th:each문으로 jsp의 forEach나 자바의 for문 처럼 사용하려면 ${#numbers.sequence(시작값, 종료값)} 을 이용한다.
#numbers.sequence의 값을 num의 담아준다.
14. 페이지 번호를 출력
하나씩 뜯어보면
반복문을 통해 만들어진 번호를 th:href 문으로 page 번호를 넘겨주고
th:text로 번호가 보이게 만들고
th:style을 통해 현재 페이지를 누른 경우 빨간색으로 표시되게 했다.
타임리프 문법은 내 블로그에서 더 확인해볼 것!
15. 이전, 다음 을 이용해 페이지 넘기기
우선 이전 같은 경우는 페이지의 시작점의 수 - 10 을 이용해 이전 페이지로 이동이 가능하다.
예) 3페이지 경우 21~30 페이지 번호가 있는데 21-10 하면 11~20인 2페이지로 이동
다음 같은 경우 페이지 끝점의 수 + 1 이용해 다음 페이지로 이동이 가능하다.
예) 3페이지로 예시를 들면 21~30 페이지 번호중 30이 페이지 끝점의 수 인데
30+1 하게 되면 페이지 번호가 31로 이동해 31~40번호를 가진 4페이지로 이동된다.
16. 첫 페이지와 마지막 페이지인 경우 첫 페이지는 이전 페이지 불가 / 마지막 페이지는 다음 페이지 불가로 만들어 준다.
같은 코드를 보면 th:block을 만들어 그 안에 th:if문을 만들어 첫페이지인 경우 이전이 안나오게하고 마지막 페이지 인 경우는 다음이 안나오게 처리 했다.
16-1. 첫 페이지에서 이전 안보이게하기
현재 페이지가 10보다 작은 경우 1~9페이지 번호가 해당된다 즉 첫번째 페이지여서 조건에 부합이 안돼 이전이 안나온다.
16-2. 마지막 페이지에서 다음 안보이게 하기
최종 페이지 번호가 마지막 페이지 번호 +1 보다 같거나 크면 조건에 부합이 안돼 다음이 안나온다.
해당 사진 예시에서 최종 페이지번호 (53), 마지막 페이지 번호 + 1 (54)
즉 lastPage (53) >= endPage+1 (54)
lastPage가 endPage보다 안크기 때문에 다음이 안나온다.
17. 처음으로가기 끝으로 가기
처음으로 가기는 그냥 th:href 를 page 맨 처음번호인 1로 보내면 되고
끝으로 가기는 lastPage(마지막페이지)로 보내주면 된다
요약
1. 페이징의 필요한 요소들을 먼저 준비해두기
model.addAttribute("list", getNoticeList); // 게시물
model.addAttribute("totalList", totalList); // 총 게시물 수
model.addAttribute("totalPage", totalPage); // 총 페이지 수
model.addAttribute("startPage", startPage); // 페이지 시작점
model.addAttribute("endPage", endPage); // 페이지 끝점
model.addAttribute("nowPage", nowPage); // 현재 페이지
model.addAttribute("lastPage", lastPage); // 마지막 페이지
2. 반복문을 통해 페이지 시작점 부터 페이지 끝점 까지 출력
- 타임리프 경우 ${#numbers.sequence(반복 시작할번호, 반복 종료번호)} 로 반복문을 돌려 출력
<th:block th:each="num : ${#numbers.sequence(startPage, endPage)}">
<a th:href="@{/notice(page = ${num})}" th:text="${num}" th:style="${nowPage == num?'color: red':'color:'}"></a>
</th:block>
3. 이전, 다음 페이지 만들어 준다
-이전 (페이지 시작점의 수 - 페이지 나눈 수)
-다음(페이지 끝점의 수 - 1)
최종 완성 코드
컨트롤러
/* ===== 게시판(공지, 자유, 문의사항 등등) ===== */
@GetMapping("/notice")
public String notice(PageDTO pageDto, Model model) {
/* 페이징 처리 관련 부분 시작 */
// 게시물 가져올 때 Limit n, m 에서 n 부분 설정
// (현재 페이지 -1) * 몇 개로 나눠 보여줄건지
// 계산식: (nowPage -1) * limitNoticeList
pageDto.setLimitNoticeNowPage((pageDto.getPage() -1) * pageDto.getLimitNoticeList());
// 게시물 가져오기
List<NoticeDTO> getNoticeList = mainService.getNoticeList(pageDto);
// 전체 게시물 수량
Integer totalList = mainService.noticeTotal();
// 나눌 페이지 수
Integer slicePage = pageDto.getSlicePage();
// 총 페이지수
// 계산식: (전체 게시물 수량(totalList) / 나눌 페이지 수(slicePage)) + 1
Integer totalPage = (totalList / slicePage) + 1;
// 페이지 시작점
// n = nowPage m = slicePage
// 계산식: (n-1)/m * m + 1
Integer startPage = (pageDto.getPage() - 1) / slicePage * slicePage + 1;
// 페이지 끝점
// startPage + (m-1)
Integer endPage = startPage + (slicePage - 1);
// 현재 페이지
Integer nowPage = pageDto.getPage();
// 마지막 페이지
// 계산식: ((totalList-1) / slicePage) + 1
Integer lastPage = ((totalList-1) / slicePage) + 1;
// 마지막 페이지 번호 이후 안나오게 해야해서 min으로 처리
endPage = Math.min(endPage, lastPage);
model.addAttribute("list", getNoticeList); // 게시물
model.addAttribute("totalList", totalList); // 총 게시물 수
model.addAttribute("totalPage", totalPage); // 총 페이지 수
model.addAttribute("startPage", startPage); // 페이지 시작점
model.addAttribute("endPage", endPage); // 페이지 끝점
model.addAttribute("nowPage", nowPage); // 현재 페이지
model.addAttribute("lastPage", lastPage); // 마지막 페이지
return "notice";
}
view(html, tymeleaf)
<!--페이징처리-->
<div class="paging_Area">
<a th:href="@{/notice?page=1}"><< 처음</a>
<th:block th:if="${nowPage > 10}">
<a th:href="@{/notice(page = ${startPage - 10})}">< 이전</a>
</th:block>
<th:block th:each="num : ${#numbers.sequence(startPage, endPage)}">
<a th:href="@{/notice(page = ${num})}" th:text="${num}" th:style="${nowPage == num?'color: red':'color:'}"></a>
</th:block>
<th:block th:if="${lastPage >= endPage + 1}">
<a th:href="@{/notice(page = ${endPage+1})}"> 다음 ></a>
</th:block>
<a th:href="@{/notice(page = ${lastPage})}">끝 >></a>
</div>
실제 페이지
'마이바티스' 카테고리의 다른 글
Java, Spring Boot / Jsch: Auth fail => apache.sshd로 해결 (1) | 2024.05.23 |
---|---|
Spring Boot SSH AWS JDBC 연결 with 마이바티스 (0) | 2024.05.20 |
마이바티스 문법 (0) | 2023.10.19 |
마이바티스 쿼리 로그 보기 (0) | 2023.05.16 |
스프링 부트에서 마이바티스 설정하기 (0) | 2023.04.04 |