• ABOUT
  • POSTS
  • GUESTBOOK

ยฉ 2025 BlueCool12 All rights reserved.

2025.08.01Spring

๐Ÿ“„ Pageable๋กœ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ (+Spring Data JPA)

๋ธ”๋กœ๊ทธ๋‚˜ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œํŒ์ฒ˜๋Ÿผ ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ์„œ๋น„์Šค์—์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ๋‚ด๋ ค์ฃผ๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜๊นŒ์ง€ ํ•ด์น  ์ˆ˜ ์žˆ๋‹ค. 

์„œ๋ฒ„ ์ž…์žฅ์—์„œ๋Š” ๊ณผ๋„ํ•œ ๋ถ€ํ•˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ถˆํ•„์š”ํ•œ ๋„คํŠธ์›Œํฌ ๋‚ญ๋น„์™€ ํ•จ๊ป˜ ๋ Œ๋”๋ง ์‹œ๊ฐ„ ์ง€์—ฐ์„ ๊ฒช๊ฒŒ ๋œ๋‹ค. ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ(Pagination)์ด๋‹ค. 

๋ฐฑ์—”๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ผ์ • ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„์–ด ์ „๋‹ฌํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” ํ•„์š”ํ•œ ํŽ˜์ด์ง€๋งŒ ์š”์ฒญํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ํ™”๋ฉด์— ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค. 

Spring Boot์—์„œ๋Š” Pageable์„ ํ™œ์šฉํ•ด ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. 

๋จผ์ € ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ ํŽ˜์ด์ง• ์š”์ฒญ์„ ๋ฐ›๋Š”๋‹ค. 

java
@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 ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์„œ๋น„์Šค๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. 
 

java
public Page<PostListDto> getAllPosts(Pageable pageable) {
  Page<Post> page = postRepository.findVisiblePosts(pageable);
  return page.map(post -> PostListDto.of(post);
}


findVisiblePosts()๋Š” ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— @Query๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ์ž‘์„ฑํ•œ ์ปค์Šคํ…€ JPA ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์ด๋‹ค. 
 

java
@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 ๊ธฐ์ค€)์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. 
 

plaintext
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์„ ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ํšจ์œจ์ ์ธ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. 
 

์ด์ „ ๊ธ€
๐Ÿ—ƒ๏ธ Redux ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ - Store, Action, Reducer, Dispatch
๋‹ค์Œ ๊ธ€
๐Ÿงฑ ์Šคํƒ(Stack)๊ณผ ํ(Queue) ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ํ™œ์šฉ ์˜ˆ์‹œ
์žฅ์‹์šฉ ๋กœ๊ณ