React.lazy() 는 리액트에서 컴포넌트를 레이지 로딩 하는데 사용된다.
레이지 로딩은 코드 스플리팅을 위해 사용되는 기능으로, 애플리케이션 번들을 작은 chunk로 분할하여 필요한 시점에 필요한 모듈을 동적으로 로드하는 방법이다.
lazy loading (지연 로딩)을 사용하는 이유는
주로 무한 스크롤 할 경우 스크롤 시 보여지는 부분을 lazy loading 시켜 유저가 직접적으로 보게 되는 경우에만 해당 컴포넌트를 불러오게 만들어서
초기 화면 로딩 시간을 줄여준다.
Lazy loading 을 활용해서 필요한 경우에만 이미지를 불러오는 기능을 만들어보자.
input field 의 value가 image 의 alt 값과 일치하는 경우에만 이미지를 불러오도록 구현하였다.
리액트에서 lazy 를 불러온 후 lazy에 사용할 컴포넌트를 가져온다.
delayForDemo 는 해당 컴포넌트를 불러오는데 1초 정도가 걸리는 컴포넌트가 있다고 가정하기 위함이다.
import React, { lazy, Suspense, useState } from "react";
const LazyImage = lazy(() => delayForDemo(import("./LazyImage.tsx")));
function delayForDemo(promise) {
return new Promise((resolve) => {
setTimeout(resolve, 1000);
}).then(() => promise);
}
lazy에 사용할 컴포넌트를 정의한다.
참고로 img 태그의 loading에 lazy 값을 넣으면 해당 이미지를 lazy loading 할 수 있다.
하지만 현재 코드에서는 어차피 렌더 되는 경우에만 이미지를 보여줌으로 굳이 넣어주지 않아도 된다.
const LazyImage: React.FC<LazyImageProps> = (props) => {
const { src, alt } = props;
return (
<div style={{ height: "200vh" }}>
<img style={{ height: "100vh" }} src={src} alt={alt} loading={"lazy"} />
</div>
);
};
인풋 값을 받고 해당 인풋 값과 image.alt 값이 일치하는 것만을 보여주는 코드이다.
map 을 돌려서 값이 일치하는 것만 보여준다.
<div>
<input
style={{ border: "solid" }}
onChange={(e) => setText(e.target.value)}
/>
<span> {text}</span>
{images.map((image, index) => {
if (image.alt !== text) return;
return (
<Suspense fallback={<div>Loading...</div>} key={index}>
<LazyImage src={image.src} alt={image.alt} />
</Suspense>
);
})}
</div>
lazy 를 사용한 경우에는 화면처럼 처음에 로딩이 뜨는 것을 볼 수 있었는데 이는 처음 해당 컴포넌트를 불러오고 있다는 의미이다. 그리고 게속해서 다른 이미지를 불러오게 하자 loading... 이 뜨지 않았는데 이는 해당 컴포넌트를 이미 불러와서 loading... 이 뜨지 않은 것이다.
95% 의 유저가 쓰지 않는 기능인데 5%의 유저만 해당 기능을 쓰는 경우 해당 5%의 유저가 리소스에 접근할 때 lazy 를 사용하면 불필요한 번들을 줄일 수 있다.