노트

번들 크기 줄이기

Bundle Size Reduction

프런트엔드#performance#tooling · 연결된 개념 12개

쉽게 말하면

번들 다이어트는 여행 가방이 무거울 때 먼저 저울에 달아 보고, 겹치는 짐과 안 쓸 짐을 빼는 일이에요. 사용자는 가방을 받기만 하는 게 아니라 풀어서 써야 하니 가벼울수록 빨리 움직여요.

비유가 깨지는 곳 JS는 같은 무게라도 이미지보다 비싸요. 이미지는 받아서 디코딩만 하면 되지만 JS는 파싱·컴파일·실행까지 해야 해서, 줄이기 전에 bundle analyzer로 먼저 재는 게 순서예요.

번들 다이어트는 사용자가 내려받는 JavaScript 양을 측정하고 줄이는 작업이다. 같은 용량이라도 JS는 이미지보다 비싸다. 이미지는 다운로드와 디코딩만 하면 되지만, JS는 다운로드·파싱·컴파일·실행을 모두 거친다.

순서

  1. 먼저 잰다. Webpack Bundle Analyzer나 Next.js bundle analyzer로 어떤 라이브러리가 큰지 본다. 추측으로 시작하지 않는다(섣부른 최적화)
  2. 같은 라이브러리의 다른 버전이 중복 설치됐는지 본다. npm은 semver(Semantic Versioning)를 지킨다고 가정하고 호환되는 높은 버전 하나로 합칠 수 있는데, 그게 npm dedupe다. 패키지 매니저의 저장 방식은 npm과 pnpm 참고
  3. 무거운 라이브러리를 바꾼다. 용도가 겹치면 하나로 합치고, 작은 대안이나 네이티브 API(Application Programming Interface)로 대체한다. Bundlephobia에서 크기를 미리 확인할 수 있다
  4. 불필요한 폴리필(Polyfill)을 뺀다. 지원 브라우저를 기준으로 판단한다
  5. 라이브러리 영향을 페이지에 가둔다. 모든 페이지가 공유하는 공통 청크 하나에 넣으면 라이브러리를 하나 추가할 때마다 전 페이지가 무거워진다. 여러 청크로 나누고, 필요할 때만 받는 동적 임포트를 쓴다

라이브러리를 만드는 쪽이라면

  • 트리 셰이킹이 되도록 ESM(ECMAScript Modules)으로 배포하고 sideEffects를 명시한다
  • 번들러가 순수 함수 호출을 지울 수 있게 /*#__PURE__*/ 주석을 단다(Terser 등이 이용)

출처: 토스 SLASH 21 - JavaScript Bundle Diet

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 번들러

    번들러(Bundler)는 모듈로 나뉜 소스 코드를 의존 관계(Dependency Graph)를 따라 묶고 변환해, 브라우저가 적은 요청으로 받을 수 있는 결과물로 만드는 빌드 도구다.

  • 구성요소 줄이기

    셀 수 있는 모든 구성요소(파일, 폴더 깊이, 클래스, 함수, 분기, 변수, 테이블, 필드, 테스트 케이스…)는 비용이라는 관점. 심플 디자인의 네 번째 규칙을 실무 기준으로 풀어낸 것이다.

  • 배럴 파일과 re-export

    배럴 파일(Barrel File)은 여러 모듈의 export를 index.ts 하나에 모아 다시 내보내(re-export) 진입점을 하나로 만드는 파일이다. 쓰는 쪽은 import { Button, Input } from './components'처럼 한 경로에서 가져온다.

  • NestJS

    NestJS는 TypeScript를 전제로 모듈·의존성 주입(Dependency Injection, DI)·데코레이터(decorator) 구조를 제공하는 Node.js 서버 프레임워크다. 2017년 Kamil Myśliwiec가 만들었고, 구조를 강제하는 방식 때문에 흔히 "Node.js의 Spring"이라 불린다.

  • 사용자 수에 따른 규모 확장

    사용자가 늘어날 때 서버 한 대짜리 시스템을 단계적으로 키워 가는 전형적인 경로. 처음부터 다 갖추는 게 아니라, 병목이 보일 때마다 한 단계씩 더한다(galls-law).

보기 옵션