Pro 에디션
Diff
한눈에 보기
섹션 제목: “한눈에 보기”NextPDF\Pro\Diff는 두 PDF 문서를 비교하여 무엇이 변경되었는지 보고합니다. 빠른
경로는 페이지 정렬된 텍스트 diff를 생성하고, 구조화된 경로는 이미지 및
메타데이터 변경 탐지를 더하여 결과를 JSON 또는 HTML로 형식화합니다.
가용성 및 라이선싱
섹션 제목: “가용성 및 라이선싱”이 기능은 NextPDF Pro(nextpdf/pro)에 포함되어 배포되며 Pro 등급 라이선스
봉투로 활성화됩니다. 해당 엔타이틀먼트가 없는 배포 환경에서는 기능의 클래스가
로드되지 않습니다. 에디션을 비교하고 라이선스를
받으십시오.
Diff 클래스를 게이트하는 런타임 기능 플래그는 없습니다. Pro 패키지가 설치되어 있으면 언제나 존재합니다.
composer require nextpdf/pro:^3개념 개요
섹션 제목: “개념 개요”PdfDiffer::compare()는 각 문서에서 페이지별로 텍스트를 추출하고, 이를 줄
단위로 분할한 뒤, 페이지 쌍마다 Myers 줄 diff를 실행하여 추가, 제거, 수정
영역을 생성합니다. 텍스트 추출은 ISO 32000-2:2020 §9.4의 텍스트 표시
연산자(Tj, TJ, ')를 파싱합니다.
StructuredDiffer는 그 위에 구축됩니다. 텍스트 영역을 문단 수준 변경으로
그룹화하고, 임베드된 이미지를 비교하며, 메타데이터를 비교하고, 집계 요약이 있는
StructuredDiffResult를 생성합니다. DiffFormatter는 그 결과를 JSON 문자열
또는 HTML 보고서 조각으로 직렬화합니다.
선택적 Artisan PDF 리더가 설치되어 있으면 텍스트 추출은 페이지 단위로 정확한 콘텐츠를 위해 이를 사용합니다. 그렇지 않으면 경계가 지정된 바이트 수준 폴백이 콘텐츠 스트림을 직접 스캔합니다.
이렇게 작동하는 이유
섹션 제목: “이렇게 작동하는 이유”differ는 렌더링된 픽셀이 아니라 추출된 텍스트와 구조를 비교합니다. 구조적
비교는 결정적이고 저렴하며, 검토자가 관심을 두는 편집상의 변경에 매핑됩니다.
픽셀 diff는 대신 안티앨리어싱과 폰트 힌팅 노이즈를 콘텐츠로 표시할 것입니다.
PDF는 바로 읽을 수 있는 문자가 아니라 글리프와 위치 정보를 저장하기 때문에, 모든
비교는 먼저 콘텐츠 스트림에서 텍스트를 재구성합니다. 이 추출 단계가 바로 Artisan
리더가 정확도를 높이는 이유이고, 경계가 지정된 FlateDecode 폴백이 커버리지를
안전성과 맞바꾸는 이유이며, 스캔된 페이지가 거의 diff되지 않는 이유입니다.
페이지 정렬은 예측 가능성을 위해 인덱스 기반을 유지하므로, 삽입된 페이지는 명확한
다운스트림 이동으로 읽힙니다.
설계 배경: PDF의 텍스트가 사실 텍스트가 아닌 이유.
동작 계약
섹션 제목: “동작 계약”- 입력. 소스와 타깃에 대한 원시 PDF 바이트입니다.
%PDF로 시작하지 않는 버퍼는InvalidArgumentException을 발생시킵니다. - 출력 (빠른 경로).
added,removed,modified영역 목록과isIdentical(),hasDifferences(),totalChanges()를 갖춘DiffResult입니다. - 출력 (구조화된 경로). 문단 diff, 이미지 diff, 메타데이터 변경,
DiffSummary를 갖춘StructuredDiffResult입니다. - 보고서 출력.
DiffFormatter는 JSON 문자열 또는 HTML 조각을 방출합니다. 시각적 나란히 보기 레드라인 PDF를 생성하지는 않습니다. - 리소스 경계. 압축 해제된 콘텐츠 스트림 크기는 압축 해제 폭탄을 방어하기 위해 상한이 적용됩니다. 바이트 수준 스캐너는 조작된 입력에 대한 치명적인 정규식 백트래킹을 피합니다.
- 결정성. 동일한 입력에 대해 diff 영역과 형식화된 출력은 안정적입니다.
공개 API 표면
섹션 제목: “공개 API 표면”| 타입 | 종류 | 주요 멤버 |
|---|---|---|
NextPDF\Pro\Diff\PdfDiffer | final class | static compare(string $sourcePdf, string $targetPdf): DiffResult, static compareTexts(array $sourcePages, array $targetPages): DiffResult, static extractText(string $contentStream): string |
NextPDF\Pro\Diff\StructuredDiffer | final class | __construct(?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null), compare(string $sourcePdf, string $targetPdf): StructuredDiffResult |
NextPDF\Pro\Diff\DiffFormatter | final class | toJson(StructuredDiffResult $result): string, toHtml(StructuredDiffResult $result): string |
NextPDF\Pro\Diff\DiffResult | final readonly class | array $added, array $removed, array $modified, isIdentical(): bool, hasDifferences(): bool, totalChanges(): int |
NextPDF\Pro\Diff\StructuredDiffResult | final readonly class | 텍스트 diff, 문단, 이미지, 메타데이터 변경, 요약 |
NextPDF\Pro\Diff\DiffType | enum | Added, Removed, Modified, Unchanged |
코드 샘플 — 빠른 시작
섹션 제목: “코드 샘플 — 빠른 시작”<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\PdfDiffer;
$diff = PdfDiffer::compare( file_get_contents('v1.pdf'), file_get_contents('v2.pdf'),);
if ($diff->hasDifferences()) { echo $diff->totalChanges(), " text changes detected\n";}코드 샘플 — 프로덕션
섹션 제목: “코드 샘플 — 프로덕션”<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\DiffFormatter;use NextPDF\Pro\Diff\StructuredDiffer;
function reviewReport(string $oldPdf, string $newPdf): string{ $result = (new StructuredDiffer())->compare($oldPdf, $newPdf);
// JSON for machine consumption; toHtml() for a review UI fragment. return (new DiffFormatter())->toJson($result);}엣지 케이스 및 함정
섹션 제목: “엣지 케이스 및 함정”- diff는 인덱스 기준으로 페이지 정렬됩니다. 앞쪽에 페이지를 삽입하면 이후 모든 페이지가 밀려 큰 다운스트림 변경이 보고됩니다. 이는 인덱스 정렬 비교에서 예상되는 동작입니다.
- 이미지 비교는 추가, 제거, 수정된 임베드 이미지를 탐지합니다. 지각적 시각 diff가 아니며 페이지를 픽셀 렌더링하지 않습니다.
- 스캔된 이미지 전용 PDF는 OCR이 수행되지 않으므로 텍스트 diff가 거의 또는 전혀 없습니다.
- 선택적 Artisan 리더가 없으면 추출은 경계가 지정된 폴백을 사용합니다. 압축이 심한 문서는 텍스트 커버리지가 줄어들 수 있습니다.
텍스트 추출은 문서 바이트에 선형적입니다. Myers diff는 유사한 문서에 대해 거의
선형이며 페이지 쌍당 최악의 경우 2차입니다. 압축 해제 상한이 메모리를
한정합니다. performance_budget를 참조하십시오.
보안 참고
섹션 제목: “보안 참고”바이트 수준 폴백은 조작된 PDF에 대한 치명적인 백트래킹을 피하기 위해 무한 정규식
대신 strpos 기반 스캔을 사용하며, 압축 해제 출력을 경계 지정합니다. diff 작업은
임베드된 스크립트를 실행하지 않습니다. Core 보안 모델을 참조하십시오.
적합성
섹션 제목: “적합성”| 주장 | 표준 조항 | 상태 |
|---|---|---|
추출을 위해 Tj 텍스트 연산자 파싱됨 | ISO 32000-2:2020 §9.4 | 검증됨 (단위 스위트) |
추출을 위해 TJ 배열 텍스트 연산자 파싱됨 | ISO 32000-2:2020 §9.4 | 검증됨 (단위 스위트) |
| 시각적 나란히 보기 레드라인 PDF 출력 | — | 미지원 (JSON/HTML 전용) |
Core 폴백 / 대안
섹션 제목: “Core 폴백 / 대안”문서 비교에 대한 Core 등가물은 없습니다. 선택적 Artisan 리더는 설치되어 있을 때 추출 정확도를 향상시키지만 필수는 아닙니다.
Enterprise 경계 참고
섹션 제목: “Enterprise 경계 참고”이는 콘텐츠 변경 탐지기입니다. 포렌식 차이 분석기가 아니며 증거용 또는 변조 귀속 보고서를 생성하지 않습니다. 그러한 사안은 이 모듈의 범위 밖입니다.
공개 경계
섹션 제목: “공개 경계”이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 티켓 접두사는 범위 밖입니다.