[react-window] 무한 스크롤 구현하기 1

김하정·2023년 12월 21일
4
post-thumbnail
post-custom-banner

사용하게 된 계기

회사에서 진행하는 프로젝트의 대부분의 리스트가 무한 스크롤로 이루어져 있었다.

무한스크롤은 스크롤을 내릴 때마다 Dom에 UI가 쌓이게 되는 구조인지라,

스크롤을 내리면 내릴수록 UI들이 쌓이게 되어
프론트 단에서의 화면 처리를 고민하지 않을 수 없었다.

그러다 화면 밖으로 나가는 UI 들은 보이지 않게끔 처리할 수 없는지에 대해 고민하게 되었고,
찾아보니 windowing 처리에 대한 라이브러리가 있어 사용한 경험을 공유하고자 한다.

react-window vs react-virtualized

windowing 처리에 대해 검색을 하다보면 위 두가지 라이브러리에 대한 글을 많이 찾아볼 수 있다.
필자는 두 개의 라이브러리 모두 다 써보았다.

react-window는 react-virtualized에 비하여 가볍다. 하지만 그만큼 지원되는 기능이 한정적이라 조금 더 다채로운 기능들을 사용하려면 여러가지의 라이브러리를 추가로 설치해주어야 한다.

가장 큰 차이로는 react-virtualized 동적인 height을 지정할 수 있고, react-window는 정적인 height을 지원한다.
(( react-window에서도 동적으로 height을 사용할 수 있는 방법이 있지만 그건 나중에 포스팅 하겠다. ))

필자의 경우, 리스트들의 높이가 다 일정하였기 때문에 react-window 를 사용하였다.

누구에게 추천하는 포스팅인지?

  • 프로젝트에 무한스크롤로 구현된 리스트가 한 화면에 많은 경우
  • 리스트의 높이가 고정적인 경우
  • 리스트가 쌓이면서 화면이 느려지거나 그로 인하여 렌더링 퍼포먼스를 개선하고자 하는 경우

infinite scroll 과 react-window 에 대한 글은 많이 올라와있지 않아,
나와 같은 고생을 덜고자하는 바람으로 이 포스팅을 작성하게 되었다.

시작하기

1) react-window 설치 (+typescript)

필요한 패키지는 다음과 같다.

npm install --save react-window   
npm install --save @types/react-window
npm install --save react-window-infinite-loader   // InifniteLoader 
npm install --save @types/react-window-infinite-loader
npm install --save react-virtualized-auto-sizer   // AutoSizer
npm install --save @types/react-virtualized-auto-sizer

위 3가지만 있으면, 무한스크롤 환경에서 windowing 처리할 준비가 다 된 것이다.
저 중, InfiniteLoader 만 없으면 무한스크롤이 아닌 환경에서도 windowing 처리가 가능하다.

그럼 가장 기본적인 부분부터 넓은 부분까지 설명을 해보도록 하겠다.

2) react-window 에서 List 사용하기

react-window 문서나 데모를 보면, 일반적으로 사용하는 컴포넌트가 List 컴포넌트 이다.
무한스크롤을 적용하지 않을 것이라면,
아래 데모 사이트에서 참고하는것도 좋은 방법이다.
react-window 데모사이트 바로가기

기본적으로 사용하는 방법은 아래와 같다.

import { FixedSizeList as List } from "react-window";
import styled from "styled-components";

function App() {
  // 임시 dummyList 생성
  const dummyList = new Array(100).fill(0).map((_, idx) => ({
    id: idx,
    name: `List ${idx}`,
  }));

  return (
    <Container>
      <List height={150} itemCount={dummyList.length} itemSize={35} width={300}>
        {({ index, style }) =>  
        	<div style={style}> {dummyList[index].name}</div>
        }
      </List>
    </Container>
  );
}

export default App;

const Container = styled.div`
  width: 350px;
  height: 90vh;
  background: #ddd;
  > div {
    background: #fff;
  }
`;

위와 같이 작성하게 되면 화면으로는 아래와 같은 영역에 List 가 생겨난다.

List는 props로 작성한 height, width의 영역을 잡게 되며 그 안에서 windowing 처리가 이루어지게 된다.
List 에 있는 itemCount 는 리스트의 총 갯수이며, itemSize 는 처음에 설명했던 것처럼 리스트 안 아이템 각각의 정적인 높이이다. (예시로 보면 35px임)

이때 중요한 것은 안쪽에 감싸진 div 에 style을 꼭 적용시켜줘야 내부에 해당 높이를 전달해줄 수 있다.

이제 콘솔로 확인해보면 다음과 같이 100개의 데이터 중, 일부의 데이터만 UI 로 그려내고 있는 것 을 확인해볼 수 있다.

windowing을 적용 안한다면 다음과 같이 100개의 UI 가 Dom에 그려질 것이다.

다음 포스팅에서 무한스크롤과, AutoSizer 활용법에 대하여 소개해보겠다.

profile
web developer
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 12월 21일

오 도움이 엄청 됐어요

답글 달기