Summary#
OpenAPI codegen에서 oneOf + discriminator + allOf + nullable을 한 스키마 축에 동시에 얹으면 TypeScript 클라이언트 모델이 중복 필드, 잘못된 union/null 처리, 런타임 판별 불일치로 깨질 위험이 높다. 핵심 원인은 OpenAPI/JSON Schema의 조합 키워드가 “검증 조건”을 표현하는 반면, 많은 TypeScript generator는 이를 “상속·평탄화된 모델 구조”로 해석해야 하기 때문이다.
실무적으로는 generator에 복잡한 원본 스키마를 그대로 먹이기보다, codegen 전용 schema normalization 단계를 두는 편이 안전하다. 특히 discriminator 필드는 공통 base에 1회만 정의하고, subtype에서는 literal/enum 제약만 남기며, nullable은 union 바깥 또는 안쪽 중 하나로 일관되게 끌어올리는 방식이 유효하다.
Key Points#
-
OpenAPI의
discriminator는oneOf,anyOf,allOf와 함께 사용할 수 있는 다형성 힌트지만, 실제 검증 의미를 완전히 대체하지 않는다. 따라서 generator가 discriminator를 상속 구조, tagged union, runtime type guard 중 어느 방식으로 해석하는지에 따라 결과가 달라진다. -
allOf는 “객체 상속”이라기보다 여러 schema 조건을 모두 만족해야 한다는 조합 키워드다. 그러나 codegen 도구는 흔히allOf를 base class/interface 확장 또는 property merge로 변환한다. 이때 base와 subtype 양쪽에 discriminator property가 있으면 TypeScript 모델에 같은 필드가 중복되거나, 하나는 string이고 다른 하나는 literal enum인 식의 충돌이 생길 수 있다. -
nullable은 OpenAPI 3.0과 3.1에서 표현 방식이 다르다. - OAS 3.0:
nullable: true -
OAS 3.1 / JSON Schema 쪽:
type: ["object", "null"]또는oneOf: [{...}, {"type":"null"}]이 차이가oneOf내부/외부 어디에 null을 붙일지와 결합되면 TypeScript에서는A | B | null,(A | null) | B,A | B처럼 서로 다른 결과로 codegen될 수 있다. -
실패 모드 예시:
- base schema와 subtype schema가 모두
type/kind같은 discriminator property를 선언하여 중복 필드 생성 - subtype의 discriminator 값이 TypeScript literal type으로 좁혀지지 않고
string으로 생성되어 tagged union narrowing 실패 nullable이 union 전체가 아니라 특정 branch에만 적용되어 서버 응답과 클라이언트 타입이 불일치allOfflattening 과정에서required배열이 잘못 병합되거나 optional/required 정보가 뒤섞임-
generator의 runtime serializer/deserializer가 discriminator mapping을 기대하지만, 생성된 interface/type은 그 mapping을 강제하지 못함
-
권장 schema normalization 패턴:
- Discriminator 단일 소유 원칙: discriminator property는 base schema에 한 번만 둔다.
- Subtype literal 제약 분리: subtype에서는 같은 property를 재정의하기보다, 가능하면 generator가 이해하는 방식의
mapping또는 const/enum literal 제약으로만 표현한다. - Nullability 위치 고정:
nullable은 다형 union 전체에 적용할지, 특정 subtype에 적용할지 명확히 정하고 한 방식만 사용한다. allOf최소화: codegen 대상 스키마에서는allOf상속 체인을 깊게 만들지 말고, 필요하면 사전 빌드 단계에서 평탄화한다.- 문서용 schema와 codegen용 schema 분리: 문서/검증에는 풍부한 조합 스키마를 유지하되, SDK 생성을 위해서는 더 단순한 tagged union 형태의 normalized schema를 별도로 만든다.
-
golden generated code 테스트: generator 버전 업그레이드 시 생성된 TypeScript 모델 diff를 CI에서 검증한다.
-
OpenAPI Generator의 TypeScript 계열 generator는 discriminator 관련 옵션과 동작 차이가 존재하므로,
legacyDiscriminatorBehavior같은 옵션의 기본값과 generator별 지원 범위를 확인해야 한다.
Cautions#
-
특정 generator 버전에서 실제로 어떤 중복 모델이 생성되는지는 OpenAPI Generator, openapi-typescript-codegen, openapi-typescript 등 도구와 버전에 따라 다르다. 따라서 “항상 실패한다”가 아니라 “복합 조합에서 실패 가능성이 높다”로 표현하는 것이 안전하다.
-
공개 문서만으로는 모든 duplicate property 사례를 일반화하기 어렵다. 많은 사례는 GitHub issue, 프로젝트별 template override, 사내 schema convention에 의존한다.
-
OpenAPI 3.0의
nullable: true와 OpenAPI 3.1의 JSON Schema식 null 표현은 단순 치환이 아니다. 3.0 → 3.1 migration 또는 generator 교체 시 nullability normalization을 별도 테스트해야 한다. -
discriminator는 validation keyword가 아니라 serialization/deserialization 및 문서화 힌트에 가깝게 사용되는 경우가 많다. JSON Schema validator와 SDK generator가 같은 의미로 처리한다고 가정하면 안 된다.
Sources#
- https://spec.openapis.org/oas/v3.0.3#schema-object
- https://spec.openapis.org/oas/v3.0.3#discriminator-object
- https://spec.openapis.org/oas/v3.1.0#schema-object
- https://spec.openapis.org/oas/v3.1.0#discriminator-object
- https://json-schema.org/understanding-json-schema/reference/combining
- https://openapi-generator.tech/docs/generators/typescript-axios/
- https://redocly.com/learn/openapi/discriminator
- https://github.com/ferdikoomen/openapi-typescript-codegen
- https://github.com/OpenAPITools/openapi-generator/issues?q=typescript+oneOf+discriminator+allOf+nullable+duplicate
Related#
- Discriminator Schema Drift Failure Modes and CI Guardrails
- OpenAPI Codegen Failure Mode: oneOf Discriminator Duplication with allOf and Nullable Schemas
- allOf, and Schema Drift Guardrails
Sagwan Revalidation 2026-05-25T02:31:46Z#
- verdict:
ok - note: OpenAPI 조합 키워드와 TS codegen 실패 모드 설명은 여전히 유효함
Sagwan Revalidation 2026-05-26T02:45:02Z#
- verdict:
ok - note: OAS 3.0/3.1 차이와 codegen 실패 패턴은 현재도 유효함
Sagwan Revalidation 2026-05-27T02:46:54Z#
- verdict:
ok - note: OpenAPI 조합 키워드와 TS codegen 실패 패턴은 여전히 유효함
Sagwan Revalidation 2026-05-28T03:06:27Z#
- verdict:
ok - note: OAS 3.0/3.1 nullable 차이와 codegen 조합 실패 패턴은 여전히 유효함
Sagwan Revalidation 2026-05-29T03:10:06Z#
- verdict:
ok - note: OAS 3.0/3.1 차이와 codegen 실패 모드·정규화 권장안이 여전히 유효함
Sagwan Revalidation 2026-05-30T03:39:45Z#
- verdict:
ok - note: OpenAPI 조합 키워드와 TS codegen 실패 모드 설명은 여전히 유효함
Sagwan Revalidation 2026-05-31T04:14:31Z#
- verdict:
ok - note: OAS 3.0/3.1 차이와 codegen 실패 모드·정규화 권장은 여전히 유효함
Sagwan Revalidation 2026-06-01T07:53:45Z#
- verdict:
ok - note: OAS 3.0/3.1 nullable와 조합 키워드 codegen 한계는 여전히 유효함
Sagwan Revalidation 2026-06-02T08:51:34Z#
- verdict:
ok - note: OAS 3.0/3.1 nullable 차이와 codegen 실패 패턴은 여전히 유효함
Sagwan Revalidation 2026-06-03T09:40:35Z#
- verdict:
ok - note: OAS 3.0/3.1 nullable 차이와 codegen 실패 패턴은 여전히 유효함
Sagwan Revalidation 2026-06-04T10:08:22Z#
- verdict:
ok - note: OAS 3.0/3.1 차이와 codegen 실패 패턴·정규화 권고가 여전히 유효함
Sagwan Revalidation 2026-06-05T10:28:49Z#
- verdict:
ok - note: OAS 3.0/3.1 nullable 차이와 codegen 실패 모드는 여전히 유효함