/////

OpenAPI 3.1 Schema Composition and Codegen Failure Modes

OpenAPI 3.1에서 oneOf/anyOf/discriminator와 additionalProperties를 함께 쓰는 스키마는 코드 생성기에서 반복적으로 실패하기 쉬운 조합이다. 핵심 원인은 OpenAPI 3.1이 JSON Schema 2020-12 계열의 평가 모델을 더 가깝게 채택했지만, 많은 코드 생성기는 여전히 OpenAPI 3.0 시절의 단순 객체 모델, 상속 모델, 또는 “닫힌 객체” 해석에 기대어 타입을 만든다는 점이다. 특히 oneOf는 “정

/////

Summary#

OpenAPI 3.1에서 oneOf/anyOf/discriminatoradditionalProperties를 함께 쓰는 스키마는 코드 생성기에서 반복적으로 실패하기 쉬운 조합이다. 핵심 원인은 OpenAPI 3.1이 JSON Schema 2020-12 계열의 평가 모델을 더 가깝게 채택했지만, 많은 코드 생성기는 여전히 OpenAPI 3.0 시절의 단순 객체 모델, 상속 모델, 또는 “닫힌 객체” 해석에 기대어 타입을 만든다는 점이다.

특히 oneOf는 “정확히 하나의 스키마만 유효해야 함”을 뜻하지만, 코드 생성기는 이를 TypeScript union, Java/Kotlin sealed/interface hierarchy, 또는 discriminator 기반 팩토리로 근사한다. 여기에 additionalProperties: false, 명시적 map-like additionalProperties, 중첩 allOf, 순환 참조, discriminator mapping이 결합되면 생성된 타입이 실제 검증 의미론과 달라지거나, 컴파일 실패, 역직렬화 실패, 누락된 unknown-field 처리, 과도한 타입 폭발을 일으킬 수 있다.

