이 페이지에는 자동 번역된 텍스트가 포함될 수 있습니다.
C# 및 VB.NET으로 PDF 문서를 만드는 방법
이 글에서는 Docotic.Pdf 라이브러리를 사용하여 .NET에서 PDF 문서를 생성하는 다양한 방법을 설명합니다. Docotic.Pdf는 외부 종속성 없이 PDF 문서를 생성, 편집, 변환 및 처리하는 고성능 순수 C# .NET 라이브러리입니다.

다음 섹션에서는 Docotic.Pdf를 사용하여 PDF를 생성하는 주요 방법을 소개합니다.
- 코어 API 사용: 텍스트, 그래픽 및 PDF 내부 구조에 대한 저수준 제어를 제공합니다. 이 옵션은 사용자 지정 레이아웃, 그래픽이 많은 문서 및 고급 기능에 가장 적합합니다.
- 단락, 표, 머리글, 바닥글 및 자동 페이지 매김을 지원하는 상위 수준 Layout API를 사용합니다. 이 API는 수동으로 위치를 계산하지 않고 구조화된 문서를 만들고자 할 때 이상적입니다.
- SVG 및 기타 웹 형식을 지원하는 HTML을 PDF로 변환: 솔루션에서 이미 HTML 문서를 생성하고 해당 HTML 및 CSS 파일의 PDF 버전이 필요한 경우 특히 유용합니다.
- 이미지에서 PDF 생성: 스캔 문서, 이미지 기반 보고서, 영수증 및 래스터 이미지로 시작하는 모든 워크플로에 유용합니다.
- PDF 병합 또는 분할: 보고서 작성, 사용자 업로드 처리, 관련 문서 결합 및 대용량 PDF 재구성에 적합합니다.
- 템플릿에서 PDF 생성. 이 방법은 영수증, 세금 신고서, 고용 계약서 및 기타 반복적인 문서 유형과 같이 일괄적으로 생성되는 문서에 일관된 서식이 필요한 경우에 효과적입니다.
이 가이드에서 다루는 추가 주제는 다음과 같습니다.
- 링크 및 JavaScript 액션과 같은 대화형 기능
- 예상 결과가 나오는지 확인하기 위한 PDF 출력 테스트 방법
코어 API를 사용하여 PDF 생성하기
Docotic.Pdf의 핵심 API는 PDF 생성의 기반이 됩니다. 이 API는 Canvas API를 통해 PDF 캔버스에 텍스트, 이미지, 벡터 그래픽을 배치하는 데 필요한 모든 기능을 저수준에서 제어할 수 있도록 해줍니다. Canvas API는 핵심 API의 하위 집합으로, 페이지 및 캔버스를 가진 다른 객체에 콘텐츠를 추가하는 데 사용되는 메서드와 속성을 제공합니다. 핵심 API는 렌더링 외에도 주석, 폼 필드, 레이어, 책갈피 및 기타 PDF 기능을 지원합니다.
다음은 텍스트 그리기, 이미지 배치, 벡터 그래픽 렌더링이라는 세 가지 기본 작업을 사용하여 간단한 PDF를 생성하는 C# 코드입니다.
using var pdf = new PdfDocument();
var canvas = pdf.Pages[0].Canvas;
canvas.Font = pdf.CreateFont(PdfBuiltInFont.HelveticaBold);
canvas.FontSize = 14;
canvas.DrawString(40, 100, "Core API demo: text, images, and vector graphics");
var image = pdf.CreateImage("image.png");
canvas.DrawImage(image, 40, 180, 120, 120, 0);
canvas.Pen.Color = new PdfRgbColor(30, 60, 160);
canvas.Pen.Width = 2;
canvas.Brush.Color = new PdfRgbColor(200, 230, 255);
canvas.DrawRectangle(new PdfRectangle(200, 200, 150, 80), PdfDrawMode.FillAndStroke);
pdf.Save("core-api-demo.pdf");
이 개요에서는 Core API의 기능 중 극히 일부만을 소개합니다. 고급 기능에 대해서는 Core API를 사용한 PDF 생성에 대한 자세한 문서를 참조하십시오. 해당 문서에서는 텍스트 크기 측정, 색 공간 작업, 클리핑 적용, 패턴으로 영역 채우기, 투명도 처리 및 기타 기능을 다룹니다.
Layout API를 사용하여 PDF 생성하기
Layout API는 복잡하고 콘텐츠가 풍부한 PDF를 가장 쉽고 효율적으로 생성할 수 있도록 지원하는 고급 문서 생성 엔진입니다.
이 API를 사용하면 페이지, 컨테이너, 텍스트 스팬, 이미지, 표, 링크, 머리글, 바닥글 등과 같은 구조적 요소들을 이용하여 PDF를 구성할 수 있습니다. 좌표를 계산하거나 페이지를 수동으로 관리하는 대신, 문서의 구조를 정의하고 레이아웃 엔진이 나머지를 처리하도록 하면 됩니다.
이 예제는 Layout API를 사용하여 PDF를 생성하는 방법을 보여줍니다. 수동 위치 지정 대신 선언적 레이아웃을 활용하는 방식입니다.
PdfDocumentBuilder.Create()
.Info(info => info.Title = "Docotic.Pdf Layout API demo")
.Generate("layout-api-demo.pdf", doc => doc.Pages(pages =>
{
pages.Content().Padding(100).Text(text =>
{
text.Span("The Layout API lets you compose PDFs from structural elements ");
text.Line("without manually calculating coordinates or handling pagination.")
.Style(s => s.Strong);
});
}));
.NET 애플리케이션에서 PDF를 생성할 때 레이아웃 API를 사용하는 방법에 대한 자세한 가이드를 참조하세요.
HTML to PDF API를 사용하여 웹 콘텐츠를 변환하기
Docotic.Pdf는 무료 HtmlToPdf 애드온과 함께 최신 고품질 Chrome 기반 HTML-PDF 변환 엔진을 제공합니다. 이 애드온에서 제공하는 API를 사용하여 최신 HTML 및 SVG, WebP 이미지와 같은 기타 웹 콘텐츠를 고품질 PDF 문서로 변환할 수 있습니다.
HTML-PDF API는 전체 HTML 페이지 또는 HTML 조각에서 PDF를 생성할 수 있습니다. URL, 원시 HTML 문자열 및 로컬 HTML 파일의 콘텐츠를 변환할 수 있습니다. 특히 로컬 HTML 파일을 사용하면 HTML 템플릿에서 PDF를 쉽게 생성할 수 있습니다.
HTML 템플릿에서 PDF를 생성하는 방법 예시는 다음과 같습니다.
public static async Task HelloHtmlTemplate()
{
static string GetUserName()
{
// Replace with real logic: form input, API call, config, etc.
return "World";
}
string html = $@"
<h1>Hello, {GetUserName()}!</h1>
<p>This PDF was generated from an HTML template.</p>";
using var converter = await HtmlConverter.CreateAsync();
using var pdf = await converter.CreatePdfFromStringAsync(html);
pdf.Save("hello-html-template.pdf");
}
더 자세한 내용과 예시는 HTML을 PDF로 변환하는 방법에 대한 심층적인 개요를 참조하세요.
이미지에서 PDF 생성하기
Docotic.Pdf는 이미지를 PDF로 변환하는 유연하고 개발자 친화적인 방법을 제공합니다. 이 라이브러리는 Core API를 통해 JPEG, BMP, GIF, PNG, TIFF 및 JPEG 2000 이미지 형식을 지원합니다.

