본문 바로가기
FE/React

LazyLoad & PreLoad

by ideal_string 2022. 10. 24.

웹을 최적화 하는데는 여러가지 방법이 있다. 이번엔  그 여러 방법중 LazyLoad와 PreLoad를 정리해둔다. 두 친구는 말 그대로 늦게 불러오기와 미리 불러오기다. 웹을 화면에 로딩할 때 느린게, 좋을까 빠른게 좋을까? 당연히 후자다. 질문의 수준이 떨어진다고 뭐라해도 무방할 정도다. LazyLoad와 PreLoad는 이 당연한 것을 돕는다.

LazyLoad

특정 페이지에 들어갈 때 이미지가 많다고 다 업로드할 때까지 페이지가 안뜬다면 어떨까? 매우 답답해하며 바로 뒤로가기를 누른다. 필자가  자주그랬다. 뜨는걸 기다리는 게 해당 콘텐츠를 보기 원하는 마음보다 더 크게 다가왔기 때문이다. 이때 필요한 게 LazyLoad다. LazyLoad는 한번에 다 받아오지 않고 필요한 콘텐츠를 그때그때 받아 띄운다. 이미지 10개가 세로로 있다고 가정하자. 이 때 LazyLoad라면 화면에 보이는 하나만 불러온 상태에서 페이지를 먼저 띄운다. 그리고 스크롤을 내릴 때마다 해당 사진을 불러오는 형식이다. 이때 장점은 첫 페이지를 빠르게 띄울 수 있다는 점이다. 아래 영상은 LazyLoad 라이브러리를 통해 적용해본 모습.

LazyLoad

PreLoad

웹페이지를 제작하다보면 다른 페이지로 이동하지 않고 무조건 특정페이지로만 이동하게 되도록 디자인할 때가 있다. PreLoad는 그때 쓰면 좋을 방법이다. 이동할 페이지에 용량이 큰 파일이 있다면 금상첨화다. LazyLoad는 라이브러리를 찾았는데 PreLoad는 라이브러리를 찾지 못했다. 그래서 useEffect를 이용했다. 리액트에서 preload 개념은 다음과 같다. 1. 브라우저는 캐시에 파일 주소와 파일명이 같은 게 있으면 캐시에서 파일을 가져온다. 2. 따라서 처음 페이지에서 다음페이지에 사용할 이미지를 미리 불러오고 전역 장소에 넣어둔다. 3. 다음 페이지로 이동하면 불러야할 이미지와 같은 주소와 이미지가 이미 있으므로 해당 이미지를 바로 불러온다.

// 미리 불러올 이미지들을 먼저 로드하는 컴포넌트
export const PRELOADED_IMAGES: HTMLImageElement[] = [];

export const preloadImage = (images: string[]) => {
  images.forEach((el) => {
    const img = new Image();
    img.src = el;
    img.onload = () => {
      PRELOADED_IMAGES.push(img);
    };
  });
};
// 페이지 파일 컴포넌트
// 미리불러올 이미지들을 배열로 만들어뒀다.
const PRELOAD_IMAGES = [
  "https://upload.wikimedia.org/wikipedia/commons/9/96/%22Den_kjekke_gutt%22_-_6._Internasjonale_Akademiske_Vinterleker_%281939%29_%2840200856483%29.jpg",
];

export default function LazyloadPreload() {
  const router = useRouter();
  // 페이지가 로드될 때 미리불러올 이미지들을 로드한다.
  useEffect(() => {
    preloadImage(PRELOAD_IMAGES);
  }, []);
  


  return (
    <div>
    // 현재 페이지에 이미지 10개 랜덤으로 띄움.
      {new Array(10).fill(1).map((_, i) => (
        <div key={i}>
          <LazyLoad height={500}>
            <img src={`https://picsum.photos/500/500?random=${i}`} />
          </LazyLoad>
        </div>
      ))}
      // 버튼을 클릭하면 다음 페이지로 이동
      <button
        onClick={() => {
          router.push("/preload");
        }}
      >
        이미지 보여주기
      </button>
    </div>
  );
}

이미지를 로드할 컴포넌트를 별도로 만들었다. preloadImage가 실행되면 해당 주소에 있는 이미지를 다운로드하고 전역 변수인 PRELOADED_IMAGES에 넣어둔다. 그리고 각 페이지에선 미리 업로드를 원하는 이미지 주소 배열을 만들고, 해당 컴포넌트를 불러와 입력하는 방식이다. 리액트는 라우팅 방식이기 때문에 가능한 일이다.  아래 주소 이미지를 들어가보면 알겠지만 40MB가 넘는 고용량의 이미지 파일이다. 상황에 따라 한번에 뛰우기 어려울 수 있다. (위에 적용한 이미지 파일 주소) 아래 영상은 preload 없시 바로 접속했을 때와, preload 후 페이지에 접속한 것을 녹화한 영상이다.

 

preload 없는 페이지 로딩. 이미지 용량이 크다보니 첫 페이지가 뜰때까지 한참 걸린다.

 

preload된 모습. 첫페이지를 적당히 둘러보고 다음 페이지를 누르니 이미지 다운로드를 처음 시작한 게 아니라, 이동하자마자 용량이 큰 파일도 바로 보여준다.

마무리

접속 환경은 누구나 완전히 다르다. 나는 핸드폰을 5G 속도로 쓰고 있지만, 누군가는 여전히 3G, 2G일 수 있다. 집 인터넷 속도도 마찬가지다. 나는 500MB 속도를 쓰지만, 누구는 1G, 10G를 쓰거나 정반대로 100MB를 여전히 쓰고 있을 수 있다. 혹여나 옆옆집의 미세한 와이파이 신호로 연명하고 있는 사람이 있을지로 모를 터. 공공기관 오픈 와이파이 속도를 생각해도 무방하다. 이런 다양한 인터넷 속도를 다 맞출 순 없으나, 개발자의 몇가지 수고로움으로 해당 웹이 조금 더 사용자에게 쾌적하게 느껴진다면, 그게 개발자에게 가장 큰 보람이 아닐까 싶다. lazyload와 preload는 단순히 만들어내는 것에 멈추지 말고, 사용자가 더욱 편하다고 느낄 수 있는 수준까지 만들 수 있도록 노력해야겠다는 생각이 드는 기능이었다.

※ 잘못된 내용이 있을 경우 댓글로 알려주세요. 배우고 익히고 수정하겠습니다:)

'FE > React' 카테고리의 다른 글

Optimistic-UI  (0) 2022.10.25
Shallow Routing  (0) 2022.10.25
HOC & HOF  (0) 2022.10.19
전역 상태 관리  (0) 2022.10.09
Lifecycle(feat. DOM)  (0) 2022.10.03