Key Points#

  • OpenAPI 3.1의 Schema Object는 JSON Schema 2020-12와 더 강하게 정렬된다.
  • OpenAPI 3.1 명세는 Schema Object가 JSON Schema 2020-12 vocabulary의 superset임을 설명한다.
  • 따라서 oneOf, anyOf, additionalProperties, $ref 등의 의미는 단순 코드 상속보다 JSON Schema 평가 규칙에 가깝다.
  • 코드 생성기는 이 평가 규칙을 완전하게 구현하지 않고 언어별 타입으로 근사하는 경우가 많다.

  • oneOf의 검증 의미론과 생성 언어의 union/interface 모델 사이에 간극이 있다.

  • JSON Schema에서 oneOf는 “정확히 하나”의 subschema만 통과해야 한다.
  • TypeScript union은 보통 “둘 중 하나처럼 보이는 값”을 표현하지만 런타임에서 정확히 하나만 매칭되는지 보장하지 않는다.
  • Java/Kotlin에서는 oneOf를 interface, abstract class, wrapper, discriminator switch 등으로 변환하는데, 이때 validation semantics가 사라질 수 있다.

  • anyOf는 코드 생성에서 더 모호하다.

  • anyOf는 하나 이상 matching이면 유효하다.
  • 여러 branch를 동시에 만족할 수 있으므로, 단일 concrete class로 고르기 어렵다.
  • 생성기는 anyOfoneOf처럼 취급하거나, wrapper class를 만들거나, 가장 넓은 object/map 타입으로 퇴화시키는 경우가 있다.

  • discriminator는 JSON Schema 검증 키워드가 아니라 OpenAPI 레벨의 힌트에 가깝다.

  • OpenAPI의 discriminator는 polymorphism과 serialization/deserialization을 돕는 장치다.
  • 그러나 oneOf/anyOf의 수학적 검증 의미를 자동으로 대체하지 않는다.
  • 일부 코드 생성기는 discriminator mapping을 사용해 모델 lookup을 빠르게 하지만, 그 과정에서 “정확히 하나의 oneOf branch만 유효한지” 같은 validation을 생략할 수 있다고 문서화한다.

  • additionalProperties는 OpenAPI Generator에서 특히 주의가 필요하다.

  • OpenAPI Generator의 여러 generator 문서는 disallowAdditionalPropertiesIfNotPresent 옵션을 제공한다.
  • 이 옵션은 과거의 비표준 동작을 유지할지, OAS/JSON Schema에 더 맞는 동작을 사용할지와 관련된다.
  • 즉, 같은 스키마라도 generator 옵션에 따라 “명시되지 않은 필드 허용/금지” 모델이 달라질 수 있다.

  • 닫힌 객체 모델과 composition이 충돌한다.

  • additionalProperties: false를 각 branch에 넣으면, oneOf branch가 서로의 필드를 unknown property로 판단해 validation 또는 generated model mapping이 실패할 수 있다.
  • allOf로 base schema와 child schema를 합성하면서 각 단계에 additionalProperties: false를 두면, base가 child의 필드를 모르는 것으로 해석되는 문제가 생길 수 있다.
  • JSON Schema 2019-09/2020-12에서는 이런 문제를 완화하기 위해 unevaluatedProperties가 중요하지만, OpenAPI codegen 지원은 generator마다 제한적일 수 있다.

  • unevaluatedProperties는 이론적으로 composition 후 남은 속성 제어에 더 적합하지만, codegen 호환성은 낮을 수 있다.

  • JSON Schema 2020-12의 unevaluatedProperties는 다른 applicator keyword가 평가한 속성을 고려한 뒤 남은 속성을 제어한다.
  • 이는 allOf/oneOf/anyOf와 닫힌 객체 모델을 함께 쓸 때 additionalProperties: false보다 자연스러운 경우가 있다.
  • 하지만 많은 OpenAPI codegen 도구가 이를 타입 생성에 완전 반영하지 않을 수 있으므로, 호환성 검증이 필요하다.

  • 실무 mitigation pattern

  • 공개 SDK 생성을 목표로 한다면 oneOf/anyOf를 깊게 중첩하지 않는다.
  • discriminator.propertyName은 반드시 required에 포함시키는 편이 안전하다.
  • discriminator 값은 enum 또는 const-like pattern으로 branch마다 명확히 분리한다.
  • branch 간 required field가 겹치지 않도록 하거나, discriminator 없이도 구분 가능한 구조를 만든다.
  • additionalProperties: false를 모든 composition layer에 반복해서 넣지 않는다.
  • OpenAPI 3.1 + JSON Schema 2020-12 기능을 적극 사용하려면, 대상 generator가 실제로 해당 키워드를 어떻게 처리하는지 golden-file 테스트를 둔다.
  • TypeScript, Java, Kotlin 각각에 대해 생성 코드 컴파일 테스트와 런타임 serialization/deserialization 테스트를 별도로 수행한다.
  • SDK codegen용 스펙과 엄밀한 validation용 스키마를 분리하는 것도 현실적인 선택이다.

  • claim-worthy guidance

  • “OpenAPI 3.1의 JSON Schema 의미론을 코드 생성 타입 시스템이 완전히 보존한다고 가정하면 안 된다.”
  • oneOf + discriminator는 deserialization 힌트이지, 생성 코드가 oneOf validation을 보장한다는 뜻은 아니다.”
  • additionalProperties: false는 composition 구조에서 branch 간 필드 충돌을 유발할 수 있으므로, codegen 대상 스키마에서는 최소화하거나 unevaluatedProperties 지원 여부를 확인해야 한다.”
  • “OpenAPI Generator의 generator별 옵션, 특히 discriminator 및 additionalProperties 관련 옵션은 결과 타입 의미론을 바꿀 수 있으므로 고정하고 문서화해야 한다.”

Cautions#

  • 이 초안은 공개적으로 확인 가능한 명세 문서와 도구 문서를 기반으로 한 일반화다. 특정 버전의 OpenAPI Generator, Swagger Codegen, TypeScript generator, Kotlin generator, Java generator에서의 실제 동작은 버전과 옵션에 따라 달라질 수 있다.
  • GitHub issue 수준의 개별 버그 사례는 이 초안에 직접 인용하지 않았다. private capsule을 확정하려면 generator별 최신 issue와 changelog를 추가 조사해야 한다.
  • unevaluatedProperties는 JSON Schema 2020-12에서 composition과 닫힌 객체 모델을 다룰 때 중요한 키워드지만, OpenAPI codegen 도구들이 이를 모두 지원한다고 가정하면 안 된다.
  • discriminator를 사용해도 oneOf validation이 자동으로 강제되는 것은 아니다. 일부 generator 옵션은 discriminator lookup을 빠르게 하는 대신 validation을 생략할 수 있다고 문서화한다.
  • additionalProperties: false를 넣는 것이 항상 나쁜 것은 아니다. 다만 composition과 함께 사용할 때 generator 및 validator 간 해석 차이를 반드시 테스트해야 한다.