PDF 형식이 지원하는 경우, Docotic.Pdf는 이미지 바이트를 픽셀 디코딩 및 재인코딩 없이 그대로 삽입하여 원본 압축을 유지합니다. 또한 가능한 경우 색 공간도 보존합니다.
더불어, HTML to PDF API를 통해 SVG 및 WebP 형식도 지원합니다. 레이블이나 설명 옆에 이미지를 배치해야 할 경우, 레이아웃 API를 사용하면 최소한의 노력으로 요소를 정렬하고 배치할 수 있습니다.
여러 이미지를 하나의 PDF 파일로 합치는 방법
Docotic.Pdf를 사용하면 여러 이미지를 하나의 PDF 파일로 간편하게 변환하고 각 페이지에 이미지를 하나씩 배치할 수 있습니다.
아래 예시는 파일에서 이미지를 불러와 각 이미지를 별도의 페이지에 배치하는 방법을 보여줍니다. 각 이미지는 페이지 크기에 맞춰 크기가 조정되고 중앙에 배치되어 깔끔하고 일관된 레이아웃을 제공합니다.
public static void ImagesOnToPdf(string[] imagePaths, string outputPath)
{
using var pdf = new PdfDocument();
foreach (string path in imagePaths)
{
var image = pdf.CreateImage(path);
var page = pdf.AddPage();
var pageWidth = page.Width;
var pageHeight = page.Height;
var scale = Math.Min(pageWidth / image.Width, pageHeight / image.Height);
var drawWidth = image.Width * scale;
var drawHeight = image.Height * scale;
var x = (pageWidth - drawWidth) / 2;
var y = (pageHeight - drawHeight) / 2;
page.Canvas.DrawImage(image, x, y, drawWidth, drawHeight, 0);
}
pdf.RemovePage(0);
pdf.Save(outputPath);
}
여러 페이지로 구성된 TIFF 및 GIF 이미지 처리
Docotic.Pdf는 여러 페이지로 구성된 TIFF 및 GIF 파일을 완벽하게 지원합니다. PDF에 이미지를 추가할
때, 이미지에 여러 페이지가 포함될 수 있는 경우 CreateImage 메서드 대신 OpenImage 메서드를
사용하십시오.
다음 코드는 TIFF 파일을 PDF로 변환하는 방법을 보여주며, 단일 페이지 이미지와 여러 페이지로 구성된 이미지 모두에 적용됩니다.
public static void OddFramesToPdf(string[] imagePaths, string outputPath)
{
using var pdf = new PdfDocument();
foreach (string path in imagePaths)
{
var imageFrames = pdf.OpenImage(path);
for (int i = 0; i < imageFrames.Count; i++)
{
if (i % 2 != 0)
continue;
var image = pdf.CreateImage(imageFrames[i]);
var page = pdf.AddPage();
page.Width = image.Width;
page.Height = image.Height;
page.Canvas.DrawImage(image, 0, 0, image.Width, image.Height, 0);
}
}
pdf.RemovePage(0);
pdf.Save(outputPath);
}
GIF를 PDF로 변환할 때도 같은 방법을 사용할 수 있습니다. 이 방법은 다른 이미지 형식에도 적용되지만, 단일 프레임으로 구성된 형식의 경우 필요 이상으로 복잡한 과정이 필요합니다.
PDF 병합 및 분할
Docotic.Pdf는 모든 기능을 갖춘 .NET 라이브러리로, 기존 문서의 페이지를 병합, 추출 및 재구성하여 새 PDF를 생성할 수 있습니다.
PDF를 병합할 때, 라이브러리는 다른 문서의 페이지뿐만 아니라 레이어, 책갈피, 페이지 레이블, 공유 JavaScript, 대상(링크 대상) 및 포함된 파일도 추가합니다. 자세한 내용과 병합된 PDF의 크기를 줄이는 방법에 대한 지침은 PDF 병합 문서를 참조하십시오.
디지털 서명이 있는 PDF는 기존 서명을 무효화하지 않고는 병합할 수 없습니다. 서명을 유지하려면 문서를 추가하는 대신 PDF 포트폴리오 생성을 사용하십시오. 또는 먼저 PDF를 병합한 다음 새 디지털 서명 적용을 사용하여 병합된 문서에 서명할 수도 있습니다.
Docotic.Pdf를 사용하면 페이지를 복사하고 추출하여 새 문서에 추가할 수도 있습니다. 복사된 페이지와 관련된 모든 콘텐츠(주석, 폼 컨트롤, 구조화된 콘텐츠, 레이어 및 기타 관련 데이터 포함)는 그대로 유지됩니다. 실제 예제는 .NET에서 PDF 분할 문서를 참조하십시오. 이 문서에는 페이지를 추출하거나 제거하는 방법도 설명되어 있습니다.
PDF 템플릿 작업하기
PDF 템플릿은 새 문서를 만들 때 기본 구조로 사용할 수 있는 미리 디자인된 PDF 파일입니다. 다양한 데이터를 입력하면서도 일관된 레이아웃을 유지해야 하는 PDF 문서를 제작할 때 유용합니다. 시각적 디자인과 데이터를 분리하고 싶을 때도 PDF 템플릿이 좋은 선택입니다.
템플릿은 양식이 포함된 PDF와 양식이 없는 정적 PDF로 나눌 수 있습니다. 두 유형 모두 동일한 목적을 수행합니다. 또한, 양식이 포함된 템플릿에는 사용자로부터 정보를 수집할 수 있는 대화형 요소가 포함되어 있으며, 이러한 요소는 평면화하지 않으면 사용자로부터 정보를 얻을 수 있습니다.
양식 기반 템플릿을 사용하여 PDF 생성하기
폼 기반 템플릿은 일반적으로 표준이자 널리 지원되는 대화형 PDF 폼 유형인 AcroForms를 포함합니다. 이러한 템플릿에서 PDF를 생성하려면 일반적으로 다음 단계를 수행해야 합니다.
- 각 자리 표시자 필드를 채웁니다.
- 추가 편집을 방지하기 위해 필드를 평면화합니다.
- 결과를 새 PDF로 저장합니다.
다음은 이름으로 자리 표시자 텍스트 필드를 찾고, 값을 할당하고, 필드를 평면화한 다음, 결과를 저장하여 템플릿에서 PDF를 생성하는 C# 코드입니다.
var nameOnCertificate = "Eva Marin";
using var pdf = new PdfDocument("certificate-template.pdf");
if (pdf.TryGetControl("name", out var field))
{
if (field is PdfTextBox nameField)
{
nameField.Text = nameOnCertificate;
nameField.Flatten();
}
}
pdf.Save($"certificate-{nameOnCertificate}.pdf");
템플릿에 플레이스홀더가 많은 경우 각 필드를 개별적으로 채우는 대신 FDF 데이터를 가져올 수 있습니다.
또한 PdfDocument.FlattenControls를 사용하여 모든 필드를 한 번에 평면화할 수도 있습니다.
폼 없이 정적 템플릿에서 PDF 생성하기
템플릿에 폼 필드가 포함되어 있지 않으면 이름과 기타 데이터를 페이지 캔버스에 직접 그려야 합니다. 정적 PDF 템플릿에는 일반적으로 텍스트, 이미지 또는 빈 영역과 같은 고정된 시각적 자리 표시자가 포함되어 있습니다. 템플릿에서 PDF를 생성하려면 이러한 빈 영역을 채우고 자리 표시자의 텍스트와 이미지를 프로그램적으로 바꿔야 합니다.
빈 공간
Canvas API를 사용하여 빈 영역에 텍스트와 이미지를 배치할 수 있습니다. 이름이나 사진을 추가하는 등 간단한 변경만 필요한 경우에는 이 방법이 효과적입니다. 영역의 좌표와 크기를 알아야 하며, 텍스트를 정확하게 배치하려면 먼저 크기를 측정한 후 그에 맞춰 정렬해야 할 수도 있습니다.
가변 길이 텍스트나 여러 줄 텍스트를 사용하는 것은 더 어렵지만 여전히 가능합니다. DrawText,
DrawString 메서드와 텍스트 크기 측정 메서드를 조합하여 필요에 따라 줄 바꿈 및 위치 조정을 할 수
있습니다. 템플릿에 이러한 영역이 여러 개 있는 경우에는 Layout API를 사용하여 PDF를 생성하는 것과
같은 다른 방법을 고려해 보세요.
자리 표시자 텍스트
Docotic.Pdf는 텍스트 찾기 및 바꾸기 기능도 제공합니다. 그러나 텍스트 검색을 템플릿 메커니즘으로 사용하는 것은 빈 자리 표시자 영역을 사용하는 것보다 일반적으로 더 쉽지 않습니다. 새 콘텐츠를 삽입하기 전에 정확한 텍스트 조각을 찾아 깔끔하게 제거해야 합니다.
자리 표시자 이미지
정적 템플릿에는 사용자 아바타 또는 제품 사진을 위한 자리 표시자 이미지가 포함될 수 있습니다. 자리
표시자 이미지를 찾으려면 각 페이지에 표시된 이미지 모음을 열거하세요. 표시된 각 이미지에 대해
표시되는 크기와 위치를 얻을 수 있습니다. 자리 표시자 이미지를 바꾸려면 PdfImage.ReplaceWith를
사용하세요.
using var pdf = new PdfDocument("invoice-template.pdf");
var paintedImages = pdf.Pages[0].GetPaintedImages();
var placeholder = paintedImages.First();
placeholder.Image.ReplaceWith("company-logo.jpg");
pdf.Save($"invoice.pdf");
또 다른 방법은 자리 표시자 이미지가 차지하는 영역 위에 새 이미지를 그리는 것이지만, 이렇게 하면 일반적으로 특별한 이유 없이 PDF 파일 크기가 커집니다.
쉽게 교체할 수 있도록 자리 표시자 디자인하기
정적 템플릿의 경우, 텍스트와 이미지 모두에 대해 예측 가능하고 명확하게 정의된 영역을 사용하여 레이아웃을 디자인하는 것이 좋습니다. 가변 길이 콘텐츠가 포함될 영역 주변에는 충분한 여백을 두고, 나중에 삽입할 이미지의 가로세로 비율과 일치하는 중립적인 자리 표시자 이미지를 사용하세요.
템플릿에 자리 표시자 텍스트를 사용하고 이를 교체할 계획이라면, 일반 텍스트 대신 텍스트 상자를
사용하여 워크플로를 간소화할 수 있습니다. 템플릿에 읽기 전용의 테두리 없는 텍스트 상자를 추가하고
그 안에 자리 표시자 텍스트를 넣으세요. 최종 PDF를 생성할 때 템플릿을 열고 이름으로 텍스트 상자를
찾은 다음 box.Text = "새 텍스트";를 사용하여 새 값을 직접 할당합니다. 그런 다음 텍스트 상자를
병합하여 더 이상 편집할 수 없도록 합니다.
인터랙티브 요소 추가
대화형 기능을 통해 정적인 PDF를 주석 및 마크업이 풍부하게 포함된 동적이고 탐색하기 쉬운 문서로 변환할 수 있습니다. 액션 및 JavaScript를 사용하여 PDF 내에서 직접 자동화를 구현할 수 있습니다.
주석
주석은 페이지에 첨부되는 개체로, 댓글, 강조 표시, 파일 첨부 및 기타 대화형 위젯을 나타냅니다. 주석은 페이지 콘텐츠에 표시되며 검토 워크플로 및 공동 작업을 지원합니다.
다음 C# 예제는 Docotic.Pdf를 사용하여 PDF 페이지에 텍스트 주석(스티커 메모라고도 함)을 추가하는 방법을 보여줍니다.
using var pdf = new PdfDocument("example.pdf");
var page = pdf.Pages[0];
var textAnnot = page.AddTextAnnotation(new PdfPoint(50, 100), "Reviewer comment");
textAnnot.Contents = "Please check the figures on this page.";
pdf.Save("text-annotation.pdf");
다음 예시는 문서의 핵심 부분을 강조하기 위해 텍스트 및 기타 콘텐츠를 강조 표시하는 방법을 보여줍니다.
using var pdf = new PdfDocument("example.pdf");
var page = pdf.Pages[0];
var color = new PdfRgbColor(255, 255, 120);
var annotationText = "Please confirm this part.";
var bounds = new PdfRectangle(50, 250, 120, 40);
page.AddHighlightAnnotation(annotationText, bounds, color);
pdf.Save("highlight-annotation.pdf");
모래밭
PDF 표준은 여러 유형의 PDF 링크를 정의합니다. 가장 중요하고 널리 사용되는 링크는 내부 링크와 하이퍼링크입니다.
내부 링크는 'GoTo' 작업이라고도 하며, 동일한 PDF 내의 특정 페이지 또는 지정된 위치로 이동할 수 있도록 합니다. 이는 상호 참조 및 내부 탐색에 유용합니다.
다음은 첫 페이지에서 인덱스 5번 페이지로 연결되는 링크를 생성하는 C# 코드입니다.
using var pdf = new PdfDocument();
var page = pdf.Pages[0];
int targetPageIndex = 5;
for (int i = 0; i < targetPageIndex; i++)
pdf.AddPage();
var rect = new PdfRectangle(50, 50, 100, 40);
page.Canvas.DrawRectangle(rect);
page.AddLinkToPage(rect, targetPageIndex);
pdf.Pages[targetPageIndex].Canvas.DrawString(50, 50, "Glad to have you here.");
pdf.Save("link-to-page.pdf");
Layout API는 절대 위치 지정을 사용하지 않고 내부 링크를 생성하는 또 다른 방법을 제공합니다.
외부 링크(URI 액션이라고도 함)는 웹 URL을 엽니다. PdfPage.AddHyperlink 메서드를 사용하여 PDF
페이지에 하이퍼링크를 추가할 수 있습니다. 그 외의 방법은 내부 링크와 동일합니다.
책갈피
책갈피(또는 개요)는 독자가 특정 섹션이나 페이지로 빠르게 이동할 수 있도록 도와주는 특별한 바로가기 또는 링크입니다. 독자가 책갈피를 클릭하면 뷰어 애플리케이션이 문서의 지정된 부분으로 이동합니다.
개요는 뷰어의 책갈피 패널에 나타나며, 책의 목차와 유사한 계층적 탐색 트리를 제공하지만 상호 작용이 가능합니다. PDF 개요에는 기본 책갈피와 하위 책갈피를 포함할 수 있어 대규모 문서를 쉽게 구조화할 수 있습니다.
다음 예제는 C#과 Docotic.Pdf를 사용하여 PDF에 책갈피를 만드는 방법을 보여줍니다. 이 코드는 세 개의 최상위 책갈피를 생성합니다. 두 번째 책갈피에는 하나의 하위 책갈피가 포함되어 있습니다.
using var pdf = new PdfDocument();
for (int i = 0; i < 5; i++)
{
var page = i == 0 ? pdf.Pages[0] : pdf.AddPage();
var canvas = page.Canvas;
canvas.FontSize = 14;
canvas.DrawString(50, 50, $"Page {i + 1}");
}
var root = pdf.OutlineRoot;
root.AddChild("Getting Started", 1);
var child = root.AddChild("Things You Can Do", 2);
child.AddChild("Making Quick Improvements", 3);
root.AddChild("Keeping Everything Running Smoothly", 4);
pdf.PageMode = PdfPageMode.UseOutlines;
pdf.Save("bookmarks.pdf");
책갈피는 실제 책의 페이지에 인쇄되어 있거나 PDF 파일에 표시되는 목차와는 다릅니다. 제목의 크기를 측정하고 페이지 번호가 포함된 항목을 작성하여 프로그램적으로 목차를 만들 수 있습니다.
Layout API를 사용하여 목차를 만드는 다른 접근 방식을 보려면 샘플 저장소의 관련 코드를 참조하세요.
PDF 스크립팅
JavaScript 액션은 가장 강력한 대화형 기능 중 하나입니다. PDF JavaScript는 문서 및 뷰어 API를 제공하는 JavaScript의 하위 집합입니다. 이는 폼 유효성 검사, 계산, 사용자 인터페이스 대화 상자 및 간단한 자동화 작업에 사용됩니다.
스크립트는 주석, 책갈피, 폼 컨트롤 또는 열기 액션에 연결할 수 있습니다. Docotic.Pdf를 사용하면 PDF에 JavaScript 코드를 삽입할 수 있습니다. 이 코드는 폼 입력 유효성 검사, 값 계산, 필드 표시/숨기기 또는 뷰어 상호 작용을 수행할 수 있습니다.
공유 JavaScript 모음에는 문서 수준에 저장된 스크립트가 포함됩니다. 이러한 스크립트는 여러 액션에서 재사용할 수 있습니다. 즉, 공유 스크립트는 유틸리티 기능 및 공유 로직에 유용합니다. 중복을 줄이고 유지 관리를 간소화하는 데 도움이 됩니다.
아래 코드는 PDF 뷰어에 경고 메시지를 표시하는 공유 스크립트를 정의하고, 버튼 클릭 액션에 해당 스크립트를 할당하여 실행하는 방법을 보여줍니다.
using var pdf = new PdfDocument();
pdf.SharedScripts.Add(
pdf.CreateJavaScriptAction("function messageBox(message) { app.alert(message,3); }")
);
var button = pdf.Pages[0].AddButton(50, 50, 100, 40);
button.Text = "Click me";
button.OnMouseUp = pdf.CreateJavaScriptAction("messageBox('Hello, dear!');");
pdf.Save("shared-javascript.pdf");
예제 스크립트는 간단하지만, 어떤 복잡성의 JavaScript 액션이든 만들 수 있습니다. Adobe JavaScript API 참조에는 사용할 수 있는 다양한 메서드가 제공됩니다. 단, Adobe 제품이 아닌 뷰어는 일반적으로 API의 일부만 지원한다는 점에 유의하십시오.
열기 작업
열기 동작은 PDF 뷰어가 문서를 열 때 실행하는 동작입니다. 일반적인 예로는 특정 페이지에서 열기, JavaScript 초기화 루틴 실행, 뷰어 환경 설정 등이 있습니다. 열기 동작의 유형에는 제한이 없습니다.
다음 예제는 GoTo 열기 동작을 만드는 방법을 보여줍니다. 이 코드는 두 번째 페이지에 텍스트를
추가하고, PDF를 열 때 뷰어가 자동으로 해당 페이지로 이동하도록 하는 열기 동작을 설정합니다.
using var pdf = new PdfDocument();
var canvas = pdf.AddPage().Canvas;
canvas.FontSize = 14;
var message =
"If you see this immediately after opening the file, " +
"your PDF viewer supports open actions.";
var options = new PdfTextDrawingOptions(new PdfRectangle(100, 100, 100, 150));
canvas.DrawText(message, options);
pdf.OnOpenDocument = pdf.CreateGoToPageAction(1, 0);
pdf.Save("open-action.pdf");
모든 뷰어가 JavaScript 열기 액션을 실행하는 것은 아닙니다. 일부는 이를 무시하거나 사용자에게 먼저 확인 메시지를 표시합니다. 어떤 뷰어는 열기 액션을 완전히 차단하기도 합니다.
PDF에 열기 액션이 포함되어 있는지 확인하려면 해당 문서를 PdfDocument 객체에 로드한 후
OnOpenDocument 속성을 검사하십시오. 이 속성이 null이면 문서에 정의된 열기 액션이 없는 것입니다.
암호화 및 디지털 서명 적용
암호화와 디지털 서명은 생성하는 PDF 파일의 보안을 강화하는 두 가지 상호 보완적인 요소입니다. 암호화는 문서를 열 수 있는 사람과 문서에 대해 수행할 수 있는 작업을 제어하고, 서명은 파일을 생성하거나 승인한 사람을 증명하고 파일이 변조되지 않았음을 확인합니다.
암호 보호 기능을 사용하면 생성 시 액세스 규칙을 설정할 수 있습니다. 보기 권한을 제한하는 열기 암호를 지정하고, 인쇄, 복사, 편집 또는 양식 작성과 같은 권한을 정의하는 소유자 암호를 지정할 수 있습니다. 인증서 암호화는 수신자별로 더욱 강력한 보호 기능을 제공하며, 공유 암호를 사용하지 않고 여러 사람에게 기밀 PDF 파일을 배포할 때 유용합니다. 자세한 내용은 암호 및 인증서를 사용한 PDF 암호화 문서를 참조하십시오.
디지털 서명은 생성 시점에 문서의 진위성과 무결성을 보장합니다. Docotic.Pdf는 파일, Windows 스토어, 하드웨어 토큰, HSM 또는 클라우드 키 서비스의 인증서를 사용하여 PDF 서명할 수 있습니다. 타임스탬프와 장기 유효성 검사 데이터를 포함하면 문서 생성 후에도 서명의 유효성을 오랫동안 확인할 수 있습니다. PKCS#11 및 클라우드 KMS를 포함한 외부 서명 워크플로도 지원됩니다.
PDF 메타데이터 설정
PDF 메타데이터는 문서에 포함된 설명 정보로, 제목, 작성자, 주제, 키워드, 생성 날짜 등의 필드를 포함합니다. 소프트웨어, 검색 엔진 및 문서 관리 시스템은 메타데이터를 통해 파일을 열지 않고도 파일의 내용을 이해할 수 있습니다.
PDF 문서는 다음과 같은 두 가지 시스템의 메타데이터를 동시에 저장할 수 있습니다.
- XMP 메타데이터
- 문서 정보 사전(
Info사전)

