OpenAPI 명세(OpenAPI Specification)는 x-로 시작하는 필드를 명세 확장(Specification Extensions)으로 허용한다. 값은 아무 JSON이든 되고, 표준 도구는 모르는 확장을 무시한다. x-oai-·x-oas-로 시작하는 이름만 OpenAPI 이니셔티브가 예약해 두었다. 흔히 "vendor extension"이라 부른다.
enum 라벨을 둘 표준 자리가 없다
스키마의 enum은 허용되는 값의 목록일 뿐, 각 값에 붙는 이름이나 화면용 라벨을 담는 필드가 없다. 그래서 도구마다 확장을 만들어 썼다.
AmountType:
type: string
enum: [exclude, include]
x-enum-varnames: [Exclude, Include] # 코드에서 쓸 이름
x-enum-descriptions: [할인 제외 금액, 할인 포함 금액] # 설명x-enum-varnames·x-enum-descriptions: OpenAPI Generator 등 여러 생성기가 알아보는 관례다. 배열 순서가enum과 짝을 이룬다x-enumNames: NSwag 계열- 서버 프레임워크가 만든 설명에서 직접 뽑아 자체 확장(
x-enum-labels같은)을 만들기도 한다. 예를 들어 drf-spectacular는 기본 설정에서 choice의 라벨을 enum의description에 마크다운 목록으로 넣어 준다 - OpenAPI 3.1부터는 스키마가 JSON Schema와 맞춰져
oneOf안에const와title을 짝지어 라벨을 표현할 수도 있지만, 코드 생성기 지원이 고르지 않다
타입 생성기는 어떻게 다루나 (2026 기준)
openapi-typescript(7.x)는 기본적으로 enum을 문자열 유니언('exclude' | 'include')으로 만든다. x-enum-varnames·x-enum-descriptions(그리고 NSwag식 x-enumNames·x-enumDescriptions)는 알아본다. --enum 옵션으로 TS enum을 만들 때 멤버 이름과 주석으로 쓴다. 반면 직접 지은 확장(x-enum-labels 등)은 무시하므로 생성된 .ts에 들어가지 않는다.
라벨은 타입이 아니라 런타임 데이터
생성기가 확장을 알아보든 아니든, 따져 볼 점은 정보의 성격이다.
- 값의 목록은 컴파일 타임에 검사할 대상이다 → 생성된 타입(유니언)
- "할인 제외 금액" 같은 라벨은 화면에 그릴 때 찾아 쓰는 문자열이다 → 런타임 데이터
그래서 명세를 받아 한 번은 타입 생성기에 넘기고, 한 번은 스크립트로 확장 필드만 뽑아 enums.json 같은 라벨 맵을 만드는 구성이 자연스럽다. 코드에서는 labels.AmountType[value]로 꺼낸다. 라벨 맵의 키를 생성된 유니언 타입으로 좁혀 두면 값이 추가됐는데 라벨이 빠지는 일을 타입 검사로 잡을 수 있다(satisfies). 라벨을 다국어로 바꿔야 할 때도 타입을 건드리지 않는다.
명세와 실제 응답이 어긋나는 문제는 스키마 드리프트, 명세를 만드는 쪽은 DRF 시리얼라이저를 본다.
출처: OpenAPI Specification 3.2.0 — Specification Extensions · openapi-typescript — Enum extensions · openapi-typescript — CLI flags · drf-spectacular — Settings