트리 셰이킹
Tree Shaking
방법
불러오기는 했지만 실제로 쓰이지 않는 코드를 배포 결과물에서 걷어 내는 최적화입니다.
등장 배경
파일 수백 개로 나눠 만든 화면 코드는 브라우저가 받기 좋게 몇 개로 묶여 나갑니다. 그 묶는 일을 하는 도구가 번들러인데, 초기 번들러는 불러온 것을 전부 담았습니다. 날짜 라이브러리에서 함수 하나만 가져다 쓰고 있어도 그 라이브러리 전체가 결과물에 들어갔습니다.
페이지덱에서 그 무게가 눈에 보인 날이 있었습니다. 첫 화면에서 받는 자바스크립트가 1.4메가바이트였습니다. 무엇이 들어 있는지 뜯어 보니 아이콘 묶음 하나가 통째로 있었고, 실제로 쓰는 아이콘은 900개 중 열두 개였습니다. 날짜 라이브러리도 전체가 들어 있었는데 쓰는 함수는 두 개였습니다. 지하철에서 접속하는 사용자의 첫 화면까지 8초가 걸렸고, 사용자가 기다리는 동안 화면은 흰 채로 있었습니다.
트리 셰이킹은 그 죽은 무게를 떨어내는 작업입니다. 이름은 나무를 흔들어 마른 가지를 떨어뜨리는 그림에서 왔습니다. 코드가 서로를 불러오는 관계를 나무로 보고, 뿌리에서 출발해 실제로 닿는 가지만 남기고 나머지를 버립니다. 사용자가 직접 보고 조작하는 화면 쪽 구현인 프론트엔드 아래에서 결과물을 줄이는 빌드 갈래에 속합니다.
사용 절차
설정 한 줄로 끝나지 않고 다섯 가지를 함께 맞춰야 합니다.
- 모듈 형식을 맞춥니다. 도구가 코드를 실행하지 않고 읽어서 판단할 수 있는 형식이어야 합니다. 무엇을 불러올지 실행 시점에 정하는 형식으로 쓰면 도구는 무엇이 쓰이는지 알 수 없어 전부 남깁니다. 표준 모듈 문법으로 적혀 있어야 한다는 뜻입니다.
- 불러오기만으로 다른 일이 벌어지는 코드를 표시합니다. 파일을 읽는 순간 전역 설정을 바꾸거나 스타일을 주입하는 코드가 그렇습니다. 도구는 그런 코드를 지웠을 때 무엇이 깨질지 알 수 없어 안전하게 남겨 둡니다. 부작용이 없는 파일이 어디인지 설정에 적어 주면 그때부터 걷어 낼 수 있습니다.
- 필요한 이름만 지정해 가져옵니다. 묶음 전체를 한 이름으로 받아 점을 찍어 꺼내 쓰면 도구 입장에서는 그 묶음 전체가 쓰이는 것으로 보입니다. 아이콘 묶음에서 열두 개를 쓴다면 열두 개의 이름을 각각 적어 가져옵니다.
- 결과를 눈으로 확인합니다. 번들 안에 무엇이 얼마씩 들어 있는지 그림으로 보여 주는 도구를 붙여 봅니다. 설정만 켜고 넘어가면 줄었다고 믿는 채로 그대로 남아 있는 경우가 흔합니다. 페이지덱에서 아이콘 묶음이 남아 있던 이유도 3번 조건을 어긴 한 줄 때문이었고, 그 한 줄은 그림을 보고서야 찾았습니다.
- 크기 상한을 빌드에 걸어 둡니다. 첫 화면 번들이 정한 값을 넘으면 빌드가 실패하게 만듭니다. 한 번 줄여 놓아도 기능을 더하다 보면 몇 달 뒤에 원래대로 돌아가기 때문입니다.
적합한 상황과 한계
값어치가 큰 자리는 외부 라이브러리를 많이 쓰는 화면 코드입니다. 직접 쓴 코드는 대개 필요한 것만 들어 있어서 걷어 낼 것이 적고, 남의 라이브러리는 우리가 쓰지 않는 기능이 대부분입니다.
한계도 분명합니다.
- 죽은 코드만 걷어 냅니다. 실제로 쓰이는 코드는 그대로 남습니다. 설정 화면에 한 번도 들어가지 않는 사용자까지 설정 화면 코드를 받는 문제는 이 방법으로 풀리지 않습니다. 그 자리에는 코드 스플리팅이, 아직 보이지도 않는 이미지에는 지연 로딩이 들어갑니다.
- 라이브러리가 협조해야 합니다. 하나의 큰 파일로 묶여 배포된 라이브러리는 잘라 낼 자리가 없습니다. 라이브러리를 고를 때 이 점을 함께 보는 팀이 나중에 덜 고생합니다.
- 이름을 실행 중에 조립해 부르는 코드에 약합니다. 문자열을 이어 붙여 함수를 찾아 쓰면 도구는 무엇이 쓰일지 알 수 없어 전부 남깁니다. 걷어 내려면 그 부분을 고정된 이름으로 바꿔야 합니다.
- 표시가 틀리면 필요한 코드가 사라집니다. 부작용이 없다고 적어 둔 파일에 실제로는 전역 스타일이 들어 있었다면, 배포 뒤에 화면 배치가 무너집니다. 2번은 성능 설정이 아니라 사실 선언이라 확인 없이 적으면 안 됩니다.
실무 용례
"아이콘 900개 중 열두 개만 쓰는데 묶음 전체가 들어가 있어요."
가져오는 방식 때문에 걷어 내기가 작동하지 않았다는 지적입니다.
"번들 그림 한 번 뽑아 보죠. 설정만 켜 두고 확인은 안 했어요."
줄었다고 믿는 상태와 실제를 갈라 보자는 제안입니다.
"이건 트리 셰이킹으로 안 빠져요. 쓰이는 코드니까 스플리팅으로 나눠야 합니다."
방법의 경계를 바로잡는 말입니다.
페이지덱에서는 태오가 첫 화면 번들 크기를 매주 한 줄로 적어 둡니다. 숫자가 올라간 주에는 무엇이 들어왔는지 그림으로 찾아 원인을 적습니다. 민서가 아이콘을 새로 넣은 주에 숫자가 크게 뛴 일이 있었고, 그 뒤로 아이콘은 쓰는 것만 이름으로 가져오는 규칙이 생겼습니다.
숫자를 줄이는 것 자체가 목적은 아닙니다. 지하철에서 8초 걸리던 첫 화면이 3초로 줄었는지가 판단 기준입니다.
흔한 오해
설정을 켜면 알아서 된다고 보는 경우가 가장 많습니다. 번들러 문서에 한 줄로 적혀 있어서 그렇게 읽힙니다. 하지만 이 최적화는 도구 혼자 하는 일이 아니라 네 가지가 맞아야 작동합니다. 모듈 형식, 부작용 표시, 가져오는 방식, 라이브러리의 협조입니다. 넷 중 하나만 어긋나도 도구는 안전한 쪽을 골라 코드를 남깁니다. 남긴다는 사실을 알려 주지도 않아서, 켜 두기만 한 팀은 몇 달 동안 줄지 않은 번들을 줄었다고 믿습니다.
번들이 작아지면 빠르다고 여기는 것도 흔합니다. 둘은 이어져 있지만 같은 말은 아닙니다. 첫 화면이 뜨는 시간은 받는 양뿐 아니라 요청 개수와 받은 코드를 실행하는 시간에도 걸립니다. 1.4메가바이트를 900킬로바이트로 줄였는데 그 안에 시작할 때 계산을 오래 하는 코드가 남아 있으면 체감은 그대로입니다. 그래서 줄인 뒤에는 번들 크기가 아니라 사용자가 첫 화면을 보기까지의 시간을 다시 재고, 그 값이 움직이지 않으면 원인이 다른 곳에 있다고 봅니다.
자주 헷갈리는 용어
| 용어 | 무엇을 하는가 | 트리 셰이킹과의 차이 |
|---|---|---|
| 코드 스플리팅 | 전부를 처음에 주지 않고 화면에 들어갈 때 나눠 받게 한다 | 쓰이는 코드를 다루는 쪽입니다. 트리 셰이킹은 쓰이지 않는 코드를 아예 버리고, 스플리팅은 쓰이는 코드를 나중으로 미룹니다. 둘을 같이 씁니다 |
같이 보면 좋은 페이지
마지막 업데이트 2026-09-16