푸터 콘텐츠로 바로가기
마이그레이션 가이드

PuppeteerSharp에서 IronPDF로의 마이그레이션 방법 (C#)

PuppeteerSharp에서 IronPDF로 마이그레이션을 통해 300MB 이상의 종속성을 가지는 브라우저 자동화 도구에서 자동 메모리 관리를 제공하는 목적 지향적 PDF 라이브러리로 PDF 생성 워크플로우를 변환합니다. 이 가이드는 Chromium 다운로드를 제거하고, 메모리 누수 문제를 해결하며, 종합적인 PDF 조작 기능을 제공하는 완벽하고 단계별 마이그레이션 경로를 제공합니다.

PuppeteerSharp에서 IronPDF로 마이그레이션해야 하는 이유

PuppeteerSharp이해하기

PuppeteerSharp는 Google's Puppeteer의 .NET 포트로, C#에 브라우저 자동화 기능을 제공합니다. Chrome의 내장된 PDF로 인쇄 기능을 사용하여 PDF를 생성합니다—브라우저에서 Ctrl+P를 누르는 것과 동일합니다. 이것은 화면에서 보이는 것과 다른 종이 최적화 출력물을 생성합니다.

PuppeteerSharp는 문서 생성을 위한 것이 아닌 웹 테스트와 스크래핑을 위해 설계되었습니다. PuppeteerSharp를 사용하여 PDF를 생성하면 상당한 생산 문제를 야기합니다.

브라우저 자동화 문제

PuppeteerSharp는 문서 생성이 아닌 브라우저 자동화를 위해 설계되었습니다. 따라서 PDF에 사용하는데 근본적인 문제가 발생합니다:

  1. 300MB 이상의 Chromium 다운로드가 처음 사용 전에 필요합니다. PuppeteerSharp의 중요한 단점은 Chromium 바이너리로 인해 배포 크기가 크다는 것입니다. 이 큰 크기는 Docker 이미지를 늘리고 서버리스 환경에서 콜드 스타트 문제를 일으킬 수 있습니다.

  2. 로드 중 메모리 누수로 인해 브라우저를 수동으로 회수해야 합니다. 무거운 로드에서 PuppeteerSharp는 메모리 누수가 발생할 수 있습니다. 브라우저 인스턴스의 메모리 누적은 프로세스 관리 및 회수를 위한 수동 개입이 필요합니다.

  3. 브라우저 수명주기 관리를 위한 복잡한 비동기 패턴.

  4. PDF로 인쇄 출력 (화면 캡처가 아닌 Ctrl+P와 동등). 레이아웃이 다시 흐르고, 기본적으로 배경이 생략되며, 출력은 브라우저 뷰포트를 일치시키기보다는 인쇄를 위해 페이지화됩니다.

  5. PDF/A 또는 PDF/UA 지원 없음 (규정 준수 요구 사항). PuppeteerSharp는 PDF/A(아카이브용) 또는 PDF/UA(접근성) 규격 문서를 생성할 수 없습니다.

  6. PDF 조작 불가 - 생성만 가능, 병합/분할/편집 불가. PuppeteerSharp는 PDF 생성을 효율적으로 하지만, 병합, 분할, 보안 강화 또는 편집 같은 추가 조작 능력이 없습니다.

PuppeteerSharpvsIronPDF비교

측면 PuppeteerSharp IronPDF
주된 목적 브라우저 자동화 PDF 생성
Chromium 의존성 300MB+ 별도 다운로드 내장 최적화 엔진
API 복잡성 비동기 브라우저/페이지 생명주기 동기 단일 행
초기화 BrowserFetcher.DownloadAsync() + LaunchAsync new ChromePdfRenderer()
메모리 관리 수동 브라우저 재활용 필요 자동
로드 하의 메모리 500MB+ 누수 발생 ~50MB 안정성
콜드 스타트 45+ 초 ~20 초
PDF/A 지원 사용 불가 지원됨
PDF/UA 접근성 사용 불가 지원됨
PDF 편집 사용 불가 병합, 분할, 스탬프, 편집
디지털 서명 사용 불가 지원됨
스레드 안전성 제한적 전체
전문가 지원 Community SLA가 포함된 상업용

플랫폼 지원

|라이브러리|.NET Framework 4.7.2|.NET Core 3.1|.NET 6-8|.NET 10| | --------- | :---: | :---: | :---: | :---: ||IronPDF| 전체 | 전체 | 전체 | 전체 ||PuppeteerSharp| 제한적 | 전체 | 전체 | 대기 중 | IronPDF의 광범위한 .NET 플랫폼 지원은 개발자가 다양한 환경에서 호환성 문제가 없이 이를 활용할 수 있도록 보장하여 2025년과 2026년을 위한 현대적인 .NET 애플리케이션에 유연한 선택을 제공합니다.


시작하기 전에

필수 조건

  1. .NET 환경: .NET Framework 4.6.2+ 또는 .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet 접근 권한: NuGet 패키지를 설치할 수 있는 능력
  3. 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
SHELL

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"
$vbLabelText   $csharpLabel

완전한 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
$vbLabelText   $csharpLabel

핵심 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
$vbLabelText   $csharpLabel

이후 (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
$vbLabelText   $csharpLabel

이 예제는 근본적인 아키텍처 차이를 보여줍니다. PuppeteerSharp는 여섯 개의 비동기 작업이 필요합니다: BrowserFetcher.DownloadAsync() (300MB 이상의 Chromium 다운로드), 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
$vbLabelText   $csharpLabel

이후 (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
$vbLabelText   $csharpLabel

PuppeteerSharp는 URL로 이동하는 데 GoToAsync()를 사용한 다음 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
$vbLabelText   $csharpLabel

이후 (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
$vbLabelText   $csharpLabel

이 예제는 두 라이브러리 간의 PDF 옵션 매핑을 보여줍니다. PuppeteerSharp는 문자열 값("20mm")이 포함된 Format, LandscapeMarginOptions와 함께 PdfOptions를 사용합니다. IronPDF는 직접적인 용지 크기 열거형, 방향 열거형 및 밀리미터 단위의 숫자 여백 값을 가진 RenderingOptions 속성을 사용합니다.

주요 매핑:

  • Format = PaperFormat.A4PaperSize = PdfPaperSize.A4
  • Landscape = truePaperOrientation = PdfPaperOrientation.Landscape
  • MarginOptions.Top = "20mm"MarginTop = 20 (숫자 밀리미터)

메모리 누수 문제

PuppeteerSharp는 지속적인 부하 하에서 메모리 축적으로 악명이 높습니다:

// ❌PuppeteerSharp- Memory grows with each operation
// Requires explicit browser recycling every N operations
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(); // Memory still accumulates!
}
// Must periodically: await browser.CloseAsync(); and re-launch

// ✅IronPDF- Stable memory, reuse renderer
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 grows with each operation
// Requires explicit browser recycling every N operations
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(); // Memory still accumulates!
}
// Must periodically: await browser.CloseAsync(); and re-launch

// ✅IronPDF- Stable memory, reuse renderer
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 grows with each operation
' Requires explicit browser recycling every N operations
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() ' Memory still accumulates!
Next
' Must periodically: Await browser.CloseAsync() and re-launch

' ✅IronPDF- Stable memory, reuse renderer
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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

중요한 마이그레이션 노트

비동기에서 동기 변환

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
$vbLabelText   $csharpLabel

마진 단위 변환

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
$vbLabelText   $csharpLabel

헤더/푸터 플레이스홀더 변환

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")
$vbLabelText   $csharpLabel

워터마크

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)
$vbLabelText   $csharpLabel

비밀번호 보호

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
$vbLabelText   $csharpLabel

디지털 서명

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)
$vbLabelText   $csharpLabel

