PuppeteerSharp에서 IronPDF로의 마이그레이션 방법 (C#)
PuppeteerSharp에서 IronPDF로의 마이그레이션은 Chromium 종속성과 함께 300MB 이상의 브라우저 자동화 도구에서 자동 메모리 관리가 가능한 목적별 PDF 라이브러리로 PDF 생성 워크플로우를 이동시키는 것입니다. 이 가이드는 런타임 Chromium 다운로드를 제거하고, 부하 중 보고된 메모리 증가를 처리하며, 포괄적인 PDF 조작 기능을 추가하는 단계별 마이그레이션 경로를 제공합니다.
PuppeteerSharp에서 IronPDF로 마이그레이션해야 하는 이유
PuppeteerSharp이해하기
PuppeteerSharp는 Google's Puppeteer의 .NET 포트로, C#에 브라우저 자동화 기능을 제공합니다. Chrome의 내장된 PDF로 인쇄 기능을 사용하여 PDF를 생성합니다—브라우저에서 Ctrl+P를 누르는 것과 동일합니다. 이것은 화면에서 보이는 것과 다른 종이 최적화 출력물을 생성합니다.
PuppeteerSharp는 문서 생성을 위한 것이 아닌 웹 테스트와 스크래핑을 위해 설계되었습니다. PuppeteerSharp를 사용하여 PDF를 생성하면 상당한 생산 문제를 야기합니다.
브라우저 자동화 문제
PuppeteerSharp는 문서 생성이 아닌 브라우저 자동화를 위해 설계되었습니다. 따라서 PDF에 사용하는데 근본적인 문제가 발생합니다:
-
300MB 이상의 Chromium 다운로드가 처음 사용 전에 필요합니다. PuppeteerSharp의 중요한 단점은 Chromium 바이너리로 인해 배포 크기가 크다는 것입니다. 이 큰 크기는 Docker 이미지를 늘리고 서버리스 환경에서 콜드 스타트 문제를 일으킬 수 있습니다.
-
부하 중 보고된 메모리 증가로 인해 수동으로 브라우저 재활용이 필요합니다. 지속적인 부하 상태에서PuppeteerSharp사용자는 일반적으로 수동 프로세스 재활용에 의해 해결되는 브라우저 인스턴스 전반에 걸친 메모리 축적을 보고했습니다.
-
브라우저 수명주기 관리를 위한 복잡한 비동기 패턴.
-
PDF로 인쇄 출력 (화면 캡처가 아닌 Ctrl+P와 동등). 레이아웃이 다시 흐르고, 기본적으로 배경이 생략되며, 출력은 브라우저 뷰포트를 일치시키기보다는 인쇄를 위해 페이지화됩니다.
-
PDF/A 또는 PDF/UA 지원 없음 (규정 준수 요구 사항). PuppeteerSharp는 PDF/A(아카이브용) 또는 PDF/UA(접근성) 규격 문서를 생성할 수 없습니다.
- PDF 조작 불가 - 생성만 가능, 병합/분할/편집 불가. PuppeteerSharp는 PDF 생성을 효율적으로 하지만, 병합, 분할, 보안 강화 또는 편집 같은 추가 조작 능력이 없습니다.
PuppeteerSharpvsIronPDF비교
| 측면 | PuppeteerSharp | IronPDF |
|---|---|---|
| 주된 목적 | 브라우저 자동화 | PDF 생성 |
| Chromium 의존성 | 300MB+ 별도 다운로드 | 내장 최적화 엔진 |
| API 복잡성 | 비동기 브라우저/페이지 생명주기 | 동기 단일 행 |
| 초기화 | BrowserFetcher.DownloadAsync() + LaunchAsync |
new ChromePdfRenderer() |
| 메모리 관리 | 수동 브라우저 재활용 | 자동 |
| 로드 하의 메모리 | 무거운 작업량에서 보고된 증가 | 지속적인 실행 동안 안정적 |
| PDF/A 지원 | 사용 불가 | 지원됨 |
| PDF/UA 접근성 | 사용 불가 | 지원됨 |
| PDF 편집 | 사용 불가 | 병합, 분할, 스탬프, 편집 |
| 디지털 서명 | 사용 불가 | 지원됨 |
| 스레드 안전성 | 제한적 (업스트림 가이드에 따라) | 전체 |
| 라이선스 | MIT (오픈 소스) | 상업용 라이선스 |
플랫폼 지원
| 라이브러리 | .NET Framework 4.7.2 | .NET Core 3.1 | .NET 6-8 | .NET 10 |
|---|---|---|---|---|
| IronPDF | 전체 | 전체 | 전체 | 전체 |
| PuppeteerSharp | netstandard2.0을 통해 | 전체 | 전체 | 전체 |
IronPDF의 현대 .NET 대상 지원은 대부분의 기존 애플리케이션에 호환성 마찰 없이 통합할 수 있음을 의미합니다.
시작하기 전에
필수 조건
- .NET 환경: .NET Framework 4.6.2+ 또는 .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet 접근 권한: NuGet 패키지를 설치할 수 있는 능력
- IronPDF 라이선스: ironpdf.com에서 라이선스 키를 획득하세요
NuGet 패키지 변경 사항
# Remove PuppeteerSharp
dotnet remove package PuppeteerSharp
# Remove downloaded Chromium binaries (~300MB recovered)
# Delete the .local-chromium folder
# Add IronPDF
dotnet add package IronPdf
# Remove PuppeteerSharp
dotnet remove package PuppeteerSharp
# Remove downloaded Chromium binaries (~300MB recovered)
# Delete the .local-chromium folder
# Add IronPDF
dotnet add package IronPdf
IronPDF로 BrowserFetcher.DownloadAsync()이(가) 필요하지 않습니다 - 렌더링 엔진이 자동으로 번들로 제공됩니다.
라이선스 구성
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
완전한 API 참조
네임스페이스 변경
// Before: PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
' Before: PuppeteerSharp
Imports PuppeteerSharp
Imports PuppeteerSharp.Media
Imports System.Threading.Tasks
' After: IronPDF
Imports IronPdf
Imports IronPdf.Rendering
핵심 API 매핑
| PuppeteerSharp API | IronPDF API | 노트 |
|---|---|---|
new BrowserFetcher().DownloadAsync() |
필요 없음 | 브라우저 다운로드 없음 |
Puppeteer.LaunchAsync(options) |
필요 없음 | 브라우저 관리 없음 |
browser.NewPageAsync() |
필요 없음 | 페이지 컨텍스트 없음 |
page.GoToAsync(url) |
renderer.RenderUrlAsPdf(url) |
직접 렌더링 |
page.SetContentAsync(html) |
renderer.RenderHtmlAsPdf(html) |
직접 렌더링 |
page.PdfAsync(path) |
pdf.SaveAs(path) |
렌더링 후 |
await page.CloseAsync() |
필요 없음 | 자동 정리 |
await browser.CloseAsync() |
필요 없음 | 자동 정리 |
PdfOptions.Format |
RenderingOptions.PaperSize |
용지 크기 |
PdfOptions.Landscape |
RenderingOptions.PaperOrientation |
방향 |
PdfOptions.MarginOptions |
RenderingOptions.MarginTop/Bottom/Left/Right |
개별 여백 |
PdfOptions.PrintBackground |
RenderingOptions.PrintHtmlBackgrounds |
배경 인쇄 |
PdfOptions.HeaderTemplate |
RenderingOptions.HtmlHeader |
HTML 헤더 |
PdfOptions.FooterTemplate |
RenderingOptions.HtmlFooter |
HTML 푸터 |
page.WaitForSelectorAsync() |
RenderingOptions.WaitFor.HtmlElementId |
요소 대기 |
코드 마이그레이션 예제
예제 1: 기본 HTML을 PDF로 변환
이전 (PuppeteerSharp):
// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
await using var page = await browser.NewPageAsync();
await page.SetContentAsync("<h1>Hello World</h1><p>This is a PDF document.</p>");
await page.PdfAsync("output.pdf");
}
}
// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
await using var page = await browser.NewPageAsync();
await page.SetContentAsync("<h1>Hello World</h1><p>This is a PDF document.</p>");
await page.PdfAsync("output.pdf");
}
}
Imports PuppeteerSharp
Imports System.Threading.Tasks
Module Program
Async Function Main(args As String()) As Task
Dim browserFetcher = New BrowserFetcher()
Await browserFetcher.DownloadAsync()
Using browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
.Headless = True
})
Using page = Await browser.NewPageAsync()
Await page.SetContentAsync("<h1>Hello World</h1><p>This is a PDF document.</p>")
Await page.PdfAsync("output.pdf")
End Using
End Using
End Function
End Module
이후 (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF document.</p>");
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF document.</p>");
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main(args As String())
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF document.</p>")
pdf.SaveAs("output.pdf")
End Sub
End Class
이 예제는 근본적인 아키텍처 차이를 보여줍니다. PuppeteerSharp는 여섯 가지 비동기 작업이 필요합니다: BrowserFetcher.DownloadAsync() (300MB 이상 크기 Chrome 다운로드), Puppeteer.LaunchAsync(), browser.NewPageAsync(), page.SetContentAsync(), 그리고 page.PdfAsync(), 적절한 처리는 await using로 해제되어야 합니다.
IronPDF는 이러한 복잡성을 모두 제거합니다: ChromePdfRenderer을(를) 생성하고 RenderHtmlAsPdf()을 호출한 다음 SaveAs()하세요. 비동기 패턴 없음, 브라우저 수명주기 없음, Chromium 다운로드 없음. IronPDF의 접근법은 현대 .NET 애플리케이션과의 더 나은 통합과 더 나은 문법을 제공합니다. HTML에서 PDF로의 문서에서 포괄적인 예제를 참조하세요.
예제 2: URL에서 PDF로 변환
이전 (PuppeteerSharp):
// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
await using var page = await browser.NewPageAsync();
await page.GoToAsync("https://www.example.com");
await page.PdfAsync("webpage.pdf");
}
}
// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
await using var page = await browser.NewPageAsync();
await page.GoToAsync("https://www.example.com");
await page.PdfAsync("webpage.pdf");
}
}
Imports PuppeteerSharp
Imports System.Threading.Tasks
Module Program
Async Function Main(args As String()) As Task
Dim browserFetcher = New BrowserFetcher()
Await browserFetcher.DownloadAsync()
Using browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
.Headless = True
})
Using page = Await browser.NewPageAsync()
Await page.GoToAsync("https://www.example.com")
Await page.PdfAsync("webpage.pdf")
End Using
End Using
End Function
End Module
이후 (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main(ByVal args As String())
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
PuppeteerSharp는 GoToAsync()을 사용하여 URL로 이동하고 PdfAsync()을 실행합니다. IronPDF는 탐색과 PDF 생성을 하나의 호출에서 처리하는 단일 RenderUrlAsPdf() 메서드를 제공합니다. 더 많은 정보를 보려면 튜토리얼을 참조하세요.
예제 3: 여백을 설정한 사용자 지정 페이지 설정
이전 (PuppeteerSharp):
// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
await using var page = await browser.NewPageAsync();
await page.SetContentAsync("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
await page.PdfAsync("custom.pdf", new PdfOptions
{
Format = PaperFormat.A4,
Landscape = true,
MarginOptions = new MarginOptions
{
Top = "20mm",
Bottom = "20mm",
Left = "20mm",
Right = "20mm"
}
});
}
}
// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
await using var page = await browser.NewPageAsync();
await page.SetContentAsync("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
await page.PdfAsync("custom.pdf", new PdfOptions
{
Format = PaperFormat.A4,
Landscape = true,
MarginOptions = new MarginOptions
{
Top = "20mm",
Bottom = "20mm",
Left = "20mm",
Right = "20mm"
}
});
}
}
Imports PuppeteerSharp
Imports PuppeteerSharp.Media
Imports System.Threading.Tasks
Module Program
Async Function Main(args As String()) As Task
Dim browserFetcher = New BrowserFetcher()
Await browserFetcher.DownloadAsync()
Await Using browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
.Headless = True
})
Await Using page = Await browser.NewPageAsync()
Await page.SetContentAsync("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>")
Await page.PdfAsync("custom.pdf", New PdfOptions With {
.Format = PaperFormat.A4,
.Landscape = True,
.MarginOptions = New MarginOptions With {
.Top = "20mm",
.Bottom = "20mm",
.Left = "20mm",
.Right = "20mm"
}
})
End Using
End Using
End Function
End Module
이후 (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
pdf.SaveAs("custom.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
pdf.SaveAs("custom.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main(args As String())
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
renderer.RenderingOptions.MarginLeft = 20
renderer.RenderingOptions.MarginRight = 20
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>")
pdf.SaveAs("custom.pdf")
End Sub
End Class
이 예제는 두 라이브러리 간의 PDF 옵션 매핑을 보여줍니다. PuppeteerSharp는 PdfOptions을 Format, Landscape, MarginOptions과 함께 사용하며, 이들은 문자열 값 ("20mm")을 포함합니다. IronPDF는 직접적으로 용지 크기 열거형, 방향 열거형, 밀리미터 단위 숫자 여백 값과 함께 RenderingOptions 속성을 사용합니다.
주요 매핑:
Format = PaperFormat.A4→PaperSize = PdfPaperSize.A4Landscape = true→PaperOrientation = PdfPaperOrientation.LandscapeMarginOptions.Top = "20mm"→MarginTop = 20(숫자 밀리미터)
지속적 부하에서의 메모리 증가
사용자들은 PuppeteerSharp를 지속적인 부하 상태에서 사용하면서 메모리 축적을 보고했으며, 일반적으로 수동 브라우저 재활용을 통해 완화되었습니다:
//PuppeteerSharp- memory growth typically requires periodic recycling
for (int i = 0; i < 1000; i++)
{
var page = await browser.NewPageAsync();
await page.SetContentAsync($"<h1>Document {i}</h1>");
await page.PdfAsync($"doc_{i}.pdf");
await page.CloseAsync();
}
// Recommended: await browser.CloseAsync(); and re-launch every N operations
//IronPDF- reuse a single renderer across operations
var renderer = new ChromePdfRenderer();
for (int i = 0; i < 1000; i++)
{
var pdf = renderer.RenderHtmlAsPdf($"<h1>Document {i}</h1>");
pdf.SaveAs($"doc_{i}.pdf");
// Memory managed automatically
}
//PuppeteerSharp- memory growth typically requires periodic recycling
for (int i = 0; i < 1000; i++)
{
var page = await browser.NewPageAsync();
await page.SetContentAsync($"<h1>Document {i}</h1>");
await page.PdfAsync($"doc_{i}.pdf");
await page.CloseAsync();
}
// Recommended: await browser.CloseAsync(); and re-launch every N operations
//IronPDF- reuse a single renderer across operations
var renderer = new ChromePdfRenderer();
for (int i = 0; i < 1000; i++)
{
var pdf = renderer.RenderHtmlAsPdf($"<h1>Document {i}</h1>");
pdf.SaveAs($"doc_{i}.pdf");
// Memory managed automatically
}
Imports PuppeteerSharp
Imports IronPdf
' PuppeteerSharp- memory growth typically requires periodic recycling
For i As Integer = 0 To 999
Dim page = Await browser.NewPageAsync()
Await page.SetContentAsync($"<h1>Document {i}</h1>")
Await page.PdfAsync($"doc_{i}.pdf")
Await page.CloseAsync()
Next
' Recommended: Await browser.CloseAsync() and re-launch every N operations
' IronPDF- reuse a single renderer across operations
Dim renderer As New ChromePdfRenderer()
For i As Integer = 0 To 999
Dim pdf = renderer.RenderHtmlAsPdf($"<h1>Document {i}</h1>")
pdf.SaveAs($"doc_{i}.pdf")
' Memory managed automatically
Next
IronPDF는 PuppeteerSharp가 요구하는 브라우저 풀링 인프라가 필요 없습니다:
// Before (PuppeteerSharp - delete entire class)
public class PuppeteerBrowserPool
{
private readonly ConcurrentBag<IBrowser> _browsers;
private readonly SemaphoreSlim _semaphore;
private int _operationCount;
// ... recycling logic ...
}
// After (IronPDF - simple reuse)
public class PdfService
{
private readonly ChromePdfRenderer _renderer = new();
public byte[] Generate(string html)
{
return _renderer.RenderHtmlAsPdf(html).BinaryData;
}
}
// Before (PuppeteerSharp - delete entire class)
public class PuppeteerBrowserPool
{
private readonly ConcurrentBag<IBrowser> _browsers;
private readonly SemaphoreSlim _semaphore;
private int _operationCount;
// ... recycling logic ...
}
// After (IronPDF - simple reuse)
public class PdfService
{
private readonly ChromePdfRenderer _renderer = new();
public byte[] Generate(string html)
{
return _renderer.RenderHtmlAsPdf(html).BinaryData;
}
}
' Before (PuppeteerSharp - delete entire class)
Public Class PuppeteerBrowserPool
Private ReadOnly _browsers As ConcurrentBag(Of IBrowser)
Private ReadOnly _semaphore As SemaphoreSlim
Private _operationCount As Integer
' ... recycling logic ...
End Class
' After (IronPDF - simple reuse)
Public Class PdfService
Private ReadOnly _renderer As New ChromePdfRenderer()
Public Function Generate(html As String) As Byte()
Return _renderer.RenderHtmlAsPdf(html).BinaryData
End Function
End Class
중요한 마이그레이션 노트
비동기에서 동기 변환
PuppeteerSharp는 async/await을 요구합니다; IronPDF는 동기 작업을 지원합니다:
// PuppeteerSharp: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
await new BrowserFetcher().DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(...);
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html);
return await page.PdfDataAsync();
}
// IronPDF: Sync default
public byte[] GeneratePdf(string html)
{
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(html).BinaryData;
}
// Or async when needed
public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
// PuppeteerSharp: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
await new BrowserFetcher().DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(...);
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html);
return await page.PdfDataAsync();
}
// IronPDF: Sync default
public byte[] GeneratePdf(string html)
{
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(html).BinaryData;
}
// Or async when needed
public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
Imports System.Threading.Tasks
Imports PuppeteerSharp
' PuppeteerSharp: Async required
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Await (New BrowserFetcher()).DownloadAsync()
Await Using browser = Await Puppeteer.LaunchAsync(...)
Await Using page = Await browser.NewPageAsync()
Await page.SetContentAsync(html)
Return Await page.PdfDataAsync()
End Using
End Using
End Function
' IronPDF: Sync default
Public Function GeneratePdf(html As String) As Byte()
Dim renderer = New ChromePdfRenderer()
Return renderer.RenderHtmlAsPdf(html).BinaryData
End Function
' Or async when needed
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Dim renderer = New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Function
마진 단위 변환
PuppeteerSharp는 문자열 단위를 사용합니다; IronPDF는 숫자 밀리미터를 사용합니다:
//PuppeteerSharp- string units
MarginOptions = new MarginOptions
{
Top = "1in", // 25.4mm
Bottom = "0.75in", // 19mm
Left = "1cm", // 10mm
Right = "20px" // ~7.5mm at 96dpi
}
//IronPDF- numeric millimeters
renderer.RenderingOptions.MarginTop = 25; // mm
renderer.RenderingOptions.MarginBottom = 19;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 8;
//PuppeteerSharp- string units
MarginOptions = new MarginOptions
{
Top = "1in", // 25.4mm
Bottom = "0.75in", // 19mm
Left = "1cm", // 10mm
Right = "20px" // ~7.5mm at 96dpi
}
//IronPDF- numeric millimeters
renderer.RenderingOptions.MarginTop = 25; // mm
renderer.RenderingOptions.MarginBottom = 19;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 8;
MarginOptions = New MarginOptions With {
.Top = "1in", ' 25.4mm
.Bottom = "0.75in", ' 19mm
.Left = "1cm", ' 10mm
.Right = "20px" ' ~7.5mm at 96dpi
}
renderer.RenderingOptions.MarginTop = 25 ' mm
renderer.RenderingOptions.MarginBottom = 19
renderer.RenderingOptions.MarginLeft = 10
renderer.RenderingOptions.MarginRight = 8
헤더/푸터 플레이스홀더 변환
| PuppeteerSharp 클래스 | IronPDF 플레이스홀더 |
|---|---|
<span class='pageNumber'> |
{page} |
<span class='totalPages'> |
{total-pages} |
<span class='date'> |
{date} |
<span class='title'> |
{html-title} |
이동 후 새로운 기능
IronPDF로 마이그레이션한 후, PuppeteerSharp가 제공할 수 없는 기능을 얻을 수 있습니다:
PDF 병합
var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
Dim pdf1 = renderer.RenderHtmlAsPdf(html1)
Dim pdf2 = renderer.RenderHtmlAsPdf(html2)
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("merged.pdf")
워터마크
var watermark = new TextStamper
{
Text = "CONFIDENTIAL",
FontSize = 48,
Opacity = 30,
Rotation = -45
};
pdf.ApplyStamp(watermark);
var watermark = new TextStamper
{
Text = "CONFIDENTIAL",
FontSize = 48,
Opacity = 30,
Rotation = -45
};
pdf.ApplyStamp(watermark);
Dim watermark As New TextStamper With {
.Text = "CONFIDENTIAL",
.FontSize = 48,
.Opacity = 30,
.Rotation = -45
}
pdf.ApplyStamp(watermark)
비밀번호 보호
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.OwnerPassword = "admin"
pdf.SecuritySettings.UserPassword = "readonly"
pdf.SecuritySettings.AllowUserCopyPasteContent = False
디지털 서명
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)
PDF/A 규정 준수
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
성능 비교 요약
| 미터법 | PuppeteerSharp | IronPDF | 개선 |
|---|---|---|---|
| 첫 번째 PDF (콜드 스타트) | 45초 이상 | 약 20초 | 55% 이상 빠름 |
| 후속 PDF들 | 변하기 쉬운 | 일관적 | 예측 가능 |
| 메모리 사용량 | 500MB 이상 (증가함) | 약 50MB (안정적임) | 메모리 90% 감소 |
| 디스크 공간 (Chromium) | 300MB+ | 0 | 다운로드 제거 |
| 브라우저 다운로드 | 필요함 | 필요 없음 | 설정 없음 |
| 스레드 안전성 | 제한적 | 전체 | 신뢰할 수 있는 동시성 |
| PDF 생성 시간 | 45초 | 20초 | 55% 더 빠름 |
마이그레이션 체크리스트
사전 마이그레이션
- 코드베이스에서 모든PuppeteerSharp사용 식별
- 문서 여백 값을 기록 (문자열을 밀리미터로 변환)
- 변환을 위한 헤더/푸터 플레이스홀더 구문을 기록합니다
- 브라우저 풀링/재활용 인프라 삭제
- ironpdf.com에서IronPDF라이선스 키 획득
패키지 변경 사항
PuppeteerSharpNuGet 패키지 제거- 약 300MB의 디스크 공간을 회수하기 위해
.local-chromium폴더 삭제 IronPdfNuGet Install-Package:dotnet add package IronPdf
코드 변경 사항
- 네임스페이스 가져오기 업데이트
BrowserFetcher.DownloadAsync()호출 제거Puppeteer.LaunchAsync()및 브라우저 관리 제거page.SetContentAsync()+page.PdfAsync()을(를)RenderHtmlAsPdf()으로 대체page.GoToAsync()+page.PdfAsync()을(를)RenderUrlAsPdf()으로 대체- 여백 문자열을 밀리미터 값으로 변환합니다
- 헤더/푸터 플레이스홀더 구문을 변환합니다
- 모든 브라우저/페이지 폐기 코드를 제거합니다
- 브라우저 풀링 인프라 삭제
- 애플리케이션 시작 시 라이선스 초기화 추가
마이그레이션 이후
- PDF 출력의 시각적 비교
- 메모리 안정성을 위한 부하 테스트 (재활용 없이 안정해야 함)
- 페이지 번호로 헤더/푸터 렌더링을 확인합니다
- 필요에 따라 새 기능(보안, 워터마크, 병합) 추가

