콘텐츠로 이동

CodeIgniter 4용 NextPDF

nextpdf/codeigniter는 프레임워크의 Services 계층을 통해 NextPDF PDF 엔진을 CodeIgniter 4 애플리케이션에 연결합니다. 컨트롤러, 작업(job) 또는 명령에서 PDF 문서를 만든 뒤, 네이티브 CodeIgniter HTTP 응답으로 반환합니다.

Terminal window
composer require nextpdf/codeigniter

패키지의 composer.jsonphp >=8.4 <9.0, nextpdf/core ^3.0 || ^5.2codeigniter4/framework ^4.6을 필요로 합니다. 또한 nextpdf/artisan, nextpdf/premiumcodeigniter4/queue를 제안합니다. 전체 요구 사항 표, 선택적 패키지 및 검증 단계는 /integrations/codeigniter/install/에서 확인할 수 있습니다.

NextPDF는 PHP 8.4 PDF 2.0 엔진입니다. 코어 엔진(nextpdf/core)은 프레임워크에 독립적입니다. 이 엔진은 HTTP, 라우팅 또는 의존성 연결에 대해 전혀 알지 못합니다. nextpdf/codeigniter는 이 엔진을 CodeIgniter 4 애플리케이션에 연결하는 어댑터입니다. 어댑터가 있으면 레지스트리, 팩터리 또는 응답 처리를 직접 연결하지 않아도 됩니다.

이 패키지는 CodeIgniter 4 애플리케이션에 네 가지를 추가합니다.

  • Services 클래스(NextPDF\CodeIgniter\Config\Services) — CodeIgniter가 자동으로 검색하며 다음과 같은 명명된 서비스를 노출합니다: fontRegistry, imageRegistry, documentFactory, pdfDocument, pdf, tsaClient, pdfSigner.
  • Pdf 라이브러리(NextPDF\CodeIgniter\Libraries\Pdf) — 고수준 컨트롤러 API입니다. 일회용 문서 하나를 감싸 한 번의 호출로 응답으로 변환합니다.
  • PdfResponse 헬퍼(NextPDF\CodeIgniter\Http\PdfResponse) — 인라인 미리 보기 또는 다운로드를 위한 CodeIgniter DownloadResponse를 생성합니다. 고정된 응답 강화 헤더 집합을 첨부합니다.
  • 두 개의 전역 헬퍼 함수pdf()pdf_document()입니다. 이들은 Composer files 자동 로드 항목과 패키지 Registrar를 통해 등록됩니다.

또한 이 패키지는 문서를 빌드하는 시점에 선택적 NextPDF 확장을 감지합니다. nextpdf/artisan이 설치되고 Chrome 바이너리가 구성되면 문서는 Chrome 렌더러를 갖게 됩니다. NextPDF Pro가 설치되면 PDF/A 출력과 디지털 서명을 동일한 Services 표면을 통해 사용할 수 있습니다. 감지는 조건부로 조용히 이루어집니다. 이 패키지는 존재하지 않는 확장을 절대 요구하지 않습니다.

컨테이너 바인딩이 아닌 Services 클래스를 사용하는 이유

섹션 제목: “컨테이너 바인딩이 아닌 Services 클래스를 사용하는 이유”

CodeIgniter 4는 PSR-11 의존성 주입 컨테이너를 제공하지 않습니다. 대신 Services 로케이터를 사용합니다. Services 로케이터는 프레임워크가 검색하는 정적 팩터리 메서드를 가진 클래스이며, 각 메서드는 공유 인스턴스 또는 새 인스턴스를 반환합니다. PSR-11은 서비스 로케이터 패턴 — 객체가 자체 의존성을 가져올 수 있도록 컨테이너를 객체에 전달하는 것 — 을 명시적으로 권장하지 않습니다(PSR-11 §1.3, 조동사 SHOULD NOT). 이 패키지는 CodeIgniter의 로케이터 규약을 따릅니다. 또한 로케이터 표면을 최소화하고 명시적으로 유지합니다: 모든 서비스는 bool $getShared 매개변수를 가진 명명된 팩터리 메서드이며, 호출자는 컨테이너 핸들이 아니라 구체적인 객체를 받습니다.

이 설계는 CodeIgniter 통합이 Laravel 및 Symfony 통합과 일관되도록 유지합니다. 각 통합은 자체 프레임워크의 관용 방식을 통해 동일한 논리적 서비스를 노출합니다.

진입점유형반환값수명
Services::fontRegistry()서비스FontRegistryInterface공유(웜업 후 잠금)
Services::imageRegistry()서비스ImageRegistry공유(크기 제한된 LRU 캐시)
Services::documentFactory()서비스DocumentFactoryInterface공유(무상태)
Services::pdfDocument(false)서비스NextPDF\Core\Document호출마다 새로 생성
Services::pdf(false)서비스NextPDF\CodeIgniter\Libraries\Pdf호출마다 새로 생성
Services::tsaClient()서비스?TsaClient공유; TSA URL이 없으면 null입니다
Services::pdfSigner(false)서비스?SignerInterface새로 생성; 서명이 비활성화된 경우 null입니다
pdf()헬퍼Pdf호출마다 새로 생성
pdf_document()헬퍼Document호출마다 새로 생성
PdfResponse::inline() / download()정적DownloadResponse호출마다
GeneratePdfJob큐 작업디스패치마다 하나

