[Typescript] enum 대신 사용할 것

in-ch·2023년 12월 6일
1

typescript

목록 보기
1/4

Intro 🔥


TypeScript의 Enum은 일반적으로 열거형 상수들의 집합을 정의하는데 사용된다.

근데 build를 하고 어플리케이션을 Tree-shaking하는 과정에서 Enum은 Tree-shaking이 제대로 되지 않는다.

참고로 Tree-shaking이란 번들링된 코드에서 사용하지 않는 코드를 자동으로 제거하여 번들 크기를 줄이고 앱의 성능을 향상시키는 것이다.

Treeshaking되는 예제 🔥


예를 들어, 다음과 같이 두 개의 모듈이 있다고 가정해보자.

// math.js
export function square(x) {
  return x * x;
}

export function cube(x) {
  return x * x * x;
}
// main.js
import { square } from './math';

console.log(square(4));

이 예시에서 main.js 모듈은 math.js 모듈에서 제공하는 cube 함수를 사용하지 않는다.
따라서 트리 쉐이킹이 적용된다면 cube 함수는 번들에 포함되지 않는다.

트리 쉐이킹이 적용된 뒤의 번들 결과물은 다음과 같이 될 것이다.

// Optimized bundle
export function square(x) {
  return x * x;
}

console.log(square(4));

왜 줄어들지 않나..? 🔥


enum은 컴파일된 javascript 코드에서 실제로 객체로 변환된다.

예를 들어 다음과 같다.

enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

function getColor(): Color {
  return Color.Green;
}

번들링 후 ..

var Color;
(function (Color) {
    Color["Red"] = "RED";
    Color["Green"] = "GREEN";
    Color["Blue"] = "BLUE";
})(Color || (Color = {}));
function getColor() {
    return Color.Green;
}

가시적으로 봐도 더 늘어나는 게 보인다...

이런 enum이 더 추가될 수록 javascript의 번들 크기를 늘리게 될 것이고 사용자 경험에 악영향을 미치게 된다.

제대로 tree-shaking이 되지 않는 이유는 객체에는 열거형 상수의 이름과 값이 포함되어 있는데, Tree-shaking은 정적으로 상수 값을 알 수 없는 상황에서는 해당 상수 값을 사용하지 않을지라도 제거할 수 없기 때문이다.

첫번째 방법 const enum

const enum은 typescript에서 상수 열거형을 정의할 때 사용된다.

일반적으로 const enum은 컴파일 시점에서 상수 값들을 직접 인라인으로 넣어준다. 이를 통해 런타임에 객체 생성 및 할당 없이도 상수 값들을 사용할 수 있다.

사용법은 간단하다.
const 만 붙이면 된다. ㅋㅋㅋ

const enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

첫번째 방법 const enum의 장점

  1. Tree-shaking과 함께 최적화: const enum은 컴파일 시점에서 인라인된 값으로 대체되므로, 코드의 어디에서나 해당 상수 값을 사용하더라도 실제 런타임에 객체 생성 없이도 사용 가능. 따라서 Tree-shaking이 효과적으로 동작하여 불필요한 코드를 제거 가능
  2. 번들 크기 감소: const enum을 사용하면 번들 크기를 줄일 수 있습니다. 컴파일된 코드에서 상수 값들이 중복되거나 반복적으로 포함되지 않으므로 번들 크기가 작아지는 효과가 있습니다.
  3. 성능 향상: 런타임에 객체 생성과 할당이 없이 상수 값들을 사용할 수 있으므로 성능 측면에서도 이점

단, 단점도 있다.

일단 const enum은 컴파일된 코드에 상수 값들이 직접 들어가기 때문에 해당 값들이 그대로 노출된다.

노출된다는 게 무슨 의미인가?

노출이 된다고..?

  1. 컴파일 의존성:
    • 다른 코드에서 해당 const enum 값을 사용하는 경우, 그 코드는 컴파일 시에 해당 값이 직접 인라인되어 포함
    • 이는 의존성 관리에 영향을 미칠 수 있으며, 해당 라이브러리의 변경으로 인해 다시 컴파일해야 하는 상황이 발생할 수 있음
  2. 버전 관리 어려움:
    • 만약 라이브러리의 const enum 값이 변경된다면, 해당 라이브러리를 사용하는 모든 코드를 다시 컴파일해야 함
    • 이는 라이브러리의 버전 관리와 호환성 유지를 어렵게 만드는 요인이 된다.
  3. 네임스페이스 충돌:
    • 여러 라이브러리에서 같은 이름의 const enum 값을 사용하면 네임스페이스 충돌이 발생할 수 있다.
    • 두 라이브러리가 같은 const enum 값을 사용하면, 컴파일 시 충돌이 일어나 오류가 발생할 수 있다.

두번째 방법 리터럴 타입의 유니온 사용

개발할 때는 가장 길어지니깐 더럽긴 한데,,, 가장 성능이 좋다.

  • 사용법
export const ORDER = {
  recent: 'recent',
  popular: 'popular',
  downloads: 'downloads',
} as const;

export type ORDER_TYPE = typeof ORDER[keyof typeof ORDER];
  • 이렇게 하면 상수 값들의 중복을 방지하고, 타입 안정성을 유지하면서도 번들 크기를 최적화할 수 있다.

결론 😎


Union Type 쓰자 !





참고:

TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다.

Handbook - Enums

Why is const enum allowed with isolatedModules?

profile
인치

0개의 댓글