NextJS: dynamic import

hwisaac·2023년 2월 28일
0

Next.js

목록 보기
3/29

설명

Next.jsdynamic importimport() 구문을 사용하여 코드 분할(Code Splitting)을 구현하는 방법입니다.

코드 분할(code splitting)은 대규모 애플리케이션에서 필요한 JavaScript 코드를 더 작은 코드조각(chunk)으로 분할하는 기술입니다. 이를 통해 애플리케이션의 초기 구동 속도를 높일 수 있습니다.

e.g. Dynamic Import

Next.jsimport()를 사용하여 외부 라이브러리와 next/dynamic을 통해 React 컴포넌트의 지연 로드를 지원합니다. 지연 로드는 페이지를 렌더링하는 데 필요한 JavaScript 양을 줄여 초기 로딩 성능을 향상시킵니다. 컴포넌트나 라이브러리는 사용될 때만 JavaScript 번들에 포함되어 가져옵니다.

next/dynamicReact.lazySuspense의 복합 확장입니다. 컴포넌트는 Suspense 경계가 해결될 때까지 수화될 수 있습니다.

예제

next/dynamic을 사용하면 헤더 컴포넌트가 페이지의 초기 JavaScript 번들에 포함되지 않습니다. 페이지는 먼저 Suspense 대기 화면을 렌더링하고, Suspense 경계가 해결될 때 헤더 컴포넌트를 렌더링합니다.

import dynamic from 'next/dynamic'

const DynamicHeader = dynamic(() => import('../components/header'), {
  loading: () => <p>Loading...</p>,
})

export default function Home() {
  return <DynamicHeader />
}

참고: import('path/to/component')에서 경로는 명시적으로 작성되어야 합니다. 템플릿 문자열이나 변수가 될 수 없습니다. 또한 import()Next.jswebpack 번들/모듈 ID를 특정 dynamic() 호출에 일치시킬 수 있도록 dynamic() 호출 내부에 있어야 합니다. dynamic()React 렌더링 내부에서 사용할 수 없습니다. preloading이 작동하려면 모듈의 최상위 수준에서 표시해야 합니다. 이는 React.lazy와 유사합니다.

With named exports

이름 있는 내보내기를 동적으로 가져오려면, import()가 반환하는 Promise에서 내보내기를 반환하면 됩니다.

// components/hello.js
export function Hello() {
  return <p>Hello!</p>
}

// pages/index.js
import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(() =>
  import('../components/hello').then((mod) => mod.Hello)
)

With no SSR

서버 측 렌더링을 비활성화하려면 ssr 옵션을 사용하여 클라이언트 측에서 컴포넌트를 동적으로 로드할 수 있습니다. 이는 window와 같은 브라우저 API에 의존하는 외부 종속성이나 컴포넌트의 경우 유용합니다.

import dynamic from 'next/dynamic'

const DynamicHeader = dynamic(() => import('../components/header'), {
  ssr: false,
})

With external libraries

외부 라이브러리를 사용하는 경우, import()를 사용하여 필요한 시점에 라이브러리를 로드할 수 있습니다. 다음 예제에서는 사용자가 검색어를 입력할 때 fuse.js 외부 라이브러리를 동적으로 로드합니다.

import { useState } from 'react'

const names = ['Tim', 'Joe', 'Bel', 'Lee']

export default function Page() {
  const [results, setResults] = useState()

  return (
    <div>
      <input
        type="text"
        placeholder="Search"
        onChange={async (e) => {
          const { value } = e.currentTarget
          // Dynamically load fuse.js
          const Fuse = (await import('fuse.js')).default
          const fuse = new Fuse(names)

          setResults(fuse.search(value))
        }}
      />
      <pre>Results: {JSON.stringify(results, null, 2)}</pre>
    </div>
  )
}

위 코드에서는 fuse.js 라이브러리를 동적으로 불러오기 위해 import()를 사용합니다. 사용자가 검색어를 입력할 때, 입력 값으로부터 검색 결과를 출력합니다.

자세한 내용은 Next.js 공식 문서를 참고하세요.

예시

Next.js에서는 dynamic import 구문을 사용하면 코드를 동적으로 로드할 수 있습니다. 다음은 Next.js에서 코드 분할을 구현하는 간단한 예시입니다.

import dynamic from 'next/dynamic';

const DynamicComponent = dynamic(() => import('../components/DynamicComponent'));

function Home() {
  return (
    <div>
      <p>Home Page</p>
      <DynamicComponent />
    </div>
  );
}

export default Home;

위의 코드에서 DynamicComponent 컴포넌트는 dynamic() 함수를 사용하여 동적으로 로드됩니다.

