JSON Schema는 JSON 데이터 구조를 설명하고 검증하는 업계 표준입니다. API 요청 페이로드 강제·설정 파일 검증·폼 유효성 검사 로직 구축 등 어떤 경우에도 온라인 JSON Schema 검증기를 사용하면 라이브러리 설치나 테스트 하네스 없이 스키마와 샘플 데이터를 즉시 테스트할 수 있습니다.

지금 JSON을 스키마로 검증하기 →

JSON Schema란

JSON Schema는 JSON 문서에 주석을 달고 검증하기 위한 선언적 어휘입니다. 스키마 자체도 JSON(또는 YAML) 문서로, 데이터의 예상되는 형태·타입·제약 조건을 설명합니다.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["id", "email", "role"],
  "properties": {
    "id": { "type": "integer", "minimum": 1 },
    "email": { "type": "string", "format": "email" },
    "role": { "type": "string", "enum": ["admin", "editor", "viewer"] },
    "createdAt": { "type": "string", "format": "date-time" }
  },
  "additionalProperties": false
}

이 스키마는 검증할 JSON 객체에 세 개의 필수 필드가 있고, id가 양의 정수, email이 유효한 이메일 주소, role이 세 가지 허용된 값 중 하나임을 보장합니다.

JSON Schema 드래프트 버전

명세는 크게 발전해 왔습니다. 버전 전체 그림을 이해하면 스키마가 예상치 못하게 동작할 때의 혼란을 방지할 수 있습니다:

드래프트출시주요 추가 기능
Draft-042013코어 어휘, $ref, allOf/anyOf/oneOf
Draft-062017const, contains, propertyNames, readOnly
Draft-072019if/then/else, writeOnly, $comment
2019-092019$defs, unevaluatedProperties, $anchor
2020-122021Prefix items, $dynamicRef, 개선된 $ref

항상 $schema로 드래프트를 선언하세요. 선언이 없으면 검증기가 다른 기본값을 적용할 수 있습니다. 현재 프로덕션 사용의 대부분은 draft-07 또는 2020-12입니다.

핵심 스키마 키워드

타입 제약

{ "type": "string" }
{ "type": "integer" }
{ "type": "number" }
{ "type": "boolean" }
{ "type": "null" }
{ "type": "array" }
{ "type": "object" }

// 여러 타입 허용:
{ "type": ["string", "null"] }

객체 제약

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer", "minimum": 0 }
  },
  "required": ["name"],
  "additionalProperties": false,
  "minProperties": 1,
  "maxProperties": 10
}

additionalProperties: false는 가장 효과적인 안전 제약입니다. properties에 나열되지 않은 모든 키를 거부하여 오타와 예상치 못한 필드를 감지합니다.

문자열 제약

{
  "type": "string",
  "minLength": 3,
  "maxLength": 100,
  "pattern": "^[a-z][a-z0-9_]*$",
  "format": "email"
}

일반적인 format 값: email·uri·date·date-time·time·ipv4·ipv6·uuid. 참고: 형식 검증은 기본적으로 선택적입니다. 검증기에서 명시적으로 활성화해야 합니다.

배열 제약

{
  "type": "array",
  "items": { "type": "string" },
  "minItems": 1,
  "maxItems": 50,
  "uniqueItems": true
}

draft 2020-12에서는 튜플 검증을 위해 itemsprefixItems로 이름이 변경되었습니다. 동질적인 배열에는 items, 위치 지정 튜플에는 prefixItems를 사용합니다.

숫자 제약

{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "exclusiveMinimum": 0,
  "multipleOf": 0.5
}

열거형과 const

// 허용된 값 중 하나:
{ "enum": ["draft", "published", "archived"] }

// 정확히 하나의 값(판별 유니온에 유용):
{ "const": "v2" }

조합 키워드

// 모든 서브스키마에 매칭되어야 함:
{ "allOf": [{ "type": "string" }, { "minLength": 1 }] }

// 최소 하나의 서브스키마에 매칭되어야 함:
{ "anyOf": [{ "type": "string" }, { "type": "number" }] }

// 정확히 하나의 서브스키마에 매칭되어야 함:
{ "oneOf": [
  { "type": "string", "format": "email" },
  { "type": "string", "format": "uri" }
] }

// 서브스키마에 매칭되지 않아야 함:
{ "not": { "type": "null" } }

조건부 검증(Draft-07 이상)

{
  "if": { "properties": { "type": { "const": "company" } } },
  "then": { "required": ["companyName", "taxId"] },
  "else": { "required": ["firstName", "lastName"] }
}

이것은 JSON Schema에서 가장 강력한 기능 중 하나입니다. 다른 필드의 값에 따라 다른 필수 필드를 강제할 수 있습니다.

스키마 참조와 재사용

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "address": {
      "type": "object",
      "required": ["street", "city", "country"],
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "country": { "type": "string", "minLength": 2, "maxLength": 2 }
      }
    }
  },
  "type": "object",
  "properties": {
    "billingAddress": { "$ref": "#/$defs/address" },
    "shippingAddress": { "$ref": "#/$defs/address" }
  }
}

