콘텐츠로 이동
getnextpdf.com

서버리스 플랫폼에서 NextPDF 실행하기

네이티브 인프로세스 NextPDF 코어 엔진은 거의 이상적인 서버리스 워크로드입니다. 그것은 프로세스 안에서 실행되는 순수 PHP입니다 — composer require nextpdf/core, 문서를 빌드하고, 바이트를 얻습니다. 생성할 외부 바이너리도, 헤드리스 브라우저도, 계속 살려 둘 데몬도, 사이드카 서비스로의 소켓도 없습니다. PDF를 빌드하는 함수는 콜드 상태로 시작하여, PHP를 실행하고, 바이트를 반환한 다음, 종료합니다. 이는 AWS Lambda(Bref 런타임을 통해), Google Cloud Run, AWS App Runner에 깔끔하게 매핑됩니다.

이 페이지는 그 네이티브 엔진을 이 세 런타임에 배포하는 것과, 그것들이 부과하는 작은 실제 제약 집합을 다룹니다.

  • 런타임 파일시스템은 영속적이지 않습니다: Lambda는 쓰기 가능한 /tmp만 보장하고, 컨테이너 런타임(Cloud Run, App Runner)은 컨테이너 범위의 임시 파일시스템을 가집니다 — 어느 쪽이든 글꼴은 배포 패키지나 이미지 안에 들어가야 하며 PHP에 등록되어야 합니다(엔진은 어떤 글꼴 경로 환경 변수도 읽지 않습니다).
  • 콜드 스타트는 오토로딩과 모든 글꼴 워밍업의 비용을 치르므로, FontRegistry를 호출마다가 아니라 컨테이너마다 한 번 워밍하십시오.
  • 패키지 크기, 메모리, 타임아웃은 사소한 요청이 아니라 빌드에 맞춰 사이징되어야 합니다.

이 페이지는 오직 네이티브 엔진을 위한 것입니다. Chrome 브리지(제안된 nextpdf/artisan 패키지를 통한 writeHtmlChrome)는 다르고 더 무거운 이야기입니다: 그것은 symfony/process를 통해 헤드리스 Chromium으로 셸 아웃하는데, 일반적인 Lambda zip이나 슬림 컨테이너에는 그것이 들어 있지 않습니다. Lambda에서 Chromium을 실행한다는 것은 브라우저와 그 공유 라이브러리를 담은 커스텀 레이어, 훨씬 큰 패키지, 그리고 훨씬 긴 콜드 스타트를 의미합니다 — 여기서는 범위 밖입니다. 순수 엔진은 그 어느 것도 필요로 하지 않습니다.

시작하기 전에 다음 요소가 준비되었는지 확인하십시오.

  • 애플리케이션에 nextpdf/core를 의존성으로 가진, 커밋된 composer.jsoncomposer.lock이 있습니다.
  • 임베드하려는 글꼴 파일이 있고, 그것을 임베드할 라이선스가 있습니다.
  • 대상에 대한 도구 체인이 있습니다 — Lambda용 Bref CLI와 serverless 프레임워크, 또는 Cloud Run / App Runner용 컨테이너 빌드.

네이티브 엔진이 서버리스에 맞는 이유

섹션 제목: “네이티브 엔진이 서버리스에 맞는 이유”

패키지에서 바로 읽어 보면, nextpdf/corephp: >=8.4 <9.0과 작은 PHP 확장 집합 — ext-mbstring, ext-intl, ext-gd, ext-openssl, ext-zlib, ext-curl — 을 요구합니다. 표준 Bref PHP 레이어는 이 모두를 번들합니다. 공식 php:8.4 컨테이너 이미지는 openssl, curl, zlib를 기본 제공하지만, mbstring, gd, intl은 번들되어 있지 않습니다 — 이들은 시스템 의존성을 설치하고 docker-php-ext-install로 확장을 활성화해야 합니다(Docker 배포 가이드 참조). Bref에서는 컴파일할 이질적인 것이 없고, 컨테이너 경로에서는 순수 엔진을 위해 이미지 빌드에서 그 세 가지 확장을 활성화합니다.

