
SPA (Single Page Application)은 파일 하나와 다수의 자바스크립트 코드 그리고 CSS 파일로 구성된다. 수백, 수천 개의 컴포넌트를 작성할 때 만들어진 자바스크립트 파일은 모두 빌드 과정을 거쳐서 하나 또는 몇 개의. js 파일로 빌드된다. 브라우저는 첫 화면을 로딩하기 위해 브라우저가 웹 서버에 경로를 요청하면, 웹 서버는 하나의. js파일을 브라우저에 넘기게 되고. 이를 받은 브라우저는 모든 화면을 위한. js 파일을 로딩합니다. 이때 지연 시간이 발생해서 사용자는 첫 화면을 보기까지 기다리는 시간이 길어질 수 있습니다.
레이지 로딩은 중요도가 떨어지거나 당장 화면에 보이지 않는 요소들의 로딩을 우선적으로 시행하지 않으면서 웹페이지 로딩 퍼포먼스를 최적화하는 기술을 의미한다. 최초 페이지 로딩 시간을 개선하고 당장 화면에 표시되지 않는 이미지, 영상 등의 리소스를 나중에 로딩하면서 최초 데이터 전달 양을 감소시키는 것이다.
레이지 로딩을 적용하면, 화면에 당장 보여지지 않거나 아직 유저의 인터렉션이 일어나지 않은 특정 리소스들의 로딩을 딜레이시킬 수 있다. 당장 필요한 컨텐츠들이 먼저 로딩되고, 다른 리소스들은 필요해질 때 로딩되기 때문에 웹 페이지의 퍼포먼스를 눈에 띄게 개선할 수 있다. 레이지 로딩은 주로 이미지와 영상들에 적용된다. 다이나믹 컴포넌트, 방대한 양의 스크립트, 외부 위젯 등 다른 컨텐츠에도 적용될 수 있다.
검색 엔진 크롤러(ex) Googlebot)는 웹 페이지를 탐색하고 콘텐츠를 인덱싱하여 검색 결과에 반영한다. 크롤러는 페이지를 로드할 때 HTML 소스 코드에서 콘텐츠를 찾고, 자바스크립트를 실행하여 동적으로 로드된 콘텐츠도 인덱싱한다. 그러나 모든 크롤러가 자바스크립트를 실행하는 것은 아니며, 자바스크립트 로딩 시간이 너무 길면 일부 콘텐츠를 인덱싱하지 못할 수도 있다. 레이지 로딩을 사용하는 경우, 콘텐츠가 사용자가 스크롤할 때까지 로드되지 않기 때문에 크롤러가 이러한 콘텐츠를 인덱싱하지 못할 수 있다. 따라서 키워드 및 비지니스 정보와 같은 SEO 대상 컨텐츠에는 지연 로딩을 사용하지 않는 것이 좋다.
placeholder는 주로 실제 콘텐츠가 로드되기 전에 사용자에게 임시로 표시되는 요소를 의미한다. 콘텐츠가 로드될 때까지 페이지가 비어 있는 상태로 보이지 않게 하고, 사용자가 로딩 중임을 인지할 수 있도록 도와줍니다. placeholder는 사용자가 실제 콘텐츠가 곧 로드될 것임을 인지하게 하여 페이지가 더 빠르게 로드된다는 느낌을 줍니다.
- 로딩 스피너 (Loading Spinner)
보통 회전하는 아이콘이나 애니메이션을 사용하여 사용자에게 로딩 중임을 알림- 프로그레스바 (progress bar)
로딩의 진행 상황을 시각적으로 표현하여 사용자가 기다려야 하는 시간을 직관적으로 파악
- 스켈레톤 스크린 (Skeleton Screen)
실제 콘텐츠의 레이아웃을 모방한 회색 블록이나 선들로 구성된 플레이스홀더를 사용하여 사용자에게 로드될 콘텐츠의 구조를 예측하게 함
- Blurred Image Placeholder
저해상도 이미지를 미리 로드하여 블러 처리한 후, 실제 고해상도 이미지가 로드될 때 교체

