Next.js
의dynamic import
는import()
구문을 사용하여 코드 분할(Code Splitting)을 구현하는 방법입니다.
코드 분할(code splitting)은 대규모 애플리케이션에서 필요한 JavaScript 코드를 더 작은 코드조각(chunk)으로 분할하는 기술입니다. 이를 통해 애플리케이션의 초기 구동 속도를 높일 수 있습니다.
e.g. Dynamic Import
Next.js
는 import()
를 사용하여 외부 라이브러리와 next/dynamic
을 통해 React
컴포넌트의 지연 로드를 지원합니다. 지연 로드는 페이지를 렌더링하는 데 필요한 JavaScript
양을 줄여 초기 로딩 성능을 향상시킵니다. 컴포넌트나 라이브러리는 사용될 때만 JavaScript
번들에 포함되어 가져옵니다.
next/dynamic
은 React.lazy
와 Suspense
의 복합 확장입니다. 컴포넌트는 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.js
가webpack
번들/모듈 ID를 특정dynamic()
호출에 일치시킬 수 있도록dynamic()
호출 내부에 있어야 합니다.dynamic()
는React
렌더링 내부에서 사용할 수 없습니다.preloading
이 작동하려면 모듈의 최상위 수준에서 표시해야 합니다. 이는React.lazy
와 유사합니다.
이름 있는 내보내기를 동적으로 가져오려면, 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)
)
서버 측 렌더링을 비활성화하려면 ssr
옵션을 사용하여 클라이언트 측에서 컴포넌트를 동적으로 로드할 수 있습니다. 이는 window
와 같은 브라우저 API
에 의존하는 외부 종속성이나 컴포넌트의 경우 유용합니다.
import dynamic from 'next/dynamic'
const DynamicHeader = dynamic(() => import('../components/header'), {
ssr: false,
})
외부 라이브러리를 사용하는 경우, 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
모듈은 다양한 옵션을 제공하므로, 필요에 따라 옵션을 설정하여 동적으로 로드된 모듈을 커스터마이징할 수 있습니다.
페이지 로딩 시간이 길어지는 문제를 해결하고자, 초기 로딩에 필요하지 않은 코드를 동적으로 로드하여 페이지 로딩 속도를 개선할 수 있습니다.
대규모 애플리케이션에서는 다양한 기능이 있을 수 있습니다. 이러한 경우 기능별로 코드를 분리하여 필요한 모듈만 로드할 수 있습니다.
모바일 기기에서는 페이지 로딩 속도가 느릴 수 있습니다. dynamic import
를 사용하면 필요한 코드만 로드하여 초기 로딩 속도를 개선할 수 있습니다.
대규모 애플리케이션에서는 코드가 복잡해지는 문제가 발생할 수 있습니다. dynamic import
를 사용하면 코드를 분리하여 유지보수성을 개선할 수 있습니다.
dynamic import
는 위와 같은 상황에서 사용하면 효율적일 수 있습니다. 하지만 항상 dynamic import
를 사용하는 것이 효율적인 것은 아닙니다.
dynamic import를 사용하는 경우에도 일부 단점이 존재합니다.
동적으로 로드된 모듈은 별도의 파일로 분리되어 서버에서 추가로 다운로드해야 하므로, 페이지 로딩 속도가 느려질 수 있습니다.
코드 분할을 위해 여러 개의 dynamic import
를 사용하는 경우, 코드가 길어지고 복잡해질 수 있습니다. 이 경우 코드 유지보수가 어려워질 수 있습니다.
따라서 동적으로 로드된 모듈이 렌더링되기 전까지 컴포넌트가 비어있는 상태로 렌더링될 수 있습니다. 이는 사용자 경험을 해칠 수 있습니다.
TypeScript
에서는 import()
구문을 지원하지만, 모듈의 타입 정보가 누락될 수 있습니다.
이러한 단점들을 고려하여, 적절한 상황에서 dynamic import
를 사용하는 것이 좋습니다. 페이지 로딩 속도 개선을 위한 목적으로 사용할 때는 특히 추가적인 HTTP
요청이 발생하는 문제를 고려해야 합니다.
next/dynamic
모듈의 옵션ssr
옵션: ssr
옵션을 false
로 설정하면 서버 사이드 렌더링을 하지 않습니다. 이 경우 클라이언트에서만 해당 모듈이 로드됩니다.
loading
옵션: loading
옵션은 동적으로 로드되는 컴포넌트가 로딩 중일 때 보여줄 컴포넌트를 지정할 수 있습니다. 로딩 중일 때 보여줄 컴포넌트를 지정하지 않으면 기본 로딩 컴포넌트가 사용됩니다.
delay
옵션: delay
옵션은 동적으로 로드되는 모듈이 로딩되기 전에 기다리는 시간을 지정할 수 있습니다. 이 값을 0으로 설정하면 즉시 로드를 시작합니다.
timeout
옵션: timeout
옵션은 동적으로 로드되는 모듈이 로딩되는 시간을 제한할 수 있습니다. 이 값을 설정하면 일정 시간 내에 모듈이 로드되지 않으면 타임아웃이 발생합니다.
webpack
옵션: webpack
옵션을 사용하면 동적으로 로드되는 모듈의 웹팩 설정을 변경할 수 있습니다.
위와 같은 옵션들을 통해 next/dynamic
모듈을 더욱 유연하게 사용할 수 있습니다.