[Querydsl] Pagination ์„ฑ๋Šฅ ๊ฐœ์„  part1.PageableExecutionUtils

2023. 2. 21. 11:54ใ†๐ŸŒฟ Spring

๋ชฉ์ฐจ

  • ๊ธฐ์กด : QueryDSL์˜ ํŽ˜์ด์ง•
  • ๊ฐœ์„  : PageableExecutionUtils : new PageImpl()์˜ count ์ฟผ๋ฆฌ ๊ฐœ์„ 
  • Test Case
    1. Test case 1. ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ 20 / ์ด content 8๊ฐœ / ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€ ํ˜ธ์ถœ
    2. Test case 2. ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ 5 / ์ด content 8๊ฐœ / ๋‘๋ฒˆ์งธ ํŽ˜์ด์ง€ ํ˜ธ์ถœ
    3. Test case 3. ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ 3 / ์ด content 8๊ฐœ / ๋‘๋ฒˆ์งธ ํŽ˜์ด์ง€ ํ˜ธ์ถœ (์ด 3๊ฐœ์˜ ํŽ˜์ด์ง€ ์กด์žฌ)
  • ๊ฒฐ๋ก 

 

(๊ธฐ์กด) QueryDSL์˜ ํŽ˜์ด์ง•

๋ณดํ†ต QueryDsl (์ดํ•˜ qdsl)์—์„œ ํŽ˜์ด์ง• ํ•  ๋• new PageImpl()์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฆ„๋Œ€๋กœ Page ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด์ด๋ฉฐ, ๋™์‹œ์— Chunk ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด์ž…๋‹ˆ๋‹ค. (์—ฌ๊ธฐ์„  ์ค‘์š”ํ•œ ๊ฒŒ ์•„๋‹ˆ๋‹ˆ ํŒจ์Šค)

- content : ํŽ˜์ด์ง•์„ ์ ์šฉํ•œ(e.g. offset, limit) ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ
- total : ํŽ˜์ด์ง•์„ ์ ์šฉํ•˜์ง€ ์•Š์€ ์ „์ฒด ๊ฒฐ๊ณผ์˜ ํฌ๊ธฐ

 

content ์ธ์ž

content ์ธ์ž๋Š” JpaQuery์˜ fetch() ํ˜น์€ fetchResults() ๊ฒฐ๊ณผ ๊ฐ’์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. fetchResults()๋Š” Deprecated ๋์œผ๋‹ˆ fetch()๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜ ์™ผ์ชฝ์€ content ์ธ์ž์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

.offset() .limit() ์„ ์‚ฌ์šฉํ•˜์—ฌ ํŽ˜์ด์ง• ์ ์šฉํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

total ์ธ์ž

์˜ค๋ฅธ์ชฝ์€ total ์ธ์ž์— ๋“ค์–ด๊ฐˆ long ํƒ€์ž…์˜ count์ž…๋‹ˆ๋‹ค.

์œ„์˜ content ์ฟผ๋ฆฌ์™€ ๋™์ผํ•œ where ์ ˆ์„ ์ ์šฉํ•˜์ง€๋งŒ, offset, limit์„ ์ ์šฉํ•˜์ง€ ์•Š์€ ๊ฒฐ๊ณผ์˜ ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๋ถˆํ•„์š”ํ•œ join clause๋„ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

new PageImpl() ์ •๋ฆฌ

new PageImpl()์€ ์ด ๋‘ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ํŽ˜์ด์ง•์„ ์ ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


 

(๊ฐœ์„ ) PageableExecutionUtils : new PageImpl()์˜ count ์ฟผ๋ฆฌ ๊ฐœ์„ 

PageableExecutionUtils๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด PageImp์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ณด๋‹ค ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. PageableExecutionUtils๋Š” ์–ด๋–ค ํŠน์ง•์„ ๊ฐ€์ง€๋Š”์ง€, ์–ด๋–ค ์‹์œผ๋กœ ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๊ณต์‹๋ฌธ์„œ์—์„œ PageableExecutionUtils ์„ค๋ช…์ž…๋‹ˆ๋‹ค.

from Docs

 

ํ•˜์ด๋ผ์ดํŠธ ๋ฐ‘์ค„์„ ์˜์—ญํ•˜๋ฉด "๋ฐ์ดํ„ฐ ์ฟผ๋ฆฌ๊ฐ€ count ์ฟผ๋ฆฌ๋ณด๋‹ค ๋น„์šฉ์ด ๋œ ๋“ ๋‹ค๊ณ  ๊ฐ€์ •"์ด๋ผ ํ•˜๋„ค์š”.

