렌더 매니페스트: 이식 가능한 렌더 요청
한눈에 보기
섹션 제목: “한눈에 보기”렌더 매니페스트는 무엇을 렌더링할지를 단일하고 이식 가능하게 설명합니다. 입력, 템플릿, 글꼴, 로캘, 적합성 프로파일, 서명 정책, 출력 대상과 Fast-Web-View 플래그를 담습니다. 모든 전송 계층(CLI, 프레임워크 통합, SaaS API, 향후 스트림 커넥터)은 동일한 RenderManifest를 구성하여 제출합니다. 이 계약은 결정적입니다. 동일한 두 매니페스트는 바이트 단위로 동일한 JSON으로 직렬화되며, 파생된 멱등성 키를 가지므로 다운스트림에서 동일한 렌더를 인식하고 중복 제거할 수 있습니다.
매니페스트는 Core 계약입니다. 매니페스트가 스키마를 정의하고, 엔진과 프리미엄 스트림 프로세서가 이를 실행합니다.
composer require nextpdf/core:^3매니페스트 구성
섹션 제목: “매니페스트 구성”안정적인 구성 경로는 빌더를 사용하는 것입니다(역직렬화된 매니페스트에는 RenderManifest::fromArray()를 사용합니다). 원시 생성자는 @internal입니다. 새로운 선택적 필드는 기본값과 함께 추가되므로, 빌더와 fromArray()는 호출 지점의 호환성을 깨지 않고 이를 수용합니다.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Manifest\OutputObjectKey;use NextPDF\Manifest\RenderManifestBuilder;use NextPDF\Manifest\TemplateRef;
$manifest = RenderManifestBuilder::create('invoice-2026-0001') ->withInlineInput('<h1>Invoice 2026-0001</h1>') ->withTemplate(TemplateRef::html()) ->withOutputKey(OutputObjectKey::file('invoices', '2026-0001.pdf')) ->withLocale('en-US') ->linearized() ->build();
// Deterministic, canonical-key-order JSON — equal manifests are byte-identical.$json = $manifest->toJson();| 필드 | 의미 |
|---|---|
jobId | 호출자 기준의 안정적인 논리적 id이며, 이벤트와 영수증에 그대로 반영됩니다. 멱등성 키에서는 제외됩니다. |
idempotencyKey | 결정적 중복 제거 키입니다(아래 참조). |
input | 렌더 데이터의 출처입니다. 인라인 페이로드, URI, 또는 데이터셋 참조와 콘텐츠 해시의 조합입니다. |
template | 렌더링 프런트엔드와 선택적 템플릿 id입니다. |
fonts | 선언된 글꼴 집합입니다(기본값은 비어 있음). |
locale | BCP-47 언어 태그입니다(기본값은 en-US). |
conformanceProfile | 안정적인 프로파일 id입니다(기본값은 none). |
signaturePolicy | 안정적인 정책 id입니다(기본값은 none). |
target | 출력 객체 키, 형식, 덮어쓰기 정책입니다. |
linearize | Fast-Web-View 플래그이며, 선형화와 결합됩니다. |
metadata | 이벤트에 그대로 반영되는 불투명한 스칼라 key/value 맵입니다. |
멱등성 키
섹션 제목: “멱등성 키”IdempotencyKey::derive()는 매니페스트의 렌더 결정 부분 집합만 해시합니다. 즉, 템플릿, 입력 콘텐츠 해시, 글꼴, 로캘, 적합성, 서명 정책, linearize 플래그, 대상 키입니다. 이 키는 jobId와 metadata를 의도적으로 제외합니다. 따라서 출력 대상을 포함해 렌더를 결정하는 입력이 동일한 두 요청은 작업 id나 추적 메타데이터가 다르더라도 키를 공유하며 중복 제거될 수 있습니다. 호출자가 명시적 키를 직접 제공할 수도 있으며, isDerived()는 어떤 경로로 생성되었는지 알려줍니다.
스키마 버전 관리
섹션 제목: “스키마 버전 관리”스키마 버전은 RenderManifest::SCHEMA_VERSION에 고정됩니다(현재 1.0). 스키마 진화는 메이저 버전 내에서 추가만 허용됩니다. 리더는 더 최신 마이너 스키마의 알 수 없는 키를 허용하지만, 더 최신 메이저 버전은 거부합니다. SchemaCompatibility::assertReadable()는 fromArray()에서 이를 강제하며, canRead() / isForwardRead()는 호출자가 예외를 던지지 않고 호환성을 테스트할 수 있게 해줍니다.
매니페스트는 readonly DTO이며 그 생성자는 @internal이므로, 빌더 또는 fromArray()를 통해 구성하세요. 새 필드는 추가적이며 기본값이 지정된 생성자 매개변수로 도입되므로, 필드 추가는 해당 호출 지점의 호환성을 깨는 변경이 아닙니다.
RenderManifestValidator::validate()는 예외를 던지지 않으며 모든 문제를 수집합니다. 첫 번째 문제에서 실패하는 대신, 발견한 모든 문제의 목록을 반환합니다. 안전하지 않은 출력 키(경로 순회, 절대 경로, 스트림 래퍼), 둘 이상의 입력 소스, 알 수 없는 적합성 프로파일 id, 유효하지 않은 BCP-47 로캘, 덮어쓰기 정책 불일치를 거부합니다. warnings()는 권고용이며 차단하지 않는 참고 사항을 반환합니다.
use NextPDF\Manifest\RenderManifestValidator;
$problems = (new RenderManifestValidator())->validate($manifest);
if ($problems !== []) { // Each entry is a stable, human-readable problem string.}매니페스트 렌더링
섹션 제목: “매니페스트 렌더링”SingleDocumentRenderer는 하나의 매니페스트를 하나의 PDF로 결정적으로 변환합니다. 이 렌더러는 순수하게 동작합니다. 바이트와 해당 sha-256 다이제스트를 반환하고 파일은 기록하지 않으므로, 스테이징과 정확히 한 번 커밋할 책임은 호출자(또는 스트림 프로세서)에 남습니다.
use NextPDF\Manifest\Render\SingleDocumentRenderer;use NextPDF\Manifest\Render\StandaloneDocumentFactory;
$renderer = new SingleDocumentRenderer(new StandaloneDocumentFactory());$outcome = $renderer->render($manifest);
$bytes = $outcome->bytes;$digest = $outcome->sha256;$pages = $outcome->pageCount;API 표면
섹션 제목: “API 표면”| 타입 | 종류 | 주요 멤버 | 안정성 | 도입 버전 |
|---|---|---|---|---|
RenderManifest | readonly DTO | toArray(), toJson(), fromArray(), canonicalDigestInput(), SCHEMA_VERSION | 안정 | 3.2.0 |
RenderManifestBuilder | 빌더 | create(), with*(), linearized(), build() | 안정 | 3.2.0 |
IdempotencyKey | 값 객체 | of(), derive(), equals(), isDerived() | 안정 | 3.2.0 |
SchemaCompatibility | 헬퍼 | canRead(), isForwardRead(), assertReadable() | 안정 | 3.2.0 |
RenderManifestValidator | 서비스 | validate(), warnings() | 안정 | 3.2.0 |
SingleDocumentRenderer | 서비스 | render(): RenderOutcome | 안정 | 3.2.0 |
fromArray()는 필수 필드가 누락되었거나 읽을 수 없는 스키마 버전인 경우 RenderManifestException을 던집니다.