IronPDF vs PDFSharpCore: 2025년에 선택해야 할 .NET PDF 라이브러리는?
PDF 생성 및 조작 기능이 필요한 현대적인 .NET 애플리케이션을 개발할 때, 적절한 라이브러리를 선택하면 프로젝트 성공에 중요할 수 있습니다. .NET 생태계에서 두 가지 주요 옵션은 각각 PDF 처리에 대한 독특한 접근 방식을 제공하는 IronPDF와 PDFSharpCore입니다. 이 종합 비교는 귀하의 특정 요구 사항, 예산 및 기술 요구에 기반한 정보에 입각한 결정을 내릴 수 있도록 도와줄 것입니다.
빠른 비교 개요
기술 세부 사항에 들어가기 전에, IronPDF와PDFSharpCore간의 주요 차이점을 요약한 포괄적인 비교 표가 있습니다.
| 범주 | 특징/측면 | IronPDF | PDFSharpCore | 핵심 이점 |
|---|---|---|---|---|
| **핵심 아키텍처** | 디자인 철학 | Chrome 기반 렌더링, 직관적인 API | 경량, 수동 PDF 구성 | IronPDF: 빠른 개발 |
| API 복잡성 | `RenderHtmlAsPdf()`와 같은 간단한 메서드 | XGraphics를 사용한 수동 드로잉 | IronPDF: 코드 70% 감소 | |
| 학습 곡선 | 일반적으로 1~2일 소요 | 보통 3-5일 | IronPDF: 빠른 채택 | |
| **플랫폼 지원** | 크로스 플랫폼 | 네이티브 지원, 추가 패키지 필요 없음 | 전체 플랫폼 간 지원 | 둘 다: 현대적 배포 |
| .NET 버전 | .NET 10, 9, 8, 7, 6, 5, Core 3.1+, Framework 4.6.2+ | .NET 6+, .NET Standard 2.0 | IronPDF: 광범위한 호환성 | |
| 운영 체제 | 윈도우, 리눅스, macOS, Docker, Azure, AWS | 윈도우, 리눅스, macOS | IronPDF: 클라우드 최적화됨 | |
| **HTML을 PDF로 변환** | 렌더링 엔진 | 풀 Chrome V8 엔진 | 네이티브 HTML 지원 없음 | IronPDF: HTML 기능 |
| CSS3/HTML5 지원 | 완전한 지원 | 타사 라이브러리 필요 | IronPDF: 최신 웹 표준 | |
| JavaScript 실행 | 완전한 JavaScript 지원 | 해당 없음 | IronPDF: 동적 콘텐츠 | |
| **핵심 기능** | 텍스트 추출 | 내장된 `ExtractAllText()` | 제한적 지원 | IronPDF: 우수한 추출 |
| 워터마킹 | HTML/CSS 기반, 전체 스타일링 | 수동 드로잉 필요 | IronPDF: 리치 워터마크 | |
| 디지털 서명 | 통합된, 시각적 서명 | Not supported | IronPDF: Enterprise 보안 | |
| 암호화 | AES-256, 사용자 정의 핸들러 | 기본 암호화 지원 | IronPDF: 고급 보안 | |
| 머리글/바닥글 | HTML 기반, 동적 콘텐츠 | 수동 위치 지정 | IronPDF: 동적 헤더 | |
| **성능** | HTML 렌더링 속도 | 평소 0.8-2초 (Chrome 엔진) | 해당 없음 | IronPDF: HTML 렌더링 |
| 대형 문서 처리 | 규모를 위한 최적화 | 메모리 효율적 | PDFSharpCore: 낮은 메모리 | |
| 스레딩 지원 | 네이티브 async/await, 병렬 처리 | 스레드 안전 작업 | IronPDF: 더 나은 확장성 | |
| **개발자 경험** | 선적 서류 비치 | 광범위한 튜토리얼, API 문서, 비디오 | 기본 문서화 | IronPDF: 더 나은 리소스 |
| 코드 예제 | 100개 이상의 실행 가능한 샘플 | 커뮤니티 예제 | IronPDF: 광범위한 샘플 | |
| IntelliSense 지원 | 전체 IntelliSense, XML 문서 | 표준 IntelliSense | 둘 다: IDE 통합 | |
| **Licensing & Pricing** | 라이선스 유형 | 상업적, 영구적 | MIT License (무료) | PDFSharpCore: 비용 없음 |
| 참가비 | Lite: $799 (1 dev, 1 project) | 무료 | PDFSharpCore: 비용 제로 | |
| 지원 | 24/5 엔지니어링 지원 포함 | 커뮤니티 지원만 | IronPDF: 프로페셔널 지원 | |
| **가장 적합한 대상** | 사용 사례 | 웹 앱, 보고서, Enterprise | 단순 PDF, 저예산 프로젝트 | 상황에 따라 다름 |
IronPDF및PDFSharpCore소개
IronPDF란 무엇인가요?
IronPDF는 개발자의 PDF 생성, 편집 및 조작을 용이하게 하기 위해 설계된 포괄적인 상업적 .NET 라이브러리입니다. Chrome 기반 렌더링 엔진 위에 구축되어, HTML, CSS 및 JavaScript 콘텐츠를 픽셀 단위로 완벽하게 PDF로 변환하는 데 뛰어납니다. 이 라이브러리는 HTML을 PDF로 변환, 디지털 서명, 워터마킹, PDF 암호화, 양식 관리를 포함한 광범위한 기능 세트를 제공합니다.
IronPDF는 .NET 10, 9, 8, 7, 6, 5, Core 3.1+, Framework 4.6.2+를 포함한 최신 .NET 버전을 지원하여, 새로운 애플리케이션과 기존 애플리케이션 모두에 유연하게 사용할 수 있습니다. 클라우드 최적화 아키텍처로 Azure, AWS, Docker 환경에서 매끄러운 배포를 지원합니다.
PDFSharpCore란 무엇인가요?
PDFSharpCore는 원본 PDFsharp 라이브러리의 .NET Core 포트로 서비스되는 오픈 소스 라이브러리입니다. MIT 라이선스 하에 배포되며, Windows 특정 라이브러리 없이 프로그램적으로 PDF를 생성하고 기본 조작하는 데 중점을 둡니다. 이는 Linux, macOS, Windows에서 실행되는 크로스 플랫폼 프로젝트에 탁월한 선택입니다.
PDFSharpCore는 네이티브 HTML을 PDF로 변환하는 기능을 제공하지 않지만, 그래픽 API를 통해 PDF 문서 생성에 대한 정밀한 제어를 제공합니다. 개발자는 좌표 기반의 드로잉 명령을 사용하여 텍스트, 이미지, 그래픽을 배치하여 수동으로 PDF 문서를 작성할 수 있습니다.
설치 및 설정
IronPDF설치 중
프로젝트에서 IronPDF를 사용하기 시작하려면 NuGet 패키지 관리자를 통해 쉽게 설치할 수 있습니다. 다음 단계를 따르세요:
- Visual Studio에서 프로젝트를 엽니다.
- 도구 > NuGet 패키지 관리자 > 솔루션용 NuGet 패키지 관리로 이동합니다.
- NuGet 관리에서 IronPdf를 검색합니다.
- 프로젝트를 선택한 후 설치를 클릭하여 프로젝트에 IronPDF를 추가합니다.
Visual Studio의 NuGet 패키지 관리자 인터페이스를 통해IronPDF설치
또한, 패키지 관리자 콘솔을 사용하여 다음 명령으로 IronPDF를 설치할 수 있습니다:
Install-Package IronPdf
PDFSharpCore설치하기
NuGet을 사용하여 PDFSharpCore를 설치하려면 다음 지침을 따르세요:
- Visual Studio 프로젝트가 열려 있는지 확인하세요.
- 도구 > NuGet 패키지 관리자 > 솔루션용 NuGet 패키지 관리로 이동합니다.
- NuGet 패키지 관리자에서 PDFSharpCore를 검색합니다.
- 프로젝트를 선택하고 설치를 클릭하여 PDFSharpCore를 통합합니다.
NuGet 패키지 관리자를 통한PDFSharpCore설치
패키지 관리자 콘솔을 선호하는 개발자들을 위해, 다음 명령으로 PDFSharpCore를 설치할 수 있습니다:
Install-Package PdfSharpCore
PDF 파일 만들기:IronPDFvs PDFSharpCore
IronPDF: 현대적 HTML 기반 접근법
IronPDF는 개발자가 이미 알고 있는 웹 기술을 활용하여 PDF 생성 방식을 혁신합니다. Chrome 기반 렌더링 엔진을 통해 HTML, CSS, JavaScript가 현대 브라우저에서 나타나는 것과 똑같이 렌더링됩니다.
고급 기능을 갖춘 HTML 문자열을 PDF로 변환
IronPDF의 HTML에서 PDF로 변환 기능은 단순한 텍스트 렌더링을 훨씬 넘어섭니다. 다음은 그 강력함을 보여주는 향상된 예입니다:
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main(string[] args)
{
// Apply your license key (required for production)
License.LicenseKey = "Your-License-Key";
// Create renderer with optimized settings
var renderer = new ChromePdfRenderer()
{
RenderingOptions = new ChromePdfRenderOptions()
{
// Set margins for professional appearance
MarginTop = 25,
MarginBottom = 25,
MarginLeft = 20,
MarginRight = 20,
// Enable JavaScript execution for dynamic content
EnableJavaScript = true,
// Wait for AJAX/animations to complete
RenderDelay = 500,
// Set paper orientation and size
PaperOrientation = PdfPaperOrientation.Portrait,
PaperSize = PdfPaperSize.A4,
// Enable printing of background colors and images
PrintHtmlBackgrounds = true
}
};
// HTML with Bootstrap styling and charts
string htmlContent = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; }
.chart-container { width: 100%; height: 300px; margin: 20px 0; }
</style>
</head>
<body>
<div class='header text-center'>
<h1>2024 Sales Performance Report</h1>
<p class='lead'>Comprehensive Analysis & Insights</p>
</div>
<div class='container mt-4'>
<div class='row'>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Q1 Performance Metrics</h5>
<table class='table table-striped'>
<thead>
<tr>
<th>Month</th>
<th>Revenue</th>
<th>Growth</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$50,000</td>
<td><span class='badge bg-success'>+12%</span></td>
</tr>
<tr>
<td>February</td>
<td>$55,000</td>
<td><span class='badge bg-success'>+10%</span></td>
</tr>
<tr>
<td>March</td>
<td>$60,000</td>
<td><span class='badge bg-success'>+9%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Revenue Trend</h5>
<canvas id='revenueChart'></canvas>
</div>
</div>
</div>
</div>
<div class='alert alert-info mt-4'>
<strong>Key Insight:</strong> Q1 showed consistent growth across all months,
with total revenue reaching $165,000, representing a 31% increase YoY.
</div>
</div>
<script>
// Create an interactive chart
const ctx = document.getElementById('revenueChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March'],
datasets: [{
label: 'Revenue',
data: [50000, 55000, 60000],
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.1)',
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
</script>
</body>
</html>";
// Render the HTML to PDF
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Add metadata for better document management
pdf.MetaData.Author = "Sales Department";
pdf.MetaData.Title = "Q1 2024 Sales Report";
pdf.MetaData.Subject = "Quarterly Performance Analysis";
pdf.MetaData.Keywords = "sales, performance, Q1, 2024";
pdf.MetaData.CreationDate = DateTime.Now;
// Save the PDF
pdf.SaveAs("sales-report-q1-2024.pdf");
Console.WriteLine("Professional sales report generated successfully!");
}
}
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main(string[] args)
{
// Apply your license key (required for production)
License.LicenseKey = "Your-License-Key";
// Create renderer with optimized settings
var renderer = new ChromePdfRenderer()
{
RenderingOptions = new ChromePdfRenderOptions()
{
// Set margins for professional appearance
MarginTop = 25,
MarginBottom = 25,
MarginLeft = 20,
MarginRight = 20,
// Enable JavaScript execution for dynamic content
EnableJavaScript = true,
// Wait for AJAX/animations to complete
RenderDelay = 500,
// Set paper orientation and size
PaperOrientation = PdfPaperOrientation.Portrait,
PaperSize = PdfPaperSize.A4,
// Enable printing of background colors and images
PrintHtmlBackgrounds = true
}
};
// HTML with Bootstrap styling and charts
string htmlContent = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; }
.chart-container { width: 100%; height: 300px; margin: 20px 0; }
</style>
</head>
<body>
<div class='header text-center'>
<h1>2024 Sales Performance Report</h1>
<p class='lead'>Comprehensive Analysis & Insights</p>
</div>
<div class='container mt-4'>
<div class='row'>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Q1 Performance Metrics</h5>
<table class='table table-striped'>
<thead>
<tr>
<th>Month</th>
<th>Revenue</th>
<th>Growth</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$50,000</td>
<td><span class='badge bg-success'>+12%</span></td>
</tr>
<tr>
<td>February</td>
<td>$55,000</td>
<td><span class='badge bg-success'>+10%</span></td>
</tr>
<tr>
<td>March</td>
<td>$60,000</td>
<td><span class='badge bg-success'>+9%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Revenue Trend</h5>
<canvas id='revenueChart'></canvas>
</div>
</div>
</div>
</div>
<div class='alert alert-info mt-4'>
<strong>Key Insight:</strong> Q1 showed consistent growth across all months,
with total revenue reaching $165,000, representing a 31% increase YoY.
</div>
</div>
<script>
// Create an interactive chart
const ctx = document.getElementById('revenueChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March'],
datasets: [{
label: 'Revenue',
data: [50000, 55000, 60000],
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.1)',
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
</script>
</body>
</html>";
// Render the HTML to PDF
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Add metadata for better document management
pdf.MetaData.Author = "Sales Department";
pdf.MetaData.Title = "Q1 2024 Sales Report";
pdf.MetaData.Subject = "Quarterly Performance Analysis";
pdf.MetaData.Keywords = "sales, performance, Q1, 2024";
pdf.MetaData.CreationDate = DateTime.Now;
// Save the PDF
pdf.SaveAs("sales-report-q1-2024.pdf");
Console.WriteLine("Professional sales report generated successfully!");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Friend Class Program
Shared Sub Main(ByVal args() As String)
' Apply your license key (required for production)
License.LicenseKey = "Your-License-Key"
' Create renderer with optimized settings
Dim renderer = New ChromePdfRenderer() With {
.RenderingOptions = New ChromePdfRenderOptions() With {
.MarginTop = 25,
.MarginBottom = 25,
.MarginLeft = 20,
.MarginRight = 20,
.EnableJavaScript = True,
.RenderDelay = 500,
.PaperOrientation = PdfPaperOrientation.Portrait,
.PaperSize = PdfPaperSize.A4,
.PrintHtmlBackgrounds = True
}
}
' HTML with Bootstrap styling and charts
Dim htmlContent As String = "
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; }
.chart-container { width: 100%; height: 300px; margin: 20px 0; }
</style>
</head>
<body>
<div class='header text-center'>
<h1>2024 Sales Performance Report</h1>
<p class='lead'>Comprehensive Analysis & Insights</p>
</div>
<div class='container mt-4'>
<div class='row'>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Q1 Performance Metrics</h5>
<table class='table table-striped'>
<thead>
<tr>
<th>Month</th>
<th>Revenue</th>
<th>Growth</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$50,000</td>
<td><span class='badge bg-success'>+12%</span></td>
</tr>
<tr>
<td>February</td>
<td>$55,000</td>
<td><span class='badge bg-success'>+10%</span></td>
</tr>
<tr>
<td>March</td>
<td>$60,000</td>
<td><span class='badge bg-success'>+9%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Revenue Trend</h5>
<canvas id='revenueChart'></canvas>
</div>
</div>
</div>
</div>
<div class='alert alert-info mt-4'>
<strong>Key Insight:</strong> Q1 showed consistent growth across all months,
with total revenue reaching $165,000, representing a 31% increase YoY.
</div>
</div>
<script>
// Create an interactive chart
const ctx = document.getElementById('revenueChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March'],
datasets: [{
label: 'Revenue',
data: [50000, 55000, 60000],
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.1)',
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
</script>
</body>
</html>"
' Render the HTML to PDF
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
' Add metadata for better document management
pdf.MetaData.Author = "Sales Department"
pdf.MetaData.Title = "Q1 2024 Sales Report"
pdf.MetaData.Subject = "Quarterly Performance Analysis"
pdf.MetaData.Keywords = "sales, performance, Q1, 2024"
pdf.MetaData.CreationDate = DateTime.Now
' Save the PDF
pdf.SaveAs("sales-report-q1-2024.pdf")
Console.WriteLine("Professional sales report generated successfully!")
End Sub
End Class
이 예시는 IronPDF의 몇 가지 고급 기능을 보여줍니다:
- Bootstrap 통합: 전문적인 스타일링을 위한 인기 있는 CSS 프레임워크 활용
- JavaScript 차트: PDF에서 Chart.js 비주얼리제이션을 동적으로 렌더링
- 반응형 디자인: 반응형 레이아웃을 지능적으로 처리
- 메타데이터 관리: 문서 관리 시스템을 위한 검색 가능한 메타데이터 추가
- 렌더링 지연: JavaScript 콘텐츠가 완전히 로드된 후 렌더링
해당 ChromePdfRenderer 클래스는 렌더링 과정에 대한 광범위한 제어를 제공합니다. 주요 옵션에는 다음이 포함됩니다:
EnableJavaScript: 렌더링 전에 JavaScript 코드를 실행합니다RenderDelay: 비동기 콘텐츠 로드를 대기합니다PrintHtmlBackgrounds: 배경 색상 및 이미지를 보존합니다PaperOrientation및PaperSize: 페이지 레이아웃을 제어합니다- 전문적인 문서 외관을 위한 여백 설정
HTML 파일 및 URL 변환
IronPDF는 기존 HTML 파일 및 실시간 웹 페이지 변환에서도 뛰어납니다:
using IronPdf;
class Program
{
static async Task Main(string[] args)
{
License.LicenseKey = "Your-License-Key";
var renderer = new ChromePdfRenderer();
// Convert a local HTML file with external resources
var filePdf = renderer.RenderHtmlFileAsPdf(@"C:\Reports\template.html");
filePdf.SaveAs("from-file.pdf");
// Convert a URL with authentication
renderer.LoginCredentials = new ChromeHttpLoginCredentials()
{
Username = "user@example.com",
Password = "secure-password"
};
// Render a password-protected page
var urlPdf = await renderer.RenderUrlAsPdfAsync("https://secure.example.com/reports");
urlPdf.SaveAs("secure-report.pdf");
}
}
using IronPdf;
class Program
{
static async Task Main(string[] args)
{
License.LicenseKey = "Your-License-Key";
var renderer = new ChromePdfRenderer();
// Convert a local HTML file with external resources
var filePdf = renderer.RenderHtmlFileAsPdf(@"C:\Reports\template.html");
filePdf.SaveAs("from-file.pdf");
// Convert a URL with authentication
renderer.LoginCredentials = new ChromeHttpLoginCredentials()
{
Username = "user@example.com",
Password = "secure-password"
};
// Render a password-protected page
var urlPdf = await renderer.RenderUrlAsPdfAsync("https://secure.example.com/reports");
urlPdf.SaveAs("secure-report.pdf");
}
}
Imports IronPdf
Friend Class Program
Shared Async Function Main(ByVal args() As String) As Task
License.LicenseKey = "Your-License-Key"
Dim renderer = New ChromePdfRenderer()
' Convert a local HTML file with external resources
Dim filePdf = renderer.RenderHtmlFileAsPdf("C:\Reports\template.html")
filePdf.SaveAs("from-file.pdf")
' Convert a URL with authentication
renderer.LoginCredentials = New ChromeHttpLoginCredentials() With {
.Username = "user@example.com",
.Password = "secure-password"
}
' Render a password-protected page
Dim urlPdf = Await renderer.RenderUrlAsPdfAsync("https://secure.example.com/reports")
urlPdf.SaveAs("secure-report.pdf")
End Function
End Class
PDFSharpCore: 수동 문서 작성
PDFSharpCore는 근본적으로 다른 접근 방식을 취하며, 개발자가 드로잉 명령을 사용하여 수동으로 PDF 문서를 구성해야 합니다. 이는 정밀한 제어를 제공하는 동시에 복잡한 레이아웃에 대해서는 상당히 더 많은 코드를 필요로 합니다.
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using System;
class Program
{
static void Main()
{
// Create a new PDF document
var document = new PdfDocument();
document.Info.Title = "Sales Report Q1 2024";
document.Info.Author = "Sales Department";
// Add a page
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.A4;
// Create graphics object for drawing
var gfx = XGraphics.FromPdfPage(page);
// Define fonts
var titleFont = new XFont("Arial", 24, XFontStyle.Bold);
var headingFont = new XFont("Arial", 14, XFontStyle.Bold);
var normalFont = new XFont("Arial", 11, XFontStyle.Regular);
// Draw title with gradient-like effect (manual implementation)
var titleBrush = new XLinearGradientBrush(
new XPoint(0, 0),
new XPoint(page.Width, 0),
XColors.DarkBlue,
XColors.Purple
);
gfx.DrawRectangle(titleBrush, 0, 0, page.Width, 80);
gfx.DrawString("2024 Sales Performance Report",
titleFont, XBrushes.White,
new XRect(0, 20, page.Width, 40),
XStringFormats.TopCenter);
// Draw table manually
double yPosition = 120;
double margin = 50;
double columnWidth = (page.Width - 2 * margin) / 3;
// Table header
gfx.DrawRectangle(XBrushes.LightGray, margin, yPosition, page.Width - 2 * margin, 25);
gfx.DrawString("Month", headingFont, XBrushes.Black,
new XRect(margin, yPosition, columnWidth, 25),
XStringFormats.Center);
gfx.DrawString("Revenue", headingFont, XBrushes.Black,
new XRect(margin + columnWidth, yPosition, columnWidth, 25),
XStringFormats.Center);
gfx.DrawString("Growth", headingFont, XBrushes.Black,
new XRect(margin + 2 * columnWidth, yPosition, columnWidth, 25),
XStringFormats.Center);
// Table data
string[,] data = {
{ "January", "$50,000", "+12%" },
{ "February", "$55,000", "+10%" },
{ "March", "$60,000", "+9%" }
};
yPosition += 25;
for (int i = 0; i < 3; i++)
{
// Alternate row colors
if (i % 2 == 0)
{
gfx.DrawRectangle(XBrushes.WhiteSmoke, margin, yPosition, page.Width - 2 * margin, 20);
}
for (int j = 0; j < 3; j++)
{
gfx.DrawString(data[i, j], normalFont, XBrushes.Black,
new XRect(margin + j * columnWidth, yPosition, columnWidth, 20),
XStringFormats.Center);
}
yPosition += 20;
}
// Draw a simple line chart (very basic implementation)
yPosition += 40;
gfx.DrawString("Revenue Trend", headingFont, XBrushes.Black,
new XRect(margin, yPosition, page.Width - 2 * margin, 25),
XStringFormats.TopLeft);
// Chart area
yPosition += 30;
double chartHeight = 150;
double chartWidth = page.Width - 2 * margin;
// Draw axes
gfx.DrawLine(XPens.Black, margin, yPosition + chartHeight, margin + chartWidth, yPosition + chartHeight);
gfx.DrawLine(XPens.Black, margin, yPosition, margin, yPosition + chartHeight);
// Plot points (simplified)
double[] revenues = { 50000, 55000, 60000 };
double maxRevenue = 65000;
double xStep = chartWidth / 3;
for (int i = 0; i < revenues.Length; i++)
{
double x = margin + (i + 0.5) * xStep;
double y = yPosition + chartHeight - (revenues[i] / maxRevenue * chartHeight);
// Draw point
gfx.DrawEllipse(XBrushes.Blue, x - 3, y - 3, 6, 6);
// Draw connecting lines
if (i > 0)
{
double prevX = margin + (i - 0.5) * xStep;
double prevY = yPosition + chartHeight - (revenues[i - 1] / maxRevenue * chartHeight);
gfx.DrawLine(new XPen(XColors.Blue, 2), prevX, prevY, x, y);
}
// Labels
gfx.DrawString($"${revenues[i]:N0}", normalFont, XBrushes.Black,
new XRect(x - 30, y - 20, 60, 15),
XStringFormats.TopCenter);
}
// Save the document
document.Save("pdfsharp-sales-report.pdf");
Console.WriteLine("PDF created with PDFSharpCore");
}
}
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using System;
class Program
{
static void Main()
{
// Create a new PDF document
var document = new PdfDocument();
document.Info.Title = "Sales Report Q1 2024";
document.Info.Author = "Sales Department";
// Add a page
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.A4;
// Create graphics object for drawing
var gfx = XGraphics.FromPdfPage(page);
// Define fonts
var titleFont = new XFont("Arial", 24, XFontStyle.Bold);
var headingFont = new XFont("Arial", 14, XFontStyle.Bold);
var normalFont = new XFont("Arial", 11, XFontStyle.Regular);
// Draw title with gradient-like effect (manual implementation)
var titleBrush = new XLinearGradientBrush(
new XPoint(0, 0),
new XPoint(page.Width, 0),
XColors.DarkBlue,
XColors.Purple
);
gfx.DrawRectangle(titleBrush, 0, 0, page.Width, 80);
gfx.DrawString("2024 Sales Performance Report",
titleFont, XBrushes.White,
new XRect(0, 20, page.Width, 40),
XStringFormats.TopCenter);
// Draw table manually
double yPosition = 120;
double margin = 50;
double columnWidth = (page.Width - 2 * margin) / 3;
// Table header
gfx.DrawRectangle(XBrushes.LightGray, margin, yPosition, page.Width - 2 * margin, 25);
gfx.DrawString("Month", headingFont, XBrushes.Black,
new XRect(margin, yPosition, columnWidth, 25),
XStringFormats.Center);
gfx.DrawString("Revenue", headingFont, XBrushes.Black,
new XRect(margin + columnWidth, yPosition, columnWidth, 25),
XStringFormats.Center);
gfx.DrawString("Growth", headingFont, XBrushes.Black,
new XRect(margin + 2 * columnWidth, yPosition, columnWidth, 25),
XStringFormats.Center);
// Table data
string[,] data = {
{ "January", "$50,000", "+12%" },
{ "February", "$55,000", "+10%" },
{ "March", "$60,000", "+9%" }
};
yPosition += 25;
for (int i = 0; i < 3; i++)
{
// Alternate row colors
if (i % 2 == 0)
{
gfx.DrawRectangle(XBrushes.WhiteSmoke, margin, yPosition, page.Width - 2 * margin, 20);
}
for (int j = 0; j < 3; j++)
{
gfx.DrawString(data[i, j], normalFont, XBrushes.Black,
new XRect(margin + j * columnWidth, yPosition, columnWidth, 20),
XStringFormats.Center);
}
yPosition += 20;
}
// Draw a simple line chart (very basic implementation)
yPosition += 40;
gfx.DrawString("Revenue Trend", headingFont, XBrushes.Black,
new XRect(margin, yPosition, page.Width - 2 * margin, 25),
XStringFormats.TopLeft);
// Chart area
yPosition += 30;
double chartHeight = 150;
double chartWidth = page.Width - 2 * margin;
// Draw axes
gfx.DrawLine(XPens.Black, margin, yPosition + chartHeight, margin + chartWidth, yPosition + chartHeight);
gfx.DrawLine(XPens.Black, margin, yPosition, margin, yPosition + chartHeight);
// Plot points (simplified)
double[] revenues = { 50000, 55000, 60000 };
double maxRevenue = 65000;
double xStep = chartWidth / 3;
for (int i = 0; i < revenues.Length; i++)
{
double x = margin + (i + 0.5) * xStep;
double y = yPosition + chartHeight - (revenues[i] / maxRevenue * chartHeight);
// Draw point
gfx.DrawEllipse(XBrushes.Blue, x - 3, y - 3, 6, 6);
// Draw connecting lines
if (i > 0)
{
double prevX = margin + (i - 0.5) * xStep;
double prevY = yPosition + chartHeight - (revenues[i - 1] / maxRevenue * chartHeight);
gfx.DrawLine(new XPen(XColors.Blue, 2), prevX, prevY, x, y);
}
// Labels
gfx.DrawString($"${revenues[i]:N0}", normalFont, XBrushes.Black,
new XRect(x - 30, y - 20, 60, 15),
XStringFormats.TopCenter);
}
// Save the document
document.Save("pdfsharp-sales-report.pdf");
Console.WriteLine("PDF created with PDFSharpCore");
}
}
Imports PdfSharpCore.Drawing
Imports PdfSharpCore.Pdf
Imports System
Friend Class Program
Shared Sub Main()
' Create a new PDF document
Dim document = New PdfDocument()
document.Info.Title = "Sales Report Q1 2024"
document.Info.Author = "Sales Department"
' Add a page
Dim page = document.AddPage()
page.Size = PdfSharpCore.PageSize.A4
' Create graphics object for drawing
Dim gfx = XGraphics.FromPdfPage(page)
' Define fonts
Dim titleFont = New XFont("Arial", 24, XFontStyle.Bold)
Dim headingFont = New XFont("Arial", 14, XFontStyle.Bold)
Dim normalFont = New XFont("Arial", 11, XFontStyle.Regular)
' Draw title with gradient-like effect (manual implementation)
Dim titleBrush = New XLinearGradientBrush(New XPoint(0, 0), New XPoint(page.Width, 0), XColors.DarkBlue, XColors.Purple)
gfx.DrawRectangle(titleBrush, 0, 0, page.Width, 80)
gfx.DrawString("2024 Sales Performance Report", titleFont, XBrushes.White, New XRect(0, 20, page.Width, 40), XStringFormats.TopCenter)
' Draw table manually
Dim yPosition As Double = 120
Dim margin As Double = 50
Dim columnWidth As Double = (page.Width - 2 * margin) / 3
' Table header
gfx.DrawRectangle(XBrushes.LightGray, margin, yPosition, page.Width - 2 * margin, 25)
gfx.DrawString("Month", headingFont, XBrushes.Black, New XRect(margin, yPosition, columnWidth, 25), XStringFormats.Center)
gfx.DrawString("Revenue", headingFont, XBrushes.Black, New XRect(margin + columnWidth, yPosition, columnWidth, 25), XStringFormats.Center)
gfx.DrawString("Growth", headingFont, XBrushes.Black, New XRect(margin + 2 * columnWidth, yPosition, columnWidth, 25), XStringFormats.Center)
' Table data
Dim data(,) As String = {
{ "January", "$50,000", "+12%" },
{ "February", "$55,000", "+10%" },
{ "March", "$60,000", "+9%" }
}
yPosition += 25
For i As Integer = 0 To 2
' Alternate row colors
If i Mod 2 = 0 Then
gfx.DrawRectangle(XBrushes.WhiteSmoke, margin, yPosition, page.Width - 2 * margin, 20)
End If
For j As Integer = 0 To 2
gfx.DrawString(data(i, j), normalFont, XBrushes.Black, New XRect(margin + j * columnWidth, yPosition, columnWidth, 20), XStringFormats.Center)
Next j
yPosition += 20
Next i
' Draw a simple line chart (very basic implementation)
yPosition += 40
gfx.DrawString("Revenue Trend", headingFont, XBrushes.Black, New XRect(margin, yPosition, page.Width - 2 * margin, 25), XStringFormats.TopLeft)
' Chart area
yPosition += 30
Dim chartHeight As Double = 150
Dim chartWidth As Double = page.Width - 2 * margin
' Draw axes
gfx.DrawLine(XPens.Black, margin, yPosition + chartHeight, margin + chartWidth, yPosition + chartHeight)
gfx.DrawLine(XPens.Black, margin, yPosition, margin, yPosition + chartHeight)
' Plot points (simplified)
Dim revenues() As Double = { 50000, 55000, 60000 }
Dim maxRevenue As Double = 65000
Dim xStep As Double = chartWidth / 3
For i As Integer = 0 To revenues.Length - 1
Dim x As Double = margin + (i + 0.5) * xStep
Dim y As Double = yPosition + chartHeight - (revenues(i) / maxRevenue * chartHeight)
' Draw point
gfx.DrawEllipse(XBrushes.Blue, x - 3, y - 3, 6, 6)
' Draw connecting lines
If i > 0 Then
Dim prevX As Double = margin + (i - 0.5) * xStep
Dim prevY As Double = yPosition + chartHeight - (revenues(i - 1) / maxRevenue * chartHeight)
gfx.DrawLine(New XPen(XColors.Blue, 2), prevX, prevY, x, y)
End If
' Labels
gfx.DrawString($"${revenues(i):N0}", normalFont, XBrushes.Black, New XRect(x - 30, y - 20, 60, 15), XStringFormats.TopCenter)
Next i
' Save the document
document.Save("pdfsharp-sales-report.pdf")
Console.WriteLine("PDF created with PDFSharpCore")
End Sub
End Class
보시다시피, PDFSharpCore로 중간 정도의 복잡성을 가진 문서를 작성하는 데에도 다음이 필요합니다:
- 각 요소의 수동 위치 지정
- 레이아웃을 위한 복잡한 계산
- HTML이나 CSS에 대한 내장 지원 없음
- 차트 및 그래픽의 수동 구현
- 동일한 결과를 위한 코드 양이 상당히 많음
PDFSharpCore로 HTML을 PDF로 변환
PDFSharpCore는 HTML을 PDF로 변환하는 것을 기본적으로 지원하지 않으므로 개발자는 서드파티 라이브러리를 사용해야 합니다. 인기있는 선택은 PDFSharpCore와 HtmlRenderer의 조합입니다:
using PdfSharpCore.Pdf;
using TheArtOfDev.HtmlRenderer.PdfSharp;
var document = new PdfDocument();
string htmlContent = File.ReadAllText("template.html");
// Note: HtmlRenderer has limited CSS support
PdfGenerator.AddPdfPages(document, htmlContent, PdfSharpCore.PageSize.A4);
document.Save("from-html.pdf");
using PdfSharpCore.Pdf;
using TheArtOfDev.HtmlRenderer.PdfSharp;
var document = new PdfDocument();
string htmlContent = File.ReadAllText("template.html");
// Note: HtmlRenderer has limited CSS support
PdfGenerator.AddPdfPages(document, htmlContent, PdfSharpCore.PageSize.A4);
document.Save("from-html.pdf");
Imports PdfSharpCore.Pdf
Imports TheArtOfDev.HtmlRenderer.PdfSharp
Private document = New PdfDocument()
Private htmlContent As String = File.ReadAllText("template.html")
' Note: HtmlRenderer has limited CSS support
PdfGenerator.AddPdfPages(document, htmlContent, PdfSharpCore.PageSize.A4)
document.Save("from-html.pdf")
그러나 이 접근 방식은 중대한 제한이 있습니다:
- 제한된 CSS3 지원 (대략 70-80% 호환성)
- JavaScript 실행 없음
- 현대 웹 기능의 취약한 처리
- 브라우저와 비교해 일관되지 않은 렌더링
모던 CSS 프레임워크 지원: 부트스트랩 및 그 이상
웹 콘텐츠에서 PDF 생성을 필요로 하는 애플리케이션 개발 시, 부트스트랩과 모던 CSS 프레임워크 지원은 필수적입니다. 대부분의 웹 애플리케이션은 일관된 디자인을 위해 이러한 프레임워크를 사용하며, 이러한 인터페이스를 수정 없이 PDF로 변환할 수 있는 능력은 개발 시간을 크게 줄여줍니다.
IronPDF: 전체 부트스트랩 및 CSS 프레임워크 지원
- 부트스트랩 5: 완전한 flexbox 레이아웃 엔진, CSS 그리드, 유틸리티 클래스 및 모든 구성 요소 시스템
- 부트스트랩 4: 전체 카드 구성 요소, 내비게이션, 플렉스 유틸리티, 반응형 클래스
- Tailwind CSS: 정확한 렌더링을 가진 모든 유틸리티 클래스
- 파운데이션: 완벽한 그리드 시스템 및 구성 요소 라이브러리
- 현대 CSS3: Flexbox, CSS Grid, 사용자 정의 속성, 애니메이션, 전환 및 변형
현실적인 증거: IronPDF는 부트스트랩 홈페이지와 모든 공식 템플릿을 픽셀 단위로 정확하게 렌더링합니다.
코드 예제: 프로젝트 진행 대시보드
using IronPdf;
// Set yourIronPDFlicense key
IronPdf.License.LicenseKey = "License-Key goes here";
var renderer = new ChromePdfRenderer();
string bootstrapProgress = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
<style>
.project-card {
transition: all 0.3s ease;
border-left: 4px solid transparent;
}
.project-card.active { border-left-color: #0d6efd; }
.progress-label { font-size: 0.75rem; font-weight: 600; }
</style>
</head>
<body>
<div class='container my-5'>
<div class='d-flex justify-content-between align-items-center mb-4'>
<div>
<h1 class='display-6 mb-1'>Project Portfolio Status</h1>
<p class='text-muted mb-0'>Q1 2025 Development Pipeline</p>
</div>
<div>
<span class='badge bg-success fs-6'>8 Active Projects</span>
</div>
</div>
<div class='row g-4 mb-4'>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-primary mb-2'>72%</div>
<h6 class='text-muted text-uppercase mb-0'>Overall Progress</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-success mb-2'>5</div>
<h6 class='text-muted text-uppercase mb-0'>On Track</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-warning mb-2'>2</div>
<h6 class='text-muted text-uppercase mb-0'>At Risk</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-danger mb-2'>1</div>
<h6 class='text-muted text-uppercase mb-0'>Delayed</h6>
</div>
</div>
</div>
</div>
<div class='card shadow-sm mb-4'>
<div class='card-header bg-primary text-white'>
<h5 class='mb-0'>Active Projects</h5>
</div>
<div class='card-body p-0'>
<div class='list-group list-group-flush'>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>E-Commerce Platform Redesign</h6>
<small class='text-muted'>Lead: Sarah Chen | Due: Apr 15, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-primary'>85%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-primary' role='progressbar' style='width: 85%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Frontend: 90%</span>
<span class='badge bg-light text-dark'>Backend: 80%</span>
<span class='badge bg-light text-dark'>Testing: 85%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Mobile App Integration</h6>
<small class='text-muted'>Lead: Marcus Johnson | Due: Mar 30, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-success'>92%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-success' role='progressbar' style='width: 92%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>iOS: 95%</span>
<span class='badge bg-light text-dark'>Android: 90%</span>
<span class='badge bg-light text-dark'>API: 100%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Customer Analytics Dashboard</h6>
<small class='text-muted'>Lead: Emily Rodriguez | Due: Apr 22, 2025</small>
</div>
<span class='badge bg-warning text-dark'>At Risk</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-warning'>58%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-warning' role='progressbar' style='width: 58%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Data Pipeline: 65%</span>
<span class='badge bg-light text-dark'>UI: 50%</span>
<span class='badge bg-light text-dark'>Reports: 45%</span>
</div>
<div class='alert alert-warning mt-2 mb-0 py-2'>
<small><strong>Issue:</strong> Resource constraints affecting timeline. Review scheduled for next week.</small>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Security Infrastructure Upgrade</h6>
<small class='text-muted'>Lead: David Kim | Due: Mar 25, 2025</small>
</div>
<span class='badge bg-danger'>Delayed</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-danger'>42%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-danger' role='progressbar' style='width: 42%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Authentication: 60%</span>
<span class='badge bg-light text-dark'>암호화: 40%</span>
<span class='badge bg-light text-dark'>Audit Logs: 25%</span>
</div>
<div class='alert alert-danger mt-2 mb-0 py-2'>
<small><strong>Critical:</strong> 7 days behind schedule. Additional resources allocated. Daily standup required.</small>
</div>
</div>
</div>
</div>
</div>
<div class='row g-4'>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Sprint Velocity</h5>
</div>
<div class='card-body'>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Current Sprint</span>
<strong>42 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-success' style='width: 84%'>84% Complete</div>
</div>
</div>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Previous Sprint</span>
<strong>38 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-info' style='width: 100%'>Completed</div>
</div>
</div>
<div class='mb-0'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Average Velocity</span>
<strong>40 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-primary' style='width: 100%'>Baseline</div>
</div>
</div>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Team Capacity</h5>
</div>
<div class='card-body'>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Frontend Team</h6>
<small class='text-muted'>6 developers</small>
</div>
<span class='badge bg-success'>92% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Backend Team</h6>
<small class='text-muted'>5 developers</small>
</div>
<span class='badge bg-success'>88% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>QA Team</h6>
<small class='text-muted'>3 testers</small>
</div>
<span class='badge bg-warning text-dark'>105% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-0'>
<div>
<h6 class='mb-0'>DevOps Team</h6>
<small class='text-muted'>2 engineers</small>
</div>
<span class='badge bg-danger'>110% Utilized</span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(bootstrapProgress);
pdf.SaveAs("project-progress.pdf");
using IronPdf;
// Set yourIronPDFlicense key
IronPdf.License.LicenseKey = "License-Key goes here";
var renderer = new ChromePdfRenderer();
string bootstrapProgress = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
<style>
.project-card {
transition: all 0.3s ease;
border-left: 4px solid transparent;
}
.project-card.active { border-left-color: #0d6efd; }
.progress-label { font-size: 0.75rem; font-weight: 600; }
</style>
</head>
<body>
<div class='container my-5'>
<div class='d-flex justify-content-between align-items-center mb-4'>
<div>
<h1 class='display-6 mb-1'>Project Portfolio Status</h1>
<p class='text-muted mb-0'>Q1 2025 Development Pipeline</p>
</div>
<div>
<span class='badge bg-success fs-6'>8 Active Projects</span>
</div>
</div>
<div class='row g-4 mb-4'>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-primary mb-2'>72%</div>
<h6 class='text-muted text-uppercase mb-0'>Overall Progress</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-success mb-2'>5</div>
<h6 class='text-muted text-uppercase mb-0'>On Track</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-warning mb-2'>2</div>
<h6 class='text-muted text-uppercase mb-0'>At Risk</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-danger mb-2'>1</div>
<h6 class='text-muted text-uppercase mb-0'>Delayed</h6>
</div>
</div>
</div>
</div>
<div class='card shadow-sm mb-4'>
<div class='card-header bg-primary text-white'>
<h5 class='mb-0'>Active Projects</h5>
</div>
<div class='card-body p-0'>
<div class='list-group list-group-flush'>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>E-Commerce Platform Redesign</h6>
<small class='text-muted'>Lead: Sarah Chen | Due: Apr 15, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-primary'>85%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-primary' role='progressbar' style='width: 85%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Frontend: 90%</span>
<span class='badge bg-light text-dark'>Backend: 80%</span>
<span class='badge bg-light text-dark'>Testing: 85%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Mobile App Integration</h6>
<small class='text-muted'>Lead: Marcus Johnson | Due: Mar 30, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-success'>92%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-success' role='progressbar' style='width: 92%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>iOS: 95%</span>
<span class='badge bg-light text-dark'>Android: 90%</span>
<span class='badge bg-light text-dark'>API: 100%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Customer Analytics Dashboard</h6>
<small class='text-muted'>Lead: Emily Rodriguez | Due: Apr 22, 2025</small>
</div>
<span class='badge bg-warning text-dark'>At Risk</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-warning'>58%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-warning' role='progressbar' style='width: 58%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Data Pipeline: 65%</span>
<span class='badge bg-light text-dark'>UI: 50%</span>
<span class='badge bg-light text-dark'>Reports: 45%</span>
</div>
<div class='alert alert-warning mt-2 mb-0 py-2'>
<small><strong>Issue:</strong> Resource constraints affecting timeline. Review scheduled for next week.</small>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Security Infrastructure Upgrade</h6>
<small class='text-muted'>Lead: David Kim | Due: Mar 25, 2025</small>
</div>
<span class='badge bg-danger'>Delayed</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-danger'>42%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-danger' role='progressbar' style='width: 42%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Authentication: 60%</span>
<span class='badge bg-light text-dark'>암호화: 40%</span>
<span class='badge bg-light text-dark'>Audit Logs: 25%</span>
</div>
<div class='alert alert-danger mt-2 mb-0 py-2'>
<small><strong>Critical:</strong> 7 days behind schedule. Additional resources allocated. Daily standup required.</small>
</div>
</div>
</div>
</div>
</div>
<div class='row g-4'>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Sprint Velocity</h5>
</div>
<div class='card-body'>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Current Sprint</span>
<strong>42 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-success' style='width: 84%'>84% Complete</div>
</div>
</div>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Previous Sprint</span>
<strong>38 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-info' style='width: 100%'>Completed</div>
</div>
</div>
<div class='mb-0'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Average Velocity</span>
<strong>40 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-primary' style='width: 100%'>Baseline</div>
</div>
</div>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Team Capacity</h5>
</div>
<div class='card-body'>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Frontend Team</h6>
<small class='text-muted'>6 developers</small>
</div>
<span class='badge bg-success'>92% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Backend Team</h6>
<small class='text-muted'>5 developers</small>
</div>
<span class='badge bg-success'>88% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>QA Team</h6>
<small class='text-muted'>3 testers</small>
</div>
<span class='badge bg-warning text-dark'>105% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-0'>
<div>
<h6 class='mb-0'>DevOps Team</h6>
<small class='text-muted'>2 engineers</small>
</div>
<span class='badge bg-danger'>110% Utilized</span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(bootstrapProgress);
pdf.SaveAs("project-progress.pdf");
Imports IronPdf
' Set your IronPDF license key
IronPdf.License.LicenseKey = "License-Key goes here"
Dim renderer As New ChromePdfRenderer()
Dim bootstrapProgress As String = "
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
<style>
.project-card {
transition: all 0.3s ease;
border-left: 4px solid transparent;
}
.project-card.active { border-left-color: #0d6efd; }
.progress-label { font-size: 0.75rem; font-weight: 600; }
</style>
</head>
<body>
<div class='container my-5'>
<div class='d-flex justify-content-between align-items-center mb-4'>
<div>
<h1 class='display-6 mb-1'>Project Portfolio Status</h1>
<p class='text-muted mb-0'>Q1 2025 Development Pipeline</p>
</div>
<div>
<span class='badge bg-success fs-6'>8 Active Projects</span>
</div>
</div>
<div class='row g-4 mb-4'>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-primary mb-2'>72%</div>
<h6 class='text-muted text-uppercase mb-0'>Overall Progress</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-success mb-2'>5</div>
<h6 class='text-muted text-uppercase mb-0'>On Track</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-warning mb-2'>2</div>
<h6 class='text-muted text-uppercase mb-0'>At Risk</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-danger mb-2'>1</div>
<h6 class='text-muted text-uppercase mb-0'>Delayed</h6>
</div>
</div>
</div>
</div>
<div class='card shadow-sm mb-4'>
<div class='card-header bg-primary text-white'>
<h5 class='mb-0'>Active Projects</h5>
</div>
<div class='card-body p-0'>
<div class='list-group list-group-flush'>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>E-Commerce Platform Redesign</h6>
<small class='text-muted'>Lead: Sarah Chen | Due: Apr 15, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-primary'>85%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-primary' role='progressbar' style='width: 85%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Frontend: 90%</span>
<span class='badge bg-light text-dark'>Backend: 80%</span>
<span class='badge bg-light text-dark'>Testing: 85%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Mobile App Integration</h6>
<small class='text-muted'>Lead: Marcus Johnson | Due: Mar 30, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-success'>92%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-success' role='progressbar' style='width: 92%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>iOS: 95%</span>
<span class='badge bg-light text-dark'>Android: 90%</span>
<span class='badge bg-light text-dark'>API: 100%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Customer Analytics Dashboard</h6>
<small class='text-muted'>Lead: Emily Rodriguez | Due: Apr 22, 2025</small>
</div>
<span class='badge bg-warning text-dark'>At Risk</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-warning'>58%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-warning' role='progressbar' style='width: 58%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Data Pipeline: 65%</span>
<span class='badge bg-light text-dark'>UI: 50%</span>
<span class='badge bg-light text-dark'>Reports: 45%</span>
</div>
<div class='alert alert-warning mt-2 mb-0 py-2'>
<small><strong>Issue:</strong> Resource constraints affecting timeline. Review scheduled for next week.</small>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Security Infrastructure Upgrade</h6>
<small class='text-muted'>Lead: David Kim | Due: Mar 25, 2025</small>
</div>
<span class='badge bg-danger'>Delayed</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-danger'>42%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-danger' role='progressbar' style='width: 42%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Authentication: 60%</span>
<span class='badge bg-light text-dark'>암호화: 40%</span>
<span class='badge bg-light text-dark'>Audit Logs: 25%</span>
</div>
<div class='alert alert-danger mt-2 mb-0 py-2'>
<small><strong>Critical:</strong> 7 days behind schedule. Additional resources allocated. Daily standup required.</small>
</div>
</div>
</div>
</div>
</div>
<div class='row g-4'>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Sprint Velocity</h5>
</div>
<div class='card-body'>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Current Sprint</span>
<strong>42 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-success' style='width: 84%'>84% Complete</div>
</div>
</div>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Previous Sprint</span>
<strong>38 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-info' style='width: 100%'>Completed</div>
</div>
</div>
<div class='mb-0'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Average Velocity</span>
<strong>40 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-primary' style='width: 100%'>Baseline</div>
</div>
</div>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Team Capacity</h5>
</div>
<div class='card-body'>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Frontend Team</h6>
<small class='text-muted'>6 developers</small>
</div>
<span class='badge bg-success'>92% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Backend Team</h6>
<small class='text-muted'>5 developers</small>
</div>
<span class='badge bg-success'>88% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>QA Team</h6>
<small class='text-muted'>3 testers</small>
</div>
<span class='badge bg-warning text-dark'>105% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-0'>
<div>
<h6 class='mb-0'>DevOps Team</h6>
<small class='text-muted'>2 engineers</small>
</div>
<span class='badge bg-danger'>110% Utilized</span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>"
Dim pdf = renderer.RenderHtmlAsPdf(bootstrapProgress)
pdf.SaveAs("project-progress.pdf")
출력: 부트스트랩 5의 플렉스박스 기반 레이아웃, 진행 바 구성 요소, 배지 유틸리티, 반응형 카드 시스템, 경고 구성 요소가 포함된 전문적인 프로젝트 관리 PDF — 모든 것이 완벽한 정렬, 간격, 색상 정확도로 렌더링됩니다.
PDFSharpCore: 내장 HTML 지원 없음
PDFSharpCore는 내장 HTML 렌더링 엔진이 없습니다. 이 라이브러리는 저수준의 PDF 조작 및 그리기 작업 전용으로 설계되었습니다:
- 부트스트랩 지원 없음: HTML/CSS 프레임워크를 전혀 처리할 수 없음
- 플렉스박스 또는 CSS Grid 없음: 모든 CSS 렌더링 기능 부재
- 수동 구성만 가능: 좌표 기반 API를 사용해 텍스트, 도형 및 이미지를 그려야 함
- 외부 도구 필요: 서드파티 HTML 렌더러 또는 변환 서비스를 사용해야 함
HtmlRenderer 통합 (서드파티)은 기본 HTML 지원만 제공하며 심각한 제한이 있습니다—대략 70-80% CSS3 호환성, 플렉스박스 없음, CSS Grid 없음, 최신 프레임워크 지원 없음.
개발 영향: 팀은 HTML 기반의 워크플로를 완전히 포기하거나 여러 도구(PDFSharpCore + 외부 HTML 렌더러)를 통합해야 하며, 이는 복잡성, 유지 관리 부담, 라이브러리 버전 간 호환성 문제를 추가합니다.
자세한 부트스트랩 프레임워크 호환성과 CSS3 렌더링 기능은 부트스트랩 & 플렉스박스 CSS 가이드를 참조하십시오.
고급 기능 비교
텍스트 추출
가장 일반적인 PDF 작업 중 하나는 인덱싱, 분석 또는 변환을 위한 텍스트 추출입니다. 두 라이브러리가 이 작업을 처리하는 방법은 다음과 같습니다:
IronPDF텍스트 추출
IronPDF는 간단한 API로 강력한 텍스트 추출 기능을 제공합니다:
using IronPdf;
// Extract all text from a PDF
var pdf = PdfDocument.FromFile("report.pdf");
string allText = pdf.ExtractAllText();
// Extract text from specific pages
for (int i = 0; i < pdf.PageCount; i++)
{
string pageText = pdf.ExtractTextFromPage(i);
Console.WriteLine($"Page {i + 1}: {pageText.Substring(0, Math.Min(100, pageText.Length))}...");
}
// Extract text from a specific region
var pageIndex = 0;
var region = new Rectangle(50, 50, 200, 100); // x, y, width, height
string regionText = pdf.ExtractTextFromPage(pageIndex, region);
using IronPdf;
// Extract all text from a PDF
var pdf = PdfDocument.FromFile("report.pdf");
string allText = pdf.ExtractAllText();
// Extract text from specific pages
for (int i = 0; i < pdf.PageCount; i++)
{
string pageText = pdf.ExtractTextFromPage(i);
Console.WriteLine($"Page {i + 1}: {pageText.Substring(0, Math.Min(100, pageText.Length))}...");
}
// Extract text from a specific region
var pageIndex = 0;
var region = new Rectangle(50, 50, 200, 100); // x, y, width, height
string regionText = pdf.ExtractTextFromPage(pageIndex, region);
Imports IronPdf
' Extract all text from a PDF
Private pdf = PdfDocument.FromFile("report.pdf")
Private allText As String = pdf.ExtractAllText()
' Extract text from specific pages
For i As Integer = 0 To pdf.PageCount - 1
Dim pageText As String = pdf.ExtractTextFromPage(i)
Console.WriteLine($"Page {i + 1}: {pageText.Substring(0, Math.Min(100, pageText.Length))}...")
Next i
' Extract text from a specific region
Dim pageIndex = 0
Dim region = New Rectangle(50, 50, 200, 100) ' x, y, width, height
Dim regionText As String = pdf.ExtractTextFromPage(pageIndex, region)
PDFSharpCore텍스트 추출
PDFSharpCore는 제한된 내장 텍스트 추출 기능을 가지고 있습니다. 비교 기사에서 언급된 바와 같이, 종종 단편적이거나 불완전한 결과를 생성합니다:
//PDFSharpCoredoesn't have reliable text extraction
// This is a significant limitation for many use cases
//PDFSharpCoredoesn't have reliable text extraction
// This is a significant limitation for many use cases
'PDFSharpCore doesn't have reliable text extraction
' This is a significant limitation for many use cases
워터마킹
PDF 워터마킹은 브랜딩과 문서 보안을 위해 필수적입니다.
IronPDF워터마킹
using IronPdf;
var pdf = PdfDocument.FromFile("document.pdf");
// HTML-based watermark with full CSS support
string watermarkHtml = @"
<div style='
font-size: 48px;
color: rgba(255, 0, 0, 0.3);
transform: rotate(-45deg);
text-align: center;
font-weight: bold;
'>
CONFIDENTIAL
</div>";
pdf.ApplyWatermark(watermarkHtml, 50, VerticalAlignment.Middle, HorizontalAlignment.Center);
// Image watermark
pdf.ApplyWatermark("logo.png", 30, VerticalAlignment.Bottom, HorizontalAlignment.Right);
pdf.SaveAs("watermarked.pdf");
using IronPdf;
var pdf = PdfDocument.FromFile("document.pdf");
// HTML-based watermark with full CSS support
string watermarkHtml = @"
<div style='
font-size: 48px;
color: rgba(255, 0, 0, 0.3);
transform: rotate(-45deg);
text-align: center;
font-weight: bold;
'>
CONFIDENTIAL
</div>";
pdf.ApplyWatermark(watermarkHtml, 50, VerticalAlignment.Middle, HorizontalAlignment.Center);
// Image watermark
pdf.ApplyWatermark("logo.png", 30, VerticalAlignment.Bottom, HorizontalAlignment.Right);
pdf.SaveAs("watermarked.pdf");
Imports IronPdf
Private pdf = PdfDocument.FromFile("document.pdf")
' HTML-based watermark with full CSS support
Private watermarkHtml As String = "
<div style='
font-size: 48px;
color: rgba(255, 0, 0, 0.3);
transform: rotate(-45deg);
text-align: center;
font-weight: bold;
'>
CONFIDENTIAL
</div>"
pdf.ApplyWatermark(watermarkHtml, 50, VerticalAlignment.Middle, HorizontalAlignment.Center)
' Image watermark
pdf.ApplyWatermark("logo.png", 30, VerticalAlignment.Bottom, HorizontalAlignment.Right)
pdf.SaveAs("watermarked.pdf")
PDFSharpCore워터마킹
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
var document = PdfReader.Open("document.pdf", PdfDocumentOpenMode.Modify);
foreach (var page in document.Pages)
{
var gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append);
// Create watermark font
var font = new XFont("Arial", 48);
// Calculate rotation
gfx.TranslateTransform(page.Width / 2, page.Height / 2);
gfx.RotateTransform(-45);
// Draw watermark
var size = gfx.MeasureString("CONFIDENTIAL", font);
gfx.DrawString("CONFIDENTIAL", font,
new XSolidBrush(XColor.FromArgb(128, 255, 0, 0)),
new XRect(-size.Width / 2, -size.Height / 2, size.Width, size.Height),
XStringFormats.Center);
}
document.Save("watermarked-pdfsharp.pdf");
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
var document = PdfReader.Open("document.pdf", PdfDocumentOpenMode.Modify);
foreach (var page in document.Pages)
{
var gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append);
// Create watermark font
var font = new XFont("Arial", 48);
// Calculate rotation
gfx.TranslateTransform(page.Width / 2, page.Height / 2);
gfx.RotateTransform(-45);
// Draw watermark
var size = gfx.MeasureString("CONFIDENTIAL", font);
gfx.DrawString("CONFIDENTIAL", font,
new XSolidBrush(XColor.FromArgb(128, 255, 0, 0)),
new XRect(-size.Width / 2, -size.Height / 2, size.Width, size.Height),
XStringFormats.Center);
}
document.Save("watermarked-pdfsharp.pdf");
Imports PdfSharpCore.Drawing
Imports PdfSharpCore.Pdf
Imports PdfSharpCore.Pdf.IO
Private document = PdfReader.Open("document.pdf", PdfDocumentOpenMode.Modify)
For Each page In document.Pages
Dim gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append)
' Create watermark font
Dim font = New XFont("Arial", 48)
' Calculate rotation
gfx.TranslateTransform(page.Width \ 2, page.Height \ 2)
gfx.RotateTransform(-45)
' Draw watermark
Dim size = gfx.MeasureString("CONFIDENTIAL", font)
gfx.DrawString("CONFIDENTIAL", font, New XSolidBrush(XColor.FromArgb(128, 255, 0, 0)), New XRect(-size.Width \ 2, -size.Height \ 2, size.Width, size.Height), XStringFormats.Center)
Next page
document.Save("watermarked-pdfsharp.pdf")
디지털 서명
디지털 서명은 문서 진위성과 무결성을 보장합니다.
IronPDF디지털 서명
using IronPdf;
using IronPdf.Signing;
var pdf = PdfDocument.FromFile("contract.pdf");
// Create a signature with certificate
var signature = new PdfSignature("certificate.pfx", "password")
{
SigningContact = "legal@company.com",
SigningLocation = "New York, NY",
SigningReason = "Contract Approval"
};
// Add visual signature
var signatureImage = new PdfSignature("certificate.pfx", "password")
{
SignatureImage = new PdfSignatureImage("signature.png", 0, 0, 200, 100)
};
// Apply signature to the last page
pdf.Sign(signature);
pdf.SaveAs("signed-contract.pdf");
using IronPdf;
using IronPdf.Signing;
var pdf = PdfDocument.FromFile("contract.pdf");
// Create a signature with certificate
var signature = new PdfSignature("certificate.pfx", "password")
{
SigningContact = "legal@company.com",
SigningLocation = "New York, NY",
SigningReason = "Contract Approval"
};
// Add visual signature
var signatureImage = new PdfSignature("certificate.pfx", "password")
{
SignatureImage = new PdfSignatureImage("signature.png", 0, 0, 200, 100)
};
// Apply signature to the last page
pdf.Sign(signature);
pdf.SaveAs("signed-contract.pdf");
Imports IronPdf
Imports IronPdf.Signing
Private pdf = PdfDocument.FromFile("contract.pdf")
' Create a signature with certificate
Private signature = New PdfSignature("certificate.pfx", "password") With {
.SigningContact = "legal@company.com",
.SigningLocation = "New York, NY",
.SigningReason = "Contract Approval"
}
' Add visual signature
Private signatureImage = New PdfSignature("certificate.pfx", "password") With {.SignatureImage = New PdfSignatureImage("signature.png", 0, 0, 200, 100)}
' Apply signature to the last page
pdf.Sign(signature)
pdf.SaveAs("signed-contract.pdf")
PDFSharpCore디지털 서명
PDFSharpCore는 내장 디지털 서명을 지원하지 않으며, 이는 문서 보안을 요구하는 비즈니스 애플리케이션에 중요한 제한 사항입니다.
폼 처리
PDF 폼 작업은 상호작용 문서에서 중요합니다.
IronPDF폼 처리
using IronPdf;
// Create a form from HTML
var html = @"
<form>
<label>Name: <input type='text' name='fullName' required></label><br>
<label>Email: <input type='email' name='email' required></label><br>
<label>Subscribe: <input type='checkbox' name='subscribe' value='yes'></label><br>
<label>
Plan:
<select name='plan'>
<option value='basic'>Basic</option>
<option value='pro'>Professional</option>
<option value='enterprise'>Enterprise</option>
</select>
</label>
</form>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Fill existing form
var filledPdf = PdfDocument.FromFile("application-form.pdf");
filledPdf.Form.FindFormField("fullName").Value = "John Doe";
filledPdf.Form.FindFormField("email").Value = "john@example.com";
filledPdf.Form.FindFormField("subscribe").Value = "yes";
filledPdf.SaveAs("completed-application.pdf");
using IronPdf;
// Create a form from HTML
var html = @"
<form>
<label>Name: <input type='text' name='fullName' required></label><br>
<label>Email: <input type='email' name='email' required></label><br>
<label>Subscribe: <input type='checkbox' name='subscribe' value='yes'></label><br>
<label>
Plan:
<select name='plan'>
<option value='basic'>Basic</option>
<option value='pro'>Professional</option>
<option value='enterprise'>Enterprise</option>
</select>
</label>
</form>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Fill existing form
var filledPdf = PdfDocument.FromFile("application-form.pdf");
filledPdf.Form.FindFormField("fullName").Value = "John Doe";
filledPdf.Form.FindFormField("email").Value = "john@example.com";
filledPdf.Form.FindFormField("subscribe").Value = "yes";
filledPdf.SaveAs("completed-application.pdf");
Imports IronPdf
' Create a form from HTML
Private html = "
<form>
<label>Name: <input type='text' name='fullName' required></label><br>
<label>Email: <input type='email' name='email' required></label><br>
<label>Subscribe: <input type='checkbox' name='subscribe' value='yes'></label><br>
<label>
Plan:
<select name='plan'>
<option value='basic'>Basic</option>
<option value='pro'>Professional</option>
<option value='enterprise'>Enterprise</option>
</select>
</label>
</form>"
Private renderer = New ChromePdfRenderer()
Private pdf = renderer.RenderHtmlAsPdf(html)
' Fill existing form
Private filledPdf = PdfDocument.FromFile("application-form.pdf")
filledPdf.Form.FindFormField("fullName").Value = "John Doe"
filledPdf.Form.FindFormField("email").Value = "john@example.com"
filledPdf.Form.FindFormField("subscribe").Value = "yes"
filledPdf.SaveAs("completed-application.pdf")
성능 벤치마크
광범위한 테스트 및 커뮤니티 피드백을 기반으로 한 성능 비교는 다음과 같습니다:
HTML을 PDF로 렌더링
| 시험 사례 | IronPDF | PDFSharpCore (with HtmlRenderer) |
|---|---|---|
| 단순 HTML (1 페이지) | 0.8-1.2s | 0.3-0.5s |
| 복잡한 HTML과 CSS3 | 1.5-2초 | 종종 실패하거나 잘못 렌더링됨 |
| JavaScript 차트 | 2-3초 | 지원되지 않음 |
| 100페이지 보고서 | 15-20초 | 45-60초 |
| 메모리 사용량 | 150-200MB | 80-120MB |
핵심 성능 인사이트
-
IronPDF는 다음에서 뛰어납니다:
- 전체 브라우저 호환성을 갖춘 복잡한 HTML 렌더링
- 배치 작업을 위한 병렬 처리
- 다양한 콘텐츠 유형에서 일관된 성능
- 더 나은 확장성을 위한 비동기 작업
- PDFSharpCore는 다음에 더 적합합니다:
- 간단한 프로그래밍 가능한 PDF 생성
- 낮은 메모리 사용량
- 기본적인 문서 수정
실제 성능 예시
//IronPDF- Batch processing with parallel execution
using IronPdf;
using System.Threading.Tasks;
class BatchProcessor
{
public static async Task ProcessInvoicesAsync(List<string> htmlInvoices)
{
var renderer = new ChromePdfRenderer();
// Process multiple PDFs in parallel
var tasks = htmlInvoices.Select(async (html, index) =>
{
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
await pdf.SaveAsAsync($"invoice-{index}.pdf");
});
await Task.WhenAll(tasks);
}
}
//IronPDF- Batch processing with parallel execution
using IronPdf;
using System.Threading.Tasks;
class BatchProcessor
{
public static async Task ProcessInvoicesAsync(List<string> htmlInvoices)
{
var renderer = new ChromePdfRenderer();
// Process multiple PDFs in parallel
var tasks = htmlInvoices.Select(async (html, index) =>
{
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
await pdf.SaveAsAsync($"invoice-{index}.pdf");
});
await Task.WhenAll(tasks);
}
}
Imports IronPdf
Imports System.Threading.Tasks
Class BatchProcessor
Public Shared Async Function ProcessInvoicesAsync(htmlInvoices As List(Of String)) As Task
Dim renderer = New ChromePdfRenderer()
' Process multiple PDFs in parallel
Dim tasks = htmlInvoices.Select(Function(html, index) _
Async Function()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Await pdf.SaveAsAsync($"invoice-{index}.pdf")
End Function)
Await Task.WhenAll(tasks)
End Function
End Class
실제 활용 사례
언제 IronPDF를 선택해야 하나요
IronPDF는 다음에 이상적입니다:
-
웹 애플리케이션 통합
- 동적 웹 콘텐츠를 PDF로 변환
- 웹 대시보드에서 보고서 생성
- HTML 템플릿에서 송장 작성
-
기업 문서 관리
- 디지털 서명을 통한 문서 워크플로 구현
- 민감한 데이터를 위한 안전하고 암호화된 PDF 생성
- 대량의 문서 일괄 처리
-
SaaS 애플리케이션
- 멀티 테넌트 PDF 생성
- Azure/AWS 상의 클라우드 네이티브 배포
- 고성능 비동기 처리
- 복잡한 보고
- 차트와 그래프가 포함된 재무 보고서
- 풍부한 미디어가 포함된 마케팅 자료
- 코드 하이라이팅이 포함된 기술 문서
PDFSharpCore를 선택할 때
PDFSharpCore는 다음에 적합합니다:
-
예산 긴축 프로젝트
- 라이선스 예산이 없는 오픈 소스 프로젝트
- 간단한 PDF 생성 요구
- 학술 또는 개인 프로젝트
-
기본 PDF 작업
- 간단한 텍스트 기반 PDF 생성
- 기본적인 문서 병합
- 간단한 그래픽 또는 도형 추가
- 경량 애플리케이션
- 메모리 제약이 있는 임베디드 시스템
- 간단한 명령줄 도구
- 최소한의 종속성을 가진 마이크로서비스
라이선스 및 가격
IronPDF라이선싱
IronPDF는 유연한 라이선스를 제공합니다 (2025년 가격 기준):
- Lite License: $799 (개발자 1명, 위치 1곳, 프로젝트 1개)
- Plus License: $1,199 (개발자 3명, 위치 3곳, 프로젝트 3개)
- Professional License: $2,399 (개발자 10명, 위치 10곳, 프로젝트 10개)
- 무료 체험판: 30일 완전 기능 체험판
추가 혜택:
- 영구 라이선스 (일회성 구매)
- 로열티 없는 재배포 가능
- 24/5 엔지니어링 지원 포함
- 1년간 무료 업데이트
- 추가 절약을 위한 Iron Suite 번들 사용 가능
PDFSharpCore라이선싱
PDFSharpCore는 MIT 라이선스 하에 완전히 무료입니다:
- 라이선스 비용 없음
- 상업적 사용 제한 없음
- 커뮤니티 지원만 제공
- 업데이트나 버그 수정 보증 없음
개발자 경험
문서화 및 리소스
IronPDF는 다음을 제공합니다:
PDFSharpCore는 다음을 제공합니다:
- 기본 GitHub 문서
- 커뮤니티 예제
- 제한된 공식 튜토리얼
지원 비교
| 지원 유형 | IronPDF | PDFSharpCore |
|---|---|---|
| 전문 지원 | 24/5 포함 | 없음 |
| 응답 시간 | 24-48시간 | 커뮤니티 의존 |
| 직접 엔지니어링 접근 | 예 | 아니요 |
| 버그 수정 보증 | 예 | 아니요 |
결론
.NET PDF 생태계에서 IronPDF와PDFSharpCore모두 중요한 역할을 하지만, 각기 다른 필요와 사용 사례를 대상으로 합니다.
다음과 같은 경우 IronPDF를 선택하세요:
- 전체 CSS3 및 JavaScript 지원을 포함한 강력한 HTML to PDF 변환이 필요합니다
- 디지털 서명, 암호화, 또는 폼 처리와 같은 고급 기능이 필요한 프로젝트
- Enterprise 또는 상업용 애플리케이션을 구축하고 있습니다
- 포괄적인 문서와 전문 지원을 중요하게 생각합니다
- 성능과 신뢰성이 중요합니다
- 클라우드 준비 배포 옵션이 필요합니다
PDFSharpCore를 선택할 때:
- 예산 제약 또는 오픈 소스 프로젝트에서 작업 중입니다
- PDF 요구사항이 간단하고 HTML 렌더링이 필요하지 않습니다 PDF 구성에 대해 수동 제어를 선호합니다 메모리 사용량이 중요한 문제입니다 커뮤니티 지원에 대한 경험이 있습니다
현대적인 PDF 생성 접근 방식과 광범위한 기능 세트, 우수한 지원을 갖춘 IronPDF는 대부분의 전문 응용 프로그램에 탁월한 선택입니다. 라이선스 투자가 필요하지만 개발 시간 절약과 신뢰성 향상으로 인해 상업 프로젝트에 대한 비용을 정당화할 수 있습니다.
차이를 직접 경험해 볼 준비가 되셨나요? IronPDF의 30일 무료 체험판을 시작하고 PDF 생성 워크플로우를 어떻게 변혁할 수 있는지 확인하세요. 포괄적인 문서, 응답성 높은 지원, 기능이 풍부한 API로 IronPDF는 개발자가 최소한의 노력으로 전문 PDF를 만들 수 있게 합니다.
!{--01001100010010010100001001010010010000010101001001011001010111110100011101000101010101000101111101010011010101000100000101010100100101010001000101111101010111010010010101010000010111110101010000010 10010010011110100010001010101010000110101010001011111010100010100100100100100101000001010011000101111101000101010110000101010001010100111001000100010001010100111110100001001001001100010011110100001001001100010011110100001101001011--}
자주 묻는 질문
C#에서 HTML을 PDF로 변환하는 방법은 무엇인가요?
IronPDF의 RenderHtmlAsPdf 메서드를 사용하여 HTML 문자열을 PDF로 변환할 수 있습니다. 이 메서드는 전체 CSS3 및 JavaScript 실행을 지원하여 높은 충실도의 렌더링을 보장합니다.
IronPDF와 PDFSharpCore의 주요 차이점은 무엇입니까?
IronPDF는 HTML에서 PDF 변환, 디지털 서명, 클라우드 플랫폼 최적화와 같은 고급 기능을 가진 상용 라이브러리입니다. PDFSharpCore는 오픈 소스로, 수동 그리기 명령을 통해 기본적인 PDF 생성에 중점을 두며, 네이티브 HTML에서 PDF 변환이 없습니다.
이러한 라이브러리를 사용하여 PDF에서 텍스트를 추출할 수 있습니까?
IronPDF는 ExtractAllText() 및 ExtractTextFromPage()와 같은 방법을 통해 문서 구조를 유지하면서 강력한 텍스트 추출 기능을 제공합니다. PDFSharpCore는 제한된 텍스트 추출 기능을 제공하며, 종종 조각난 결과를 초래합니다.
C#에서 PDF에 디지털 서명을 추가하는 가장 좋은 방법은 무엇입니까?
IronPDF는 디지털 서명 지원을 포괄적으로 제공하며, 시각적 서명과 인증서 사용을 포함합니다. PDF 서명을 위한 사용자 정의 가능한 옵션을 제공하여 안전한 문서 워크플로에 적합합니다.
HTML 렌더링 속도 측면에서 이러한 라이브러리들이 어떻게 수행됩니까?
IronPDF는 종종 복잡한 HTML을 PDF로 약 0.8-2초 안에 렌더링하며, 전체 CSS3 및 JavaScript 지원을 포함합니다. PDFSharpCore는 간단한 프로그래밍 PDF 생성에는 더 빠르지만 현대적인 웹 기술을 지원하지 않아 렌더링 기능에 영향을 미칩니다.
PDF 라이브러리를 평가할 수 있는 체험판이 있습니까?
IronPDF는 30일 무료 체험판을 제공하여, HTML에서 PDF 변환을 포함한 모든 기능을 탐색할 수 있습니다. PDFSharpCore는 MIT 라이선스 하에 무료로 제공되어 기본 기능을 제공하며 체험판은 없습니다.
PDF 폼을 처리하기 위해 더 적합한 라이브러리는 무엇입니까?
IronPDF는 HTML에서 폼을 만들고 채우고 폼 데이터를 추출할 수 있는 기능을 갖추어 폼 처리에 뛰어납니다. PDFSharpCore는 기본적인 폼 처리를 지원하지만 수동 필드 생성이 필요하며 동일한 자동화 수준을 제공하지 않습니다.
각 라이브러리는 크로스 플랫폼 개발을 어떻게 지원합니까?
IronPDF와 PDFSharpCore는 모두 Windows, Linux 및 macOS를 지원합니다. IronPDF는 Azure 및 AWS와 같은 클라우드 플랫폼에 최적화된 구성을 갖추고 있지만, PDFSharpCore는 클라우드 환경을 위한 추가 설정이 필요할 수 있습니다.
이러한 라이브러리로 어떤 종류의 지원을 기대할 수 있습니까?
IronPDF는 24-48시간의 응답 시간을 갖춘 24/5 전문 엔지니어링 지원과 자세한 문서를 제공합니다. PDFSharpCore는 포럼과 GitHub을 통한 커뮤니티 지원에 의존하며, 응답 시간이 보장되지 않습니다.
복잡한 PDF 작업의 성능 처리 측면에서 각 라이브러리는 어떻게 수행됩니까?
IronPDF는 복잡한 HTML 렌더링을 처리하고 대량 작업을 위한 병렬 처리를 지원하여 우수한 처리량을 제공합니다. PDFSharpCore는 간단한 문서에 대해 메모리 효율성에서 장점을 보이지만, 고급 렌더링 기능은 부족합니다.



