본문 바로가기
SPA/React

[React] 지연 로딩(Lazy Loading)으로 최적화하기

by J4J 2021. 8. 18.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 지연 로딩으로 최적화하는 방법에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

지연 로딩이란?

 

지연 로딩이라고 하는 것은 말 그대로 로딩을 바로 하지 않고 지연시켰다가 로딩을 나중에 해준다는 뜻입니다.

 

 

 

간단한 예시로 더 자세하게 말씀드리겠습니다.

 

예를 들어 한 페이지에 많은 양의 사진이 사용된다고 가정해보겠습니다.

 

요즘 만들어지는 사진들은 용량이 크기 때문에 화면을 처음 로드할 때 많은 양의 사진을 한 번에 로드를 하는 것은 서비스의 속도를 늦추는 요인이 될 수 있습니다.

 

심지어 이렇게 로드되는 많은 사진들이 한 화면에 전부 보이는 일은 드뭅니다.

 

 

 

그럼 만약 페이지를 로드할 때 페이지에서 사용되는 모든 사진을 한 번에 로드하는 것이 아니라 실제 화면에 보이는 사진들만 로드를 한다면 어떨까요?

 

화면에서 볼 수 있는 사진의 양은 한정적이기 때문에 로드해야 되는 사진의 개수는 눈에 띄게 줄어들게 될 것입니다.

 

결과적으로 처음 로드할 때 화면에 보여지는 이미지들만 로드를 해주고 나머지 사진들은 로드되는 것을 지연시켰다가 스크롤을 내리면서 나머지 사진들이 보이게 될 때 추가적인 로드를 해준다면 사용자에게 더 빠른 속도로 화면을 보여줄 수 있게 됩니다.

 

그리고 이런 결과를 만드는 방법이 지연 로딩을 이용하는 것입니다.

 

 

 

지연 로딩을 구현하는 방법은 여러 방법이 있는 것 같습니다.

 

저는 그 중 자바스크립트에서 API로 제공해주는 IntersectionObserver을 이용하여 구현해 볼 것이고 또한 타입 스크립트를 곁들여 보겠습니다.

 

 

반응형

 

 

지연 로딩 적용 방법

 

구현을 하기에 앞서 화면에서 불러올 사진들을 업로드해보겠습니다.

 

이미지 없음

 

티스토리

 

 

 

이미지 없음 사진 같은 경우는 프로젝트 내부에 존재할 정적 사진으로 실제 보일 이미지가 화면에 나타나기 전에 보이고 있을 사진입니다.

 

해당 사진은 굳이 다운로드를 하여 사용하실 필요 없이 가지고 계시는 다른 사진으로 대체해도 무방합니다.

 

 

 

티스토리 사진 같은 경우는 서버를 통해 가져올 이미지 화면입니다.

 

해당 이미지의 url은 https://blog.kakaocdn.net/dn/ck83td/btrcwxeJJm6/ugdgkwZcq1YTnNEnksZ4z1/img.jpg로 설정되어 있습니다.

 

위의 url을 이용하여 지연 로딩을 테스트해보겠습니다.

 

 

 

[ 1. 지연 로딩이 적용될 이미지 파일 생성 ]

 

해당 파일을 불러와 사용할 곳은 App.tsx입니다.

 

그렇기 때문에 App.tsx와 동일한 위치에 lazyImage.tsx라는 이름으로 생성하겠습니다.

 

import * as React from 'react';
import NoImage from './image/noImage.gif';

interface ILazyImage {
    src: string;
}

const LazyImage: React.FC<ILazyImage> = ({ src }): JSX.Element => {
    // state
    const [isLoading, setIsLoading] = React.useState<boolean>(false); // 실제 화면에 보여지고 있는지 여부를 확인

    // ref
    const imgRef = React.useRef<HTMLImageElement>(null); // 이미지 태그 요소
    const observer = React.useRef<IntersectionObserver>(); // IntersectionObserver 변수

    // useEffect
    React.useEffect(() => {
        observer.current = new IntersectionObserver(intersectionOberserver); // 인스턴스 생성
        imgRef.current && observer.current.observe(imgRef.current); // 이미지 태그 관찰 시작
    }, [])

    // IntersectionObserver 설정
    const intersectionOberserver = (entries: IntersectionObserverEntry[], io: IntersectionObserver) => {
        entries.forEach((entry) => {
            if (entry.isIntersecting) { // 관찰되고 있는 entry가 보여지게 된 다면
                io.unobserve(entry.target); // 관찰 종료
                setIsLoading(true); // 로딩 체크
            }
        })
    }

    return (
        // 화면에 보여지기 전이라면 NoImage, 화면에 보여지고 있다면 src에 해당하는 이미지
        <img ref={imgRef} src={isLoading ? src : NoImage} style={{width: '200px', height: '160px'}} />
    )
}

export default LazyImage

 

 

 

혹시나 말씀드리는 부분인데 타입 스크립트에서는 설정에 따라 이미지 파일을 불러오기 위해 타입을 지정해줘야 합니다.

 

타입 지정이 안돼 있으면 에러 표시가 계속 나오는데 설정하는 방법에 대해 아직 포스팅을 하지 않았기 때문에 포스팅을 하게 되면 링크를 걸도록 하겠습니다.

 ※ 링크 추가 → 타입 스크립트 환경에서 정적 이미지 파일 사용하기

 

 

 

[ 2. App.tsx에서 화면 그리기 ]

 

App.tsx에서는 lazyImage를 이용하여 화면에 사진이 노출되도록 구현해보겠습니다.

 

예시를 들기 위해 동일한 사진을 100장 그려보겠습니다.

 

import * as React from 'react';
import LazyImage from './lazyImage';

const App = (): JSX.Element => {
    return (
        <div>
            {[...Array(100)].map((val, index) => {
                return (
                    <LazyImage key={index} src='https://blog.kakaocdn.net/dn/ck83td/btrcwxeJJm6/ugdgkwZcq1YTnNEnksZ4z1/img.jpg' />
                )
            })}
        </div>
    )
}

export default App;

 

 

 

 

실행 화면

 

위와 같이 구현을 해보고 실행을 해보면 다음과 같은 결과를 볼 수 있습니다.

 

실행 화면

 

 

 

처음 화면에는 티스토리 사진이 명확히 보이고 있지만 스크롤을 빠르게 내려보면 이미지 없음 사진에서 티스토리 사진으로 변경되는 것을 확인할 수 있습니다.

 

 

 

 

참조

 

react lazyloading 이미지 컴포넌트 구현하기

 

 

 

 

 

 

이상으로 지연 로딩으로 최적화하는 방법에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글