콘텐츠로 이동

Exception: 타입화된 예외 계층 구조

NextPDF가 던지는 모든 예외는 단일 추상 기반 클래스 NextPdfException을 확장하므로, 하나의 catch로 모든 엔진 오류를 처리할 수 있습니다. 각 도메인 예외는 ContextAwareExceptionInterface를 구현하므로, 메시지 문자열을 파싱하지 않고도 로깅 및 APM을 위한 구조화된 진단 필드를 노출합니다.

Terminal window
composer require nextpdf/core:^3

이 계층 구조는 세 계층으로 이루어져 있습니다:

RuntimeException (PHP SPL)
└── NextPdfException (abstract; implements ContextAwareExceptionInterface)
├── InvalidConfigException
├── FontNotFoundException
├── FontParsingException
├── ImageProcessingException
├── SignatureException
├── EncryptionException
├── WriterException
├── PageLayoutException
├── HtmlParsingException
├── CompressionException
├── NotImplementedException
├── … (23 domain exceptions total)
└── Strict\StrictModeViolation (abstract)
├── Strict\IncompatibleRenderingModeException
├── Strict\OracleConformanceFailure
└── Strict\UnregisteredCssDeviation

NextPdfException은 SPL RuntimeException을 확장합니다. RuntimeException을 catch하면 NextPDF 오류도 함께 잡힙니다. NextPdfException을 catch하면 범위가 엔진 오류로 좁혀집니다. 대상별 복구가 필요하면 리프 클래스를 catch하십시오. Strict\ 하위 트리는 적합성 모드 위반을 추상 클래스 StrictModeViolation 아래에 묶으며, 이 클래스 자체는 NextPdfException을 확장합니다.

문자열 코드가 아니라 컨텍스트. NextPDF는 오류를 문자열 오류 코드가 아니라 PHP 타입으로 식별합니다. 예외 클래스에는 NPDF-#### 코드 상수가 없습니다. 대신 ContextAwareExceptionInterface::getContext()는 로그나 APM 페이로드로 안전하게 직렬화할 수 있는 snake_case 기본 필드의 array<string, mixed>를 반환합니다. NextPdfException::getContext()는 기본적으로 []를 반환합니다. 각 도메인 예외는 해당 실패와 관련된 필드로 이를 재정의합니다. 예를 들어 FontNotFoundException::getContext()font_name, search_paths, fallback_attempted를 반환합니다. WriterExceptionoutput_pathwriter_state를 반환합니다. InvalidConfigExceptionconfig_key, given_value, expected_type을 반환합니다. 별도의 안정적인 NEXTPDF_W_* 문자열 식별자는 예외가 아니라 Support 모듈의 비치명적 WarningCode 열거형에 속합니다.

조치 가능성. 각 도메인 예외의 클래스 docblock은 개발자, 인프라 또는 라이브러리 호출자 중 누가 조치할 수 있는지 명시합니다. InvalidConfigException은 개발자 오류입니다(구성을 수정하십시오). FontNotFoundException은 개발자 또는 인프라 오류입니다(경로 또는 파일 권한을 확인하십시오). WriterException은 인프라 오류입니다(디스크, 권한, 출력 스트림). NotImplementedException은 호출자 오류입니다(해당 호출을 제거하거나, 명시된 후속 작업이 반영된 릴리스에 고정하십시오). 여러 예외는 정확한 근본 원인을 드러내는 명명된 생성자(SignatureException::ltvCapabilityMissing(), ::tsaRequired() 등)를 제공하므로, 운영자는 일반적인 메시지 대신 실제 원인을 확인할 수 있습니다.

심볼종류주요 멤버
NextPDF\Contracts\ContextAwareExceptionInterfaceinterfacegetContext(): array<string, mixed>
NextPDF\Exception\NextPdfExceptionabstract class다음을 확장: RuntimeException; getContext() (기본값 [])
NextPDF\Exception\InvalidConfigExceptionfinalgetConfigKey(), getGivenValue(), getExpectedType(), getContext()
NextPDF\Exception\FontNotFoundExceptionfinalgetFontName(), getSearchPaths(), wasFallbackAttempted(), getContext()
NextPDF\Exception\SignatureExceptionfinalgetCertInfo(), getSignatureLevel(), getDetail(), getContext(); 명명된 생성자 ltvCapabilityMissing(), tsaRequired(), httpClientMissing(), …
NextPDF\Exception\WriterExceptionfinalgetOutputPath(), getWriterState(), getContext()
NextPDF\Exception\PageLayoutExceptionfinalgetPageNumber(), getContext()
NextPDF\Exception\NotImplementedExceptionfinal$feature, $followUp
NextPDF\Exception\Strict\StrictModeViolationabstract다음을 확장: NextPdfException
NextPDF\Exception\Strict\IncompatibleRenderingModeExceptionfinal다음을 확장: StrictModeViolation

전체 리프 목록(23): BarcodeEncoderNotFoundException, BarcodeException, CompressionException, ContentStreamBalanceException, CssParserLimitExceededException, CssResolutionBudgetExceededException, EncryptionException, FontNotFoundException, FontParsingException, GraphicsStateBalanceException, HtmlParsingException, ImageProcessingException, InvalidConfigException, LinearizationInvariantException, LinearizationUnimplementedException, MissingShadingResourceException, NotImplementedException, PageLayoutException, PdfRViolationException, SignatureException, TemplateException, UnsupportedAlgorithmException, WriterException.