적합성을 깔끔하게 만드는 것은 엔진이 하지 않는 일입니다.

  • 코어 경로에 서브프로세스 없음. 문서를 빌드하고 getPdfData()를 호출하는 것은 처음부터 끝까지 인프로세스 PHP입니다. symfony/process 의존성은 선택적 Chrome 브리지를 위해 존재하며, 네이티브 렌더링을 위한 것이 아닙니다 — 네이티브 PDF 생성은 결코 프로세스를 생성하지 않습니다.
  • 영속 상태 없음. 각 호출은 새로운 문서를 빌드하고 바이트를 반환합니다. 따뜻한 컨테이너를 제외하고는 요청 간에 살아남아야 할 것이 없으며, 그것은 글꼴 워밍업(아래)에 활용하되 정확성을 위해서는 결코 의존하지 않습니다.
  • 쓰기 가능한 작업 디렉터리 불필요. 엔진은 PDF를 메모리에 빌드하고 문자열로 반환합니다. 사용자가 save()를 호출할 때만 디스크를 건드립니다. 서버리스에서는 그렇게 하지 않습니다 — 바이트를 반환합니다 — 그러므로 영속 파일시스템의 부재가 빌드 경로를 무는 일이 없습니다.

단 하나의 강한 제약: 영속적으로 쓰기 가능한 파일시스템 없음

섹션 제목: “단 하나의 강한 제약: 영속적으로 쓰기 가능한 파일시스템 없음”

배포 파일시스템은 영속적이지 않지만, 모델은 런타임마다 다릅니다. AWS Lambda는 쓰기 가능한 /tmp만 보장합니다(기본 512 MB, 최대 10 GB까지 구성 가능). 함수 파일시스템의 나머지는 읽기 전용입니다. 컨테이너 런타임(Cloud Run, App Runner)은 /tmp 전용 모델이 아니라 컨테이너 범위의 쓰기 가능한 임시 파일시스템을 가집니다 — 그러나 거기에 쓰인 어떤 것이든 컨테이너가 재활용될 때 사라지므로, 그것은 저장소가 아니라 스크래치 공간입니다. 어느 경우든, 스테이징에는 /tmp나 구성된 볼륨을 선호하고, 애플리케이션 이미지 경로에 대한 쓰기를 영속 저장소로 결코 의존하지 마십시오. 두 가지 결과가 따라옵니다.

영속 출력을 기대하며 save()를 호출하지 마십시오. NextPDF\Core\Documentsave(string $path): voidgetPdfData(): string을 모두 노출합니다. 서버리스에서는 getPdfData()를 사용하고 바이트를 반환하거나 업로드하십시오 — 애플리케이션 디렉터리에 대한 쓰기를 영속 저장소로 취급하지 마십시오. 파일을 스테이징해야 한다면(예를 들어 객체 저장소로 멀티파트 업로드하기 위해), /tmp(또는 구성된 볼륨) 아래에 쓰고 정리하되, 따뜻한 컨테이너에서는 이 스크래치 공간이 호출 간에 지속되고 그 크기 한도에 산입된다는 점을 기억하십시오.

use NextPDF\Core\Document;
// Right for serverless: get the bytes, return or upload them.
$pdf = $document->getPdfData(); // string of PDF bytes, built in memory
// Avoid on serverless: save() writes to disk. On Lambda the application
// directory is read-only; on Cloud Run / App Runner it is writable but
// ephemeral (lost on container recycle). Neither is durable storage.
// $document->save('/var/task/out.pdf'); // not durable — return the bytes instead

런타임에 OS 글꼴을 설치하지 말고, 자동 글꼴 발견에 의존하지 말고, 프로덕션을 위해 글꼴 파일을 번들하십시오. Lambda에서는 읽기 전용 파일시스템이 apt-get install fonts-*를 아예 막습니다. 컨테이너 런타임에서는 모든 런타임 설치가 임시 파일시스템에 떨어지고 다음 재활용에서 사라집니다. 그리고 그것은 어차피 도움이 되지 않을 것인데, 네이티브 엔진은 어떤 OS/fontconfig 글꼴도 읽지 않기 때문입니다 — 그것은 등록한 파일에서만 글꼴을 해석합니다. 따라서 프로덕션에서는 글꼴 파일이 배포 산출물 안에 실려야 합니다. 의도적으로 글꼴 파일을 /tmp나 구성된 볼륨으로 가져온다면, 글꼴 레지스트리에 명시적으로 등록하고 추가되는 콜드 스타트 및 신뢰성 비용을 받아들여야 합니다 — 권장되는 프로덕션 패턴이 아닙니다.

패키지나 이미지에 글꼴 번들링 및 등록

섹션 제목: “패키지나 이미지에 글꼴 번들링 및 등록”

