-
Notifications
You must be signed in to change notification settings - Fork 0
오프셋 기반 페이지네이션 vs 커서 기반 페이지네이션
khw7385 edited this page Feb 24, 2025
·
1 revision
특정한 정렬 기준에 따라 + 지정된 갯수
의 데이터를 가져오는 것
서버의 처리에서 처리 방식은 두 가지고 존재한다.
- 오프셋 기반 페이지네이션(Offset-based Pagination)
- DB의 offset 쿼리를 사용하여 ‘페이지’단위로 구분하여 요청/응답
- 커서 기반 페이지네이션(Cursor-based Pagination)
- Cursor 개념을 사용하여 사용자에게 응답해준 마지막 item을 기준으로 다음 요청을 하는 것
- 클라이언트가 item(커서)와 함께 다음 item 들을 n 개 요청/응답하게 구현 기준으로 다음 n개 요청/응답
프론트 엔드 코드에서의 페이지네이션
- 페이지 버튼 형식, 페이지를 보여주고 사용자가 클릭하여 페이지를 이동하는 방식(1, 2, 3, …,)
- 무한 스크롤
간단하게 OFFSET 쿼리와 LIMIT 쿼리에 콤마를 붙여 ‘건너 뛸’ row 숫자를 지정하여 페이지네이션을 구현한다.(Mysql 에서)
SELECT *
FROM post
order by create_at desc limit [페이지 크기] offset [페이지 번호 * 페이지 크기];
limit 뒤: 가져올 데이터의 수
offset 뒤: 넘겨야 하는 데이터의 수
장점
- 직관적이고 구현하기 편하다 - JPA에서는 Pageable 을 이용하기 쉽게 구현(Page, Slice, Pagable)
- 유저가 특정 페이지를 선택하고 이동할 수 있다
- 전체 페이지의 개수를 알 수 있다.
단점
- 중복 데이터 발생
- 데이터를 offset 만큼 읽는데, offset이 많아질수록 성능이 느려진다.
커서(Cursor) 라는 개념은 offset 을 사용하지 않고 Cursor를 기준으로 다음 n 개의 데이터를 응답해주는 방식이다. 커서란 사용자에게 응답해준 마지막의 데이터의 식별자 값이 Cursor 가 된다.
SELECT *
FROM post
WHERE id <= {cursor} ORDER BY id DESC LIMIT {limit}
장점
- 오프셋을 사용하지 않기 때문에 성능 상 이점이 있다. → 테이블 풀 스캔을 하지 않아도 된다.
단점
- where 절에 여러 조건이 들어가면 성능이 offset 보다 안 좋을 수는 있다. → 무한 스크롤의 경우 정렬 기능을 잘 제공하지 않는다. 하지만, 유튜브에는 또 무한 스크롤도 정렬 기능이 있어서 더 알아봐야 한다.
- 커서는 반드시 유니크한 값을 가져야 한다.
- 페이징 버튼 형식으로 해야 한다면 오프셋 기반 페이지네이션을 해야 한다.
특징
- 첫 페이지 조회할 때와 두 번째 페이지부터 조회할 때 사용되는 쿼리가 달라 동적 쿼리가 필요하다. 첫 페이지를 조회할 때는 기준이 되는 id 값을 알 수 없기 때문이다.
- 마지막 페이지에서 스크롤을 한다면?
- 데이터는 존재하지 않기 때문에 아무 데이터도 응답하지 않는다.
- 다음 데이터가 존재하지 않는다는 필드를 추가해주면 좋다.
대부분의 RDBMS 는 WHERE에 OR 연산자 사용하면 인덱스를 제대로 활용하지 못한다.
오프셋 기반 페이지네이션을 사용해도 되는 경우
- 데이터의 변화가 거의 없다시피하여 중복 데이터가 노출될 염려가 없는 경우
- 일반 유저에게 노출되는 리스트가 아니라 중복 데이터가 노출되어도 크게 문제 되지 않는 경우
- 검색엔진이 인덱싱할 이유도, 유저가 마지막 페이지를 갈 이유도, 오래된 데이터의 링크가 공유될 이유도 없는 경우
- 애초에 row 수가 그렇게 많지 않아 특별히 퍼포먼스 걱정이 필요 없는 경우
나머니의 경우 커서 기반 페이지네이션을 사용하는 것이 좋다.