1. @PageableDefault() 사용하여 페이징 처리하기
여러 개의 리스트를 한 번에 보여주지 않고, 정해진 개수로 페이징 처리할 때 @PageableDefault() 어노테이션을 사용하면 쉽게 처리할 수 있습니다.
Service 클래스
@Transactional(readOnly = true)
public Page<Board> BoardList(Pageable pageable) {
return postsRepository.findAll(pageable);
}
우리는 JpaRepository를 상속받은 Repository의 findAll 함수를 사용하여 파라미터로 Pageable 객체를 넣어주면 간단하게 페이징 기능을 구현할 수 있습니다.
Page <T>를 타입으로 지정하면, 반드시 파라미터로 Pageable 객체를 넣어주어야 합니다.
Controller 클래스
@GetMapping("/")
public String index(Model model,
@PageableDefault(size=10, sort = "id", direction = Sort.Direction.DESC)
Pageable pageable) {
model.addAttribute("boards", BoardService.pageList(pageable));
return "index";
}
Controller 클래스에서 View에 리스트 데이터를 전달해 주므로 Controller에서 Service 클래스를 이용하여 데이터를 페이징 처리하여 전달합니다.
@PageableDefault 어노테이션을 통해 한 페이지에 보여줄 크기를 정하고 (size=?), 어떤 필드를 기준으로 정렬할 건지 정하고 (sort = ?), 오름차순 정렬인지 내림차순 정렬인지 (direction = Sort.Direction.DESC) 설정해 줍니다.
그리고 PageableDefault 값을 갖고 있는 변수 Pageable pageable을 선언하여 pageable 변수에 값을 저장합니다.
Page의 값은 1이 아닌 0부터 시작합니다.
즉 url에 localhost:8082/?page=0 인 경우 첫 번째 페이지를 보여주는 주소입니다.
2. 페이징 처리되어 반환되는 JSON 형태의 데이터 값
BoardService.pageList(pageable) 실행하여 반환되는 값 - JSON 형식의 데이터
"content":[
{
"content": [
{"id": 1, "username": "User 0", "title": "Korea", "age": 0},
// 중간 생략
{"id": 5, "username": "User 4", "title": "Korea", "age": 4}
],
"pageable": {
"sort": {
"sorted": false, // 정렬 상태
"unsorted": true,
"empty": true
},
"pageSize": 5, // 한 페이지에서 나타내는 원소의 수 (게시글 수)
"pageNumber": 0, // 페이지 번호 (0번 부터 시작)
"offset": 0, // 해당 페이지에 첫 번째 원소의 수
"paged": true,
"unpaged": false
},
"totalPages": 20, // 페이지로 제공되는 총 페이지 수
"totalElements": 100, // 모든 페이지에 존재하는 총 원소 수
"last": false, // 마지막 페이지인지
"number": 0, // 현재 페이지의 인덱스
"sort": {
"sorted": false, // 정렬 여부
"unsorted": true, // 정렬이 되지 않았는지
"empty": true // 정렬 기준이 없는지
},
"size": 5, // 현재 페이지의 데이터의 개수
"numberOfElements": 5, // 현재 페이지의 데이터 개수
"first": true, // 첫 번째 페이지인지
"empty": false // 페이지 내용이 비어있는지
}
Pageable이 가지고 있는 값을 보면 페이지 처리에 유용한 정보들이 많이 있습니다.
그래서 우리는 Service 클래스에서 페이징 처리한 후 엔티티 객체가 아닌 Page<T> 객체를 통해 실제 엔티티 값과 페이징 처리에 관한 값을 같이 넘겨줘 편리하게 View에 페이징 처리할 수 있습니다.
<div>
<th:block th:each="board : ${boards.content}">
<div class="card m-2">
<div class="card-body">
<h4 class="card-title" th:text="${board.title}"></h4>
<a th:href="@{/board/{id}(id=${board.id})}" class="btn btn-primary">상세보기</a>
</div>
</div>
</th:block>
<ul class="pagination justify-content-center">
<li class="page-item" th:classappend="${boards.first ? 'disabled' : 'active'}">
<a class="page-link"
th:href="@{?page={page}(page=${boards.number-1})}">Previous</a>
</li>
<li class="page-item" th:classappend="${boards.last ? 'disabled' : 'active'}">
<a class="page-link"
th:href="@{?page={page}(page=${boards.number+1})}">Next</a>
</li>
</ul>
</div>
첫 번째 th:block에서는 th:each=”board: ${boards.content}” 를 통해 한 페이지의 데이터들을 하나씩 전달하여 board를 통해 한 페이지에 있는 데이터들을 하나씩 접근할 수 있습니다.
ul 태그를 통해 이전과 다음 버튼을 만들었습니다.
th:classappend="${boards.first ? 'disabled' : 'active'}" 코드를 통해 해당 페이지가 첫 번째인지 확인하여 활성화 또는 비활성화를 적용합니다.
th:href="@{?page={page}(page=${boards.number-1})}" 부분은 Previous 링크를 누르게 되면 이전 페이지로 이동하게 해 줍니다.
boards.number는 현재 페이지의 인덱스를 나타내므로 URL에 ?page="이전 페이지의 인덱스" 값을 전달하여 이전 페이지로 이동시킵니다.