IRONSOFTWAREHOME
동영상

C#에서 사용자 지정 로깅을 사용하는 방법

Curtis Chau
Curtis Chau
Updated: 2026년 7월 19일

fo.net (FO.NET)에서 IronPDF로 마이그레이션은 .NET PDF 생성 과정의 주요 업데이트입니다. 이 가이드는 구식 XSL-FO 마크업에서 최신 HTML/CSS 기반 PDF 생성으로 코드베이스를 전환하는 간단하고 체계적인 경로를 제공합니다. 개발팀이 이미 익숙한 기술을 사용합니다.

fo.net에서 IronPDF로 마이그레이션해야 하는 이유

fo.net의 도전 과제

fo.net (FO.NET) 은 XSL-FO 문서를 PDF로 변환하는 초기 Apache FOP 빌드의 C# 포트입니다. 이는 Apache 2.0 라이선스이지만 현재 개발에는 여러 제약이 있습니다:

  1. 구식 기술: XSL-FO(Extensible Stylesheet Language Formatting Objects)는 2001년 W3C 규격입니다; W3C는 2013년에 XSL-FO 워킹 그룹을 종료했으며 이 언어는 더 이상의 개발이 없습니다.

  2. 복잡한 학습 곡선: XSL-FO는 복잡한 XML 기반 마크업을 요구하며 전문적인 포맷 객체 (fo:block, fo:table, fo:page-sequence 등)로 구성됩니다.

  3. HTML/CSS 지원 부족: fo.net은 HTML이나 CSS를 렌더링할 수 없으며, HTML을 직접 XSL-FO로 변환해야 합니다 (일반적으로 XSLT를 통해).

  4. 버려짐/관리되지 않음: nuget.org의 Fonet 패키지는 2011년 4월에 마지막으로 게시되었습니다 (v1.0.0, .NET Framework 2.0). 커뮤니티 포크 Fonet.Standard (.NET Standard 2.0)는 2020년 5월에 마지막으로 게시되었습니다 (v1.0.5). CodePlex 저장소는 폐지되었으며 GitHub 포크 (prepare/FO.NET, nholik/FO.Net, hahmed/Fo.Net)는 휴면 상태입니다.

  5. 실질적으로 Windows 전용: 레거시 Fonet 빌드는 Windows로 제한되는 System.Drawing (GDI+) API에 의존합니다.

  6. **제한된 현대 기능:**JavaScript엔진 없음, CSS3 (플렉스박스/그리드) 없음, 현대 웹폰트 로딩 없음.

  7. URL 렌더링 없음: fo.net은 웹 페이지를 직접 렌더링할 수 없으며, 수동 HTML-to-XSL-FO 변환이 필요합니다.

fo.net vsIronPDF비교

측면fo.net (FO.NET)IronPDF
입력 형식XSL-FO (구식 XML)HTML/CSS (현대 웹 표준)
학습 곡선급진적인 (XSL-FO 전문성)부드러움 (HTML/CSS 지식)
유지보수버려짐 (마지막 릴리스 2020년 5월)적극적으로 유지보수됨
플랫폼 지원Windows 전용크로스 플랫폼 (.NET Framework 4.6.2+, .NET Core 3.1+, .NET 5/6/7/8/9+)
CSS 지원None전체 CSS3 (Flexbox, Grid)
JavaScriptNone전체JavaScript지원
URL 렌더링지원되지 않음내장형
최신 기능제한적머리글, 바닥글, 워터마크, 보안
문서화구식철저한 튜토리얼

전환이 합리적인 이유

fo.net은 XSL-FO가 문서 형식 지정의 표준으로 채택될 것으로 예상될 때 설계되었습니다. 그 기대는 실현되지 않았습니다. HTML/CSS가 범용 문서 포맷이 된 반면, XSL-FO는 틈새 기지가 되었으며 — 대부분의 XSL-FO 자원은 2005–2010에 속해, 유지 관리가 점점 어려워지고 있습니다.

IronPDF은 당신이 이미 가지고 있는 기술로 현대 .NET에서 전문 PDF를 만들 수 있게 합니다.


시작하기 전에

