Framework/Springboot

[Springboot] ํŽ˜์ด์ง€๋„ค์ด์…˜ Pageable ๊ฐ์ฒด์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž

yuri lee 2023. 2. 12. 11:13
๋ฐ˜์‘ํ˜•

Intro

์•ˆ๋…•ํ•˜์„ธ์š”. ์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ์Šคํ”„๋ง๋ถ€ํŠธ์˜ Pageable ํŽ˜์ด์ง€๋„ค์ด์…˜ ๊ฐ์ฒด์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ œ ๊ฒฝ์šฐ Task๋ฅผ ์ง„ํ–‰ํ•˜๋˜ ๋„์ค‘ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์ด ๋“ค์–ด์˜ธ์Šต๋‹ˆ๋‹ค. ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ์š”, ๊ทธ์ค‘์—์„œ๋„ ์ €๋Š” Spring Data JPA๋ฅผ ์ด์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Spring Data JPA๋ฅผ ์ด์šฉํ•˜๋ฉด Pageable ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€๋„ค์ด์…˜(pagination) ์ •๋ณด๋ฅผ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. JPA Query ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ Pageable์„ ๋„˜๊ฒจ์„œ DB์— ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ์•Œ์•„์„œ ์ž˜ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค :-)

Pageable

Pageable๋Š” Pagination ์š”์ฒญ ์ •๋ณด๋“ค์„ ๋‹ด๊ธฐ ์œ„ํ•œ ์ถ”์ƒ ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.

  • class QPageRequest : QueryDSL์„ ์œ„ํ•œ Pageable ๊ตฌํ˜„์ฒด
  • class PageRequest : ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ Pageable ๊ตฌํ˜„์ฒด
  • enum Unpaged : pagination ์ •๋ณด๊ฐ€ ์—†๋Š” ๊ฒƒ์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌํ˜„์ฒด

๋ณดํ†ต ์ด ์ค‘์—์„œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ธ PageRequest๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

Example

UserController์— user ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ดค์Šต๋‹ˆ๋‹ค. getPageRequest ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด PageRequest ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@RestController
@RequestMapping("api/v1/user")
class UserController(
    private val userApiService: UserApiService
) : BaseMobileApiController() {

    /**
     * user ์กฐํšŒ
     */
    @GetMapping
    suspend fun getUsers(
        principal: Principal,
        pageable: Pageable,
    ): ApiResponse<Page<UserRes>> {
        val res = userApiService.getUsers(principal, getPageRequest(pageable))
        return ApiResponse.ok(res)
    }
}


์œ„ user ์กฐํšŒ API๋ฅผ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

"content":[
{
    "content": [
        {"id": 1, "username": "User 0", "address": UK", "age": 20},
        ...,
        {"id": 5, "username": "User 4", "address": "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
}



https://velog.io/@chlee4858/Jpa-Pagination-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0
https://wonit.tistory.com/483

๋ฐ˜์‘ํ˜•