네이티브 엔진은 fontconfig나 OS 설치 글꼴이 아니라 NextPDF\Typography\FontRegistry를 통해 글꼴 파일에서 글꼴을 해석합니다. 서버리스에서는 이것이 타협 불가능합니다: 배포 후 글꼴을 둘 영속 파일시스템이 없으므로, 글꼴은 패키지(Lambda zip 또는 레이어) 안에 또는 이미지(Cloud Run / App Runner) 안에 실립니다.

.ttf / .otf / .ttc 파일을 프로젝트 내 디렉터리 — resources/fonts/가 관례입니다 — 아래에 번들하여 산출물에 포함되도록 하십시오. 그런 다음 그 디렉터리를 PHP에 등록하십시오. 엔진은 어떤 글꼴 경로 환경 변수도 읽지 않습니다: NEXTPDF_FONTS_PATHnextpdf/laravel 패키지의 fonts_path 구성 키의 기본값(env('NEXTPDF_FONTS_PATH', resource_path('fonts')))이며, 오직 그 프레임워크 통합에서만 소비되고 nextpdf/core에서는 소비되지 않습니다. 순수 함수는 번들된 디렉터리로 레지스트리를 구성해야 합니다.

use NextPDF\Typography\FontRegistry;
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
// Register the directory the deployment artifact bundled the fonts into.
// On Lambda/Bref the code root is /var/task; adjust for your runtime.
$registry = new FontRegistry(__DIR__ . '/resources/fonts');
// (equivalently, $registry->addFontDirectory(__DIR__ . '/resources/fonts');)
$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));
$document = $factory->create();

그것이 글꼴에 대한 서버리스의 전부입니다. 파일 명명 규칙, 전체 레지스트리 API, 비영속 파일시스템 처리는 전용 페이지에 있습니다 — 여기서 중복하지 마십시오. 완전한 패턴은 프로덕션에서 네이티브 엔진을 위한 글꼴 프로비저닝을 읽고, 번들한 것과 동일한 디렉터리를 등록하십시오. Docker 배포 가이드는 Cloud Run / App Runner 경우에 대한 동등한 이미지 측 번들링을 다룹니다.

콜드 스타트: 컨테이너마다 한 번 FontRegistry 워밍

섹션 제목: “콜드 스타트: 컨테이너마다 한 번 FontRegistry 워밍”

콜드 스타트는 PHP 부트스트랩, Composer의 최적화된 오토로더, 그리고 첫 빌드가 유발하는 모든 글꼴 파싱의 비용을 치릅니다. 부트스트랩은 피할 수 없지만, 글꼴 작업을 핫 경로 밖으로 옮기고 따뜻한 호출 전반에 재사용할 수 있습니다.

FontRegistryDocumentFactory핸들러 밖에서 한 번 구성하여 컨테이너의 수명 동안 살아 있고 모든 따뜻한 호출에서 재사용되도록 하십시오. 선택적으로 사용할 것을 아는 글꼴 파일로 warmup()을 호출하여 첫 렌더가 아니라 초기화 중에 파싱되도록 한 다음, 레지스트리를 lock()하여 그 파싱된 상태를 동결하고 호출별 변경이 경합하지 못하게 하십시오.

use NextPDF\Typography\FontRegistry;
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
// Container-scoped, built once at cold start (module scope, not per request).
$fontsDir = __DIR__ . '/resources/fonts';
$registry = new FontRegistry($fontsDir);
// Parse the fonts you will actually use now, so the first render does not.
$registry->warmup([
$fontsDir . '/liberation/LiberationSans-Regular.ttf',
$fontsDir . '/liberation/LiberationSans-Bold.ttf',
]);
// Freeze the parsed state for the life of the warm container.
$registry->lock();
$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));
// Each invocation: fresh document from the shared, warm factory.
$handler = static function (array $event) use ($factory): string {
$document = $factory->create();
$document->addPage();
$document->cell(0, 10, 'Hello from serverless', newLine: true);
return $document->getPdfData();
};

warmup()lock() 전에 호출하십시오 — 레지스트리는 일단 잠기면 동결되므로, 그 이후의 워밍업은 구성 오류를 일으킵니다. 워밍업 시 로드에 실패하는 글꼴은 런타임 세부가 아니라 배포 시점 오류로 취급하십시오: 워밍하려는 모든 글꼴 경로가 시작 시 실제로 존재하고 파싱되는지 검증하고, 그렇지 않으면 오타가 난 경로가 나중에 누락된 글리프로 드러나게 두지 말고 배포(또는 헬스 체크)를 실패시키십시오. 워밍업 목록은 일반적인 호출이 필요로 하는 글꼴로 유지하십시오. 거의 쓰지 않는 큰 패밀리를 워밍하는 것은 모든 콜드 스타트를 길게 만들 뿐입니다.

