노트

enum과 as const 객체

Enums and const Objects

프런트엔드#ts#performance · 연결된 개념 8개

쉽게 말하면

enum은 '주문 대기, 결제 완료'처럼 정해진 상태 목록에 이름을 붙여 오타 없이 쓰게 하는 문법이에요. 다만 다른 타입처럼 사라지지 않고 실제 객체로 남아서, 요즘은 as const 객체로 대신하는 경우가 많아요.

비유가 깨지는 곳 enum은 IIFE로 객체를 만드는 실행 코드라 번들러가 부수 효과를 의심해 통째로 남기기 쉬워요. 값을 인라인하는 const enum도 파일 단위 변환 도구에서는 제대로 동작하지 않아요.

TypeScript의 enum은 관련된 상수 집합에 이름과 타입을 함께 주는 문법이다. 다른 TS 타입과 달리 런타임 객체로 컴파일되어 남는다. 요즘 프런트엔드에서는 같은 일을 as const 객체와 유니언 타입으로 하는 경우가 많다.

enum Direction { Up, Down }
// 컴파일 결과: IIFE + 양방향 매핑
// Direction[Direction["Up"] = 0] = "Up"  → Direction.Up === 0, Direction[0] === "Up"
 
const STATUS = { Pending: 'PENDING', Success: 'SUCCESS' } as const
type Status = (typeof STATUS)[keyof typeof STATUS]     // 'PENDING' | 'SUCCESS'
  • 숫자 enum은 역방향 매핑(Reverse Mapping)까지 생성하고, 아무 숫자나 들어가는 구멍이 있다. 쓴다면 문자열 enum이 디버깅과 서버 통신에 낫다
  • 트리 셰이킹에 불리하다. enum은 IIFE(Immediately Invoked Function Expression)로 객체를 만드는 실행 코드라, 번들러가 부수 효과 가능성을 의심해 통째로 남기기 쉽다. as const 객체는 평범한 리터럴이라 분석이 쉽고 타입은 컴파일 때 사라진다(트리 셰이킹)
  • const enum: 사용처에 값을 인라인해서 객체가 안 남는다. 하지만 파일 단위로 변환하는 도구(Babel, esbuild, isolatedModules)는 다른 파일의 값을 몰라 인라인하지 못하고 일반 enum처럼 다루거나, .d.ts에 선언된 const enum은 아예 쓰지 못하게 한다. 라이브러리 배포에도 위험하다(verbatimModuleSyntax와 import type)
  • enum이 어울리는 곳: 백엔드나 공통 라이브러리처럼 런타임 객체(Object.values)가 필요하고 값 집합이 고정된 도메인 개념(주문 상태, 권한)

상수 객체에서 타입을 뽑는 문법은 매핑된 타입과 keyof, 이름 붙은 상수의 가치는 매직 넘버와 설명 상수, 문자열 규칙을 타입으로 만드는 방법은 템플릿 리터럴 타입.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 유니언·인터섹션·리터럴 타입

    유니언 타입(Union Type, A | B)은 "A이거나 B인 값"이고, 인터섹션 타입(Intersection Type, A & B)은 "A이면서 B인 값"이다. 리터럴 타입(Literal Type)은 'left'나 3처럼 특정 값 하나만 허용하는 타입이다.

  • tsconfig 핵심 옵션

    tsconfig.json은 TypeScript 컴파일러(tsc)에게 어떤 파일을, 어떤 규칙으로 검사하고, 무엇을 출력할지 알려 주는 프로젝트 설정 파일이다. tsc --init으로 만들고, 이 파일이 있으면 tsc만 쳐도 프로젝트 전체를 컴파일한다(-w는 감시 모드, watch mode).

  • 기본형 집착

    전화번호·금액·우선순위 같은 도메인 개념을 끝까지 문자열이나 숫자로만 다루는 냄새. 같은 검증과 포맷 코드가 여기저기 반복되고, 문자열로 모든 걸 표현하는 "stringly typed" 코드가 된다.

  • any와 unknown

    any는 그 값에 대한 타입 검사를 포기하는 타입이고, unknown은 타입을 아직 모르니 확인하기 전에는 쓰지 못하게 하는 타입이다. 둘 다 아무 값이나 받을 수 있지만, 꺼내 쓸 때가 다르다.

  • type과 interface

    type(타입 별칭, Type Alias)과 interface는 둘 다 타입에 이름을 붙이는 방법이다. 객체 모양을 정의할 때는 대부분 바꿔 써도 되지만, 확장 방식과 표현 범위가 다르다.

보기 옵션