๋ธ๋ก๊ทธ๋ ์ปค๋ฎค๋ํฐ ๊ฒ์ํ์ฒ๋ผ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ์๋น์ค์์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ๋ด๋ ค์ฃผ๋ ๊ฒ์ ๋นํจ์จ์ ์ผ ๋ฟ๋ง ์๋๋ผ ์ฌ์ฉ์ ๊ฒฝํ๊น์ง ํด์น ์ ์๋ค.
์๋ฒ ์
์ฅ์์๋ ๊ณผ๋ํ ๋ถํ๊ฐ ๋ฐ์ํ๊ณ ํด๋ผ์ด์ธํธ ๋ธ๋ผ์ฐ์ ๋ ๋ถํ์ํ ๋คํธ์ํฌ ๋ญ๋น์ ํจ๊ป ๋ ๋๋ง ์๊ฐ ์ง์ฐ์ ๊ฒช๊ฒ ๋๋ค. ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ด ๋ฐ๋ก ํ์ด์ง ์ฒ๋ฆฌ(Pagination)์ด๋ค.
๋ฐฑ์๋์์ ๋ฐ์ดํฐ๋ฅผ ์ผ์ ๋จ์๋ก ๋๋์ด ์ ๋ฌํ๋ฉด ํด๋ผ์ด์ธํธ๋ ํ์ํ ํ์ด์ง๋ง ์์ฒญํ๊ณ ํจ์จ์ ์ผ๋ก ํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ํ์ํ ์ ์๋ค.
Spring Boot์์๋ Pageable์ ํ์ฉํด ๋งค์ฐ ๊ฐ๋จํ๊ฒ ํ์ด์ง ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํ ์ ์๋ค.
๋จผ์ ์ปจํธ๋กค๋ฌ์์ ํด๋ผ์ด์ธํธ์ ํ์ด์ง ์์ฒญ์ ๋ฐ๋๋ค.
@GetMapping
public PageResponse<PostListResponse> getAllPosts(
@PageableDefault(page = 0, size = 10) Pageable pageable) {
Page<PostListResponse> page = userPostService.getAllPosts(pageable)
.map(PostListResponse::from);
return PageResponse.from(page);
}
Spring Boot์์ ํ์ด์ง ์ฒ๋ฆฌ๋ฅผ ํ ๋ Pageable์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ผ๋ฉด ํด๋ผ์ด์ธํธ๊ฐ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ page, size, sort ๊ฐ์ ์๋์ผ๋ก ๋งคํํด์ค๋ค.
์๋ฅผ ๋ค์ด /posts?page=0&size=10 ์ด๋ผ๋ ์์ฒญ์ด ๋ค์ด์ค๋ฉด Spring์ ํด๋น ๊ฐ์ ์ฝ์ด Pageable ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ค๋ค. ํ์ง๋ง ํด๋ผ์ด์ธํธ๊ฐ ์๋ฌด๋ฐ ๊ฐ์ ์ ๋ฌํ์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํด ๊ธฐ๋ณธ๊ฐ์ ์ง์ ํด์ค ์ ์๋ ์ด๋
ธํ
์ด์
์ด @PageableDefault์ด๋ค.
@PageableDefault์๋ page(ํ์ด์ง ๋ฒํธ), size(ํ์ด์ง ํฌ๊ธฐ), sort(์ ๋ ฌ ํ๋), direction(์ ๋ ฌ ๋ฐฉํฅ)์ 4๊ฐ์ง ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌํ ์ ์๋ค.
์๋ต์ผ๋ก Page<T>๋ฅผ ๊ทธ๋๋ก ๋ฐํํ ์๋ ์์ง๋ง ๋ถํ์ํ ์ ๋ณด๋ฅผ ์ ๊ฑฐํ๊ณ ํ๋ก ํธ์๋์ ํ์ํ ๋ฐ์ดํฐ๋ง ๊น๋ํ๊ฒ ์ ๋ฌํ๊ธฐ ์ํด PageResponse<T>๋ผ๋ ๋ณ๋์ ์๋ต ๊ฐ์ฒด๋ฅผ ์ ์ํด ์ฌ์ฉํ์๋ค.
์ดํ์๋ ์ ๋ฌ๋ฐ์ Pageable ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์๋น์ค๋ฅผ ๊ตฌํํ๋ค.
public Page<PostListDto> getAllPosts(Pageable pageable) {
Page<Post> page = postRepository.findVisiblePosts(pageable);
return page.map(post -> PostListDto.of(post);
}
findVisiblePosts()๋ ๋ ํฌ์งํ ๋ฆฌ์ @Query๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ์์ฑํ ์ปค์คํ
JPA ์ฟผ๋ฆฌ ๋ฉ์๋์ด๋ค.
@Query("""
SELECT p FROM Post p
WHERE p.isPublic = true AND p.isDeleted = false
ORDER BY p.createdAt DESC
""")
Page<Post> findVisiblePosts(Pageable pageable);
JPA๋ Pageable ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ํ์ด์ง ์ฒ๋ฆฌ๋ฅผ ์๋์ผ๋ก ์ง์ํ๋ฉฐ ์ค์ ๋ก ์คํ๋๋ SLQ(PostgreSQL ๊ธฐ์ค)์ ๋ค์๊ณผ ๊ฐ๋ค.
select
p1_0.id,
p1_0.title,
p1_0.slug,
p1_0.content,
p1_0.is_public,
p1_0.is_deleted,
p1_0.created_at,
p1_0.updated_at
from
post p1_0
where
p1_0.is_public=true
and p1_0.is_deleted=false
order by
p1_0.created_at desc
fetch
first ? rows only
fetch first ? rows only ๊ตฌ๋ฌธ์ ๊ฒฝ์ฐ PostgreSQL์์ ์ฌ์ฉํ๋ ํ์ค SQL ํ์ด์ง ๋ฌธ๋ฒ์ผ๋ก MySQL์ LIMIT ? ๊ณผ ๋์ผํ ์ญํ ์ ํ๋ค. ์ฆ ์์์๋ถํฐ ?๊ฐ์ ํ๋ง ๊ฐ์ ธ์ค๋ผ๋ ์๋ฏธ์ด๋ค.
๋ํ ์ฒซ ํ์ด์ง๋ฅผ ์์ฒญํ๋ ๊ฒฝ์ฐ OFFSET์ ์๋ต๋์ด ์คํ๋์ง ์๋๋ค. JPA๋ ์ด๋ฌํ ํ์ด์ง ๊ตฌ๋ฌธ์ Pageable ๊ฐ์ฒด๋ฅผ ํตํด ์๋์ผ๋ก ์์ฑํด์ฃผ๊ธฐ ๋๋ฌธ์ SQL์ ์ง์ ์์ฑํ์ง ์๊ณ ๋ ํจ์จ์ ์ธ ํ์ด์ง ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํ ์ ์๋ค.
