본문 바로가기

React

Infinite Scroll & pagination API

Infinite Scroll & pagination을 사용하면 한 번에 많은 양의 데이터를 렌더링 하지 않고 적절한 양의 데이터를 렌더링 후 사용자의 액션에 따라 다음 데이터를 렌더링 시킬 수 있습니다.

 

우선 게시판 등에서 많이 사용되는 pagination API에 대해 살펴보도록 하겠습니다.

 

 

pagination 
 

react-js-pagination

Simple, easy to use component for pagination. Compatible with bootstrap paginator stylesheets. Latest version: 3.0.3, last published: 3 years ago. Start using react-js-pagination in your project by running `npm i react-js-pagination`. There are 110 other p

www.npmjs.com

저의 경우 react-js-pagination API를 사용하여 상품 리뷰 pagination 작업을 진행하였습니다.

 

Pagination 컴포넌트에 몇 가지 prop만 전달해주기만 하면 간단하게 사용이 가능합니다.

 

reviewData는 리뷰페이지에 렌더링 시킬 상품 리뷰 데이터이며, 이후 생성하는 State들을 통해 slice와 map 메서드를 이용하여 조건을 걸어 렌더링 시켜줄 예정입니다.

 

다음으로 앞서 설명한 Pagination 컴포넌트에 전달할 prop을 관리할 State를 만들어주었습니다.

 

currentPage는 현재 페이지를 관리 해주는 State입니다. 사용자가 페이지 2번을 선택하면 currentPage는 2가 되게 됩니다.

 

perPage는 페이지에 렌더링 시켜줄 데이터의 개수입니다. 저의 경우 10으로 설정해주어 페이지에 10개의 데이터만 렌더링 되게 해 주었으며, 고정 값이기 때문에 별도의 State로 관리하지 않고 상수로 생성해주었습니다.

 

마지막으로 indexOfLastQnAindexOfFirstQnA는 렌더링 된 데이터의 가장 앞에 위치한 데이터의 인덱스와 가장 마지막에 위치한 데이터의 인덱스를 관리해주는 State입니다.

 

첫 시작 인덱스는 0으로 시작하게 되며, 저의 경우 페이지당 렌더링 시킬 데이서의 개수를 10개로 설정하였기 때문에 마지막 인덱스는 9가 되게 됩니다. 추후 데이터를 인덱스로 잘라 사용하기 위해 slice 메서드를 사용하게 되는데 slice 메서드는 두 번째 인자로 전달하게 되는 인덱스 번호의 앞까지 자르기 때문에 indexOfLastQnA는 마지막 인덱스 + 1을 해준 10이 되게 됩니다.

( reviewData.slice(0, 10) : 0번 인덱스부터 9번 인덱스까지 자릅니다. )

 

다음으로 현재 페이지가 변할 때마다 해당 페이지에 렌더링 되는 데이터의 인덱스를 useEffect를 사용해 업데이트해주었습니다.

 

(현재 페이지 * 페이지에 렌더링 시킬 데이터의 개수)를 해주어 첫 번째 페이지의 데이터의 마지막 인덱스는 10, 두 번째 페이지의 데이터의 마지막 인덱스는 20으로 업데이트되도록 해주었습니다.

 

(데이터의 마지막 인덱스 - 페이지에 렌더링 시킬 데이터의 개수)를 해주어 첫 번째 페이지의 데이터의 첫 번째 인덱스는 0, 두 번째 페이지의 데이터의 마지막 인덱스는 10으로 업데이트되도록 해주었습니다.

 

useEffect를 사용하였기 때문에 indexOfLastQnA indexOfFirstQnA는 현재 페이지가 변화할 때마다 업데이트가 되게 됩니다.

 

 

마지막 단계에서는 slice를 사용하여 데이터를 잘라 렌더링 시켜주고, Pagination 컴포넌트 설정을 해줍니다.

 

우선 Pagination 컴포넌트의 prop을 살펴보겠습니다.

 

active : 현재 페이지를 표시해줍니다. 현재 페이지로 선택된 li 요소에 active 클래스를 부여하여 추수 이를 이용하여 css 작업이 가능해지게 됩니다.

 

onChange : 현재 페이지 State를 업데이트시켜줍니다. 페이지 2번을 클릭하면 currentPage를 2로 업데이트시켜주는 역할을 합니다.

 

totalItemsCount : 데이터의 총 개수를 전달해줍니다.

 

itemsCountPerPage : 한 페이지에 렌더링 시켜줄 데이터의 개수를 설정하는 prop입니다. 앞서 생성한 perpage 상수를 전달하게 되면 (총 데이터 개수 / 한 페이지에 렌더링 시키는 데이터의 개수)를 계산하고 올림 하여 페이지의 수를 설정해주게 됩니다.

(앞서 전달받은 totalItemsCount을 이용하여 페이지 개수를 계산하게 됩니다.)

 

pageRangeDisplayed : 브라우저에 보이는 페이지 수량을 설정해줍니다.

 

 

이렇게 생성해준 Pagination 컴포넌트에서 페이지를 선택할 때마다 perPage State가 업데이트되면 useEffect에서  indexOfLastQnA indexOfFirstQnA 업데이트 함수가 실행되게 되며, slice 메서드에 전달되는 인자의 값도 변하게 되어 렌더링 되는 데이터 또한 변하게 됩니다.

 

 

 

 

