
오늘은
enum
과 const enum
그리고 as const
에 대해 알아보도록 하겠습니다. 많은 개발자들 사이에서 어떤게 더 좋다, 안좋다 라는 이야기들이 많은데 포스팅을 통해 어떤게 더 좋은지, 어떤게 더 유용한지에 대해 알아보는 시간도 가져보도록 하겠습니다.Enum (열거형)
TypeScript의
enum
은 상수 집합에 이름을 부여하는 방법입니다. enum
을 사용하면 코드를 더 명확하게 표현할 수 있으며, 유효한 값들의 집합을 정의할 수 있습니다.예시 코드
enum Direction { Up, Down, Left, Right } function move(direction: Direction) { // ... } move(Direction.Up); // 유효한 호출 move(10); // 컴파일 에러: 10은 Direction 타입이 아닙니다.
장점
- 코드 가독성 향상:
enum
의 사용은 리터럴 값보다 의미를 분명하게 전달합니다.
- 타입 안정성 강화:
enum
을 사용함으로써 예상치 못한 값으로 인한 오류를 줄일 수 있습니다.
단점
- JavaScript로 컴파일 될 때 추가 코드가 생성됩니다. 이는 런타임에 부가적인 비용을 초래할 수 있습니다.
Const Enum (상수 열거형)
const enum
은 enum
과 유사하지만, TypeScript 컴파일러에 의해 인라인 처리되어 런타임에서의 추가적인 비용 없이 사용됩니다.예시 코드
const enum Direction { Up, Down, Left, Right } function move(direction: Direction) { // ... } move(Direction.Up);
장점
- 런타임 퍼포먼스: 컴파일 시에
enum
멤버가 실제 값으로 대체되어 런타임 비용이 줄어듭니다.
단점
- 인라인 제약:
const enum
의 값은 항상 인라인으로 사용되어야 하므로,enum
처럼 동적으로 접근할 수 없습니다.
- 리플렉션의 제한: 런타임에
const enum
멤버들의 리스트를 얻거나 사용하는 것이 불가능합니다.
as const
(상수 단언)
as const
는 TypeScript에서 리터럴 타입의 값이 변하지 않음을 단언하는 방법입니다. 이를 사용하면 객체 리터럴이나 배열의 모든 프로퍼티를 읽기 전용으로 만들고, 타입을 리터럴 타입으로 좁힐 수 있습니다.예시 코드
let directions = { up: 0, down: 1, left: 2, right: 3 } as const; function move(direction: typeof directions[keyof typeof directions]) { // ... } move(directions.up); move(10); // 컴파일 에러: 10은 타입 '0 | 1 | 2 | 3'에 할당될 수 없습니다.
장점
- 유연성:
as const
를 사용하면 객체 또는 배열이 불변임을 쉽게 선언할 수 있습니다.
- 타입 추론 강화: TypeScript는
as const
를 사용한 변수에 더 구체적인 타입을 추론합니다.
단점
- 상수값만 가능: 변수에 할당된 값이 상수일 때만
as const
를 사용할 수 있습니다.
- 확장성 제한
Enum vs Const Enum vs as const
Enum
- 사용 사례:
enum
은 실행 시점에 객체로 존재해야 할 때, 즉 런타임에 해당 열거형의 키와 값을 모두 사용해야 할 때 적합합니다.
- 장점: 타입과 값을 모두 가지고 있으며, 런타임에 이를 반영할 수 있습니다. 동적으로 값을 검사하거나 키를 순회할 수 있습니다.
- 단점: JavaScript로 변환될 때 추가적인 코드가 생성되어 더 큰 번들 사이즈와 런타임 비용을 초래할 수 있습니다.
Const Enum
- 사용 사례: 런타임에서 열거형의 객체가 필요 없고, 오직 컴파일 타임에서만 상수 값이 필요할 때
const enum
이 적합합니다.
- 장점: 컴파일 시에 인라인 처리되어 런타임 성능에 부담을 주지 않습니다. 번들 사이즈를 줄일 수 있습니다.
- 단점: 런타임에 열거형의 키와 값을 반영할 수 없습니다. 디버깅이 어려울 수 있고, 타입스크립트 컴파일러 옵션
preserveConstEnums
을 설정하지 않으면 해당 정보를 잃어버릴 수 있습니다.
as const
- 사용 사례: 객체 리터럴이나 배열의 값이 변하지 않으며, 타입 시스템에 리터럴 타입으로서의 최대한의 정보를 제공할 때
as const
를 사용합니다.
- 장점: 불변성을 확보하며, 타입 추론을 통해 더 구체적인 타입을 얻을 수 있습니다. 또한, 코드가 간결해지며 런타임에 추가적인 비용이 발생하지 않습니다.
- 단점: 확장성이 제한됩니다. 객체 또는 배열의 구조가 변경되면 타입도 함께 변경되어야 하며, 리터럴 타입만을 사용할 수 있어 동적인 키를 가진 객체에는 사용하기 어렵습니다.
어떤 것이 더 나은가?
결국 선택은 사용 사례에 따라 달라집니다:
- 런타임 성능이 중요하고, 열거형이 컴파일 타임에만 필요하다면,
const enum
이 바람직합니다.
- 런타임에 열거형의 정보가 필요하다면,
enum
을 사용해야 합니다.
- 객체의 불변성과 타입 추론의 정확성이 중요한 경우에는,
as const
를 사용하는 것이 좋습니다.
각각의 기능은 특정 상황에서 최상의 결과를 제공하기 위해 설계되었습니다. 따라서 자신의 프로젝트에서 가장 중요한 요소가 무엇인지 고려하고, 그에 맞춰 적절한 기능을 선택해야 합니다.
TypeScript에서
enum
을 사용하면 Tree-shaking이 되지 않습니다, 하지만 Union Types을 사용하는 as const
의 경우에는 Tree-shaking 이 가능합니다. 이러한 이유때문인지 as const를 사용하자는 여론도 많이 있습니다.언제나 개발엔 정답은 없고 보다 나은 만 존재한다 생각하기에.. 판단은 스스로가 하는 것이 좋아보입니다!