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\PdfReader 및 NextPDF\Artisan\PageImporter의 존재를 확인합니다. 둘 다 오토로더를 통해 해석되면 Chrome 경로를 사용할 수 있습니다. 해석되지 않으면 core는 치명적 오류를 발생시키는 대신 레이아웃 예외를 발생시킵니다. 따라서 “검색”이란 Artisan 클래스가 오토로더에 있는지 여부입니다. Composer가 그 답을 제공하며, 프레임워크 메커니즘은 전혀 관여하지 않습니다.
이는 의도적인 설계입니다. 이 브리지는 프레임워크가 관리하는 서비스가 아니라, core 엔진이 패키지 경계를 넘어 접근하는 기능입니다. 따라서 Artisan은 Laravel, Symfony, CodeIgniter, CLI 스크립트, 큐 워커에서 동일한 방식으로 사용할 수 있으며, 그중 어느 것도 필수 전제가 아닙니다.
부팅 시퀀스
섹션 제목: “부팅 시퀀스”부트스트랩 커널도, 명령 등록도, 지연 프로바이더 단계도 없습니다. 최초의 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에 전달한 값 그 자체입니다.
- 명시적 생성자 인수, 또는
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/