dynamic() 함수의 인자로는 코드 분할을 적용할 모듈을 로드하는 함수를 전달합니다.

import() 구문은 Promise를 반환하므로, 로드할 모듈의 경로를 동적으로 지정할 수 있습니다.

dynamic() 함수는 로드된 모듈을 렌더링하는 React 컴포넌트를 반환합니다. 이를 통해 동적으로 로드된 모듈을 렌더링할 수 있습니다.

next/dynamic 모듈은 다양한 옵션을 제공하므로, 필요에 따라 옵션을 설정하여 동적으로 로드된 모듈을 커스터마이징할 수 있습니다.

언제 쓸까?

1. 초기 페이지 로딩 속도를 개선해야 할 때.

페이지 로딩 시간이 길어지는 문제를 해결하고자, 초기 로딩에 필요하지 않은 코드를 동적으로 로드하여 페이지 로딩 속도를 개선할 수 있습니다.

2. 기능별 코드 분할이 필요한 경우.

대규모 애플리케이션에서는 다양한 기능이 있을 수 있습니다. 이러한 경우 기능별로 코드를 분리하여 필요한 모듈만 로드할 수 있습니다.

3. 모바일 기기에서의 성능 개선이 필요한 경우.

모바일 기기에서는 페이지 로딩 속도가 느릴 수 있습니다. dynamic import를 사용하면 필요한 코드만 로드하여 초기 로딩 속도를 개선할 수 있습니다.

4. 대규모 애플리케이션의 코드 유지보수가 필요한 경우.

대규모 애플리케이션에서는 코드가 복잡해지는 문제가 발생할 수 있습니다. dynamic import를 사용하면 코드를 분리하여 유지보수성을 개선할 수 있습니다.

dynamic import는 위와 같은 상황에서 사용하면 효율적일 수 있습니다. 하지만 항상 dynamic import를 사용하는 것이 효율적인 것은 아닙니다.

단점

dynamic import를 사용하는 경우에도 일부 단점이 존재합니다.

1. dynamic import를 사용하면 추가적인 HTTP 요청이 발생합니다.

동적으로 로드된 모듈은 별도의 파일로 분리되어 서버에서 추가로 다운로드해야 하므로, 페이지 로딩 속도가 느려질 수 있습니다.

2. dynamic import는 코드가 복잡해질 수 있습니다.

코드 분할을 위해 여러 개의 dynamic import를 사용하는 경우, 코드가 길어지고 복잡해질 수 있습니다. 이 경우 코드 유지보수가 어려워질 수 있습니다.

3. dynamic import는 비동기적으로 동작합니다.

따라서 동적으로 로드된 모듈이 렌더링되기 전까지 컴포넌트가 비어있는 상태로 렌더링될 수 있습니다. 이는 사용자 경험을 해칠 수 있습니다.

4. dynamic import는 TypeScript에서 타입 체크가 어려울 수 있습니다.

TypeScript에서는 import() 구문을 지원하지만, 모듈의 타입 정보가 누락될 수 있습니다.

이러한 단점들을 고려하여, 적절한 상황에서 dynamic import를 사용하는 것이 좋습니다. 페이지 로딩 속도 개선을 위한 목적으로 사용할 때는 특히 추가적인 HTTP 요청이 발생하는 문제를 고려해야 합니다.

next/dynamic 모듈의 옵션

  1. ssr 옵션: ssr 옵션을 false로 설정하면 서버 사이드 렌더링을 하지 않습니다. 이 경우 클라이언트에서만 해당 모듈이 로드됩니다.

  2. loading 옵션: loading 옵션은 동적으로 로드되는 컴포넌트가 로딩 중일 때 보여줄 컴포넌트를 지정할 수 있습니다. 로딩 중일 때 보여줄 컴포넌트를 지정하지 않으면 기본 로딩 컴포넌트가 사용됩니다.

  3. delay 옵션: delay 옵션은 동적으로 로드되는 모듈이 로딩되기 전에 기다리는 시간을 지정할 수 있습니다. 이 값을 0으로 설정하면 즉시 로드를 시작합니다.

  4. timeout 옵션: timeout 옵션은 동적으로 로드되는 모듈이 로딩되는 시간을 제한할 수 있습니다. 이 값을 설정하면 일정 시간 내에 모듈이 로드되지 않으면 타임아웃이 발생합니다.

  5. webpack 옵션: webpack 옵션을 사용하면 동적으로 로드되는 모듈의 웹팩 설정을 변경할 수 있습니다.

위와 같은 옵션들을 통해 next/dynamic 모듈을 더욱 유연하게 사용할 수 있습니다.

0개의 댓글