본문 바로가기
  • 프론트엔드 개발자 세오세오 | Frontend dev Seo
Learn to Code

레이지로딩(lazy loading)이란?

by CEOSEO 2023. 7. 27.
728x90
반응형

레이지로딩 (lazy loading)이란?

레이지 로딩이란 중요도가 떨어지거나 당장 화면에 보이지 않는 요소들의 로딩을 우선적으로 시행하지 않으면서 웹페이지 로딩 퍼포먼스를 최적화하는 기술을 의미한다.

 

레이지 로딩의 목적은 (1) 최초 페이지 로딩 시간을 개선하고 당장 화면에 표시되지 않는 이미지, 영상 등의 리소스를 나중에 로딩하면서 (2) 최초 데이터 전달 양을 감소시키는 것이다.

 

웹페이지를 로딩하는 기존 방식은 모든 리소스들을 한번에 받는 것이다. 이렇게하면 최초 로딩 시간이 더 커지게 되는데, 이러한 로딩 시간 증가는 인터넷 연결 속도가 느린 지역이나 디바이스를 사용할 때 특히 더 두드러지게 체감된다.

 

이러한 문제를 해결하기 위해 사용할 수 있는 테크닉이 레이지 로딩인 것이다. 레이지 로딩을 적용하면, 화면에 당장 보여지지 않거나 아직 유저의 인터렉션이 일어나지 않은 특정 리소스들의 로딩을 딜레이시킬 수 있다. 이러한 방식을 적용하면, 당장 필요한 컨텐츠들이 먼저 로딩되고, 다른 리소스들은 필요해질 때 로딩되기 때문에 웹 페이지의 퍼포먼스를 눈에 띄게 개선할 수 있다.

 

레이지 로딩은 주로 이미지와 영상들에 적용된다. 만약 레이지 로딩 테크닉이 페이지에 적용된 경우, HTML 마크업의 이미지 태그는 최초론 플레이스홀더 또는 이미지의 적은 해상도 버전을 적용하게 된다. 유저가 스크롤을 내려서 해당 이미지가 뷰포트에 들어오게 될 경우, 자바스크립트가 그 플레이스홀더를 대체하면서 제대로된 사이즈의 이미지를 로딩하게 되는 것이다.

 

이미지나 영상 뿐만 아니라, 다이나믹 컴포넌트, 방대한 양의 스크립트, 외부 위젯 등 다른 컨텐츠에도 적용될 수 있다. 이렇듯 용량이 컨텐츠들을 추후 필요해질 때 추가 로딩하도록 개발을 진행한다면 최초 페이지 로딩 시간을 줄이고 사용자 경험을 개선할 수 있다.

 

이제 레이지로딩이 무엇인지 알았으니, 어떻게 적용하면되는지 살펴보도록하자! ✨

 

 

 

레이지로딩 사용법 4가지

1. Next.js: next/dynamic 사용하기

next/dynamic import 함수는 컴포넌트가 필요할 때만 로딩하도록 해준다. 최초로 로딩되어야 하는 양을 줄여주기 때문에 웹사이트의 로딩 속도를 개선할 수 있다.

 

next/dynamic을 사용하기 위해선, 이걸 적용하고 싶은 컴포넌트의 import statement를 next/dynamic 함수로 감싸야 한다.

 

import React, {useState} from 'react';
import dynamic from 'next/dynamic'

const AboutUs = dynamic(() => import('./About'), {ssr: false})
// => dynamic으로 AboutUs 함수를 감싼 모습
// => {ssr: false}는 Next.js에게 이 AboutUs는 서버 사이드 렌더링 하지말라고 알려주는 부분.
// 왜 하지 말아야하냐면, 이 컴포넌트는 필요해진 경우에만 로딩되어야 하기 때문에 서버가 미리 렌더할 필요가 없음.


const Home = () => {
  const [isLoaded, setIsLoaded] = useState(false)
  
  return (
    <div>
     <h1>This is Home Page.</h1>
     { isLoaded && <AboutUs/> }
    </div>
  )
}

export default Home;

 

 

2. React

next/dynamic 말고, 리엑트의 빌트인 레이지 로딩 기능을 사용할 수도 있다. next/dynamic이 있지만 여전히 선택 가능한 옵션이다.

 

리엑트에선 React.lazy() 메소드를 사용하면 된다. 이걸로 레이지로딩을 적용하고 싶은 컴포넌트의 import statement를 감싸면 되는 것이다.

 

import React, { useState } from 'react';

const AboutUs = React.lazy(() => import('./About'));

const Home = () => {
  const [isLoaded, setIsLoaded] = useState(false)
  
  return (
    <div>
      <h1>Title!!!!!</h1>
      { isLoaded && <AboutUs/>}
    </div>
  )
}

export default Home;

 

React.lazy() 메소드는 프로믹스 객체를 리턴한다. 이 프로믹스 객체는 로딩이 되었을 때 컴포넌트를 뿜뿜한다. 이 프로미스 객체를 사용해서 언제 이 뿜뿜되는 컴포넌트를 렌더할지 컨트롤할 수 있게 되는 것이다.

 

next/dynamic과 React.lazy()를 사용하는 두 가지 경우 모두, 레이지로딩을 적용할 컴포넌트를 언제 로딩할지 지정해주기 위해 state를 사용해야 한다. 이를 통해 어떤 조건이 갖추어져야 특정 컴포넌트를 렌더링할지 컨트롤할 수 있게 된다.

 

 

 

