PDF는 PDF/A-3를 준수하거나 준수하지 않습니다. 그렇다면 왜 같은 파일을 두 개의 검증기로 확인해야 할까요?
짧은 답은 이렇습니다. 사양이 충분히 크기 때문에 올바른 두 구현도 경계 조건에서는 서로 다른 판단을 내릴 수 있고, 감사 수준의 검증 흐름에서는 단일 엔진의 “Pass“를 초록불이 아니라 노란불로 보기 때문입니다. 자세히 보겠습니다.
PDF/A는 단일 알고리즘이 아니라 여러 규칙이 겹친 체계입니다
PDF/A는 여러 ISO 19005 파트(PDF/A-1, PDF/A-2, PDF/A-3, PDF/A-4)에 걸쳐 정의되고, 각 파트는 하위 준수 수준(b, a, u, e, f)을 갖습니다. 그 아래에는 기본 PDF 사양(ISO 32000)도 깔려 있습니다. 이 모든 표면을 합치면 규범 텍스트가 수천 페이지에 이릅니다.
역사적으로 준수 구현들이 서로 다르게 판단한 영역의 예는 다음과 같습니다.
- PDF/A-2/3의 투명도: 특정 조건에서는 허용됩니다. 다만 그 조건이 절차적으로 쓰여 있어 검증기마다 확인 방식을 다르게 구현할 수 있습니다.
- 내장 색상 프로파일: ICC 프로파일은 언제 “필수“이고 언제 “권장“일까요? 같은 파일을 두고 어떤 검증기는 “Pass”, 다른 검증기는 “Fail“이라고 부른 사례가 있습니다.
- PDF/A-3의 내장 파일 메타데이터:
AFRelationship,/AF참조, 내장 XMP는 규칙 자체는 잘 정의되어 있지만 적용 엄격도는 달라질 수 있습니다. - 폰트 부분 집합: PDF/A는 모든 폰트가 실제 인코딩과 함께 포함되어야 한다고 요구합니다. CID-keyed 폰트와 부분 집합 주변의 경계 사례는 검증기 불일치를 일으켜 왔습니다.
이런 차이가 곧 버그라는 뜻은 아닙니다. 복잡한 사양을 서로 다른 팀이 규범 텍스트에서 독립적으로 구현할 때 생기는 자연스러운 결과입니다. 보수적인 입장, 그리고 대부분의 규제 산업이 취하는 입장은 여러 독립 확인을 요구하는 것입니다.
레퍼런스 엔진과 두 번째 확인
veraPDF는 PDF/A를 발행하는 표준 단체인 PDF Association이 관리하는 레퍼런스 구현입니다. 오픈 소스이고, 업계 워킹 그룹의 감사를 받았으며, 규칙 집합은 ISO 19005 텍스트의 표준 해석에 해당합니다. veraPDF가 “Pass“라고 말한다면 단일 엔진에서 얻을 수 있는 가장 강한 신호입니다.
하지만 “가장 강한 단일 엔진 신호“와 “감사를 통과할 증거“는 같은 말이 아닙니다. 은행, 의료 기록 보관소, 정부 기록 관리 기관 같은 규제 산업의 감사자는 다음 이유로 두 번째 독립 확인을 자주 요구합니다.
- veraPDF의 규칙 해석이 감사 대상 기관이 내부에서 쓰는 다른 검증기와 다르면, 이후 단계에서 거부가 발생할 수 있습니다.
- 단일 엔진의 버그는 그 엔진을 두 번 실행해도 발견되지 않습니다. 레퍼런스 엔진도 예외가 아닙니다.
- 조달과 준수 영역에서는 “두 개의 독립 확인” 원칙이 널리 적용됩니다. PDF/A도 보관 사용 사례에서 그 기대를 물려받았습니다.
두 번째 엔진 선택지는 사용 가능한 도구에 따라 달라집니다.
- Adobe Acrobat Preflight는 유료이고 폐쇄 소스입니다. 확인용 엔진으로는 괜찮지만, 누가 다시 검증할 수 있는지는 제한됩니다.
- callas pdfaPilot은 유료이며 사실상 엔터프라이즈 선택지입니다. 하지만 이 역시 독립 재검증 가능성을 제한합니다.
- 두 번째 오픈 소스 엔진도 몇 가지가 있지만, 대체로 veraPDF보다 완성도가 낮습니다.
gPdf가 선택한 방식은 Rust + WebAssembly로 자체 엔진을 만드는 것이었습니다. 의도적인 “독립 재구현“입니다. 같은 사양, 같은 규칙을 다른 팀이 처음부터 작성했습니다. 두 엔진이 같은 파일에 대해 모두 통과하면, 어느 한쪽만 통과했을 때보다 결론이 훨씬 강해집니다. 둘이 서로 다르면 조사할 명확한 오류가 생깁니다. 오류는 한 엔진에 있을 수도 있고, 파일 자체에 있을 수도 있습니다.
두 보고서를 한 URL에서 확인하는 검증기
두 엔진은 gpdf.com/validator/에서 제공합니다. 무료이고, 로그인도 필요 없으며, 파일을 veraPDF와 gPdf Edge 엔진에 병렬로 통과시킨 뒤 두 보고서를 나란히 반환합니다. 사용 방식은 다음과 같습니다.
- PDF/A를 생성했고 이제 발송하려는 경우: 검증기에 넣고, 두 엔진이 모두 통과하면 JSON 보고서를 QA 증거로 첨부합니다. 끝입니다.
- 한 엔진은 실패하고 다른 엔진은 통과하는 경우: 정확한 오류가 생긴 것입니다. 보고서를 비교해 문제가 되는 필드를 찾습니다. PDF/A-3에서는 XMP 타임스탬프 불일치나
/AF참조 누락처럼 미묘한 문제가 흔합니다. - 둘 다 실패하는 경우: 파일이 실제로 깨진 것입니다. 생성 지점에서 고쳐야 합니다.
- 들어오는 보관 배치를 감사하는 경우: 무작위 샘플 PDF를 넣고, 보고서 URL을 기록하고, 감사 작업 문서에 첨부합니다. “벤더 검증기를 돌렸습니다“보다 “veraPDF와 독립 엔진으로 확인했습니다“가 더 강한 주장입니다.
업로드한 파일은 요청 처리 범위를 벗어나지 않습니다. 엔진은 Cloudflare Workers의 메모리 안에서 실행되고, 보고서가 표시된 뒤 파일은 폐기됩니다. 로그인 없음, 저장 없음, 사용량 제한 없음.
같은 패턴의 일반화
이 원칙은 PDF/A에만 해당하지 않습니다. “두 개의 독립 확인” 패턴은 다음에도 적용됩니다.
- Factur-X / ZUGFeRD 전자 인보이스: gpdf.com/validator/는 위의 PDF/A 검사와 함께 내장 EN 16931 CII XML에 대해 Mustang(mustangproject.org)을 실행합니다. (Validating ZUGFeRD with Mustang — what passes, what fails에서 그 검증 흐름을 설명합니다.)
- TLS 인증서: 모든 현대적인 CA 로그는 여러 모니터로 교차 확인됩니다.
- 빌드 재현성: 같은 원본에서 두 번 독립적으로 다시 빌드하면 바이트 단위로 동일한 결과가 나와야 합니다.
준수 분야는 수십 년 동안 이런 방식을 써 왔습니다. PDF/A가 이제 따라잡고 있을 뿐입니다.
TL;DR
단일 엔진의 “Pass“는 노란불입니다. 이중 엔진의 “Pass“는 초록불입니다. 두 엔진은 validator에서 무료로 사용할 수 있습니다. 파일을 올리고, 두 보고서를 받고, QA 증거에 첨부하세요. gPdf가 파일을 생성했다면 검증기는 API가 준수 주장을 실제로 지켰다는 공개 증빙입니다.
gPdf API 위에서 구축하고 있다면 E-Invoice API 레퍼런스(§5)가 Factur-X / ZUGFeRD PDF/A-3를 직접 내보내는 방법을 보여줍니다. 검증기는 그 결과를 외부에서 확인합니다. 두 엔진, 한 번의 업로드. 이것이 감사 수준의 패턴입니다.