Sources#

  • https://spec.openapis.org/oas/v3.1.0.html
  • https://json-schema.org/draft/2020-12/json-schema-core.html
  • https://json-schema.org/draft/2020-12/json-schema-validation.html
  • https://openapi-generator.tech/docs/generators/typescript-fetch/
  • https://openapi-generator.tech/docs/generators/java
  • https://openapi-generator.tech/docs/generators/kotlin
  • https://swagger.io/docs/specification/v3_0/data-models/inheritance-and-polymorphism/
  • https://swagger.io/docs/specification/v3_0/data-models/dictionaries/

Sagwan Revalidation 2026-05-16T06:43:43Z#

  • verdict: ok
  • note: OAS 3.1/JSON Schema 조합의 codegen 한계는 여전히 유효하다.

Sagwan Revalidation 2026-05-17T07:04:23Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마와 codegen 한계 설명은 여전히 유효하다.

Sagwan Revalidation 2026-05-18T07:27:41Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합별 코드생성 한계는 현재도 유효한 실무 주의점이다.

Sagwan Revalidation 2026-05-19T07:54:54Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마와 코드생성 한계 설명은 여전히 유효함

Sagwan Revalidation 2026-05-20T08:16:57Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마의 코드생성 한계는 여전히 유효하다.

Sagwan Revalidation 2026-05-21T08:20:08Z#

  • verdict: ok
  • note: 전날 검증 이후 관련 명세·codegen 관행 변화가 없어 유효함

Sagwan Revalidation 2026-05-22T08:45:44Z#

  • verdict: ok
  • note: OAS 3.1/JSON Schema 조합의 codegen 한계는 여전히 유효함

Sagwan Revalidation 2026-05-23T09:05:26Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마와 코드 생성기 한계 설명은 여전히 유효함

Sagwan Revalidation 2026-05-24T09:16:06Z#

  • verdict: ok
  • note: 최근 관행과 명세 해석 모두 여전히 유효해 보입니다.

Sagwan Revalidation 2026-05-25T09:53:43Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마의 codegen 한계는 여전히 유효하다.

Sagwan Revalidation 2026-05-26T10:09:19Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마의 codegen 한계는 여전히 유효함

Sagwan Revalidation 2026-05-27T11:00:43Z#

  • verdict: ok
  • note: 전날 검증 이후 관련 명세·코드 생성 관행 변화가 없어 여전히 유효함

Sagwan Revalidation 2026-05-28T11:00:59Z#

  • verdict: ok
  • note: 2026년 현재도 OpenAPI 3.1 코드생성 한계 설명이 유효함

Sagwan Revalidation 2026-05-29T11:17:24Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합/코드젠 실패 모드는 현재 practice와도 부합함

Sagwan Revalidation 2026-05-30T11:20:09Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마와 코드생성 한계 설명은 여전히 유효함

Sagwan Revalidation 2026-05-31T11:48:36Z#

  • verdict: ok
  • note: 전일 검증 이후 명세·codegen 관행 변화 없어 재사용 가능

Sagwan Revalidation 2026-06-01T15:31:34Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마의 코드 생성 한계는 여전히 유효하다.

Sagwan Revalidation 2026-06-02T19:52:41Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마의 코드생성 한계 설명은 여전히 유효하다.

Sagwan Revalidation 2026-06-03T20:49:29Z#

  • verdict: ok
  • note: OpenAPI 3.1 조합 스키마와 코드 생성기 한계 설명은 여전히 유효함

Sagwan Revalidation 2026-06-04T20:57:20Z#

  • verdict: ok
  • note: 전일 검증 이후 관련 명세·관행 변화 없어 내용은 여전히 유효함

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1