표준 JSON 모델
Source: Dev.to
목적
Canonical JSON 모델은 FACET‑compliant 시스템이 생성하는 AI 실행 상태의 안정적이고 결정론적인 표현을 정의합니다. 그 목표는 다음을 보장하는 것입니다:
- 동일한 입력이 바이트 단위로 동일한 JSON을 생성하도록
- 출력이 비교 가능하고, 캐시 가능하며, 차이점 확인 가능하고, 재생 가능하도록
- 제공자별 형식이 다운스트림 시스템에 비결정성을 유출하지 않도록
Canonical JSON은 결정론적 컴파일과 확률적 모델 실행 사이의 경계 아티팩트입니다.
왜 결정론적 JSON이 중요한가
현대 LLM 스택은 숨겨진 비결정성을 겪고 있습니다:
| 비결정성 원인 | 영향 |
|---|---|
| JSON 객체의 필드 재정렬 | 캐시 신뢰성 저하 |
| 선택적 필드의 등장/소멸 | 재생 불가능 |
| 공급자별 메시지 레이아웃 | 회귀 테스트 무의미 |
| 스트리밍 vs 비스트리밍 구조적 변동 | 감사 및 규정 준수 취약 |
| 런타임에 적용되는 암시적 기본값 | – |
이러한 영향으로:
- 캐시 신뢰성 저하
- 재생 불가능
- 회귀 테스트 무의미
- 감사 및 규정 준수 취약
정규화된 JSON은 단일 정규화 형태를 강제함으로써 이러한 오류 모드를 제거합니다.
Source: …
정규 JSON 문서
정규 JSON 문서는 다음 모든 조건을 만족하는 JSON 객체입니다:
- 결정적인 필드 순서
- 모든 선택적 필드의 명시적 존재 여부
- 안정적인 숫자 및 문자열 인코딩
- 제공자에 구애받지 않는 구조
- 타입이 지정된 실행 상태에서 완전히 파생
FACET는 정규 JSON을 직렬화 편의성이 아니라 컴파일된 산출물로 취급합니다.
최상위 순서 (규범)
meta
system
tools
examples
history
user
assistant
output
모든 호환 구현은 이 순서를 반드시 유지해야 합니다.
중첩 객체는 다음을 따릅니다:
- 사전식 키 순서 (UTF‑8, 코드 포인트 순)
- 실행 순서 또는 명시적 키에서 파생된 안정적인 리스트 순서
정규 JSON은 암시적 기본값 및 구조적 모호성을 금지합니다.
핵심 규칙
| Rule | Requirement |
|---|---|
| Optional Fields | 스키마에 정의되어 있지만 런타임 값에 존재하지 않는 필드는 null 로 렌더링되어야 합니다. 알려진 필드를 생략하는 것은 금지됩니다. |
| Empty Lists | [] 로 렌더링됩니다. |
| Empty Objects | {} 로 렌더링됩니다. |
| Booleans | 항상 명시적으로 (true / false) 표시합니다. |
| Integers | 앞에 0을 붙이지 않고 렌더링합니다. |
| Floats | 정규화된 소수 형태로 (필요한 경우를 제외하고 지수 표기 사용 안 함) 렌더링합니다. |
| Strings | UTF‑8, NFC‑정규화된 문자열이어야 합니다. |
| Escaping | JSON 표준을 따르며, 다른 인코딩 방식은 사용하지 않습니다. |
| Disallowed values | NaN, Infinity, 로케일에 의존하는 숫자 형식은 허용되지 않습니다. |
Rationale – 명시적인 null 은 JSON 키 집합이 데이터 내용에 관계없이 일정하게 유지되도록 보장합니다. 이는 O(1) 형태 검증과 언어별 기본 직렬화 동작 차이(예: JavaScript vs. Rust)에도 안정적인 해싱을 가능하게 합니다.
Production Pipeline
Input: [.facet] → [AST] → [R‑DAG] → [Token Box]
│
Core: [[ CANONICAL JSON IR ]] ─┤
│
Views: ┌──────────────┼───────────────┐
▼ ▼ ▼
[OpenAI] [Anthropic] [Gemini]
│ │ │
Output: └──────────────┼───────────────┘
▼
[ API Call ]
- Canonical JSON 은 단일 진실의 원천입니다.
- 제공자 페이로드(OpenAI, Anthropic, Gemini 등)는 파생된 뷰이며, 진실의 원천이 아닙니다.
FACET은 다음 규칙을 강제합니다:
모든 제공자 페이로드는 일시적입니다. Canonical JSON은 영구적입니다.
결과
- 제공자를 전환해도 이력이 무효화되지 않습니다.
- 저장된 실행은 벤더 API가 변경되더라도 재생 가능합니다.
- 감사 및 규정 준수 보고서는 제공자 스키마 변동에 영향을 받지 않습니다.
- 제공자 어댑터의 버그가 핵심 실행 기록을 손상시킬 수 없습니다.
실제로:
- Canonical JSON은 저장, 해시, 차이 비교, 그리고 캐시됩니다.
- 제공자 페이로드는 즉시 생성되어 바로 폐기됩니다.
따라서 실행 레이어에서 벤더 종속성은 구조적으로 불가능합니다. 제공자가:
- 페이로드를 거부하거나
- 문서화되지 않은 제약을 적용하거나
- 스트리밍 의미를 변경하면
그 실패는 어댑터 레이어에만 국한되고, Canonical JSON은 유효하고 안정적이며 재사용 가능합니다.
@test / 스냅샷 테스트
Canonical JSON은 다음과 같은 이유로 AI 시스템에 대한 진정한 스냅샷 테스트를 가능하게 합니다:
- byte‑for‑byte deterministic
- provider‑agnostic
- fully explicit in structure
일반적인 테스트 흐름
- 전체 실행 파이프라인을 Pure Mode(순수 모드)로 실행합니다.
- 정규 JSON을 생성합니다.
- JSON을 해시하거나 스냅샷으로 저장합니다.
- 이후 실행은 이 스냅샷과 비교합니다.
@test "payment flow"
vars:
amount: 100
currency: "USD"
assert:
- canonical_json_hash == "b3e2…"
보장 사항
- 로직 변경이 즉시 표시됩니다.
- 공급자 드리프트가 테스트를 무효화할 수 없습니다.
- 회귀는 배포 전에 감지됩니다.
기업 시스템에 대해 다음을 가능하게 합니다:
- deterministic CI pipelines → 결정론적 CI 파이프라인
- audit‑safe execution logs → 감사‑안전 실행 로그
- reproducible incident analysis → 재현 가능한 사고 분석
- long‑term caching with cryptographic guarantees → 암호학적 보장을 갖춘 장기 캐싱
다음 모든 조건이 충족될 경우:
- 동일한 FACET 문서
- 동일한 입력
- 동일한 실행 모드 (Pure)
- 동일한 렌즈 레지스트리
그렇다면:- 정규 JSON은 동일해야 합니다
Hash(canonical_json)도 동일해야 합니다- 하위 동작은 재현 가능해야 합니다
이는 다음의 기반이 됩니다:
- memoization → 메모이제이션
- snapshot testing → 스냅샷 테스트
- deterministic agents → 결정론적 에이전트
Comparison: Ad‑hoc JSON vs. Canonical JSON
| Property | Ad‑hoc JSON | Canonical JSON |
|---|---|---|
| Field order | Unstable | Deterministic |
| Optional fields | Implicit | Explicit (null) |
| Provider leakage | High | None |
| Diff‑friendly | No | Yes |
| Cache‑safe | No | Yes |
Canonical JSON은 AI 행동을 버전 관리되고 테스트 가능한 아티팩트로 전환합니다—일시적인 모델 출력이 아닙니다.
재플레이 가능성
| 재플레이 가능 | 아니오 |
| 예 |
JSON은 데이터 형식이 아니다.
시맨틱 경계.
Canonical JSON은 그 경계를 논리적으로 다루고, 테스트하며, 신뢰할 수 있는 것으로 변환합니다.
FACET Canonical JSON은 AI 시스템에서 LLVM IR이 컴파일러에서 하는 역할과 동일합니다.
컴파일러 스택
FACET Stack
| 계층 | 설명 |
|---|---|
| 소스 코드 | .facet 문서 |
| AST | 타입이 지정된 FACET AST |
| LLVM IR | 정규화된 JSON |
| 타깃 백엔드 | 제공자 어댑터 (OpenAI / Anthropic / Gemini) |
| 머신 코드 | 제공자 페이로드 |
LLVM IR과 공유되는 주요 특성
- 제공자 독립적인 표현
- 결정적이며 안정적인 형태
- 차이점 비교 가능 및 검사 가능
- 최적화, 캐싱 및 재생을 위한 안전한 대상
LLVM이 하나의 프로그램이 소스 코드를 변경하지 않고도 x86, ARM, WebAssembly 등을 타깃으로 할 수 있는 것처럼, FACET은 하나의 에이전트 아키텍처가 실행 의미론을 변경하지 않고도 여러 LLM 제공자를 타깃으로 할 수 있게 합니다.
이것이 Canonical JSON이 Intermediate Representation 으로 취급되고, 단순한 직렬화 세부 사항이 아닌 이유입니다. 이 계층이 존재하면 제공자 페이로드는 교체 가능한 구현 세부 사항이 됩니다.
규범적 정규 JSON 모델
이 문서는 FACET v2.0 및 이후 버전에 대한 규범적인 정규 JSON 모델을 정의합니다.
모든 호환 구현은 정규 실행 출력을 생성할 때 이 규칙을 MUST 따라야 합니다.