계약 / 추출
한눈에 보기
섹션 제목: “한눈에 보기”추출 도메인은 PDF를 읽고 검증하며 그 내용을 구조화된 데이터로 변환하기 위한 계약을 담고 있습니다. 여기에는 인스펙터, 준수 검증기, PDF/A 관리자, 가져온 객체 계약, 임베딩 및 벡터 인덱스 계약, 전자 송장 검증기 하위 네임스페이스가 포함됩니다.
composer require nextpdf/core:^3개념 개요
섹션 제목: “개념 개요”InspectorInterface는 원시 PDF를 읽고, 구조화된 InspectResult를 반환합니다. 이 결과에는 파일 안의 객체가 나열됩니다. 엔진이 작성하지 않은 PDF를 읽는 모든 도구에 사용하십시오.
ExternalComplianceValidatorInterface는 veraPDF와 같은 외부 검사기에 연결됩니다. 검사기는 PDF/A 및 PDF/UA를 테스트합니다. null 구현은 검사기가 설정되지 않았을 때 “사용 불가” 결과를 반환합니다. veraPDF가 없는 사이트도 계속 작동합니다. ProfileValidatorInterface는 배포 프로필을 기준으로 런타임을 검사합니다. 필수 및 권장 확장을 확인하고 형식화된 판정을 반환합니다.
PdfAManagerInterface는 PDF/A 파일 작성 중 사양 준수를 유지합니다. JavaScript, JavaScript 폼 액션, 내장 암호화를 차단합니다. PDF/A는 이 세 가지를 모두 금지합니다. 또한 모든 글꼴이 임베드되었는지 검사합니다. 사양에 맞는 메타데이터를 설정하고, 카탈로그보다 먼저 필요한 객체를 작성합니다. 실제 클래스는 Pro 에디션에 포함되어 제공됩니다. Core는 class_exists()로 이를 찾아 계약으로 캐스팅합니다. 따라서 오픈 소스 엔진에는 유료 의존성이 없습니다.
두 계약, 즉 ImportedFormObjectInterface와 EmbeddedPdfObjectInterface는 가져온 객체를 다룹니다. 이들은 기존 PDF에서 읽은 객체에 대한 형식화된 접근을 제공합니다. 그러면 엔진은 이를 다시 임베드할 수 있습니다. 무손실 경로는 원시 딕셔너리 바이트를 보존합니다. 폴백 경로는 객체 스트림에서 가져온 객체에 대해 파싱된 딕셔너리 배열을 제공합니다. 다시 임베드된 각 객체는 PDF 간접 객체입니다. 객체 번호와 세대 번호가 이를 식별합니다 — ISO 32000-2 §7.3.10.
임베딩 계약은 검색 작업에 사용됩니다. EmbeddingServiceInterface는 텍스트를 밀집 벡터로 변환하고, 모델 크기와 이름을 보고합니다. 호출자는 런타임에 맞춰 적응합니다. Pro 에디션은 CPU 모델을 실행합니다. Enterprise 에디션은 GPU 모델을 실행합니다. VectorIndexInterface는 최근접 이웃 인덱스를 구축하고 검색합니다. Core에서 사용할 수 있는 작은 인프로세스 인덱스입니다. 더 큰 규모의 검색은 Enterprise 전용 계약에 포함됩니다.
EInvoice 그룹은 계층을 가로지르는 전자 송장 검사기를 담고 있습니다. ValidatorInterface는 CII 또는 UBL 페이로드에 대해 사전 점검을 실행합니다. SchematronRunnerInterface는 비즈니스 규칙 검사를 실행합니다. ValidationResult는 발견 사항과 규칙 위반을 수집합니다. 검사기는 잘못된 입력을 예외가 아니라 결과로 거부해야 합니다. 또한 DOCTYPE 및 과도하게 큰 페이로드로부터 보호해야 합니다.
API 표면
섹션 제목: “API 표면”| 유형 | 종류 | 주요 멤버 | 안정성 | 도입 버전 |
|---|---|---|---|---|
InspectorInterface | 인터페이스 | inspect(string, InspectConfig): InspectResult | 실험적 | 2.2.0 |
ExternalComplianceValidatorInterface | 인터페이스 | validate(string, ComplianceFlavour), isAvailable() | 실험적 | 2.4.0 |
ProfileValidatorInterface | 인터페이스 | validate(DeploymentProfile): DeploymentProfileResult | 실험적 | 2.4.0 |
PdfAManagerInterface | 인터페이스 | validateNoJavaScript(), validateFont(), validateNoEncryption(), applyOutputProfile(), writeRequiredObjects() | 안정 | 1.10.0 |
ImportedFormObjectInterface | 인터페이스 | getWidth(), getHeight(), getEmbeddedObjects(), getResourcesDict(), getMediaBox(), getContentStream() | 안정 | 1.8.0 |
EmbeddedPdfObjectInterface | 인터페이스 | getRawDictionaryBytes(), getRawStreamData(), getDictionary() | 안정 | 1.8.0 |
EmbeddingServiceInterface | 인터페이스 | embed(), batchEmbed(), getDimension(), getModelName() | 실험적 | 2.1.0 |
VectorIndexInterface | 인터페이스 | build(), search(), delete(), count() | 실험적 | 2.1.0 |
EInvoice\ValidatorInterface | 인터페이스 | validate(string, ValidatorContext): ValidationResult | 실험적 | 5.1.0 |
EInvoice\ValidationResult | final readonly 클래스 | $isValid, getErrors(), getWarnings(), fail() | 실험적 | 5.1.0 |
EInvoice 네임스페이스는 SchematronRunnerInterface, ProfileInterface, ValidationFinding, RuleViolation, 그리고 ProfileType, RuleSeverity, ValidationFindingLevel 열거형도 게시합니다.
코드 예제 — 빠른 시작
섹션 제목: “코드 예제 — 빠른 시작”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\InspectorInterface;use NextPDF\Inspect\InspectConfig;
/** * Inspect a PDF and report its object count. * * @param InspectorInterface $inspector A configured inspector. * @param string $pdfData Raw PDF bytes. */function describe(InspectorInterface $inspector, string $pdfData): \NextPDF\Inspect\InspectResult{ return $inspector->inspect($pdfData, new InspectConfig());}이 함수는 계약에 의존하므로 어떤 인스펙터 구현이든 이를 충족할 수 있습니다.
코드 예제 — 프로덕션
섹션 제목: “코드 예제 — 프로덕션”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\EInvoice\ValidatorInterface;use NextPDF\Contracts\EInvoice\ValidatorContext;use NextPDF\Contracts\ExternalComplianceValidatorInterface;use NextPDF\ValueObjects\ComplianceFlavour;use Psr\Log\LoggerInterface;
final readonly class InvoiceConformanceService{ public function __construct( private ValidatorInterface $invoiceValidator, private ExternalComplianceValidatorInterface $pdfaValidator, private LoggerInterface $logger, ) {}
/** * Validate the invoice XML, then the PDF/A-3 carrier. * * @param string $xml The CII or UBL invoice payload. * @param string $pdfPath Absolute path to the PDF/A-3 carrier. */ public function validate(string $xml, string $pdfPath, ValidatorContext $ctx): bool { $result = $this->invoiceValidator->validate($xml, $ctx);
if (!$result->isValid) { $this->logger->warning('Invoice XML invalid', [ 'errors' => \count($result->getErrors()), ]);
return false; }
if (!$this->pdfaValidator->isAvailable()) { $this->logger->info('PDF/A validator unavailable; skipping carrier check.');
return true; }
$carrier = $this->pdfaValidator->validate($pdfPath, ComplianceFlavour::PdfA3b);
return $carrier->isConformant(); }}이 서비스는 검증기가 있다고 가정하지 않고, 사용할 수 없는 경우를 명시적으로 처리합니다.
예외 사례 및 주의점
섹션 제목: “예외 사례 및 주의점”EInvoice\ValidatorInterface::validate()는 형식이 잘못된 입력에 대해 실패한ValidationResult를 반환합니다. well-formedness 위반 시 예외를 던지지 않습니다.$isValid를 확인하고, 이런 경우 호출을 try/catch로 감싸지 마십시오.ExternalComplianceValidatorInterface::isAvailable()는 판정에 의존하기 전에 반드시 확인해야 합니다. null 구현은 “사용 불가”를 반환합니다. 이를 “부적합”으로 취급하면 거짓 음성이 발생합니다.EmbeddedPdfObjectInterface::getRawDictionaryBytes()는 객체 스트림에서 가져온 객체에 대해null을 반환합니다.getDictionary()로 폴백하십시오. 원시 바이트가 항상 존재한다고 가정하지 마십시오.EmbeddingServiceInterface::getDimension()은 계층에 따라 다릅니다. 고정 폭 벡터를 할당하는 코드는 차원을 하드코딩하지 말고 런타임에 읽어야 합니다.VectorIndexInterface::build()는 벡터 목록과 id 목록의 길이가 같고 차원이 일관될 것을 요구합니다. 불일치가 있으면InvalidArgumentException이 발생합니다. 구축하기 전에 검증하십시오.
검사 및 검증 비용은 문서 크기와 객체 수에 비례해 증가합니다. performance_budget은 벽시계 시간 1500ms 및 최대 64MB로, 보통 크기의 단일 문서를 처리합니다. 외부 veraPDF 호출은 검증기 자체의 프로세스 시간을 추가합니다. 이 프로세스 시간은 엔진 예산 밖에 있으며 요청 경로 밖에서 실행해야 합니다. 임베딩 비용은 텍스트 길이에 비례해 증가하며, 특히 GPU 모델에서는 루프 호출보다 배치 처리가 훨씬 저렴합니다. batchEmbed()을 우선 사용하십시오. 벡터 검색은 인프로세스 인덱스의 경우 인덱스 크기에 대해 준선형입니다. 재현성 프로필은 structural입니다. 검증 보고서는 타임스탬프와 환경 지문을 기록합니다. 두 번의 실행은 해당 필드에서 다르지만 적합성 판정은 동일하게 유지됩니다.
보안 참고 사항
섹션 제목: “보안 참고 사항”추출은 엔진이 생성하지 않은 문서를 읽으므로 모든 입력은 신뢰할 수 없습니다. 인스펙터와 전자 송장 검증기는 모두 외부에서 제공된 바이트를 파싱합니다. 전자 송장 검증기는 XML 외부 엔티티 및 billion-laughs 공격을 방지하기 위해 파싱하기 전에 DOCTYPE, 과도하게 큰 페이로드, 금지된 제어 문자 페이로드를 차단해야 합니다. 가져온 객체의 재임베딩은 외부 PDF에서 바이트를 복사합니다. 악의적인 원본 객체가 적대적인 콘텐츠를 담고 있을 수 있으므로, 재임베딩은 바이트를 실행하지 않고 보존합니다. PDF/A 시행은 JavaScript와 액션을 제거합니다. PDF/A 관리자는 JavaScript와 암호화를 거부합니다. 둘 다 프로필에서 금지되어 있으며, 둘 다 장기 보존 아카이브 문서의 악용 벡터이기 때문입니다. 검사된 콘텐츠, 가져온 객체, 송장 XML을 전반에 걸쳐 적대적 입력으로 취급하십시오.
적합성
섹션 제목: “적합성”| 주장 | 표준 | 조항 | 증거 |
|---|---|---|---|
| PDF/A-4는 JavaScript와 JavaScript 폼 액션을 금지합니다. PDF/A 관리자는 둘 다 거부합니다. | ISO 19005-4 | §6.7.1 | 조항으로 인용됨 (코퍼스에 없음) |
| 다시 임베드된 모든 객체는 객체 번호와 세대 번호로 식별되는 PDF 간접 객체입니다. | ISO 32000-2 | §7.3.10 |
ISO 19005-4는 조항으로 참조됩니다. 검증 가능한 인용 코퍼스에 없으므로 reference_id가 기록되지 않습니다. ISO 32000-2 간접 객체 주장은 용어집에 고정되어 있습니다. 둘 다 의역되었습니다. 엔진은 어떤 규범 텍스트도 재현하지 않습니다.
상업적 맥락
섹션 제목: “상업적 맥락”Core는 추출 계약을 정의하고 고정합니다. PdfAManagerInterface, EmbeddingServiceInterface, 그리고 VectorIndexInterface 뒤에서 동작하는 프로덕션 코드는 CPU 및 GPU 임베딩 모델과 전체 PDF/A 시행 경로를 포함하여 Pro 및 Enterprise 에디션에 포함되어 제공됩니다. Core는 런타임에 class_exists()로 이를 해결합니다. 따라서 오픈 소스 엔진은 상업적 의존성을 지니지 않으며, 업그레이드 시 API가 변경되지 않습니다.