๋œป์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์€๋ฐ, ์šฐ๋ฆฌ์˜ ์ตœ๊ณ  ์„ฑ๋Šฅ ๋ฒˆ์—ญ๊ธฐ(์•„๋‹˜)์—๊ฒŒ ๋ฌผ์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์˜์—ญ๊ณผ ํฌ๊ฒŒ ์ฐจ์ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค, ์ด๋Ÿฐ ๋‚˜ chat gpt์—๊ฒŒ ๋น„๋นŒ์ˆ˜ ์žˆ์„์ง€๋„..?

 

์ •๋ฆฌํ•˜์ž๋ฉด, PageableExecutionUtils์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹จ์ˆœ new PageImpl()์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋ณด๋‹ค ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

PageableExecutionUtils ํด๋ž˜์Šค๋Š” ๋‚ด๋ถ€์— getPage()๋ผ๋Š” ๋‹จ ํ•˜๋‚˜์˜ (์ •์ ) ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

 

PageableExecutionUtils.getPage()

public static <T> Page<T> getPage(List<T> content, Pageable pageable, LongSupplier totalSupplier) {

    Assert.notNull(content, "Content must not be null");
    Assert.notNull(pageable, "Pageable must not be null");
    Assert.notNull(totalSupplier, "TotalSupplier must not be null");

    if (pageable.isUnpaged() || pageable.getOffset() == 0) {

        if (pageable.isUnpaged() || pageable.getPageSize() > content.size()) {
            return new PageImpl<>(content, pageable, content.size());
        }

        return new PageImpl<>(content, pageable, totalSupplier.getAsLong());
    }

    if (content.size() != 0 && pageable.getPageSize() > content.size()) {
        return new PageImpl<>(content, pageable, pageable.getOffset() + content.size());
    }

    return new PageImpl<>(content, pageable, totalSupplier.getAsLong());
}
}

 

์•„๋ž˜ ํ•„๊ธฐ๋ฅผ ๋ณด๋ฉด ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ• ์ง€๋„? ์•„๋‹์ง€๋„?

 

 

์œ„ ํ•„๊ธฐ๋ฅผ ์ •๋ฆฌํ•˜์ž๋ฉด

1. ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€์ด๋ฉด์„œ content ํฌ๊ธฐ๊ฐ€ ํ•œ ํŽ˜์ด์ง€์˜ ์‚ฌ์ด์ฆˆ๋ณด๋‹ค ์ž‘์„ ๋•Œ (ex, content:3๊ฐœ, page ํฌ๊ธฐ: 10)

2. ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€์ผ ๋•Œ (getOffset์ด 0์ด ์•„๋‹ˆ๋ฉด์„œ, content ํฌ๊ธฐ๊ฐ€ ํ•œ ํŽ˜์ด์ง€์˜ ์‚ฌ์ด์ฆˆ๋ณด๋‹ค ์ž‘์„ ๋•Œ)

totalSupplier ๋Œ€์‹  content์˜ size์™€ offset ๊ฐ’์œผ๋กœ total ๊ฐ’์„ ๋Œ€์‹ ํ•ฉ๋‹ˆ๋‹ค.

 

PageableExecutionUtils.getPage() ๋‚ด๋ถ€์—์„  ๊ฒฐ๊ตญ new PageImpl()์„ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ new PageImpl()์„ ํ•œ๋ฒˆ ๋” ์ถ”์ƒํ™”ํ–ˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ธฐ์กด new PageImpl()์™€ getPage()์˜ ์ฐจ์ด๋Š” ์„ธ ๋ฒˆ์งธ ์ธ์ž๋งŒ LongSupplier totalSupplier ๋กœ ๋ณ€๊ฒฝ๋๋‹ค๋Š” ๊ฒƒ์ด์ฃ .

long total ์ธ primitive ์ธ์ž๋ฅผ LongSupplier totalSupplier ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋Œ€์‹ ํ•ฉ๋‹ˆ๋‹ค.

์›์‹œํ˜• ํƒ€์ž… ๋Œ€์‹  ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ›์„ ๋•Œ ์ƒ๊ธฐ๋Š” ์ด์ ์€ ๋ฌด์—‡์ผ๊นŒ์š”?

 

