노트

트리 셰이킹

Tree Shaking

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

쉽게 말하면

트리 셰이킹은 나무를 흔들어 말라붙은 잎을 떨어뜨리듯, 아무 데서도 쓰지 않는 코드를 최종 번들에서 빼내는 거예요. 사용자가 내려받는 파일이 그만큼 가벼워져요.

비유가 깨지는 곳 흔든다고 다 떨어지진 않아요. 불러오기만 해도 뭔가 실행되는 부수 효과가 있거나 CommonJS, 동적 접근처럼 정적으로 분석할 수 없으면 번들러가 남겨 둬요. 그래서 ESM과 sideEffects 표시가 필요해요.

트리 셰이킹(Tree Shaking)은 번들러가 import/export를 정적으로 분석해, 어디서도 쓰지 않는 export를 최종 번들에서 빼는 최적화다. 빌드 단계의 죽은 코드 제거라고 보면 된다.

  • 전제는 ESM(ECMAScript Modules)이다. ES 모듈의 import/export는 최상위에 고정돼 있어서 실행 전에 의존 그래프를 만들 수 있다. CommonJS의 require는 런타임에 조건부로도 호출할 수 있어서 무엇이 쓰이는지 확정하기 어렵다
  • 부수 효과가 있으면 지우지 못한다. 모듈을 불러오기만 해도 무언가 실행된다면 지우면 안 된다. 그래서 package.json의 "sideEffects": false(또는 폴리필 같은 예외 파일 목록)로 번들러에게 안전하다고 알려 준다
  • 깨지기 쉬운 경우
    • import * as utils처럼 namespace 전체를 가져오면 번들러가 보수적으로 판단할 수 있다
    • utils[key]처럼 동적으로 접근하면 정적 분석이 안 된다
    • Babel 같은 변환 단계가 ESM을 CommonJS로 바꿔 버리면 효과가 사라진다(@babel/preset-env의 modules 옵션)
    • TS의 enum은 IIFE(Immediately Invoked Function Expression)로 컴파일돼 지우기 어렵다
  • named import와 ESM 배포판(lodash-es, date-fns)을 쓰면 효과가 좋다
구분트리 셰이킹코드 스플리팅
목적안 쓰는 코드 제거번들을 여러 조각으로 분리
시점빌드로딩 전략

코드 스플리팅과 동적 임포트과 같이 쓰고, 배럴 파일과 re-export은 잘못 구성하면 트리 셰이킹을 방해할 수 있다. 번들러별 차이는 번들러 참고.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 이진 탐색 트리

    각 노드가 자식을 최대 둘 가지고, 왼쪽 서브트리의 모든 값은 노드보다 작고 오른쪽은 크다는 규칙을 지키는 트리. 비교할 때마다 한쪽 가지를 버리므로 정렬된 데이터를 빠르게 찾고 넣을 수 있다.

  • 청킹과 코드 읽기

    여러 정보를 의미 있는 덩어리 하나로 묶어 기억하는 것. 아는 것이 많을수록 코드를 큰 덩어리로 읽는다.

  • 트리 순회

    트리의 모든 노드를 한 번씩 방문하는 방법. 같은 층을 먼저 훑는 너비 우선(Breadth-First)과, 한 가지를 끝까지 내려가는 깊이 우선(Depth-First)이 있고, 깊이 우선은 노드를 언제 방문하느냐에 따라 셋으로 나뉜다.

  • 변경하기 쉬운 프런트엔드 코드

    Frontend Fundamentals는 "좋은 프런트엔드 코드 = 변경하기 쉬운 코드"라는 관점에서 가독성(Readability)·예측 가능성(Predictability)·응집도(Cohesion)·결합도(Coupling) 네 기준과 구체적인 기법을 정리한 공개 가이드다. 네 기준은 서로 부딪치기도 해서 상황에 맞게 무엇을 우선할지 고르는 것이 핵심이다.

  • Feature-Sliced Design

    Feature-Sliced Design(FSD)은 프론트엔드 코드를 레이어(layer)·슬라이스(slice)·세그먼트(segment) 세 단계로 나누고, 누가 누구를 import할 수 있는지를 규칙으로 정하는 아키텍처 방법론이다. 폴더 이름 규약처럼 보이지만 본질은 의존 방향 규칙이다.

보기 옵션