핵심 정리
{
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Current workflow state",
"default": "draft",
"examples": ["draft", "published"],
"deprecated": false
}
}
}annotation 역할
default는 빈 값을 자동으로 채우지 않는다
JSON Schema의 annotation keyword는 validation 결과를 직접 바꾸는 제약이 아닙니다. default는 가장 자주 오해되는 keyword입니다. schema에 default가 있어도 validator가 missing property를 자동으로 채워야 한다는 뜻이 아닙니다. 문서 생성기, form generator, client SDK 같은 비검증 도구가 입력 힌트로 사용할 수 있는 값에 가깝습니다.
기본값을 실제 데이터에 채워 넣어야 한다면, validation 단계와 별도로 normalization 단계를 명시해야 합니다. 이 구분이 없으면 서버는 기본값을 기대하지만 클라이언트는 필드를 보내지 않고, validator는 통과하지만 애플리케이션 로직에서 값이 없어지는 문제가 생깁니다.
{
"type": "object",
"properties": {
"pageSize": { "type": "integer", "default": 20 }
}
}위 schema는 pageSize가 없을 때 validation을 실패시키지 않습니다. 필수 입력이면 required가 필요하고, 기본값 적용은 별도 처리입니다.
examples와 description은 소비자 경험을 안정화한다
title, description, examples는 schema를 읽는 사람과 도구를 위한 설명입니다. API 문서, form UI, SDK 문서에서 필드 의도를 보여 주는 역할이 크며, validation을 대체하지 않습니다. 좋은 description은 필드의 타입을 반복하기보다 단위, 범위 의미, 값이 비어 있을 때의 해석을 설명해야 합니다.
examples는 실제로 schema를 통과하는 값으로 유지하는 편이 좋습니다. 형식이 틀린 예시는 문서 사용자에게 잘못된 payload를 학습시키고, 테스트 fixture로 재사용될 때 오류를 만들 수 있습니다.
readOnly, writeOnly, deprecated는 API 계약 힌트다
readOnly는 응답에는 보이지만 수정 요청에서는 받지 않는 값, writeOnly는 요청에는 받지만 응답에는 노출하지 않는 값에 맞습니다. deprecated는 여전히 받을 수 있지만 새 사용을 피해야 하는 필드를 표시할 때 씁니다. 이 keyword들도 validator 하나만으로 전체 동작이 완성되지 않습니다. 요청/응답 serializer, 문서 생성, 서버 로직이 같은 의미로 해석해야 실제 계약이 됩니다.
어디에 쓸까
| 상황 | 적합한 keyword |
|---|---|
| 짧은 필드 이름 설명 | title |
| 단위, 의미, 사용 조건 설명 | description |
| 누락 시 의미상 기본값 표현 | default |
| 문서와 테스트용 대표 값 | examples |
| 요청에는 받지만 응답에는 숨김 | writeOnly |
| 응답 전용 값 | readOnly |
| 제거 예정 필드 표시 | deprecated |
주의할 점
annotation keyword를 validation keyword처럼 해석하면 계약이 흔들립니다. 특히 default는
missing 값을 자동으로 채우지 않으므로, 기본값 적용이 필요하면 별도 normalization 단계를 둬야 합니다.
실패 예시
- schema에 default가 있으니 서버 코드에서 값이 항상 있다고 가정
- 결과: validator는 통과하지만 애플리케이션 로직에서 undefined/null 처리 실패
- 대응: required, default, normalization의 책임을 분리한다참고 링크
1 sources