필수 조건

  1. .NET 환경: IronPDF는 .NET Framework 4.6.2+, .NET Core 3.1+, .NET 5/6/7/8/9+를 지원합니다.
  2. NuGet 액세스: NuGet에서 패키지를 설치할 수 있는지 확인하십시오.
  3. 라이센스 키: ironpdf.com에서 제품 사용을 위한IronPDF라이센스 키를 얻으십시오.

프로젝트 백업하기

# Create a backup branch
git checkout -b pre-ironpdf-migration
git add .
git commit -m "Backup before fo.net toIronPDF migration"
SHELL

모든 fo.net 사용 식별

# Find all fo.net references
grep -r "FonetDriver\|Fonet\|\.fo\"\|xsl-region" --include="*.cs" --include="*.csproj" .

# Find all XSL-FO template files
find . -name "*.fo" -o -name "*.xslfo" -o -name "*xsl-fo*"
SHELL

XSL-FO 템플릿 문서화

마이그레이션 전에 모든 XSL-FO 파일을 카탈로그하고 다음을 기록하십시오:

  • 페이지 치수 및 여백
  • 사용된 글꼴
  • 테이블 및 그 구조
  • 헤더와 푸터 (fo:static-content)
  • 페이지 번호 매기기 패턴
  • 이미지 참조

빠른 시작 마이그레이션

1단계: NuGet 패키지 업데이트

# Remove fo.net package
dotnet remove package Fonet
dotnet remove package FO.NET

# Install IronPDF
dotnet add package IronPdf
SHELL

단계 2: 네임스페이스 업데이트

// Before (fo.net)
using Fonet;
using Fonet.Render.Pdf;
using System.Xml;

// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;

3단계:IronPDF초기화

// Set license key at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

4단계: 기본 변환 패턴

// Before (fo.net with XSL-FO)
FonetDriver driver = FonetDriver.Make();
using (FileStream output = new FileStream("output.pdf", FileMode.Create))
{
    driver.Render(new StringReader(xslFoContent), output);
}

// After (IronPDF with HTML)
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");

완전한 API 참조

네임스페이스 매핑

fo.net 네임스페이스IronPDF 동등
FonetIronPdf
Fonet.Render.PdfIronPdf
Fonet.Layout해당 없음
Fonet.Fo해당 없음
Fonet.ImageIronPdf

FonetDriver에서 ChromePdfRenderer로

FonetDriver 메서드IronPDF 동등
FonetDriver.Make()new ChromePdfRenderer()
driver.Render(inputStream, outputStream)renderer.RenderHtmlAsPdf(html)
driver.Render(inputFile, outputStream)renderer.RenderHtmlFileAsPdf(path)
driver.BaseDirectoryRenderingOptions.BaseUrl
driver.OnError += handler렌더 시도/캐치

RenderingOptions (PDF 구성)

fo.net (XSL-FO 속성)IronPDF RenderingOptions
page-heightPaperSize 또는 SetCustomPaperSize()
page-widthPaperSize
margin-topMarginTop
margin-bottomMarginBottom
margin-leftMarginLeft
margin-rightMarginRight
reference-orientationPaperOrientation

XSL-FO에서 HTML로 변환 가이드

XSL-FO 요소를 HTML/CSS로

이 fo.net 마이그레이션의 근본적인 변화는 XSL-FO 요소를 그에 상응하는 HTML로 변환하는 것입니다:

XSL-FO 요소HTML/CSS 상응
<fo:root><html>
<fo:layout-master-set>CSS @page 규칙
<fo:simple-page-master>CSS @page
<fo:page-sequence><body> 또는 <div>
<fo:flow><main> 또는 <div>
<fo:static-content>HtmlHeaderFooter
<fo:block><p>, <div>, <h1>-<h6>
<fo:inline><span>
<fo:table><table>
<fo:table-row><tr>
<fo:table-cell><td>, <th>
<fo:list-block><ul>, <ol>
<fo:list-item><li>
<fo:external-graphic><img>
<fo:page-number>{page} 플레이스홀더
<fo:page-number-citation>{total-pages}
<fo:basic-link><a href>

XSL-FO 속성을 CSS로