๊ฒฐ๊ณผ๋ก ์ ์ธ ์–˜๊ธฐ์ง€๋งŒ ํ˜„์žฌ ์ƒํ™ฉ์—์„ , ํ˜ธ์ถœ ์‹œ์ ์„ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ ์‹œ์ ์ด์š”? count ์ฟผ๋ฆฌ์˜ ํ˜ธ์ถœ ์‹œ์ ์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด pageImpl()์—์„  count ๊ฐ’์„ ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋„ฃ๊ธฐ ์œ„ํ•ด count ์ฟผ๋ฆฌ๋ฅผ ํ•„์ˆ˜๋กœ ํ˜ธ์ถœํ–ˆ์ง€๋งŒ PageableExecutionUtils.getPage() ์—์„  count ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์ธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋…ธ๋ž€์ƒ‰ ํ•˜์ด๋ผ์ดํŠธ๋ฅผ ๋ณด๋ฉด, new PageImpl()์˜ ์„ธ๋ฒˆ์งธ ์ธ์ž๋กœ totalSupplier ๋Œ€์‹  content.size() , pageable.getOffset() ๊ฐ’์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ฆ‰ count ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์•„ ๋ถˆํ•„์š”ํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด pageImpl์—์„œ ๋‘ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋˜ ๊ฒƒ์— ๋น„ํ•ด ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์ด๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์ƒ˜ํ”Œ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

@RequiredArgsConstructor
public class BookmarkRepositoryImpl implements BookmarkRepositoryCustom {

    private final JPAQueryFactory query;
    private final QFolder qFolder = QFolder.folder;
    private final QBookmark qBookmark = QBookmark.bookmark;

    @Override
    public Page<BookmarkResponse> findBookmarksWithFolderId(Long userId, Pageable pageable) {

        List<BookmarkResponse> fetch = query.select(new QBookmarkResponse(qBookmark, qFolder.id))
            .from(qBookmark)
            .where(condition(userId))
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .fetch();

        JPAQuery<Long> count = query.select(qBookmark.count())
            .from(qBookmark)
            .where(condition(userId));

        return PageableExecutionUtils.getPage(fetch, pageable, count::fetchOne);  // ์—ฌ๊ธฐ
    }
}

 

PageableExecutionUtils.getPage()์˜ ์„ธ ๋ฒˆ์งธ ์ธ์ž์—์„œ, () -> count.fetchOne() ๋žŒ๋‹ค์‹์„ ์ธ์ž๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.

์ฆ‰ getPage() ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ํ•ด๋‹น ๋žŒ๋‹ค์‹์„ ํ˜ธ์ถœํ•˜๊ธฐ ์ „๊นŒ์ง€ count ์ฟผ๋ฆฌ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

์œ„์—์„œ totalSupplier ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š” ์กฐ๊ฑด์„ ๋‹ค์‹œ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€์ด๋ฉด์„œ content ํฌ๊ธฐ๊ฐ€ ํ•œ ํŽ˜์ด์ง€์˜ ์‚ฌ์ด์ฆˆ๋ณด๋‹ค ์ž‘์„ ๋•Œ (ex, content:3๊ฐœ, page ํฌ๊ธฐ: 10)

2. ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€์ผ ๋•Œ (getOffset์ด 0์ด ์•„๋‹ˆ๋ฉด์„œ, content ํฌ๊ธฐ๊ฐ€ ํ•œ ํŽ˜์ด์ง€์˜ ์‚ฌ์ด์ฆˆ๋ณด๋‹ค ์ž‘์„ ๋•Œ)

 

test case ๋งˆ๋‹ค API๋ฅผ ํ˜ธ์ถœํ•ด ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


 

Test Case

 

Test case 1. ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ 20 / ์ด content 8๊ฐœ / ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€ ํ˜ธ์ถœ 

 

API ํ˜ธ์ถœ 

Debugger

์นผ๊ฐ™์ด ์กฐ๊ฑด๋ฌธ์— ๊ฑธ๋ฆฌ๋ฉด์„œ content.size()๋ฅผ ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋ฐ›๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ฒฐ๊ณผ

{
    "content": [
        {
            "id": 1,
            "url": "www.google.com",
            "name": "๋ฐ”๋“œ ๋–ก๋ฝ ใ… ",
            "folderId": 3
        },
        
      ...
      
        {
            "id": 17,
            "url": "chat.openai.com",
            "name": "์ง€ํ”ผํ‹ฐ์•ผ ๊ธ€์ข€ ์จ๋‹ค์˜ค",
            "folderId": 1
        },
        {
            "id": 19,
            "url": "www.google.com",
            "name": "๋ฐฑ์—”๋“œ",
            "folderId": 1
        }
    ],
    "pageable": {
        "sort": {
            "empty": true,
            "unsorted": true,
            "sorted": false
        },
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 20,
        "paged": true,
        "unpaged": false
    },
    "last": true,
    "totalPages": 1,
    "totalElements": 8,
    "first": true,
    "size": 20,
    "number": 0,
    "sort": {
        "empty": true,
        "unsorted": true,
        "sorted": false
    },
    "numberOfElements": 8,
    "empty": false
}

 

