Pagination(페이지네이션)은 많은 데이터를 한 번에 로드하지 않고, 페이지 단위로 나누어 처리하는 방식입니다. 특히, 대량의 데이터를 처리할 때 성능 개선에 큰 도움을 줄 수 있습니다. 이 글에서는 Spring에서 제공하는 Pageable을 활용하여 백엔드에서 데이터를 페이지 단위로 조회하고, 이를 프런트엔드에 전달하는 방법을 설명하겠습니다.
1. Pageable 개념과 사용 목적
Pageable은 Spring Data JPA에서 제공하는 인터페이스로, 요청된 페이지 번호, 페이지 크기 등의 정보를 기반으로 데이터를 가져올 수 있도록 지원합니다. 데이터베이스에서 필요한 데이터만 가져와 메모리 사용을 최소화하고, 동시에 필요한 데이터만 프런트엔드에 전달하여 성능을 최적화할 수 있습니다.
주요 특징:
- page: 요청한 페이지 번호 (0부터 시작)
- size: 한 페이지에 포함될 데이터의 개수
- sort: 데이터 정렬 방식
2. Pageable을 활용한 페이지네이션 구현
다음은 Pageable을 사용해 데이터를 조회하고, 조회 결과와 페이지 정보를 API 응답으로 제공하는 예시입니다.
Pagination 객체 정의
먼저, 페이지 정보를 담을 DTO 객체인 Pagination 클래스를 정의합니다. 이 객체는 현재 페이지, 페이지 크기, 총 페이지 수, 총 데이터 개수 등을 저장합니다.
package com.example.simple_board.common;
import lombok.*;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Pagination {
// 현재 페이지
private Integer page;
// 페이지당 크기
private Integer size;
// 현재 페이지에 있는 요소 개수
private Integer currentElement;
// 총 페이지 수
private Integer totalPage;
// 전체 데이터 개수
private Long totalElement;
}
API Controller에서 Pageable 사용
다음은 Pageable을 사용해 게시글 목록을 페이지 단위로 가져오는 Controller의 예입니다. @PageableDefault 어노테이션을 사용해 기본 페이지와 페이지 크기를 설정할 수 있습니다.
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/posts")
public class PostController {
private final PostService postService;
@GetMapping("/all")
public Api<List<PostEntity>> list(
@PageableDefault(page = 0, size = 10) Pageable pageable
) {
return postService.all(pageable);
}
}
PostService에서 Pageable 처리
PostService에서는 PostRepository를 사용하여 데이터베이스에서 Pageable 객체를 활용해 페이지 단위로 데이터를 조회합니다. 또한, 조회된 데이터와 함께 페이지네이션 정보를 담은 Pagination 객체를 생성하여 API 응답에 포함시킵니다.
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
@Service
public class PostService {
private final PostRepository postRepository;
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
public Api<List<PostEntity>> all(Pageable pageable) {
// Pageable 객체를 이용해 데이터 조회
Page<PostEntity> list = postRepository.findAll(pageable);
// 페이지네이션 정보 생성
Pagination pagination = Pagination.builder()
.page(list.getNumber()) // 현재 페이지 번호
.size(list.getSize()) // 페이지당 데이터 개수
.currentElement(list.getNumberOfElements())// 현재 페이지 데이터 개수
.totalPage(list.getTotalPages()) // 전체 페이지 수
.totalElement(list.getTotalElements()) // 전체 데이터 수
.build();
// 응답 객체 생성
Api<List<PostEntity>> response = Api.<List<PostEntity>>builder()
.body(list.toList()) // 조회된 데이터
.pagination(pagination) // 페이지네이션 정보
.build();
return response;
}
}
Api 응답 포맷 정의
데이터와 페이지네이션 정보를 함께 포함할 수 있는 Api 응답 포맷을 정의합니다.
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class Api<T> {
private T body; // 실제 데이터
private Pagination pagination; // 페이지네이션 정보
}
3. 프런트엔드에 페이지네이션 정보 전달
이제 백엔드에서 반환된 페이지네이션 정보를 프런트엔드로 전달할 수 있습니다. 예를 들어, 프런트엔드에서는 응답을 통해 페이지 정보와 함께 데이터를 받아 사용자가 현재 어떤 페이지에 있는지, 전체 페이지 수는 얼마인지 등을 알 수 있습니다.
응답 예시
{
"body": [
{
"id": 1,
"title": "게시글 제목 1",
"content": "게시글 내용 1"
},
{
"id": 2,
"title": "게시글 제목 2",
"content": "게시글 내용 2"
}
],
"pagination": {
"page": 0,
"size": 10,
"currentElement": 2,
"totalPage": 1,
"totalElement": 2
}
}
- body: 실제 데이터 목록입니다.
- pagination: 페이지네이션 정보를 담고 있으며, 현재 페이지, 페이지 크기, 전체 페이지 수, 전체 데이터 개수를 포함합니다.
프런트엔드에서 페이지네이션 처리
프런트엔드에서는 백엔드에서 전달된 페이지네이션 정보를 활용해 페이지 네비게이션을 구현할 수 있습니다. 예를 들어, 아래와 같은 페이지 네비게이션 UI를 만들 수 있습니다.
<div>
<span>Page {{pagination.page + 1}} of {{pagination.totalPage}}</span>
<button v-if="pagination.page > 0" @click="goToPage(pagination.page - 1)">Previous</button>
<button v-if="pagination.page < pagination.totalPage - 1" @click="goToPage(pagination.page + 1)">Next</button>
</div>
프런트엔드에서 페이지 변경 요청이 발생하면, 해당 페이지 번호를 포함한 요청을 백엔드로 보내고, 다시 데이터를 받아서 화면을 갱신할 수 있습니다.
Spring의 Pageable을 사용하면 데이터를 페이지 단위로 효율적으로 처리하고, 필요한 만큼의 데이터만 프런트엔드로 전송할 수 있습니다. 또한, 페이지네이션 정보와 데이터를 함께 전달함으로써 프런트엔드에서 보다 직관적인 사용자 경험을 제공할 수 있습니다.
'Spring Boot' 카테고리의 다른 글
[Spring Boot] Spring MVC 아키텍처: 요청 처리 흐름과 주요 컴포넌트 (0) | 2024.10.14 |
---|---|
[Spring Boot] Filter란? 필터를 활용한 요청 및 응답 로깅 (0) | 2024.10.12 |
[Spring Boot] 여러가지 Annotation (2) | 2024.10.10 |
[Spring Boot] JPA 연관 관계 설정하기 (1) | 2024.10.10 |
[Spring Boot] MySQL 연결하기 (3) | 2024.10.05 |