
C#에서 애플리케이션 데이터로, HTML 페이지로, 또는 이미 존재하는 PDF를 채워서 PDF 문서를 생성할 수 있습니다. 각 출발점은 서로 다른 워크플로로 이어지며, 선택은 레이아웃 제어, 콘텐츠가 늘어날 때의 페이지 나눔, 대상 머신이 갖춰야 하는 렌더링 의존성, 그리고 출력을 검증하는 방식에 따라 달라집니다.
아래 섹션들은 시작 자료를 기준으로 Spire.PDF for .NET 워크플로를 분류하고, 테스트에서 각각이 어떤 결과를 냈는지 잘못된 부분까지 포함해 보고합니다. Spire.PDF for .NET 12.11.0으로 테스트했습니다(2026년 11월, Windows 11 Pro, .NET 10 콘솔 앱).
빠른 탐색
1. 보유한 자료로 시작하기
프로그램이 런타임에 보유한 자료에서 시작하십시오. 쿼리 결과 레코드, HTML 페이지, 또는 다른 사람이 설계한 PDF가 여기에 해당합니다. 아래 표는 각 입력을 워크플로와 연결합니다.
| 분류 | 런타임 입력 | 워크플로 |
|---|---|---|
| 새 PDF 생성 | 애플리케이션 데이터 / 구조화된 데이터 | 좌표 기반 또는 네이티브 흐름 레이아웃 |
| 새 PDF 생성 | HTML/CSS 페이지 또는 템플릿 | HTML-to-PDF 렌더링 |
| 기존 PDF | 채울 수 있는 양식(AcroForm) | 양식 필드 채우기 |
| 기존 PDF | 채울 수 있는 양식(XFA) | XFA 필드 처리 |
| 기존 PDF | 자리 표시자 텍스트가 있는 고정 레이아웃 | 텍스트 교체 |
처음 두 행은 새 PDF를 생성하므로 레이아웃을 직접 소유하고 페이지가 어떻게 나뉠지 결정해야 합니다. 마지막 세 행은 기존 PDF에서 시작하며, 파일이 레이아웃을 고정하고 작업은 값을 파일이 제공하는 위치에 넣는 것입니다. 이 가이드 전반에서 사용하는 월간 QA 보고서처럼 쿼리 결과로 C#에서 PDF 보고서를 생성하는 작업은 첫 번째 행에서 시작합니다. 프런트엔드 팀이 유지 관리하는 HTML 청구서 템플릿은 두 번째 행에서 시작하고, 공급업체로부터 받은 양식은 마지막 세 행 중 하나에서 시작합니다.
이 가이드는 Spire.PDF가 지원하는 워크플로를 다루며, 모든 C# PDF 기법을 망라한 분류가 아닙니다.
2. 애플리케이션 데이터에서 PDF 생성하기
좌표 기반 그리기는 각 텍스트 블록, 선, 이미지를 지정한 위치에 배치합니다. 고정된 디자인을 정밀하게 제어할 수 있으며 라이브러리 외에 렌더링 엔진이 필요하지 않습니다. 비용은 콘텐츠 길이가 변할 때 나타납니다. 페이지 나눔이 코드의 몫이 되기 때문입니다. 마지막 요소가 끝난 위치를 추적하고, 페이지를 직접 추가하고, 콘텐츠가 바뀌면 위치를 다시 계산해야 합니다. 짧은 발췌가 이 패턴을 보여 줍니다.
var font = new PdfTrueTypeFont("Segoe UI", 11f, PdfFontStyle.Regular, true);
var layout = new PdfTextLayout { Layout = PdfLayoutType.Paginate };
PdfPageBase page = doc.Pages.Add();
float y = 40;
foreach (string text in summaryParagraphs)
{
var r = new PdfTextWidget(text, font, PdfBrushes.Black)
.Draw(page, new RectangleF(40, y, 500, 0), layout);
page = r.Page; // the text may have flowed onto a new page
y = r.Bounds.Bottom + 10;
if (y > 760) { page = doc.Pages.Add(); y = 40; } // you own the page breaks
}
중요한 단계는 레이아웃 결과가 반환하는 페이지를 따라가는 것입니다. 위젯이 보고하는 페이지에 계속 그리며, 프레임이 바닥에 도달하면 새 페이지를 추가하십시오. DataTable로 만든 보고서에는 별도의 DataTable to PDF 튜토리얼이 있습니다.
네이티브 흐름 레이아웃은 페이지 나눔을 코드에서 꺼냅니다. Spire.PDF for .NET 12.9.18부터 제공되는 PdfContentBuilder는 콘텐츠를 섹션으로 스트리밍하며 늘어나는 만큼 페이지를 나눕니다. 제목, 단락, string[][]로 만든 표, 이미지, 목록, 코드 블록, 여섯 가지 차트 유형, 페이지 나눔, 목차를 제공합니다. 새 문서만 생성하며 기존 파일을 불러오는 진입점은 없습니다.
아래의 월간 QA 보고서는 두 섹션과 표 하나를 사용합니다. summaryParagraphs, results(첫 행이 헤더인 string[][]), closing은 자체 코드에서 가져옵니다.
using Spire.Pdf;
using Spire.Pdf.Layout;
PdfDocument doc = new PdfDocument();
PdfContentBuilder builder = new PdfContentBuilder(doc);
var s1 = builder.AddSection();
s1.AddHeading1("Monthly QA Report - October");
foreach (var p in summaryParagraphs) s1.AddParagraph(p);
s1.AddTable(results); // string[][] rows; header row repeats on page breaks
var s2 = builder.AddSection();
s2.AddHeading1("Next Month Outlook");
s2.AddParagraph(closing);
builder.Build();
doc.SaveToFile("QA-Report.pdf");
doc.Dispose();
콘텐츠 양이 두 접근 방식을 구분합니다. 작은 보고서(두 섹션, 5행 표)는 676ms에 두 페이지로 생성되었습니다. 긴 단락 8개와 40행 표가 있는 더 큰 보고서는 1,369ms(10.8KB)에 5페이지로 나뉘었습니다. 같은 콘텐츠를 좌표로 그리면 510ms(28.7KB)에 3페이지가 나왔습니다. 이 시간 측정값은 한 대의 Windows 머신에서 나온 것으로 이 설정에 대한 정상성 확인용입니다. 실행 속도를 비교하기 전에 각 파일이 어떻게 보이는지 먼저 비교하십시오.