Infinite Scroll

무한 스크롤을 사용하면 위의 페이지네이션을 사용한 경우처럼 페이지를 따로 넘겨줄 필요 없으며 스크롤을 내리는 액션만으로 다음 페이지의 데이터를 볼 수 있게 됩니다.

 

 

react-infinite-scroll-component

An Infinite Scroll component in react.. Latest version: 6.1.0, last published: 2 years ago. Start using react-infinite-scroll-component in your project by running `npm i react-infinite-scroll-component`. There are 339 other projects in the npm registry usi

www.npmjs.com

저의 경우 react-infinite-scroll-component API를 사용하여 상품 페이지를 만들었으며 사용하기 위한 단계를 살펴보도록 하겠습니다.

 

우선 초기 설정 단계입니다.

 

startNum State는 서버에 통신시 DB 쿼리문에 사용하기 위해 관리하는 State입니다.

DB에 저장된 데이터에서 특정 범위에 해당하는 데이터를 추출할 경우 limit 0, 20, limit 10, 20의 형식으로 작성하기 때문에

0과 10 즉 시작 인덱스를 관리해주는 State입니다.

 

hasMore State는 InfiniteScroll 컴포넌트에 전달하는 prop으로 가져올 데이터가 더 있는지 없는지 여부를 체크합니다.

추후  InfiniteScroll 컴포넌트 스크롤이 바닥에 위치할 때 실행할 함수를 전달하게 되는데 hasMore state가 false가 되면 

더 이상 전달한 함수를 실행시키지 않게 됩니다.

 

tmpNum State는 서버 통신시 응답으로 전달받은 데이터의 시작 인덱스를 임시로 관리하는 State입니다.useEffect의 의존성 배열에 startNum을 넣어놨기 때문에 startNum를 바로 업데이트시켜주는 것이 아닌 InfiniteScroll 컴포넌트에 전달한 스크롤이 바닥에 위치할때 실행할 함수 안에서 업데이트를 진행해줍니다.이렇게 되면 스크롤이 바닥에 위치했을 때 업데이트된 startNum를 사용하여 서버와 통신을 하게 됩니다.

 

 

 

다음은 서버 설정 단계입니다.

 

저의 경우 axios로 서버 통신 시 쿼리 스트링을 이용해 startNum을 전달해주었기 때문에 서버에서 요청을 받을 때 qurey를 이용해 startNum을 받아 주었습니다.

 

DB 쿼리문을 사용해 특정 범위에 위치한 데이터를 가져올 경우 마지막 값은 고정값에 해당하기 때문에 endNum을 앞단에서 별도로 관리하지 않고 뒷단에서 상수로 선언해주었습니다. endNum은 추후 응답으로 전달하는 startNum을 증가시켜주는데도 이용됩니다.

(limit 0, 20 : 0번 인덱스부터 20개의 데이터 추출, limit 15, 30 : 15번 인덱스부터 30개의 데이터 추출)

 

또한 저의 경우 베스트 상품 페이지에 판매량이 높은 상품 100개만 노출시키기 위해 별도의 lastDataNum을 생성해주었습니다. 추후 응답으로 전달하는 moreData의 값을 설정하는 기준으로 사용됩니다.

 

서버 응답시 result(result [0] : 전체 상품 데이터, result [1] : limit 조건을 통해 추출한 상품 데이터), startNum(시작 인덱스),  moreData(더 조회할 데이터가 있는지 없는지)를 전달하게 됩니다.

startNum의 경우 데이터의 길이가 0보다 크다면 처음 전달받은 startNum(0) + endNum(20) = 20을 전달하게 되고,

moreData의 경우 100개의 상품만 보여주어야 되기 때문에 startNum이 lastDataNum(100) 보다 클 경우 false를 전달하게 하였습니다.

(startNum이 80이면 true, 100부터 false가 되며 hasMore State가 false가 되면 더 이상 서버 통신을 하지 않게 됩니다. )

 

 

마지막으로 컴포넌트 prop 설정 단계입니다.

 

dataLength : 한번에 렌더링 키실 데이터의 개수입니다. 저의 경우 서버에서 20개의 데이터만 추출하여 전달받았기 때문에 데이터의 길이만큼 전달해주었습니다.

 

next : 스크롤이 바닥에 위치하면 실행시키는 함수입니다. 함수 내부에는 startNum을 업데이트시켜주는 함수를 넣어두어 별도로 관리하던 데이터 시작 인덱스로 startNum을 업데이트시켜주게 됩니다.

 

hasMore : 렌더링할 데이터가 있는지 없는지를 체크합니다. 저의 경우 서버에서 startNum이 100 이상이 되면 false를 전달하게 하여 더 이상 next에 전달한 함수가 실행되지 않게 됩니다.

 

'React' 카테고리의 다른 글

React 관심사 분리  (0) 2023.01.11
React 기본 정리  (0) 2023.01.10
Redux의 State를 올바르게 사용하는 방법  (0) 2022.11.08
Redux 정리  (0) 2022.11.08
사용자 입력값 유효성 검사  (0) 2022.11.01