헤더 영역 바로가기 컨텐츠 영역 바로가기 푸터 영역 바로가기
썸네일

React에서 로딩중일때 임시로 표시할 스켈레톤 UI를 구현해보자!

CODi

2024-10-13 00:33

리액트로 작업하던 토이 프로젝트가 있었는데 API에서 데이터를 받아오는 동안 빈 화면으로 냅두는건 좀 아니다 싶어 스켈레톤 UI를 구현해보기로 했습니다!

스켈레톤 UI 활용 예시

1. SCSS 작성

우선 스켈레톤 UI 가 어느 상황에서든 잘 확장해 사용 할 수 있도록 flex를 사용해 CSS 구조를 잡았습니다.

또한 스켈레톤 UI 가 표시되는 동안에 심심하지 않도록 'skeleton-loading' 이라는 로딩도 같이 넣어두었어요.

.skeleton-wrapper {
    width:100%;
    height:100%;
    display:flex;
    gap:2.0rem;

    > div {
        flex:1;

        .skeleton {
            background:var(--color-gray-800);
            margin :10px 0;
            border-radius:4px;
            animation: skeleton-loading 1.5sinfiniteease-in-out;

            &.text {
                width :100%;
                height :12px;
            }

            &.title {
                width:50%;
                height:20px;
                margin-bottom:15px;
            }

            &.avatar{
                width:100px;
                height:100px;
                border-radius:0.8rem;
            }

            &.thumbnail {
                width:100%;
                height:auto;
                aspect-ratio:1/1;/* 정사각형 비율 */
            }
        } 
    }
}

// 로딩을 위한 애니메이션
@keyframes skeleton-loading {
    0% {
        background-color:var(--color-gray-800);
    }

    50% {
        background-color:var(--color-gray-700);
    }

    100% {
        background-color:var(--color-gray-800);
    }
}

2. 구현에 사용할 JSX 구성

2-1. Main.jsx : 상태 값에 따른 스켈레톤 UI 표시 여부 구현

꼭 저와 똑같이 할 필요는 없기에 자신의 상황에 맞게 변형해 사용하시면 되요!

일단 저는 설명을 위해 useState를 사용해 availiable 이라는 state의 기본값이 false 상태일 경우 SkeletonItem이라는 스켈레톤 컴포넌트를 표시하고

availiable의 값이 true로 바뀔때는 원래 표시하려고 했던 내용들을 표시하도록 하였습니다.

이때 중요한점은 로딩할때 보여줄 SkeletonItem의 내용은 원본과 비슷한 구조여야 합니다.

그래야 로딩이 끝나고 이질감이 없겠죠?

import React, { useState, useEffect, Fragment } from 'react';
import SkeletonComponents from '@/components/common/SkeletonComponents';

// 메인
const main = () => {
    const [availiable, setAvailiable] = useState(false);

    return(
        <Fragment>
            { availiable ?
                <div className="container">            
        ​            <div className="container-inner">
                        <h1>제목입니다</h1>
                        <p>설명입니다.</p>
                    </div>
                </div>
                : <SkeletonItem/>
            }
        </Fragment>
    )
}


// 공통 : 스켈레톤 UI
const SkeletonItem = () => {
    return (
        <div className="skeleton-wrapper">
            <div className="skeleton-playlist">
                <SkeletonComponents type="title" />
                <SkeletonComponents type="text" />
            </div>
        </div>
    );
};


export default main

2-2 SkeletonComponents.jsx : 타입별로 표시해줄 스켈레톤 컴포넌트 만들기

scss를 작성할때 text, title 등등 타입별 스타일이 있었는데

여기서 타입별로 props를 통해 해당하는 스타일을 이용할거기 때문에

class명을 props로 받은 값을 이용 하도록 해주었습니다.

const SkeletonComponents = ({ type }) => {
    const classes=`skeleton ${type}`;

    return <div className={classes} />;
};


export default SkeletonComponents;

마치며

이와 같은 과정을 거치면

처음에 보여드렸던 예시와 똑같이 만들어졌을거에요

간단하게만 보여드렸지만 좀 더 디테일한 구조는 한번 이것저것 하나씩 추가시켜 만들어 나가 보세요!