이번에 회사 코드를 작성하면서, 페이지네이션을 구현해볼 기회가 있었다.
페이지네이션이란 콘텐츠를 여러 페이지로 나누고, 이전 혹은 다음 페이지로 넘어가거나 특정 페이지로 넘어갈 수 있는 링크를 페이지 상단이나 하단에 배치하는 방법을 의미한다.
이러한 페이지네이션은 LIMIT
와 OFFSET
을 사용하여서, 간단한 방식으로 구현될 수 있다.
LIMIT
← 결과 중에서 적힌 갯수만큼만 가져온다.
OFFSET
← 어디서부터 가져올지
SELECT *
FROM EXAMPLE
WHERE model_name LIKE "%modelName%"
LIMIT 0, 10;
위의 쿼리는 내가 페이지네이션을 이용해 조회를 할 때 작성했던 쿼리이다.
위의 방식이 어떤 방식인지에 대해서 먼저 이야기를 해보고, 더 나은 방식은 무엇이 있는지에 대해서 알아보자.
SELECT *
FROM EXAMPLE
WHERE model_name LIKE "%modelName%"
LIMIT 0, 10;
오프셋 기반 페이지네이션은 MYSQL 기준으로 OFFSET
, LIMIT
를 사용한 쿼리를 이용한다.
첫번째 인자 =
OFFSET
// 기본값은 0이다.
두번째 인자 =LIMIT
무한 스크롤을 구현할 때는 보통 OFFSET
을 변수로 두고 페이지가 넘어갈때마다 정해진 만큼씩 더해주는 방법을 사용한다.
이 방식을 사용하면 조건절을 거친 전체 결과를 먼저 가져오고, 결과 데이터에서 OFFSET
에 명시된 순서부터 LIMIT까지의 데이터만을 가져온다.
OFFSET은 단순히 레코드를 조회하기 전에 데이터베이스가 건너뛰는 레코드의 수다.
즉, 요청한 데이터를 바로 조회하는 것이 아니라, 이전에 데이터를 모두 조회하고 그 결과값에서 OFFSET을 조건으로 잘라내는 것이다.
이 때 큰 문제점이 있는데 바로 OFFSET
의 순서를 가진 데이터를 찾기 위해 그 전에 데이터들을 읽어야 하기 때문에 OFFSET
이 1억이 되어버리면 1억개의 데이터를 읽은 후에 찾아서 가져올 수 있다는 것이다.
SELECT *
FROM EXAMPLE
WHERE model_name LIKE "%modelName%"
LIMIT 10;
SELECT *
FROM EXAMPLE
WHERE model_name LIKE "%modelName%"
AND id > 10
LIMIT 10;
먼저 커서 기반 페이지는 Cursor 개념을 사용하고, 사용자에게 응답해준 마지막 데이터의 식별값을 Cursor로 사용한다.
커서 기반 페이지네이션은 위 오프셋 기반 페이지네이션의 문제점을 해결해준다.
위 코드를 보면, 첫번째 페이지의 요청으로 처음 데이터부터 10개의 데이터를 사용자에게 응답해주었다.
그리고 이 때 마지막으로 응답해준 데이터의 식별값(id)은 10이며, 해당 10을 Cursor로 사용해서, 2번째 페이지에서는 10의 다음 식별값인 11부터 조건절에 사용해 사용자에게 응답해준다.
이 때 커서 기반 페이지네이션의 장점은 마지막으로 읽은 데이터의 다음 데이터부터 10개를 조회하기 때문에 매번 원하는 데이터 개수만큼만 조회한다는 이점이 있다.
더 쉽게 이야기하면, 굳이 커서 뒤의 데이터들을 읽을 필요없이, LIMIT 절 만큼 자른다는 것이다.
이는 대용량 데이터일수록 더 효율적인 속도를 보여준다.
가장 큰 차이점은 오프셋 기반 페이지네이션은 오프셋에 해당 하는 순서의 데이터를 찾기 위해서 오프셋 이전 데이터들을 읽을 필요가 있고, 커서 기반 페이지네이션은 커서 이후의 데이터들만 찾으면 되기에 이전 데이터들은 읽을 필요가 없다는 것이다.
즉 Offset 기반 페이지네이션은 우리가 원하는 데이터가 ‘몇 번째’에 있다는 데에 집중하고 있다면, 커서 기반 페이지네이션은 우리가 원하는 데이터가 '어떤 데이터의 다음'에 있다는데에 집중한다!