์‹คํ–‰๋œ ์ฟผ๋ฆฌ

์กฐํšŒ ์ฟผ๋ฆฌ๋งŒ ์‹คํ–‰๋˜๊ณ , count ์ฟผ๋ฆฌ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Test case 2. ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ 5 / ์ด content 8๊ฐœ / ๋‘ ๋ฒˆ์งธ ํŽ˜์ด์ง€ ํ˜ธ์ถœ 

API ํ˜ธ์ถœ

 

Debugger

์กฐ๊ฑด๋ฌธ์— ๊ฑธ๋ฆฌ๋ฉด์„œ offset ํฌ๊ธฐ์™€ content ์‚ฌ์ด์ฆˆ๋ฅผ ๋”ํ•˜์—ฌ totalCount๋ฅผ ๋Œ€์‹ ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

์‹คํ–‰๋œ ์ฟผ๋ฆฌ

Test case1๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์กฐํšŒ ์ฟผ๋ฆฌ๋งŒ ์‹คํ–‰๋˜๊ณ , count ์ฟผ๋ฆฌ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

 

Test case 3.  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ 3 / ์ด content 8๊ฐœ / ๋‘ ๋ฒˆ์งธ ํŽ˜์ด์ง€ ํ˜ธ์ถœ  (์ด 3๊ฐœ์˜ ํŽ˜์ด์ง€ ์กด์žฌ)

๋งจ ์•ž/๋’ค ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•œ case 1, 2์™€ ๋‹ฌ๋ฆฌ Test Case3๋Š” ์ค‘๊ฐ„ ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

 

API ํ˜ธ์ถœ

Debugger

์ด์ „ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์™€ ๋‹ฌ๋ฆฌ totalSupplier.getAsLong()์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

์ด์ „์—๋Š” count ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์€ ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, ์ด๋ฒˆ ํ…Œ์ŠคํŠธ์ผ€์ด์Šค์—์„œ๋Š” count ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋  ๊ฒƒ์„ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์‹คํ–‰๋œ ์ฟผ๋ฆฌ

์งœ์ž”

์กฐํšŒ ์ฟผ๋ฆฌ์™€ count ์ฟผ๋ฆฌ ๋ชจ๋‘ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Testcase 4. PageableExecutionUtils.getPage() ๋Œ€์‹  new PageImpl() ๋ฐ”๋กœ ์‚ฌ์šฉ

pageImpl์„ ๋ฐ”๋กœ ํ˜ธ์ถœํ•  ๋• ์–ด๋–จ๊นŒ์š”?

์ฒซ ํŽ˜์ด์ง€์™€ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ–ˆ์Œ์—๋„ ๋‘ ๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ชจ๋‘ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์ฆ‰ PageableExecutionUtils์„ ์‚ฌ์šฉํ•ด ์ค‘๊ฐ„ ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

 


 

๊ฒฐ๋ก 

์ด๋กœ์จ PageableExecutionUtils.getPage()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ count ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ผ€์ด์Šค๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€๋ฅผ ์กฐํšŒํ•  ๋•Œ๋งŒํผ์€ ๋ถˆํ•„์š”ํ•œ count ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๊ฒ ๋„ค์š”.

 

์‚ฌ์šฉ์ž๊ฐ€ ์ฒซ ํŽ˜์ด์ง€์—์„œ ๋จธ๋ฌด๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€ ์„œ๋น„์Šค๋ผ๋ฉด ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ์ž˜ ์ด๋ฃจ์–ด์งˆ ๊ฒƒ์ด๋ผ ์˜ˆ์ƒํ•ด ๋ด…๋‹ˆ๋‹ค.

์ถ”๊ฐ€๋กœ ์ œ๊ฐ€ ๋งŒ๋“ค๊ณ ์ž ํ•˜๋Š” ์„œ๋น„์Šค๋Š” ํŽ˜์ด์ง•์„ ๋ชฉ์ฐจํ˜•์œผ๋กœ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ  ์Šคํฌ๋กค ํ˜•์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” noOffset์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€ ์„ฑ๋Šฅ๊ฐœ์„ ์„ ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ๋‹ค์Œ ํฌ์ŠคํŠธ์—์„œ ๋” ๋‹ค๋ค„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์•ˆ๋‡ฝ!