IronWord 사용하여 C#에서 입력 가능한 양식 템플릿을 만드는 방법
수년간, 대규모로 개인화된 Word 문서를 생성해야 했던 .NET 팀은 두 가지 진짜 옵션이 있었고, 둘 다 좋지 않았습니다.
첫 번째는 COM 상호 운용을 통해 Microsoft Word 자체를 자동화하는 것이었습니다. 처음에는 잘 작동했지만, 그 이후로는 그렇지 못했습니다. Word 간 상호 운용은 느리고, 불안정하며, 각 기기에 Word 라이선스가 필요하고, Linux 컨테이너, Azure 기능, 또는 Word가 설치되지 않은 모든 서버 환경에서 실행하려고 할 때 문제가 발생합니다. 이를 시도했던 대부분의 팀은 결국 이를 피하기 위해 다시 작성했습니다.
두 번째는 사용자 정의 찾기 및 바꾸기 파이프라인이었습니다. .docx를 XML 또는 텍스트로 읽고, 플레이스홀더 토큰을 실제 값으로 교체한 다음 결과를 저장합니다. 간단한 경우에는 효과가 있었지만, 복잡한 필드 구조를 사용하는 실제 Word 문서에서는 실패했습니다. 이러한 구조는 개발자가 기대하는 단순한 {{FirstName}} 토큰과는 전혀 다르게 생겼습니다.
IronWord는 이제 메일 병합을 기본적으로 지원합니다. Microsoft Word에서 디자인된 템플릿은 Word 자체가 생성한 같은 병합 필드 구문을 사용하여 .NET 코드에서 직접 채워지며, Word 설치가 필요 없습니다.
기능 설명
메일 병합 엔진은 Word가 생성하는 두 가지 스타일의 병합 필드를 처리합니다.
- "FieldName" 형식의 간단한 필드로, 이는 템플릿에 <
> 형식을 직접 타이핑하여 얻는 것입니다. - 복잡한 필드로, 삽입 → 빠른 부분 → 필드를 통해 Word가 생성한 다중 요소 XML 구조
템플릿은 문서당 한 번 교체되는 단일 값 플레이스홀더와, "TableStart:Name" 및 "TableEnd:Name" 마커로 경계가 지정된 반복 구역을 포함할 수 있으며, 이는 데이터 레코드별로 한 행으로 확장됩니다.
두 번째 부분이 이 기능이 자리를 차지하는 이유입니다. 반복 구역은 청구서의 한 템플릿 행이 50개 행의 품목 테이블로 확장되는 방식이거나, 라벨 시트의 한 연락처 슬롯이 데이터베이스로부터 채워진 전체 Avery 그리드가 되는 방식입니다.
CRM에서의 개인화된 양식 서신
대부분의 팀은 영업 운영을 통해 메일 병합을 처음 수행합니다. CRM은 고객 기록을 보유하고 있습니다. 마케팅이나 영업 운영은 개인화된 양식 서신, 환영 패킷, 갱신 통지를 보내야 합니다. 패턴은 간단합니다: 하나의 템플릿, 고객당 하나의 행, 하나의 개인화된 문서가 나옵니다.
// Template: "Dear «FirstName», thank you for your order of «Amount»..."
DataTable customers = LoadFromSalesforce(); // FirstName, LastName, Amount, ...
foreach (DataRow row in customers.Rows)
{
var doc = new WordDocument("cover-letter-template.docx");
doc.MailMerge.Execute(row);
doc.SaveAs($"letters/{row["LastName"]}.docx");
}
// Template: "Dear «FirstName», thank you for your order of «Amount»..."
DataTable customers = LoadFromSalesforce(); // FirstName, LastName, Amount, ...
foreach (DataRow row in customers.Rows)
{
var doc = new WordDocument("cover-letter-template.docx");
doc.MailMerge.Execute(row);
doc.SaveAs($"letters/{row["LastName"]}.docx");
}
Imports System.Data
' Template: "Dear «FirstName», thank you for your order of «Amount»..."
Dim customers As DataTable = LoadFromSalesforce() ' FirstName, LastName, Amount, ...
For Each row As DataRow In customers.Rows
Dim doc As New WordDocument("cover-letter-template.docx")
doc.MailMerge.Execute(row)
doc.SaveAs($"letters/{row("LastName")}.docx")
Next
데이터 소스는 DataTable입니다. Salesforce, HubSpot, SQL Server, CSV, API 응답 등을 로드하면 추가 어댑터 코드 없이 메일 병합 소스가 됩니다.
반복 항목이 있는 송장
반복 구역 기능이 빛을 발휘하는 것은 송장입니다. 송장 템플릿에는 헤더(고객명, 주문 ID, 날짜), 품목 테이블의 한 행, 그리고 푸터(총계)가 있습니다. 병합이 실행되면, 템플릿의 한 행이 모든 제품에 대해 행간 제품 수와 무관하게 확장됩니다.
// Template:
// Bill To: «CustomerName» Order: «OrderId»
// ┌──────────┬─────┬──────────┐
// │ «TableStart:Items»«Product» │ «Qty» │ «LineTotal» «TableEnd:Items» │
// └──────────┴─────┴──────────┘
// Total: «Total»
var doc = new WordDocument("invoice-template.docx");
doc.MailMerge.ExecuteWithRegions(orderLineItems); // one row per product
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "CustomerName", "Acme Industries" },
{ "OrderId", "10444" },
{ "Total", "$1,117.71" },
});
doc.SaveAs("invoice-10444.docx");
// Template:
// Bill To: «CustomerName» Order: «OrderId»
// ┌──────────┬─────┬──────────┐
// │ «TableStart:Items»«Product» │ «Qty» │ «LineTotal» «TableEnd:Items» │
// └──────────┴─────┴──────────┘
// Total: «Total»
var doc = new WordDocument("invoice-template.docx");
doc.MailMerge.ExecuteWithRegions(orderLineItems); // one row per product
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "CustomerName", "Acme Industries" },
{ "OrderId", "10444" },
{ "Total", "$1,117.71" },
});
doc.SaveAs("invoice-10444.docx");
Imports System.Collections.Generic
' Template:
' Bill To: «CustomerName» Order: «OrderId»
' ┌──────────┬─────┬──────────┐
' │ «TableStart:Items»«Product» │ «Qty» │ «LineTotal» «TableEnd:Items» │
' └──────────┴─────┴──────────┘
' Total: «Total»
Dim doc As New WordDocument("invoice-template.docx")
doc.MailMerge.ExecuteWithRegions(orderLineItems) ' one row per product
doc.MailMerge.Execute(New Dictionary(Of String, String) From {
{"CustomerName", "Acme Industries"},
{"OrderId", "10444"},
{"Total", "$1,117.71"}
})
doc.SaveAs("invoice-10444.docx")
같은 패턴은 견적서, 구매 주문서, 명세서, 가변 길이 목록이 고정된 모양 페이지 안에 있는 모든 문서에 적용됩니다.
Avery 라벨 시트 및 봉투
운송 및 운영 팀은 연락처 목록에서 라벨과 봉투를 생성하며, Avery 5160, 5161, 5163와 그들의 국제적 등가물은 수십 년간 존재해온 표준화된 템플릿입니다. IronWord는 그것들을 직접 채워 넣습니다. 라벨 그리드의 각 셀은 단일 API 호출에서 적절한 연락처를 가져옵니다.
// Template: a 3×10 Avery 5160 grid, each cell has «CONTACT_FULLNAME» / «CONTACT_ADDRESS»
var doc = new WordDocument("avery-5160.docx");
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "CONTACT_FULLNAME", "Jane Doe" },
{ "CONTACT_ADDRESS", "100 Main Street, Boston, MA 02108" },
});
doc.SaveAs("labels-jane.docx");
// Template: a 3×10 Avery 5160 grid, each cell has «CONTACT_FULLNAME» / «CONTACT_ADDRESS»
var doc = new WordDocument("avery-5160.docx");
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "CONTACT_FULLNAME", "Jane Doe" },
{ "CONTACT_ADDRESS", "100 Main Street, Boston, MA 02108" },
});
doc.SaveAs("labels-jane.docx");
Imports System.Collections.Generic
' Template: a 3×10 Avery 5160 grid, each cell has «CONTACT_FULLNAME» / «CONTACT_ADDRESS»
Dim doc As New WordDocument("avery-5160.docx")
doc.MailMerge.Execute(New Dictionary(Of String, String) From {
{"CONTACT_FULLNAME", "Jane Doe"},
{"CONTACT_ADDRESS", "100 Main Street, Boston, MA 02108"}
})
doc.SaveAs("labels-jane.docx")
가변 길이 연락처 목록의 경우, 송장 예제의 ExecuteWithRegions 패턴이 적용됩니다: 하나의 셀을 반복 단위로 정의하고, 나머지 시트는 자동으로 채워집니다.
다중 구역 보고서
가장 강력한 응용 프로그램은 다중 구역 보고서입니다. 분기 요약에는 각자 자체 데이터 테이블에 의해 구동되는 "상위 고객" 및 "상위 제품" 섹션이 포함될 수 있습니다. DataSet이 여러 테이블을 포함할 때, 병합은 단일 호출에서 두 구역 모두를 확장시킵니다.
// Template:
// Top Customers
// «TableStart:Customers» • «Name» | «City» | «Revenue» «TableEnd:Customers»
// Top Products
// «TableStart:Products» «ProductName»: «Revenue» «TableEnd:Products»
var ds = new DataSet();
ds.Tables.Add(topCustomers); // TableName = "Customers"
ds.Tables.Add(topProducts); // TableName = "Products"
var doc = new WordDocument("quarterly-report.docx");
doc.MailMerge.ExecuteWithRegions(ds); // expands both regions
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "CompanyName", "Iron Software" },
{ "ReportDate", "Q2 2026" },
});
doc.SaveAs("Q2-2026-report.docx");
// Template:
// Top Customers
// «TableStart:Customers» • «Name» | «City» | «Revenue» «TableEnd:Customers»
// Top Products
// «TableStart:Products» «ProductName»: «Revenue» «TableEnd:Products»
var ds = new DataSet();
ds.Tables.Add(topCustomers); // TableName = "Customers"
ds.Tables.Add(topProducts); // TableName = "Products"
var doc = new WordDocument("quarterly-report.docx");
doc.MailMerge.ExecuteWithRegions(ds); // expands both regions
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "CompanyName", "Iron Software" },
{ "ReportDate", "Q2 2026" },
});
doc.SaveAs("Q2-2026-report.docx");
Imports System.Data
Imports System.Collections.Generic
' Template:
' Top Customers
' «TableStart:Customers» • «Name» | «City» | «Revenue» «TableEnd:Customers»
' Top Products
' «TableStart:Products» «ProductName»: «Revenue» «TableEnd:Products»
Dim ds As New DataSet()
ds.Tables.Add(topCustomers) ' TableName = "Customers"
ds.Tables.Add(topProducts) ' TableName = "Products"
Dim doc As New WordDocument("quarterly-report.docx")
doc.MailMerge.ExecuteWithRegions(ds) ' expands both regions
doc.MailMerge.Execute(New Dictionary(Of String, String) From {
{"CompanyName", "Iron Software"},
{"ReportDate", "Q2 2026"}
})
doc.SaveAs("Q2-2026-report.docx")
DataSet의 각 DataTable은 해당 "TableStart:..." 구역과 이름이 일치하며, 스칼라 필드는 같은 패스에서 헤더 값을 채워줍니다.
이와 같은 문서 워크플로우를 대기하고 있는 팀에게, Iron Suite 는 IronWord를 IronPDF, IronOCR, IronXL 및 IronBarcode와 함께 하나의 라이선스로 번들화합니다.
무료 체험 시작하기, 신용 카드가 필요 없습니다.
왜 이게 작동하는가
몇 가지 차이점이 이 접근 방식을 다른 대안과 구분시킵니다:
네이티브 Word 구문. 템플릿은 Microsoft Word에서 디자인되며, Word가 이미 제공하는 병합 필드 도구를 사용합니다. .docx로 저장하고 파일을 IronWord에 전달하면 병합이 실행됩니다. 형식 특정 템플릿 언어 없음, 번역 레이어 없음, 문서를 설계하는 팀에 대한 별도의 학습 곡선 없음.
간단한 필드와 복잡한 필드 형식 모두. Word는 필드를 삽입한 방법에 따라 두 가지 개별 필드 구조를 생성합니다. IronWord는 둘 다 처리하여, 다른 팀원이 다른 방법으로 디자인한 기존 템플릿도 수정 없이 모두 작동합니다.
외부 의존성 없음. 라이브러리는 전적으로 .NET에서 실행됩니다. Word 설치 없음, COM 없음, Office 라이선스 없음, 상호 운용 불안정 없음. Windows 개발자 기계에서 실행되는 동일한 코드가 Linux 컨테이너, Azure 기능, 또는 서버리스 빌드 에이전트에서도 동일하게 실행됩니다.
요약
메일 병합은 .NET 문서 도구 공간에서 오래된 공백이었으며, 해결 방법들은 잘 오래가지 못했습니다. IronWord의 네이티브 메일 병합은 Word의 자체 병합 필드 구문을 반영하는 모델로 그 간극을 메우며, 간단한 값과 반복 구역 모두를 지원하고, .NET에서 문서 자동화와 역사적으로 함께 제공되었던 배포 관련 잡음을 전혀 포함하지 않습니다.
청구서, 라벨, 편지, 계약서, 보고서를 대규모로 생성하는 팀에게, 이는 하나의 템플릿에서 수천 개의 개인화된 문서로 가장 깔끔한 경로입니다.
자주 묻는 질문
IronWord 메일 병합이란?
IronWord 메일 병합은 Microsoft Word 설치없이도 .NET 애플리케이션에서 개인화된 Word 문서를 생성할 수 있는 기능입니다.
IronWord 메일 병합을 대량으로 문서 생성에 사용할 수 있나요?
예, IronWord 메일 병합은 대량 처리에 이상적인 대규모 개인화된 Word 문서 생성을 처리하도록 설계되었습니다.
IronWord 메일 병합을 사용하려면 Microsoft Word가 필요한가요?
아니요, IronWord 메일 병합은 Microsoft Word 설치가 필요 없으며 .NET 애플리케이션 내에서 매끄러운 문서 생성 경험을 제공합니다.
IronWord 메일 병합을 사용하여 생성할 수 있는 문서 유형은 무엇인가요?
IronWord 메일 병합은 Word 템플릿을 사용하여 청구서, 편지, 라벨 및 보고서를 포함한 다양한 문서를 생성할 수 있습니다.
IronWord 메일 병합은 .NET과 어떻게 통합되나요?
IronWord 메일 병합은 .NET에서 기본적으로 지원되어, 개발자들에게 애플리케이션 내에서 메일 병합 기능을 구현할 수 있는 간단하고 효율적인 방법을 제공합니다.
전통적인 방법에 비해 IronWord 메일 병합을 사용하는 이점은 무엇인가요?
IronWord 메일 병합을 사용하면 Microsoft Word가 필요 없어지며, 타사 소프트웨어에 대한 의존을 줄이고 .NET 애플리케이션에서 문서를 생성하는 확장 가능한 솔루션을 제공합니다.
IronWord 메일 병합을 보고서 생성에 사용할 수 있나요?
예, IronWord 메일 병합은 Word 템플릿에서 상세 보고서를 생성하는 데 사용할 수 있어 다양한 문서화 요구에 적합합니다.
IronWord 메일 병합은 자동화된 문서 생성에 적합한가요?
예, IronWord 메일 병합은 자동화된 문서 생성에 이상적이며, 개발자들이 .NET 애플리케이션 내에서 프로그램적으로 개인화된 문서를 생성할 수 있게 합니다.




