2026년에 독일 B2B 고객에게 전자 인보이스를 보낸다면, 파일은 ZUGFeRD를 준수하거나 수신 단계에서 반려됩니다. 프랑스의 Factur-X도 마찬가지입니다. 형식은 EN 16931 CII XML을 첨부한 PDF/A-3 래퍼입니다. 처음부터 만들기는 쉽지 않고, 검증에는 레퍼런스 엔진이 필요합니다.
실무에서 그 레퍼런스 엔진은 Mustang(mustangproject.org)입니다. Mustang은 PDF/A-3에서 내장 XML을 추출하고 EN 16931 Schematron에 대해 검증하는 오픈 소스 Java 프로젝트입니다. 오픈 소스 도구 중 ZUGFeRD와 Factur-X 지원이 가장 깊고, 독립 검증기관 상당수가 Mustang을 실행합니다.
이 글은 Mustang이 표시하는 실패 유형과 더 빠르게 실행하는 방법을 설명합니다.
Mustang이 실제로 확인하는 것
Factur-X 또는 ZUGFeRD PDF를 Mustang에 넣으면 대략 다음을 수행합니다.
- 내장 파일 추출. PDF/A-3는 첨부 파일을
/EmbeddedFiles이름 트리에 저장합니다. Mustang은 표준 파일명(Factur-X는factur-x.xml, ZUGFeRD 2.x는zugferd-invoice.xml)을 찾아 바이트를 꺼냅니다. - AFRelationship 확인. 첨부 파일은 Factur-X / ZUGFeRD 기준에 따라
AFRelationship="Alternative"로 선언되어야 합니다. 다른 값(Source,Data,Supplement)은 실패입니다. - XMP 네임스페이스와 버전 확인. Factur-X 1.0은
urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#를 사용합니다. ZUGFeRD 2.x는urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#를 사용합니다. 네임스페이스나 버전 문자열이 틀리면 실패합니다. - XML을 Cross-Industry Invoice(CII)로 파싱. XML은 올바른 형식이어야 하고, 올바른 CII 루트 요소(
rsm:CrossIndustryInvoice)로 시작해야 합니다. - EN 16931 Schematron 실행. 검증의 대부분을 차지합니다. 필드 의미, 필수 코드, 합계 계산, VAT 로직, 거래 당사자 식별자 등을 다루는 약 200개의 비즈니스 규칙을 확인합니다.
Pass는 인보이스가 EU 전역의 EN 16931 준수 AP 시스템에서 받아들여질 수 있다는 뜻입니다. Fail은 고객의 AP 자동화가 수신 시 인보이스를 거부하고, 매출채권(AR) 팀이 수동 예외를 처리해야 한다는 뜻입니다.
가장 자주 보는 다섯 가지 실패 유형
팀들이 첫 전자 인보이스를 테스트할 때 validator의 Mustang 쪽에서 반복적으로 나타나는 항목입니다.
1. Wrong AFRelationship
ERROR: Embedded file factur-x.xml uses AFRelationship="Source",
expected "Alternative".
PDF 사양은 첨부 파일에 여러 관계 유형을 허용합니다. Factur-X / ZUGFeRD는 구체적으로 Alternative를 요구합니다. 첨부 XML이 사람이 보는 PDF 내용의 대체 표현이라는 뜻입니다. PDF 생성기가 Data를 사용하도록 설정되어 있다면(많은 라이브러리의 기본값), Mustang은 즉시 실패합니다. 사람이 보는 PDF는 정상 표시되지만, 구조화된 전송 데이터는 AP 시스템에서 사용할 수 없습니다.
2. Wrong / missing XMP namespace
ERROR: XMP metadata missing fx:DocumentType or fx:DocumentFileName under
namespace urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#.
PDF의 XMP 패킷은 이 파일이 어떤 Factur-X 프로파일인지(예: MINIMUM, BASIC, EN 16931, EXTENDED)와 어떤 파일명을 찾아야 하는지 선언해야 합니다. PDF/A-3 래퍼를 직접 작성할 때 놓치기 쉽습니다. gPdf의 /api/v1/e-invoice/render 엔드포인트는 이를 자동으로 내보냅니다.
3. CII XML 형식은 맞지만 EN 16931 Schematron 실패
ERROR: BR-CO-25 — In an invoice (BR-01) the
ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime is required when
ram:DocumentTypeCode is 380.
현실의 실패 대부분이 여기에 속합니다. XML 문법은 유효하지만 비즈니스 규칙이 실패합니다. EN 16931 Schematron 규칙에는 BR-01, BR-CO-25 같은 안정적인 ID가 있어 EN 16931 사양에서 찾아볼 수 있습니다. 흔한 항목은 다음과 같습니다.
- BR-01: 인보이스에는 고유한 인보이스 번호가 있어야 합니다.
- BR-04: 인보이스에는 발행일이 있어야 합니다.
- BR-05: 인보이스에는 인보이스 유형 코드가 있어야 합니다.
- BR-CO-25: 문서 유형이 “Commercial invoice“이면 결제 조건이 필요합니다.
- BR-Z-01: VAT 카테고리 코드는
S,Z,E,AE,K,G,O,L,M중 하나여야 합니다.
기준 데이터를 고치고, 다시 생성하고, 다시 검증하세요.
4. PDF/A 래퍼 자체가 검증을 통과하지 않음
INFO: CII XML extracted and validates against EN 16931.
ERROR: PDF/A-3b conformance check failed: missing Output Intent.
Mustang의 XML 검사는 통과하지만 그 아래의 PDF/A-3 래퍼가 실패하는 경우입니다. 흔한 원인은 누군가 XML은 제대로 작성했지만 PDF/A-3가 아니라 일반 PDF를 내보낸 것입니다. 내장 파일은 존재하지만 보관 래퍼 규칙을 만족하지 못합니다. gpdf.com/validator/는 veraPDF를 병렬로 실행해 이를 잡아냅니다. PDF/A-3 실패는 veraPDF 열에 표시되고 Mustang은 XML 통과를 보고합니다.
5. 인코딩 / 선언 불일치
ERROR: XML declares <?xml version="1.0" encoding="UTF-8"?> but the
embedded byte stream is UTF-8 with BOM. Mustang strict mode rejects BOM.
XML 생성 도구가 UTF-8 BOM을 내보낸 뒤 그 바이트를 그대로 내장할 때 의외로 자주 생기는 문제입니다. 해결책은 내장하기 전에 BOM을 제거하는 것입니다(gPdf의 전자 인보이스 엔드포인트는 이를 정규화합니다).
Java 설치 없이 Mustang 실행하기
일회성 점검이라면 Java와 Mustang CLI를 설치해도 괜찮습니다. 하지만 지속적인 검증, 즉 인보이스를 생성할 때마다 또는 CI에서 전자 인보이스 준수를 확인할 때마다 실행해야 한다면 굳이 그런 번거로움을 감수할 필요가 없습니다.
gpdf.com/validator/는 Mustang을 브라우저에서 실행합니다.
- Factur-X / ZUGFeRD PDF를 업로드 영역에 끌어다 놓습니다.
- 검증기가 내장 XML을 추출하고 Mustang의 Schematron 엔진을 실행합니다(JavaScript / WebAssembly로 컴파일되어 Cloudflare Worker에서 실행).
- Mustang 보고서는 veraPDF의 PDF/A-3 보고서와 나란히 돌아옵니다(두 계층이 모두 통과해야 하기 때문입니다).
- QA 증거로 쓸 JSON 보고서를 다운로드합니다.
로그인 없음. 사용량 제한 없음. Maven으로 설치하는 Mustang과 같은 엔진을 무료 공개 서비스로 제공하는 방식입니다.
TL;DR
Mustang은 다섯 가지 흔한 실패 유형을 표시합니다. 대부분은 “완전히 준수하는 Factur-X / ZUGFeRD PDF/A-3를 내보내지 못하는 도구로 파일을 만들었다“는 문제로 귀결됩니다. gPdf E-invoice API는 이를 한 번의 호출로 생성합니다. validator는 Mustang + veraPDF 두 엔진을 병렬로 실행해 결과를 검증합니다.
Mustang이 잡는 오류 대부분은 XML 의미 자체보다 래퍼 또는 AFRelationship 문제입니다. 파일을 올바르게 생성하는 것이 대부분의 작업이고, 검증기는 그 사실을 증명하는 증빙입니다.