선택적 콘텐츠 레이어(OCG) 만들기
한눈에 보기
섹션 제목: “한눈에 보기”콘텐츠를 흔히 레이어라고 부르는 이름 있는 선택적 콘텐츠 그룹(OCG)으로 감쌉니다. 리더는 레이어 패널에서 각 레이어를 토글할 수 있으며, 한 레이어는 기본적으로 숨겨 둡니다. 이 레시피는 examples/26-layers.php를 따릅니다.
OCG는 Type /OCG를 갖는 ISO 32000-2 선택적 콘텐츠 그룹 딕셔너리입니다. NextPDF는 레이어 표시를 BDC/EMC 사이에 OC 마크된 콘텐츠 태그와 함께 둘러쌉니다.
composer require nextpdf/core:^3선택적 확장 기능은 필요하지 않습니다. 레이어 API는 1.0.0 이후 안정적이며 8.1–8.4 백포트 매트릭스에서 실행됩니다.
개념 개요
섹션 제목: “개념 개요”startLayer($name, $visible)는 OCG를 엽니다. 대응하는 endLayer()까지 그려진 모든 항목은 해당 그룹에 속합니다. $name은 리더가 레이어 패널에 표시하는 레이블입니다. ISO 32000-2는 OCG Name을 필수 사용자 대상 문자열로 규정합니다. $visible: false를 전달하면 그룹이 기본 구성의 OFF 상태로 등록되므로, 사용자가 켜기 전까지 리더가 이를 숨깁니다.
가시성은 리더 협조 방식입니다. 멤버십 딕셔너리의 기본 가시성 정책은 AnyOn이며, 이는 참조된 그룹 중 하나라도 ON이면 레이어가 표시된다는 뜻입니다. 숨겨진 레이어는 리더 관례에 의해서만 숨겨집니다. 제거되거나 보호되는 것이 아니며, 삭제(redaction)도 보안 제어도 아닙니다. 콘텐츠를 제거하려면 해당 콘텐츠를 그리지 마십시오.
API 표면
섹션 제목: “API 표면”API 표면은 PHPDoc에서 자동 생성됩니다. 이 레시피는 다음 두 메서드를 사용합니다.
startLayer(string $name, bool $visible = true): static— 이름 있는 OCG를 엽니다.$visible: false는 이를 기본 숨김 상태로 만듭니다.endLayer(): static— 가장 최근에 연 레이어를 닫습니다(startLayer()와 균형을 이룸).
코드 예제 — 빠른 시작
섹션 제목: “코드 예제 — 빠른 시작”<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->addPage();
$doc->startLayer('Content', visible: true);$doc->setFont('helvetica', '', 12);$doc->cell(0, 8, 'Always-visible body content.', newLine: true);$doc->endLayer();
$doc->startLayer('Debug Grid', visible: false); // hidden until toggled$doc->setDrawColor(200, 200, 200);for ($x = 0.0; $x <= 210.0; $x += 10.0) { $doc->line($x, 0, $x, 297);}$doc->endLayer();
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf');코드 예제 — 프로덕션
섹션 제목: “코드 예제 — 프로덕션”다음은 하니스에서 바로 사용할 수 있는 완전한 예제입니다. NEXTPDF_COOKBOOK_OUTPUT을 따르며 자체적으로 어떤 엔트로피도 고정하지 않습니다.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Layer Examples (OCG)');$doc->addPage();
// Layer 1 — background, visible by default.$doc->startLayer('Background', visible: true);$doc->setFillColor(230, 240, 250);$doc->rect(10, 10, 190, 277, 'F');$doc->endLayer();
// Layer 2 — watermark, visible by default; can be toggled off.$doc->startLayer('Watermark', visible: true);$doc->setFont('helvetica', 'B', 54);$doc->setTextColor(200, 200, 200);$doc->startTransform();$doc->rotate(45, 105, 148);$doc->setXY(30, 135);$doc->cell(150, 20, 'DRAFT', align: Alignment::Center);$doc->stopTransform();$doc->endLayer();
// Layer 3 — main content, visible by default.$doc->startLayer('Content', visible: true);$doc->setTextColor(0);$doc->setFont('helvetica', 'B', 20);$doc->setXY(10, 15);$doc->cell(0, 14, 'Layer Examples (OCG)', newLine: true);$doc->ln(4);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'This document contains four optional content groups. ' . "Toggle them in your reader's Layers panel.");$doc->endLayer();
// Layer 4 — debug grid, hidden by default.$doc->startLayer('Debug Grid', visible: false);$doc->setDrawColor(180, 180, 180);$doc->setLineWidth(0.15);for ($x = 0.0; $x <= 210.0; $x += 10.0) { $doc->line($x, 0, $x, 297);}for ($y = 0.0; $y <= 297.0; $y += 10.0) { $doc->line(0, $y, 210, $y);}$doc->endLayer();
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf';$doc->save($out);
echo "Created layers.pdf\n";예외 사례 및 함정
섹션 제목: “예외 사례 및 함정”- 모든
startLayer()를endLayer()로 짝을 맞추십시오. 닫히지 않은 레이어는EMC없이 매달린BDC를 남기며, 이로 인해 문서 구조가 잘못된 형식이 됩니다. 각 여는 호출을 그에 대응하는 닫는 호출과 짝지으십시오. - 숨겨진 레이어는 제거되지 않습니다.
visible: false는 리더 관례에 의해서만 콘텐츠를 숨깁니다. 표시와 모든 텍스트는 여전히 파일 안에 있으며 복구할 수 있습니다. 이는 삭제(redaction)가 아닙니다. 민감한 데이터는 그리지 마십시오. - 레이어 패널 지원은 다양합니다. 토글하려면 선택적 콘텐츠를 노출하는 리더가 필요합니다. 인쇄 파이프라인과 최소 기능 뷰어는 기본 꺼짐 레이어를 항상 표시하거나 항상 숨길 수 있습니다.
- 중첩. 중첩된 레이어는 허용되지만, 각 내부 그룹의 가시성은 여전히 독립적입니다. 멤버십 정책을 연결하지 않는 한, 외부가 OFF인 레이어가 내부가 ON인 그룹을 숨긴다고 가정하지 마십시오.
각 레이어는 OCG 딕셔너리 하나와 해당 표시를 감싸는 BDC/EMC 쌍을 추가합니다. 이 오버헤드는 무시할 수 있는 수준입니다. 비용은 레이어 개수가 아니라 레이어 내부 콘텐츠에 따라 증가하므로, 2000 ms / 64 MB 예산 내에 충분히 들어옵니다.
보안 참고 사항
섹션 제목: “보안 참고 사항”선택적 콘텐츠 가시성은 리더 협조 방식이며, 접근 제어가 아닙니다. 레이어를 숨긴다고 해서 해당 콘텐츠가 암호화되거나 삭제(redaction)되거나 제거되지는 않습니다. 누구나 레이어를 다시 활성화하거나 바이트를 추출할 수 있습니다. 기밀 텍스트를 숨기기 위해 숨겨진 레이어를 사용하지 마십시오. 대신 콘텐츠를 완전히 생략하십시오. 이 레시피는 입력 파싱이나 네트워크 접근을 수행하지 않습니다.
적합성
섹션 제목: “적합성”| 진술 | 사양 | 조항 | reference_id 참조 ID |
|---|---|---|---|
OCG 딕셔너리는 Type /OCG를 갖습니다. | ISO 32000-2 | §8.11.2 | |
OCG Name은 필수 사용자 대상 레이블입니다. | ISO 32000-2 | §8.11.2 | |
선택적 콘텐츠는 BDC/EMC 사이에 OC 태그와 함께 둘러싸입니다. | ISO 32000-2 | §8.11.3.2 | |
| OCMD 정책은 AllOn/AnyOn/AnyOff/AllOff입니다(기본값 AnyOn). | ISO 32000-2 | §8.11.4.3 |
재현성 프로필 — 구조적. 트레일러 /ID와 날짜 원자는 저장할 때마다 달라집니다. 하니스는 해당 원자를 제거하고 qpdf로 정규화된 구조를 비교합니다. 이 레시피는 NextPDF가 그 구조를 어떻게 생성하는지 설명합니다. 이는 일반적인 ISO 32000-2 적합성을 주장하지 않습니다.
상업적 맥락
섹션 제목: “상업적 맥락”해당 없음. 선택적 콘텐츠 그룹은 Core 기능이며, Premium 게이트가 없습니다.