Pagination #200
ratcomp9992
started this conversation in
General
Pagination
#200
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
개요
프로젝트를 진행할 때 다른 팀원의 페이징 관련 코드를 보면서 '이런게 있구나' 정도만 하고 넘어갔었는데, 기회가 생긴 김에 페이징에 대해 알아보고자 한다.
목차
개념
MySQL에서의 페이징
JPA에서의 페이징
개념
게시물이 1000개 존재한다고 가정한다.
특정 클라이언트를 통해 게시물 목록 조회 API를 호출할 때마다 1000개를 모두 전달해주면 굉장히 오래 걸릴 것이다.
그래서 DB나 애플리케이션 서버에서 게시글을 페이지로 구분해 전달한다.
이렇게 데이터를 정렬하고, 페이지 크기에 따라 나눠서 전달하는 기법을 Pagination 이라고 하고,
페이지를 나누는 행동이나 과정을 Paging이라고 한다.
MySQL에서의 페이징
LIMIT
LIMIT은 결과에서 몇 개의 row를 반환할 지 제한하는 구문이다.
SELECT 명령의 마지막에 지정하는 것으로 WHERE이나 ORDER BY 구문의 뒤에 위치한다.
select 컬럼명 from 테이블명 limit 갯수;
select * from table_name limit 10;
= 처음부터 10개 출력
OFFSET
OFFSET은 LIMIT 구문에서의 시작 위치를 지정할 수 있게 해준다.
OFFSET 값은 0부터 시작한다.
select 컬럼명 from 테이블명 limit 갯수 OFFSET 시작 인덱스;
select * from member limit 3 offset 2;
* OFFSET은 생략하여 사용할 수 있다.
select * from member limit 3, 2;
= 이 쿼리는 위의 쿼리와 비슷해보이지만, 다른 결과를 반환한다.
select 컬럼명 from 테이블명 limit 시작 인덱스, 갯수;
OFFSET 문제점
OFFSET 크기에 따른 성능 저하
CREATE 시 데이터 중복 출력
![image](https://private-user-images.githubusercontent.com/141790867/342968699-707c7c47-fa03-422f-9bab-fa2f960430fe.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE3MDk4MjgsIm5iZiI6MTcyMTcwOTUyOCwicGF0aCI6Ii8xNDE3OTA4NjcvMzQyOTY4Njk5LTcwN2M3YzQ3LWZhMDMtNDIyZi05YmFiLWZhMmY5NjA0MzBmZS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzIzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcyM1QwNDM4NDhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0wMWMxZDIxOGQ3OGY2MmFiMDE0MmU0ODNiNzJhMDFhNzc0N2Q4NjNhZWFmY2JhNTJkNmJkNzc0MzQ4ZjE5N2I2JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.sBHqWGJAfSutKhcSuhaeTkJcJ6PLB6TIf1r2OOAHxH8)
![image](https://private-user-images.githubusercontent.com/141790867/342968719-ab70c6d5-5edc-44df-b313-ca5541734b72.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE3MDk4MjgsIm5iZiI6MTcyMTcwOTUyOCwicGF0aCI6Ii8xNDE3OTA4NjcvMzQyOTY4NzE5LWFiNzBjNmQ1LTVlZGMtNDRkZi1iMzEzLWNhNTU0MTczNGI3Mi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzIzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcyM1QwNDM4NDhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1jMmMyOTU1MWQ2YjNhMGQ4N2RlMDVhYTk3NmFiY2U3MGFiZjJkY2U1OTdmYzA0OGZjYmNmZTliN2E2NTZkYmU0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.wbjr1bePwaFThUWImbnhXwRtJXaqayDayV1EJWjekmY)
2페이지로 접속함과 동시에 다른 유저가 새 데이터 "바, 사"를 등록했다면?
DELETE 시 데이터 누락
![image](https://private-user-images.githubusercontent.com/141790867/342969222-237e2794-18e2-4f1d-bafc-a24d9d2b36b5.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE3MDk4MjgsIm5iZiI6MTcyMTcwOTUyOCwicGF0aCI6Ii8xNDE3OTA4NjcvMzQyOTY5MjIyLTIzN2UyNzk0LTE4ZTItNGYxZC1iYWZjLWEyNGQ5ZDJiMzZiNS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzIzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcyM1QwNDM4NDhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT05MTNlYTdhNDBkY2U5ODg3Y2Y2MGEwNzYyMWViMGY0MzBkZjU3NzM3ZjFiZTZiMTIyMmE1YWEyOTgxOTlmYmEwJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.19c4z7qAgO7IHEVLudK6txKBtk-lhZq1nH1SsWadBqE)
2페이지로 접속함과 동시에 다른 유저가 "가, 나"를 삭제했다면?
OFFSET 문제점 해결방안
NoOffset
기존 OFFSET 페이징 방식이 페이지 번호와 사이즈를 기반으로 한다면,
NoOffset은 페이지 번호가 없는 더보기 방식을 사용한다.
NoOffset 방식은 조회 시작 부분을 인덱스로 빠르게 찾아, 매번 첫 페이지만 읽도록 하기 때문에 빠르다.
직전 조회 결과의 마지막 ID를 입력으로 받아, 이전 페이지 전체를 건너 뛸 수 있게 되는 것이다.
커버링 인덱스
서브 쿼리를 통해 클러스터드 인덱스가 걸려있는 id 컬럼만으로 OFFSET, LIMIT구문을 먼저 실행한다.
JPA에서의 페이징
Pageable
Pageable은 Spring에서 제공하는 페이징 요청을 정의하는 인터페이스로, Page와 Slice의 요청을 생성하는 데에 사용된다.
Slice
페이징된 결과에 대한 데이터를 담을 수 있는 객체이다.
Page
Slice를 상속 받아 사용하며, 페이징된 결과에 대한 데이터를 담을 수 있는 객체이다.
Slice를 통해 얻을 수 있는 정보 이외에, 총 데이터나 요소의 수에 대한 정보도 얻을 수 있다.
![image](https://private-user-images.githubusercontent.com/141790867/342948098-f222d710-efc7-45a0-8a74-45c1d5d6b259.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE3MDk4MjgsIm5iZiI6MTcyMTcwOTUyOCwicGF0aCI6Ii8xNDE3OTA4NjcvMzQyOTQ4MDk4LWYyMjJkNzEwLWVmYzctNDVhMC04YTc0LTQ1YzFkNWQ2YjI1OS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzIzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcyM1QwNDM4NDhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT00ZTE3ZWI0NTU0MWM2MmQ1NDU3OWJmMGY3OWRiMDA2MjZhZWQyZDc0YjM5YzYxYTRhMDU3NjRlMzcxYzdkZGM3JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.2tq1Plm168KO2WmIHU-4QDU0gnZ5UFQQRYIWELUC_WI)
Page vs Slice
Beta Was this translation helpful? Give feedback.
All reactions