빠른 비교
{
"if": {
"properties": {
"country": { "const": "KR" }
},
"required": ["country"]
},
"then": {
"required": ["postalCode"]
},
"else": {
"properties": {
"postalCode": { "type": "string" }
}
}
}조건 방식
if, then, else는 값에 따라 subschema를 고른다
if가 유효하면 then이 적용되고, if가 유효하지 않으면 else가 적용됩니다. 국가별 우편번호, 결제 수단별 필수 field, 타입별 payload 구조처럼 한 field 값에 따라 다른 제약을 적용할 때 사용합니다.
{
"type": "object",
"properties": {
"paymentType": { "enum": ["card", "bank"] }
},
"required": ["paymentType"],
"if": {
"properties": {
"paymentType": { "const": "card" }
},
"required": ["paymentType"]
},
"then": {
"required": ["cardToken"]
},
"else": {
"required": ["bankAccountId"]
}
}조건이 많아지면 schema가 읽기 어려워지므로, discriminated union처럼 명확한 type field를 두는 설계를 먼저 검토합니다.
required는 조건 field 존재 여부를 따로 잡아야 한다
properties 안의 조건은 해당 property가 없을 때도 통과할 수 있습니다. 그래서 조건 판단에 반드시 필요한 field는 root나 해당 subschema에서 required로 같이 묶어야 합니다.
{
"required": ["paymentType"],
"if": {
"properties": {
"paymentType": { "const": "card" }
},
"required": ["paymentType"]
},
"then": {
"required": ["cardToken"]
}
}조건 field가 없어도 then이나 else가 예상과 다르게 적용될 수 있으므로, 조건 field 존재 여부를 테스트 케이스에 넣어야 합니다.
dependentRequired는 field 동반 관계에 맞다
어떤 field가 있으면 다른 field도 반드시 있어야 하는 단순 동반 조건에는 dependentRequired가 더 읽기 쉽습니다. 예를 들어 creditCard가 있으면 billingAddress도 필요하다는 규칙입니다.
{
"type": "object",
"properties": {
"creditCard": { "type": "string" },
"billingAddress": { "type": "string" }
},
"dependentRequired": {
"creditCard": ["billingAddress"]
}
}값의 내용에 따라 다른 구조를 고르는 경우는 if/then/else, field 존재의 동반 관계는 dependentRequired로 나누면 schema가 단순해집니다.
dependentSchemas는 field 존재 시 추가 schema를 적용한다
dependentSchemas는 특정 property가 존재할 때 별도 schema를 전체 object에 적용합니다. 단순 required 목록보다 더 복잡한 조건이 필요할 때 사용합니다.
{
"dependentSchemas": {
"couponCode": {
"properties": {
"discountType": { "const": "coupon" }
},
"required": ["discountType"]
}
}
}조건이 여러 단계로 중첩되면 검증 오류 메시지가 복잡해질 수 있습니다. 사용자에게 보여 줄 오류 메시지는 validator 기본 출력에만 의존하지 말고 별도 매핑을 준비하는 편이 좋습니다.
선택 기준
| 조건 | 적합한 keyword |
|---|---|
| 값에 따라 다른 schema 적용 | if / then / else |
| field A가 있으면 field B 필요 | dependentRequired |
| field A가 있으면 복합 규칙 적용 | dependentSchemas |
| 여러 타입 payload 구분 | 명시적 type 또는 discriminator field |
| 조건 field가 필수 | required를 함께 명시 |
| 오류 메시지 중요 | 조건별 테스트와 오류 매핑 |
주의할 점
조건부 schema는 빠르게 복잡해집니다. API 설계에서 조건이 너무 많다면 schema keyword를 더 쌓기보다 payload 구조를 분리하거나 명시적인 type field를 추가하는 것이 더 읽기 쉽습니다.
조건 field가 없는 입력, 조건 field가 예상 밖 값인 입력, 조건에 맞지만 필수 field가 빠진 입력을 모두 테스트해야 합니다. 조건부 검증은 happy path만 확인하면 실제 운영에서 가장 먼저 깨집니다.
참고 링크
1 sources