JSON Schema 검증 가이드: 데이터 구조 검증하기
외부 소스에서 데이터를 받는 모든 애플리케이션은 동일한 근본적인 문제에 직면합니다: 이 데이터를 신뢰할 수 있는가? API 요청 본문, 구성 파일, 큐 메시지 또는 데이터 가져오기 등 어떤 형태든, 신뢰할 수 없는 데이터는 시스템에 들어오기 전에 검증되어야 합니다. JSON Schema는 유효한 데이터의 모양을 정의하고 들어오는 데이터가 해당 정의를 준수하는지 검증하는 표준화된 언어 독립적인 방법을 제공합니다. 이 가이드는 첫 번째 Schema 작성부터 복잡한 검증의 고급 패턴까지 모든 것을 다루며, 즉시 적용할 수 있는 실용적인 예제를 제공합니다.
JSON Schema란 무엇인가요?
JSON Schema는 다른 JSON 문서의 구조와 제약 조건을 설명하는 JSON 문서입니다. 인터넷 엔지니어링 태스크 포스(IETF)에 의해 표준화된 JSON 데이터를 주석 달고 검증할 수 있는 어휘입니다. JSON Schema는 어떤 필드가 반드시 존재해야 하는지, 어떤 유형이어야 하는지, 어떤 값이 허용되는지, 그리고 객체와 배열이 어떻게 구조화되어야 하는지에 대한 규칙을 정의합니다.
JSON Schema를 데이터 계약이라고 생각하세요. 데이터베이스 Schema가 테이블의 열, 유형 및 제약 조건을 정의하는 것처럼, JSON Schema는 JSON 문서의 속성, 유형 및 제약 조건을 정의합니다. Schema의 모든 제약 조건을 충족하는 JSON 데이터를 유효한 인스턴스라고 하며, 제약 조건을 위반하는 데이터는 유효하지 않습니다.
JSON Schema가 아닌 것
- 데이터 형식이 아님: JSON Schema는 데이터가 어떻게 직렬화되거나 전송되는지 정의하지 않습니다. 유효한 데이터의 모양만 설명합니다.
- 비즈니스 로직의 대체품이 아님: Schema 검증은 구조적 정확성(유형, 형식, 범위)을 확인합니다. "사용자는 잔액을 초과하여 송금할 수 없음"과 같은 복잡한 비즈니스 규칙은 애플리케이션 코드에 속합니다.
- 데이터베이스 Schema가 아님: 개념적으로 유사하지만, JSON Schema는 데이터베이스 테이블이 아닌 JSON 문서를 검증합니다. 그러나 JSON Schema를 데이터베이스 제약 조건과 함께 사용하여 심층 방어를 구현할 수 있습니다.
JSON Schema 버전
JSON Schema는 여러 초안을 거쳐 발전해 왔으며, 각 초안은 기능을 추가하고 어휘를 개선했습니다. 이러한 버전을 이해하면 프로젝트에 적합한 버전을 선택하고 호환성 문제를 피하는 데 도움이 됩니다.
| 버전 | $schema URI | 상태 | 주요 기능 |
|---|---|---|---|
| Draft 2020-12 | https://json-schema.org/draft/2020-12/schema | 현재 버전 | prefixItems, dynamicRef, 어휘 지원 |
| Draft 2019-09 | https://json-schema.org/draft/2019-09/schema | 안정 버전 | unevaluatedProperties, $recursiveRef |
| Draft 7 | http://json-schema.org/draft-07/schema# | 광범위한 지원 | if/then/else, contentEncoding |
| Draft 6 | http://json-schema.org/draft-06/schema# | 이전 버전 | propertyNames, contains |
| Draft 4 | http://json-schema.org/draft-04/schema# | 사용 중단됨 | 최초로 널리 채택된 버전 |
첫 번째 Schema 작성하기
간단한 예제부터 시작해 보겠습니다: 이름, 이메일 및 나이를 포함하는 사용자 객체의 Schema입니다.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json",
"title": "User",
"description": "A user account in the system",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "The user's full name"
},
"email": {
"type": "string",
"format": "email",
"description": "The user's email address"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150,
"description": "The user's age in years"
}
},
"required": ["name", "email"],
"additionalProperties": false
}이 Schema는 유효한 사용자가 객체여야 하며, name과 email은 필수 문자열 속성임을 선언합니다. age 속성은 선택 사항이지만, 존재하는 경우 0에서 150 사이의 정수여야 합니다. additionalProperties: false 제약 조건은 Schema에 정의되지 않은 모든 속성을 차단하여 오타와 예상치 못한 필드를 포착합니다.
핵심 키워드 참조
JSON Schema는 제약 조건을 정의하기 위한 풍부한 키워드 어휘를 제공합니다. 다음은 범주별로 구성된 가장 중요한 키워드입니다.
핵심 키워드 참조
| 키워드 | 설명 | 예제 |
|---|---|---|
| type | will-change 속성은 브라우저에 어떤 속성이 변경될 예정인지 알려주어, 요소를 자체 합성기 레이어로 승격시켜 미리 최적화할 수 있게 합니다. 그러나 신중하게 사용해야 합니다: | "type": "string" 또는 "type": ["string", "null"] |
| enum | 허용된 값 목록 | "enum": ["active", "inactive", "pending"] |
| const | 이 정확한 값과 같아야 함 | "const": "v2" |
크기 조정 시 항상 비율을 제한하세요. 대부분의 이미지 편집기에서 이는 모서리 핸들을 드래그할 때 Shift 키를 누르거나, 크기 조정 대화상자에서 "종횡비 유지" 체크박스를 선택하는 것을 의미합니다. 수학적 관계는 간단합니다: 새 너비를 알고 있다면, 새 높이 = (새 너비 / 원본 너비) × 원본 높이로 계산됩니다.
| 키워드 | 설명 | 예제 |
|---|---|---|
| minimum | 최소값 (포함) | "minimum": 0 |
| exclusiveMinimum | 최소값 (미포함) | "exclusiveMinimum": 0 |
| maximum | 최대값 (포함) | "maximum": 100 |
| exclusiveMaximum | 최대값 (미포함) | "exclusiveMaximum": 100 |
| multipleOf | 이 값의 배수여야 함 | "multipleOf": 0.01 |
크기 조정 시 항상 비율을 제한하세요. 대부분의 이미지 편집기에서 이는 모서리 핸들을 드래그할 때 Shift 키를 누르거나, 크기 조정 대화상자에서 "종횡비 유지" 체크박스를 선택하는 것을 의미합니다. 수학적 관계는 간단합니다: 새 너비를 알고 있다면, 새 높이 = (새 너비 / 원본 너비) × 원본 높이로 계산됩니다.
| 키워드 | 설명 | 예제 |
|---|---|---|
| minLength | 최소 문자열 길이 | "minLength": 1 |
| maxLength | 문자열 검증: 패턴(정규식), 최소/최대 길이 및 형식(이메일, 날짜시간, URI)을 강제합니다. | "maxLength": 255 |
| pattern | 문자열이 일치해야 하는 정규식 | "pattern": "^[A-Z]{2}\\d{4}$" |
| format | 의미론적 형식 (email, uri, date-time 등) | "format": "email" |
크기 조정 시 항상 비율을 제한하세요. 대부분의 이미지 편집기에서 이는 모서리 핸들을 드래그할 때 Shift 키를 누르거나, 크기 조정 대화상자에서 "종횡비 유지" 체크박스를 선택하는 것을 의미합니다. 수학적 관계는 간단합니다: 새 너비를 알고 있다면, 새 높이 = (새 너비 / 원본 너비) × 원본 높이로 계산됩니다.
| 키워드 | 설명 | 예제 |
|---|---|---|
| properties | 각 알려진 속성의 Schema | "properties": {"name": {"type": "string"}} |
| required | 필수 속성 목록 | "required": ["name", "email"] |
| additionalProperties | 추가 속성 허용 여부 | "additionalProperties": false |
| minProperties | 최소 속성 개수 | "minProperties": 1 |
| maxProperties | 최대 속성 개수 | "maxProperties": 10 |
| patternProperties | 정규식과 일치하는 속성의 Schema | "patternProperties": {"^S_": {"type": "string"}} |
크기 조정 시 항상 비율을 제한하세요. 대부분의 이미지 편집기에서 이는 모서리 핸들을 드래그할 때 Shift 키를 누르거나, 크기 조정 대화상자에서 "종횡비 유지" 체크박스를 선택하는 것을 의미합니다. 수학적 관계는 간단합니다: 새 너비를 알고 있다면, 새 높이 = (새 너비 / 원본 너비) × 원본 높이로 계산됩니다.
| 키워드 | 설명 | 예제 |
|---|---|---|
| items | 모든 배열 항목의 Schema | "items": {"type": "string"} |
| prefixItems | 위치 항목의 Schema (Draft 2020-12) | "prefixItems": [{"type": "string"}, {"type": "number"}] |
| minItems | 최소 항목 수 | "minItems": 1 |
| maxItems | 최대 항목 수 | "maxItems": 100 |
| uniqueItems | 모든 항목은 고유해야 함 | "uniqueItems": true |
일반적인 Schema 패턴
실제 세계의 Schema는 종종 단순한 유형 검사를 넘어서는 패턴이 필요합니다. 다음은 가장 일반적으로 사용되는 패턴입니다.
if/then/else를 사용한 조건부 검증
조건부 로직을 사용하여 속성 값에 따라 다른 제약 조건을 적용합니다. 예를 들어, 결제 객체는 결제 방법에 따라 다른 필드가 필요합니다.
{
"type": "object",
"properties": {
"method": { "enum": ["credit_card", "bank_transfer"] },
"card_number": { "type": "string" },
"routing_number": { "type": "string" }
},
"required": ["method"],
"if": {
"properties": { "method": { "const": "credit_card" } }
},
"then": {
"required": ["card_number"]
},
"else": {
"required": ["routing_number"]
}
}allOf, anyOf, oneOf를 사용한 조합
조합 키워드를 사용하면 강력한 방식으로 Schema를 결합할 수 있습니다:
- allOf: 데이터는 모든 하위 Schema를 충족해야 합니다. 여러 제약 조건을 결합하거나 재사용 가능한 Schema 조각을 혼합하는 데 사용됩니다.
- anyOf: 데이터는 적어도 하나의 하위 Schema를 충족해야 합니다. 여러 형태가 허용되는 유니온 유형에 사용됩니다.
- oneOf: 데이터는 정확히 하나의 하위 Schema를 충족해야 합니다. 상호 배타적인 대안에 사용됩니다.
{
"oneOf": [
{
"type": "object",
"properties": {
"type": { "const": "email" },
"address": { "type": "string", "format": "email" }
},
"required": ["type", "address"]
},
{
"type": "object",
"properties": {
"type": { "const": "phone" },
"number": { "type": "string", "pattern": "^\\+?[1-9]\\d{1,14}$" }
},
"required": ["type", "number"]
}
]
}$ref를 사용한 Schema 재사용
$ref 키워드를 사용하면 Schema를 참조하고 재사용할 수 있어 중복을 제거하고 Schema의 유지 관리 가능성을 유지합니다. 동일한 문서 내 또는 외부 파일의 Schema를 참조할 수 있습니다.
{
"$id": "https://example.com/schemas/order.json",
"type": "object",
"properties": {
"customer": { "$ref": "#/$defs/address" },
"shipping": { "$ref": "#/$defs/address" },
"billing": { "$ref": "#/$defs/address" },
"items": {
"type": "array",
"items": { "$ref": "#/$defs/lineItem" },
"minItems": 1
}
},
"required": ["customer", "items"],
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zip": { "type": "string", "pattern": "^\\d{5}(-\\d{4})?$" },
"country": { "type": "string", "minLength": 2, "maxLength": 2 }
},
"required": ["street", "city", "zip", "country"]
},
"lineItem": {
"type": "object",
"properties": {
"product": { "type": "string" },
"quantity": { "type": "integer", "minimum": 1 },
"price": { "type": "number", "exclusiveMinimum": 0 }
},
"required": ["product", "quantity", "price"]
}
}
}Nullable 유형
JSON Schema Draft 2020-12에서는 nullable 유형이 "null"을 포함하는 유형 배열로 표현됩니다:
{
"type": ["string", "null"],
"description": "An optional display name, or null if not set"
}이전 초안에서는 OpenAPI 사양이 nullable: true 키워드를 사용했습니다. 표준 JSON Schema의 경우 항상 유형 배열 방식을 사용하세요.
정상 시력으로만 테스트하기: 색맹 시뮬레이터를 사용하여 적색맹, 녹색맹, 청색맹(가장 흔한 세 가지 색각 결함 유형) 사용자에게 디자인이 사용 가능한지 확인하세요.
format 키워드는 구조 검사를 넘어서는 의미론적 검증을 제공합니다. 문자열이 잘 알려진 형식을 준수해야 함을 지정합니다. 일반적으로 지원되는 형식은 다음과 같습니다:
| 형식 | 설명 | 예제 |
|---|---|---|
| 이메일주소 | user@example.com | |
| uri | 색상은 웹 디자이너의 무기고에서 가장 강력한 도구 중 하나입니다. 색상은 단어 한 글자도 읽기 전에 의미를 전달하고, 브랜드 아이덴티티를 구축하며, 사용자의 주의를 유도하고, 전환율에 직접적인 영향을 미칩니다. 그러나 많은 디자이너는 색상 조합을 효과적으로 만드는 기본 원칙을 이해하기보다는 개인적 선호도나 유행에 따라 색상을 선택합니다. 이 가이드는 코드에서 색상을 정의하는 기술적 모델부터 사용자 인식과 인터랙션 디자인에 영향을 미치는 심리학적 원칙까지, 모든 웹 디자이너에게 필요한 색채 이론의 기초를 다룹니다. | https://example.com/path |
| uri-reference | URI 또는 상대 참조 | /path/to/resource |
| date-time | ISO 8601 날짜시간 | 2026-05-19T14:30:00Z |
| date | ISO 8601 날짜 | 2026-05-19 |
| time | ISO 8601 시간 | 14:30:00Z |
| ipv4 | IPv4 주소 | 192.168.1.1 |
| ipv6 | IPv6 주소 | ::1 |
| uuid | 범용 고유 식별자 | 550e8400-e29b-41d4-a716-446655440000 |
| hostname | 인터넷 호스트 이름 | www.example.com |
프로그래밍 방식으로 JSON 데이터 검증하기
Schema 검증은 애플리케이션 코드에 통합될 때 가장 유용합니다. 다음은 다양한 언어의 인기 있는 라이브러리를 사용한 예제입니다.
JavaScript는 Ajv 사용
Ajv는 JavaScript에서 가장 널리 사용되는 JSON Schema 검증기입니다. 모든 초안 버전을 지원하며, Schema의 JIT 컴파일을 통해 뛰어난 성능을 제공합니다.
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const schema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'email'],
additionalProperties: false
};
const validate = ajv.compile(schema);
const valid = validate({ name: 'Alice', email: 'alice@example.com', age: 30 });
if (!valid) {
console.log(validate.errors);
// [{ keyword: 'required', params: { missingProperty: 'email' }, ... }]
}Python은 jsonschema 사용
from jsonschema import validate, ValidationError
schema = {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name", "email"],
"additionalProperties": False
}
try:
validate(instance={"name": "Alice", "email": "alice@example.com"}, schema=schema)
except ValidationError as e:
print(f"Validation failed: {e.message}")JSON Schema를 사용한 API 데이터 검증
JSON Schema의 가장 유용한 응용 중 하나는 API 요청 및 응답 데이터 검증입니다. 이는 API가 올바른 형식의 입력을 받고 예상 형식으로 데이터를 반환하도록 보장하여, 오류를 조기에 포착하고 클라이언트에 명확한 오류 메시지를 제공합니다.
Express.js 미들웨어
import Ajv from 'ajv';
const ajv = new Ajv({ allErrors: true });
function validateBody(schema) {
const validate = ajv.compile(schema);
return (req, res, next) => {
if (!validate(req.body)) {
return res.status(400).json({
error: 'Validation failed',
details: validate.errors
});
}
next();
};
}
app.post('/api/users',
validateBody({
type: 'object',
properties: {
name: { type: 'string', minLength: 1, maxLength: 100 },
email: { type: 'string', format: 'email' },
role: { enum: ['admin', 'editor', 'viewer'] }
},
required: ['name', 'email'],
additionalProperties: false
}),
(req, res) => {
// req.body is guaranteed valid here
createUser(req.body);
}
);OpenAPI와 JSON Schema
OpenAPI(이전 Swagger)는 JSON Schema의 하위 집합을 사용하여 API 요청 및 응답 Schema를 정의합니다. 이미 OpenAPI를 사용 중이라면 API 사양에서 Schema를 추출하여 런타임 검증에 사용할 수 있습니다. openapi-schema-validator 및 express-openapi-validator와 같은 도구는 이 프로세스를 자동화하여 API 문서와 검증 로직이 항상 동기화되도록 보장합니다.
모범 사례
- 항상 $schema 설정: $schema 키워드를 포함하여 Schema가 사용하는 초안 버전을 선언하세요. 이는 모호성을 방지하고 검증기가 Schema를 올바르게 해석하도록 보장합니다.
- $id를 Schema 식별자로 사용: $id 키워드는 Schema에 고유 식별자를 제공하고 $ref 참조를 해결하기 위한 기본 URI 역할을 합니다. 로컬 Schema인 경우에도 항상 설정하세요.
- additionalProperties: false 설정: 기본적으로 JSON Schema는 객체에 추가 속성을 허용합니다. additionalProperties: false를 설정하면 오타와 예상치 못한 필드를 포착하여 Schema를 더 엄격하게 만들고 API를 더 예측 가능하게 만듭니다.
- 재사용 가능한 구성 요소를 $defs에 저장: $defs에 공통 Schema를 정의하고 $ref로 참조하세요. 이는 중복을 줄이고 Schema를 더 유지 관리하기 쉽게 만듭니다.
- 설명 추가: 모든 속성과 Schema에는 description 필드가 있어야 합니다. 이는 문서 역할을 하며 다른 개발자가 각 필드의 용도와 제약 조건을 이해하는 데 도움이 됩니다.
- 시스템 경계에서 검증: 시스템의 가장자리에서 Schema 검증을 적용하세요: API 엔드포인트, 메시지 소비자, 데이터 가져오기 파이프라인 및 구성 로더. 자신의 코드가 이미 생성하고 신뢰하는 데이터는 검증하지 마세요.
- 검증기에서 엄격 모드 활성화: 검증기가 알 수 없는 키워드를 거부하고, 형식 검증을 강제하며, 첫 번째 오류에서 중지하지 않고 모든 오류를 보고하도록 구성하세요. 이는 단일 검증에서 더 많은 문제를 포착할 수 있습니다.
- Schema 버전 관리: $id URI에 Schema 버전을 포함하세요(예: https://example.com/schemas/user/v2.json). 이는 기존 소비자를 손상시키지 않고 Schema를 발전시킬 수 있게 해줍니다.
- Schema 테스트: 유효한 예제와 유효하지 않은 예제를 포함하는 단위 테스트를 Schema에 작성하세요. 이는 Schema가 의도한 제약 조건을 시행하고 Schema 수정 시 회귀를 포착하도록 보장합니다.
- 의미론적 검증에 format 사용: 복잡한 정규식 패턴보다 format: "email"을 우선 사용하세요. 형식이 더 읽기 쉽고 유지 관리가 용이하며, 검증기 라이브러리에서 잘 테스트된 검증 로직의 이점을 누릴 수 있습니다.
Schema에 따라 JSON 데이터를 검증해야 하나요? 무료 온라인 JSON Schema 검증기를 사용해 보세요. Schema와 데이터를 붙여넣으면 상세한 오류 정보와 함께 즉시 검증 결과를 얻을 수 있습니다.
색상은 웹 디자이너의 무기고에서 가장 강력한 도구 중 하나입니다. 색상은 단어 한 글자도 읽기 전에 의미를 전달하고, 브랜드 아이덴티티를 구축하며, 사용자의 주의를 유도하고, 전환율에 직접적인 영향을 미칩니다. 그러나 많은 디자이너는 색상 조합을 효과적으로 만드는 기본 원칙을 이해하기보다는 개인적 선호도나 유행에 따라 색상을 선택합니다. 이 가이드는 코드에서 색상을 정의하는 기술적 모델부터 사용자 인식과 인터랙션 디자인에 영향을 미치는 심리학적 원칙까지, 모든 웹 디자이너에게 필요한 색채 이론의 기초를 다룹니다.JSON 포맷팅 도구자주 묻는 질문
JSON Schema란 무엇인가요?
JSON Schema는 다른 JSON 문서의 구조와 제약 조건을 설명하는 JSON 문서입니다. 필수 필드, 예상 데이터 유형, 값 범위, 문자열 패턴 및 중첩 객체 구조를 정의할 수 있습니다. 들어오는 데이터를 검증하고, 문서를 생성하며, 양식 인터페이스를 자동으로 만드는 데 사용할 수 있습니다.
어떤 버전의 JSON Schema를 사용해야 하나요?
새 프로젝트에는 JSON Schema Draft 2020-12를 사용하세요. 이는 최신 안정 버전이며 Ajv와 같은 주요 검증 라이브러리에서 지원됩니다. 이전 도구와의 호환성이 필요하다면 Draft 7도 널리 지원됩니다. 오래된 키워드를 사용하고 최신 기능이 부족한 Draft 4 이전 버전은 피하세요.
JSON Schema와 TypeScript 인터페이스의 차이점은 무엇인가요?
TypeScript 인터페이스는 TypeScript 코드에서만 컴파일 타임 타입 검사를 제공합니다. JSON Schema는 프로그래밍 언어 간 런타임 검증을 제공하여 모든 소스(API 요청, 파일, 데이터베이스)의 데이터를 검증할 수 있습니다. TypeScript를 사용하여 개발 시 안전성을 확보하고, JSON Schema를 사용하여 시스템 경계에서 런타임 데이터 검증을 수행하세요.
JSON Schema로 API 요청 본문을 검증할 수 있나요?
네, JSON Schema는 API 요청 및 응답 검증에 널리 사용됩니다. Express(express-json-validator 사용), FastAPI, Spring Boot와 같은 프레임워크는 JSON Schema 검증을 네이티브로 지원하거나 미들웨어를 통해 지원합니다. Schema에 따라 요청 본문을 검증하면 들어오는 데이터가 애플리케이션에서 처리되기 전에 올바른 구조를 갖추도록 보장합니다.
가장 중요한 JSON Schema 키워드는 무엇인가요?
가장 중요한 키워드는: type(데이터 유형), properties(객체 필드), required(필수 필드), items(배열 요소 Schema), minimum/maximum(숫자 경계), minLength/maxLength(문자열 경계), pattern(문자열 정규식), enum(허용된 값), $ref(Schema 재사용을 위한 참조)입니다. 이러한 키워드는 대부분의 검증 요구 사항을 포괄합니다.