XSL-FO 속성CSS 동등예시
font-familyfont-family동일한 구문
font-sizefont-size동일한 구문
font-weightfont-weightbold, normal, 700
text-aligntext-alignleft, center, right, justify
colorcolor16진수, RGB, 이름
background-colorbackground-color동일한 구문
space-beforemargin-top요소 이전
space-aftermargin-bottom요소 이후
start-indentmargin-left왼쪽 들여쓰기
keep-togetherpage-break-inside: avoid중단 방지
break-before="page"page-break-before: always페이지 강제 중단

코드 예제

예제 1: 기본 HTML에서 PDF로

이전 (fo.net과 XSL-FO):

// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
using System.Xml;

class Program
{
    static void Main()
    {
        // fo.net requires XSL-FO format, not HTML
        // First convert HTML to XSL-FO (manual process)
        string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
            <fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
                <fo:layout-master-set>
                    <fo:simple-page-master master-name='page'>
                        <fo:region-body/>
                    </fo:simple-page-master>
                </fo:layout-master-set>
                <fo:page-sequence master-reference='page'>
                    <fo:flow flow-name='xsl-region-body'>
                        <fo:block>Hello World</fo:block>
                    </fo:flow>
                </fo:page-sequence>
            </fo:root>";
        
        FonetDriver driver = FonetDriver.Make();
        driver.Render(new StringReader(xslFo), 
            new FileStream("output.pdf", FileMode.Create));
    }
}

이후 (IronPDF와 HTML):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        string html = "<h1>Hello World</h1><p>This is HTML content.</p>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
    }
}

IronPDF 접근 방식을 사용하면 25개 이상의 XSL-FO 마크업 줄을 단 4개의 깔끔한 C# 코드 줄로 줄일 수 있습니다. 더 많은 HTML에서 PDF로의 옵션에 대해서는 IronPDF HTML에서 PDF로의 문서를 참조하세요.

예제 2: 사용자 정의 설정을 사용한 PDF

이전 (fo.net과 XSL-FO):

// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;

class Program
{
    static void Main()
    {
        // fo.net settings are configured in XSL-FO markup
        string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
            <fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
                <fo:layout-master-set>
                    <fo:simple-page-master master-name='A4' 
                        page-height='297mm' page-width='210mm'
                        margin-top='20mm' margin-bottom='20mm'
                        margin-left='25mm' margin-right='25mm'>
                        <fo:region-body/>
                    </fo:simple-page-master>
                </fo:layout-master-set>
                <fo:page-sequence master-reference='A4'>
                    <fo:flow flow-name='xsl-region-body'>
                        <fo:block font-size='14pt'>Custom PDF</fo:block>
                    </fo:flow>
                </fo:page-sequence>
            </fo:root>";
        
        FonetDriver driver = FonetDriver.Make();
        driver.Render(new StringReader(xslFo), 
            new FileStream("custom.pdf", FileMode.Create));
    }
}

이후 (IronPDF와 HTML):

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.MarginTop = 20;
        renderer.RenderingOptions.MarginBottom = 20;
        renderer.RenderingOptions.MarginLeft = 25;
        renderer.RenderingOptions.MarginRight = 25;
        
        string html = "<h1 style='font-size:14pt'>Custom PDF</h1>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("custom.pdf");
    }
}

IronPDF는 XML 마크업에 설정을 포함시키는 대신 프로그래밍 가능한 렌더링 옵션을 제공합니다.

예제 3: URL을 PDF로

이전 (fo.net - 지원하지 않음):

// NuGet: Install-Package Fonet
using Fonet;
using System.IO;
using System.Net;

class Program
{
    static void Main()
    {
        // fo.net does not support URL rendering directly
        // Must manually download, convert HTML to XSL-FO, then render
        string url = "https://example.com";
        string html = new WebClient().DownloadString(url);
        
        // Manual conversion from HTML to XSL-FO required (complex)
        string xslFo = ConvertHtmlToXslFo(html); // Not built-in
        
        FonetDriver driver = FonetDriver.Make();
        driver.Render(new StringReader(xslFo), 
            new FileStream("webpage.pdf", FileMode.Create));
    }
    
