아무리 빠른 인터넷 환경이라고 해도 수백 개, 1,000개 이상의 데이터를 받는 데에는 시간이 오래 걸린다. 많은 데이터를 하나의 페이지에 랜더링해야 할 때 어떻게 지연 로딩을 할 수 있는지 알아보자.


Skeleton Loading


스켈레톤 로딩을 사용하지 않았을 때 화면에 밀려나는 현상이 있어 UX 관점에서 좋지 않았다.


스켈레톤 스크린 (Skeleton Screen) 이란?

화면의 뼈대와 같은 느낌을 주는 UI / UX 기법으로 데이터를 불러오는 중일 때 해당 데이터가 화면에 어떻게 나타날지 미리 알 수 있게 해주는 역할을 한다.


skele.gif)


react-loading-skeleton

사용법도 간단하고 기존 프로젝트에 사용하기도 편해보여서 선정했다.


SkeletonUser.js

import Skeleton from 'react-loading-skeleton';
import 'react-loading-skeleton/dist/skeleton.css';

const SkeletonUser = () => {
  return (
    <>
      <StyledSummary>
        <div className="image">
          <Skeleton circle={true} height={120} width={120} />
        </div>
        <div className="stats">
          <Skeleton width={'500px'} height={'20px'} />
          <Skeleton width={'500px'} height={'20px'} />
          <Skeleton width={'500px'} height={'20px'} />
        </div>
      </StyledSummary>
    </>
  );
};

export default SkeletonUser;

이런식으로 편리하고 빠르게 작업할 수 있었다.


✔️ 그래서 만족스러운 결과가 나왔나요..?

스켈레톤 스크린이 UI/UX적인 면에서 얼마나 좋은지 알 수 있었다. 하지만 개발하고 있는 여행 일기 작성 서비스에 적용하기에는 아직 이용자도 적고 불러올 데이터도 많지 않아서 큰 효과가 없었다. 현재 사용자 프로필 보여주는 부분에서 적용하고 있다.


Infinite Scroll


무한 스크롤(Infinite Scroll)이란?

사용자가 특정 페이지 하단에 도달했을 때, API가 호출되며 콘텐츠가 끊기지 않고 계속 로드되는 사용자 경험 방식이다.


무한 스크롤과 비교되는 가장 대표적인 것은 페이지네이션이 있다.

페이지네이션(Pagination)은 페이지를 클릭하면 다음 페이지 주소로 이동한다.

무한 스크롤은 한 페이지에서 스크롤만으로 새로운 콘텐츠를 보여주게 되므로, 많은 양의 콘텐츠를 스크롤하여 볼 수 있는 장점이 있다.

두 기법은 어떤 UI/UX를 사용자에게 보여줄 것인지에 따라 다르게 적용해주면 된다.


infinte.gif


react-infinite-scroll-component

react-infinite-scroll-component 라이브러리를 사용했다. 마찬가지로 사용법이 간단하고 기존 프로젝트에 사용하기도 편해보여서 선정했다.


MyPage.js

import InfiniteScroll from 'react-infinite-scroll-component';

const MyPage = () => {
  const fetchDiaryList = async (page) => {
    const res = await axios.get(`/member/me/diaries?size=10&page=${page}`);

    const cards = res.data.data;
    const pagination = res.data.pageInfo;

    if (cardList.length > 0) {
      const previousCards = cardList;
      const newCards = cards;
      setCardList([...previousCards, ...newCards]);
    } else {
      setCardList(cards);
    }
    setPage(pagination.page + 1);
    setTotalPage(pagination.totalPages);
  };

  useEffect(() => {
    fetchDiaryList(page);
  }, []);

  return (
    <InfiniteScroll
      dataLength={items.length}
      next={fetchMoreData}
      hasMore={hasMore}
      loader={<h4>Loading...</h4>}
      endMessage={
        <p style={{ textAlign: 'center' }}>
          <b>마지막 페이지입니다.</b>
        </p>
      }
    >
      ...
    </InfiniteScroll>
  );
};

export default MyPage;

✔️ 마무리


처음 구현해보는 무한 스크롤이었다. 무한스크롤을 구현할 수 있을까? 걱정했지만, 실제 서비스에서 구현했고, 만족스러운 결과가 나와서 다행인 것 같다.

보완할 점이 있다면, 현재 데이터가 많지 않아서 일반 사용자가 봤을 때 무한 스크롤이 구현되고 있는지 모를 것 같다. 천천히 loading 될 수 있게 setTimeout을 적용해 할 것 같다.