Post

[JPA] Paging

[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 ํƒ€์ž…์€ ๊ณ ์ •๋œ ๊ฐœ์ˆ˜์˜ ๋ฐ์ดํ„ฐ๋งŒ ์‚ฌ์šฉํ•  ๋•Œ, ํŽ˜์ด์ง• ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š” ์—†์„ ๋•Œ ์œ ์šฉํ•˜๋‹ค.
This post is licensed under CC BY 4.0 by the author.