PDF는 컨테이너입니다: 내장 파일과 연관 데이터
Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3
한눈에 보기
섹션 제목: “한눈에 보기”대부분의 사람들은 PDF를 페이지 더미로 떠올립니다. 그것은 여러분이 보는 부분입니다. 하지만 PDF는 컨테이너이기도 하며, 그 안에 다른 파일 전체를 담을 수 있습니다 — 스프레드시트, XML 페이로드, 원본 소스 문서를, 여러분이 다른 사람에게 건네는 동일한 단일 파일 속에 묶어서 말입니다.
이 페이지는 그것이 어떻게 작동하는지를 설명합니다. 즉, 바이트를 저장하는 내장 파일 스트림, 그것들을 나열하는 이름 트리, 그리고 첨부가 그저 거기에 놓여 있는지 아니면 실제로 무언가를 의미하는지를 결정하는 하나의 키입니다.
왜 중요한가
섹션 제목: “왜 중요한가”유형이 없는 첨부와 유형이 있는 첨부는 사람에게는 동일하게 보입니다. 둘 다 PDF 안에 실려 있는 파일이며 — 이 엔진에서는 — 둘 다 문서와 연관되어 있습니다. 차이는 그중 하나는 그것이 무엇을 위한 것인지를 기계에 알려 주고, 다른 하나는 기계가 추측하도록 관계를 비워 둔다는 점입니다.
그 차이가 하이브리드 전자 청구서에서는 모든 것을 좌우합니다. 세무 플랫폼은 여러분의 청구서 페이지를 읽지 않습니다. 그것은 여러분이 내장한 XML을 읽습니다. 그 XML이 보이는 문서의 청구서 데이터로서가 아니라 구별되지 않는 덩어리로 첨부되어 있다면, 적합한 리더는 그것이 처리해야 할 페이로드임을 확실하게 알 방법이 없습니다. 페이지는 완벽해 보입니다. 청구서는 거부됩니다. 그 실패는 며칠 뒤에, 보류된 결제를 뒤에 달고 도착합니다.
파일을 산출하는 계층에서 관계를 올바르게 처리하는 것이, 거부된 청구서를 하나씩 발견하는 것보다 훨씬 저렴합니다.
- PDF는 내장 파일 스트림으로 모든 파일의 바이트를 내장할 수 있습니다 (Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4). 스트림은 데이터와 더불어 작은 매개변수 딕셔너리를 담습니다. 즉, 원본 크기, 날짜, 그리고 체크섬입니다.
- 내장 파일은
EmbeddedFiles이름 트리에 목록화되므로, 리더는 문서 전체를 훑지 않고도 이름으로 그것들을 열거할 수 있습니다. - 연관 파일은 한 걸음 더 나아갑니다. 즉,
AFRelationship(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3) 을 선언합니다 — 여덟 가지 표준 값(Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified) 중 하나, 또는 사용자 정의 값 — 으로 그 파일이 자신이 첨부된 콘텐츠와 어떻게 관계되는지를 말합니다. - 그 유형이 있는 관계가 하이브리드 전자 청구서(ZUGFeRD / Factur-X)와 PDF/A-3 첨부의 배후 메커니즘입니다 (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3).
- NextPDF는 코어에서 원시 컨테이너 기본 요소를 지원합니다. 즉, 명시적인 관계를
동반한
embedFile()과embedFileFromString()입니다. 고급 에디션은 이 기본 요소 위에 전용 EN 16931 / ZUGFeRD / Factur-X 전자 청구서 임베더를 추가합니다.
NextPDF가 접근하는 방식
섹션 제목: “NextPDF가 접근하는 방식”서로의 위에 쌓인 두 계층으로 생각해 보십시오.
아래 계층은 저장입니다. 내장 파일 스트림
(Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4) 은 원본 파일의 바이트를 PDF 스트림
객체로 감싼 것으로, 원본 크기, 수정 날짜, 그리고 압축되지 않은 데이터의 체크섬을
기록하는 매개변수 딕셔너리를 동반합니다. 스트림은 파일 명세 딕셔너리를 통해
도달되며, 그 딕셔너리의 /EF 딕셔너리가 내장 파일 스트림을 가리킵니다 — 스트림
자체는 /EF를 담지 않습니다. 리더는 그 파일을 바이트 단위로 그대로 다시 꺼낼 수
있습니다. 이 파일들을 찾을 수 있도록, 문서 카탈로그는 EmbeddedFiles 이름 트리 —
이름에서 각 파일 명세로의 정렬된 지도 — 를 담으므로, 뷰어는 모든 페이지를 훑지 않고도
“이 PDF 안에는 3개의 파일이 있다”라고 나열할 수 있습니다.
위 계층은 의미입니다. 내장 파일은 그 자체로는 그저 존재할 뿐입니다. 연관 파일
메커니즘 (Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13) 은 파일을 무언가에 — 문서
전체, 페이지, 그래픽 객체에 — 부착하고, 거기에 AFRelationship을 새깁니다. ISO
32000-2는 여덟 가지 표준 값으로 된 작은 어휘를 정의하며
(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3), 사용자 정의 값도 허용합니다. 각
표준 값은 정확한 질문 하나에 답합니다.
AFRelationship | 파일에 대해 주장하는 것 |
|---|---|
Source | 이것은 보이는 콘텐츠가 그것으로부터 생성된 소스 자료입니다(예: 원본 워드프로세서 문서). |
Data | 이것은 보이는 콘텐츠에 결부된 구조화된 데이터입니다 — 표준적인 사례는 렌더링된 청구서 페이지 배후의 청구서 XML입니다. |
Alternative | 이것은 동일한 콘텐츠의 대체 표현입니다(예: 오디오 또는 비디오 버전). |
Supplement | 이것은 콘텐츠를 확장하지만 그 일부는 아닌 보충 자료입니다. |
EncryptedPayload | 내장 파일은 PDF가 불투명한 덩어리로 감싸는 암호화된 페이로드입니다. |
FormData | 파일은 양식 데이터(FDF, XFDF, 또는 XML 양식 페이로드)입니다. |
Schema | 파일은 Data 파일의 구조를 기술하는 스키마입니다(예: XML 데이터를 위한 XSD 또는 JSON Schema). |
Unspecified | 관계가 의도적으로 명시되지 않았습니다. 정직하지만, 기계에 아무것도 알려 주지 않습니다. |
이 여덟 가지를 넘어, 표준은 애플리케이션 고유의 사용자 정의 관계 값 또한 허용하므로, 어휘는 고정된 것이 아니라 확장 가능합니다.
연관 파일은 키 하나만이 아니라 두 가지가 함께 작동하여 정의됩니다. /AF 연관은
파일 명세를 문서의 한 부분에 결속하고, 파일 명세 안의 AFRelationship 키는 그런
다음 의미론적 관계를 진술합니다. 연관 지점(문서 카탈로그, 페이지, 또는 객체)의
/AF 엔트리는 배열입니다 — 그 배열은 보통 간접 참조로 하나 이상의 파일 명세
딕셔너리를 담습니다. /AF는 단일 참조가 아닙니다. 문서 수준 연관 파일은 문서
카탈로그의 /AF 배열에 나열되어 자신의 AFRelationship을 담은 파일 명세입니다. 그
스프레드시트를 Unspecified로 표시하면 그것을 문서와 연관시키기는 했으되 왜인지에
대해서는 기계에 아무것도 알려 주지 않은 것입니다. 같은 스프레드시트를 Data로
표시하면 모든 적합한 리더에게 그것이 무엇이고 무엇을 위한 것인지를 알려 준 것입니다.
바이트는 같습니다. 의미론은 그렇지 않습니다.
이것이 바로 전자 청구서 사례가 “XML 파일을 첨부하라”가 아닌 이유입니다. 그것은 “이
XML을 이 문서를 위한 Data 연관 파일로서, 적합한 PDF/A-3 운반체 안에 내장하라”입니다
— 청구서 유효성과 법적 수용은 운반체가 수행하지 않는 별개의 검사로 남습니다. 그
흐름에는 네 단계가 있으며, 그것을 올바르게 유지하는 것은 바로 순서입니다.
- Store the bytes파일은 자신의 크기, 날짜, 그리고 체크섬과 함께 내장 파일 스트림으로 감싸진다 (ISO 32000-2 §7.11.4).
- Register it by name파일 명세가 EmbeddedFiles 이름 트리에 추가되어, 리더가 문서를 훑지 않고도 첨부를 열거할 수 있다.
- Declare the relationshipAFRelationship 값(Source나 Data 같은 여덟 가지 표준 값 중 하나)이 파일이 콘텐츠와 어떻게 관계되는지를 표시하며, 문서 수준에서 연관된다 (ISO 32000-2 §14.13.3).
- Make it archivalPDF/A-3 운반체는 내장된 페이로드가 적합한 보관용 PDF/A 문서 하나 안에 실리도록 허용한다. 청구서 유효성과 법적 수용은 별개의 검사로 남는다 (ISO 19005-3).
그 네 번째 단계가 바로 PDF/A-3가 별개의 프로파일로 존재하는 이유입니다. 이전의 보관용
프로파일들은 무엇을 내장할 수 있는지를 제한했습니다. PDF/A-3
(Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3) 는 모든 형식의 파일이 적합한
보관용 문서 안에 실릴 수 있도록 허용하는 부분입니다. 그것은 내장된 페이로드를
허용합니다 — 그 페이로드를 검증하거나 법적 지위를 부여하지는 않습니다. 그것이 없다면
하이브리드 청구서 — 사람이 읽는 페이지이면서 세무 시스템이 파싱하는 데이터이기도 한
하나의 파일 — 는 적합한 보관용 PDF/A 문서가 아예 될 수 없을 것입니다. 청구서가
유효한지 그리고 법적으로 수용되는지는 별개의 문제로 남습니다. 고급 에디션이
추가하는 전용 전자 청구서 임베더는 바로 이것 위의 편의 이음매입니다. 즉, 페이로드를
내장하고, 관계를 Data로 설정하고, 그것을 올바르게 등록하므로, 여러분이 컨테이너
배관을 손으로 조립하지 않아도 됩니다. 더 깊은 청구 및 보관 메커니즘은 아래에 링크된
이웃하는 두 페이지에 있습니다. 이 페이지는 그 둘이 함께 딛고 서는 컨테이너에 관한
것입니다.
실용적인 예제
섹션 제목: “실용적인 예제”작고 완전한 프로그램입니다. 중요한 두 호출은 유형이 없는 연관 파일과 유형이 있는
연관 파일의 차이이며 — 관계는 여러분이 설정해야 할 명시적인 인수입니다. 이 엔진에서는
두 호출 모두 연관 파일을 산출합니다. embedFile()과 embedFileFromString()은
항상 파일 명세를 문서 카탈로그의 /AF 배열에 등록하므로, 관계가 바꾸는 유일한 것은
그 연관이 무엇을 의미하는가입니다. 그것은 Unspecified로 기본 설정되며, 이는 파일을
연관시키되 왜인지에 대해서는 기계에 아무것도 알려 주지 않습니다. 전자 청구서
페이로드의 경우, 리더가 그것을 찾을 수 있도록 Data로 설정합니다.
<?php
declare(strict_types=1);
use NextPDF\Core\Document;use NextPDF\Navigation\AFRelationship;
$document = Document::createStandalone();$document->addPage();$document->setFont('helvetica', 'B', 16);$document->cell(0, 12, 'Invoice INV-2026-0042', newLine: true);
// An UNTYPED associated file: the bytes are embedded AND the file spec is// added to the document catalog's /AF array, but the relationship says// nothing about why. A reader can open it; a machine cannot tell its role.// The relationship is left Unspecified (its default); the second argument is// the human-readable description. embedFile accepts the AFRelationship enum.$document->embedFile( '/srv/invoices/INV-2026-0042-source.docx', 'Original source document', AFRelationship::Unspecified,);
// A TYPED associated file: the invoice XML is declared as the DATA behind// the visible page. This is the relationship a hybrid e-invoice reader// looks for — the same intent the dedicated e-invoice embedder sets.// embedFileFromString takes the data, a filename, a description, and a// relationship as a PDF-name string ('/Data').$invoiceXml = $generateCiiXml(); // your ERP authors this; the engine never does$document->embedFileFromString( $invoiceXml, 'factur-x.xml', 'Factur-X invoice data', '/Data',);
$bytes = $document->getPdfData();'/Data' 관계는 오해의 여지가 없습니다. 첫 번째 첨부 — Unspecified로 남겨진 것 —
은 명시된 의미는 없지만 똑같이 연관되어 있습니다. 두 호출 모두에 대해 엔진은 내장 파일
스트림을 쓰고, 파일을 EmbeddedFiles 이름 트리에 추가하고, 그 파일 명세를 문서
카탈로그의 /AF 배열에 나열하고, 여러분이 진술한 관계를 기록합니다 — 엔진이 대신
하나를 골라 주지 않습니다. 이 엔진에는 이름 트리 전용 모드가 없습니다. 이렇게 내장하는
모든 파일은 문서에 연관된 파일이므로, 관계는 여러분이 제어하는 유일한 레버입니다.
흔한 오해
섹션 제목: “흔한 오해”흔한 가정은 “내장된”과 “연관된”이 같은 것을 가리키는 두 단어라는 것입니다. 아닙니다.
내장된은 저장에 관한 것입니다 — 바이트가 PDF 안에 있다는 뜻입니다. 연관된은 결속에
관한 것입니다 — 파일 명세가 문서의 한 부분에 있는 /AF 배열에 나열되어 있고,
AFRelationship을 담고 있다는 뜻입니다. 추상적인 PDF 모델에서는 파일이 결코 연관되지
않고도 이름 트리에 내장될 수 있습니다. NextPDF의 embedFile() 경로는 그것을 그
상태로 두지 않습니다 — 항상 /AF 연관을 씁니다 — 따라서 이 엔진에서 열린 질문은 결코
파일이 연관되어 있는지 여부가 아니라 관계가 무엇을 말하는가입니다.
두 번째 함정. 뷰어가 어느 첨부가 청구서인지를 “알아낼” 것이라고 가정하는 것입니다.
적합한 리더는 추측하기로 되어 있지 않습니다. 그것은 관계가 Data라고 말하는 파일을
찾습니다. 관계를 Unspecified로 남겨 두면 페이로드를 연관시키되 그 역할에 대해서는
기계에 유용한 것을 아무것도 알려 주지 않은 것입니다.
한계와 경계
섹션 제목: “한계와 경계”컨테이너 메커니즘은 솔직하게 짚어 둘 가치가 있는 방식으로 강력합니다. embedFile()은
PHP 프로세스가 읽을 수 있는 어떤 경로든 읽습니다. 그것이 기능입니다 — 그리고 그것이
경계이기도 합니다. 엔진은 주어진 바이트를 부착합니다. 어떤 경로가 여러분이 노출하려고
의도한 것인지는 엔진이 여러분 대신 결정하지 않으며, 결정할 수도 없습니다.
| Edition | Availability |
|---|---|
| Core |
|
| Pro | Not in this edition |
| Enterprise | Not in this edition |
명료하게 진술할 가치가 있는 추가적인 한계가 두 가지 있습니다.
- 내장은 검증이 아닙니다. 엔진은 여러분이 주는 바이트를 담습니다. 내장된 XML이 적합한 청구서 페이로드인지는 별개의 문제이며, 검증기가 답합니다 — 청구 페이지를 참조하십시오.
- 유형이 있는 첨부는 그 자체로 적합한 보관용 파일이 아닙니다. 하이브리드 파일을 법적인 PDF/A-3 문서로 만들려면 보관 모드와 독립적인 적합성 검사가 필요합니다 — 보관 페이지를 참조하십시오.
관련 문서
섹션 제목: “관련 문서”- 청구서와 전자 청구 — 이
메커니즘이 가능하게 하는 사용 사례. 즉, 기계가 읽을 수 있는 청구서를 자신의
Data연관 파일로 담는 하이브리드 PDF. - 보관과 PDF/A — 운반체가 PDF/A-3 파일인 이유와, 적합성이 약속하는 것과 약속하지 않는 것.
- PDF 파일의 해부학 — 이름 트리와 문서 카탈로그가 파일 구조 안 어디에 자리 잡는지.
- 스트림과 필터 — 내장 파일의 바이트가 스트림 객체 안에 어떻게 저장되고 압축되는지.
용어집
섹션 제목: “용어집”- 내장 파일 스트림 — 외부 파일의 바이트를 담은 PDF 스트림 객체로, 원본 크기, 날짜, 그리고 체크섬을 기록하는 매개변수 딕셔너리를 동반합니다 (ISO 32000-2 §7.11.4).
- EmbeddedFiles 이름 트리 — 내장 파일을 이름으로 나열하는 문서 카탈로그 안의 정렬된 지도로, 리더가 문서 전체를 훑지 않고도 첨부를 열거할 수 있게 합니다.
- 연관 파일 —
/AF연관(문서 카탈로그, 페이지, 또는 객체 상의)으로 문서의 한 부분에 결속되고, 그것이 그 콘텐츠와 어떻게 관계되는지를 진술하는AFRelationship을 담은 내장 파일. 문서 수준 사례 — 카탈로그의/AF배열에 있는 파일 명세 — 가 이 페이지가 중심으로 삼는 것입니다 (ISO 32000-2 §14.13.3). - AFRelationship — 그 값이 관계를 명명하는 파일 명세 키 (ISO 32000-2 §7.11.3).
여덟 가지 표준 값(
Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified) 중 하나, 또는 사용자 정의 값을 취합니다.Data는 하이브리드 전자 청구서 페이로드가 사용하는 값입니다. - PDF/A-3 — 모든 형식의 파일을 내장하도록 허용하여 적합한 하이브리드 문서를 가능하게 하는 ISO 19005-3 보관용 프로파일.
- 하이브리드 청구서 — 사람이 읽을 수 있는 페이지이면서 기계가 읽을 수 있는 내장 청구서 페이로드이기도 한 하나의 PDF 파일.