좌표 기반 그리기는 구조가 데이터 양에 의존하지 않는 페이지에 적합합니다. 흐름 레이아웃은 보고서와 목록처럼 길이가 데이터를 따르는 문서에 적합합니다. 직접 조립하는 방식을 더 자세히 알고 싶은 개발자는 C# PDF 문서 생성 튜토리얼에서 시작할 수 있습니다.

네이티브 흐름 레이아웃과 HTML 렌더링은 서로 다른 메커니즘입니다. 빌더는 자체 API로 콘텐츠를 구성하며 CSS를 읽지 않고, HTML 렌더러는 마크업과 스타일시트를 파싱하므로 스타일링 옵션과 런타임 요구 사항이 다릅니다. 아래 표는 이 가이드의 모든 워크플로를 비교합니다.
| 워크플로 | 레이아웃 제어 | 동적 콘텐츠 | 외부 런타임 요구 사항 | 주요 제한 |
|---|---|---|---|---|
| 좌표 기반 | 명시적 좌표, 요소별 배치 | 레이아웃과 페이지 나눔을 직접 관리(PdfTextLayout.Paginate) |
추가 렌더링 엔진 없음 | 콘텐츠 크기가 바뀌면 좌표 수정 필요 |
네이티브 흐름 레이아웃(PdfContentBuilder, 12.9.18+) |
섹션, 제목, 단락 스트리밍 | 스트리밍 콘텐츠, 테스트에서 자동 페이지 나눔 확인 | 추가 렌더링 엔진 없음 | 생성 전용, 요소 범위는 API가 제공하는 것까지(표, 이미지, 목록, 코드 블록, 차트, 목차) |
| HTML-to-PDF | CSS와 렌더링 엔진 | HTML 기반 콘텐츠에 적합 | Chromium(Chrome 또는 Edge 경로) 또는 Qt 렌더링 플러그인 | 렌더링 환경에 의존, CSS 배경은 엔진마다 다름 |
| AcroForm 채우기 | 원래 양식 필드 레이아웃 | 필드 이름으로 채우기 | 추가 렌더링 엔진 없음 | 파일의 필드 정의에 종속 |
| 정적 텍스트 교체 | 원래 페이지 레이아웃 | 고정 텍스트 교체 | 추가 렌더링 엔진 없음 | 일반적인 동적 레이아웃 재구성 불가 |
3. HTML 및 CSS를 PDF로 변환하기
C#에서 HTML로 PDF를 생성하려면 Spire.PDF가 페이지를 렌더링 엔진에 전달하고 인쇄 결과를 저장합니다. 두 가지 엔진을 사용할 수 있습니다. ChromeHtmlConverter는 Chromium을 구동하며 Chrome 또는 Edge 실행 파일 경로를 받습니다. Qt 옵션인 Spire.Additions.Qt.HtmlConverter는 공식 플러그인 패키지에 의존하며, 이 패키지에는 HTMLConverter.dll, Qt5 런타임, Html2Pdf.exe가 포함됩니다. 플러그인 폴더는 애플리케이션 실행 파일 옆에 둡니다. 폴더가 없으면 호출이 Fail to load ...\plugins\HTMLConverter.dll : error 126으로 실패합니다.
테스트에서는 같은 HTML을 두 엔진으로 전달했습니다. 둘 다 두 페이지를 생성하고 CSS page-break-before를 준수했습니다. Qt 실행은 4,398ms가 걸렸고 진한 파란색 표 헤더 배경이 그대로 유지된 60.6KB 파일을 생성했습니다. Chromium 실행은 Edge 157.0.4341.42, A4 용지, 0.4인치 여백을 사용했으며 머신에 이미 설치된 브라우저를 재사용했습니다.
두 경로는 서로 다르게 상충합니다. Qt는 별도의 플러그인 설치를 요구하는 반면, Chromium은 Chrome 또는 Edge 설치를 재사용합니다. 각 엔진은 CSS 배경 인쇄에 대한 자체 규칙이 있으며, 스타일시트가 무엇을 요청할지 결정합니다. 예를 들어 print-color-adjust: exact를 사용합니다. 웹 애플리케이션에서는 요청 내부가 아니라 백그라운드 작업으로 변환을 실행하십시오.

