Django Pagination 종류, 차이점

런던행·2021년 5월 21일
0

Django 업그레이드

목록 보기
16/17

이 글에서는 기본적인 페이지네이션 종류와 차이점, 그리고 실무 경험으로 바탕으로 각 페이지네이션 적용 방법, CursorPagination에서 오해 할 수 있는 깊이있게 다루고자 한다.

장고 rest-framework에서 기본적으로 제공하는 페이지네이션은 아래와 같다.
(https://www.django-rest-framework.org/api-guide/pagination/#pagination)

  • PageNumberPagination
  • LimitOffsetPagination
  • CursorPagination

PageNumberPagination

요청 시, 원하는 페이지(page) 번호를 정해서 가져오는 방법이다.

Request:

GET https://api.example.org/accounts/?page=4

Response:

HTTP 200 OK
{
    "count": 1023
    "next": "https://api.example.org/accounts/?page=5",
    "previous": "https://api.example.org/accounts/?page=3",
    "results": [
       …
    ]
}

LimitOffsetPagination

요청시, 원하는 지점(offset)과 그 지점으로 부터 데이터 갯수(limit)를 정해서 가져오는 방법이다.

Request:

GET https://api.example.org/accounts/?limit=100&offset=400

Response:

HTTP 200 OK
{
    "count": 1023
    "next": "https://api.example.org/accounts/?limit=100&offset=500",
    "previous": "https://api.example.org/accounts/?limit=100&offset=300",
    "results": [
       …
    ]
}

CursorPagination

요청 했던 데이터 기준으로 앞, 뒤로만 이동할 때 사용한다.

Request:

GET https://api.example.org/accounts/?cursor=bz0xJnI9MQ

Response:

HTTP 200 OK
{
    "next": "bz0xJnI9MQ",
    "previous": null,
    "results": [
       …
    ]
}

CursorPagination 왜 사용 하는가?

CursorPagination 이외에 위에 언급된 다른 페이지네이션과 응답값을 확인해보면 CursorPagination에 없는 키 값이 존재 하는데 "count" 값이다.
테이블에 데이터가 누적이 될 수록 전체 목록 조회 시, "count" 의 계산 시간이 커지기 시작한다. 내부적으로 전체 목록 갯수를 구하는 페이지네이션은 점차 느려지게 되기에 그런 경우에 한 에서는 CursorPagination 좋은 대안이 될 수 있고, 바꾸는 작업도 했었다.

CursorPagination 실행 쿼리 분석

첫번재 호출

SELECT ...
FROM `...`
WHERE (...
       AND `employments_employment`.`id` < 1257)
ORDER BY `employments_employment`.`id` DESC
LIMIT 2

다음 페이지 호출

SELECT ...
FROM `...`
WHERE (...
       AND `employments_employment`.`id` < 1255)
ORDER BY `employments_employment`.`id` DESC
LIMIT 2

CursorPagination는 정렬 key값을 기준으로 해서 비교연산(employments_employment.id < 1257)를 활용하여 쿼리를 생성하고 있다. 비교 연산으로 scope를 줄이고 limit로 데이터 갯수를 제한하고 있다.
비교 연산 시, 문제가 될 수 있는 부분은 위의 예제는 정렬 키 값이 'id'라 유니크 하지만 유니크하지 않는 키 값으로 비교 시, 중복 데이터가 다음 요청에서 누락이 될 수 있다고 생각 할 수 있다. 그러나 키 값이 중복이라도 그 부분까지 내부적으로 처리해서 쿼리를 만들고 있는게 확인이 되었다.

WHERE (...
       AND `employments_employment`.`name` < 'bbb')
ORDER BY `employments_employment`.`name` ASC
LIMIT 2
OFFSET 1

필드가 name인 경우 중복으로 저장 할 수 있다. 이 때 limit과 offset으로 키 값이 중복이 있더라도 문제가 되지 않는다.
중복 값으로 비교연산을 하는 경우 개발팀 내부적으로 문제가 있을 수가 있다고 제기를 해서 생성되는 쿼리를 관찰 하였다.

profile
unit test, tdd, bdd, laravel, django, android native, vuejs, react, embedded linux, typescript

0개의 댓글