Skip to content

오프셋 기반 페이지네이션 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 값을 알 수 없기 때문이다.
  • 마지막 페이지에서 스크롤을 한다면?
    • 데이터는 존재하지 않기 때문에 아무 데이터도 응답하지 않는다.
    • 다음 데이터가 존재하지 않는다는 필드를 추가해주면 좋다.

OR 연산자의 문제점

대부분의 RDBMS 는 WHERE에 OR 연산자 사용하면 인덱스를 제대로 활용하지 못한다.

결론

오프셋 기반 페이지네이션을 사용해도 되는 경우

  • 데이터의 변화가 거의 없다시피하여 중복 데이터가 노출될 염려가 없는 경우
  • 일반 유저에게 노출되는 리스트가 아니라 중복 데이터가 노출되어도 크게 문제 되지 않는 경우
  • 검색엔진이 인덱싱할 이유도, 유저가 마지막 페이지를 갈 이유도, 오래된 데이터의 링크가 공유될 이유도 없는 경우
  • 애초에 row 수가 그렇게 많지 않아 특별히 퍼포먼스 걱정이 필요 없는 경우

나머니의 경우 커서 기반 페이지네이션을 사용하는 것이 좋다.

Clone this wiki locally