HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
[New] 아만드팀
[New] 아만드팀
/
🌟
팀프로젝트
/
📕
만두 WIKI
/
무한 스크롤 구현
무한 스크롤 구현
무한 스크롤 구현

무한 스크롤 구현

오프셋 페이징 No offset 방식 구현 코드페이징 타입결론 Reference

오프셋 페이징

  • offset : 어디부터 시작해서 조회할건지?
  • limit : 몇개를 조회할건가?
  • 해당 쿼리는 뒤로 갈수록 느려지는 데 이는 앞에서 읽었던 행을 다시 읽어야 하기 때문이다.
  • offset 10000, limit 10이라 하면 최종적으로 10,010개의 행을 읽어야 하기 때문에 점점 느려질 수 밖에 없다.
 

No offset 방식

  • 조회 시작 부분을 인덱스로 빠르게 찾아 매번 첫 페이지만 읽도록 하는 방식
  • 매번 이전 페이지 전체를 건너뛸 수 있게 된다.
  • 해당 방식으로 사용하면 클라이언트에서 스크롤 했을 때 마지막 예약 번호만 넘겨주면 무한스크롤 방식으로도 사용이 가능하다!
  • 성능도 좋아지고 일석이조!
 

구현 코드

 

페이징 타입

  • Page
    • 데이터 총 개수, 다음 페이지의 존재 여부, 페이징해서 가져온 데이터 확인 가능
    • 데이터의 총 개수를 가지고 있기 때문에 조회시 count쿼리를 한번 더 실행
  • Slice
    • 다음 페이지의 존재 여부와 페이징해서 가져온 데이터는 확인할 수 있으나 데이터의 총 개수에 대한 정보는 가지고 있지 않다.
    • count 쿼리 대신 limit + 1조회를 통해 마지막 페이지인지 정보를 확인하기 때문에 page보다 조금의 성능 이점이 있다.
게시판처럼 전체 페이지의 수를 보여줄 필요가 있다면 Page를 무한 스크롤처럼 전체 페이지의 수를 알 필요가 없다면 Slice를 사용하면 된다.
 

결론

  • No offset 방식을 커서 기반 페이지네이션라고 부르기도 하는 것 같다.
  • 현재 방식에서는 pageSize와 lastReservationId만 받아서 동적쿼리를 위해 QueryDsl을 사용했지만 간단한 쿼리의 경우 PageRequest.of(0, pageSize)와 Spring Data Jpa를 사용하여 좀 더 간단하게 구현할 수 있을 것 같다.
 

Reference

  • https://bbbicb.tistory.com/40
  • 1. 페이징 성능 개선하기 - No Offset 사용하기
  • JPA Pagination을 이용한 무한 스크롤 구현기
  • Querydsl Select 필드로 Entity 사용시 주의 사항
  • Querydsl select에서 상수 사용하기
  • Querydsl (JPA) 에서 Cross Join 발생할 경우
 
SELECT * FROM Reservation r ORDER BY r.id DESC OFFSET 페이지번호 LIMIT 페이지사이즈
SELECT * FROM Reservation r WHERE r.id < 마지막조회 ID ORDER BY r.id DESC LIMIT 페이지사이즈
@Override public List<ReservationDto> findReservationsByGuestAndStatus( Long lastReservationId, int pageSize, User guest, ReservationStatus status ) { return queryFactory.select(toReservationDto(status)) .from(reservation) .innerJoin(reservation.room, room) .innerJoin(room.host, user) .where(ltReservationId(lastReservationId), eqStatus(status), eqGuest(guest)) .limit(pageSize) .orderBy(reservation.id.desc()) .fetch(); }