콘텐츠로 이동

프로덕션에서 compat-legacy 실행하기

이 어댑터는 HTTP 핸들러, 큐 워커, 장기 실행 프로세스에서 안전하게 실행할 수 있습니다. 레거시 TCPDF 6.2.13보다 더 안전한 이유는 프로덕션에서 흔히 문제가 되는 두 가지 위험 요소, 즉 버퍼로 직접 출력하는 동작과 오류 시 die()를 호출하는 동작을 제거했기 때문입니다. 이 페이지에서는 어댑터를 올바르게 운영하는 방법을 설명합니다.

전제 조건: /integrations/tcpdf-compat/migration/에서 엄격 모드 감사를 완료하고, 프로덕션에는 엄격 모드를 상태로 배포합니다.

레거시 TCPDF의 Output()은 활성 출력 버퍼로 직접 출력합니다. 이 동작은 HTTP 프레임워크의 응답을 손상시키고 큐 워커의 동작을 망가뜨릴 수 있습니다. 대신 이 어댑터는 안전한 대상 브리지를 통해 출력을 라우팅합니다.

호출자에 맞는 출력 대상을 사용합니다:

상황대상이유
스토리지에 기록하는 큐 워커Output($path, 'F')파일에 쓰고 빈 문자열을 반환합니다. 버퍼와 상호작용하지 않습니다.
생성 후 attach/uploadOutput($name, 'S')PDF 바이트를 반환하며, 보낼 위치는 사용자가 제어합니다.
이메일 첨부 파일Output($name, 'E')Content-Type: application/pdf를 포함한 base64 MIME 본문을 반환합니다.
직접 제어하는 HTTP 응답Output($name, 'S')바이트를 받은 다음 헤더와 본문을 직접 설정합니다.
examples/production-worker.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;
use NextPDF\Compat\Tcpdf\TCPDF;
/**
* Render an invoice in a queue worker. Returns the storage path.
*
* @throws \RuntimeException on a render failure (Error() throws, not die()).
*/
function renderInvoiceJob(array $invoice, string $storageDir): string
{
$pdf = new TCPDF('P', 'mm', 'A4');
$pdf->SetFont('helvetica', '', 12);
$pdf->AddPage();
$pdf->Cell(0, 10, 'Invoice ' . $invoice['number'], 0, 1);
$path = $storageDir . '/invoice-' . $invoice['number'] . '.pdf';
try {
$pdf->Output($path, 'F'); // writes file, no buffer pollution
} catch (TcpdfNotImplementedException $e) {
// Only reachable if strict mode is on — it must NOT be in production.
throw new \RuntimeException('Adapter strict-mode gap in production: ' . $e->getMessage(), 0, $e);
} catch (\RuntimeException $e) {
// Error() throws RuntimeException instead of die().
throw new \RuntimeException('PDF render failed: ' . $e->getMessage(), 0, $e);
}
return $path;
}

HTTP 핸들러에서는 'S'를 우선 사용하고 헤더를 직접 설정합니다:

examples/production-http.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
$pdf->Cell(0, 10, 'Report');
$bytes = $pdf->Output('report.pdf', 'S');
header('Content-Type: application/pdf');
header('Content-Length: ' . strlen($bytes));
header('Content-Disposition: inline; filename="report.pdf"');
echo $bytes;

Error()RuntimeException을 던지며, die()를 절대 호출하지 않습니다. 이는 레거시 TCPDF에서 운영상 가장 큰 단일 변경 사항입니다.

  • 모든 렌더링 진입점을 try/catch로 감쌉니다.
  • 예외를 애플리케이션의 오류 계약(HTTP 5xx, 작업 실패, 재시도, 데드 레터)에 매핑합니다.
  • 렌더링 실패 시 프로세스가 종료된다고 가정하지 마십시오 — 종료되지 않습니다.