PDF/A 규정 준수

pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
$vbLabelText   $csharpLabel

성능 비교 요약

미터법 PuppeteerSharp IronPDF 개선
첫 번째 PDF (콜드 스타트) 45초 이상 약 20초 55% 이상 빠름
후속 PDF들 변하기 쉬운 일관적 예측 가능
메모리 사용량 500MB 이상 (증가함) 약 50MB (안정적임) 메모리 90% 감소
디스크 공간 (Chromium) 300MB+ 0 다운로드 제거
브라우저 다운로드 필요함 필요 없음 설정 없음
스레드 안전성 제한적 전체 신뢰할 수 있는 동시성
PDF 생성 시간 45초 20초 55% 더 빠름

마이그레이션 체크리스트

사전 마이그레이션

  • 코드베이스에서 모든PuppeteerSharp사용 식별
  • 문서 여백 값을 기록 (문자열을 밀리미터로 변환)
  • 변환을 위한 헤더/푸터 플레이스홀더 구문을 기록합니다
  • 브라우저 풀링/재활용 인프라 삭제
  • ironpdf.com에서IronPDF라이선스 키 획득

패키지 변경 사항

  • PuppeteerSharp NuGet 패키지 제거
  • 약 300MB의 디스크 공간을 회수하기 위해 .local-chromium 폴더 삭제
  • IronPdf NuGet Install-Package: dotnet add package IronPdf

코드 변경 사항

  • 네임스페이스 가져오기 업데이트
  • BrowserFetcher.DownloadAsync() 호출 제거
  • Puppeteer.LaunchAsync() 및 브라우저 관리 제거
  • page.SetContentAsync() + page.PdfAsync()RenderHtmlAsPdf()로 대체
  • page.GoToAsync() + page.PdfAsync()RenderUrlAsPdf()로 대체
  • 여백 문자열을 밀리미터 값으로 변환합니다
  • 헤더/푸터 플레이스홀더 구문을 변환합니다
  • 모든 브라우저/페이지 폐기 코드를 제거합니다
  • 브라우저 풀링 인프라 삭제
  • 애플리케이션 시작 시 라이선스 초기화 추가

마이그레이션 이후

  • PDF 출력의 시각적 비교
  • 메모리 안정성을 위한 부하 테스트 (재활용 없이 안정해야 함)
  • 페이지 번호로 헤더/푸터 렌더링을 확인합니다
  • 필요에 따라 새 기능(보안, 워터마크, 병합) 추가

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해