다음 항목들은 다루지 않았습니다. JavaScript에 의존해 렌더링되는 페이지, 외부 리소스, 사용자 지정 글꼴, 서버의 동시 부하, Linux 또는 Docker. 개발 머신에서 실행되는 변환기가 프로덕션 컨테이너에서도 실행된다는 것을 보여 주지 않으며, 이 가이드는 Linux를 검증하지 않았습니다. 전체 안내가 포함된 템플릿 기반 페이지는 C#에서 HTML 템플릿으로 PDF 생성하기를 참조하십시오.
4. 기존 PDF 양식 및 템플릿 다루기
템플릿이 이미 PDF일 때 C#에서 템플릿으로 PDF를 생성한다는 것은 두 가지 다른 의미입니다. 채울 수 있는 양식은 이름이 지정된 AcroForm 필드 객체를 가집니다. 디자인된 페이지는 빈칸처럼 보이는 자리 표시자 텍스트만 가질 수 있습니다. 화면에서는 비슷해 보이지만 코드에서는 다르게 동작합니다.
| 속성 | AcroForm 필드 | 정적 자리 표시자 텍스트 |
|---|---|---|
| 파일에 존재하는 형태 | 자체 이름을 가진 필드 객체 | 일반 페이지 텍스트 |
| 찾는 방법 | 필드 이름 | 텍스트 자체 |
| 상호 작용성 | 평면화하기 전까지 유지 | 상호 작용 불가 |
| 평면화 후 | 값이 페이지 텍스트가 됨 | 해당 없음 |

