TIL/BackEnd

[BE]무한 스크롤(Infinite Scrolling) & 페이지네이션(Pagination)

JoJobum 2022. 10. 4.

요즘 사람들이 많이 사용하는 어플리케이션에 무한 스크롤이 없는 것을 오히려 찾아보기 힘들 정도라고 생각한다.

막상 쓸 때에는 이것을 어떻게 구현하냐? 라는 것에 대해 고민을 크게 해본적이 없었지만, 이번에 구현해보면서 했던 고민과 알게 된 점을 적고자 한다.

 

무한 스크롤은 말그대로 페이지 이동을 하지않고 계속 내려도 (보여줄 컨텐츠가 있다면) 컨텐츠를 무한정으로 보여주는 기능을 의미한다.

이러한 기능을 어떻게 구현할 것이냐? 라고 물으면 그냥 바로 생각나는 것은 무한대의 컨텐츠를 서버에게 요청하고 클라이언트가 받아서 줄줄이 소세지마냥 보여줍니다! 라는 생각이 났었다.

동작을 할 것이다 하지만 생각을 하면서도 너무 비효율적일 것이라는 생각을 동시에 하게 된다. 어떤 유저는 우리가 의도한대로 한 화면에서 무한대의 컨텐츠를 즐길 수도 있지만, 어떤 유저는 화면에 동시에 띄워지는 2~3개 정도의 컨텐츠를 보고 다른 화면을 넘어갈 수도 있다. 그리고 전자가 많을까? 후자가 많을까? 를 생각해보면 후자가 많을 것이 너무 당연하다. 그런데 매번 화면에 들어갈 때마다 무한대의 컨텐츠를 주고 받는 작업을 하는 것은 너무 비효율적이다. 우선 컨텐츠를 로딩하는 시간이 너무 오래 걸릴 것이고, 서버에 부하도 많이 걸릴 것이다. 이뿐만이 아니라 사진이나 동영상 등의 데이터를 많이 잡아먹는 컨텐츠들이라면 유저도 모르게 유저의 통신요금 고지서에 0을 마구 찍어버릴 수 있다.

 

그래서 이러한 부분을 해결하기 위해 어떻게 하냐? 라는 것은 전체 중의 우선적으로 보여주어야하는 부분만을 가져오는 것이다.

여기서 페이지네이션(Pagination)이라는 개념이 들어가는데 말 그래도 페이지화 하여 일정 갯수의 컨텐츠가 1개의 페이지에 속하여 1개의 페이지씩 보여주는 것이다.

엄밀히 따지면 위의 사진처럼 유저가 페이지 숫자를 눌러 페이지를 탐색하는 것을 페이지네이션이라고 하고

유저가 페이지 하단에 도달했을 때 다음 페이지의 컨텐츠를 자동으로 로드해주는 것을 무한 스크롤이라고 하는데

 

내 생각에는 결국 자동으로하냐 유저가 하냐 차이이지 결국엔 페이지의 개념을 사용하는 것은 동일한 것 같다.

 

그래서 페이지의 개념을 도입하여 부분 부분 보여주는 것은 알겠는데 좀 더 구체적으로 어떻게 이를 구현하는지에 대해 말하고자 한다.

 

 

1. Offset Based Pagination - offset 과 limit를 사용하는 방법

예를 들어 20~1 번의 데이터가 존재하고 페이지당 데이터를 5개를 보여주자 하였을 때

(숫자가 높을수록 나중에 쌓인 데이터로 우선적으로 보여줘야한다고 하자)

=> offset(시작 지점): 14, limit(끝 지점):10 이면 

처음 페이지를 건너뛰고 2번째 페이지(15~11), 3번째 페이지(10~6)를 보여주는 방식인데

 

이러한 방식은

DB에서 모든 컬럼을 읽어와 offset부터 limit 수로 자르는 작업이기에 계속해서 모든 컬럼 내용을 읽어와야하기에 느리고 

한번 데이터를 부른 후, 데이터에 변화가 생겼을 때 이를 반영할 수 없다

 

2. Cursor Based Pagination - next_id 와 size를 이용하는 방법

이 방식은 원하는 데이터가 몇 번째 데이터냐에 집중한다.

next_id 는 불러오기 시작할 데이터의 인덱스 값, size는 페이지의 크기가 된다.

위와 동일한 상황이란 next_id =14에서 5개를 집어와서 14~10 번의 데이터를 보여주는 방식이다.

 

이렇게 하면 앞선 Offset Based Pagination의 단점을 해결할 수 있다.

 

 

어떻게 더 이상 불러올 데이터가 없는지 아는지에 대한 고민

위의 개념을 이제 실제 코드로 구현하려고 하면 부딪히는 문제이다. 그래서 next_id부터 size 갯수 만큼씩 불러오는 건 알겠는데,

어떻게 끝을 알 것인가?

라는 문제는 서버 측에서 size+1개의 데이터를 불러오는 것으로 해결했다.

 

 

최초에 데이터를 조회하기 시작할 next_id 를 받는 api로 클라이언트에게 어디서 부터 호출해야할지 알려주고

클라이언트가 next_id 와 size를 보내면, next_id로부터 size+1 개의 데이터를 조회한다. 그리고 조회한 데이터의 갯수가 size+1 이라면 지금 현재 페이지 이후에도 데이터가 존재한다는 의미이기에 size 갯수 만큼의 데이터를 클라이언트에게 보내면서 다음 next_id와 끝인지 아닌지 판별하는 변수인 isLast를 false로 같이 보내준다. 이를 바탕으로 클라이언트는 isLast가 true가 나올 때까지 계속 페이지를 불러온다. 만약 size+1 보다 불러온 데이터가 작다면 마지막 페이지라는 의미이기에 isLast를 true로 바꿔서 보내주는 것으로 끝을 알린다.

 

 

 

참고자료

[DB] 커서 기반, 오프셋 기반 페이지네이션 - SW Developer (wonyong-jang.github.io)

반응형

댓글