컴포넌트 lazy loading 과 preloading

googboy·2025년 6월 19일

컴포넌트 로딩 전략: Lazy Loading과 Preloading

웹 애플리케이션의 성능 최적화는 사용자 경험에 직접적인 영향을 미치는 중요한 요소입니다. 특히 컴포넌트 로딩 전략은 초기 로딩 시간과 전반적인 애플리케이션 성능에 큰 영향을 줍니다. 이 글에서는 두 가지 주요 로딩 전략인 Lazy Loading과 Preloading의 적절한 사용 케이스를 구분하여 살펴보겠습니다.

Lazy Loading(지연 로딩)

Lazy Loading은 컴포넌트나 리소스를 실제로 필요할 때까지 로딩을 지연시키는 기술입니다. 이 방식은 초기 로딩 시간을 단축시키고 필요한 리소스만 로드하여 성능을 최적화합니다.

Lazy Loading이 적합한 케이스

  1. 초기 화면에 보이지 않는 컴포넌트

    • 스크롤해야 보이는 콘텐츠
    • 탭이나 아코디언 내부의 콘텐츠
    • 모달이나 팝업 컴포넌트
  2. 조건부로 렌더링되는 컴포넌트

    • 특정 사용자 액션 후에만 표시되는 컴포넌트
    • 관리자 전용 기능이나 대시보드
  3. 큰 용량의 라이브러리를 사용하는 컴포넌트

    • 차트, 그래프, 지도 등 무거운 라이브러리에 의존하는 컴포넌트
  4. 라우트 기반 컴포넌트

    • 다른 페이지로 이동할 때만 필요한 컴포넌트

예시: React에서의 Lazy Loading

// 모달 컴포넌트 지연 로딩 예시
import React, { lazy, Suspense, useState } from 'react';

// 모달 컴포넌트를 lazy loading으로 불러옴
const ModalWindow = lazy(() => import('./ModalWindow.js'));

function App() {
  const [isModalVisible, setIsModalVisible] = useState(false);

  return (
    <div>
      <button onClick={() => setIsModalVisible(true)}>모달 열기</button>
      
      {/* 모달이 필요할 때만 로딩 */}
      {isModalVisible && (
        <Suspense fallback={<div>로딩 중...</div>}>
          <ModalWindow onClose={() => setIsModalVisible(false)} />
        </Suspense>
      )}
    </div>
  );
}

이 예시에서는 사용자가 '모달 열기' 버튼을 클릭할 때만 ModalWindow 컴포넌트가 로드됩니다. 이는 초기 로딩 시간을 단축시키고, 필요할 때만 리소스를 사용하게 합니다

Preloading(사전 로딩)

Preloading은 사용자가 특정 컴포넌트나 리소스를 요청하기 전에 미리 로드하는 기술입니다. 이 방식은 사용자가 실제로 컴포넌트를 요청했을 때 즉시 표시할 수 있어 사용자 경험을 향상시킵니다.

Preloading이 적합한 케이스

  1. 사용자가 곧 방문할 가능성이 높은 라우트

    • 메인 네비게이션의 주요 페이지
    • 사용자 흐름에서 다음 단계로 예상되는 페이지
  2. 자주 사용되는 중요 컴포넌트

    • 검색 기능, 장바구니, 결제 프로세스 등 핵심 기능
  3. 초기 로딩 후 백그라운드에서 로드할 수 있는 컴포넌트

    • 첫 페이지 로드 후 유휴 시간에 로드할 수 있는 컴포넌트
  4. 네트워크 상태가 좋을 때 미리 로드할 컴포넌트

    • 네트워크 상태를 감지하여 조건부로 미리 로드

예시: React에서의 Preloading

React에서 Preloading을 구현하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법들을 살펴보겠습니다.

1. 마우스 호버 시 Preloading

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

// lazyWithPreload 함수 구현
function lazyWithPreload(importFunction) {
  const Component = lazy(importFunction);
  Component.preload = importFunction;
  return Component;
}

// 모달 컴포넌트를 lazyWithPreload로 불러옴
const ModalWindow = lazyWithPreload(() => import('./ModalWindow.js'));

function App() {
  const [isModalVisible, setIsModalVisible] = useState(false);

  return (
    <div>
      <button 
        onClick={() => setIsModalVisible(true)}
        onMouseEnter={() => ModalWindow.preload()} // 마우스 호버 시 미리 로드
      >
        모달 열기
      </button>
      
      {isModalVisible && (
        <Suspense fallback={<div>로딩 중...</div>}>
          <ModalWindow onClose={() => setIsModalVisible(false)} />
        </Suspense>
      )}
    </div>
  );
}

