콘텐츠로 이동

템플릿의 컨텍스트

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

어떤 속성의 Code generation 탭: 템플릿이 읽는 그 플래그와 변수

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 컬럼, 요청 본문).

불리언 플래그는 활성화되었을 때에만 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 · nullabletimestamps · softDelete(불리언)idempotent · deprecated(불리언)
unique · searchable · immutable · pii운영 프로필(값): volumetry · accessPattern · traffic · freshness · sensitivity · retentioncacheSeconds(숫자) · 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 — 는 모델의 네이티브 필드 입니다.

이 컨텍스트는 버전 관리되며(ctx['contextVersion']), 애플리케이션의 저장소에 동봉된 JSON-Schema(docs/contributing/design-codegen-context.schema.json)에 의해 빠짐없이 기술됩니다 — 그것을 당신의 템플릿에 복사하면, 그 CI가 기준 컨텍스트를 검증합니다. AI 에이전트는 MCP 도구 get_design_template_contract 를 통해 동일한 계약을 즉석에서 얻습니다.