    static string ConvertHtmlToXslFo(string html)
    {
        // Custom implementation required - extremely complex
        throw new System.NotImplementedException();
    }
}

이후 (IronPDF - 내장 지원):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("webpage.pdf");
    }
}

URL의 PDF 렌더링은 이 fo.net 마이그레이션에서 실용적인 장점 중 하나입니다: IronPDF가JavaScript실행을 즉시 처리합니다. URL을 PDF로 변환에 대해 더 알아보세요.

예제 4: 헤더와 푸터

이전 (fo.net과 XSL-FO):

<fo:static-content flow-name="xsl-region-before">
    <fo:block text-align="center" font-size="10pt">
        Company Name - Confidential
    </fo:block>
</fo:static-content>

<fo:static-content flow-name="xsl-region-after">
    <fo:block text-align="right" font-size="10pt">
        Page <fo:page-number/> of <fo:page-number-citation ref-id="last-page"/>
    </fo:block>
</fo:static-content>
XML

이후 (IronPDF):

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
    HtmlFragment = "<div style='text-align:center; font-size:10pt;'>Company Name - Confidential</div>",
    DrawDividerLine = true
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
    HtmlFragment = "<div style='text-align:right; font-size:10pt;'>Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};

IronPDF는 복잡한 XSL-FO 영역 정의를 간단한 HTML 헤더와 푸터로 대체합니다.

예제 5: PDF 보안

이전 (fo.net):

// fo.net has very limited PDF security options
// Must use post-processing with another library

이후 (IronPDF):

using IronPdf;

public byte[] GenerateSecurePdf(string html)
{
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf(html);

    // Set metadata
    pdf.MetaData.Title = "Confidential Report";
    pdf.MetaData.Author = "Company Name";

    // Password protection
    pdf.SecuritySettings.OwnerPassword = "owner123";
    pdf.SecuritySettings.UserPassword = "user456";

    // Restrict permissions
    pdf.SecuritySettings.AllowUserCopyPasteContent = false;
    pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint;
    pdf.SecuritySettings.AllowUserEdits = IronPdf.Security.PdfEditSecurity.NoEdit;

    return pdf.BinaryData;
}

성능 고려 사항

ChromePdfRenderer 재사용

fo.net 마이그레이션 동안 최적의 성능을 위해 ChromePdfRenderer 인스턴스를 재사용하세요:

// GOOD - Reuse the renderer
public class PdfService
{
    private static readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();

    public byte[] Generate(string html) => _renderer.RenderHtmlAsPdf(html).BinaryData;
}

// BAD - Creating new instance each time
public byte[] GenerateBad(string html)
{
    var renderer = new ChromePdfRenderer();  // Wasteful
    return renderer.RenderHtmlAsPdf(html).BinaryData;
}

단위 변환 도우미

fo.net XSL-FO는 다양한 단위를 사용합니다.IronPDF여백에 밀리미터 단위를 사용합니다. 여기에 도우미 클래스가 있습니다:

public static class UnitConverter
{
    public static double InchesToMm(double inches) => inches * 25.4;
    public static double PointsToMm(double points) => points * 0.352778;
    public static double PicasToMm(double picas) => picas * 4.233;
    public static double CmToMm(double cm) => cm * 10;
}

// Usage
renderer.RenderingOptions.MarginTop = UnitConverter.InchesToMm(1);  // 1 inch

문제 해결

문제 1: 페이지 크기 차이

문제: fo.net 마이그레이션 후 PDF 페이지 크기가 다르게 보입니다.

해결: XSL-FO 페이지 크기를 정확히 매핑합니다:

// XSL-FO: page-height='11in' page-width='8.5in' (Letter)
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;

// XSL-FO: page-height='297mm' page-width='210mm' (A4)
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

// Custom size (in mm)
renderer.RenderingOptions.SetCustomPaperSize(210, 297);

문제 2: fo:block을 HTML 매핑으로

문제: <fo:block>이/가 무엇으로 바뀌어야 할지 확신이 서지 않습니다.

해결: 적절한 의미의 HTML을 사용하세요:

  • 제목: <h1> 부터 <h6>
  • 단락: <p>
  • 일반 컨테이너: <div>
  • 인라인 텍스트: <span>

