TypeScript 의 enum 은 악마일까?

miinhho·2025년 6월 22일
post-thumbnail

TypeScript 에서 enum 사용을 피하라는 영상이나 글을 종종 보게 된다.
다만 enum 이 꼭 나쁜 것일까...? 에 대해서는 아니라고 말하고 싶다.

as const: TypeScript 변수의 값을 절대로 바꾸지 못하도록 하는 type assertion 이다.


enum 의 단점

1. 예상치 못한 동작을 일으킨다.

enum Role {
  ADMIN,
  USER
}

// JavaScript 로 컴파일된 결과
var Role;
(function (Role) {
    Role[Role["ADMIN"] = 0] = "ADMIN";
  	Role[Role["USER"] = 1] = "USER";
})(Role|| (Role = {}));

이를 JavaScript 로 더 보기쉽게 옮기자면, 다음과 같이 변한다.
그렇기 때문에 Object.values() 와 같은 메서드를 사용했을 때 0, 1 이 추가되어서 나온다.

const Role = {
  ADMIN: 0,
  0: "ADMIN",
  USER: 1,
  1: "USER",
};

["USER", "ADMIN", 0, 1] 

다음과 같이 문자열을 할당하거나, const enum 을 사용한다면, 이러한 현상을 피할 수 있다.
다만 as const 라는 대안이 바로 보인다.

/// 문자열 할당
enum Role {
    USER = "USER",
    ADMIN = "ADMIN",
}

// JavaScript 로 컴파일된 결과
var Role;
(function (Role) {
    Role["ADMIN"] = "ADMIN";
    Role["USER"] = "USER";
})(Role || (Role = {}));

/// const enum

const enum Role {
	USER,
  	ADMIN
}
// JavaScript 로 컴파일 될 때는 할당된 값으로 변환됨.
// 설정되지 않았을 때는 자동으로 USER = 0, ADMIN = 1, ...

// ["USER", "ADMIN"]
Object.values(Role)

꼭 key 의 값과 동일한 문자열일 필요는 없다.


2. 해당되는 값을 바로 넣을 수 없다

enum Role {
    ADMIN = "ADMIN",
    USER = "USER",
}

function helloUser(name: string, role: Role): void {
    switch (role) {
        case Role.ADMIN: {
            console.log(`Hello admin ${name}!`);
            break;
        }
        case Role.USER: {
            console.log(`Hello user ${name}`);
            break;
        }
    }
}

// Argument of type '"ADMIN"' is not assignable to parameter of type 'Role'.
helloUser('John Doe', 'ADMIN');

helloUser('John doe', Role.ADMIN);

enum 을 사용한다면, Role.ADMIN 에 해당하는 'ADMIN' 을 바로 사용할 수 없으며, 항상 Role.ADMIN 으로 사용해야 한다.

as const 를 사용한다면, 'ADMIN' 을 바로 사용할 수 있다.

const Role = {
    ADMIN: "ADMIN",
    USER: "USER",
} as const;

type RoleType = keyof typeof Role;

function helloUser(name: string, role: RoleType): void {
    switch (role) {
        case Role.ADMIN: {
            console.log(`Hello admin ${name}!`);
            break;
        }
        case Role.USER: {
            console.log(`Hello user ${name}`);
            break;
        }
    }
}

helloUser('John Doe', 'ADMIN');
helloUser('John doe', Role.ADMIN);

다만 이런 단점들을 나열하다보면, enum 의 장점 또한 엿보인다.


enum 의 장점

1. 타입 지원이 강력하다

as const 를 사용한 예시를 보면, helloUser 에서 Role 를 사용하기 위해 RoleType 을 따로 만들어서 사용하는 것을 볼 수 있다.

하지만 enum 을 사용한 예시를 보면, 바로 Role 을 사용했다.
이와 같이 enumas const 보다 타입 지원이 강력하고, 이는 개발자의 편의성과 직결된다.

2. 해당되는 값을 바로 넣을 수 없다

enum 의 해당되는 값을 바로 넣을 수 없다는 점은, 오히려 명확한 인터페이스를 제공하고 실수를 방지하기 쉽다.



하지만...

enum 은 처음에 설명했던 것과 같이, as const 에 비해 단점도 많다.
잘못 사용하면 예상치 못한 동작을 발생시킬 수도 있으며, 유연하지 않다.

as constenum 에 비해 훨씬 유연하기 때문에, 외부 API 와의 호환성이 높다.
또한 const 의 확장이기 때문에 JavaScript 호환성도 뛰어나며, JSON 직렬화/역직렬화 에서 유연함이 빛을 발한다.

enum 은 트리 쉐이킹을 지원하긴 하지만, 사용하지 않는 속성은 번들에서 제거가 가능한 as const 와 달리 전체가 포함되거나, 제거된다.


결론

TypeScript 의 enum 은 꼭 나쁘진 않다.
하지만 as constenum 보다 더 유연하고, 확실한 동작을 하는 것은 사실이다.

profile
재미있는 걸 좋아합니다

0개의 댓글