Skip to content

HTML 렌더러

HtmlRenderer 클래스는 모든 HTML-to-PDF 작업의 주요 진입점입니다. 콘텐츠 로드, 출력 구성 및 PDF 문서 렌더링을 위한 플루언트 API를 제공합니다.

팩토리 메서드

정적 create() 팩토리로 렌더러 인스턴스를 생성합니다.

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

// 기본 구성 (Chrome 자동 감지)
$renderer = HtmlRenderer::create();

// 사용자 정의 Chrome 바이너리 경로
$renderer = HtmlRenderer::create(
    chromePath: '/usr/bin/google-chrome',
);

// 사용자 정의 임시 디렉토리
$renderer = HtmlRenderer::create(
    chromePath: '/usr/bin/chromium',
    tempDir: '/tmp/artisan-render',
);

콘텐츠 로드

문자열에서

loadHtml()로 원시 HTML을 직접 전달합니다. 문자열은 완전한 HTML 문서이거나 조각일 수 있습니다.

php
$renderer->loadHtml('<h1>Hello, World!</h1>');

조각을 전달하면 Artisan이 자동으로 최소한의 <!DOCTYPE html> 문서로 래핑합니다.

로컬 파일에서

loadFile()로 디스크에서 .html 파일을 로드합니다. 파일 내의 스타일시트, 이미지, 스크립트에 대한 상대 경로는 파일의 디렉토리에서 해석됩니다.

php
$renderer->loadFile('/templates/quarterly-report.html');

URL에서

loadUrl()로 실시간 URL을 가져와 렌더링합니다. 페이지는 헤드리스 Chrome 내에서 로드되므로 JavaScript가 실행되고 AJAX 호출이 렌더링 전에 완료됩니다.

php
$renderer->loadUrl('https://reports.example.com/q4-2026');

느린 페이지에서 중단을 방지하기 위해 내비게이션 타임아웃을 설정할 수 있습니다:

php
$renderer->loadUrl('https://example.com/dashboard', timeoutMs: 30000);

출력 메서드

파일로 저장

php
$renderer->save('/output/report.pdf');

문자열로 가져오기

추가 처리(예: 데이터베이스 저장, 이메일 첨부)를 위해 원시 PDF 바이트를 가져옵니다.

php
$pdfContent = $renderer->toString();

// 예: 데이터베이스에 저장
DB::table('documents')->insert([
    'name'    => 'report.pdf',
    'content' => $pdfContent,
]);

브라우저로 전송

적절한 헤더와 함께 PDF를 HTTP 응답으로 직접 스트리밍합니다.

php
// 인라인 표시 (브라우저 PDF 뷰어)
$renderer->output('report.pdf', 'inline');

// 강제 다운로드
$renderer->output('report.pdf', 'download');

전체 예제: 송장

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

$html = <<<'HTML'
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: 'Inter', sans-serif; margin: 20mm; }
        .header { display: flex; justify-content: space-between; align-items: flex-start; }
        .company { font-size: 24px; font-weight: 700; color: #1a237e; }
        .meta { text-align: right; color: #666; font-size: 13px; }
        .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin: 30px 0; }
        .grid section { padding: 15px; background: #f8f9fa; border-radius: 6px; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th { background: #1a237e; color: white; padding: 10px 12px; text-align: left; }
        td { border-bottom: 1px solid #e0e0e0; padding: 10px 12px; }
        tr:nth-child(even) { background: #fafafa; }
        .total { font-weight: 700; font-size: 18px; text-align: right; margin-top: 20px; }
    </style>
</head>
<body>
    <div class="header">
        <div class="company">Acme Corporation</div>
        <div class="meta">
            Invoice #2026-001<br>
            Date: 2026-02-16<br>
            Due: 2026-03-16
        </div>
    </div>
    <div class="grid">
        <section>
            <strong>Bill To</strong><br>
            Jane Smith<br>
            456 Oak Avenue<br>
            Springfield, IL 62704
        </section>
        <section>
            <strong>Ship To</strong><br>
            Jane Smith<br>
            789 Elm Street<br>
            Springfield, IL 62704
        </section>
    </div>
    <table>
        <thead>
            <tr>
                <th>Item</th>
                <th>Qty</th>
                <th>Unit Price</th>
                <th>Amount</th>
            </tr>
        </thead>
        <tbody>
            <tr><td>Web Development</td><td>40 hrs</td><td>$150.00</td><td>$6,000.00</td></tr>
            <tr><td>UI/UX Design</td><td>20 hrs</td><td>$125.00</td><td>$2,500.00</td></tr>
            <tr><td>Annual Hosting</td><td>1</td><td>$1,200.00</td><td>$1,200.00</td></tr>
        </tbody>
    </table>
    <div class="total">Total: $9,700.00</div>
</body>
</html>
HTML;

HtmlRenderer::create()
    ->loadHtml($html)
    ->save('/invoices/2026-001.pdf');

메서드 체이닝

HtmlRenderer의 모든 세터는 $this를 반환하여 플루언트 빌더 패턴을 구현합니다.

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\RenderOptions;
use Yeeefang\TcpdfNext\Artisan\StyleInjector;

HtmlRenderer::create()
    ->loadFile('/templates/report.html')
    ->withOptions(
        RenderOptions::create()
            ->setPageSize('A4')
            ->setLandscape(false)
            ->setMargins(top: 15, right: 10, bottom: 15, left: 10)
            ->setPrintBackground(true)
    )
    ->withStyleInjector(
        StyleInjector::create()
            ->addCss('body { font-size: 12pt; }')
    )
    ->save('/output/styled-report.pdf');

오류 처리

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\Exceptions\RenderException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\ChromeNotFoundException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\TimeoutException;

try {
    HtmlRenderer::create()
        ->loadUrl('https://example.com/slow-report')
        ->save('/output/report.pdf');
} catch (ChromeNotFoundException $e) {
    // Chrome 바이너리를 찾을 수 없음 -- CHROME_PATH 확인
    logger()->error('Chrome not installed: ' . $e->getMessage());
} catch (TimeoutException $e) {
    // 페이지 로드 또는 렌더링 시간이 너무 오래 걸림
    logger()->warning('Render timed out: ' . $e->getMessage());
} catch (RenderException $e) {
    // 기타 렌더링 실패
    logger()->error('Render failed: ' . $e->getMessage());
}

다음 단계

LGPL-3.0-or-later 라이선스로 배포됩니다.