최근 groups API를 다루는 작업을 하면서 페이지네이션, 특히 discovery 컨텍스트가 아닌 경우에 대해 몇 가지 생각을 해 보았습니다.
컨텍스트
명확성을 위해, "discovery 컨텍스트"라 함은 list_controller.rb와 tags_controller.rb에서 사용되는 페이지네이션을 의미합니다. 이 두 파일은 이전 페이지와 다음 페이지 URL을 생성하기 위해 유사한 construct_url_with 메서드를 사용합니다.
이와 관련하여, 이 construct_url_with 메서드들은 서로 매우 유사하므로 포함(include) 모듈로 통합할 수 있을 것입니다. 그러나 이 페이지네이션은 토픽 목록 생성에 매우 밀접하게 연관되어 있어, 다른 문제와 구분되는 별도의 영역으로 볼 수 있습니다.
패턴
non-discovery 컨텍스트에서 페이지네이션은 다음과 같은 형태의 어떤 버전을 사용합니다:
page = params[:page].to_i
page_size = 38
items = items.offset(page * page_size).limit(page_size)
이 패턴의 버전을 다양한 컨트롤러에서 확인할 수 있습니다. 예를 들어(다음은 전부 나열한 것은 아닙니다):
- groups
- web hooks
- emails
- notifications
- directory items
- staff action logs
…
세 번째-party 클라이언트에서 이러한 엔드포인트를 사용할 때 페이지네이션에는 몇 가지 문제가 있습니다.
문제점
구체적: “더 보기” URL 포함
일부 엔드포인트는 더 이상 페이지가 없더라도 “더 보기” URL(다음 “페이지”)을 반환합니다.
예를 들어, meta에서 제가 볼 수 있는 그룹은 9개입니다. 그러나 해당 페이지의 .json 파일에는 존재하지 않는 두 번째 페이지에 대한 “load_more_groups” 항목이 포함되어 있습니다(페이지 번호는 실질적으로 0부터 시작하므로 "page 1"은 두 번째 페이지입니다):
https://meta.discourse.org/g.json
...
"total_rows_groups":9,
"load_more_groups":"/groups?page=1"
API 클라이언트는 페이지를 반복할 때 페이지 카운팅을 스스로 처리하기보다 “더 보기” URL을 사용하려는 경향이 있으므로, 이는 엔드포인트의 "버그"라고 할 수 있습니다.
일반적: 명명 규칙, 페이지 크기 처리 및 반환되는 페이지네이션 데이터의 차이
더 일반적으로, non-discovery 컨텍스트에서 페이지네이션 명명 규칙, 페이지 크기 및 반환되는 페이지네이션 데이터에 상당한 차이가 있습니다. 예를 들어
- "page"는
:page또는:offset으로 불립니다. - "항목의 총 수"는
total_rows_*"로 포함되기도 하지만, 항상 포함되는 것은 아니며 때로는 다른 이름으로 불립니다. - 대부분의 페이지 크기는 해당 액션 내에서 로컬 변수로 할당되며 서로 약간씩 다릅니다. 따라서 이를 찾기 위해 코드를 직접 살펴봐야 합니다.
제안
제가 제기한 여러 사항에는 다양한 이유가 있습니다. 많은 non-discovery 엔드포인트는 주로(또는 오직) Discourse 앱 클라이언트에 의해 소비되며, 해당 클라이언트에 맞게 조정되어 있습니다. 이는 당연한 일입니다.
그럼에도 불구하고, 특히 외부 클라이언트(예: groups)에서 자주 소비되는 엔드포인트의 non-discovery 페이지네이션을 점진적으로 더 표준화된 방향으로 이동시키는 움직임이 있을 수 있으며, 이는 “더 보기” URL 포함과 같은 문제를 해결하는 것도 더 쉽게 만들어 줄 것입니다.
제가 염두에 둔 것은 기본적으로 이 패턴을 코드화하고, 선택된 일부 엔드포인트(예를 들어 Groups부터 시작하여)에서 페이지네이션을 처리할 수 있는 “Pagination” 모듈입니다.
이 부분에 대해 PR을 만들 수도 있지만, 먼저 논의하기 위해 이 글을 올렸습니다.