Pageable
Pageable은 Spring Framework (특히 Spring Data)에서 페이징 처리를 쉽게 하기 위해 제공하는 인터페이스입니다. 즉, "어떤 페이지를, 몇 개씩 가져올지 알려주는 정보"라고 이해하면 됩니다.
이러한 페이징을 개발하기 위해서는 page 관련 쿼리를 파라미터로 받아서 직접 처리하는 방법이 있었지만 Spring 프로젝트에서는 효과적으로 페이징을 처리할 수 있게 방법이 있습니다.
🏷️ 의존성
// jpa를 사용 안하는 경우
implementation 'org.springframework.data:spring-data-commons'
// jpa를 사용하는 경우
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
위에 의존성을 사용하면 JPA는 사용하지 않지만, Pageable, Page, Slice 등 페이징 관련 유틸 클래스를 사용하고 싶은 경우에도 사용이 가능합니다.
🏷️ 주요 구성 요소
구성 | 예시 | 설명 |
page | 0 | 몇 번째 페이지 (0부터 시작) |
size | 10 | 한 페이지에 몇 개 항목 |
sort | createdAt,desc | 어떤 컬럼 기준으로 정렬할지 |
🏷️ 사용 방법 예시
✅ Repository
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findAll(Pageable pageable);
}
✅ Controller
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRepository;
// 방법 1: RequestParam으로 page/size 직접 받기
// → 정렬 옵션 등을 코드로 제어할 때 유리
@GetMapping("/page1")
public ResponseEntity<Page<User>> page(
@RequestParam int page,
@RequestParam int size) {
Pageable pageable = PageRequest.of(page, size);
Page<User> users = userRepository.findAll(pageable);
return ResponseEntity.ok(users);
}
// 방법 2: Pageable을 메서드 인자로 자동 주입
// → page, size, sort 등을 클라이언트에서 직접 조절 가능
@GetMapping("/page2")
public Page<User> getUsers(Pageable pageable) {
return userRepository.findAll(pageable);
}
}
이러면 GET방식으로 /members?page=0&size=3과 같은 API를 호출하면 Spring이 알아서 Pageable 객체에 매핑해 줍니다. 또한 GET방식으로 /members처럼 쿼리 파라미터를 따로 지정하지 않아도, JPA 자체 default 값인 (page=0&size=20)에 따라 페이징을 처리합니다.
✔️ defulat 값 변경하는 법
1. application.yml으로 글로벌 설정 변경
spring.data.web.pageable.default-page-size=20
2. @PageableDefault을 통한 개별 설정 변경
@GetMapping
public Page<User> getUsers(
@PageableDefault(
size = 10, // 한 page 사이즈
sort = "createdAt", // 정렬 기준
direction = Sort.Direction.DESC // 정렬 차순(오름차순, 내림차순)
) Pageable pageable
) {
return userRepository.findAll(pageable);
}
✅ 결과 예시
// json
{
"content": [ ...유저 데이터... ],
"totalPages": 10,
"totalElements": 100,
"size": 10,
"number": 1,
"first": false,
"last": false
}
🏷️ 반환 타입
✅ Page
@GetMapping
public Page<User> getUsers(Pageable pageable) {
return userRepository.findAll(pageable);
}
가장 많이 사용되는 반환 타입으로 전체 데이터 개수, 총 페이지 수, 현재 페이지 등의 페이징 정보와 데이터 리스트를 함께 담고 있습니다.
다음과 같은 경우 사용을 고려해볼 수 있습니다.
- 전체 개수(total count)가 필요한 경우
- 클라이언트에서 페이지네이션 UI 구성할 때 유용
✅ Slice
Page보다 가벼운 구조로 전체 개수(totalElements)는 없고 다음 페이지가 있는지만 알려줍니다.(hasNext)
@GetMapping("/slice")
public Slice<User> getUserSlice(Pageable pageable) {
return userRepository.findAll(pageable);
}
다음과 같은 경우 사용을 고려해볼 수 있습니다.
- 성능이 중요한 모바일 앱, 무한 스크롤 UI 등
- 전체 개수는 굳이 필요 없고, "다음 페이지가 있냐?"만 필요한 경우
✅ List
페이징 정보를 무시하고 데이터만 받고 싶을 때 사용합니다.
@GetMapping("/list")
public List<User> getUserList() {
return userRepository.findAll(); // 모든 데이터 가져옴
}
// 또는 아래처럼 Pageable을 써도 그냥 리스트만 받는 경우
@GetMapping("/paged-list")
public List<User> getUserList(Pageable pageable) {
return userRepository.findAll(pageable).getContent(); // 리스트만 꺼냄
}
다음과 같은 경우 사용을 고려해볼 수 있습니다.
- 페이징 정보 필요 없고, 리스트만 보내줄 때
- 혹은 프론트에서 페이징 따로 처리할 때
📖 Reference
'코딩 공부 > web & Java' 카테고리의 다른 글
[Spring] BCryptPasswordEncoder (0) | 2025.04.04 |
---|---|
[Java] Comparable과 Comparator (0) | 2025.04.04 |
[Java] Stream (0) | 2025.04.02 |
[JPA] CRUDRepository와 JPARepository (0) | 2025.04.01 |
[Mockito] ArgumentMatchers 및 any,eq (1) | 2024.10.21 |