코드 스플리팅(Code Splitting)은 하나의 큰 JavaScript 번들을 여러 청크(chunk)로 나누는 빌드 기법이고, 동적 임포트(Dynamic Import, import())는 그 청크를 실제로 필요해질 때 받아오는 방법이다. 나누는 것은 "어떻게", 불러오는 시점은 "언제"의 문제다.
- 브라우저는 JS를 받기만 하는 게 아니라 파싱·컴파일·실행까지 해야 한다. 그래서 초기 번들이 작을수록 저사양 모바일에서 체감 차이가 크다(Core Web Vitals)
import()를 만나면 번들러가 별도 청크를 만든다. React에서는React.lazy(() => import('./Chart')), Next.js에서는next/dynamic을 쓴다- 자르는 단위는 보통 라우트, 또는 지도·차트·에디터·동영상 플레이어처럼 처음엔 필요 없는 무거운 기능이다
- 너무 잘게 자르면 클릭할 때마다 다운로드를 기다리게 된다. 이 대기는 prefetch·preload로 줄인다
- 안 쓰는 코드를 아예 빼는 트리 셰이킹과는 다른 기법이고, 둘은 같이 쓴다
const Editor = dynamic(() => import('@/components/Editor'), {
loading: () => <p>에디터 로딩 중...</p>,
})Next.js App Router에서
라우트 단위 분할은 기본으로 해 준다. 그래서 컴포넌트마다 dynamic()을 붙이기보다 아래 순서로 생각한다.
- 서버 컴포넌트로 둘 수 있나? 그러면 클라이언트로 JS를 아예 보내지 않는다
- 첫 화면에 필요한 클라이언트 컴포넌트인가? 그러면 그냥 import한다
- 무겁고 나중에 써도 되나? 그때
next/dynamic을 쓴다
번들을 줄이는 다른 방법은 번들 크기 줄이기에 정리했다.