핵심 정리
| 키워드 | 기준 | 용도 |
|---|---|---|
$ref | static resolution | 고정된 schema 참조 |
$anchor | static named fragment | 현재 schema resource 안의 이름 있는 위치 |
$dynamicRef | dynamic scope | 평가 경로에 따라 바뀔 수 있는 참조 |
$dynamicAnchor | dynamic scope target | 확장 가능한 재귀 지점 |
{
"$dynamicAnchor": "node",
"type": "object",
"properties": {
"children": {
"type": "array",
"items": { "$dynamicRef": "#node" }
}
}
}동적 참조
$ref는 schema 문서만 보고 해석할 수 있다
일반 $ref는 URI와 JSON Pointer를 따라 고정된 schema 위치를 찾습니다. 같은 schema 문서와 같은 기준 URI라면 어떤 instance를 검증하든 참조 대상이 바뀌지 않습니다. 반복 조각을 $defs에 두고 내부에서 재사용하거나, 외부 schema 파일을 가져오는 대부분의 상황은 $ref로 충분합니다.
{
"$defs": {
"id": { "type": "string" }
},
"properties": {
"userId": { "$ref": "#/$defs/id" }
}
}이 구조는 읽기 쉽고 validator 지원도 넓습니다. 재귀 구조도 단순 자기 참조라면 $ref로 표현할 수 있습니다.
$dynamicRef는 평가 경로의 dynamic scope를 사용한다
JSON Schema 2020-12의 $dynamicRef와 $dynamicAnchor는 확장 가능한 재귀 schema를 위해 도입된 고급 기능입니다. 정적 $ref처럼 schema 문서 안의 위치만 보는 것이 아니라, 실제 평가가 어떤 schema를 지나왔는지에 따라 같은 이름의 dynamic anchor를 다시 찾을 수 있습니다.
{
"$id": "https://example.com/tree",
"$dynamicAnchor": "node",
"type": "object",
"properties": {
"children": {
"type": "array",
"items": { "$dynamicRef": "#node" }
}
}
}나중에 이 tree schema를 확장해 모든 node에 추가 필드를 요구하려면, 확장 schema도 같은 이름의 $dynamicAnchor를 제공할 수 있습니다. 그러면 children 쪽 재귀 참조가 원래 base node가 아니라 현재 확장된 node 규칙을 따라가도록 만들 수 있습니다.
draft와 validator 지원이 실제 경계다
$dynamicRef와 $dynamicAnchor는 Draft 2020-12에서 $recursiveRef, $recursiveAnchor를 대체한 기능입니다. 따라서 schema에 $schema를 명시하고, 실제 사용하는 validator가 2020-12의 dynamic reference를 지원하는지 확인해야 합니다. 오래된 validator는 keyword를 무시하거나 오류를 내거나, 정적 참조처럼 잘못 해석할 수 있습니다.
선택 기준
| 상황 | 선택 |
|---|---|
| 반복되는 공통 조각 재사용 | $defs + $ref |
| 외부 schema 고정 참조 | $id + $ref |
| 단순 자기 재귀 | 일반 $ref 먼저 검토 |
| 재귀 schema를 확장 schema에서 다시 특수화 | $dynamicRef + $dynamicAnchor |
| validator 호환성이 낮음 | dynamic reference 피하고 명시적 schema로 분리 |
| 오류 메시지 추적이 중요 | dynamic path를 보여 주는 validator 사용 |
대부분의 API schema에서는 $dynamicRef까지 필요하지 않습니다. 팀이 직접 schema library나 meta-schema를 만들고, 그 schema를 다른 팀이 확장하는 구조에서 가치가 커집니다.
주의할 점
$dynamicRef는 $ref의 더 좋은 기본값이 아닙니다. 평가 중 dynamic scope에 의존하므로,
schema를 읽는 사람과 validator가 같은 모델을 이해해야 합니다. 단순 재사용에는 $ref를
쓰는 편이 더 안전합니다.
실패 예시
- 단순 address schema 재사용에 $dynamicRef를 사용함
- 결과: validator 호환성 문제가 생기고 참조 대상 추적이 어려워짐
- 대응: 재귀 확장 문제가 아니면 $defs와 $ref로 유지한다참고 링크
2 sources