TIL (Typescript에서 enum을 사용하면 안되는 이유 With FE)

이우길·2022년 8월 2일
1

TIL

목록 보기
1/1
post-thumbnail

이번 글은 TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다.를 기반으로 작성되었습니다.

Goal


Tree-shaking이란?

enum을 사용하면 안되는 이유를 먼저 알기전에 Tree-shaking이라는 개념을 먼저 알아야 한다.

Tree-shaking은 죽은 코드(사용 되지 않는 코드)의 제거를 위해 Javascript컨텍스트에서 일반적으로 사용되는 용어이다.

export를 하였지만 import되지 않은 모듈이나 사용되지 않는 코드를 삭제하며 번들을 줄여주는 역할을 한다.


enum

enum은 열거형 변수로 정수를 하나로 합칠 때 유용하게 사용될 수 있다. 하지만 Javascript에는 없는 기능이며 Typescript에서만 사용할 수 있다.

먼저 Typescript에서 enum은 아래와 같다.

enum MAIL_SEARCH_FILTER {
  FROM = "from",
  TO = "to",
}

MAIL_SEARCH_FILTER enum이 Javascript로 트랜스파일되면 아래와 같은 코드로 바뀐다.

"use strict";
var MAIL_SEARCH_FILTER;
(function (MAIL_SEARCH_FILTER) {
  MAIL_SEARCH_FILTER["FROM"] = "from";
  MAIL_SEARCH_FILTER["TO"] = "to";
})(MAIL_SEARCH_FILTER || (MAIL_SEARCH_FILTER = {}));

Typescript에서 enum을 사용하면 Tree-shaking이 되지 않는다.

enum에서 말했듯이 enum은 Typescript에서만 구현한 기능이기 때문에 트랜스파일 과정을 거치면 Javascript에서는 IIFE(즉시 실행 함수)의 모습을 띄게 된다.

Javascript에서 존재하지 않는 것을 구현하기 위해 Typescript컴파일러는 IIFE(즉시 실행 함수)를 포함한 코드를 생성하게 된다.

번들러 중에는(예를 들어 Rollup) IIFE사용하지 않은 코드라고 판단을 할 수 없다. 그렇기 때문에 Tree-shaking이 적용되지 않고 번들에 그대로 포함되게 되는 것이다.


그럼 대체품은 뭐가 있을까?

Union Type를 사용하면 된다.

Union Type이란?

간단히 이야기하면 유니온 타입(Union Type)이란 Javascript의 OR 연산자(||)와 같이 A이거나 B이다 라는 의미의 타입이다.


먼저 상수를 담을 object를 생성 한 후 해당 object를 통해 Union Type을 생성해주면 된다.

const MAIL_SEARCH_FILTER = {
  FROM = "from",
  TO = "to",
} as const;

// 1. `keyof typeof MAIL_SEARCH_FILTER`를 통해 `object`의 key를 뽑아온다.
// 2. `typeof MAIL_SEARCH_FILTER[${key}]`을 통해 해당 key에 해당하는 프러퍼티 값을 타입으로 사용
type MAIL_SEARCH_FILTER = typeof MAIL_SEARCH_FILTER[keyof typeof MAIL_SEARCH_FILTER];
const from: MAIL_SEARCH_FILTER = 'from';

위와 같이 작성 후 트랜스파일 과정을 거친 Javascript 코드는 아래와 같다.

"use strict";
const MAIL_SEARCH_FILTER = {
    FROM: 'from',
    TO: 'to'
};
const from = 'from';

결과적으로 Typescript코드에서 정의한 타입의 이점을 그대로 가져가면서, Javascript로 트랜스파일 해도 IIFE가 생성되지 않는다.

그렇기 때문에 만약 해당 타입이 사용되지 않는다면 Tree-shaking의 적용 대상이 되어 번들에 포함되지 않게 된다.


그렇다면 const enum은?

Typescript에서 const enum을 사용해 보면 enum과 거의 같다고 느껴지겠지만, enum의 내용이 트랜스파일할 때 인라인으로 확장된다는 점이 다르다.

Typescript에서 const enum을 선언하는 방법은 아래와 같다.

const enum MAIL_SEARCH_FILTER  {
  FROM= "from",
  TO = "to",
};

const from = MAIL_SEARCH_FILTER.FROM

위의 코드가 Javascript로 트랜스파일 과정을 거치면 아래와 같이 인라인으로 확장된다.

"use strict";
;
const from = "from" /* MAIL_SEARCH_FILTER.FROM */;

const enumTree-shaking관점에서 Union Type과 같다고 한다. 트랜스파일 되는 것만 봐도 IIFE가 생성되지 않는다. 또한 enum에 긴 문자열을 할당할 때 트랜스파일 과정에서 유니코드로 변환 되기 때문에 해당 타입의 값이 수 없이 길어진다.

추가적으로 단점 2가지가 존재한다.

  1. const enumBabel로 전송할 수 없다.

  2. --isolatedModules가 활성화 된 환경에서 앰비언트 컨텍스트 (일반적으로 .d.ts, declare class를 의미한다.)에서 선언 된 const enum을 다른 모듈에서 액세스 할 경우 컴파일 오류가 발생한다.


정리

  1. enumTypescript의 기능이며 Javascript에는 없는 기능이다.

  2. Javascript로 트랜스파일 될 때 enumIIFE를 포함한 코드로 변환된다.

  3. 변환된 IIFE를 포함된 코드는 번들러가 사용여부를 판단하지 못하기 때문에 Tree-shaking에서 제외된다.

  4. 그렇기 때문에 enum대신 Union Type를 사용해야 한다.


REFERENCES

profile
leewoooo

0개의 댓글