Bref는 게시된 레이어와 serverless.yml 플러그인으로 Lambda용 PHP 런타임을 제공합니다. php-84 런타임은 이미 nextpdf/core가 필요로 하는 확장을 실어 보내므로, 코드와 글꼴을 배포하고 함수를 핸들러에 가리키게 하면 됩니다. 최소한의 serverless.yml:

service: nextpdf-serverless
provider:
name: aws
region: us-east-1
runtime: provided.al2023
plugins:
- ./vendor/bref/bref
functions:
generate:
handler: handler.php
description: Generate a PDF with the native NextPDF engine
runtime: php-84
memorySize: 1024 # size to the build; see "Sizing" below
timeout: 30 # seconds; raise for large documents
# The Lambda filesystem is read-only except /tmp. Fonts ship in the
# package under resources/fonts and are registered in the handler.

핸들러는 따뜻한 컨테이너 범위 팩토리로 문서를 빌드하고 바이트를 반환합니다. HTTP API의 경우, API Gateway가 본문을 바이너리로 취급하도록 application/pdf 콘텐츠 타입과 함께 base64로 인코딩하여 반환하십시오. 호출 또는 큐 트리거의 경우, 바이트를 객체 저장소에 업로드하고 키를 반환하십시오.

handler.php (outline)
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
// --- Cold-start: built once per container, reused across warm invocations. ---
$fontsDir = __DIR__ . '/resources/fonts';
$registry = new FontRegistry($fontsDir);
$registry->warmup([$fontsDir . '/liberation/LiberationSans-Regular.ttf']);
$registry->lock();
$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));
// --- Per-invocation handler. ---
return static function (array $event) use ($factory): array {
$document = $factory->create();
$document->addPage();
$document->cell(0, 10, 'Invoice', newLine: true);
// getPdfData() materializes the whole PDF in memory and returns it.
$bytes = $document->getPdfData();
return [
'statusCode' => 200,
'isBase64Encoded' => true,
'headers' => ['Content-Type' => 'application/pdf'],
'body' => base64_encode($bytes),
];
};

트래픽을 연결하기 전에 패키지가 건강한 환경을 담고 있는지 검증하십시오. nextpdf/corevendor/bin/nextpdf에 설치된 CLI를 실어 보내며, 그 doctor 명령은 엔진이 필요로 하는 정확히 그 확장을 보고합니다. 동일한 런타임 이미지나 레이어에 대해 한 번 실행하여 PHP 8.4와 모든 필수 확장이 존재하는지 확인하십시오.

Cloud Run과 App Runner는 zip된 함수가 아니라 컨테이너를 실행하므로, 빌드는 Bref 패키지가 아니라 NextPDF 애플리케이션 컨테이너화하기의 Docker 이미지입니다. 네이티브 엔진 제약은 동일합니다: 글꼴을 이미지에 번들하고, 번들된 디렉터리를 PHP에 등록하고, 비특권으로 실행하고, 파일시스템을 비영속으로 취급하십시오. Lambda의 /tmp 전용 모델과 달리, Cloud Run / App Runner 컨테이너는 컨테이너 범위의 쓰기 가능한 임시 파일시스템을 가집니다 — 그러나 그것은 매 재활용에서 재설정되므로, 스크래치에는 /tmp(Cloud Run에서는 tmpfs)나 구성된 볼륨을 사용하고 애플리케이션 이미지 경로에 대한 쓰기를 영속 저장소로 결코 의존하지 마십시오.

Lambda와의 차이는 구조적이 아니라 운영적입니다.

  • 컨테이너는 요청 전반에 따뜻하게 유지될 수 있습니다 — 동시성 설정 아래에서, 따라서 위의 컨테이너 범위 FontRegistry/DocumentFactory 워밍업은 다음 호출뿐 아니라 많은 요청에 걸쳐 이득을 냅니다.
  • HTTP로 서빙합니다(호출 이벤트가 아니라 FPM 또는 내장 PHP 서버 SAPI), 따라서 프레임워크의 응답을 통해 바이트를 반환합니다. 큰 문서의 경우, 스트리밍 응답으로 반환하십시오 — 큰 생성 PDF를 HTTP 응답으로 스트리밍하기 참조.
  • 요청 타임아웃과 메모리는 함수별이 아니라 서비스에 설정됩니다(Cloud Run 서비스 타임아웃 / 메모리, App Runner 인스턴스 구성).

