콘텐츠로 이동

NextPDF Artisan 부팅과 검색

Artisan은 서비스 프로바이더, 번들, 프레임워크 자동 검색 매니페스트가 없는 순수 PSR-4 라이브러리입니다. 클래스가 오토로드 가능해지는 순간 “부팅”됩니다. 여기서 검색은 Composer의 PSR-4 맵만을 의미하며, 그 이상은 아닙니다.

패키지 composer.json은 두 개의 PSR-4 루트를 선언합니다 — NextPDF\Artisan\src/Artisan/NextPDF\Parser\src/Parser/. extra.laravel도, Symfony 번들 클래스도, CodeIgniter 등록기도 없습니다. 부팅 시 스캔하거나 등록하거나 후킹하는 작업은 전혀 없습니다.

통합 지점은 nextpdf/core 쪽에 있습니다. Document는 (HasTextOutput 컨선을 통해) writeHtmlChrome()를 노출하며, 이 메서드는 런타임 class_exists() 검사를 통해 NextPDF\Parser\PdfReaderNextPDF\Artisan\PageImporter의 존재를 확인합니다. 둘 다 오토로더를 통해 해석되면 Chrome 경로를 사용할 수 있습니다. 해석되지 않으면 core는 치명적 오류를 발생시키는 대신 레이아웃 예외를 발생시킵니다. 따라서 “검색”이란 Artisan 클래스가 오토로더에 있는지 여부입니다. Composer가 그 답을 제공하며, 프레임워크 메커니즘은 전혀 관여하지 않습니다.

이는 의도적인 설계입니다. 이 브리지는 프레임워크가 관리하는 서비스가 아니라, core 엔진이 패키지 경계를 넘어 접근하는 기능입니다. 따라서 Artisan은 Laravel, Symfony, CodeIgniter, CLI 스크립트, 큐 워커에서 동일한 방식으로 사용할 수 있으며, 그중 어느 것도 필수 전제가 아닙니다.

no

yes

Composer autoload (PSR-4)

Application constructs Document

Document::setChromeRendererConfig(config)

Document::writeHtmlChrome(html)

class_exists PdfReader

and PageImporter?

core raises layout exception

resolve ChromeHtmlRenderer

render → parse → import Form XObject

Diagram

부트스트랩 커널도, 명령 등록도, 지연 프로바이더 단계도 없습니다. 최초의 writeHtmlChrome() 호출이 전체 수명 주기의 진입점입니다.

Artisan에는 DI 컨테이너가 없으며 바인딩을 등록하지 않습니다. 컴포넌트는 생성자 주입 방식의 일반 객체입니다. ChromeRendererConfig를 만들어 ChromeHtmlRenderer에 전달하고, 선택적으로 PSR-3 로거와 사용자 정의 HtmlSecurityPolicyInterface를 주입합니다. 호스트 컨테이너에서는 ChromeHtmlRenderer를 직접 싱글톤으로 등록하세요 — 예제는 /integrations/artisan/production-usage/를 참조하세요.

일부 NextPDF 기능(Premium 전자 송장 계약)은 일반적으로 프레임워크 컨테이너를 통해 해석됩니다. Artisan은 컨테이너 없는 환경(CLI 도구, 독립 실행 스크립트, 사용자 정의 러너)에서도 실행되므로 EInvoiceServiceFactory를 함께 제공합니다.

메서드반환값반환값이 null인 경우
makeEmbedder()EmbedderInterface (Pro 에디션)Pro 티어가 설치되어 있지 않음
makeValidator()ValidatorInterface (Enterprise 에디션)Enterprise 티어가 설치되어 있지 않음
makeDefaultProfile()ProfileInterface (EN16931, Pro 에디션)Pro 티어가 설치되어 있지 않음
makeSchematronRunner()SchematronRunnerInterface (Enterprise 에디션)Enterprise 티어가 설치되어 있지 않음

각 호출은 새로운 인스턴스를 반환합니다(일회용 의미를 갖습니다 — embed 및 validate 호출은 변경 가능한 XML 파싱 컨텍스트를 소유하므로 상태를 공유해서는 안 됩니다). 이 팩토리는 컨테이너가 없는 드문 경우를 위한 편의 수단일 뿐, 서비스 로케이터가 아닙니다. 권장 패턴은 여전히 생성 시점에 객체를 구성하여 생성자 인수로 전달하는 것입니다. 부재 시 null을 반환하는 동작은 프레임워크 래퍼 패키지를 그대로 따르므로, 동일한 호출 코드가 Premium 유무와 관계없이 실행됩니다. 출처: src/Artisan/EInvoiceServiceFactory.php. 통합 테스트는 tests/Integration/Artisan/EInvoiceServiceFactoryIntegrationTest.php에서 수행됩니다.

구성 파일 캐스케이드는 없습니다. 구성은 ChromeRendererConfig에 전달한 값 그 자체입니다.

  1. 명시적 생성자 인수, 또는
  2. ChromeRendererConfig::fromArray() — 호스트가 제공한 배열에서 생성합니다(스네이크 케이스 키. 설정되지 않은 키는 생성자 기본값으로 대체됩니다. chrome_binary는 비어 있지 않은 문자열일 때만 적용됩니다).

해석된 구성은 렌더러의 수명 동안 변경할 수 없습니다. 모든 키는 /integrations/artisan/configuration/에서 확인하세요.

  • “브리지를 검색할 수 있는가?”class_exists(\NextPDF\Artisan\PageImporter::class)true이면 Composer의 오토로더가 이를 포함하고 있으며, core가 Chrome 경로를 사용합니다.
  • “부팅되었는가?” — 실패할 수 있는 부팅 단계가 없습니다. 누락된 의존성은 첫 writeHtmlChrome() 호출에서 타입이 지정된 예외로 드러나며, /integrations/artisan/troubleshooting/.에 매핑되어 있습니다.
  • 컨테이너 없는 Premium 확인EInvoiceServiceFactory::makeEmbedder() === null은 Pro 티어가 설치되지 않았음을 의미하며, 오픈 소스 렌더링 경로에는 영향이 없습니다.
  • /integrations/artisan/integration/
  • /integrations/artisan/overview/
  • /integrations/artisan/configuration/
  • /integrations/artisan/production-usage/
  • /integrations/artisan/troubleshooting/