기반 타입으로 모든 엔진 오류를 catch하십시오.

<?php
declare(strict_types=1);
use NextPDF\Core\Document;
use NextPDF\Exception\NextPdfException;
try {
$doc = Document::createStandalone();
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Hello');
$doc->save('out.pdf');
} catch (NextPdfException $e) {
\error_log($e->getMessage());
}

이 패턴은 examples/15-exception-handling.php에서 실행 가능한 예제로 제공됩니다.

리프 수준에서 복구하고 구조화된 컨텍스트를 로그 파이프라인에 전달하십시오.

<?php
declare(strict_types=1);
use NextPDF\Contracts\ContextAwareExceptionInterface;
use NextPDF\Core\Document;
use NextPDF\Exception\FontNotFoundException;
use NextPDF\Exception\NextPdfException;
use Psr\Log\LoggerInterface;
function render(Document $doc, LoggerInterface $logger): void
{
try {
$doc->setFont('Brand-Sans', '', 12);
$doc->cell(0, 10, 'Invoice');
$doc->save('invoice.pdf');
} catch (FontNotFoundException $e) {
// Targeted recovery: fall back to a built-in font.
$logger->warning($e->getMessage(), $e->getContext());
$doc->setFont('helvetica', '', 12);
$doc->save('invoice.pdf');
} catch (NextPdfException $e) {
// Any other engine error: structured context, then rethrow.
$context = $e instanceof ContextAwareExceptionInterface
? $e->getContext()
: [];
$logger->error($e->getMessage(), $context);
throw $e;
}
}
  • catch 순서가 중요합니다. NextPdfException 앞에 리프 클래스를 나열하십시오. 먼저 오는 catch (NextPdfException)은 모든 하위 클래스를 처리해 버립니다.
  • getContext() 키는 snake_case이고 값은 기본형 또는 기본형 목록입니다. 중첩된 객체가 없으므로 페이로드는 항상 JSON에 안전합니다.
  • 기반 NextPdfException::getContext()[]를 반환합니다. 이를 재정의하지 않는 하위 클래스에는 구조화된 필드가 없습니다. 그러한 경우에는 getMessage()에 의존하십시오.
  • NextPdfException은 추상 클래스이므로 직접 인스턴스화할 수 없습니다. 구체적인 리프를 던지십시오.
  • NotImplementedException은 의도적으로 명확하게 드러납니다. 이는 일시적인 실패가 아니라 의도적으로 구현이 없음을 알립니다. 이를 재시도하지 마십시오.
  • Strict\* 위반은 복구 가능한 런타임 오류가 아니라 적합성 모드 계약 위반을 나타냅니다. 이를 구성 또는 입력 결함으로 처리하십시오.
  • 문자열 오류 코드 상수는 없습니다. 예외 타입으로 매칭하십시오. 기계가 소비해야 하는 경우에는 getContext()를 전달하십시오.

예외 생성은 단일 객체 할당과 메시지 구성을 위한 sprintf로 이루어지며, O(1)입니다. getContext()는 이미 보유한 필드로 구성된 작은 연관 배열을 반환하며, 필드 수에 대해 O(1)입니다. 예외는 핫 패스가 아니라 실패 경로입니다. 이 비용은 실패한 작업 자체에 비하면 무시할 수 있는 수준입니다. 이 참조 페이지의 기본 performance_budgetwall_ms: 1500, peak_mb: 64입니다.

컨텍스트 필드는 문서에서 파생된 세부 정보를 담을 수 있습니다. FontNotFoundException은 파일 시스템 검색 경로를 포함하고, WriterException은 출력 경로를 포함하며, InvalidConfigException은 제공된 값을 포함합니다. 경로와 값이 배포 레이아웃이나 사용자 입력을 드러낼 수 있으므로, 신뢰 수준이 낮은 로그 싱크로 전달하기 전에 컨텍스트 키를 정리하거나 허용 목록으로 제한하십시오. 예외 메시지는 사람이 읽을 수 있도록 작성되며 동일한 세부 정보를 포함할 수 있습니다. 보안에 민감한 컨텍스트에서는 원본 메시지를 최종 사용자에게 노출하지 마십시오. SignatureException은 구체적인 근본 원인(누락된 패키지, 빈 TSA URL)을 의도적으로 메시지에 담으므로, 운영자는 호출 지점을 grep하지 않고도 분류할 수 있습니다. 이 세부 정보는 최종 사용자용이 아니라 운영자용입니다.

이 모듈은 엔진 오류 모델이며 규범적 표준 인용을 포함하지 않습니다. 예를 들어 PdfRViolationException 또는 Strict\OracleConformanceFailure처럼 표준 위반에 대해 발생하는 예외는 여기서가 아니라 위반을 감지하는 모듈에서 해당 조항을 참조합니다.

  • /modules/core/contracts/ContextAwareExceptionInterface 정의
  • /modules/core/observability/getContext()를 APM으로 전달
  • /modules/core/config/InvalidConfigException, NotImplementedException
  • /modules/core/support/DegradedException; WarningCode (NEXTPDF_W_*)
  • /modules/core/event/InvalidConfigException, 발생 위치: addListener()

용어집: 컨텍스트 인식형 예외 · 저하 정책