그 밖의 모든 것 — 확장 집합, 글꼴 등록, getPdfData() 출력 호출 — 은 Lambda 핸들러와 동일한 코드입니다.

사이징: 패키지, 메모리, 타임아웃

섹션 제목: “사이징: 패키지, 메모리, 타임아웃”
  • 패키지 및 이미지 크기. 산출물은 vendor/(프로덕션 전용 — --no-dev로 설치)와 번들된 글꼴을 운반합니다. 글꼴이 지배합니다: 전체 CJK 패밀리는 수십 메가바이트입니다. 실제로 렌더링하는 글꼴만 실어 Lambda 패키지를 한도 아래로 유지하고 이미지를 작게 유지하십시오. 이는 콜드 스타트도 단축합니다. 번들된 Liberation 패밀리(resources/fonts/liberation/)는 작고 메트릭 호환 Helvetica 치환을 다룹니다.
  • 메모리. getPdfData()전체 문서를 메모리에 빌드하고 하나의 문자열로 반환하므로, 최대 메모리는 대략 완성된 PDF 하나의 크기에 빌드의 작업 집합을 더한 것입니다. 함수/컨테이너 메모리를 평균이 아니라 생성하는 가장 큰 문서에 맞춰 사이징하십시오. Lambda에서는 메모리가 CPU도 스케일하므로, 더 많은 메모리가 종종 더 빠른 빌드와 더 저렴한 실행을 의미합니다 — 밀리초당 요율이 더 높음에도 — 둘 다 측정하십시오. 몇 페이지 문서는 512–1024 MB에서 편안하고, 이미지가 많거나 페이지가 많은 문서는 더 필요합니다.
  • 타임아웃. 전송이 아니라 빌드가 요청 예산을 지배합니다. 함수 타임아웃을 최악의 경우 빌드 시간보다 여유 있게 위로 설정하십시오. 문서가 타임아웃을 위험에 빠뜨릴 만큼 크다면, 생성을 동기 요청을 막는 대신 결과를 객체 저장소에 쓰는 비동기 트리거(큐 기반 Lambda 또는 Cloud Run 작업)로 옮기십시오.
  • /tmp 크기. /tmp 아래에 무언가를 스테이징한다면, 그 크기 한도를 고려하고 그것이 따뜻한 호출 전반에 지속됨을 기억하십시오 — 정리하지 않으면 오래 사는 컨테이너가 그것을 서서히 채웁니다.
  • 앱 디렉터리에 대한 영속 save() 없음. 배포 파일시스템은 영속적이지 않습니다 — Lambda의 앱 디렉터리는 읽기 전용이고(/tmp만 쓰기를 받음), Cloud Run / App Runner 컨테이너 파일시스템은 쓰기 가능하지만 임시적입니다. getPdfData()를 사용하고 바이트를 반환/업로드하십시오. 필요하면 /tmp나 구성된 볼륨 아래에 스테이징하십시오.
  • 자동 글꼴 발견에 의존하지 마십시오. 런타임에 OS 글꼴을 설치하지 말고, 자동 글꼴 발견에 의존하지 말고, 프로덕션을 위해 글꼴 파일을 번들하십시오. 네이티브 엔진은 어떤 OS/fontconfig 글꼴도 읽지 않습니다 — 그것은 등록한 파일만 해석합니다. 의도적으로 글꼴 파일을 /tmp나 구성된 볼륨으로 가져온다면, 글꼴 레지스트리에 명시적으로 등록하고 추가되는 콜드 스타트 및 신뢰성 비용을 받아들여야 합니다. 파일을 번들하고 등록하십시오. 위에 링크된 글꼴 페이지를 참조하십시오.
  • NEXTPDF_FONTS_PATH는 순수 엔진에 아무것도 하지 않습니다. 그것은 nextpdf/laravel 구성 기본값이며, nextpdf/core가 읽는 변수가 아닙니다. 그 변수만 설정하는 순수 Bref 핸들러는 어떤 글꼴도 등록하지 않고 두부(tofu)를 렌더링합니다.
  • Chrome 브리지는 일반 함수에 맞지 않습니다. writeHtmlChrome는 헤드리스 Chromium과 symfony/process 서브프로세스 경로를 필요로 합니다. Chromium을 Lambda에 올리려면 브라우저와 그 라이브러리를 담은 커스텀 레이어, 훨씬 큰 패키지, 긴 콜드 스타트가 필요합니다. 네이티브 엔진과 writeHtml은 그 어느 것도 필요로 하지 않습니다 — 서버리스에서는 그것들을 선호하십시오.
  • 콜드 스타트 비용은 오토로드와 글꼴 파싱입니다. 프로덕션 설치에 --optimize-autoloader를 사용하고 컨테이너마다 레지스트리를 한 번 워밍하십시오. 거의 쓰지 않는 글꼴을 워밍하지 마십시오.
  • API Gateway는 바이너리 처리가 필요합니다. Content-Type: application/pdf와 함께 isBase64Encoded: true를 반환하고, API가 application/pdf를 바이너리 미디어 타입으로 취급하도록 구성하십시오. 그렇지 않으면 클라이언트가 손상된 바이트를 받습니다.
  • 프리미엄과 ionCube은 더 무거운 산출물 고려 사항입니다. ionCube로 인코딩된 NextPDF Pro / Enterprise 빌드는 런타임의 정확한 PHP 빌드에 맞춘 ionCube Loader가 필요하며, 기본 Bref 레이어는 그것을 포함하지 않습니다. 그것은 코어 서버리스 배포의 범위 밖입니다.
  • 개발 의존성을 실어 보내지 마십시오. --no-dev로 설치하여 테스트 및 분석 도구가 함수 패키지나 이미지에 결코 들어가지 않게 하십시오.
  • 빌드하기 전에 입력을 검증하십시오. 요청 입력으로 구동되는 PDF 빌드는 메모리 고갈 벡터입니다. 어떤 빌드 작업이 실행되기 전에 경계에서 범위를 벗어나거나 과대한 입력을 거부하고, 동시성을 제한하여 높은 트래픽이 최대 메모리를 곱해 메모리 부족 실패로 만들지 않게 하십시오.
  • 글꼴과 라이선스를 공개 산출물 밖에 두십시오. 임베드할 라이선스가 있는 글꼴만 번들하고, 프리미엄 라이선스 파일을 공개적으로 푸시되는 이미지나 레이어에 절대 굽지 마십시오 — 대신 환경 값이나 시크릿 관리자를 통해 런타임에 공급하십시오.
  • 최소 권한. 함수/서비스에 필요한 IAM 권한만 부여하고(예를 들어 하나의 출력 버킷에 대한 쓰기 접근), Docker 가이드가 보여 주듯 컨테이너를 비특권으로 실행하십시오.

