TypeScript Enum vs Union Type, 뭘 써야 할까
문제
TypeScript 프로젝트에서 상수 집합을 정의할 때마다 고민이 생긴다. enum을 쓸까, union type을 쓸까. 팀마다 컨벤션도 다르고, 인터넷 글마다 말이 다르다.
Enum의 함정
enum Status {
Active = 'ACTIVE',
Inactive = 'INACTIVE',
Pending = 'PENDING'
}
이게 JavaScript로 컴파일되면 이런 코드가 나온다.
var Status;
(function (Status) {
Status["Active"] = "ACTIVE";
Status["Inactive"] = "INACTIVE";
Status["Pending"] = "PENDING";
})(Status || (Status = {}));
런타임에 객체가 생성되는 거다. 번들 사이즈에 영향을 주고, tree-shaking도 안 된다.
Union Type으로 해결
const STATUS = {
Active: 'ACTIVE',
Inactive: 'INACTIVE',
Pending: 'PENDING',
} as const;
type Status = typeof STATUS[keyof typeof STATUS];
// 결과: 'ACTIVE' | 'INACTIVE' | 'PENDING'
as const를 붙이면 리터럴 타입으로 추론된다. 런타임 코드가 최소화되고, tree-shaking도 잘 된다.
값이 단순하면 이것만으로도 충분하다.
type Direction = 'up' | 'down' | 'left' | 'right';
핵심 포인트
enum은 런타임 객체를 생성한다. 번들 사이즈가 늘어난다const enum은 인라인되지만,--isolatedModules환경(Vite, Next.js 등)에서 못 쓴다as const+ union type이 대부분의 경우에 더 낫다- enum이 필요한 경우: 비트 플래그 연산이나 런타임에 역방향 매핑이 필요할 때 정도다