React.lazy 사용해보기

IT공부중·2020년 4월 6일
14

React

목록 보기
1/10
post-thumbnail

오늘은 React에 내장되어있는 lazy를 사용해 볼 것이다.

React.lazy는 코드분할을 하게 해준다. 코드 분할은 앱을 "지연 로딩"하게 도와주고 사용자들에게 획기적인 성능 향상을 하게 해줍니다. 앱의 코드 양을 줄이지 않고도 사용자가 필요하지 않은 코드를 불러오지 않게 하며 앱의 초기화 로딩에 필요한 비용을 줄여준다.

React.lazy는 아직 서버 사이드 렌더링을 하지 못 해서 서버사이드 렌더링을 위해서는 Loadable Components를 추천한다고 합니다.

일단 해보기 위해서 react 프로젝트를 만들었습니다.

create-react-app --typescript react-practice

그리고 나서

src폴더 밑에 components 폴더를 만들고 그 안에 다음과 같은 파일들을 만들었습니다.
LazyWrapper.tsx : Item 들을 그릴 컴포넌트
LazyItem.tsx : 각각의 Item 컴포넌트,
LazyImage.tsx : Item 안의 이미지를 그릴 컴포넌트,

그리고 db는 아니지만.. database 폴더를 만들고 그 안에 images.ts 파일을 만들었습니다.

src/database/images.ts

export interface Iimage {
    id: number,
    src: string,
    name: string,
}

export const images: Iimage[] = [
    {
        id : 0,
        src: 'https://images.unsplash.com/photo-1558979158-65a1eaa08691?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
        name: 'landscape'
    },
    {
        id : 1,
        src: 'https://images.unsplash.com/photo-1585858966753-e25673d9c46c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1051&q=80',
        name: 'snack'
    },
    {
        id : 3,
        src: 'https://images.unsplash.com/photo-1527304240506-c090883340d9?ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80',
        name: 'children'
    },
    {
        id : 4,
        src: 'https://images.unsplash.com/photo-1499323888381-7fd102a793de?ixlib=rb-1.2.1&auto=format&fit=crop&w=967&q=80',
        name: 'girl'
    },
    {
        id : 5,
        src: 'https://images.unsplash.com/photo-1485744455408-5363f9f7e1d3?ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60',
        name: 'butterfly'
    },
    {
        id : 6,
        src: 'https://images.unsplash.com/photo-1529429649738-cf96fc78378b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1055&q=80',
        name: 'man & sea'
    },
    {
        id : 7,
        src: 'https://images.unsplash.com/photo-1442528010304-834a5d4f3925?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60',
        name: 'sun flower'
    },
    {
        id : 8,
        src: 'https://images.unsplash.com/photo-1438109491414-7198515b166b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
        name: 'camera girl'
    },
    {
        id : 9,
        src: 'https://images.unsplash.com/photo-1474312650852-739d4703e766?ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80',
        name: 'camera man'
    },
    {
        id : 10,
        src: 'https://images.unsplash.com/photo-1586041828037-18790fa5bedd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60',
        name: 'cake'
    },
    {
        id: 11,
        src: 'https://images.unsplash.com/photo-1586053146627-018fff4b0e84?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=701&q=80',
        name: 'car'
    }
];

저작권 없이 사용할 수 있는 unsplash 이미지를 사용하였습니다. 이 이미지들을 불러와서 lazy 시켜볼 것입니다.

src/App.tsx

import React from 'react';
import logo from './logo.svg';
import './App.css';
import LazyWrapper from './components/LazyWrapper';

function App() {
  return (
    <div className="App">
      <LazyWrapper/>
    </div>
  );
}

export default App;

src/components/LazyWrapper.tsx

import React from 'react';
import { images } from '../database/images';
import LazyItem from './LazyItem';

const LazyWrapper = () => {
    return (
        <div>
            {images.map(image => 
                <LazyItem key={image.id} src={image.src} name={image.name}/>)}
        </div>
    );
};

export default LazyWrapper;

src/components/LazyItem.tsx

import React, {lazy, Suspense} from 'react';


export interface Iprops {
    src: string,
    name: string,
}

const LazyImage = lazy(() => import('./LazyImage')); // 이미지를 그리는 컴포넌트를 lazy 시켰습니다. lazy는 동적 import를 사용하는 함수를 인자로 넣어줘야합니다.

const LazyItem = ({src, name}: Iprops) => {
    return (
        <div>
            <Suspense fallback={<div>...loading</div>}> // 컴포넌트가 다 불러오기 전까지 ...loading이라는 컴포넌트를 보여줍니다. Suspense를 사용하지 않으면 에러가 납니다.
                <LazyImage src={src} name={name}/> // 다 불러와지면 해당 컴포넌트를 보여줍니다.
            </Suspense>
            {name}
        </div>
    );
};

export default LazyItem;

src/components/LazyImage.tsx

import React from 'react';
import { Iprops } from './LazyItem';

const LazyImage = ({src, name} :Iprops) => {
    return (
        <img src={src} alt={name}/>
    );
};

export default LazyImage;

그리고 npm start로 실행을 시켜주면 됩니다.

컴퓨터가 너무 빨라서 lazy loading이 되는걸 제대로 보기 힘들 수 있다. 개발자도구의 네트워크 창으로 가서 online으로 설정되어있는걸 Fast 3G로 바꾸면 이미지 부분이 ...loading이 떳다가 사진이 나오는걸 볼 수가 있을 것이다.

위에서부터 순서대로 불러오고 있는 것을 볼 수가 있다.

느낀점

공식 문서를 보면서 React.lazy가 있는 것을 보기만 하고 한번도 사용해보지 않았는데 이번에 lazy loading에 대해 관심을 가지게 되면서 사용해보게 되었다. 컴포넌트들이 하나씩 로딩이 되는게 신기했다.

하지만 image의 lazyloading에는 이것을 사용하기 보다 직접 만들어 사용하는게 나을 것 같다. 스크롤이 내려가서 해당 위치에 도착했을 때 이미지를 불러오기를 바랬는데 그렇게는 되지 않는 것 같다. 공식문서를 보아도 어느 곳에 코드분할을 도입할지 결정하는 것이 까다롭다고 한다. 그리고 가장 좋은 장소는 라우트라고 한다. 그래서 다음번에는 이미지 lazy loading을 따로 만들어 보는 것과 라우트에서 React.lazy를 사용해 보려고 한다.

profile
3년차 프론트엔드 개발자 문건우입니다.

1개의 댓글

comment-user-thumbnail
2022년 10월 12일

It is reported that it is hard to know where to add code division, even while consulting the official documentation. A route is supposedly the driving directions greatest option. So, I'll attempt to implement picture slow loading independently next time and utilize React.lazy in the route.

답글 달기