이 예시에서는 사용자가 버튼 위에 마우스를 올렸을 때 ModalWindow.preload()를 호출하여 컴포넌트를 미리 로드합니다. 사용자가 버튼 위에 마우스를 올리고 클릭하기까지의 시간(약 0.2~0.5초)을 활용하여 컴포넌트를 미리 로드함으로써 클릭 시 즉시 표시할 수 있습니다.

2. 컴포넌트 마운트 후 Preloading

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

// lazyWithPreload 함수 구현
function lazyWithPreload(importFunction) {
  const Component = lazy(importFunction);
  Component.preload = importFunction;
  return Component;
}

// 모달 컴포넌트를 lazyWithPreload로 불러옴
const ModalWindow = lazyWithPreload(() => import('./ModalWindow.js'));
const HeavyComponent = lazyWithPreload(() => import('./HeavyComponent.js'));

function App() {
  const [isModalVisible, setIsModalVisible] = useState(false);

  // 컴포넌트 마운트 후 백그라운드에서 미리 로드
  useEffect(() => {
    // 페이지 로드 후 중요 컴포넌트 미리 로드
    ModalWindow.preload();
    
    // 네트워크 상태가 좋을 때만 추가 컴포넌트 로드
    if (navigator.connection && navigator.connection.effectiveType === '4g') {
      HeavyComponent.preload();
    }
  }, []);

  return (
    <div>
      <button onClick={() => setIsModalVisible(true)}>
        모달 열기
      </button>
      
      {isModalVisible && (
        <Suspense fallback={<div>로딩 중...</div>}>
          <ModalWindow onClose={() => setIsModalVisible(false)} />
        </Suspense>
      )}
    </div>
  );
}

이 예시에서는 useEffect를 사용하여 컴포넌트가 마운트된 후 백그라운드에서 중요 컴포넌트를 미리 로드합니다. 또한 네트워크 상태를 확인하여 좋은 상태일 때만 추가 컴포넌트를 로드하는 조건부 로딩도 구현할 수 있습니다.

3. react-dom의 preload API 사용 (React 18 이상)

import React, { useState } from 'react';
import { preload } from 'react-dom';

function App() {
  const [showComponent, setShowComponent] = useState(false);

  // 컴포넌트에서 사용할 리소스 미리 로드
  preload("https://example.com/important-font.woff2", { as: "font" });
  preload("https://example.com/critical-script.js", { as: "script" });

  return (
    <div>
      <button onClick={() => setShowComponent(true)}>
        컴포넌트 표시
      </button>
      
      {showComponent && <ImportantComponent />}
    </div>
  );
}

React 18에서 도입된 preload API를 사용하면 폰트, 스크립트, 스타일시트 등 컴포넌트에서 사용할 리소스를 미리 로드할 수 있습니다. 이는 컴포넌트가 렌더링되기 전에 필요한 리소스를 미리 준비하여 렌더링 속도를 향상시킵니다.

로딩 전략 선택 시 고려사항

로딩 전략을 선택할 때는 다음 요소들을 고려해야 합니다:

  1. 사용자 행동 패턴

    • 사용자가 어떤 순서로 기능을 사용하는지 분석
    • 사용 빈도가 높은 기능 식별
  2. 리소스 크기와 복잡성

    • 컴포넌트의 크기와 의존성 평가
    • 로딩 시간이 사용자 경험에 미치는 영향 고려
  3. 네트워크 환경

    • 대상 사용자의 일반적인 네트워크 상태 고려
    • 모바일 사용자를 위한 최적화 전략 수립
  4. 애플리케이션 특성

    • SPA(Single Page Application)와 MPA(Multi Page Application)에 따른 전략 차별화
    • 서버 사이드 렌더링(SSR) 여부에 따른 접근 방식 조정

결론

Lazy Loading과 Preloading은 상호 배타적인 전략이 아니라 상호 보완적인 전략입니다. 초기 로딩 시간을 최소화하기 위해 Lazy Loading을 적용하고, 사용자 경험을 향상시키기 위해 중요한 컴포넌트는 Preloading하는 균형 잡힌 접근 방식이 이상적입니다

최적의 로딩 전략은 애플리케이션의 특성, 사용자 행동 패턴, 그리고 비즈니스 요구사항에 따라 달라질 수 있으므로, 실제 사용자 데이터와 성능 측정을 기반으로 지속적으로 최적화하는 것이 중요합니다

0개의 댓글