24 KiB
title, source_type, status, confidence, tags, related_projects, last_reviewed
| title | source_type | status | confidence | tags | related_projects | last_reviewed | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| API Evolution & Schema (compatibility + serialization + HTTP contract surface) | llm-generated | reviewed | medium |
|
|
2026-06-04 |
API Evolution & Schema (compatibility + serialization)
Layer:
wiki/concepts/— 일반 개념. 특정 프로젝트의 결정/구현 사실은wiki/projects/에서 다룬다.
Summary
API evolution은 두 축으로 나뉜다. (1) compatibility / deprecation — 응답 필드 제거나 의미 변화를 막기 위해 breaking change를 분류하고 migration window 동안 deprecated marker와 Sunset 헤더로 client에게 신호를 보낸다. (2) schema / serialization — date·money·enum·null·unknown field의 의미를 framework default에 맡기지 않고 명시 계약으로 고정한다. 대표 결정 라인업은 90d public + 30d internal migration window, RFC 8594 Sunset 헤더, ISO-8601 offset datetime (UTC default), BigDecimal scale 2 + HALF_UP, strict inbound / tolerant outbound 정책이다.
Standard (공식 정의)
Compatibility / deprecation 표준 후보
- RFC 8594 Sunset header (IETF): 응답 헤더로 자원이 응답 불가가 될 시점을 HTTP-date로 알린다.
Sunset단독은 언제 사라지는지 신호일 뿐이고, deprecation 자체는 별도Deprecation헤더(IETF draft)로 표시하는 것이 표준 의도다. - Microsoft REST API versioning policy:
api-versionquery/header를 정식 권고. major version 단위 breaking change 허용, minor/preview는 additive only. preview API는 별도 lifecycle. - GitHub REST API: 2022년부터
X-GitHub-Api-Version: YYYY-MM-DD날짜 헤더. 새 버전 release 후 24개월 EOL 정책, EOL된 버전 호출은410 Gone응답. preview API는Accept헤더application/vnd.github.<name>-preview+json로 옵트인. - Stripe date-based versioning: account마다 첫 호출 시 version pin. 이후 새 version이 나와도 client가 명시적으로 upgrade하지 않으면 freeze forever (Stripe가 영구적으로 구버전 응답을 유지). 외부 컨슈머 규모가 큰 결제 도메인 특화.
- Google AIP-180 (Backwards compatibility): enum value 제거 / 의미 변경 / 응답 필드 제거 / 기본값 변경 / required request field 추가 모두 breaking으로 분류. additive (optional response field 추가)만 minor에 허용.
- Twitter tier-based: legacy / current / beta 트랙 병렬 운영.
- Spring HATEOAS: 응답에
_links로 다음 자원 URI를 동봉해 client가 version이 아닌 link relation에 결합하게 한다.
Schema / serialization 표준 후보
- ISO-8601: date·time·datetime·duration의 wire 표현 표준. offset datetime(
2026-05-22T11:30:00+09:00또는Z)이 timezone ambiguity 회피의 정석. - JSON Schema (draft 2020-12): JSON payload의 shape 검증 spec.
additionalProperties: false로 unknown field strict,nullable/required/enum으로 의미 분리. - OpenAPI 3.1: JSON Schema 2020-12 정합. response shape SSOT 후보.
deprecated: true플래그를 schema/operation 양쪽에 둘 수 있어 deprecation marker 표준 위치가 된다. - Avro schema evolution: backward / forward / full compatibility를 schema registry가 자동 검사. 필드 추가/삭제 시 default 의무, alias로 rename. event/outbox 환경에 우위.
- Protobuf:
reserved키워드로 field number와 name 재사용을 영구 차단. wire-format 기반 strict typing. - Jackson (Java):
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES는 defaulttrue. 단,FAIL_ON_NULL_FOR_PRIMITIVES는 defaultfalse라 null/missing primitive가 묵시적으로 0이 된다. 출력측은SerializationFeature.WRITE_DATES_AS_TIMESTAMPS(defaultfalse→JavaTimeModule경유 ISO-8601 문자열,true면 epoch/배열)와JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN(defaultfalse→ 큰 값이 지수 표기1.23E+10)이 wire 형식을 좌우한다. 이 둘은 프레임워크 기본값이라 버전 업그레이드로 flip 될 수 있으므로 계약을 명시 핀하고 effective bean 동작 테스트로 회귀를 잡는 것이 안전하다. - Property naming strategy: Jackson
PropertyNamingStrategies(camelCase default /SNAKE_CASE/KEBAB_CASE)는 wire 의 field 이름 컨벤션을 결정한다. 한 번 정하면 client 가 그 이름에 결합하므로 변경 자체가 breaking — 전역 strategy 변경은 모든 응답 field rename 과 동치다. - Null vs absent (
@JsonInclude):JsonInclude.Include.NON_NULL/NON_ABSENT/NON_EMPTY는 null 또는 빈 값을 출력에서 생략 한다. 생략(absent)과 명시적null은 client 에게 다른 의미(부재 vs 값이 null) 일 수 있어, JSON Merge Patch 같은 부분 갱신 의미가 필요하면JsonNullable<T>로 3-상태(present-null / present-value / absent)를 구분한다. - Java BigDecimal: 금액 계산 표준.
new BigDecimal(double)함정 (0.1→0.1000000000000000055511151231257827021181583404541015625),setScale(2, RoundingMode.HALF_UP)패턴, JSON에서는 string 직렬화로 client 부동소수 손실 회피가 표준 권고. - Smithy: AWS의 API modeling DSL. SDK 코드 생성 친화적, 단 외부 ecosystem에서는 OpenAPI보다 미성숙.
HTTP contract surface 표준 (conditional request / cache / pagination)
versioning·schema 와 별개로, HTTP API surface 자체의 일반 계약 표준. (RFC 9110/9111 은 IETF official-standard, AIP 는 Google community guideline)
- Conditional request (RFC 9110 §13):
ETag는 representation 의 opaque validator (weakW/"..."또는 strong). write 는If-Match로 optimistic concurrency 검증 — condition 이 false 면 412 Precondition Failed. read 는If-None-Match로 cache validation — match 면 304 Not Modified (body 없음, client 저장본 사용). RFC 9110 은If-Match에 strong comparison 을 MUST 로 요구한다. - HTTP caching (RFC 9111 §5.2):
Cache-Controldirective —no-store(저장 금지, 인증 API 안전 default),private(shared cache 저장 금지),public(Authorization 있어도 shared cache 허용),max-age=N(stale 판정 초). 협상/인증 응답은Vary(RFC 9110 §12.5.5) 로 어떤 request 부분이 content 선택에 영향을 줬는지 명시해 proxy/CDN cache poisoning 을 막는다. - Pagination (Google AIP-158, JSON:API): offset (
page/size) vs cursor (opaque token). AIP-158 은 page token 이 opaque + URL-safe MUST, server-side size cap SHOULD coerce, empty next-token = end-of-collection 을 규정. JSON:API 는linksobject 안의first/last/prev/nextkey 위치를 정의. 구체 숫자(size cap, TTL)는 표준이 아닌 구현 trade-off. - Transport error 의미 구분 (RFC 9110 §15): 413 Content Too Large, 406 Not Acceptable (응답 표현 협상 실패) vs 415 Unsupported Media Type (요청 본문 format), 405 Method Not Allowed (+
Allowheader MUST). 같은 code 로 뭉개면 표준 의미가 손실된다. - Long-running operation (Google AIP-151 + RFC 9110): 비동기 처리는 202 Accepted +
Locationpolling URL + Operation 객체(done/response/error).Retry-After로 polling interval 권고.
한계 / 주의점
Compatibility / deprecation 측
- Stripe freeze-forever: 무기한 구버전 유지 비용이 외부 결제 컨슈머 규모에서만 정당화된다. internal API에 그대로 차용하면 server 코드에 N개 버전 분기를 영구 운반하게 된다.
- GitHub 24개월 EOL +
410 Gone: 길어 보이는 EOL window지만 catalog에 EOL 응답 코드(410)를 명시하지 않으면 client 입장에서 어느 날 갑자기 410과 다를 바 없다. EOL 응답 코드 자체를 contract에 박는 것이 필요하다. - Twitter tier-based (legacy/current/beta): 트랙별 행위 분기가 server-side 복잡도와 운영 비용을 곱한다. 단일 팀 / internal-first 환경에 과하다.
- Spring HATEOAS (links over versions): 이론적으로 우아하지만 실제 client가
_links를 dynamic하게 따라가는 경우는 드물고, 학습 곡선과 client 구현 강제 비용이 크다. - Google AIP-180
enum value 제거 = breaking: client switch/case 누락을 유발하므로 strict 분류가 맞지만, enum value 추가 또한 client 입장에서 unknown enum 처리 정책이 없으면 깨진다 — server-side enum addition을 "additive"로만 분류하는 단순화는 위험하다. Sunset단독 사용: RFC 8594는 언제 사라지는지만 알린다. 같은 자원이 이미 deprecated인지는Deprecation헤더로 함께 보내야 정합이다. Sunset만 보내면 "사라질 날짜는 알지만 지금 권장 여부는 모름" 상태가 된다.Sunset헤더 단독 사용 금지 —Deprecationdraft와 paired: IETF httpapi WG 권고에 따르면Sunset헤더는Deprecation헤더(draft-ietf-httpapi-deprecation-header, RFC 9745 진행)와 paired로 송신해야 client tooling이 deprecation 상태를 감지할 수 있다. paired invariant는 "Sunset 시점 ≥ Deprecation 시점". 추가로Link: <url>; rel="deprecation"/rel="sunset"을 함께 보내 사람-가독 가이드를 연결한다. ca-tmpl처럼 marker만 OpenAPI에 박고 응답 헤더 paired 송신을 누락하면 외부 client interceptor가 deprecation을 자동 인지하지 못한다.
Schema / serialization 측
- Avro / Protobuf strict typing: schema registry가 backward/forward 자동 검사로 강력하나, 외부 REST API가 JSON인 환경에서는 outbox / event 한정 도입이 현실적이다.
- Smithy: AWS SDK 친화적이지만 외부 ecosystem(예: third-party tooling, doc generator) 성숙도가 OpenAPI 대비 낮다.
- Jackson default:
FAIL_ON_UNKNOWN_PROPERTIES=true는 strict inbound와 정합하나,FAIL_ON_NULL_FOR_PRIMITIVES=false는 null/empty/missing 분리 정책과 불일치다 — 명시적으로 override하지 않으면 contract가 깨진 줄도 모르고 0이 흘러간다. - "Jackson은 unknown field tolerant가 default"라는 오해: 보안/계약 측면에서 unknown inbound를 silently 허용하면 typo로 인한 데이터 손실 + payload smuggling 모두 위험. strict inbound가 안전 default.
- JSON 환경의 Protobuf
reserved흉내: Protobuf는 field number / name 재사용을 wire-format 수준에서 영구 차단한다(reserved 3, 5;/reserved "foo";). OpenAPI 3.1 / JSON Schema 2020-12에는 동등 시맨틱이 없다 —deprecated: true는 비권장 신호일 뿐 재사용 차단이 아니고, field가 사라지면 schema에서도 사라져 미래 재사용 방지 불가. 현실적 대안은 두 가지: (1) OpenAPIx-removed-fields같은 Specification Extension으로 schema SSOT에 catalog를 통합하고 자체 lint로 재사용 검출, (2) 별도 markdown catalog(예:docs/removed-fields-catalog.md)에 제거된 이름/번호/일자 기록 후 CI에서 OpenAPI diff와 cross-check. 둘 다 표준 검증 도구가 없어 자체 도구 작성이 따라온다. (needs-confirmation) new BigDecimal(double)함정: 같은0.1이BigDecimal.valueOf(0.1)(정확)과new BigDecimal(0.1)(부동소수 잔차)으로 갈린다. 코드 review 규칙으로 차단하지 않으면 unit test 통과 + 운영에서 1원 차이 인시던트가 흔하다.- ISO-8601 offset 없는 datetime:
2026-05-22T11:30:00는 표준상 valid이지만 timezone이 누락된다. 서버 timezone에 따라 의미가 달라지므로 contract에서는 offset 필수로 강제해야 한다. 직렬화 형식을WRITE_DATES_AS_TIMESTAMPS=false로만 핀해도JavaTimeModule(jackson-datatype-jsr310)이 등록되지 않으면LocalDateTime이[2026,5,22,...]배열로 직렬화되므로, module 등록 + effective 직렬화 동작 테스트가 함께 필요하다. - naming strategy 변경 = 전역 breaking change: snake_case ↔ camelCase 같은
PropertyNamingStrategy전역 변경은 모든 응답 field 이름이 바뀌는 것과 같아 deprecation window 없이 적용하면 client 가 일제히 깨진다. naming 은 초기에 고정하고 이후 변경을 breaking change catalog 대상으로 다뤄야 한다. @JsonInclude(NON_NULL)의 의미 손실: null 생략은 payload 를 줄이지만 "값이 null" 과 "field 부재" 를 구분 불가하게 만든다. 부분 갱신(PATCH/merge-patch) contract 에서는 이 구분이 의미를 가지므로 3-상태(JsonNullable/Optional) 표현을 별도로 둬야 하고, 무분별한 NON_NULL 전역 적용은 이 의미 분리를 무너뜨린다.
흔한 오해
- "Stripe 방식이 표준이다" — IETF/W3C 표준이 아니고 진영별 사례다. 외부 결제 컨슈머 규모를 가정한 trade-off의 결과다.
- "
Sunset헤더만 보내면 deprecation은 끝이다" — 잘못.Deprecation헤더(현재 진행 중인지)와Sunset헤더(언제 사라지는지)는 함께 사용해야 정합이다. - "Jackson은 unknown field tolerant가 안전한 default다" — 잘못. inbound strict가 보안/계약 안전 default이고, outbound는 schema에 없는 field가 노출되지 않도록 controlled해야 한다(소위 strict inbound / tolerant outbound가 아니라 "strict inbound / schema-controlled outbound"가 정확).
- "enum 값 추가는 무조건 additive다" — server-side 입장에서는 additive지만 client 입장에서는 unknown enum 처리 정책이 없으면 깨진다. client side에 unknown enum fallback이 contract로 명시되어야 비로소 additive다.
Project Application
- wiki/projects/ca-tmpl/api-evolution-and-schema — ca-tmpl 의사결정 기록 (현재
documented-only, Phase C2 미진입). 실제 구현 여부는 project 문서 참조. - raw/project-notes/ca-skeleton-operational-contract §13 API Contract Surface / §16 Schema / Serialization Contract / §18 API Compatibility / Deprecation / §29 G-F (외부 근거 인덱스)
- raw/branch-notes/feature-api-compatibility-deprecation-contract — breaking change catalog(7행), 90d/30d migration window, OpenAPI
deprecated: truemarker, Sunset 헤더 채택 - raw/branch-notes/feature-schema-serialization-contract — ISO-8601 offset/UTC, BigDecimal scale 2 + HALF_UP, unknown field strict inbound, null/empty/missing 의미 분리
위 branch-note들이 (a) breaking change 7 분류 + migration window + deprecation marker 위치, (b) serialization producer 책임(date/time/money/enum/null/unknown)을 계약으로 둔다. canonical 승급 여부와 검증 등급은 해당 project 문서가 판정한다.
ca-tmpl 의 HTTP contract surface (versioning/pagination/conditional/cache/OpenAPI) 는 위 두 축과 달리 실제 코드로 구현·로컬 검증됐다 — 구현 사실과 검증 등급은 wiki/projects/ca-tmpl/api-evolution-and-schema 의 "API contract baseline 구현" 절 참조.
Claim-backed Knowledge
각 Knowledge Point 는 이미 §Sources 에 인용된 자료로만 뒷받침된다. company-tech-blog 출처는 사례일 뿐 official best practice 로 격상하지 않는다.
| Knowledge Point | Supporting Claims | Confidence | Notes |
|---|---|---|---|
Sunset 헤더는 자원이 응답 불가가 될 시점을 HTTP-date 로 알리며 Deprecation 헤더와 paired 송신해야 client tooling 이 deprecation 상태를 감지 |
raw/official-docs/compat-rfc-8594-sunset-header, raw/official-docs/sunset-deprecation-headers-paired-usage | high | official-standard(RFC 8594) + IETF httpapi draft. "Sunset 단독 충분" 금지. invariant: Sunset 시점 ≥ Deprecation 시점 |
| Google AIP-180 은 enum 제거/의미변경, 응답 필드 제거, 기본값 변경, required request field 추가를 breaking 으로 분류 | raw/official-docs/api-versioning-google-aip-180 | high | official-reference (Google community guideline, IETF/W3C 표준 아님). additive 만 minor 허용 |
Jackson FAIL_ON_UNKNOWN_PROPERTIES default true (strict inbound) 이나 FAIL_ON_NULL_FOR_PRIMITIVES default false (null/missing primitive → 묵시적 0) |
raw/official-docs/schema-jackson-unknown-field-handling | high | official-vendor-doc. "Jackson default 가 안전" 금지 — 후자는 명시 override 필요 |
new BigDecimal(double) 은 부동소수 잔차를 남기므로 BigDecimal.valueOf + setScale(2, HALF_UP) + JSON string 직렬화 권고 |
raw/official-docs/schema-bigdecimal-money-serialization-java | high | official-vendor-doc. client 부동소수 손실 회피 |
| ISO-8601 offset datetime 이 timezone ambiguity 회피의 정석, offset 없는 표현은 서버 timezone 의존 | raw/official-docs/schema-jackson-unknown-field-handling | medium | wire 계약에서 offset 강제 근거 (ISO-8601 일반 상식 + Jackson 직렬화 자료) |
OpenAPI 3.1 은 JSON Schema 2020-12 정합의 machine-readable HTTP API contract 이며 deprecated: true marker 를 schema/operation 양쪽에 둘 수 있음 |
raw/official-docs/openapi-spec-3-1-0 | high | official-standard(OAS/Linux Foundation). "marker 만으로 client 가 알아서 migrate" 금지 |
Protobuf reserved 는 field number/name 재사용을 wire-format 수준에서 영구 차단하나 OpenAPI/JSON Schema 에는 동등 시맨틱이 없음 |
raw/official-docs/schema-protobuf-vs-json-evolution, raw/official-docs/protobuf-reserved-vs-json-openapi-extension | medium | official-reference. "JSON 에서 완벽 흉내" 금지 — x- extension + 자체 lint 필요, needs-confirmation |
RFC 9110 conditional request: ETag validator + If-Match(write, strong comparison MUST)→412 + If-None-Match(read)→304; RFC 9111 cache directive(no-store/private/public/max-age) + Vary 로 cache poisoning 방지 |
raw/official-docs/rfc9110-http-semantics, raw/official-docs/rfc9111-http-caching | high | official-standard(IETF). ca-tmpl 의 weak/lenient If-Match 비교는 skeleton 단순화 — project 문서 참조 |
Pagination: AIP-158 은 page token opaque+URL-safe MUST, server-side size cap SHOULD coerce, empty next-token = EoC. JSON:API 는 links 의 first/last/prev/next 위치 정의 |
raw/official-docs/spring-data-pageable-defaults (offset/zero-indexed) | medium | official-vendor-doc(Spring). size cap 숫자/TTL 은 표준 아닌 구현 trade-off |
내가 설명할 수 있어야 하는 것
- API evolution 의 세 영역 분리: compatibility/deprecation vs schema/serialization vs HTTP contract surface (versioning/pagination/conditional/cache). 세 영역이 framework default 가 아니라 명시 계약이어야 하는 이유.
SunsetvsDeprecation헤더의 역할 분리와 paired 송신 이유, paired invariant.- breaking change 분류 기준 (enum 축소/제거, 응답 필드 제거, 기본값 변경, required request field 추가) 과 "internal API 니까 그냥 한다" 가 위험한 이유 (client deploy lag).
- strict inbound / schema-controlled outbound 의 정확한 의미와 Jackson 의 두 feature default 차이.
- money 직렬화에서
double위험 /BigDecimal.valueOf/ HALF_UP / JSON string 직렬화 근거. - conditional request 가 DB optimistic lock 과 같은 충돌의 HTTP 표현이라는 점 (ETag → If-Match → 412, If-None-Match → 304), strong vs weak comparison 차이.
- 인증 API 의 안전한 cache default =
no-store+Vary가 cache poisoning 을 막는 원리. - offset vs cursor pagination trade-off, size cap 이 DoS 방어인 이유, page token opacity 의 의미.
- transport error 의미 구분 (406 vs 415, 405 +
Allow, 413/414) 을 같은 code 로 뭉개면 안 되는 이유.
Interview Questions
- 90d public + 30d internal migration window의 근거는? 더 짧게/길게 잡으면 어떤 비용이 생기는지? Stripe(freeze forever)나 GitHub(24mo EOL)와 비교했을 때 internal-first 환경에서 90d가 합리적인 이유는?
Sunset헤더와Deprecation헤더의 차이는? 둘 중 하나만 보내면 client 입장에서 어떤 정보가 빠지는지?- enum value 추가/제거가 breaking change가 되는 이유는? client side에 unknown enum fallback이 있을 때와 없을 때 분류가 어떻게 달라지는지?
- strict inbound / tolerant outbound가 무슨 의미인지? Jackson
FAIL_ON_UNKNOWN_PROPERTIES와FAIL_ON_NULL_FOR_PRIMITIVES는 default가 어떻게 잡혀 있고, 어느 쪽을 override해야 하는지? - money 직렬화에서
BigDecimalscale 2 + HALF_UP을 택한 이유는?double이 위험한 이유,new BigDecimal(double)함정, JSON string 직렬화로 client 부동소수 손실을 회피하는 이유를 설명할 수 있는지?
Do Not Overclaim
- "Stripe 방식이 API versioning의 표준이다"라고 말하면 안 된다 — 진영별 사례이며 외부 결제 컨슈머 규모에 특화된 trade-off다.
- "
Sunset헤더만 보내면 deprecation 정책으로 충분하다"라고 말하면 안 된다 —Deprecation헤더와 함께 사용해야 정합이다. - "OpenAPI
deprecated: true로 표시했으니 client가 알아서 migration한다"라고 단정하면 안 된다 — schema marker는 신호일 뿐이고 실제 cutover는 migration window + contract test + compatibility fixture가 함께 강제해야 한다. - "Jackson default가 안전하다"고 단정하면 안 된다 —
FAIL_ON_UNKNOWN_PROPERTIES는 strict default이지만FAIL_ON_NULL_FOR_PRIMITIVES는 lenient라 null/missing primitive가 묵시적으로 0이 된다. - "Avro / Protobuf로 가면 schema evolution이 자동 검사된다"라고 일반화하면 안 된다 — registry 인프라(예: Confluent Schema Registry)와 wire format 변경 비용이 따라온다. 외부 REST가 JSON인 환경에서는 outbox/event 한정 도입이 현실적이다.
- "narrow enum / 응답 필드 제거 / 필드 rename"을 "internal API니까 그냥 한다"라고 정당화하면 안 된다 — client가 deploy lag을 가지면 internal에서도 breaking이다.
Sources
공식 표준 / 표준 후보
- raw/official-docs/compat-rfc-8594-sunset-header — IETF RFC 8594 (HTTP
Sunsetheader) - raw/official-docs/sunset-deprecation-headers-paired-usage — IETF RFC 8594 + Deprecation draft paired 사용 권고 (Sunset 단독 금지)
- raw/official-docs/api-versioning-google-aip-180 — Google AIP-180 (Backwards compatibility 분류)
- raw/official-docs/schema-jackson-unknown-field-handling — Jackson DeserializationFeature default
- raw/official-docs/schema-bigdecimal-money-serialization-java — Java BigDecimal scale/HALF_UP + JSON string 직렬화
- raw/official-docs/schema-avro-evolution-rules — Avro backward/forward/full compatibility
- raw/official-docs/schema-protobuf-vs-json-evolution — Protobuf
reservedfield semantics - raw/official-docs/protobuf-reserved-vs-json-openapi-extension — Protobuf
reserved시맨틱의 JSON/OpenAPI 환경 흉내 대안 비교 (G-F follow-up, needs-confirmation) - raw/official-docs/rfc9110-http-semantics — IETF RFC 9110 (HTTP Semantics): conditional request(ETag/If-Match/If-None-Match/304/412), transport error(406/413/414/415/405+Allow), HEAD/OPTIONS, 202+Retry-After, Vary
- raw/official-docs/rfc9111-http-caching — IETF RFC 9111 (HTTP Caching):
no-store/private/public/max-agedirective - raw/official-docs/openapi-spec-3-1-0 — OpenAPI 3.1.0 (machine-readable HTTP API contract, JSON Schema 2020-12 정합)
- raw/official-docs/google-aip-185-resource-versioning — Google AIP-185 (major-only
/v1path versioning) - raw/official-docs/google-aip-158-pagination — Google AIP-158 (page token opacity + size cap + EoC)
- raw/official-docs/jsonapi-pagination-format — JSON:API pagination link key/위치
- raw/official-docs/google-aip-151-long-running-operations — Google AIP-151 (LRO Operation shape + polling)
- raw/official-docs/spring-data-pageable-defaults — Spring Data
Pageablezero-indexed + size default +DEFAULT_MAX_PAGE_SIZE2000
진영별 사례 (표준 아님)
- raw/company-tech-blogs/api-versioning-stripe-date-based — Stripe date-based versioning (account pin + freeze)
- raw/company-tech-blogs/api-versioning-github-rest-date-header — GitHub
X-GitHub-Api-Version+ 24mo EOL +410 Gone
Canonical (프로젝트 결정 사실)
- raw/project-notes/ca-skeleton-operational-contract §13 / §16 / §18 API Compatibility / Deprecation / §29 G-F
- raw/branch-notes/feature-api-compatibility-deprecation-contract
- raw/branch-notes/feature-schema-serialization-contract