* 만약 레이지로딩하고 싶은 친구가 이미지일 경우?!

=> next/image를 사용한 레이지로딩

 

레이지로딩하고 싶은 친구가 이미지일 경우, next/image를 사용하면 더 간단하게 레이지로딩 테크닉을 적용할 수 있다. Next.js의 Image 컴포넌트 안엔 레이지로딩과 이미지의 최적화 기능이 이미 탑제되어 있기 때문이다✨

 

next/image의 사용법은 매우 간단하다. 단순히 HTML img 태그를 Next.js의 image 컴포넌트로 교체해서 사용하면 된다.

 

import Image from 'next/image';

function MyBeautifulComponent() {
  return (
    <div>
      // 기존 HTML 플레인 image 태그를 사용했을 떄
        <img src="/path/to/image.jpg" alt="a plain image" />
      // Next.js의 귀염뽀짝 Image 컴포넌트로 사용했을 때
        <Image src="/path/to/image.jpg" alt="a plain image" width={500} height={300} />
    </div>
  )
}

 

 

 

3. 별도 라이브러리: react-lazyload

react-lazyload는 리엑트 프로젝트에서 컴포넌트에 레이지로딩을 쉽게 적용할 수 있게 해주는 라이브러리이다. 이 아이는 컴포넌트가 뷰포트에 들어와서 사용자 화면에 보여져야할 때에 Intersection Observer API를 사용해서 컴포넌트를 로딩하게 해준다.

 

npm install react-lazyload

 

import React, { useState } from 'react';
import ReactLazyload from 'react-lazyload';

const Image = ReactLazyload(() => import('./image.jpg'));

const App = () => {
  const [isLoaded, setIsLoaded] = useState(false);

  return (
    <div className="App">
      <h1>My App</h1>
      {isLoaded && <Image />}
    </div>
  );
};

 

🧐 React.lazy와의 차이점은?

  • lazy는 리엑트의 빌트인 기능이다. Suspense 컴포넌트를 사용해서 컴포넌트를 비동기적으로 로딩해준다. 이게 뭔말이냐면, 컴포넌트의 렌더링이 로딩이 끝날때까지 보여지지 않게 된다는 것이다. 최초로 렌더되는 자바스크립트 양의 감소를 통해 앱의 성능을 개선시켜준다.
  • 반면에, react-lazyload는 IntersectionObserver API를 사용한다. 뷰포트에 들어와서 눈에 보여야될 경우에 발동된다는 것이다.
  •  

🤓 언제 React.lazy말고 react-lazyload를 선택해야할까?

  • react-lazyload는 뷰포트에 보여지게 되느냐 아니냐 여부와 최초 자바스크립트 양을 줄여준다는 것에서 시너지가 필요할 때 선택하면 된다.
  • React.lazy는 컴포넌트가 뷰포트에 보여지는지 여부와 상관 없이 레이지로딩을 적용하고 싶을 때 사용한다. 다만 주의할 점은, 매우 여러 컴포넌트에 마구잡이로 React.lazy를 적용할 경우 오히려 성능에 부정적인 영향이 있을 수 있다는 점을 감안해야 한다.

 

 

 

요약하자면, react-lazyload와 React.lazy는 아래와 같은 차이점들이 있다:

 

  react-lazyload React.lazy()
IntersectionObserver API 사용 여부 Yes No
뷰포트에 보여지는 컴포넌트들에만 레이지 로딩 적용 가능 Yes No
여러개의 컴포넌트에 레이지로딩을 적용할 경우 오히려 앱 성능에 부정적인 영향을 줄 수 있음 No Yes

 

4. 별도 라이브러리 없이 Intersection Observer API

별도로 라이브러리 추가할 필요 없이, 만약 뷰포트 관련으로 보여지는 놈들만 로딩하겠어!! 하는 마음가짐이라면 Intersection Observer API를 사용해서 레이지로딩을 구현할 수도 있다.

 

 

import { useEffect, useRef } from 'react';

function MyAwesomeComponent () {
  const targetRef = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
           // 여기서 컴포넌트나 리소스를 로딩
        }
      })
    })

    if (targetRef.current) {
      observer.observe(targetRef.current)
    }

    // 옵저버 정리
    return () => {
      observer.disconnect();
    }
    
  }, [])
  

return (
  <div ref={targetRef}>
   // 레이지로딩되는 컨텐츠들은 요기
  </div>
)
}

 

Intersection Observer API에 대한 추가 정보는 요 글을 참고하면 된다:

2021.08.18 - [Learn to Code] - Intersection Observer API: 스크롤링에 따라 엘리먼트가 짠!하고 나타나게 해주는 애니메이션을 만들고 싶을 때

 

Intersection Observer API: 스크롤링에 따라 엘리먼트가 짠!하고 나타나게 해주는 애니메이션을 만들고

채용 과제를 만들면서 틈틈이 파이널 프로젝트 개선 작업을 진행하고 있다. 사각사각의 랜딩 페이지를 수정하면서 커스텀 훅을 하나 만들었는데, 이 훅이 하는 일이 바로 마치 스크롤링을 할 때

seo-tory.tistory.com

 

 

 

728x90
반응형

댓글