실제 필드는 이름으로 찾고 채운 뒤 선택적으로 평면화합니다. Spire.Pdf.Interactive.Forms 네임스페이스의 AcroForm API는 12.10.7에서 등장했으며 12.11.0에서 테스트했습니다.
using Spire.Pdf.Interactive.Forms;
PdfDocument doc = new PdfDocument();
doc.LoadFromFile("existing-form.pdf");
PdfForm form = PdfForm.Create(doc);
var field = form.GetField("team") as PdfTextField;
field.Text = "Release QA";
field.RefreshAppearances(); // without this the value is stored but renders invisible
form.Flatten(); // after this the value sits in the page text layer
doc.SaveToFile("final.pdf");
테스트에서 세 가지 동작이 나타났습니다.
-
Text를 설정한 후RefreshAppearances()를 호출해야 값이 필드의 어피어런스에 그려져 즉시 표시됩니다. - 여전히 상호 작용 가능한 필드의 값은 양식 레이어에 있습니다. 평면화 후 필드 수는 4에서 0이 되었고 값은 페이지 텍스트에 합쳐졌으며,
PdfTextExtractor가 이를 읽을 수 있었습니다. -
AddWidget은 페이지 수준 좌표를 사용하는 반면page.Canvas위치는 여백 기준이므로 위젯 배치 시 두 좌표계를 분리해 유지하십시오.

