템플릿의 컨텍스트
코드를 생성할 때, Restorm은 당신의 설계 전체 를 ctx 라는 객체 형태로
템플릿에 전달합니다. 당신의 모델, enum, 라우트, 그리고 무엇보다 그 의도
(searchable, PII, cache, 그리고 모델의 운영 프로필 전체: volumetry,
accessPattern, traffic, freshness, sensitivity, retention)가 거기에 있습니다 —
템플릿은 그것들을 읽어 무엇을 생성할지 결정합니다. 이를 위해 변수는 필요
없습니다: 당신이 설계에 이미 입력한 정보는 직접 사용할 수 있습니다.

ctx 의 형태
Section titled “ctx 의 형태”ctx├─ design # name, version, description, basePath, defaultAuth, vars├─ enums[] # name, description, values[]├─ models[] # name, description, inherits, identifier, timestamps, softDelete,│ # volumetry, accessPattern, traffic, freshness, sensitivity,│ # retention, properties[], allProperties[], examples[], vars└─ groups[] # name, basePath, versionPrefix, headers[], routes[] └─ routes[] # method, path, fullPath, params[], body, responses[], # auth, pagination, cacheSeconds, idempotent, deprecated, vars참조는 이름으로 이루어집니다(내부 식별자로는 결코 아닙니다): property.enum
은 enum의 이름, property.references.model 은 대상 모델의 이름, model.inherits
는 부모의 이름입니다. 모델에서 properties[] 는 그 고유 속성을 나열하고(타입
선언을 위해), allProperties[] 는 고유 + 상속된, 평탄화된 속성을
나열합니다(완전한 인스턴스를 위해: 예시 데이터, SQL 컬럼, 요청 본문).
플래그 읽기: 황금률
Section titled “플래그 읽기: 황금률”불리언 플래그는 활성화되었을 때에만 ctx에 존재합니다. 엔진은
StrictUndefined 로 렌더링합니다: 따라서 키의 존재를 테스트 해야 하며,
그 값을 결코 테스트해서는 안 됩니다.
{# ✅ correct — on teste la présence #}{% if 'searchable' in p %}INDEX({{ p['name'] }}){% endif %}
{# ❌ faux — lève une erreur quand le flag est absent #}{% if p.searchable %}…{% endif %}property.required(불리언)와 route.auth(열거)만이 항상 존재합니다. 다른
불리언 플래그는 「존재 = 참」입니다. 값 을 가지는 필드(volumetry, 운영
프로필, cache…)는 입력되었을 때 그 값을 가지며, 그렇지 않으면 존재하지 않습니다 —
동일한 존재 규칙입니다.
| 속성 에서 | 모델 에서 | 라우트 에서 |
|---|---|---|
readOnly · writeOnly · nullable | timestamps · softDelete(불리언) | idempotent · deprecated(불리언) |
unique · searchable · immutable · pii | 운영 프로필(값): volumetry · accessPattern · traffic · freshness · sensitivity · retention | cacheSeconds(숫자) · pagination(객체) |
모델의 운영 프로필 값: accessPattern
(readHeavy / writeHeavy / balanced / appendOnly), traffic
(low / medium / high), freshness(strong / shortCache / longCache),
sensitivity(public / internal / confidential / pii), retention
(permanent / archivable / ephemeral), volumetry(hundreds /
tenThousands / millions).
예: 읽기 수요가 높은 데이터를 캐싱하기
Section titled “예: 읽기 수요가 높은 데이터를 캐싱하기”정보가 이미 설계에 있는지 여부에 따라 두 가지 경우가 있습니다.
a) 설계가 이미 그 정보를 가지고 있다
Section titled “a) 설계가 이미 그 정보를 가지고 있다”어떤 라우트에 캐시 기간 을 입력했다면, 그것은 route['cacheSeconds'] 에
도착합니다. route['idempotent'] 는 그것이 캐싱하기에 안전(읽기 전용)함을
알려줍니다.
{% for group in ctx['groups'] %}{% for route in group['routes'] %}{% if 'cacheSeconds' in route and 'idempotent' in route %}// {{ route['method'] }} {{ route['fullPath'] }}app.use("{{ route['fullPath'] }}", cache({{ route['cacheSeconds'] }}));{% endif %}{% endfor %}{% endfor %}b)「읽기 수요가 높다」는 모델의 네이티브 필드
Section titled “b)「읽기 수요가 높다」는 모델의 네이티브 필드”변수는 필요 없습니다:「읽기 수요가 높다」는 모델의 액세스 프로필 그 자체입니다.
모델의 설정, 운영 프로필 그룹에서 Lecture dominante(읽기 우세)를 선택하면,
템플릿은 그것을 model['accessPattern'] 에서 읽습니다. 그것을
model['freshness'](신선도 허용치)와 결합해, 캐싱해야 하는지, 얼마나 오래
캐싱할지 결정합니다.
{% for model in ctx['models'] %}{% if model['accessPattern'] == 'readHeavy' and model['freshness'] != 'strong' %}{% set ttl = 3600 if model['freshness'] == 'longCache' else 60 %}registerCache("{{ model['name'] }}", {{ ttl }}); // cache activé ({{ ttl }}s){% endif %}{% endfor %}!= 'strong' 테스트에 주목하세요: 읽기 우세 이지만 강한 일관성을 가진 모델은
캐싱해서는 안 됩니다. 두 의도를 설계 안에서 나란히 두는 것의 바로 그 의의가
여기에 있습니다.
생성 변수 는 설계가 아직 가지고 있지 않은 것(템플릿 고유의 설정)을 위해 남겨두세요: 비즈니스 의도 — volumetry, accessPattern, traffic, freshness, sensitivity, retention — 는 모델의 네이티브 필드 입니다.
완전한 계약
Section titled “완전한 계약”이 컨텍스트는 버전 관리되며(ctx['contextVersion']), 애플리케이션의 저장소에
동봉된 JSON-Schema(docs/contributing/design-codegen-context.schema.json)에 의해
빠짐없이 기술됩니다 — 그것을 당신의 템플릿에 복사하면, 그 CI가 기준 컨텍스트를
검증합니다. AI 에이전트는 MCP 도구 get_design_template_contract 를 통해 동일한
계약을 즉석에서 얻습니다.