번들 크기 줄이기

번들 크기 줄이기 (Minimizing bundle size)

비용이 많이 드는 import 패턴을 피해서 번들 크기를 줄이고 개발 성능을 개선하는 방법을 함께 알아봐요. Material UI를 쓰다 보면 번들 크기가 신경 쓰이기 마련인데, 올바른 import 습관만 잡아도 확실히 달라진답니다.

출처: 문서

본문

비용이 많이 드는 import 패턴을 피해서 번들 크기를 줄이고 개발 성능을 개선하는 방법을 알아보세요.

번들 크기는 중요해요 (Bundle size matters)

Material UI의 메인테이너들은 번들 크기를 매우 진지하게 다뤄요. 모든 커밋마다, 모든 패키지와 그 패키지의 핵심 부분에 대해 크기 스냅샷(size snapshot)을 찍는데요. 여기에 dangerJS를 결합하면, 모든 Pull Request에서 상세한 번들 크기 변경을 살펴볼 수 있어요.

배럴 import 피하기 (Avoid barrel imports)

최신 번들러는 프로덕션 빌드에서 이미 사용하지 않는 코드를 tree-shake 처리하므로, 최상위(top-level) import를 쓸 때는 그걸 걱정할 필요가 없어요. 진짜 성능 문제는 개발(development) 중에 발생하는데, @mui/material이나 @mui/icons-material 같은 배럴 import(barrel imports) 가 시작 및 리빌드 시간을 눈에 띄게 느리게 만들 수 있어요.

// ✅ 권장
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';

이렇게 쓰는 대신:

// ❌ 개발 시 더 느림
import { Button, TextField } from '@mui/material';

특히 @mui/icons-material을 쓸 때 이런 차이가 두드러지는데, named import는 기본 경로 기반(default path-based) import보다 최대 6배까지 느릴 수 있어요:

// 🐌 개발 시 더 느림
import { Delete } from '@mui/icons-material';

// 🚀 개발 시 더 빠름
import Delete from '@mui/icons-material/Delete';

이 방식은 패키지에서 불필요한 부분을 로드하지 않도록 해주고, 특별한 설정도 필요 없어요. 또한 공식 예제와 데모에서 모두 기본으로 사용하는 방식이기도 하죠.

기존 코드베이스에 배럴 import가 있다면, 아래 path-imports codemod를 사용해서 코드를 마이그레이션하세요:

npx @mui/codemod@latest v5.0.0/path-imports <path>

ESLint로 모범 사례 강제하기 (Enforce best practices with ESLint)

실수로 깊은(deep) import를 하는 것을 막으려면 ESLint 설정에서 no-restricted-imports 규칙을 사용할 수 있어요:

// .eslintrc
{
  "rules": {
    "no-restricted-imports": [
      "error",
      {
        "patterns": [{ "regex": "^@mui/[^/]+$" }]
      }
    ]
  }
}

VS Code의 배럴 파일 자동 import 피하기 (Avoid VS Code auto-importing from barrel files)

VS Code가 @mui/material에서 자동으로 import하지 못하게 하려면, VS Code 프로젝트 설정에서 typescript.autoImportSpecifierExcludeRegexes를 사용할 수 있어요:

// .vscode/settings.json
{
  "typescript.preferences.autoImportSpecifierExcludeRegexes": ["^@mui/[^/]+$"]
}

Next.js 13.5 이상을 사용 중인가요? (Using Next.js 13.5 or later?)

Next.js 13.5 이상을 쓰고 있다면 잘 되고 있는 거예요. 이 버전들은 optimizePackageImports 옵션을 통해 자동 import 최적화를 포함하고 있어요. 덕분에 import를 최적화하기 위한 수동 설정이나 Babel 플러그인이 더는 필요 없답니다.

parcel 사용하기 (Using parcel)

Parcel은 기본적으로 package.json의 "exports"를 해석하지 않아요. 그 결과 항상 우리 라이브러리의 commonjs 버전으로 해석되어 버리죠. 우리의 ESM 버전을 최적으로 활용하려면, packageExports 옵션을 활성화하세요.

// ./package.json
{
  "@parcel/resolver-default": {
    "packageExports": true
  }
}

더 알아보기 (Learn more)