Next.js에서 번들 사이즈 최적화하기

개발

Next.js에서 번들 사이즈 최적화하기

Bundle analyzer 설정

먼저, 번들 사이즈 분석을 위한 @next/bundle-analyzer를 설치합니다.

pnpm add -D @next/bundle-analyzer

그리고 next.config.js에 다음과 같이 설정합니다.

const analyzing = process.env.ANALYZE === "true";
 
/** @type {import('next').NextConfig} */
const nextConfig = {
    // Your Next.js config
};
 
if (analyzing) {
    const withBundleAnalyzer = require("@next/bundle-analyzer")({
        enabled: true,
    });
    module.exports = withBundleAnalyzer(nextConfig);
} else {
    module.exports = nextConfig;
}

ANALYZE 환경 변수를 true로 설정하면 번들 사이즈 분석이 실행됩니다.
ANALYZE=true pnpm build와 같이 실행하거나, package.json에 해당 스크립트를 추가하시면 됩니다.

이러면 .next 디렉토리에 analyze 디렉토리가 추가되며, client.html, edge.html, nodejs.html 파일들이 생성됩니다.

Analyze 결과 - 큰 파일 존재

이제 이 파일들을 분석하면서 애플리케이션 덩치를 줄여 나가면 됩니다.

Dynamic import

Next.js에서는 코드 스플리팅을 위해 dynamic 함수를 제공합니다.
dynamic 함수를 사용하면 페이지 로딩 시 필요한 컴포넌트만 로드할 수 있습니다.

import dynamic from "next/dynamic";
 
const DynamicComponent = dynamic(() => import("../components/DynamicComponent"));

절대적인 기준이랄 게 없긴 하지만, 500KB 이상인 파일이나, 150KB 정도가 넘어가는 파일이라도 페이지 로딩에 정말 필수적이지 않다면 dynamic을 통해 로드하는 편입니다.

Tree shaking

분석 결과를 보면, node_modules에 여러 패키지들이 한 파일에 묶여 있는 것을 확인할 수 있습니다.
만약 barrel file을 사용하고 있다면 더 거대하게 파일이 생성되어 있을 수도 있습니다.

이땐, 간단하게 package.jsonsideEffects 필드를 추가해 주시면 됩니다.

{
  // ...
  "sideEffects": false
  // ...
}

만약 Turborepo같은 monorepo를 사용하신다면, 분리된 패키지에도 해당 옵션을 활성화해 주셔야 합니다.
또한 패키지를 제작하신다면 ESM으로 만드셔서, Tree-shakable하게 만드시는 것도 중요합니다.

또한, 제대로 최적화되지 않은 거대한 패키지가 있다면 optimizePackageImports를 추가하는 것도 방법입니다.
lodash-es, @mui/material같은 덩치 크기로 유명한 패키지들은 기본적으로 설정되어 있습니다.

Conclusion

Analyze 결과 - Tree shaking

이정도 까지만 진행하셔도, 번들 사이즈를 상당히 줄일 수 있습니다.

상술했듯, 여전히 초기 로딩 속도 최적화를 하고, 사용자 경험을 향상시키기 위해 번들 사이즈 최적화는 중요한 이슈입니다.
이번 글에서 다룬 번들 분석, Dynamic import, Tree shaking 같은 최적화 방법들은 실제로 적용하기 쉽고, 그 효과도 즉각적으로 확인할 수 있는 방법들입니다.

번들 사이즈를 최적화하는 것은 단순히 파일 크기를 줄이는 것 이상으로, 코드를 효율적으로 관리하고 유지보수하는데도 큰 도움이 됩니다.
이를 통해 더욱 빠르고 사용자 친화적인 웹 애플리케이션을 구축할 수 있습니다.
꾸준히 번들 사이즈를 모니터링하고 최적화하는 습관을 기른다면, 사용자에게 더 나은 성능과 경험을 제공할 수 있을 것입니다.

Report an issue