이 가이드는 규범적 표준 주장을 하지 않습니다. 플랫폼 사실은 nextpdf/core 패키지에서 바로 읽힙니다: php: >=8.4 <9.0 제약과 필수 확장 ext-mbstring, ext-intl, ext-gd, ext-openssl, ext-zlib, ext-curl. 표준 Bref PHP-8.4 런타임 레이어는 여섯 가지를 모두 번들합니다. 공식 php:8.4 이미지는 openssl, curl, zlib를 제공하지만, mbstring, gd, intldocker-php-ext-install로 이미지 빌드에서 설치하고 활성화해야 합니다(Docker 페이지 참조). 출력 호출은 실제 코어 표면 NextPDF\Core\Document::getPdfData(): string입니다(그 디스크 형제는 save(string $path): void). 글꼴은 NextPDF\Typography\FontRegistry를 통해 등록되며 — 그 디렉터리 생성자 인수 / addFontDirectory(), 콜드 스타트 패턴을 위한 warmup(array $fontFiles)lock()NextPDF\Core\DocumentFactory::create()를 통해 연결됩니다. NEXTPDF_FONTS_PATHnextpdf/laravel 패키지의 fonts_path 구성 키(env('NEXTPDF_FONTS_PATH', resource_path('fonts')))이며, nextpdf/core가 읽는 변수가 아닙니다. nextpdf CLI doctor 명령은 패키지에서 "bin": ["bin/nextpdf"]로 선언되고 소비하는 앱에서 vendor/bin/nextpdf에 설치됩니다. Bref 런타임 이름과 AWS Lambda / Cloud Run / App Runner 동작은 그 벤더들이 문서화한 기능입니다.