XMP는 설명 메타데이터를 삽입하기 위한 더욱 풍부하고 구조화된 표준 형식입니다. Info 사전은
간단하고 널리 지원되지만 제한적이며, PDF 2.0 표준(ISO 32000-2)에서는 XMP 메타데이터를 권장하므로 더
이상 사용되지 않습니다. Docotic.Pdf는 두 시스템 모두를 읽고 쓸 수 있으며, 두 시스템을 동기화 상태로
유지하는 도우미 메서드를 제공합니다.
Docotic.Pdf는 PDF 파일을 저장하기 전에 일부 메타데이터를 자동으로 업데이트합니다. 예를 들어, 라이브러리는 기본적으로 제작자(Producer)와 생성자(Creator) 값을 설정합니다. 이 동작을 변경하고 명시적으로 설정한 메타데이터 값을 유지하려면 저장 옵션을 사용하십시오.
XMP 메타데이터
PdfDocument.Metadata 속성을 사용하여 PDF의 XMP 메타데이터에 접근하고 수정할 수 있습니다. 이
속성을 통해 XMP Core, Dublin Core, PDF 스키마와 같은 잘 알려진 스키마를 사용할 수 있을 뿐 아니라
사용자 지정 메타데이터도 관리할 수 있습니다.
using var pdf = new PdfDocument();
var xmp = pdf.Metadata;
xmp.Pdf.Creator = new XmpString("Second-line authoring terminal");
xmp.Pdf.Title = new XmpString("Quarterly Report");
var creators = new XmpArray(XmpArrayType.Ordered);
creators.Values.Add(new XmpString("Second-line authoring terminal"));
creators.Values.Add(new XmpString("Assistive authoring terminal"));
xmp.DublinCore.Creators = creators;
var descriptions = new XmpArray(XmpArrayType.Alternative);
descriptions.Values.Add(new XmpLanguageAlternative("x-default", "Quarterly Report"));
descriptions.Values.Add(new XmpLanguageAlternative("fr", "Rapport trimestriel"));
descriptions.Values.Add(new XmpLanguageAlternative("de", "Quartalsbericht"));
xmp.DublinCore.Descriptions = descriptions;
var author1 = new XmpString("First Author");
author1.Qualifiers.Add("role", "main author");
var author2 = new XmpString("Second Author");
author2.Qualifiers.Add("role", "co-author");
var authors = new XmpArray(XmpArrayType.Unordered);
authors.Values.Add(author1);
authors.Values.Add(author2);
xmp.Custom.Properties.Add("authors", authors);
pdf.Save("with-xmp-metadata.pdf");
XMP는 배열, 구조체 및 형식화된 값을 지원하므로 풍부한 메타데이터에 적합합니다. 위 코드는 또한 사용자 지정 XMP 스키마에 애플리케이션별 속성을 저장하는 방법을 보여줍니다.
문서 정보 사전
Info 딕셔너리는 주로 텍스트 문자열 값을 저장합니다. 크기가 작고 지원 범위가 넓지만 기능에는
제한이 있습니다. 이전 버전 도구와의 호환성을 위해서는 Info 딕셔너리를 사용하고, 그 외의 경우에는
XMP를 사용하는 것이 좋습니다.
메타데이터 동기화
독자와 자동화 도구가 혼동할 수 있는 불일치를 방지하기 위해 두 메타데이터 시스템을 동기화 상태로 유지하는 것이 좋습니다.
PdfDocument.SyncMetadata 메서드를 사용하여 XMP와 Info 값을 일치시켜 해당 필드가 서로 대응되도록
정렬하십시오. 이 메서드는 XMP에서 누락된 Info 속성을 채우고, 마찬가지로 Info에서 누락된 XMP
필드를 채웁니다. XMP가 우선시되는 경우 preferXmp: true로 설정하고, Info 사전이 우선시되는 경우
false로 설정하십시오.
pdf.SyncMetadata(preferXmp: true);
이 메서드가 동기화하는 속성에 대한 자세한
내용은 SyncMetadata 문서의 비고 섹션을 참조하십시오.
페이지 레이블 및 뷰어 기본 설정 구성
새로 생성된 PDF 파일은 명확한 페이지 번호 매기기, 세밀한 뷰어 설정, 그리고 문서 내용을 더욱 효과적으로 보여주도록 선택된 페이지 레이아웃을 통해 개선될 수 있습니다. 이러한 설정은 독자가 파일을 처음 보고 탐색하는 방식에 영향을 미칩니다.
페이지 레이블
페이지 레이블은 PDF 뷰어에 각 페이지에 표시할 레이블을 알려주는 메타데이터입니다. 표시되는 페이지
번호가 실제 페이지 번호와 달라야 할 때 사용합니다. 예를 들어, PDF의 서문에는 i, ii, iii를,
본문에는 1, 2, 3을 표시하려는 경우에 사용합니다.
다음 C# 코드는 PDF 페이지 레이블을 처음 세 페이지에는 소문자 로마 숫자로, 나머지 페이지에는 1부터 시작하는 아라비아 숫자로 지정하는 방법을 보여줍니다.
using var pdf = new PdfDocument();
for (int i = 0; i < 8; i++)
pdf.AddPage();
pdf.PageLabels.AddRange(0, 2, PdfPageNumberingStyle.LowercaseRoman);
pdf.PageLabels.AddRange(3, PdfPageNumberingStyle.DecimalArabic);
pdf.Save("with-page-labels.pdf");
PDF 뷰어 설정
PDF 뷰어 환경설정은 문서에 포함된 권장 사항으로, 뷰어가 문서를 어떻게 표시해야 하는지를 제안합니다. 예를 들어, 도구 모음을 숨기거나, 창을 가운데 정렬하거나, 창 크기를 페이지에 맞추도록 지정할 수 있습니다. 뷰어 환경설정은 페이지 레이아웃 및 열기 동작 설정과 함께 사용됩니다.
Docotic.Pdf를 사용하여 PDF 보기 환경설정을 변경하는 방법은 다음과 같습니다.
using var pdf = new PdfDocument();
pdf.ViewerPreferences.DisplayTitle = false;
pdf.ViewerPreferences.FitWindow = true;
pdf.ViewerPreferences.HideToolBar = true;
pdf.ViewerPreferences.HideMenuBar = true;
pdf.ViewerPreferences.HideWindowUI = true;
pdf.ViewerPreferences.CenterWindow = true;
pdf.Save("with-viewer-prefs.pdf");
참고로, Adobe Acrobat 및 기타 뷰어는 설정에 따라 이러한 기본 설정을 무시할 수 있습니다.
페이지 레이아웃 및 페이지 모드
페이지 레이아웃은 문서가 열릴 때 페이지 배열 방식을 결정합니다. 한 페이지씩 표시, 한 열 연속 표시, 또는 두 페이지 펼침 방식 중에서 선택할 수 있습니다. 페이지 모드는 문서가 열릴 때 표시되는 UI 패널을 제어합니다. 책갈피/개요, 첨부 파일, 미리보기 이미지, 또는 표시 안 함 중에서 선택할 수 있습니다.
다음은 생성된 PDF 파일이 두 페이지 펼침 방식으로, 왼쪽 페이지부터 표시되고 미리보기 이미지 패널이 첫 화면에 나타나도록 지정하는 방법입니다.
using var pdf = new PdfDocument();
for (int i = 0; i < 7; i++)
{
var page = i > 0 ? pdf.AddPage() : pdf.Pages[0];
page.Canvas.FontSize = 36;
page.Canvas.DrawString(100, 100, $"Page {i + 1}");
}
pdf.PageLayout = PdfPageLayout.TwoPageLeft;
pdf.PageMode = PdfPageMode.UseThumbs;
pdf.Save("with-layout-and-mode.pdf");
PDF 저장하기
Docotic.Pdf는 사용자가 생성하거나 편집한 동일한 문서에서 다양한 PDF 파일 또는 스트림을 생성할 수 있습니다. 이러한 출력물은 서로 다른 버전의 PDF 형식을 준수할 수 있으며, 바이트 길이와 생성에 필요한 메모리 용량도 다를 수 있습니다.
라이브러리가 PDF 바이트를 생성하는 방식은 저장 옵션에 따라 달라집니다. 저장 옵션을 명시적으로
지정하지 않으면 PdfDocument 객체의 Save, SignAndSave, TimestampAndSave 메서드는 기본 설정을
사용합니다. 이러한 기본값은 대부분의 시나리오에서 잘 작동하도록 신중하게 선택되었지만, 경우에 따라
조정해야 할 수도 있습니다.
사용 가능한 옵션 및 기본값에 대한 자세한 내용은 PdfSaveOptions 클래스 문서를 참조하십시오. 아래 섹션에서는 몇 가지 중요한 옵션을 강조하고 실용적인 권장 사항을 제공합니다.
PDF 버전
Docotic.Pdf는 기본적으로 객체 스트림을 사용하여 파일 압축률을 높입니다. 따라서 이 라이브러리는 기본적으로 PDF 1.5 파일과 스트림을 생성합니다.
PDF 1.5 파일을 보려면 Adobe Reader 6(2003년 출시) 이상 버전이 필요합니다. 일반적으로 이는 문제가 되지 않지만, 구형 도구, 이전 버전의 뷰어 또는 이전 버전의 PDF만 지원하는 임베디드 장치를 지원해야 하는 경우에는 문제가 될 수 있습니다.
다음은 이전 버전의 PDF 파일로 저장하는 방법입니다.
using var pdf = new PdfDocument();
var options = new PdfSaveOptions
{
Version = PdfVersion.Pdf14,
UseObjectStreams = false,
};
pdf.Save("version-1.4.pdf", options);
PDF 1.4 버전으로 저장하려면 객체 스트림도 비활성화해야 합니다. 문서에 최신 버전에서 도입된 기능이 포함된 경우 라이브러리는 이전 버전을 사용하지 않습니다.
파일 크기 축소
RemoveUnusedObjects, OptimizeIndirectObjects, WriteWithoutFormatting, UseObjectStreams와
같은 몇 가지 저장 옵션을 true로 설정하면 Docotic.Pdf의 파일 크기가 줄어듭니다(바이트 단위).
참조되지 않은 객체와 불필요한 공백을 제거하고 데이터를 객체 스트림에 압축하여 PDF를 생성하는 방법은 다음과 같습니다.
using var pdf = new PdfDocument();
var options = new PdfSaveOptions
{
UseObjectStreams = true,
RemoveUnusedObjects = true,
OptimizeIndirectObjects = true,
WriteWithoutFormatting = true,
};
pdf.Save("optimized.pdf", options);
이러한 옵션은 PDF 파일을 완전히 새로 작성할 때 가장 효과적입니다. 부분 저장 시에는 새로 추가된 버전에만 적용되며 파일의 이전 부분을 정리하거나 최적화할 수 없습니다.
점진적 업데이트
Docotic.Pdf는 PDF를 증분 업데이트할 수 있습니다. WriteIncrementally가 true로 설정되면
라이브러리는 기존 파일을 덮어쓰는 대신 변경 사항을 추가합니다. 이전의 상호 참조 및 객체 데이터는
그대로 유지됩니다. 추가된 데이터를 증분 업데이트라고 하며, 현재 업데이트와 이전의 모든 업데이트를
합쳐 새 버전의 파일을 구성합니다.
새로 생성된 문서는 이전 버전이 없으므로 증분 업데이트가 불가능합니다. 라이브러리는 새 문서에 대해서는 이 옵션을 무시하고 비증분 모드로 파일을 작성합니다.
증분 업데이트가 필요한 경우
이미 서명이 포함된 문서에 새 디지털 서명을 추가할 때는 파일을 증분 저장해야 합니다. 이전에 서명된 파일에 새 주석이나 양식 데이터를 추가하여 업데이트할 때도 마찬가지입니다. 이러한 경우 전체 파일을 덮어쓰면 기존 서명이 무효화됩니다.
동시에, 첫 번째 디지털 서명을 적용하기 전에 증분 저장이 아닌 전체 저장을 수행하여 서명된 기준 파일이 깨끗하고 완전히 새로 작성된 파일이 되도록 하는 것이 좋습니다. 이전 버전에서 구조적 문제가 있는 문서에 서명하면 예상치 못한 서명 유효성 검사 문제가 발생할 수 있습니다.
증분 추가는 감사 가능한 수정 기록을 보존해야 하거나 문서 저장을 추가 전용으로 강제해야 하는 워크플로에서도 필요합니다.
점진적 업데이트 사용의 이점
증분 업데이트 방식을 사용하면 동일 파일에 여러 서명을 할 수 있으며, 기존 서명을 무효화하지 않고 서명 후 양식 필드 입력과 같은 제한된 범위의 수정 작업을 수행할 수 있습니다.
또한, 수정된 데이터만 기록되므로 작은 변경 사항에 대한 저장 속도가 더 빠릅니다. 뿐만 아니라 문서의 수정 이력을 보존하므로 감사 및 기타 규정 준수 관련 워크플로에 필수적입니다.
피해야 할 문제점 및 함정
증분 업데이트는 수정된 객체만 추가하기 때문에 파일 전체에 걸쳐 전역 압축을 적용하거나 더 이상 사용되지 않는 객체를 제거할 수 없습니다. 결과적으로, 증분 업데이트는 일반적으로 전체 재작성보다 파일 크기가 크고 최적화가 떨어집니다.
파일 크기는 사용되지 않는 객체가 없더라도 이전 버전의 모든 데이터가 파일에 남아 공간을 차지하기 때문에 각 수정마다 증가합니다.
이전 버전의 민감하거나 잘못된 정보는 복구될 수 있으며, 기존 PDF 형식 문제나 이전 버전의 구조적 결함은 새 데이터를 추가해도 수정되지 않습니다.
또한 일부 뷰어 및 처리 도구는 여러 버전이 포함된 PDF 파일을 제대로 처리하지 못할 수 있습니다. 증분 업데이트를 사용하기 전에 모든 문서 사용자가 여러 버전이 포함된 파일을 처리할 수 있는지 확인해야 합니다.
PDF 출력 테스트
자동화된 PDF 테스트는 생성된 PDF를 저장소 또는 아티팩트 스토리지에 저장된 기준 PDF와 비교하여 콘텐츠 및 레이아웃의 회귀 오류로부터 릴리스를 보호합니다. 기준 PDF를 사용하면 텍스트, 글꼴, 이미지 또는 레이아웃의 의도치 않은 변경 사항을 감지하고 모든 빌드에서 수동 QA를 수행해야 하는 필요성을 줄일 수 있습니다.
구조 검사, 텍스트 추출 및 시각적 비교를 결합하여 가장 신뢰할 수 있는 결과를 얻으세요.
접근 방식에 대한 간략한 비교
| 방법 | 속도 | 감광도 | ~에 가장 적합함 |
|---|---|---|---|
| 구조적 비교 | 빠른 | 높음: 객체 수준의 변화를 감지합니다 | 동일한 문서의 두 버전이 구조적으로 동일한지 확인해야 하는 회귀 테스트 |
| 텍스트 추출 | 빠른 | 중간: 일반적으로 레이아웃 변경을 무시합니다 | 의미론적 콘텐츠 및 테이블 검증 |
| 시각적 차이 | 더 느리게 | 높음: 콘텐츠 변경과 렌더링/레이아웃 변경을 모두 감지합니다 | 시각적 회귀 포착 |
문서 구조 비교
PdfDocument.DocumentsAreEqual 메서드를 사용하면 시간에 따라 변하는 문서 속성을 무시하고 PDF 객체 그래프, PDF 버전 및 문서 보안 저장소(DSS)를 비교할 수 있습니다. 이 메서드는 문서 메타데이터, 트레일러 ID 및 기타 자동 생성 속성도 무시합니다.
이 메서드는 예상치 못한 객체가 추가되거나 제거되지 않았는지 확인해야 하는 PDF 문서 테스트
워크플로에 적합합니다. DocumentsAreEqual은 파일 및 스트림 오버로드를 지원하며 암호화된 PDF도
비교할 수 있습니다.
이 기법을 보여주는 전체 예제는 Docotic.Pdf 샘플에서 확인할 수 있습니다. 이 샘플은 일반 .NET 애플리케이션에서 이 메서드를 사용하는 방법뿐만 아니라 네이티브 AOT 애플리케이션에서 DocumentsAreEqual을 사용하는 방법도 보여줍니다.
추출된 텍스트를 통해 PDF 검증하기
텍스트 추출 기능을 사용하여 문서 전체 또는 개별 페이지에서 텍스트를 추출하고 문자열을 비교할 수 있습니다. 텍스트 추출 옵션을 사용하여 추출 과정을 세밀하게 조정할 수 있습니다. 예를 들어 바닥글이 있는 사각형 영역을 제외할 수 있습니다. 비교를 쉽게 하기 위해 추출된 텍스트를 줄 단위 또는 단어 단위로 분할할 수 있습니다.
구조적 검사를 위해서는 먼저 각 텍스트 덩어리, 단어 또는 문자에 대한 위치, 글꼴 및 기타 상세 정보와 함께 텍스트를 추출합니다. 그런 다음 추출된 각 요소를 해당 기준 요소와 비교합니다.
시각적 차이 감지
먼저 PDF 페이지를 이미지로 렌더링하고 각 이미지를 기준 이미지와 비교합니다. ImageSharp.Compare 또는 Magick.NET과 같은 특수 라이브러리를 사용하여 이미지 차이를 감지할 수 있습니다.
두 이미지의 모든 대응 픽셀이 정확히 일치하도록 픽셀 단위 비교를 엄격하게 수행하는 것이 좋습니다. 렌더링 과정에서 약간의 차이가 허용되는 경우 비교 로직을 조정하여 사소한 차이를 허용할 수 있지만, 픽셀 단위까지 정확히 일치하는 것이 가장 신뢰할 수 있는 결과를 제공합니다.
두 이미지가 픽셀 단위 비교를 수행하기 전에 두 이미지가 동일한지 여부를 빠르게 사전 검사하는 방법으로 해싱을 고려해 볼 수 있습니다. 렌더링된 각 이미지에 대해 SHA-256 해시를 계산하고, 해시 값이 일치하면 두 이미지는 거의 확실히 동일합니다. 해시 값이 다르면 픽셀 단위 비교를 수행합니다.
결론
Docotic.Pdf는 .NET 환경에서 PDF를 생성하고 조작하기 위한 포괄적이고 다층적인 툴킷을 제공합니다. 개발자는 Core API를 사용한 저수준 제어, Layout API를 사용한 고수준 문서 생성, 또는 웹 기술 기반 워크플로우를 위한 HTML-PDF 변환 중에서 선택할 수 있습니다.
또한, 이 라이브러리는 이미지 기반 PDF, 템플릿 기반 생성, 그리고 주석, 링크, 책갈피, JavaScript 액션, 열기 액션과 같은 풍부한 대화형 기능을 지원합니다.
안정성을 보장하기 위해 Docotic.Pdf는 PDF 출력 테스트 방법을 제공하여 애플리케이션 변경으로 인해 회귀 오류나 예상치 못한 차이가 발생하지 않도록 합니다.