컨트롤러는 세 줄로 PDF를 반환합니다. Services::pdf()는 새 문서를 감싸는 새 Pdf 라이브러리를 생성합니다. 그런 다음 download()는 CodeIgniter DownloadResponse를 생성합니다.

<?php
declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\HTTP\DownloadResponse;
use NextPDF\CodeIgniter\Config\Services;
final class InvoiceController extends BaseController
{
public function download(int $id): DownloadResponse
{
$pdf = Services::pdf();
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
}
}

전체 실행 가능한 안내는 /integrations/codeigniter/quickstart/에 있습니다. 여기서는 라우팅, 인라인 미리 보기 및 pdf()pdf_document() 헬퍼 변형을 다룹니다.

프로덕션에서는 Services::pdf(false)로 비공유 인스턴스를 요청해야 합니다. 단일 기본 예외 NextPDF\Exception\NextPdfException을 포착해야 합니다. 모든 코어 및 확장 실패가 이를 확장합니다. 오류를 묵살하지 말고 컨텍스트와 함께 실패를 로깅해야 합니다.

try {
$pdf = Services::pdf(false);
$pdf->document()->addPage();
$pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");
} catch (NextPdfException $e) {
$logger->error('pdf.invoice.failed', [
'invoice_id' => $id,
'exception' => $e::class,
'message' => $e->getMessage(),
]);
return $this->response
->setStatusCode(ResponseInterface::HTTP_INTERNAL_SERVER_ERROR)
->setJSON(['error' => 'pdf_generation_failed', 'invoice_id' => $id]);
}

완전한 프로덕션 컨트롤러는 /integrations/codeigniter/production-usage/에 있습니다. 여기서는 관측성 타이밍, 워커에 안전한 수명 및 비동기 생성을 추가합니다.

  • 글꼴 및 이미지 레지스트리는 프로세스 수명 동안 유지되는 싱글턴입니다. 문서는 절대 공유되지 않습니다. pdfDocumentpdf는 호출할 때마다 새 인스턴스를 반환하므로, 한 요청이 다른 요청으로 콘텐츠를 유출할 수 없습니다. Services::pdf(false)pdf()는 모두 새 문서를 감싸는 새 라이브러리를 반환합니다.
  • 이 패키지는 mbstringzlib PHP 확장을 필요로 합니다. 글꼴 레지스트리는 프로세스당 한 번 이 확장들을 검증합니다. 두 확장 중 하나라도 없으면, 글꼴 레지스트리는 누락된 확장의 이름을 명시하는 런타임 오류를 발생시킵니다.
  • 선택적 확장 동작은 동일한 애플리케이션에 무엇이 설치되어 있는지에 따라 달라집니다. nextpdf/core만 존재하는 경우, 서명 및 PDF/A 경로는 null을 반환하거나 건너뜁니다. 이들은 절대 불필요한 오류를 내며 실패하지 않습니다.

이 통합은 엔진 자체를 넘어서는 측정 가능한 오버헤드를 추가하지 않습니다. 글꼴 레지스트리는 한 번 파싱된 후 잠깁니다. 이미지 레지스트리는 imageCacheMb 설정(기본값 50 MB)으로 크기가 제한되는 LRU 캐시입니다. PDF 빌드 비용은 어댑터가 아니라 코어 엔진과 문서 콘텐츠에 의해 결정됩니다. 이 문서 모음의 페이지당 예산은 벽시계 시간 1500 ms / 최대 128 MB입니다. 실제 레시피는 프런트 매터에서 자체 예산을 설정합니다.

PdfResponse는 내보내는 모든 PDF에 고정된 응답 헤더 집합을 첨부합니다: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy: default-src 'none', X-Robots-Tag: noindex, nofollow, Referrer-Policy: no-referrer. 파일 이름은 정리되며, ASCII가 아닌 이름은 RFC 5987 확장 매개변수로 내보내집니다. 큐 작업은 빌더 콜러블을 App\PdfBuilders 네임스페이스로 제한하고, 출력 경로를 WRITEPATH/pdfs/로 한정합니다. 전체 위협 모델은 /integrations/codeigniter/security-and-operations/를 참조합니다.

  • 모듈 검색은 Composer의 PSR-4 자동 로딩에 의존합니다. 네임스페이스 접두사는 기본 디렉터리에 매핑되고, 정규화된 클래스 이름은 파일 경로에 매핑됩니다(PSR-4 §x1.x3).
  • Services 설계는 PSR-11 §1.3에서 논의된 로케이터 관련 지침을 따릅니다.

NextPDF 코어는 Apache-2.0입니다. 디지털 서명, PDF/A 아카이빙 및 Factur-X 전자 송장 임베딩은 NextPDF Pro와 NextPDF Enterprise에서 제공합니다. CodeIgniter 패키지는 해당 서비스 메서드를 노출합니다. 이러한 메서드는 일치하는 Premium 패키지가 동일한 애플리케이션에 설치될 때까지 null을 반환합니다.

  • /integrations/codeigniter/install/ — 패키지를 설치하고 검증합니다.
  • /integrations/codeigniter/quickstart/ — 컨트롤러에서의 첫 PDF입니다.
  • /integrations/codeigniter/configuration/ — 모든 구성 키입니다.
  • /integrations/codeigniter/boot-and-discovery/ — CodeIgniter가 Services 클래스를 찾는 방법입니다.
  • /integrations/codeigniter/integration/ — 연결 참조 및 스모크 테스트입니다.