계약 / 관측 가능성
한눈에 보기
섹션 제목: “한눈에 보기”관측 가능성 도메인에는 엔진의 런타임 상태를 노출하는 계약이 포함됩니다. 여기에는 구조화된 오류 컨텍스트를 위한 ContextAwareExceptionInterface, 선택적 가속 사이드카를 위한 SpectrumInterface, 작업 진행 상황을 스트리밍하기 위한 JobNotificationInterface, 기능 손실 시 동작을 정의하는 DegradationPolicy 열거형이 포함됩니다.
composer require nextpdf/core:^3개념 개요
섹션 제목: “개념 개요”ContextAwareExceptionInterface는 진단용 계약입니다. 모든 NextPDF 도메인 예외는 이 계약을 구현합니다. 포착한 NextPDF 예외를 이 인터페이스로 캐스팅하면 애플리케이션 성능 모니터링(APM) 도구, 로깅 파이프라인 또는 오류 리포터에 전달할 구조화된 컨텍스트를 얻을 수 있습니다. 컨텍스트는 snake_case 키와 기본형 값만 포함하는 연관 배열입니다. 중첩 객체는 포함하지 않습니다. 따라서 예기치 않은 부작용 없이 JSON 또는 APM 페이로드로 직렬화됩니다. 덕분에 진단 데이터를 복구하려고 예외 메시지를 파싱할 필요가 없습니다. 3.1.0 부터 stable 상태입니다.
SpectrumInterface는 선택적 가속 사이드카를 위한 계약입니다. Spectrum은 하드웨어 감지, PDF 파싱, 이미지 압축을 로컬 사이드카 프로세스로 오프로드하는 CPU 병렬 엔진입니다. 이 계약은 서킷 브레이커를 거쳐 가용성을 보고하므로, 사이드카가 중단되어도 잦은 상태 점검이 장애를 연쇄적으로 확산시키지 않습니다. 캐시된 결과로 하드웨어 기능을 탐지하고, 활성 리소스 예산을 노출하며, 상위 수준 모듈에 범용 요청 전송 기능을 제공합니다. 엔진은 사이드카 없이도 동작합니다. 이 계약은 가속을 강한 의존성이 아니라 주입 가능한 옵션으로 만들기 위해 존재합니다. JobNotificationInterface는 사이드카의 서버 전송 이벤트(SSE) 엔드포인트에서 타입이 지정된 작업 이벤트를 제너레이터로 스트리밍합니다. 제너레이터는 종료 이벤트가 도착하거나 스트림이 닫히면 종료됩니다.
DegradationPolicy는 기능 손실 시 동작을 정의하는 열거형입니다. 기능이 저하되면 정책은 영향도를 고려해 예외를 던질지, 경고할지, 아니면 조용히 수집할지를 결정합니다. Strict는 영향이 규정 준수 위험, 의미 손실 또는 차단에 해당할 때 예외를 던집니다. 출력 정확성이 필수인 규제 환경에 적합한 선택입니다. 기본값인 Balanced는 제한적인 저하에 대해 구조화된 경고를 발생시키고 계속 진행하며, 차단 영향이 있을 때만 예외를 던집니다. 대부분의 프로덕션 배포에 적합한 선택입니다. Permissive는 모든 이벤트를 조용히 수집하며 예외를 절대 던지지 않습니다. 최선의 노력 수준 출력이 허용되는 미리 보기 또는 초안 모드에 적합한 선택입니다. SpectrumInterface, JobNotificationInterface, DegradationPolicy 타입은 experimental 상태입니다. 이들의 호환성 보장은 ContextAwareExceptionInterface보다 약합니다.
API 표면
섹션 제목: “API 표면”| 타입 | 종류 | 주요 멤버 | 안정성 | 도입 버전 |
|---|---|---|---|---|
ContextAwareExceptionInterface | interface | getContext(): array<string, mixed> | stable | 3.1.0 |
SpectrumInterface | interface | isAvailable(), probe(), getBudget(), request() | experimental | 2.1.0 |
JobNotificationInterface | interface | streamEvents(string): Generator<int, JobEvent> | experimental | 2.2.0 |
DegradationPolicy | enum (string) | Strict, Balanced, Permissive | experimental | 2.3.0 |
getContext()는 기본형 또는 기본형 리스트만 반환합니다. streamEvents()는 종료 이벤트가 나올 때까지 JobEvent 객체를 산출합니다. SpectrumInterface::request()는 원시 응답 본문을 string으로 반환합니다. probe()는 HardwareReport를 반환하고, getBudget()는 SpectrumBudget를 반환합니다.
코드 예제 — 빠른 시작
섹션 제목: “코드 예제 — 빠른 시작”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\ContextAwareExceptionInterface;use Psr\Log\LoggerInterface;
/** * Log a NextPDF exception with its structured context. * * @param \Throwable $e A caught exception. * @param LoggerInterface $logger A PSR-3 logger. */function logWithContext(\Throwable $e, LoggerInterface $logger): void{ if ($e instanceof ContextAwareExceptionInterface) { $logger->error($e->getMessage(), $e->getContext());
return; }
$logger->error($e->getMessage());}구조화된 컨텍스트는 메시지를 파싱하지 않고도 로그 레코드로 전달됩니다.
코드 예제 — 프로덕션
섹션 제목: “코드 예제 — 프로덕션”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\DegradationPolicy;use NextPDF\Contracts\SpectrumInterface;use Psr\Log\LoggerInterface;
final readonly class AcceleratedParseService{ public function __construct( private ?SpectrumInterface $spectrum, private DegradationPolicy $policy, private LoggerInterface $logger, ) {}
/** * Send a parse batch to the sidecar when healthy, otherwise fall back. * * @param list<array{id: string, data: string}> $documents PDF binaries with caller IDs. * * @return string Raw sidecar response body; decode with a batch-result parser. */ public function parse(array $documents): string { if ($this->spectrum?->isAvailable() === true) { return $this->spectrum->request( 'POST', '/v1/parse', json: ['documents' => $documents], scope: ['parse'], ); }
if ($this->policy === DegradationPolicy::Strict) { throw new \RuntimeException('Accelerator required under strict policy.'); }
$this->logger->info('Accelerator unavailable; using PHP fallback.');
return $this->phpFallback($documents); }
/** @param list<array{id: string, data: string}> $documents @return string */ private function phpFallback(array $documents): string { // Pure-PHP parse path omitted for brevity. return ''; }}null 허용 SpectrumInterface는 가속을 선택 사항으로 만듭니다. 이 계약은 전송 메서드 request() 하나를 노출하며, 이 메서드는 원시 응답 본문을 string으로 반환합니다. 상위 수준 파서는 그 본문을 NextPDF\Accelerator\BatchResult로 변환합니다. 구체 클래스 SpectrumClient는 parseBatch()와 같이 타입이 지정된 헬퍼를 추가하며, 이러한 헬퍼는 request()를 감싸고 BatchResult를 직접 반환합니다. 이러한 헬퍼는 고정된 계약의 일부가 아닙니다. 성능 저하 정책은 사이드카 부재가 치명적인지 여부를 결정합니다.
엣지 케이스 및 주의 사항
섹션 제목: “엣지 케이스 및 주의 사항”- 모든
\Throwable이 NextPDF 예외인 것은 아닙니다. 항상instanceof ContextAwareExceptionInterface로 확인한 뒤getContext()를 호출해야 합니다. - 계약상
getContext()는 기본형만 반환합니다. 중첩 객체를 기대하는 소비자는 잘못된 가정에 의존하는 것입니다. 이 계약은 JSON에 안전한 값을 보장합니다. SpectrumInterface::isAvailable()는 서킷 브레이커 뒤에 있으므로 자주 호출해도 안전하지만,true결과는 특정 시점의 확인일 뿐입니다. 확인과 호출 사이에 사이드카 연결이 끊기는 경우를 처리해야 합니다.JobNotificationInterface::streamEvents()는 제너레이터입니다. 두 번 반복해도 이벤트가 다시 재생되지 않습니다. 한 번만 소비해야 합니다.DegradationPolicy::Permissive는 예외를 절대 던지지 않습니다. 해당 모드에서는 규정 준수에 영향을 주는 저하가 조용히 지나갑니다. 규제 대상 출력에는 사용하지 않아야 합니다.
관측 가능성 계약은 무시할 수 있을 정도의 비용만 추가합니다. getContext()는 미리 구성된 배열을 반환합니다. isAvailable()는 캐시되고 서킷 브레이커가 적용된 상태 점검 프로브입니다. 이 계약은 구현체가 프로브 결과를 최소 30 초 동안 캐시하도록 요구하므로, 핫 패스가 사이드카를 반복적으로 호출하지 않습니다. streamEvents()는 엔진이 아니라 사이드카의 이벤트 발생 속도에 따라 제한됩니다. 1500 ms 벽시계 시간과 64 MB 최대치라는 performance_budget는 계약 자체가 아니라 계약이 관측하는 기반 작업에 의해 설정됩니다. 재현성 프로파일은 structural입니다. 이벤트 스트림과 예외 컨텍스트에는 타임스탬프가 포함됩니다. 두 번 실행해도 구조는 동일하게 유지되고 해당 필드만 달라집니다.
보안 참고 사항
섹션 제목: “보안 참고 사항”구조화된 예외 컨텍스트에 비밀 정보가 포함되면 데이터 유출 표면이 됩니다. 이 계약은 컨텍스트를 기본형으로 제한하여 우발적인 객체 누출을 줄입니다. 배포 환경은 컨텍스트가 로그 싱크에 도달하기 전에 여전히 민감한 값을 정제해야 합니다. 이는 프로젝트 로깅 정책이 요구하는 안전 텔레메트리 의무입니다. 가속 사이드카는 전송을 통해 접근하는 별도 프로세스입니다. 요청 메서드는 권한 부여를 위한 스코프 클레임도 함께 전달합니다. 배포 환경은 사이드카 경계를 신뢰 경계로 취급해야 합니다. Permissive로 설정된 성능 저하 정책은 보안 관련 기능 손실을 가릴 수 있습니다. 출력 정확성이 통제 항목인 경우에는 Strict를 사용해야 합니다. 예외 컨텍스트, 작업 이벤트, 사이드카 응답은 로깅될 수 있는 데이터로 취급하고 그에 맞게 정제해야 합니다.
적합성
섹션 제목: “적합성”이 페이지는 직접적인 규범적 주장을 하지 않습니다. 관측 가능성 계약은 엔진 상태를 노출하지만, 조항을 인용해야 하는 표준화된 프로토콜을 엔진이 구현하는 것은 아닙니다. 위에서 언급한 안전 텔레메트리 및 로그 정제 의무는 외부 표준이 아니라 프로젝트 내부 로깅 정책에서 비롯됩니다. 관측되는 작업 자체가 표준화된 경우 — 서명, PDF/A 문서 — 해당 적합성은 서명 또는 추출 페이지에 문서화되어 있습니다.
참고 자료
섹션 제목: “참고 자료”- 계약: 41개의 공개 인터페이스(SPI) — SPI 개요 및 안정성 등급.
- 관측 가능성 — 이 계약들이 노출하는 런타임 상태 모듈.
- 가속기 —
SpectrumInterface뒤에 있는 Spectrum 사이드카 클라이언트. - 예외 —
ContextAwareExceptionInterface를 구현하는 예외. - 성능 — 관측 대상 작업이 따르는 예산.