name: laravel-pdf description: | spatie/laravel-pdf 패키지를 사용하여 PDF를 생성할 때 사용하는 스킬. Blade 뷰 또는 HTML로부터 PDF 생성, 포맷 설정, 저장, 다운로드, 큐를 통한 백그라운드 생성, 테스트까지 다룹니다. Browsershot, Cloudflare, DOMPDF 드라이버를 지원합니다.
이 스킬을 사용하는 상황: - PDF 생성: "PDF 만들어줘", "인보이스 PDF", "견적서 출력" - spatie/laravel-pdf 패키지 관련 작업 - PDF 다운로드 응답, S3 저장, 큐 처리 - PDF 생성 테스트 작성
Laravel PDF (spatie/laravel-pdf)
PDF 생성 기본
Blade 뷰로 PDF 생성
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->save('/some/directory/invoice.pdf');
순수 HTML로 PDF 생성
Pdf::html('<h1>Hello world</h1>')->save('hello.pdf');
컨트롤러에서 PDF 반환
pdf() 헬퍼를 사용합니다. 기본은 브라우저 인라인 표시입니다.
use function Spatie\LaravelPdf\Support\pdf;
class DownloadInvoiceController
{
public function __invoke(Invoice $invoice)
{
return pdf()
->view('pdf.invoice', compact('invoice'))
->name('invoice.pdf');
}
}
강제 다운로드
return pdf()
->view('pdf.invoice', compact('invoice'))
->name('invoice.pdf')
->download();
포맷 설정
용지 크기
use Spatie\LaravelPdf\Enums\Format;
Pdf::view('pdf.invoice', $data)
->format(Format::A4)
->save('invoice.pdf');
가로 방향
Pdf::view('pdf.invoice', $data)
->landscape()
->save('invoice.pdf');
여백 설정
Pdf::view('pdf.invoice', $data)
->margins(top: 15, right: 10, bottom: 15, left: 10, unit: 'mm')
->save('invoice.pdf');
커스텀 용지 크기
Pdf::view('pdf.receipt', $data)
->paperSize(57, 500, 'mm')
->save('receipt.pdf');
헤더 & 푸터
Pdf::view('pdf.invoice', $data)
->headerView('pdf.header', ['company' => $company])
->footerView('pdf.footer')
->save('invoice.pdf');
HTML로 직접 지정하는 방법:
Pdf::view('pdf.invoice', $data)
->headerHtml('<div>Header</div>')
->footerHtml('<div>Footer</div>')
->save('invoice.pdf');
헤더/푸터 Blade 뷰 안에서
@pageNumber(현재 페이지),@totalPages(전체 페이지) 디렉티브를 사용할 수 있습니다. 이미지 삽입 시@inlinedImage($path)디렉티브를 사용하세요.
조건부 포맷
Pdf::view('pdf.invoice', $data)
->format('a4')
->when($invoice->isLandscape(), fn($pdf) => $pdf->landscape())
->save('invoice.pdf');
디스크 저장
Pdf::view('invoice')
->disk('s3')
->save('invoices/invoice.pdf');
Base64 인코딩
$base64 = Pdf::view('pdf.invoice', $data)->base64();
기본값 설정
서비스 프로바이더에서 전역 기본값을 설정합니다:
use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\LaravelPdf\Enums\Format;
Pdf::default()
->format(Format::A4)
->headerView('pdf.header');
드라이버
LARAVEL_PDF_DRIVER 환경변수 또는 config/laravel-pdf.php에서 드라이버를 선택합니다.
| 드라이버 | 특징 | 요구사항 |
|---|---|---|
browsershot |
기본값, Chromium 기반 고품질 | spatie/browsershot + Node.js |
cloudflare |
외부 바이너리 불필요 | Cloudflare 계정 |
dompdf |
순수 PHP, 간단한 PDF에 적합 | dompdf/dompdf |
Browsershot 드라이버
composer require spatie/browsershot
PDF별로 Browsershot 인스턴스를 커스터마이징할 수 있습니다:
use Spatie\Browsershot\Browsershot;
Pdf::view('pdf.invoice', $data)
->withBrowsershot(function (Browsershot $browsershot) {
$browsershot->scale(0.5);
})
->save('invoice.pdf');
Cloudflare 드라이버
Node.js나 Chrome 바이너리 없이 사용 가능합니다.
LARAVEL_PDF_DRIVER=cloudflare
CLOUDFLARE_API_TOKEN=your-api-token
CLOUDFLARE_ACCOUNT_ID=your-account-id
⚠️ Cloudflare 드라이버는
withBrowsershot(),onLambda(), PNG 출력을 지원하지 않습니다.
DOMPDF 드라이버
composer require dompdf/dompdf
LARAVEL_PDF_DRIVER=dompdf
⚠️ DOMPDF는 CSS 2.1과 일부 CSS 3만 지원합니다. Flexbox·Grid 미지원. 헤더/푸터는 매 페이지마다 반복되지 않고 본문 앞뒤에 한 번만 추가됩니다.
withBrowsershot(),onLambda()는 효과가 없습니다.
PDF별 드라이버 지정
Pdf::view('pdf.invoice', $data)
->driver('dompdf')
->save('invoice.pdf');
큐를 통한 백그라운드 생성
Pdf::view('pdf.invoice', $data)
->saveQueued('invoice.pdf')
->then(fn(string $path, ?string $diskName) => Mail::to($user)->send(new InvoiceMail($path)))
->catch(fn(Throwable $e) => Log::error($e->getMessage()));
then콜백은$path(저장 경로)와$diskName(로컬 저장 시null)을 받습니다.
큐 설정
Pdf::view('pdf.invoice', $data)
->saveQueued('invoice.pdf', connection: 'redis', queue: 'pdfs');
// 또는 메서드 체이닝
Pdf::view('pdf.invoice', $data)
->saveQueued('invoice.pdf')
->onQueue('pdfs')
->onConnection('redis')
->delay(now()->addMinutes(5));
S3 디스크와 함께 사용
Pdf::view('pdf.invoice', $data)
->disk('s3')
->saveQueued('invoices/invoice.pdf');
⚠️
saveQueued()는withBrowsershot()과 함께 사용할 수 없습니다.
테스트
Fake 설정
use Spatie\LaravelPdf\Facades\Pdf;
beforeEach(function () {
Pdf::fake();
});
PDF 저장 검증
Pdf::assertSaved(function (PdfBuilder $pdf, string $path) {
return $path === storage_path('invoices/invoice.pdf')
&& str_contains($pdf->html, '$10.00');
});
PDF 응답 반환 검증
Pdf::assertRespondedWithPdf(function (PdfBuilder $pdf) {
return $pdf->isDownload()
&& $pdf->downloadName === 'invoice.pdf';
});
큐 PDF 검증
Pdf::assertQueued('invoice.pdf');
Pdf::assertQueued(fn(PdfBuilder $pdf, string $path) => $path === 'invoice.pdf');
Pdf::assertNotQueued();
간단한 단언
Pdf::assertViewIs('pdf.invoice');
Pdf::assertSee('합계: ₩10,000');
Pdf::assertViewHas('invoice', $invoice);
Pdf::assertSaved(storage_path('invoices/invoice.pdf'));
배경색 렌더링
PDF에서 배경색이 출력되지 않는 경우 아래 CSS를 Blade 뷰에 추가하세요:
<style>
html {
-webkit-print-color-adjust: exact;
}
</style>