Spring Data JPA์์๋ Pagination์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋๋ก Pageable ๊ฐ์ฒด๋ฅผ ์ ๊ณตํ๋ค.
์คํ์ ๊ธฐ๋ฐ Pagenation
DB์ offset์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ‘ํ์ด์ง’ ๋จ์๋ก ๊ตฌ๋ถํ์ฌ ์์ฒญ/์๋ต ํ๋ค.
controller
/**
* ๊ฒ์๋ฌผ page ์กฐํ
*
* @param pageable
* @return Page<PostDto>
*/
@GetMapping(produces = APPLICATION_JSON_VALUE)
public ApiResponse<Page<PostDTO.Response>> getPosts(@PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
Page<PostDTO.Response> pages = postService.findAll(pageable);
return ApiResponse.ok(pages);
}
service
public Page<PostDTO.Response> findAll(Pageable pageable) {
return postRepository.findAll(pageable)
.map(postConverter::convertResponseOnlyPostDto);
}
repository Page<T> findAll(Pageable pageable) ๋ฉ์๋ SpringDataJPA์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํด ์ฃผ๋ CRUD์ด๋ค.
ํด๋ฆฌ๊ฐ ์ด๋ป๊ฒ ๋๊ฐ๋ ์ง ํ์ธํด๋ณด์
@Test
@DisplayName("pageNation ์ฟผ๋ฆฌ ํ์ธ")
public void findAll(){
Page<Post> pages = postRepository.findAll(PageRequest.of(0,10)); // page : 0 , size : 10
}
MySQL ์์๋ผ๋ฉด ๊ฐ๋จํ๊ฒ OFFSET ์ฟผ๋ฆฌ์ LIMIT ์ฟผ๋ฆฌ์ ์ฝค๋ง๋ฅผ ๋ถ์ฌ '๊ฑด๋ ๋ธ' row ์ซ์๋ฅผ ์ง์ ํ์ฌ ํ์ด์ง๋ค์ด์ ์ ๊ตฌํํ๋ค.
SELECT id FROM products ORDER BY id LIMIT (one_size *(page-1)), one_size;
-
SELECT * FROM products LIMIT ์ซ์ OFFSET ํ์ด์ง ๋๋ฒ;
OFFSET ํค์๋๋ฅผ ํ์ฉํ๋ ๋ฐฉ์. ๊ฒฐ๊ณผ์ ์ฑ๋ฅ์ ๋์ผํ๋ค.
Pageable์ ์ฌ์ฉํ์ง ์๊ณ ์ฟผ๋ฆฌ๋ฅผ ์ง์ ์์ฑํด ๋ณด๋ ค๊ณ ๋ ํ์์ผ๋ JPQL๋ limit ํค์๋๋ฅผ ์ง์ํ์ง ์๋๋ค๊ณ ํ๋ค. JPA์์ limit์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ๋ฌด์กฐ๊ฑด pagenation๋ฅผ ํ๊ฑฐ๋ ์๋๋ฉด ์ฟผ๋ฆฌ๋ก ์์ฑํ๊ณ ์ถ๋ค๋ฉด NativeQuery๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ QueryDSL์ ์ฌ์ฉํด์ผํ ๊ฒ ๊ฐ๋ค.
PageRequest
PageRequest์ ์ํด Pageable์ ํ์ด์ง ์ ๋ณด๊ฐ ๋ด๊ฒจ ๊ฐ์ฒดํ ๋๋ค.
- of(int page, int size) : 0๋ถํฐ ์์ํ๋ ํ์ด์ง ๋ฒํธ์ ๊ฐ์. ์ ๋ ฌ์ด ์ง์ ๋์ง ์์
- of(int page, int size, Sort sort) : ํ์ด์ง ๋ฒํธ์ ๊ฐ์, ์ ๋ ฌ ๊ด๋ จ ์ ๋ณด
- of(int page int size, Sort sort, Direction direction, String ... props) : 0๋ถํฐ ์์ํ๋ ํ์ด์ง ๋ฒํธ์ ๊ฐ์, ์ ๋ ฌ์ ๋ฐฉํฅ๊ณผ ์ ๋ ฌ ๊ธฐ์ค ํ๋๋ค
@PageableDefault
spring mvc์ ์ํด ์ปจํธ๋กค๋ฌ์์ Pageable์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ์ ์๋ค. ์คํ๋ง ๋ฐ์ดํฐ๋ pageable์ PageRequest ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํด์ค๋ค.
→ ์ด๋ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด page(0๋ถํฐ ์์),size,sort๋ฅผ ๋ฐ์ ์ ์๋ค.
์คํ๋ง ๋ถํธ์์ ๊ธฐ๋ณธ์ผ๋ก defualt size 20, max page size 2000์ผ๋ก ๋ฑ๋ก๋์ด ์๋ค.
@PageableDefault ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ๊ฐ๋ณ ์ค์ ์ด ๊ฐ๋ฅํ๋ค. ๊ธฐ๋ณธ defult ๊ฐ์ด ์๋๋ผ๋ ๋ช ์์ ์ผ๋ก ์ ์ธํด ์ฃผ๋ ๊ฒ์ด ์ข๋ค.
offset ์ฟผ๋ฆฌ์ ํผํฌ๋จผ์ค ์ด์
๊ทน๋จ์ ์ผ๋ก 10์ต๋ฒ์งธ ํ์ด์ง์ ์๋ ๊ฐ์ ์ฐพ๊ณ ์ถ๋ค๋ฉด offset์ ๋งค์ฐ ํฐ ์ซ์๊ฐ ๋ค์ด๊ฐ๋ค. ์ ๋ ฌ ๊ธฐ์ค ํด๋น row๊ฐ ๋ช๋ฒ์งธ ์์์ธ์ง ์์ง ๋ชปํ๋ฏ๋ก ์ง์ ๋ offset๊น์ง ๋ชจ๋ ๋ง๋ค์ด ๋์ ํ ์ง์ ๋ ๊ฐฏ์๋ฅผ ์ํํ์ฌ ์๋ผ๋ ๋ฐฉ์์ด๋ค. ๋๋ฌธ์ ํผํฌ๋จผ์๊ฐ ์ด์ ๋น๋กํ์ฌ ๋จ์ด์ง๊ฒ ๋๋ค.
Faster Pagination in Mysql – Why Order By With Limit and Offset is Slow?
Why Order By With Limit and Offset is Slow - Faster Pagination in Mysql
Paging using LIMIT and OFFSET clauses in MySQL can be very slow. In this article we describe the seek method that allows a faster, more stable paging performance.
www.eversql.com
์๋ชป๋ ์ ๋ณด๊ฐ ์๋ค๋ฉด ๋๊ธ์ ํตํด ์๋ ค์ฃผ์ธ์. ๊ฐ์ฌํฉ๋๋ค.
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] Filter์ Interceptor ์ฐจ์ด (2) | 2023.04.22 |
---|---|
[JPA] ์ปค์ ๊ธฐ๋ฐ pagenation ๊ตฌํํ๊ธฐ (8) | 2023.03.01 |
[Spring] Spring MVC (0) | 2023.02.18 |
[Spring] Request ์ด๋ ธํ ์ด์ (parameter mapping) (2) | 2022.12.01 |
[Java] List ์ ํจ์ฑ ๊ฒ์ฌ (1) | 2022.12.01 |
๋๊ธ