[EXT-011][실무] JSON 구조와 값의 범위를 자동 검사하기
페이지 정보

본문
[이번 수업]
JSON에 이름이 없거나 수량이 음수라면 업무 처리 전에 막아야 합니다. JSON Schema(JSON 구조와 제약을 기계가 읽게 적는 표준)로 필수 속성, 자료형과 값의 범위를 검사합니다.
[선수지식]
JSON 객체·배열과 Python 가상환경을 알고, 패키지 설치 명령을 실행할 수 있으면 됩니다. EXT-010의 JSON 표현과 검증의 차이를 알면 좋습니다.
[학습목표]
1. JSON Schema의 방언과 주요 검증 키워드를 설명한다.
2. 스키마 자체와 입력 데이터를 각각 검사한다.
3. 검증 오류를 안전하고 이해하기 쉽게 처리한다.
[핵심개념]
현재 공개 규격은 Draft 2020-12입니다. `$schema`는 도구에 방언(dialect, 키워드 묶음과 의미)을 알립니다. `type`은 자료형, `properties`는 속성 규칙, `required`는 필수 속성, `minimum`과 `minLength`는 값의 하한입니다.
`properties`만으로 필수가 되지 않아 `required`가 따로 필요합니다. 검증은 문자열을 숫자로 자동 변환하지 않습니다. `additionalProperties: false`는 그 객체의 미선언 속성을 거부하므로 중첩 객체마다 정책을 정합니다.
스키마도 배포 전에 메타스키마로 검사합니다. `format`은 설정에 따라 주석일 수 있으므로 구현 동작을 확인하고 테스트합니다. 통과 뒤에도 재고와 사용자 권한 같은 업무 규칙은 따로 확인합니다.
[따라하기]
macOS/Linux는 `python3 -m venv .venv` 뒤 `. .venv/bin/activate`, Windows PowerShell은 `py -m venv .venv` 뒤 `.\.venv\Scripts\Activate.ps1`을 실행합니다. 이어 `python -m pip install jsonschema`를 실행하고 아래를 schema_check.py로 저장합니다.
```python
from jsonschema import Draft202012Validator
schema = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"count": {"type": "integer", "minimum": 1},
},
"required": ["name", "count"],
"additionalProperties": False,
}
samples = [
{"name": "연필", "count": 2},
{"name": "", "count": 0, "admin": True},
]
Draft202012Validator.check_schema(schema)
validator = Draft202012Validator(schema)
for number, sample in enumerate(samples, start=1):
errors = list(validator.iter_errors(sample))
result = "통과" if not errors else f"실패 {len(errors)}개"
print(f"{number}번: {result}")
```
`python schema_check.py`를 실행합니다. 예상 결과입니다.
```text
1번: 통과
2번: 실패 3개
```
오류의 `path`로 입력 위치를 알려 주되 내부 경로나 서버 정보는 노출하지 않습니다.
[흔한 실수]
서버 검증을 생략하면 직접 보낸 요청을 막지 못합니다. `required` 없이 `properties`만 쓰거나, 숫자와 숫자 모양 문자열을 섞는 것도 흔합니다. 기존 API에 `additionalProperties: false`를 갑자기 적용하면 호환성이 깨질 수 있으므로 계약 버전과 테스트를 함께 관리하세요.
[보안 주의]
본인 소유의 로컬·격리 환경에서만 실습하세요. 요청 계층에서도 전체 크기와 중첩 깊이를 제한합니다. 신뢰하지 않는 원격 `$ref`를 자동으로 가져오지 말고 승인한 로컬 스키마나 허용 목록만 사용하세요. 정규식은 단순하게 유지하고 검증 뒤에도 인증·인가를 수행합니다.
[직접 해볼 과제]
`price`를 0 이상의 number로 추가하고 필수 속성으로 만드세요. 정상 표본에는 1200, 오류 표본에는 -1을 넣어 실패 개수가 늘어나는지 확인한 뒤 오류의 `path`와 메시지를 한 줄씩 출력해 보세요.
[확인문제]
1. `properties`와 `required`의 역할은 어떻게 다릅니까?
2. 스키마에 `$schema`를 명시하는 이유는 무엇입니까?
3. 구조 검증이 통과해도 인증·인가가 필요한 이유는 무엇입니까?
[다음 학습]
다음에는 스키마 변경이 기존 사용자를 깨뜨리는지 예제 모음으로 검사하는 계약 테스트를 배웁니다.
[공식 참고 자료]
- JSON Schema 현재 규격 안내: https://json-schema.org/specification
- JSON Schema Draft 2020-12 Core: https://json-schema.org/draft/2020-12/json-schema-core
- JSON Schema Draft 2020-12 Validation: https://json-schema.org/draft/2020-12/json-schema-validation
- Python jsonschema 검증 문서: https://python-jsonschema.readthedocs.io/en/stable/validate/
- OWASP 입력 검증 지침: https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html
JSON에 이름이 없거나 수량이 음수라면 업무 처리 전에 막아야 합니다. JSON Schema(JSON 구조와 제약을 기계가 읽게 적는 표준)로 필수 속성, 자료형과 값의 범위를 검사합니다.
[선수지식]
JSON 객체·배열과 Python 가상환경을 알고, 패키지 설치 명령을 실행할 수 있으면 됩니다. EXT-010의 JSON 표현과 검증의 차이를 알면 좋습니다.
[학습목표]
1. JSON Schema의 방언과 주요 검증 키워드를 설명한다.
2. 스키마 자체와 입력 데이터를 각각 검사한다.
3. 검증 오류를 안전하고 이해하기 쉽게 처리한다.
[핵심개념]
현재 공개 규격은 Draft 2020-12입니다. `$schema`는 도구에 방언(dialect, 키워드 묶음과 의미)을 알립니다. `type`은 자료형, `properties`는 속성 규칙, `required`는 필수 속성, `minimum`과 `minLength`는 값의 하한입니다.
`properties`만으로 필수가 되지 않아 `required`가 따로 필요합니다. 검증은 문자열을 숫자로 자동 변환하지 않습니다. `additionalProperties: false`는 그 객체의 미선언 속성을 거부하므로 중첩 객체마다 정책을 정합니다.
스키마도 배포 전에 메타스키마로 검사합니다. `format`은 설정에 따라 주석일 수 있으므로 구현 동작을 확인하고 테스트합니다. 통과 뒤에도 재고와 사용자 권한 같은 업무 규칙은 따로 확인합니다.
[따라하기]
macOS/Linux는 `python3 -m venv .venv` 뒤 `. .venv/bin/activate`, Windows PowerShell은 `py -m venv .venv` 뒤 `.\.venv\Scripts\Activate.ps1`을 실행합니다. 이어 `python -m pip install jsonschema`를 실행하고 아래를 schema_check.py로 저장합니다.
```python
from jsonschema import Draft202012Validator
schema = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"count": {"type": "integer", "minimum": 1},
},
"required": ["name", "count"],
"additionalProperties": False,
}
samples = [
{"name": "연필", "count": 2},
{"name": "", "count": 0, "admin": True},
]
Draft202012Validator.check_schema(schema)
validator = Draft202012Validator(schema)
for number, sample in enumerate(samples, start=1):
errors = list(validator.iter_errors(sample))
result = "통과" if not errors else f"실패 {len(errors)}개"
print(f"{number}번: {result}")
```
`python schema_check.py`를 실행합니다. 예상 결과입니다.
```text
1번: 통과
2번: 실패 3개
```
오류의 `path`로 입력 위치를 알려 주되 내부 경로나 서버 정보는 노출하지 않습니다.
[흔한 실수]
서버 검증을 생략하면 직접 보낸 요청을 막지 못합니다. `required` 없이 `properties`만 쓰거나, 숫자와 숫자 모양 문자열을 섞는 것도 흔합니다. 기존 API에 `additionalProperties: false`를 갑자기 적용하면 호환성이 깨질 수 있으므로 계약 버전과 테스트를 함께 관리하세요.
[보안 주의]
본인 소유의 로컬·격리 환경에서만 실습하세요. 요청 계층에서도 전체 크기와 중첩 깊이를 제한합니다. 신뢰하지 않는 원격 `$ref`를 자동으로 가져오지 말고 승인한 로컬 스키마나 허용 목록만 사용하세요. 정규식은 단순하게 유지하고 검증 뒤에도 인증·인가를 수행합니다.
[직접 해볼 과제]
`price`를 0 이상의 number로 추가하고 필수 속성으로 만드세요. 정상 표본에는 1200, 오류 표본에는 -1을 넣어 실패 개수가 늘어나는지 확인한 뒤 오류의 `path`와 메시지를 한 줄씩 출력해 보세요.
[확인문제]
1. `properties`와 `required`의 역할은 어떻게 다릅니까?
2. 스키마에 `$schema`를 명시하는 이유는 무엇입니까?
3. 구조 검증이 통과해도 인증·인가가 필요한 이유는 무엇입니까?
[다음 학습]
다음에는 스키마 변경이 기존 사용자를 깨뜨리는지 예제 모음으로 검사하는 계약 테스트를 배웁니다.
[공식 참고 자료]
- JSON Schema 현재 규격 안내: https://json-schema.org/specification
- JSON Schema Draft 2020-12 Core: https://json-schema.org/draft/2020-12/json-schema-core
- JSON Schema Draft 2020-12 Validation: https://json-schema.org/draft/2020-12/json-schema-validation
- Python jsonschema 검증 문서: https://python-jsonschema.readthedocs.io/en/stable/validate/
- OWASP 입력 검증 지침: https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html
- 이전글[EXT-012][실무] 주소 문자열을 직접 붙이지 않고 안전하게 만들기 26.09.08
- 다음글[EXT-010][실무] 같은 JSON을 항상 같은 바이트로 만들기 26.09.07
댓글목록
등록된 댓글이 없습니다.
