import { NextRequest, NextResponse } from 'next/server'; import puppeteer from 'puppeteer'; /** * PDF 생성 API * POST /api/pdf/generate * * Body: { * html: string, * styles: string, * title?: string, * orientation?: 'portrait' | 'landscape', * documentNumber?: string, * createdDate?: string, * showHeaderFooter?: boolean * } * Response: PDF blob */ export async function POST(request: NextRequest) { try { const { html, styles = '', title = '문서', orientation = 'portrait', documentNumber = '', createdDate = '', showHeaderFooter = true, } = await request.json(); if (!html) { return NextResponse.json( { error: 'HTML content is required' }, { status: 400 } ); } // Puppeteer 브라우저 실행 (Docker Alpine에서는 시스템 Chromium 사용) const browser = await puppeteer.launch({ headless: true, executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || undefined, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu', '--disable-software-rasterizer', ], }); const page = await browser.newPage(); // 전체 HTML 문서 구성 (인라인 스타일 포함) const fullHtml = ` ${title}
${html}
`; // 뷰포트 설정 (문서 전체가 보이도록 넓게) await page.setViewport({ width: 1200, height: 1600, deviceScaleFactor: 2, }); // HTML 설정 await page.setContent(fullHtml, { waitUntil: 'networkidle0', }); // 헤더 템플릿 (문서번호, 생성일) const headerTemplate = showHeaderFooter ? `
${documentNumber ? `문서번호: ${documentNumber}` : ''} ${createdDate ? `생성일: ${createdDate}` : ''}
` : ''; // 푸터 템플릿 (라인 + 페이지번호) const footerTemplate = showHeaderFooter ? `
${title} Page /
` : ''; // PDF 생성 (자동 스케일로 A4에 맞춤) const pdfBuffer = await page.pdf({ format: 'A4', landscape: orientation === 'landscape', printBackground: true, preferCSSPageSize: false, scale: 0.75, // 문서를 75%로 축소하여 A4에 맞춤 displayHeaderFooter: showHeaderFooter, headerTemplate: headerTemplate, footerTemplate: footerTemplate, margin: { top: showHeaderFooter ? '20mm' : '10mm', right: '10mm', bottom: showHeaderFooter ? '20mm' : '10mm', left: '10mm', }, }); // 브라우저 종료 await browser.close(); // PDF 응답 return new NextResponse(Buffer.from(pdfBuffer), { status: 200, headers: { 'Content-Type': 'application/pdf', 'Content-Disposition': `attachment; filename="${encodeURIComponent(title)}.pdf"`, }, }); } catch (error) { console.error('PDF 생성 오류:', error); return NextResponse.json( { error: 'PDF 생성 중 오류가 발생했습니다.' }, { status: 500 } ); } }