많은 소프트웨어 엔지니어에게 엔티티 목록을 가져오는 엔드포인트가 아마도 가장 선호하는 구현일 것입니다—필요한 것은 모든 항목을 가져오는 SQL 문과 몇 가지 사소한 작업뿐입니다. 모든 것이 재미있고 게임이었지만, 데이터베이스 내 엔티티 수가 병목 현상이 되어 각 GET 요청마다 수만 개의 항목이 반환됩니다. 서버 측 로그에 빨간색으로 강조된 오류 메시지로 폭격적으로 보게 됩니다. 이전에 애플리케이션에 만족했던 사용자들이 점점 더 부진한 성능에 대해 불평하기 시작합니다. 제품 관리자는 거의 무너질 듯 당신에게 불만을 표출하고 있습니다. 뭐라고요?! 이 모든 일이 일어나지 않도록 막고 싶다고요? 페이지네이션이 바로 당신이 필요한 것입니다! 이것은 엔드포인트의 성능을 획기적으로 향상시키고 서버 과부하를 막아줄 수 있습니다. 오늘은 페이지네이션을 정의하고 가장 일반적인 페이지네이션 기법을 소개하겠습니다.
페이지네이션이란 무엇인가?
먼저 페이지네이션에 대한 기본적인 개요부터 시작해 보겠습니다. 페이지네이션은 방대한 결과 세트를 더 작고 관리하기 쉬운 단위로 나누는 기법입니다. 간단히 말해, 페이지네이션은 대량의 데이터를 여러 조각, 즉 이름 그대로 '페이지'로 나누는 것입니다. 여러분 중 일부는 "왜 페이지를 포함해서 코드를 복잡하게 만들어야 하는가?"라고 궁금해하실 수도 있습니다. "왜 모든 레코드를 사용자에게 주고 끝내는 쉬운 방법을 택하지 못할까요?" 그 이유는 주로 두 가지입니다. 첫째, 사용자가 페이지 처리된 표에서 필요한 정보를 더 쉽게 찾을 수 있어 전반적인 사용자 경험이 향상됩니다. 둘째, 페이지 전송은 반환되는 항목의 평균 수를 줄이는 데 도움을 줍니다. 데이터 전달 속도를 높일 뿐만 아니라 대량의 데이터 전송에 필요한 자원을 절약하는 데도 도움이 됩니다.
프론트엔드 페이지네이션 vs. 백엔드 페이지네이션
페이지네이션은 프론트엔드와 백엔드 모두에서 이루어질 수 있습니다. 페이지네이션에 접근하기 전에 프론트엔드와 백엔드 페이지네이션을 구분해야 합니다. 프론트엔드 페이지네이션은 UI/UX 디자인과 더 밀접하게 연관된 정보를 쉽게 이해하기 쉽게 보여주어 사용자의 시각적 인식을 향상시키는 데 중점을 둡니다. 반면, 백엔드 페이지네이션의 주된 목적은 백엔드 서버를 과부하시키는 것을 피하고 데이터 전송의 효율성을 높이는 것입니다. 프론트엔드 페이지네이션과 비교했을 때, 백엔드 페이지네이션은 우리 엔지니어들에게 더 적합합니다. 다음 섹션에서는 주로 백엔드 페이지네이션 기법을 소개하겠습니다. (프론트엔드 페이지네이션에 관심이 있다면, 귀사의 UI/UX 디자이너들과 자유롭게 논의해 보시기 바랍니다. 그들은 이 주제에 대해 기꺼이 알려줄 것입니다.)
백엔드에서 페이지네이션을 어떻게 구현할까?
엔드포인트에 대해 페이지네이션을 구현하는 방법은 여러 가지가 있습니다. 여기서는 가장 일반적인 페이지네이션 기법 몇 가지를 다루겠습니다.
오프셋 기반 페이지네이션
오프셋 기반 페이지네이션은 가장 간단한 페이지 설정 기법 중 하나입니다. 엔드포인트 사용자는 오프셋과 제한을 활용하여 엔드포인트에 필요한 데이터 페이지를 전달합니다. 오프셋은 대상 데이터 앞에서 건너뛸 레코드 수를 나타냅니다. 제한은 한 페이지에 최대 레코드 수를 결정합니다.
페이지네이트 데이터를 가져오기 위한 SQL 문장을 구성할 때, 이 두 매개변수를 직접 활용할 수 있습니다. 예를 들어, 'users' 테이블에서 데이터를 가져오고 싶다고 가정해 봅시다. 세 번째 페이지의 데이터를 얻고 싶고, 각 페이지에는 10개의 레코드가 포함되어 있습니다. 이 경우, 원하는 데이터를 얻기 위해 다음과 같은 SQL 문장을 작성할 수 있습니다.
사용자 중에서 선택 *
ID ASC 순서
제한 10
오프셋 20;
제한은 10인데, 각 페이지마다 '사용자' 테이블에서 10개의 레코드만 가져오기 때문입니다. 오프셋은 20인데, 각 페이지는 10행인 첫 두 페이지를 건너뛰어 10개의 레코드 중 세 번째 페이지를 얻어야 하기 때문입니다.
오프셋 기반 페이지네이션의 장점:
오프셋 기반 페이지네이션은 SQL 문장을 만들 때 'offset'과 'limit'을 직접 사용할 수 있어 구현이 쉽습니다. 복잡한 논리는 필요하지 않습니다. 오프셋 기반 페이지네이션이 구현된 엔드포인트의 사용자는 아무 페이지로도 점프할 수 있습니다. 이것은 모든 페이지네이션 기법에 공통된 보편적 특성으로 볼 수 있지만, 일부 페이지네이션 기법은 이 특성을 갖지 못하는 경우가 있습니다. 이는 나중에 보여드리겠습니다.
오프셋 기반 페이지네이션의 단점:
오프셋 기반 페이지 지정은 특히 오프셋이 큰 경우 성능이 저하됩니다. 이유는 간단합니다: 데이터베이스가 건너뛸 행(오프셋)과 목표 데이터를 함께 쿼리해야 하고, 결국 이를 버려야 하므로 컴퓨팅 자원 낭비가 발생합니다. 오프셋 기반 페이지 생성은 일관성 없는 결과를 반환하기 쉽습니다. 그 이유를 설명하기 위해 다음 두 가지 예시를 사용하겠습니다: a. 데이터 삭제: 사용자가 첫 번째 페이지를 보고 있다고 가정하여 누군가가 첫 페이지에서 레코드를 삭제한다고 가정합니다. 그러면 두 번째 페이지의 첫 번째 레코드가 삭제된 레코드 때문에 첫 번째 페이지의 마지막 레코드가 됩니다. 사용자가 두 번째 페이지로 이동하면 원래 첫 번째 레코드를 볼 수 없습니다. b. 데이터 삽입: 사용자가 첫 번째 페이지를 보고 있다고 가정하여 누군가가 첫 번째 페이지에 레코드를 삽입합니다. 그러면 첫 번째 페이지의 마지막 레코드가 두 번째 페이지로 뒤로 이동합니다. 사용자가 두 번째 페이지로 이동하면 첫 번째 페이지의 마지막 레코드가 다시 보이는데, 이는 원래 일어나서는 안 됩니다.
페이지 기반 페이지 지정
페이지 기반 페이지 지정은 본질적으로 오프셋 기반 페이지 지정과 동일합니다. 유일한 차이점은 페이지 기반 페이지 지정이 사용자가 현재 보고 있는 페이지를 추적하기 위해 페이지 번호를 사용한다는 점입니다. 다음 공식을 사용하여 페이지 번호를 오프셋으로 쉽게 변환할 수 있습니다:
오프셋 = (페이지 번호 - 1) * 제한
커서 기반 페이지네이션
커서 기반 페이지네이션은 커서 또는 포인터를 사용하여 엔드포인트 사용자가 커서를 사용해 본 마지막 레코드를 추적하는 페이지네이션 기법입니다. 커서는 보통 다음과 같은 정보를 포함합니다: 커서 위치와 그에 대응하는 값을 식별하는 데 사용되는 열(커서의 고유성을 보장하기 위해 최소 하나의 고유 열이 있어야 함) 결과는 이 열들을 기반으로 어떤 순서(오름차순 또는 내림차순)로 정렬되나요? 엔드포인트 사용자가 결과를 커서 앞에 요청하는지 뒤에 위치하는지 예시를 소개합니다:
{
"열":[
{
"이름": 별명",
"가치": 숀",
"is_ascending":사실이야
},
{
"name":"id",
"value":"23bf6f87-a4f5-4a9f-b441-1c98f7027E04",
"is_ascending":사실이야
}
],
"is_backward":false
}
이 커서는 엔드포인트 사용자가 다음 열 값으로 줄 뒤에 있는 닉네임과 ID로 오름차순으로 정렬된 데이터를 검색할 수 있게 합니다:
별명 칼럼: "숀"
ID 열: "23bf6f87-a4f5-4a9f-b441-1c98f7027e04"
닉네임 열만 포함하는 것은 불충분할 수 있으므로, 닉네임 열에는 중복된 값이 포함될 가능성이 큽니다. 고유 커서가 없으면 데이터베이스가 요청된 데이터를 확실히 찾을 수 없습니다. ID 열을 보조 식별자로 추가하면 커서의 유일성을 보장합니다.
엔드포인트는 페이지화된 데이터와 함께 앞뒤로 이동할 수 있는 커서를 계산하고 반환해야 하므로, 엔드포인트 사용자가 데이터 소스의 레코드를 쉽게 탐색할 수 있습니다.
커서 기반 페이지 설정의 장점:
커서 기반 페이지네이션은 데이터베이스에 많은 레코드가 있을 때 모든 페이지네이션 기법 중 보통 가장 우수한 성능을 보입니다. 그 이유는 오프셋 기반 페이지네이션과 달리 커서 기반 페이지네이션은 원하지 않는 데이터를 쿼리했다가 버릴 필요가 없기 때문입니다. 커서 기반 페이지네이션은 요청된 레코드를 효율적으로 찾아내고 검색할 수 있게 합니다. 커서 기반 페이지네이션은 오프셋을 사용하지 않아 행 이동에 저항성이 있습니다. 기존 행을 제거하거나 새 행을 추가하더라도, 커서 기반 페이지네이션은 행을 건너뛰거나 두 개의 다른 페이지에 같은 행을 표시하지 않습니다.
커서 기반 페이지네이션의 단점
커서 기반 페이지네이션의 구현은 꽤 복잡합니다. (너무 복잡해서 너무 길어지지 않도록 별도의 기술 블로그에서 다룰 필요가 있다고 느낍니다. 계속 지켜봐 주세요!)
엔드포인트 사용자는 모든 탐색이 앞뒤 커서에 의존하기 때문에 특정 페이지로 점프할 수 없습니다.
어떤 페이지네이션 기법을 써야 할까?
경험 법칙으로는 사용자 수가 증가함에 따라 레코드 수가 기하급수적으로 증가하지 않을 것으로 예상되거나 사용자가 어떤 페이지로든 점프할 수 있도록 하는 것이 필수적일 때 오프셋 기반(또는 페이지 기반) 페이지 지정을 구현하는 것이 좋습니다. 그렇지 않으면 커서 기반 페이지네이션이 성능이 더 우수하기 때문에 더 나은 선택일 것입니다.
요약
이 글에서는 페이지네이션이 무엇을 하는지, 그리고 왜 필요한지 설명하는 것으로 시작했습니다. 그 다음, 가장 널리 사용되는 페이지네이션 기법들과 그 각각의 장점과 단점을 소개했습니다. 그 다음에는 언제 어떤 페이지네이션 기법을 사용해야 하는지에 대한 조언을 드렸습니다. 이 글이 여러분이 엔드포인트에 페이지네이션을 도입할지, 어떻게 구현할지 정보에 입각한 결정을 내리기에 충분한 정보를 제공했기를 바랍니다.