Artisan 패키지는 서로 연결된 두 가지 책임을 가집니다. Chrome을 통해 HTML을 렌더링하고, 그 결과로 생성된 PDF 페이지를 NextPDF 문서로 가져옵니다. 디버깅할 때는 Chrome, 파서, 임포터 경계를 각각 분리해서 다루십시오.
이 가이드는 nextpdf/artisan을 기반으로 렌더러 통합, 장기 실행 워커, 파서 진단 또는 테스트를 작성할 때 사용하십시오.
| 계층 | 소유 주체 | 책임 | 여기에 두지 말아야 할 것 |
|---|
| 애플리케이션 | 애플리케이션 | HTML 생성을 승인하고 렌더러 구성을 선택합니다. | 브라우저 프로세스 관리. |
| HTML 정책 | 애플리케이션 및 패키지 | 렌더링 전에 안전하지 않거나 크기가 과도한 HTML을 거부합니다. | 테넌트 승인 또는 비즈니스 결정. |
| Chrome 렌더러 | nextpdf/artisan | Chrome을 사용해 HTML을 독립 실행형 PDF로 렌더링합니다. | 일반적인 PDF 복구 또는 임의의 PDF 편집. |
| 파서/임포터 | nextpdf/artisan | 렌더링된 PDF를 파싱하고 한 페이지를 form XObject로 가져옵니다. | 전체 PDF 적합성 검증. |
| 코어 엔진 | nextpdf/nextpdf | 가져온 form 객체를 배치하고 최종 문서를 작성합니다. | Chrome CDP 수명 주기. |
| 단계 | 동작 | 개발자 조치 |
|---|
| 구성 생성 | ChromeRendererConfig는 바이너리, 타임아웃, CSS, 입력 크기, 샌드박스 동작을 정의합니다. | 하드코딩된 런타임 가정 대신 환경별 구성을 사용하십시오. |
| 렌더러 생성 | ChromeHtmlRenderer는 BrowserPool을 소유합니다. | 워커 내부에서 렌더러를 재사용하고, 종료 시 닫으십시오. |
| HTML 검증 | 보안 정책이 크기를 확인하고 문서를 기본 CSS로 래핑합니다. | 이 단계 전에 호출자 권한을 검증하십시오. |
| Chrome 인쇄 | CDP가 독립 실행형 PDF를 렌더링합니다. | 검토된 정책으로 허용한 경우가 아니면 외부 리소스를 차단 상태로 유지하십시오. |
| PDF 파싱 | PdfReader::parse()는 xref 데이터, 페이지, 객체, 리소스, 리비전을 읽습니다. | 진단이 목적이 아닌 한 파서 실패를 렌더링 실패로 처리하십시오. |
| 페이지 가져오기 | PageImporter::import()는 페이지 콘텐츠, 미디어 박스, 리소스, 임베디드 객체를 추출합니다. | 워크플로가 의도적으로 다른 페이지를 선택하지 않는 한 페이지 0을 가져오십시오. |
| 경로 | 용도 |
|---|
app/Pdf/Renderers/* | ChromeHtmlRenderer를 감싸는 애플리케이션 래퍼. |
app/Pdf/Templates/* | HTML 템플릿 렌더링 및 DTO-뷰 매핑. |
app/Pdf/Policies/* | HTML 크기, 리소스, 테넌트 렌더링 정책. |
tests/Pdf/Renderer/* | 작은 HTML 픽스처를 사용하는 렌더러 스모크 테스트. |
tests/Pdf/Parser/* | 가져온 Chrome 출력용 파서 픽스처. |
템플릿 렌더링은 브라우저 렌더링과 분리해 두십시오. 렌더러는 최종 HTML과 알려진 페이지 너비를 받아야 합니다.
use NextPDF\Artisan\ChromeHtmlRenderer;
use NextPDF\Artisan\ChromeRendererConfig;
use NextPDF\Artisan\PageImporter;
use NextPDF\Parser\PdfReader;
$renderer = new ChromeHtmlRenderer(new ChromeRendererConfig(
$result = $renderer->render($html, widthPt: 595.28);
$reader = new PdfReader($result->getPdfData());
$form = (new PageImporter())->import($reader);
워커 프로세스마다 또는 요청 범위마다 렌더러를 하나씩 생성하십시오. 렌더러를 재사용하면 Chrome을 반복해서 시작하는 비용을 피할 수 있습니다. 렌더러를 명시적으로 닫으면 워커 종료 중 프로세스 누수를 방지할 수 있습니다.
final class InvoiceChromeRenderer
public function __construct(
private readonly ChromeHtmlRenderer $renderer,
public function renderInvoice(string $html): string
->render($html, widthPt: 595.28)
public function close(): void
$this->renderer->close();
파서 API는 Chrome 출력 가져오기가 실패할 때 유용합니다. 진단은 읽기 전용으로 유지하고, 가져오기에 성공한 뒤에는 파서 상태를 변경하지 마십시오.
| 진단 질문 | 사용할 API | 예상 신호 |
|---|
| 파일이 파싱됩니까? | PdfReader::parse() | 유효하지 않은 PDF 구조이면 예외를 발생시킵니다. |
페이지 0이 존재합니까? | PdfReader::getPage(0) | 반환값은 PdfObject입니다. |
| 콘텐츠가 있습니까? | PdfReader::getPageContentStream($page) | 비어 있지 않은 콘텐츠 스트림. |
| 리소스가 있습니까? | PdfReader::getPageResources($page) | 리소스 딕셔너리 배열. |
| 증분 리비전이 있습니까? | PdfReader::getRevisionCount() | 개수가 1보다 큽니다. |
| 어떤 객체가 실패했습니까? | PdfTokenizer::getOffset() 및 파서 예외 컨텍스트. | 픽스처 축소를 위한 바이트 오프셋. |
| 확장 지점 | 사용 용도 | 제약 조건 |
|---|
ChromeRendererConfig::fromArray() | 프레임워크 구성 매핑. | 알 수 없거나 잘못 입력된 선택적 값은 기본값으로 대체됩니다. |
HtmlSecurityPolicyInterface | 파싱 계층의 HTML 정책. | 전송, 프로세스, 권한 제어를 대체하지 않습니다. |
LoggerInterface | 렌더링 및 브라우저 진단. | 기본적으로 HTML 콘텐츠를 로깅하지 마십시오. |
BrowserPool | 장기 실행 Chrome 프로세스 재사용. | 워커 종료 시 닫아야 합니다. |
PageImporter | 파싱된 외부 페이지 임베딩. | 리더를 먼저 파싱해야 합니다. |
| 파서 클래스 | 진단 및 가져온 Chrome 출력 처리. | 일반적인 PDF 복구 툴킷이 아닙니다. |
- 최소 렌더링 테스트로 HTML 조각을 재현하십시오.
- 다음을 검증하십시오:
maxHtmlSize, 기본 CSS, Chrome 바이너리 경로.
- 포인트 단위의 고정 너비로 렌더링하십시오.
- 반환된 PDF 바이트를
PdfReader::parse()로 파싱하십시오.
- 워크플로가 의도적으로 다른 페이지를 선택하지 않는 한 페이지
0을 가져오십시오.
- 각 실패를 재현하는 가장 작은 HTML용 픽스처 테스트를 추가하십시오.
- 워커 종료 후크에서 렌더러를 닫으십시오.
| 실패 | 처리되어야 할 위치 | 권장 대응 |
|---|
| Chrome 바이너리 누락 | 배포 점검 및 렌더러 생성 경로. | 렌더링 트래픽을 수락하기 전에 준비 상태 검사에서 실패하게 하십시오. |
| 크기 초과 HTML | HTML 정책. | Chrome을 시작하기 전에 거부하십시오. |
| 브라우저 타임아웃 | 렌더러 경계. | 렌더링을 실패로 처리하고 템플릿 이름, 크기, 너비, 타임아웃을 기록하십시오. |
| 파서 실패 | 가져오기 경계. | 정책이 허용하는 경우 디버깅을 위해 작고 정제된 픽스처를 저장하십시오. |
| 브라우저 프로세스 누수 | 워커 수명 주기. | 종료 시 닫고 제어된 렌더링 횟수 후에 다시 시작하십시오. |
| 관심사 | 기본값 | 재정의 시점 |
|---|
| 렌더링 타임아웃 | 30초. | 측정 가능하고 범위가 제한된 문서에 대해서만 늘리십시오. |
| 최대 HTML 크기 | 5,000,000바이트. | 공개 엔드포인트의 경우 낮추십시오. |
| 샌드박스 | 활성화됨. | 컨테이너 제약 조건이 요구하고 호스트가 격리된 경우에만 비활성화하십시오. |
| 높이 | 값이 heightPt <= 0일 때 자동. | 엄격한 레이아웃 계약에는 고정 높이를 사용하십시오. |
| 외부 리소스 | 렌더러 정책으로 차단됨. | 검토된 리소스 정책을 통해서만 허용하십시오. |
- 렌더링 테스트가 대표적인 HTML과 CSS를 다룹니다.
- 보안 테스트가 크기 초과 HTML과 차단된 리소스 시도를 다룹니다.
- 가져오기 테스트는 반환된 form 객체에 콘텐츠, 미디어 박스, 리소스가 있는지 확인합니다.
- 파서 테스트가 xref 테이블, xref 스트림, 객체 스트림, 잘못된 형식의 픽스처 사례를 다룹니다.
- 워커 테스트는
close()를 호출하고 남아 있는 브라우저 프로세스가 없는지 확인합니다.
- 성능 테스트는 템플릿 및 콘텐츠 크기별로 렌더링 시간을 기록합니다.