$defs(이전 드래프트에서는 definitions)는 스키마를 DRY하게 유지합니다. $ref는 로컬(#/...)과 원격(https://...) 참조를 모두 지원합니다.

코드로 JSON Schema 검증하기

Node.js(AJV)

AJV는 가장 빠르고 널리 사용되는 JavaScript JSON Schema 검증기입니다:

npm install ajv ajv-formats
import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv({ allErrors: true });
addFormats(ajv);

const schema = {
  type: 'object',
  required: ['email', 'age'],
  properties: {
    email: { type: 'string', format: 'email' },
    age: { type: 'integer', minimum: 18 },
  },
  additionalProperties: false,
};

const validate = ajv.compile(schema);
const data = { email: 'user@example.com', age: 25 };

if (validate(data)) {
  console.log('Valid');
} else {
  console.log('Errors:', validate.errors);
}

AJV는 스키마를 최적화된 JavaScript 함수로 컴파일하므로 매우 빠르고 핫 요청 경로에도 적합합니다.

Python(jsonschema)

pip install jsonschema
import jsonschema
from jsonschema import validate, ValidationError

schema = {
    "type": "object",
    "required": ["email", "age"],
    "properties": {
        "email": {"type": "string", "format": "email"},
        "age": {"type": "integer", "minimum": 18},
    },
    "additionalProperties": False,
}

data = {"email": "user@example.com", "age": 25}

try:
    validate(instance=data, schema=schema)
    print("Valid")
except ValidationError as e:
    print(f"Invalid: {e.message}")
    print(f"Path: {list(e.absolute_path)}")

모든 오류(첫 번째만이 아닌)를 얻으려면 jsonschema.Draft202012Validator를 사용합니다:

from jsonschema import Draft202012Validator

validator = Draft202012Validator(schema)
errors = list(validator.iter_errors(data))
for error in errors:
    print(f"{'.'.join(str(p) for p in error.path)}: {error.message}")

Go(santhosh-tekuri)

go get github.com/santhosh-tekuri/jsonschema/v6
package main

import (
    "fmt"
    "strings"

    "github.com/santhosh-tekuri/jsonschema/v6"
)

func main() {
    schemaJSON := `{
        "type": "object",
        "required": ["email", "age"],
        "properties": {
            "email": {"type": "string", "format": "email"},
            "age": {"type": "integer", "minimum": 18}
        }
    }`

    compiler := jsonschema.NewCompiler()
    compiler.AddResource("schema.json", strings.NewReader(schemaJSON))
    schema, err := compiler.Compile("schema.json")
    if err != nil {
        panic(err)
    }

    data := map[string]any{"email": "user@example.com", "age": 25}
    if err := schema.Validate(data); err != nil {
        fmt.Println("Invalid:", err)
    } else {
        fmt.Println("Valid")
    }
}

실용적인 사용 사례

API 요청 검증

비즈니스 로직에 도달하기 전에 게이트웨이나 미들웨어 레이어에서 API 페이로드를 검증합니다.

설정 파일 검증

시작 시 애플리케이션 설정을 검증하고, 알 수 없는 런타임 오류 대신 명확한 오류 메시지로 빠르게 실패하도록 합니다.

JSON Schema vs 런타임 검증 라이브러리

접근 방식이식성언어 지원학습 곡선도구
JSON Schema높음(언어 중립)주요 언어 전부중간우수
TypeScript(Zod/Yup)TypeScript만TypeScript/JS낮음양호
Pydantic(Python)Python만Python낮음양호
Protobuf/gRPC높음(바이너리)전부높음우수
OpenAPI spec높음전부중간우수

JSON Schema는 폴리글랏 스택 전체에서 공유되는 단일 정규 스키마가 필요할 때 가장 유리합니다. 한 번 정의하면 어떤 언어에서도 검증할 수 있습니다.

흔한 실수

additionalProperties: false를 설정하지 않음 — 스키마가 여분의 필드를 받아들이게 되어 클라이언트가 예상치 못한 데이터를 쉽게 전달할 수 있습니다.

검증기 설정 없이 format 사용format: "email"은 어노테이션이지 제약이 아닙니다. 검증기에서 형식 검증을 명시적으로 활성화하지 않는 한 강제되지 않습니다.

드래프트 버전 혼용$schema에서 draft-07을 선언하면서 $defs(2019-09 이상)를 사용하면 정의되지 않은 동작이 발생합니다.

required 누락required가 없으면 모든 properties가 기본적으로 선택적입니다. properties는 있지만 required 배열이 없는 스키마는 {}에 대해 검증이 통과됩니다.

DB의 ID에 type: "integer" 사용 — 큰 정수 ID(64비트)는 JavaScript의 안전한 정수 범위를 초과할 수 있습니다. "type": "string" 또는 "maximum": 9007199254740991을 추가하는 것을 고려하세요.

온라인 JSON Schema 검증기

스키마를 샘플 데이터에 대해 로컬로 테스트하려면 검증기 설정·파일 로드·코드 실행이 필요합니다. ZeroTool JSON Schema 검증기는 그 모든 번거로움을 없애줍니다:

  • JSON Schema와 샘플 JSON을 나란히 붙여 넣기
  • 오류 경로 하이라이트와 즉각적인 검증
  • draft-04·draft-06·draft-07·2019-09·2020-12 지원
  • 100% 로컬 처리 — 데이터가 브라우저 밖으로 나가지 않음

JSON Schema 검증기 사용해보기 →