빠른 비교
| keyword | 보는 범위 | 잘 맞는 상황 |
|---|---|---|
additionalProperties | 같은 schema object의 properties 이후 | 단일 object schema |
unevaluatedProperties | 적용된 schema들이 평가하지 않은 member | allOf, $ref 조합 |
properties | 이름이 고정된 member 규칙 | 기본 object 검증 |
patternProperties | 패턴 기반 동적 key | prefix나 regex key |
{
"allOf": [
{ "$ref": "#/$defs/baseUser" }
],
"properties": {
"role": { "type": "string" }
},
"unevaluatedProperties": false
}조합 경계
additionalProperties는 같은 schema 조각 안에서 닫는다
additionalProperties: false는 같은 schema object 안의 properties와 patternProperties가 다루지 않은 member를 제한합니다. allOf 안쪽 schema와 바깥 schema를 자동으로 합쳐서 전체 object를 닫아 주는 문법이 아닙니다.
{
"allOf": [
{
"type": "object",
"properties": {
"id": { "type": "string" }
},
"additionalProperties": false
}
],
"properties": {
"name": { "type": "string" }
}
}이런 구조에서는 바깥의 name이 안쪽 schema 기준으로는 additional property처럼 보일 수 있습니다. schema를 조합할 때 닫힌 object가 예상보다 빨리 막히는 이유입니다.
unevaluatedProperties는 조합 뒤에 남은 member를 본다
unevaluatedProperties는 현재까지 적용된 schema들이 평가하지 않은 member를 대상으로 합니다. 그래서 $ref, allOf, 조건부 schema를 통해 여러 곳에서 property를 정의한 뒤 마지막에 남은 필드를 막는 용도에 적합합니다.
{
"allOf": [
{ "$ref": "#/$defs/baseUser" }
],
"properties": {
"department": { "type": "string" }
},
"unevaluatedProperties": false
}이 구조는 base schema와 현재 schema가 평가한 필드를 모두 고려한 다음, 그 밖의 필드를 닫는 의도에 가깝습니다.
validator draft 지원을 먼저 확인해야 한다
unevaluatedProperties는 최신 draft 계열에서 쓰는 keyword입니다. 오래된 validator나 draft를 쓰는 환경에서는 동작하지 않거나 무시될 수 있습니다. 따라서 $schema를 명시하고, 실제 사용하는 validator가 해당 draft와 keyword를 지원하는지 확인해야 합니다.
선택 기준
| 상황 | 선택 |
|---|---|
| 단일 object schema를 닫음 | additionalProperties: false |
allOf로 공통 schema를 합침 | unevaluatedProperties: false 검토 |
$ref로 property를 재사용 | unevaluatedProperties 검토 |
| draft 호환성이 낮음 | 단순 schema로 재구성 |
| 외부 API 응답 검증 | 닫힌 schema를 신중히 사용 |
주의할 점
unevaluatedProperties는 additionalProperties의 단순 대체제가 아닙니다. 조합 schema에서 어떤 member가 이미 평가되었는지에 의존하므로, validator draft와 구현 지원을 반드시 확인해야 합니다.
schema를 너무 닫으면 확장성이 떨어집니다. 내부 설정 파일에는 유용하지만, 외부 API 응답처럼 새 필드가 추가될 수 있는 데이터에는 과도한 결합을 만들 수 있습니다.
참고 링크
2 sources