사용자가 페이지 하단에 도달했을 때 리소스가 계속 로드되는 방식이다. 무한 스크롤은 scroll 이벤트, Intersection observer API를 통해 구현할 수 있다. scroll 이벤트는 스크롤을 내릴 때마다 발생되는 단점이 있고, 이를 개선하기 위해서는 debounce, throttle를 사용해야하는 번거로움이 있었다. scroll 이벤트의 단점을 개선한 Intersection observer API가 등장하였다. 무한스크롤을 구현했던 기록은 따로 남겨두었기 때문에 생략한다.
웹 페이지 내 이미지는 두 가지 방법으로 로드할 수 있습니다. 바로 <img> 태그와 CSS 속성 중 background를 이용하는 것입니다. <img>태그를 이용한 방법이 좀 더 자주 사용된다.
img 태그를 이용한 레이지 로딩은 이미지가 뷰포트에 들어올 때 이미지를 로드한다. 자바스크립트 이벤트를 이용하거나 Intersection Observer API를 사용하여 쉽게 구현할 수 있다.
초기 설정: img 태그의 src 속성에 이미지를 직접 설정하지 않고, data-src 같은 커스텀 데이터 속성에 이미지 URL을 저장한다.
가시성 관찰: Intersection Observer를 사용하여 img 요소가 뷰포트에 들어오는지 관찰한다.
이미지 로드: 이미지가 뷰포트에 들어오면 data-src 속성의 값을 src 속성으로 이동하여 이미지를 로드한다.
페이지가 로드되면 모든 img 태그는 placeholder 이미지나 빈 상태로 존재한다. 사용자 스크롤로 인해 이미지가 뷰포트에 들어올 때까지 Intersection Observer가 이를 감시한다. 이미지가 뷰포트에 들어오면, Intersection Observer가 이벤트를 트리거하여 data-src 속성의 값을 src 속성으로 설정한다. 브라우저는 src 속성의 URL을 통해 이미지를 로드하고 렌더링한다.
<img class="lazy" data-src="https://via.placeholder.com/300x200" alt="Example Image 1">
HTML5에서 도입된 loading 속성을 사용하여 이미지와 iframe 요소의 지연 로드를 브라우저 자체에서 처리하는 방법으로 자바스크립트 코드를 작성할 필요 없이, 간단하게 HTML 속성을 추가하여 레이지 로딩을 구현할 수 있다. loading 속성은 img와 iframe 요소에 사용할 수 있으며, 세 가지 값을 가질 수 있습니다
lazy: 요소가 뷰포트에 거의 도달할 때 로드한다.
eager: 요소를 즉시 로드한다. 이는 기본 동작과 동일하다.
auto: 브라우저가 로드 방식을 결정한다.
<img src="example.jpg" loading="lazy" alt="..." />
<iframe src="example.html" loading="lazy"></iframe>
CSS background image를 로드하기 위해서는 현재 문서 내 DOM 노드에 CSS 스타일이 적용되는지 여부를 결정하기 위해 CSSOM(CSS Object Model)과 DOM(Document Object Model) Tree를 구성하는 것이 필요하다. 문서 내 엘리먼트에 CSS의 background image가 적용되어 있지 않다면, 브라우저는 background image를 로드하지 않고, 엘리먼트에 CSS 규칙에 적용될 경우 브라우저가 이미지를 로딩하게 될 것이다.
CSS background 속성을 사용한 레이지 로딩은 div 등의 요소에 배경 이미지를 설정할 때 유용하다. 자바스크립트와 Intersection Observer API를 사용하여 배경 이미지를 동적으로 설정할 수 있다.
초기 설정: div 요소 등에 배경 이미지 URL을 data-bg 같은 커스텀 데이터 속성에 저장합니다.
가시성 관찰: Intersection Observer를 사용하여 div 요소가 뷰포트에 들어오는지 관찰합니다.
배경 이미지 로드: 요소가 뷰포트에 들어오면 data-bg 속성의 값을 background-image 속성으로 설정하여 이미지를 로드합니다.
페이지가 로드되면 모든 div 요소는 배경 이미지 없이 placeholder로 존재한다. 사용자 스크롤로 인해 div 요소가 뷰포트에 들어올 때까지 Intersection Observer가 이를 감시한다. 요소가 뷰포트에 들어오면, Intersection Observer가 이벤트를 트리거하여 data-bg 속성의 값을 background-image 속성으로 설정한다. 브라우저는 background-image 속성의 URL을 통해 이미지를 로드하고 렌더링한다.
<div class="bg-container lazy-bg" data-bg="https://via.placeholder.com/300x200"></div>
코드에서 당장 사용하는 부분만을 로딩하고, 현재 필요하지 않은 코드 부분은 따로 분리시켜 나중에 로드함으로써 로딩시간을 개선하는 것.
React.lazy: 동적으로 컴포넌트를 임포트하여, 컴포넌트가 필요할 때까지 로드하지 않도록 한다.
Suspense: lazy 로드된 컴포넌트가 로드될 때까지 로딩 상태를 관리한다. 로딩 중에 보여줄 fallback UI를 설정할 수 있다.
지연 시간이 길어진다면 사용자에게 로딩 중임을 나타내는 화면을 보여주는 것이 좋다. 이런 화면을 fallback UI라고 부르며 이 기능을 손쉽게 구현할 수 있도록 도와주는 컴포넌트가 Suspense 컴포넌트다. 리액트 Suspense는 컴포넌트 내부에서 사용하는 데이터가 로딩 중이거나 데이터 로딩에 실패한 경우 예외를 throw하면 그 컴포넌트가 렌더링할 준비가 되지 않았다고 인식하고 fallback UI를 렌더링한다. 처리가 완료되어 Promise가 정상적인 데이터를 응답하면 비로소 컴포넌트의 렌더링을 수행하여 데이터가 화면에 나타나게 된다.
import React, { Suspense, lazy } from 'react';
// React.lazy를 사용하여 컴포넌트를 동적으로 임포트
const LazySomeComponent = lazy(() => import('./SomeComponent'));
const App = () => {
return (
<div>
<h1>Lazy Loading Components in React</h1>
{/* Suspense로 감싸서 로딩 중에 보여줄 폴백 UI를 설정 */}
<Suspense fallback={<div>Loading...</div>}>
<LazySomeComponent />
</Suspense>
</div>
);
};
export default App;
또 다른 방법으로 react-lazyload는 React 프로젝트에서 컴포넌트에 레이지로딩을 쉽게 적용할 수 있게 해주는 라이브러리이다. React.lazy는 리엑트의 빌트인 기능이다. Suspense 컴포넌트를 사용해서 컴포넌트를 비동기적으로 로딩해준다. 즉, 컴포넌트의 렌더링이 로딩이 끝날때까지 보여지지 않게 된다는 것이다. 반면에, react-lazyload는 IntersectionObserver API를 사용한다. 뷰포트에 들어와서 눈에 보여야될 경우에 발동된다는 것이다.
React.lazy는 컴포넌트가 뷰포트에 보여지는지 여부와 상관 없이 레이지로딩을 적용하고 싶을 때 사용한다. 매우 여러 컴포넌트에 React.lazy를 적용할 경우 오히려 성능에 부정적인 영향이 있을 수 있다는 점을 감안해야 한다.
레이지로딩(lazy loading)이란?
[React] 레이지 로딩이란?
브라우저 로딩 동안의 사용자 경험을 개선하는 방법들
웹 성능 최적화를 위한 Image Lazy Loading 기법