주기적인 엄격 모드 CI 작업(권장)을 실행한다면, 그 과정에서 발생하는 TcpdfNotImplementedException은 실제 발견 사항입니다: 코드 경로가 지원되지 않는 TCPDF 매개변수에 의존하고 있다는 뜻입니다. 이를 불안정한 테스트가 아니라 마이그레이션 작업 항목으로 다루십시오.

  • 문서는 첫 번째 출력 호출 시 PDF 바이트를 지연 생성합니다. Close()는 선택 사항이며, 호출하면 바이트를 캐시합니다. Open()은 안전한 무동작(no-op)으로 처리됩니다.
  • endPage()는 아무 동작도 하지 않습니다 — NextPDF가 페이지 수명 주기를 관리합니다. 핫 루프에서 제거하십시오. 별도의 가치를 더하지 않습니다.
  • 작업 사이에는 PHP가 어댑터를 가비지 컬렉션하도록 두십시오. _destroy()는 어댑터의 캐시된 데이터를 재설정하지만, 일반적인 워커 루프에서는 명시적으로 호출할 필요가 없습니다.
  • 문서마다 새 어댑터를 생성하십시오. 장기 실행 워커에서 서로 관련 없는 문서에 동일한 어댑터 인스턴스를 재사용하지 마십시오. 문서 상태는 인스턴스별로 관리됩니다.
  • 이 어댑터는 얇은 위임 계층입니다. 비용을 좌우하는 것은 어댑터가 아니라 엔진입니다.
  • 레거시 상수는 부팅 시 한 번 정의하십시오. LegacyDefaults::register()LegacyBootstrap::enableAliases()는 모두 멱등하고 가드가 적용되어 있으므로 반복 호출 비용이 낮습니다. 요청마다 상수를 정의하는 것은 낭비입니다.
  • 브라우저가 아닌 환경에서는 'I'/'D'보다 Output(..., 'S') 또는 'F'를 선호하십시오. inline/download 경로는 프레임워크와 무관한 출력을 생성하므로, 워커에서는 보통 원하지 않는 결과입니다.
  • 대량 생성 시에는 어댑터가 아니라 엔진을 프로파일링하십시오. 렌더링에 비하면 어댑터 자체 오버헤드의 페이지당 예산은 작습니다.
  • 각 어댑터 인스턴스는 독립적이며 자체 문서 상태를 보유합니다. 각 작업 단위가 자체 어댑터 인스턴스를 사용한다면, 프로세스 또는 워커 수준의 동시성은 안전합니다.
  • LegacyBootstrapLegacyDefaults의 멱등성 가드는 프로세스 로컬 정적 상태를 사용하며, 일반적인 PHP per-request/per-worker 모델에서는 안전합니다. 이들은 스레드 간에 변경 가능한 상태를 공유하도록 설계되지 않았습니다.
  • 엄격 모드 감사 완료. 프로덕션은 엄격 모드를 끈 상태로 실행됩니다.
  • 모든 렌더링 진입점이 RuntimeException에 대해 try/catch로 감싸져 있음(die()에 의존하지 않음).
  • 워커는 인라인 경로가 아닌 Output(..., 'F') 또는 'S'를 사용함.
  • 레거시 상수가 첫 번째 생성 전에, 부팅 시 한 번 정의됨.
  • 회귀를 잡기 위한 주기적인 엄격 모드 CI 작업이 마련되어 있음.
  • 바이트 수준 테스트 어서션이 다시 기준선에 맞춰짐(/integrations/tcpdf-compat/migration/ 참고).
  • /integrations/tcpdf-compat/security-and-operations/ — 암호화, 서명 태세, 강화
  • /integrations/tcpdf-compat/troubleshooting/ — 프로덕션 실패 패턴과 해결 방법
  • /integrations/tcpdf-compat/configuration/ — 엄격 모드와 상수 위생
  • /integrations/tcpdf-compat/migration/ — 프로덕션에 앞서 반드시 수행해야 하는 감사