문제 3: 폰트 불일치

문제: 폰트가 fo.net 출력과 다르게 보입니다.

해결: 웹 폰트를 사용하거나 CSS에서 시스템 폰트를 지정하세요:

<style>
    @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
    body { font-family: 'Roboto', Arial, sans-serif; }
</style>
HTML

문제 4: 페이지 번호가 작동하지 않음

문제: <fo:page-number/>이/가 작동하지 않습니다.

**해결책:**IronPDF플레이스홀더를 헤더/푸터에 사용하세요:

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
    HtmlFragment = "<div style='text-align:center;'>Page {page} of {total-pages}</div>",
    MaxHeight = 15  // mm
};

마이그레이션 체크리스트

사전 마이그레이션

  • 모든 XSL-FO 템플릿 파일 (.fo, .xslfo) 초록
  • 사용된 문서 페이지 크기와 여백을 기록하세요
  • 머리말/꼬리말 설정 (fo:static-content) 기록
  • 테이블 구조 및 스타일을 식별하세요
  • 프로젝트를 버전 관리에 백업하세요 -IronPDF라이센스 키를 받으세요

패키지 마이그레이션

  • Fonet 또는 FO.NET 패키지 제거: dotnet remove package Fonet
  • IronPdf Install-Package: dotnet add package IronPdf
  • 네임스페이스 임포트를 Fonet에서 IronPdf로 업데이트
  • 시작 시IronPDF라이센스 키를 설정하세요

코드 마이그레이션

  • FonetDriver.Make()을/를 new ChromePdfRenderer()(으)로 대체
  • driver.Render()을/를 renderer.RenderHtmlAsPdf()(으)로 대체
  • 파일 출력을 스트림에서 pdf.SaveAs()로 업데이트
  • 오류 이벤트 처리기를 try/catch로 교체하세요
  • fo:static-content을/를 HtmlHeaderFooter로 변환
  • <fo:page-number/>을/를 {page} 플레이스홀더로 대체

테스트

  • 출력 모습이 원래의 fo.net PDF와 동일한지 비교하세요
  • 페이지 크기와 여백을 확인하세요
  • 헤더와 푸터를 확인하세요
  • 페이지 번호를 검증하세요
  • 테이블 렌더링을 테스트하세요
  • 이미지 로딩을 확인하세요

마이그레이션 이후

  • .fo.xslfo 템플릿 파일 삭제
  • fo.net 관련 코드 및 유틸리티를 제거하세요
  • 문서 업데이트

IronPDF에서 사용된IronPDF표면에 대한 더 깊은 커버리지를 위해 IronPDF API 레퍼런스를 참조하십시오.

참고해 주세요: FO.NET, Fonet, 및 Apache FOP는 그 소유자의 상표입니다. 이 사이트는 FO.NET 프로젝트나 Apache Software Foundation과 관련이 없으며, 승인받지 않았고, 후원받지도 않았습니다. 모든 제품명, 로고 및 브랜드는 해당 소유자의 자산입니다. 비교는 정보 제공 목적으로만 사용되며, 작성 시점에 공개적으로 이용 가능한 정보를 반영합니다.
Curtis Chau
기술 문서 작성자

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

...
더 읽어보기

관련 기사

Key in blue circle

무료 30일 체험 키를 즉시 받으세요.

Your trial license will be sent to your email address

제한 없음. 100% 무제한 이용. 신용카드 불필요.

bullet_checked신용카드나 계정 생성은 필요하지 않습니다.제한 없음. 100% 무제한 이용. 신용카드 불필요.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
무료 라이브 데모를 예약하세요
Booking Badge

전 세계 수백만 엔지니어들이 신뢰하는 제품입니다.

Iron Software의 고객 로고
부담 없는 무료 상담을 받아보세요
아래 양식을 작성하시거나 sales@ironsoftware.com으로 이메일을 보내주세요.
고객님의 정보는 항상 비밀로 유지됩니다.
전 세계 수백만 엔지니어들이 신뢰하는 제품입니다.
Iron Software의 고객 로고
지금 바로 30일 무료 체험판 키를 받으세요.
신용카드나 계정 생성은 필요하지 않습니다.