Next js에서 번들 크기를 줄이는 방법
Source: Dev.to
번역하려는 전체 텍스트를 제공해 주시면, 요청하신 대로 한국어로 번역해 드리겠습니다. 코드 블록, URL 및 마크다운 형식은 그대로 유지하겠습니다.
번들 크기가 중요한 이유
무거운 번들은 사용자가 앱과 상호작용하기도 전에 앱을 느리게 만듭니다.
- 첫 로드가 느려짐: 브라우저가 JavaScript를 다운로드하고 파싱하는 데 시간이 더 오래 걸립니다.
- 코어 웹 바이탈 감소: Google은 SEO 순위를 위해 성능을 중요하게 생각합니다.
- 모바일 경험 악화: 느린 연결 환경에서는 큰 번들이 고통스럽습니다.
번들 크기를 줄이는 것은 사용자 만족도와 검색 순위에 직접적인 영향을 미칩니다.
Source: …
Step 1: Analyze Your Bundle
블랜드를 무작정 최적화할 수는 없습니다. 먼저, 번들 안에 무엇이 들어 있는지 확인하세요.
@next/bundle-analyzer 사용하기:
npm install @next/bundle-analyzer
next.config.js 업데이트:
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({});
분석기 실행:
ANALYZE=true npm run build
번들의 트리맵이 생성됩니다.
**source-map-explorer**도 시도해 보세요 – 파일별로 번들 크기에 얼마나 기여하는지 시각화해 주는 또 다른 도구입니다.
목표는 수정하기 전에 가장 큰 문제 요소들을 파악하는 것입니다.
단계 2: 더 스마트하게 가져오기
전체 라이브러리를 가져와야 할 필요가 없는데 함수 하나나 두 개만 필요할 때 전체를 가져오는 실수를 흔히 저지릅니다.
Bad way:
import _ from 'lodash';
const result = _.isEmpty(obj);
Better way:
import isEmpty from 'lodash/isEmpty';
const result = isEmpty(obj);
두 번째 방법은 필요한 부분만 포함합니다. Next.js는 또한 트리‑쉐이킹과 next.config.js의 optimizePackageImports 옵션을 지원하여 라이브러리의 사용되지 않는 부분을 자동으로 제거합니다.
Step 3: 동적 임포트 사용
모든 코드를 첫 페이지 렌더링 시에 로드할 필요는 없습니다. 상호작용 후에만 사용된다면 나중에 로드하세요.
동적 컴포넌트 임포트:
import dynamic from 'next/dynamic';
const Chart = dynamic(() => import('../components/Chart'), {
ssr: false,
loading: () => <p>Loading...</p>,
});
이렇게 하면 차트 코드가 초기 번들에 포함되지 않습니다. 동적 임포트는 다음과 같은 경우에 적합합니다:
- 모달
- 차트 / 그래프
- 서드파티 위젯
- 거의 방문하지 않는 섹션
Step 4: 무거운 코드를 서버에 두기
Next.js는 서버와 클라이언트 코드를 분리합니다. 그 분리를 현명하게 활용하세요.
- 데이터를
getServerSideProps또는getStaticProps에서 가져오고, 모든 것을 클라이언트에서 가져오지 마세요. - 브라우저에서 실행될 필요가 없는 로직은 Server Components(App Router)를 사용하세요.
- 불필요한 비즈니스 로직을 클라이언트에 전달하지 마세요.
이렇게 하면 번들 크기가 줄어들고, 보안이 향상되며, 성능이 개선됩니다.
Step 5: Externalize or Replace Heavy Dependencies
Some libraries are simply too big. You have two choices: lazy‑load them or replace them.
- Charts: Use a lighter charting library or load the heavy one on demand.
- Date libraries: Replace Moment.js with Day.js or date‑fns.
- React → Preact: Some projects swap React for Preact for smaller bundles (check compatibility first).
In next.config.js, you can also externalize server‑only packages so they don’t end up in the client bundle.
Step 6: Optimize Assets (Not Just JavaScript)
이미지, 폰트 및 CSS를 최적화하면 전체 성능이 향상됩니다.
- Images: Next.js
<Image>컴포넌트를 사용하여 레이지 로딩, 압축 및 반응형 크기 조정을 적용합니다. - Fonts: 필요한 문자와 굵기만 가져오고, Google Fonts를 자체 호스팅하는 것을 고려합니다.
- CSS: Tailwind의 purge 기능이나 기타 CSS 트리‑쉐이킹을 활성화하여 사용되지 않는 스타일을 제거합니다.
Step 7: 지속적인 모니터링
한 번 최적화하는 것만으로는 충분하지 않습니다. 새로운 의존성이나 기능이 추가될 때마다 무게가 늘어날 수 있습니다.
- 예산 설정:
size-limit와 같은 도구는 번들이 정의된 크기를 초과하면 경고합니다. - 분석기 재실행: 배포하기 전에 CI 워크플로의 일부로 포함시키세요.
- 성능 추적: Lighthouse 점수, LCP(최대 콘텐츠 페인트), TTI(인터랙티브까지 시간)를 모니터링하세요.
빠른 체크리스트
@next/bundle-analyzer로 분석합니다.- 큰 의존성을 가벼운 대안으로 교체합니다.
- 필요한 것만 가져옵니다.
- 비핵심 UI에는
next/dynamic을 사용합니다. - 무거운 로직은 서버 측에 둡니다.
- 이미지, 폰트, CSS를 최적화합니다.
- 번들 크기를 지속적으로 모니터링합니다.
Final Thoughts
Next.js에서 번들 크기를 줄이는 것은 매 바이트마다 집착하는 것이 아니라, 실제로 중요한 것에 집중하는 것입니다: 더 빠른 로드 시간, 더 나은 SEO, 그리고 더 만족스러운 사용자. 큰 효과를 주는 것부터 시작하세요—컴포넌트를 지연 로드하고 의존성을 정리하는 것—그 다음에 import 최적화와 자산 처리로 미세 조정합니다. 이러한 관행을 적용하면 앱이 얼마나 부드럽고 반응성이 뛰어난지 뚜렷한 차이를 느낄 수 있을 것입니다.