enum관련된 상수들의 집합 에 이름을 붙이는 TypeScript 고유 기능입니다.

숫자 enum(Numeric Enum)

TYPESCRIPT
// 기본값은 0부터 자동 증가
enum Direction {
  Up,     // 0
  Down,   // 1
  Left,   // 2
  Right,  // 3
}

console.log(Direction.Up);    // 0
console.log(Direction[0]);    // 'Up' (역방향 매핑)

// 시작값을 지정하면 그 이후부터 증가
enum StatusCode {
  OK = 200,
  Created = 201,
  BadRequest = 400,
  NotFound = 404,
}

역방향 매핑(Reverse Mapping)

숫자 enum은 값에서 이름으로 역방향 조회가 가능합니다.

TYPESCRIPT
enum Color {
  Red,    // 0
  Green,  // 1
  Blue,   // 2
}

console.log(Color.Red);    // 0
console.log(Color[0]);     // 'Red'
console.log(Color[1]);     // 'Green'

컴파일된 JavaScript를 보면 양방향 매핑이 어떻게 구현되는지 알 수 있습니다.

JAVASCRIPT
// 컴파일 결과
var Color;
(function (Color) {
  Color[Color["Red"] = 0] = "Red";
  Color[Color["Green"] = 1] = "Green";
  Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));

문자열 enum(String Enum)

TYPESCRIPT
enum EventType {
  Click = 'CLICK',
  Hover = 'HOVER',
  Scroll = 'SCROLL',
}

console.log(EventType.Click); // 'CLICK'
// console.log(EventType['CLICK']); // ❌ 역방향 매핑 없음

문자열 enum은 역방향 매핑이 **없습니다 **. 대신 디버깅할 때 값이 의미를 가지므로 더 읽기 쉽습니다.

숫자 vs 문자열 enum

특성숫자 enum문자열 enum
기본값0부터 자동 증가모든 값 직접 지정 필요
역방향 매핑가능불가능
디버깅값이 숫자라 의미 파악 어려움값이 문자열이라 직관적
번들 크기더 큼 (양방향 매핑 코드)상대적으로 작음

const enum

const enum은 컴파일 시 ** 완전히 인라인 **됩니다. JavaScript에 enum 객체가 남지 않습니다.

TYPESCRIPT
const enum Size {
  Small = 'S',
  Medium = 'M',
  Large = 'L',
}

const shirt = Size.Medium;
JAVASCRIPT
// 컴파일 결과 — enum 객체가 없음!
const shirt = 'M'; // 값이 직접 인라인됨

const enum의 제약

TYPESCRIPT
const enum Direction {
  Up, Down, Left, Right
}

// ❌ 역방향 매핑 불가 (런타임에 객체가 없으므로)
// Direction[0]; // Error

// ❌ 변수로 동적 접근 불가
// const key = 'Up';
// Direction[key]; // Error

면접 포인트: const enum을 쓰면 번들 크기가 줄어들지만, isolatedModules 옵션과 함께 쓸 수 없는 경우가 있습니다. Babel이나 esbuild 같은 트랜스파일러는 파일 단위로 컴파일하므로 const enum의 교차 파일 인라이닝이 불가합니다.

enum의 함정

숫자 enum의 타입 안전성 문제

TYPESCRIPT
enum Status {
  Active = 0,
  Inactive = 1,
}

// ⚠️ 아무 숫자나 할당 가능 — 타입 안전하지 않음!
const status: Status = 42; // 에러가 나지 않음!

공부하다 보니 이 부분에서 많이 놀랐습니다. 숫자 enum은 어떤 숫자든 할당할 수 있어서 타입 안전성이 깨질 수 있습니다. 문자열 enum이나 리터럴 유니온을 쓰는 것이 더 안전합니다.

트리쉐이킹 문제

일반 enum은 IIFE(즉시 실행 함수)로 컴파일되기 때문에, 번들러가 사용하지 않는 enum을 제거(트리쉐이킹)하지 못할 수 있습니다.

대안: 리터럴 유니온 + 객체

TYPESCRIPT
// 리터럴 유니온 — 가장 가벼운 대안
type Direction = 'up' | 'down' | 'left' | 'right';

// 값이 필요하면 as const 객체
const Direction = {
  Up: 'up',
  Down: 'down',
  Left: 'left',
  Right: 'right',
} as const;

type Direction = (typeof Direction)[keyof typeof Direction];
// 'up' | 'down' | 'left' | 'right'

// 사용
function move(dir: Direction) {
  console.log(dir);
}

move(Direction.Up);   // 'up'
move('down');          // 'down' — 직접 문자열도 가능

이 패턴은 트리쉐이킹이 잘 되고, 숫자 enum의 타입 안전성 문제도 없습니다.

enum을 언제 써야 하나

TYPESCRIPT
// ✅ enum이 적합한 경우
// 1. 양방향 매핑이 필요할 때
enum HttpStatus {
  OK = 200,
  NotFound = 404,
}
console.log(HttpStatus[200]); // 'OK' — 역방향 매핑 활용

// 2. 기존 코드베이스와의 호환
// Angular 등 enum을 널리 사용하는 프레임워크

// ✅ 리터럴 유니온이 적합한 경우
// 1. 단순한 문자열/숫자 상수 집합
type Theme = 'light' | 'dark' | 'system';

// 2. 트리쉐이킹이 중요한 프론트엔드 프로젝트
// 3. 라이브러리 개발 (소비자가 enum에 의존하지 않도록)

정리

  • 숫자 enum은 역방향 매핑이 가능하지만 타입 안전성이 약하다
  • 문자열 enum은 역방향 매핑이 없지만 디버깅이 쉽다
  • const enum은 인라인되어 번들 크기를 줄이지만 제약이 있다
  • 리터럴 유니온 + as const 객체가 현대적인 대안이다
  • 면접에서는 enum의 컴파일 결과와 트리쉐이킹 문제를 알면 좋다
댓글 로딩 중...