ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Next.js의 dynamic import: 필요할 때만 불러와서 로딩 최적화하기
    개발 여정/FrontEnd 2025. 4. 29. 22:30

     

    Next.js의 dynamic import란?

     

    Next.js에서 로딩 최적화를 위해 제공하는 기술 중 하나로 dynamic import가 있다. dynamic import를 한 마디로, 아주 쉽게 요약하면 다음과 같이 말할 수 있다.

     

    "필요할 때만" 컴포넌트를 불러오는 것

     

     

    기본적으로 자바스크립트에서는 정적 import를 사용하면 모든 코드를 번들에 포함시킨다. 하지만 dynamic import를 사용하면, 특정 컴포넌트를 별도의 청크(Chunk)로 분리시켜 필요할 때만 불러온다.

     

    Dynamic import를 사용하는 이유

     

    1. 초기 로딩 속도 최적화
      • 페이지 최초 로딩 시 dynamic import에 포함된 요소는 부르지 않아서 시간 절약
    2. 렌더링 지연 관리
      • 가벼운 컴포넌트를 먼저 렌더링하고, 무거운 컴포넌트는 나중에 보여줄 수 있음
    3. UX(사용자 경험) 개선
      • dynamic import + loading 화면을 결합하면 무거운 컴포넌트를 로딩하더라도 흰 화면만 보여주는 로딩 시간을 줄여주기 때문에 사용자의 불안을 완화시켜줄 수 있음
    4. 번들 사이즈 관리
      • 한꺼번에 모든 컴포넌트를 내려받지 않아서, 네트워크 리소스를 아낄 수 있음
      • 필요한 순간에만 가져오기 때문에 서버 요청량도 자연스럽게 분산됨
      • 모바일 기기처럼 리소스가 약한 환경에서 특히 효과적

     

    dynamic import 기본 문법

    // page에서 SomeComponent 동적으로 불러오기
    
    import dynamic from 'next/dynamic';
    
    const SomeComponent = dynamic(() => import('./SomeComponent'));
    • page에서 dynamic import를 사용해서 SomeComponent를 호출한다.
    • 이때 SomeComponent는 별도 청크로 분리되어 필요한 순간에만 로드된다.

     

    무거운 컴포넌트를 동적 임포트하기

     

    용량이 적은 LightComponentHevyComponent 컴포넌트를 page에 임포트해온다고 해보자.

     

     

    정적 import를 사용했을 때

    import LightComponent from '../LightComponent';
    import HeavyComponent from '../HeavyComponent';
    
    export default function Page(){
        return (
            <LightComponent />
            <HeavyComponent />
        )
    }
    
    • 용량이 큰 HeavyComponent도 js번들에 포함됨
    • 전체 앱이 가벼워도 HeavyComponent 때문에 전체 로딩이 느려짐

     

     

    동적 import를 사용했을 때

    import LightComponent from '../LightComponent';
    
    const HeavyComponent = dynamic(() => import('../HeavyComponent'), {loading: () => <p>Loading...</p>,
    }); // loading 옵션을 포함해서 loding하는 동안 Loading... 메시지를 보여줄 수 있도록 함
    
    export default function Page(){
        return (
            <LightComponent />
            <HeavyComponent />
        )
    }
    
    • Page 번들에 직접 포함되지 않고 HeavyComponent는 다른 chunk로 분리돼서 관리됨
    • Page 번들 크기가 줄어들었기 때문에 전체 페이지를 로딩할 때 시간이 줄어듦 (흰 화면만 보여주는 시간이 줄어듦)
    • LightComponent를 먼저 보여줄 수 있음
    • dynamic import에 loading 옵션을 넣어줬기 때문에 HeavyComponent를 보여주는 동안 사용자에게 'Loading...' 메시지를 보여줘서 체감 대기 시간을 감축시킬 수 있음

     

     

    조건부 렌더링으로 '필요한 때'를 더 세밀하게 제어

    모달과 같이 사용자 인터랙션이 필요한 경우를 제어해서 사용할 수도 있다.

    const Modal = dynamic(() => import('./Modal'));
    
    export default function Home() {
        const [open, setOpen] = useState(false);
        return (
            <>
                <button onClick={() => setOpen(true)}>Open Modal</button>
                {open && <Modal />}
            </>
        )
    }
    • button이 클릭되기 전 open === false 상태에서는 Modal 컴포넌트가 import 되지 않음
    • 버튼이 클릭되면 open === true 가 되면서 dynamic import가 실행되고 이때부터 Modal 청크를 서버에서 받아옴

     

     

     

    정적 import를 사용했을 때, 동적 import를 사용했을 때를 플로우 차트로 정리해보면 이렇다.

     

    정적 import를 사용했을 때 flow

    페이지 진입
        ↓
    공통 컴포넌트 렌더링 시작
        ↓
    static import로 불러온 HeavyComponent도 js번들에 무조건 포함
        ↓
    페이지 열자마자 HeavyComponent 청크도 같이 다운로드
        ↓
    HeavyComponent가 화면에 안 보이는 상황이어도 무조건 다운로드

     

     

    동적 import를 사용했을 때 flow

    페이지 진입
        ↓
    공통 컴포넌트 렌더링 시작
        ↓
    dynamic import로 불러온 HeavyComponent는 청크로 따로 분리
        ↓
    초기에는 해당 청크는 다운로드 ❌
        ↓
    HeavyComponent가 화면에 실제 렌더링되려고 할 때
        ↓
    서버에 청크 요청 → 다운로드
        ↓
    HeavyComponent가 화면에 렌더링됨
    

     

    요약: dynamic import는 '컴포넌트 불러올 때'를 조절해서 로딩 속도를 줄여주는 도구

     

    결국 요약하자면 dynamic import의 역할은 다음과 같다.

    • 초기 로딩 속도를 줄여줘서 UX 관점에서 페이지가 늦게 뜨는 걸 막을 수 있음
    • 버튼, scroll을 이용해서 필요할 때만 특정 컴포넌트를 불러올 수 있음
    • 서버 리소스와 요청 시간도 분배가 가능하기 때문에 서버 쪽 부담도 줄여줄 수 있음
Designed by Tistory.