양식 데이터는 form.ExportData(path, DataFormat.XFDF, ...)를 통해 XFDF로 파일 밖으로 내보낼 수도 있으며, 테스트에서 표준 XFDF를 생성했습니다. PDF 양식 데이터 가져오기 및 내보내기 튜토리얼에서 더 자세히 다룹니다.
고정 자리 표시자 텍스트는 삽입하는 값이 교체하는 표식과 크기가 비슷할 때 완성된 페이지에서 작동합니다. 교체는 원래 레이아웃을 유지하므로 각 새 값이 원본이 남긴 공간에 맞는지 확인하십시오.
XFA 양식은 별도의 양식 유형입니다. 문서화된 기능은 XFA 양식 객체를 통해 지원되는 필드를 읽고 수정하는 것입니다. 평가의 일부로 자체 샘플을 사용해 워크플로를 검증하십시오.
5. 배포 및 출력 검증
이 가이드의 모든 것은 Windows 개발 머신에서 실행되었습니다. Linux, Docker, 서버 호스팅은 이 가이드에서 검증하지 않았습니다. HTML 엔진은 다른 곳에서 가장 많은 주의가 필요합니다. Chromium 경로는 대상 머신에 브라우저 실행 파일이 필요하고, Qt 경로는 애플리케이션 옆에 플러그인 폴더가 필요합니다. Spire.PDF는 Linux 및 macOS용 공식 플러그인 패키지를 게시합니다. 의존하기 전에 자체 배포 이미지에서 테스트하고, 위 시간 측정값은 개발 머신에서 나온 것이므로 대상 호스트에서 변환 시간을 측정하십시오.
생성 문제는 예외를 거의 발생시키지 않습니다. 파일은 생성되고, 잘못된 것은 출력물 자체에서만 드러납니다. 그래서 아래 검사들은 코드가 오류 없이 실행되었는지에 의존하지 않고 파일을 검사합니다.
| 검사 | 잡아내는 문제 | 방법 |
|---|---|---|
| 페이지 수 | 너무 길게 진행되거나, 일찍 멈추거나, 전혀 진행되지 않은 페이지 나눔 | check.Pages.Count |
| 텍스트 추출 | 누락된 제목이나 데이터, 남아 있는 자리 표시자 표식 | 각 페이지에 PdfTextExtractor 적용 |
| 양식 검증 | 필드에 도달하지 못한 값 | 평면화 전에 API로 필드 값 읽기, 평면화 후 파일을 다시 열어 표시되는 콘텐츠 확인 |
| 육안 검사 | 텍스트 넘침, 잘못된 페이지 나눔, 대체된 글꼴, 누락된 이미지 | PDF를 열어 모든 페이지 확인 |
PdfDocument check = new PdfDocument();
check.LoadFromFile("QA-Report.pdf");
Console.WriteLine(check.Pages.Count); // expected page count
string text = new PdfTextExtractor(check.Pages[0])
.ExtractText(new PdfTextExtractOptions()); // titles, data, leftovers
Console.WriteLine(text.Contains("#")); // a stray placeholder marker
텍스트 추출은 페이지를 직접 보는 것을 대체하지 않습니다. 파일에 문자가 존재하는지만 확인하며, 넘침, 잘림, 인쇄되지 않은 헤더 배경에 대해서는 아무것도 말해 주지 않습니다. 검사를 워크플로에 맞추십시오. 좌표 및 흐름 출력에는 페이지 수와 육안 검사, HTML 출력의 배경에는 육안 검사, 양식에는 평면화 전 API 읽기 확인을 적용하십시오. 보고서 작업의 경우 테스트 파이프라인에서 처음 세 가지 검사를 실행하고 템플릿이나 레이아웃이 변경될 때마다 육안 검사를 반복하십시오. 워크플로별로 알려진 정상 출력 하나를 유지하고 라이브러리 업그레이드 후 비교하십시오. 여기의 모든 결과는 12.11.0에 연결되어 있기 때문입니다.
6. FAQ
C#에서 PDF를 생성하는 것과 만드는 것의 차이는 무엇입니까?
API 수준에서는 차이가 없습니다. 두 표현 모두 코드로 PDF 파일을 만드는 것을 뜻합니다. 중요한 것은 입력입니다. 애플리케이션 데이터, HTML 페이지, 또는 필드나 자리 표시자 텍스트가 있는 기존 PDF입니다. 이 가이드의 의사 결정 표에서 보듯이 그 입력에서 워크플로를 선택하십시오.
라이브러리 없이 C#에서 PDF를 생성할 수 있습니까?
기술적으로는 가능합니다. PDF는 코드로 직접 작성할 수 있는 문서화된 파일 형식이기 때문입니다. 실제로는 비용이 글꼴 임베딩, 스트림 압축, 텍스트 추출 지원, 뷰어 간 렌더링 일관성에 발생합니다. 각각은 자체 코드와 테스트가 필요하며 라이브러리가 그 작업을 흡수합니다.
코드 기반 생성과 HTML 렌더링 중에서 어떻게 선택합니까?
레이아웃을 누가 소유하는지로 결정하십시오. 개발자가 소유하고 데이터가 구조를 형성한다면 코드로 PDF를 생성하십시오. 디자이너가 이미 HTML과 CSS를 유지 관리한다면 그 페이지를 렌더링하고 렌더링 엔진 의존성을 수용하십시오. 데이터가 페이지를 정의할 때는 코드를, 페이지가 출력을 정의할 때는 HTML을 선택하십시오.
7. 결론
애플리케이션 데이터는 좌표 기반 그리기 또는 네이티브 흐름 레이아웃을 가리키며, 흐름 레이아웃은 테스트에서 스스로 페이지를 나눴습니다. HTML 페이지는 렌더링 엔진을 가리키며, 테스트에서 변환 시간, 배경 인쇄, 대상 머신에 필요한 것이 달라졌습니다. 기존 PDF는 필드가 있으면 양식 필드를, 레이아웃이 고정되어 있으면 텍스트 교체를 가리킵니다. 이 파일들 중 어느 것이든 배포되기 전에 페이지 수, 추출된 텍스트, 렌더링된 페이지를 확인하십시오.
실제 비즈니스 환경에서 Spire.PDF for .NET을 테스트해야 한다면 임시 라이선스를 신청할 수 있습니다.