[JPA] Paging
๐ Paging์ด๋?
Paging
์ ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์กฐํํ๋ ๊ฒ์ด ์๋, ์ผ์ ํฌ๊ธฐ์ ํ์ด์ง ๋จ์๋ก ๋ถํ ํ์ฌ ์กฐํํ๋ ๋ฐฉ๋ฒ์ด๋ค. ๋๋์ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์กฐํํ ๋ ๋ฐ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
๐ ๊ตฌ์ฑ ์์
Pageable
Pageable
๋ ํ์ด์ง ์ ๋ณด๋ฅผ ์ถ์ํํ ์ธํฐํ์ด์ค์ด๋ค. ํ์ด์ง ๋ฒํธ, ํ๋์ ํ์ด์ง์ ํฌํจ๋ ๋ฐ์ดํฐ์ ์, ๋ฐ์ดํฐ ์ ๋ ฌ ๊ธฐ์ค ๋ฐ ๋ฐฉํฅ๊ณผ ๊ฐ์ ์ ๋ณด๋ฅผ ํ๋์ ๊ฐ์ฒด๋ก ๋ฌถ์ด์ ๊ด๋ฆฌํ๋ค.
1
2
3
4
@GetMapping("/users")
public Page<UserDto> getUsers(Pageable pageable) {
return userService.getUsers(pageable);
}
Spring MVC
๋ HTTP request ํ๋ผ๋ฏธํฐ์ ์ฟผ๋ฆฌ๋ฅผ ๋ถ์ํ์ฌ ์๋์ผ๋ก Pageable
๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์๋ค.
ex) /users?page=0&size=10&sort=id,desc
1
2
3
4
5
6
7
@GetMapping("/users")
public Page<UserDto> getUsers(
@PageableDefault(size = 10, sort = "id", direction = Sort.Direction.DESC)
Pageable pageable) {
return userService.getUsers(pageable);
}
1
2
3
4
5
6
7
spring:
data:
web:
pageable:
default-page-size: 10
max-page-size: 100
one-indexed-parameters: false
๋ง์ฝ ํ์ด์ง ํ๋ผ๋ฏธํฐ์ ๊ธฐ๋ณธ ๊ฐ์ ์ค์ ํ๊ณ ์ถ๋ค๋ฉด @PageableDefault
์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ๊ฑฐ๋, ์ ํ๋ฆฌ์ผ์ด์
์ค์ ํ์ผ์ ์ ์ญ ์ค์ ์ ์ ์ฉํ๋ค.
1
2
3
4
5
6
7
8
9
@GetMapping("/dashboard")
public String getDashboard(
@Qualifier("user") @PageableDefault(size = 5) Pageable userPageable,
@Qualifier("post") @PageableDefault(size = 10) Pageable postPageable,
Model model) {
// ...
}
๋ง์ฝ ํ๋์ ์ปจํธ๋กค๋ฌ์ ์ฌ๋ฌ ๊ฐ์ Pageable
๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ, @Qualifier
์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ๋ค. ํ๋ผ๋ฏธํฐ ์ ๋์ฌ๋ฅผ ๋ณด๊ณ ์ฌ๋ฐ๋ฅธ Pageable
๊ฐ์ฒด์ ๋งคํ๋ ์ ์๋๋ก ํ๋ค.
ex) /dashboard?user_page=0&user_size=5&post_page=1&post_size=10
PageRequest
PageRequest
๋ Pageable
์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ก, of
๋ฉ์๋๋ฅผ ํตํด ํ์ด์ง ์ ๋ณด๋ฅผ ์ง์ ์์ฑํ๋ค. page
๋ 0๋ถํฐ ์์ํด์ผ ํ๋ฉฐ, size
๋ 1 ์ด์์ด์ด์ผ ํ๋ค.
1
2
// static PageRequest of(int page, int size)
PageRequest request= PageRequest.of(0, 10);
Sort
Sort
๋ JPA์์ ๋ฐ์ดํฐ ์ ๋ ฌ์ ์ํ ์ ๋ณด๋ฅผ ์บก์ํํ๋ ํด๋์ค์ด๋ค. ์ฌ๋ฌ ์ ๋ ฌ ์กฐ๊ฑด์ ํ๋์ ๊ฐ์ฒด๋ก ๊ด๋ฆฌํ ์ ์๋ค. ์ดํ ์ฟผ๋ฆฌ๋ก ๋ณํ๋ ๋ ORDER BY
์ ๊ณผ ์์๋๋ค.
1
2
3
4
Pageable pageable = PageRequest.of(0, 10,
Sort.by("name").ascending().and(Sort.by("createdAt").descending()));
Page<User> users = userRepository.findAll(pageable);
PageRequest
์ ๊ฐ์ด ํ์ด์ง๊ณผ ์ ๋ ฌ์ ๋์์ ์ฒ๋ฆฌํ ๋ ๊ฐ์ด ์ฌ์ฉ๋ ์ ์๋ค.
๐ ํ์ด์ง ๋ฆฌํด ํ์
Page
Page
๊ฐ์ฒด๋ ๋ค์ํ ํํ์ ํ์ด์ง ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค. ์ ์ฒด ์์์ ์์ ์ ์ฒด ํ์ด์ง ์๋ฅผ ๊ณ์ฐํ๋ค.
1
2
SELECT โฆ FROM โฆ ORDER BY โฆ LIMIT :size OFFSET :offset
SELECT COUNT(*) FROM โฆ
๋ด๋ถ์ ์ผ๋ก ๋ ๊ฐ์ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋๋ฐ, ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ์ฟผ๋ฆฌ, ๋ฐ์ดํฐ ์ ์ฒด ๊ฐ์๋ฅผ ์กฐํํ๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ค.
1
2
3
4
5
6
@Transactional(readOnly = true)
public Page<UserDto> findUsers(Pageable pageable) {
Page<User> userPage = userRepository.findAll(pageable);
return userPage.map(UserDto::new);
}
map
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด Page<Entity>
๋ฅผ Page<DTO>
๋ก ์ฝ๊ฒ ๋ณํํ ์ ์๋ค. ๋ณํ ์ ํ์ด์ง๋ค์ด์
๊ด๋ จ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ์ ์ง๋๋ค.
Slice
Slice
๊ฐ์ฒด๋ ์ ์ฒด ๋ฐ์ดํฐ ๊ฐ์๋ฅผ ๊ณ์ฐํ์ง ์๊ณ ๋ค์ ํ์ด์ง์ ์กด์ฌ ์ฌ๋ถ๋ง ํ์ธํ๋ค. Page
๊ฐ์ฒด๋ ์ ์ฒด ํ์ด์ง ์๋ฅผ ์กฐํํ๋ COUNT
์ฟผ๋ฆฌ๋ฅผ ์คํํ์ง๋ง Slice
๊ฐ์ฒด๋ฅผ ์คํํ์ง ์๋๋ค. ์ฆ, ์กฐํ ์ฟผ๋ฆฌ ํ ๋ฒ๋ง ์คํํ๋ค.
๋๋์ ๋ฐ์ดํฐ์์
COUNT
์ฟผ๋ฆฌ๋ ๋ณ๋ชฉ ํ์์ด ๋ฐ์ํ ์ ์๋ค.
List
List
ํ์
์ผ๋ก ๋ฆฌํด๋๋ฉด, ํ์ด์ง ๋ฉํ๋ฐ์ดํฐ ์์ด ๋จ์ํ ๋ฐ์ดํฐ๋ง ๋ฆฌํดํ๋ค.
Page
๊ฐ์ฒด๋ ํ์ด์ง ๋ฒํธ, ์ ์ฒด ๋ฐ์ดํฐ ์๋ฅผ ์ฌ์ฉํด์ผ ํ ๋, ํน์ ํ์ด์ง๋ก ์ด๋ํด์ผ ํ ๋ ์ ์ฉํ๋ค.Slice
๊ฐ์ฒด๋ ๋ฌดํ ์คํฌ๋กค๊ณผ ๊ฐ์ด ๋ค์ ๋ฐ์ดํฐ์ ์ ๋ฌด๋ง ํ์ธํ ๋ ์ ์ฉํ๋ค.List
ํ์ ์ ๊ณ ์ ๋ ๊ฐ์์ ๋ฐ์ดํฐ๋ง ์ฌ์ฉํ ๋, ํ์ด์ง ๋ฉํ๋ฐ์ดํฐ๊ฐ ํ์ ์์ ๋ ์ ์ฉํ๋ค.