Pro 에디션
Interop — 심층 참조
한눈에 보기
섹션 제목: “한눈에 보기”이 페이지는 NextPDF\Pro\Interop\V1에 대한 계약 수준의 참조입니다. 이 모듈은 14개의 공개 심볼을 포함합니다. 직렬화 계약 1개(InteropResultInterface), CI 무결성 가드 1개(SchemaLock), 최상위 결과 DTO 3개(ExtractedText, DocumentSegmentation, FormData), 그리고 이를 뒷받침하는 값 객체와 열거형 9개입니다. 모든 DTO는 하나의 분석 결과에 대한 불변이며 JSON 직렬화가 가능한 뷰입니다. 와이어 형태는 버전이 지정되고 잠겨 있으며, 이 표면의 어떤 것도 분석을 다시 실행하지 않습니다. 작업 중심 관점은 기능 페이지에서 확인할 수 있습니다.
가용성 및 라이선스
섹션 제목: “가용성 및 라이선스”이 기능은 NextPDF Pro(nextpdf/pro)에 포함되어 제공되며 Pro 등급 라이선스 봉투로 활성화됩니다. 해당 엔타이틀먼트가 없는 배포는 이 기능의 클래스를 로드하지 않습니다. 에디션을 비교하고 라이선스를 받으세요.
이 모듈을 게이트하는 런타임 기능 플래그는 없습니다. nextpdf/pro가 설치되고 라이선스가 부여된 경우 언제든지 클래스를 사용할 수 있습니다.
공개 API 표면
섹션 제목: “공개 API 표면”| 심볼 | 매개변수 | 기본 동작 | 반환 | 던지거나 실패하는 조건 | 비고 |
|---|---|---|---|---|---|
InteropResultInterface | — | 최상위 결과 DTO를 위한 계약; JsonSerializable을 확장 | — | 던지지 않음 | SCHEMA_VERSION은 문자열 '1.0'입니다. |
InteropResultInterface::toArray() | 없음 | 항상 schema_version을 담는 JSON 안전 배열로 직렬화 | array<string, mixed> | 던지지 않음 | 구현체는 type 판별자도 방출합니다. |
InteropResultInterface::toJson() | int $flags = 0 | toArray() 출력을 인코딩; JSON_THROW_ON_ERROR가 항상 OR로 포함됨 | string | 인코딩할 수 없는 데이터에 대해 JsonException | JSON_PRETTY_PRINT 같은 플래그를 전달하세요. |
SchemaLock::verify() | 없음 | 디스크상의 V1 schema.json을 해시하여 잠긴 SHA-256과 비교 | bool | 던지지 않음 | 스키마 파일이 없거나, 읽을 수 없거나, 수정되면 false. |
SchemaLock::expectedHash() | 없음 | 잠긴 해시를 반환 | string | 던지지 않음 | CI 실패 분류를 위한 진단 출력. |
SchemaLock::actualHash() | 없음 | 현재 스키마 파일의 해시를 반환 | string | 던지지 않음 | I/O 실패 시 센티넬 문자열 FILE_NOT_FOUND / READ_FAILED가 해시를 대체합니다. |
BoundingBox | float $x, float $y, float $width, float $height | PDF 사용자 공간 포인트 단위의 불변 박스, 원점은 왼쪽 아래 | — | 던지지 않음 | area(), overlaps(), toArray(), fromArray(). |
DocumentInfo | int $pageCount 및 선택적 메타데이터 필드 6개 | 불변 문서 메타데이터 | — | 던지지 않음 | fromArray()가 모든 필드를 타입 가드하며, 없는 필드는 기본값으로 대체됩니다. |
PageInfo | int $pageNumber, float $width, float $height, int $rotation = 0 | 불변 페이지 메타데이터 | — | 던지지 않음 | isLandscape(); fromArray()는 숫자 문자열과 부동소수를 강제 변환합니다. |
ExtractedText | list<ExtractedPage> $pages, DocumentInfo $documentInfo, float $processingTimeMs = 0.0 | 전체 문서 텍스트 추출 결과 | — | toJson()에서만 JsonException | page(), totalBlockCount(), plainText(), fromArray(). |
ExtractedPage | PageInfo $pageInfo, list<TextBlock> $textBlocks | 읽기 순서대로 담긴 페이지별 텍스트 블록 컨테이너 | — | 던지지 않음 | plainText()는 블록 내용을 단일 공백으로 연결합니다. |
TextBlock | string $content, BoundingBox $boundingBox, int $pageNumber, string $fontName = '', float $fontSize = 0.0 | 위치가 지정된 연속 텍스트 런 | — | 던지지 않음 | 폰트 이름과 크기는 최선 노력(블록 내 지배적 폰트)입니다. |
DocumentSegmentation | list<Segment> $segments, DocumentInfo $documentInfo, float $processingTimeMs = 0.0 | 레이아웃 인식 분할 결과 | — | toJson()에서만 JsonException | segmentCount(), ofType(), onPage(), contentSegments(), fromArray(). |
Segment | SegmentType $type, string $content, BoundingBox $boundingBox, int $pageNumber, float $confidence = 1.0, list<Segment> $children = [] | 분류된 페이지 영역; 자식은 재귀적으로 중첩됨 | — | 던지지 않음 | isHighConfidence() 임계값은 0.8; descendantCount()는 재귀적입니다. |
SegmentType | 문자열 기반 열거형 | 12개 케이스, heading부터 unknown까지 | — | 던지지 않음 | isContent()와 isStructural()이 케이스를 분할합니다. |
FormData | list<FormField> $fields, DocumentInfo $documentInfo, float $processingTimeMs = 0.0 | 전체 문서 폼 추출 결과 | — | toJson()에서만 JsonException | field(), dataFields(), filledCount(), toKeyValueMap(), fromArray(). |
FormField | string $name, FormFieldType $type, 및 선택적 필드 6개 | 단일 추출 폼 필드 | — | 던지지 않음 | isFilled()는 value !== ''입니다. |
FormFieldType | 문자열 기반 열거형 | 8개 케이스, text부터 button까지 | — | 던지지 않음 | isDataField()는 button과 signature에 대해 false입니다. |
interface InteropResultInterface extends JsonSerializable
public const SCHEMA_VERSION = '1.0';
public function toArray(): array;
public function toJson(int $flags = 0): string;final class SchemaLock
public static function verify(): bool
public static function expectedHash(): string
public static function actualHash(): stringfinal readonly class ExtractedText implements InteropResultInterface
public function __construct( public array $pages, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function page(int $pageNumber): ?ExtractedPage
public function totalBlockCount(): int
public function plainText(): string
public static function fromArray(array $data): selffinal readonly class DocumentSegmentation implements InteropResultInterface
public function __construct( public array $segments, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function ofType(SegmentType $type): array
public function onPage(int $pageNumber): array
public function contentSegments(): array
public static function fromArray(array $data): selffinal readonly class FormData implements InteropResultInterface
public function __construct( public array $fields, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function field(string $name): ?FormField
public function dataFields(): array
public function toKeyValueMap(): array
public static function fromArray(array $data): self동작 계약
섹션 제목: “동작 계약”- 버전 지정 봉투. 모든 최상위 DTO(
ExtractedText,DocumentSegmentation,FormData)는InteropResultInterface를 구현합니다. 그toArray()출력은 항상schema_version('1.0')과type판별자를 담습니다:extracted_text,document_segmentation, 또는form_data. - JSON 인코딩.
toJson()은 호출자의 플래그에JSON_THROW_ON_ERROR를 OR로 결합하여json_encode에 위임합니다.jsonSerialize()는toArray()에 위임하므로json_encode($dto)는 동일한 형태를 생성합니다. - 결정적 직렬화. 키 순서와 형태는 DTO에 의해 고정됩니다.
Segment::toArray()는children이 비어 있으면 그 키를 생략하고,FormField::toArray()는bounding_box가null이면 그것을 생략합니다. 소비자는 두 키를 모두 선택적으로 취급해야 합니다. - 왕복. 각 DTO는 디코딩된 JSON 객체를 받는 정적
fromArray()를 노출합니다. 필드는 이 프로세스 간 경계에서 타입 가드됩니다: 없거나 타입이 잘못된 값은 던지는 대신 문서화된 기본값으로 대체됩니다. - 열거형 대체. 인식되지 않는
type문자열은Segment::fromArray()에서SegmentType::Unknown으로,FormField::fromArray()에서FormFieldType::Text로 매핑됩니다. - 좌표.
BoundingBox좌표는 PDF 사용자 공간 단위(포인트, 1/72인치)이며 원점은 페이지의 왼쪽 아래 모서리입니다. 페이지 번호는 전체적으로 1부터 시작합니다. - 일반 텍스트 연결.
ExtractedPage::plainText()는 블록 내용을 단일 공백으로 연결합니다.ExtractedText::plainText()는 페이지를 빈 줄("\n\n")로 연결합니다. - 분할 쿼리.
ofType(),onPage(),contentSegments()는 최상위 세그먼트만 필터링하고 재색인된 리스트를 반환합니다.contentSegments()는SegmentType::isContent()가true인 타입을 선택합니다:heading,sub_heading,paragraph,table,list,code. - 폼 쿼리.
FormData::dataFields()와toKeyValueMap()은 비데이터 필드 타입(button,signature)을 제외합니다.filledCount()는 값이 비어 있지 않은 문자열인 필드를 셉니다. - 스키마 잠금.
SchemaLock::verify()는 패키지와 함께 제공되는 V1schema.json을 읽고, CRLF를 LF로 정규화하고, SHA-256으로 해시한 뒤, 잠긴 상수와 상수 시간으로 비교합니다. CI는 이를 사용하여 조용한 스키마 드리프트를 차단합니다. 잠금 값은 의도적인 버전 지정 스키마 변경이 있을 때만 바뀝니다. - 버전 정책. V1 표면은 명시적인 공개 계약입니다. 추가 변경은 스키마 버전을 올리고, 호환성을 깨는 변경은 새로운 메이저 버전을 요구합니다.
엣지 케이스 및 실패 모드
섹션 제목: “엣지 케이스 및 실패 모드”- 이 표면에서 유일하게 던지는 멤버는
toJson()입니다: 배열이 인코딩 불가능할 때, 예를 들어 추출된 내용에 잘못된 UTF-8이 있을 때JsonException을 던집니다. SchemaLock::verify()는 스키마 파일이 없거나, 읽을 수 없거나, 수정되면false를 반환하며 절대 던지지 않습니다. 드리프트와 I/O 실패를 구분하려면expectedHash()와actualHash()를 비교하세요.fromArray()대체는 설계상 조용합니다. 타입이 잘못된page_number는1이 되고, 타입이 잘못된confidence는 기본값이 됩니다. 조작된 기본값이 용납되지 않는 경우 상류에서 검증하세요.- 숫자 문자열 강제 변환은 비대칭입니다.
PageInfo::fromArray()는 int 및 float 필드에 대해 숫자 문자열을 받아들이지만,Segment와TextBlock은confidence와font_size에 대해 int 또는 float만 받아들입니다. BoundingBox::fromArray()는 문서화된 배열 형태에 따라 네 개의 키를 모두 요구합니다. 이를 내장하는 DTO는 래퍼 키가 없으면 0 박스(또는FormField의 경우null)로 대체합니다.ExtractedPage::fromArray()는 키가 없거나 타입이 잘못되면 595 × 842 포인트의 페이지 1로 된 대체page_info로 대체합니다.FormField::fromArray()는required와read_only에 대해 엄격한 불리언만 받아들입니다. 참으로 평가되는 문자열과 정수는false로 매핑됩니다.Segment자식은 깊이 제한 없이 재귀합니다. 극도로 깊은 중첩은 PHP의 메모리와 스택 한계에 의해서만 제한됩니다.- 이 모듈에서는 어떠한 암호화 키나 서명 연산도 발생하지 않습니다.
SchemaLock은 SHA-256을 오로지 파일 무결성 체크섬으로만 사용하므로 FIPS 모드 특유의 동작은 없습니다.
적합성
섹션 제목: “적합성”Interop V1은 NextPDF가 소유한 버전 지정 와이어 계약입니다. 외부 표준을 구현하지 않으므로 규범 인용 표는 없습니다. BoundingBox 의미론은 생산하는 Core 하위 시스템이 사용하는 PDF 사용자 공간 좌표 모델과 정렬됩니다. 이는 구조적 정렬 진술이지 적합성 테스트 결과가 아닙니다. NextPDF는 어떠한 인증도 보유하지 않으며 부여하지도 않습니다.
개발 노트
섹션 제목: “개발 노트”- 소비자에서
schema_version으로 분기하세요. 추가 키는 호환 가능한 것으로 취급하고, 알 수 없는 메이저 버전은 명시적으로 거부하세요. - CI에서
SchemaLock::verify()를 실행하세요. 실패 시expectedHash()와actualHash()를 로깅하고, 제자리 편집이 아닌 의도적인 버전 지정 스키마 변경을 요구하세요. - 프로세스 간 왕복의 경우 연관 배열(
json_decode($json, true))로 디코딩하고 그 결과를 대응하는fromArray()에 전달하세요. - 모든 DTO는
final이며readonly입니다. 컴포지션으로 확장하고, 공개 필드에서 새로운 뷰를 파생하세요. toKeyValueMap()은 데이터를 담는 필드만 평탄화합니다.signature필드의 존재가 중요할 때는FormData::$fields에서 직접 읽으세요.- 재사용은 안전합니다: DTO는 가변 상태나 리소스를 보유하지 않으므로 캐시되고, 요청 간 공유되고, 반복적으로 직렬화될 수 있습니다.
발행 경계
섹션 제목: “발행 경계”이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만을 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 티켓 접두사는 범위 밖입니다.