1. 개요
TypeScript에서 enum은 tree shaking이 되지 않는다는 이슈가 있었다.
이것이 정확히 어떤 것인지 살펴보도록 하자.
2. 미리 알아두어야 하는 개념
2.1. Bundling (번들링)
여러 개의 코드를 하나로 묶고 압축까지 하는 과정을 의미한다.
한 개의 웹 프로젝트를 제작하기 위해서는 여러 개의 JavaScript 파일을 작성하기 마련인데, 프로젝트를 배포할 때 클라이언트에게 여러 개의 JavaScript 파일을 제공하는 것은 매우 비효율적이다.
따라서 작성한 코드를 한데 묶어 전송하는 것이 바람직하다.
또한 옛날과는 다르게 모던 웹 개발에서는 JavaScript 파일 내에 html 요소도 넣고 있으며(Ex. JSX), CSS도 포함시키고 있다(CSS in JS).
따라서 과거와는 비교할 수 없을 정도로 JavaScript의 파일 용량이 비대해졌기 때문에, 파일의 용량을 줄이는 작업은 빠른 서비스와 좋은 UX를 위한 필수적인 요소로 자리잡게 되었다.
번들링을 수행하는 대표적인 도구로 vite, webpack, esbuild, roll-up이 있다.
2.2. Tree Shaking
사용하지 않는 코드를 제거하는 과정이며, 번들러가 파일의 용량을 줄이도록 만드는 대표적인 작업 중 하나이다.
(나무를 흔들어서 나뭇잎을 떨구는 과정, 혹은 가지치기 이미지를 떠올리자)
사용하지 않는 모듈, 함수, 변수 등을 번들링 과정에서 제외시키게 되어 결과적으로 번들링된 파일의 용량이 줄어드는 효과를 얻을 수 있다.
3. enum
3.1. enum의 도입 배경
프로그래밍 언어에서 모든 변수는 항상 key와 value의 관계를 가지고 있음을 볼 수 있다.
간단한 변수조차도 변수의 이름이 key가 되고 변수의 값이 value가 되며, JavaScript의 객체 역시 항상 key-value 관계로 구성되어 있다.
하지만 개발을 하다보면 key만 필요할 뿐 value는 그닥 필요하지 않은 경우가 종종 생긴다.
내 경험에 따르면 특정 상태, 혹은 이벤트명을 나타낼 때가 대표적이라 생각한다.
if (status === "UP") {
// ...
}
socket.on("LEFT", () => {
// ..
});
보통은 위의 코드와 같이 상태나 이벤트 이름을 직접 string 리터럴로 나타낼 수 있는데, 사람은 언제나 실수를 하는 존재이기 때문에 오타를 작성할 가능성이 있다.
잘 작성한 로직이라도 저런 부분에서 오타가 발생하면 디버깅하는데 엄청난 시간이 소요될 가능성이 높다.
이런 경우에 사용할 수 있는 방법이 바로 enum이다.
enum을 선언할 때는 단순히 key만 지정하면 되며, value는 굳이 지정할 필요가 없다.
(value를 지정하지 않을 경우 자동으로 0부터 n까지의 숫자가 대입된다)
웬만한 언어에서 enum 문법을 지원하고 있으며, TypeScript에서도 enum 문법이 도입되었다.
enum Move {
UP,
DOWN,
LEFT,
RIGHT,
}
앞에서 본 코드에 enum을 적용한다면 아래와 같을 것이다.
enum을 통해 미리 선언된 key만을 이용할 수 있기 때문에 오타에 의한 버그를 방지할 수 있다.
(만약 enum을 사용하는 과정에서 key를 잘못 타이핑한경우 TS 컴파일러가 버그를 잡아내기 때문에 금방 디버깅 할 수 있다)
if (status === Move.UP) {
// ...
}
socket.on(Move.LEFT, () => {
// ..
});
4. 논란
상기한 편리성에도 불구하고 TypeScript의 enum은 논란의 대상에 서있다.
바로 enum 코드는 tree shaking되지 않는다는 것이다.
즉 사용하지 않는 enum 코드가 번들링 과정에서 tree shaking되지 않으므로 사용을 지양해야 한다는 주장이다.
정말로 그런지 확인해보기 위해 검증을 하였고, 테스트 환경은 아래와 같다.
(typescript: 5.3.3, tsconfig target: ES2020)
우선 ts파일에 아래와 같은 코드를 작성하였다.
enum Move {
UP,
DOWN,
LEFT,
RIGHT,
}
TypeScript 컴파일러에 의해 컴파일된 결과는 아래와 같다.
var Move;
(function (Move) {
Move[Move["UP"] = 0] = "UP";
Move[Move["DOWN"] = 1] = "DOWN";
Move[Move["LEFT"] = 2] = "LEFT";
Move[Move["RIGHT"] = 3] = "RIGHT";
})(Move || (Move = {}));
번들링 결과를 살펴보기 위해 roll up 번들러가 제공하는 웹 repl을 통해 변환된 JavaScript 코드를 붙여넣었다.
그리고 그 결과는 아래 사진과 같다.
맨 처음 TypeScript의 enum 코드는 정의만 되어있을 뿐 사용되지는 않았기 때문에 tree shaking의 대상이 된다.
하지만 roll up 번들러에서는 사용되지 않은 enum 코드를 tree shaking하지 않았다.
왜 그럴까?
enum이 있는 TypeScript코드가 JavaScript 코드로 바뀌면서 enum 부분이 IIFE 함수로 변환되었는데, 번들러 입장에서는 IIFE 함수가 사용하지 않는 코드라고 판단할 수 없기 때문에 tree shaking하지 못한 것이다.
'TypeScript' 카테고리의 다른 글
TypeScript 도입을 위한 tsconfig.json (0) | 2023.12.06 |
---|---|
extends vs implements (1) | 2023.10.07 |