Delphi용 PDFium Component는 TPdf.ValidatePdfX 함수를 통해 즉시 인쇄 가능한 PDF/X 문서 검증 기능을 지원합니다. 이 검증은 ISO 15930 표준 규격에 따라 2단계(two-layer) 구조로 상세 동작합니다. 1단계로 파일 헤더 바이트 수준에서 8가지 요소(사용 금지된 LZW 압축 필터, JavaScript 삽입 여부, 폼 필드 존재 여부, OPI 참조, TrimBox 누락 여부, Trapped 키 누락 여부 등)를 검사하고, 2단계로 PDFium 오브젝트 모델 스캔을 가동해 내부의 FPDFFont_GetIsEmbedded API로 매 페이지의 모든 텍스트 객체 폰트가 내장(embedded)되었는지를 전수 확인합니다. 검사 완료 시 검출된 표준 호환성 레벨과 개별 위반 항목들을 열거형(enum) 배열 목록으로 정리한 TPdfXValidationResult 레코드를 반환하므로, Delphi 애플리케이션은 인쇄소에서 출력물이 반려되기 전에 사용자에게 정확히 어떤 파일 손상이 일어났는지 인쇄판을 굽기 전 즉시 경고해 줄 수 있습니다
만일 인쇄 의뢰를 위해 상업용 인쇄소로 파일을 전송했다가 'TrimBox 누락', '폰트 미내장', 'Trapped 미설정' 등의 단문 거절 메시지와 함께 반려당해 본 경험이 있다면, 오류를 뒤늦게 파악했을 때 따르는 비용 낭비의 고통을 잘 알고 계실 것입니다. PDF/X는 인쇄 전처리(prepress)용 규격으로 장기 보존용인 PDF/A와는 목표가 다릅니다. 보관 보존용 PDF/A가 문서의 시각적 형태를 수십 년 뒤에도 동일하게 렌더링하는 것을 목표로 한다면, PDF/X는 문서의 색상 분판(separates), 래스터화(images), 재단(trims)이 내일 아침 타사의 하드웨어 RIP 장비에서도 정확하게 가공될 수 있도록 신뢰성을 보장하는 데 특화되어 있습니다. 두 표준은 XMP 메타데이터 표식, 출력 의도(OutputIntents), 내장 ICC 프로파일 설정 등 많은 내부 공용 장치를 공유하지만 해결하려는 목적지가 다릅니다. 따라서 본 컴포넌트는 두 규격의 개별 전용 검사 모듈을 독립 탑재해 배포합니다. (PDF/A 규격 검증 기법은 PDFium Component를 활용한 PDF/A 보존 규격 프리플라이트 검증 가이드에서 대조해 보실 수 있습니다.)
ISO 15930 표준은 인쇄용 PDF 파일에 구체적으로 무엇을 요구할까요?
ISO 15930 규격은 소위 '블라인드 교환(blind exchange)'을 가능하게 하기 위해 태어났습니다. 디자이너가 대면한 적 없는 인쇄소에 파일을 건네면, 인쇄소 측에서 사후 조율 전화나 누락된 폰트 전송 요청 이메일, 혹은 디자이너 컴퓨터에만 존재해 링크가 깨진 이미지 등의 문제없이 완벽한 인쇄물을 독립적으로 곧바로 출력해 낼 수 있게 보장하는 것입니다. 표준 사양의 모든 제약 조항은 오직 이 목적에 맞추어 설계되었습니다. 출력 측의 RIP 장비가 해당 서체를 보유하고 있지 않을 수 있으므로 파일 내에 폰트를 무조건 내장시켜야 하고, 파일 자체만으로 모든 재화가 완비되어 있어야 하므로 외부 임포트 링크 참조를 금지하며, 종이 위의 인쇄 잉크에는 onclick 마우스 클릭 액션 따위가 작동하지 않으므로 일체의 인터랙티브 동작 속성들을 배제시킵니다
PDFium Component는 총 세 가지 세부 인쇄 표준 규격을 인지하고 이를 TPdfXConformance 열거형 결과로 보고해 줍니다. 첫째는 PDF/X-1a:2001(ISO 15930-1, PDF 1.3/1.4 버전 기반의 CMYK 및 별색 전용 표준) 규격인 pxc1a, 둘째는 PDF/X-3:2002(ISO 15930-3, RGB, Lab 및 ICC 프로파일 관리 컬러를 수용) 규격인 pxc3, 셋째는 PDF/X-4:2010(ISO 15930-7, PDF 1.6 기반 하에서 레이어 및 투명도 효과를 공식 허용) 규격인 pxc4입니다. 인쇄 파일 식별 메타데이터가 전혀 검출되지 않는 일반 PDF 문서는 pxcNone으로 반환됩니다. 이 경우 해당 파일은 인쇄용 문서가 아니라는 1차 결론을 주며, 검사기가 동시 제공하는 상세 위반 로그를 참고하여 어떤 요소들을 개량해야 인쇄 규격 파일로 보정할 수 있는지 그 해답을 찾을 수 있습니다
RIP 장비 벤더의 관점에서 생각해 보면 이 수많은 제한 사양들이 납득이 갈 것입니다. LZW 압축 방식(/LZWDecode)이 모든 PDF/X 변종 규격에서 금지된 이유는, 뷰어 장치가 라이선스 분쟁과 구버전 호환성 오버헤드가 잔존하는 압축 해제 필터를 사용하지 않도록 차단하기 위함입니다. 델파이 표준 Flate(Deflate) 필터가 동일한 압축 성능을 제공하므로 이를 대체 사용해야 합니다. JavaScript, AcroForm 입력 폼 필드, /AA(추가 액션) 사전 데이터 역시 금지 대상입니다. 인쇄용 문서는 종이 위에 잉크로 안착될 고정 마크 정보만을 엄격하게 정의해야 하며, 열람 시점에 작동해 외형 그래픽 요소를 바꾸어 놓을 수 있는 모든 변동 가능 요소들은 디자이너가 의도한 검판(proofed) 결과물 그대로 최종 인쇄되도록 보장하는 대원칙을 훼손하기 때문입니다. OPI(Open Prepress Interface) 자리 표시자 역시 기획 의도상 고해상도 그래픽 원본을 외부 시스템 저장소에 링크해 두는 기술이므로, 파일 자체 완비성을 지향하는 블라인드 교환 사상에 대치되어 즉각 거부됩니다
왜 인쇄소는 TrimBox가 없는 PDF를 무조건 거절할까요?
재단 상자(TrimBox)는 제판 재단 가위질을 마치고 살아남는 최종 결과 책자의 실물 인쇄 사각형 영역을 뜻합니다. 반면 모든 PDF가 가진 미디어 상자(MediaBox)는 도련(bleed), 재단 표식(crop marks), 정밀 정합 타겟(registration targets), 컬러 조정 바까지 모두 포함하는 큰 가상의 종이 전체 도판을 뜻합니다. 인쇄소 터잡기(imposition) 소프트웨어는 각 페이지의 재단 상자(TrimBox) 데이터를 추적해 인쇄용 터잡기 판 위에 문서를 정렬해 배치합니다. 이 재단 상자 규격이 파일 내에 기록되어 있지 않으면, 인쇄 오퍼레이터는 명함이나 카탈로그의 경계가 정확히 어디서 종결되는지를 순수 어림짐작으로 판단해야 하고, 잘못 절단하면 도련 영역이 잘려 나가거나 책 가장자리에 원치 않는 흰색 실선 경계가 남는 인쇄 사고가 발생합니다. 그렇기 때문에 ISO 15930 표준은 매 페이지마다 TrimBox(혹은 ArtBox) 설정을 필수로 요구하며, ValidatePdfX 함수 역시 이 데이터가 누락된 시트가 한 개라도 검출되면 즉시 pvxiMissingTrimBox 오류를 보고하도록 설계되어 있습니다
트랩 정보(/Trapped) 키 역시 인쇄 단계의 또 다른 가공 질문에 대한 답을 제공합니다. 트래핑(trapping)은 인쇄 도중 인근 잉크가 미세하게 밀리더라도 글자 주변에 흰색 빈틈이 생기지 않도록 인접 색상들의 외곽선을 아주 미세하게 겹쳐 인쇄(overprint)해 주는 기술입니다. 인쇄소는 이 트래핑 처리가 디자이너 측 파일 내에 이미 선작업 되었는지를 인지해야 합니다. 트래핑이 완료된 문서에 재차 트래핑을 먹이면 외곽선이 2배로 뚱뚱해지는 그래픽 훼손이 발생하고, 반대로 처리가 누락된 파일을 그냥 출력하면 접합면 경계에 보기 싫은 실선 빈틈이 생기기 때문입니다. PDF/X 문서는 문서 정보 사전에 /Trapped /True 혹은 /Trapped /False 값을 무조건 명기하도록 규정하며, 이 속성값이 없거나 /Unknown으로 지정되어 있으면 오퍼레이터가 직접 눈으로 판별해 개입해야 하는 지연이 유발됩니다. 컴포넌트는 이를 감지해 pvxiTrappedNotSet 결함으로 즉각 분류합니다
TPdf.ValidatePdfX를 사용한 2단계 유효성 검사 기입 방법
TPdf.ValidatePdfX 함수는 인수를 취하지 않으며, 감지된 규격 레벨인 Conformance, 발견된 결함 집합인 Issues, 그리고 규격 준수 여부를 지칭하는 IsCompliant 도우미 속성을 제공하는 TPdfXValidationResult 레코드 구조체를 반환해 줍니다. 내부적으로는 적재된 문서를 메모리 스트림으로 임시 해제해 바이트 스캐너를 1차 통과시키고, 이어 실시간으로 PDFium 엔진의 전체 오브젝트 노드를 순환 순회하는 2차 검사를 기동합니다. 간략한 검사 예시 소스 코드는 다음과 같습니다
uses PDFium, FPdfPdfx;
procedure CheckPrintReadiness(const FileName: string);
var
Pdf: TPdf;
Res: TPdfXValidationResult;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := FileName;
Pdf.Active := True;
Res := Pdf.ValidatePdfX;
Writeln('Detected conformance: ',
Ord(Res.Conformance)); // pxc1a, pxc3, pxc4, pxcNone...
if Res.IsCompliant then
Writeln('PDF/X checks passed')
else
begin
if pvxiMissingTrimBox in Res.Issues then
Writeln('REJECT: no /TrimBox on the pages');
if pvxiTrappedNotSet in Res.Issues then
Writeln('REJECT: /Trapped missing or /Unknown');
if pvxiPdfiumFontNotEmbedded in Res.Issues then
Writeln('REJECT: a page uses a non-embedded font');
if pvxiLzwForbidden in Res.Issues then
Writeln('REJECT: LZWDecode filter present');
end;
finally
Pdf.Free;
end;
end;
반환되는 Issues 객체는 일반적인 오브젝트 파스칼의 집합(set) 형식이므로 사용자의 인쇄 워크플로우 요구사항에 맞춰 간편하게 분기 제어할 수 있습니다. 예컨대 기하학적인 치명 구조 오류는 거절(reject)로 지정하고, 표준 규격 상의 권장 조항일 뿐인 제목 누락(pvxiMissingTitle)은 단순 경고(warning)로 흘려보낼 수 있습니다. 이 레코드 객체는 컴포넌트의 자동 보고서 생성기에도 원본 정보로 그대로 전달되므로, enum 대조가 아닌 깔끔한 PDF 보고서 문서를 자동으로 찍어내어 배포하고 싶다면 PDFium Component를 활용한 일괄 프리플라이트 보고서 CLI 도구 구축 가이드의 설계 방식을 PDF/X 검증 단계에 그대로 접목할 수 있습니다
바이트 검사 레이어가 감지하는 영역과 놓치기 쉬운 허점
바이트 수준 검사 레이어는 압축 스트림 내부 본문 영역을 깨끗하게 제외하고 문서 구조의 원시 마크업 텍스트 영역만을 토큰 분석하므로, 문서에 내장된 일반 사진 JPEG 파일의 색상 바이너리 내에 마침 /JavaScript라는 바이트 패턴이 우연히 삽입되어 있어도 거짓 양성(false positive) 오보를 내지 않도록 정교하게 예방 설계되어 있습니다. 기본 마커 대조(XMP 메타데이터의 pdfxid:GTS_PDFXVersion, ICC 프로파일이 결합된 OutputIntent 설정, 트레일러의 고유 /ID 식별 번호 검사 및 문서 암호화 전면 차단 체크) 외에도 다음과 같은 8가지 정밀 스캔 위반 항목들이 추가되어 감지 처리됩니다
pvxiLzwForbidden— 파일 내부 임의 위치에 LZWDecode 압축 필터(/LZWDecode)가 사용됨 (모든 PDF/X 변종 규격 금지)pvxiJavaScriptForbidden— 문서에 액션이나 이름 트리 형태로 JavaScript 구문이 내장됨pvxiFormFieldsForbidden— 아크로폼 입력창 사전(/AcroForm) 혹은 XFA 형식 데이터 구조가 기입됨pvxiAdditionalActions— 추가 동작 지정 속성인/AA딕셔너리가 감지됨pvxiEmbeddedFilesForbidden— 첨부 파일 사전(/EmbeddedFiles) 혹은 파일 첨부(/FileAttachment) 형식의 주석 개체가 발견됨pvxiOpiForbidden— 고해상도 외부 대치 링크용/OPI혹은/Alternates데이터 구조가 기입됨pvxiMissingTrimBox— 문서 내 임의 페이지에서 재단 경계 상자(/TrimBox) 정보를 찾을 수 없음pvxiTrappedNotSet— 트래핑 상태 속성인/Trapped지시자가 없거나/Unknown으로 정의됨
바이트 토큰 스캔 방식은 물리적 렌더링 엔진 라이브러리를 가동할 필요가 없어 연산이 극도로 민첩하다는 뚜렷한 이점을 갖지만, 폰트 검출 영역에 있어서는 이론적인 탐색 한계가 존재합니다. 이 단계에서는 파일 전체에 내장된 폰트 리소스 블록이 단 1개라도 존재하는지 여부만을 대략적으로 탐색해 감지할 수 있기 때문입니다. 만약 임의의 문서에 총 10개의 서체가 쓰였고 그중 9개는 내장되었으나 사소한 1개의 서체만 내장되지 않고 사용자 PC용 기본 서체를 참조하고 있을 때, 바이트 스캐너는 내장 폰트 리소스 블록을 검출해 냈으므로 정상 문서로 오진해 버립니다. 이러한 치명적인 판정 허점을 보완하기 위해 제2단계 전수 텍스트 개체 검사 레이어가 기동하는 것입니다
서체별 폰트 임베딩 개별 확인 기법
PDFium Component의 오브젝트 모델 검사 레이어는 폰트 미내장 문제를 매우 정밀하게 판별해 냅니다. 바이트 검사를 마친 후, TPdf.ValidatePdfX 함수는 매 페이지를 순환 로드하여 FPDFPage_CountObjects 함수로 드로잉 요소 객체 목록을 전체 수집합니다. 수집된 드로잉 요소 중 텍스트 속성을 띈 객체(text objects)를 마주치면 즉시 FPDFTextObj_GetFont 함수로 폰트 핸들을 추출한 다음, 최종적으로 FPDFFont_GetIsEmbedded API를 기동해 해당 서체가 문서에 임베딩되어 수록되었는지를 확인합니다. 단 한 글자라도 내장되지 않은 서체가 검출되면 전체 결함 리포트 집합에 pvxiPdfiumFontNotEmbedded 플래그를 추가합니다. 이 객체 트리 순환 연산은 효율적으로 조기 중단(short-circuits)하도록 정교하게 최적화되어 있습니다. 특정 페이지에서 미내장 서체가 확정되는 순간 해당 페이지 내 다른 텍스트 스캔을 즉시 멈추고 다음 페이지 로드 역시 즉각 기각하므로, 300페이지짜리 대형 문서라 하더라도 1페이지 선두에서 미내장 서체가 감지되면 불필요하게 시간 낭비하지 않고 수 밀리초 만에 즉시 결함 판정을 보고합니다
알아 두면 유용한 두 가지 기술적 사양이 있습니다. 첫째, 이 세부 폰트 검증은 PDFium 엔진 핵심 DLL 파일이 가동되어야 하며 FPDFFont_GetIsEmbedded API 진입점을 정상 내보내는 DLL 사양이어야 작동합니다. 만일 해당 API가 누락된 오랜 구버전 DLL이 연결된 환경에서는 에러를 뿜는 대신 조용히 해당 폰트 교차 검증만 건너뛰어 대처하므로 오작동을 예방합니다. 둘째, 이 체크는 폰트의 내장 여부만을 판별할 뿐, 폰트 전체 임베딩과 부분 임베딩(subsetting)의 세부 차이를 변별하거나 문자 폰트의 글리프 누락 범위 검사 등은 지원하지 않습니다. 만약 특정 문서에서 폰트 오류가 터졌을 때 어떤 페이지의 어떤 폰트가 범인인지 세부 로그 정보 조회가 필요하다면, Delphi용 PDF 폰트 속성 정보 분석 및 메타 데이터 추출 가이드에 기술된 개별 폰트 조회 기법을 응용해 판별하십시오
DLL 파일이나 문서 전체 로드 없이 스트림만으로 초고속 검증하기
바이트 수준 검사기는 FPdfPdfx 유닛에 수록된 ValidatePdfXCompliance(Source: TStream) 독립 함수를 통해 단독 기동할 수 있으며, 이 함수는 어떠한 외부 C++ DLL 종속성도 필요로 하지 않는 100% 순수 오브젝트 파스칼 모듈입니다. 덕분에 PDFium 엔진 DLL 배포가 곤란한 장소인 웹 서버 백엔드 업로드 파일 일차 검증기나, 빌드 파이프라인 CI 자동 점검 러너 환경, 또는 기계 환경에 컴파일 배포해야 하는 초경량 Lazarus 서비스 등 플랫폼 환경에 무겁고 번거로운 네이티브 DLL 동반 배포 없이 깔끔하게 탑재해 구동시킬 수 있습니다. 임의의 판독 가능한 스트림 변수를 연결해 작동시키십시오
uses Classes, FPdfPdfx;
function QuickPdfXGate(const FileName: string): Boolean;
var
Fs: TFileStream;
Res: TPdfXValidationResult;
begin
Fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Res := ValidatePdfXCompliance(Fs);
Result := Res.IsCompliant and (Res.Conformance <> pxcNone);
finally
Fs.Free;
end;
end;
한계 제약도 명확합니다. 이 가벼운 독립 함수는 마커 검사 및 8대 바이너리 콘텐츠 규칙 검사는 전부 수행해 내지만, 폰트 개체 전수 임베딩 상태를 판별하는 2단계 PDFium 오브젝트 검사는 수행할 수 없어 폰트 임베딩 진단을 대략적인 유무 확인(coarse heuristic) 수준으로 간소화 처리합니다. 따라서 실무 제품 개발 시에는 ValidatePdfXCompliance 독립 함수를 서버 입구나 파일 접수처의 초고속 일차 통제 장치로 전진 배치하고, 이를 통과한 정규 문서를 대상으로만 TPdf.ValidatePdfX 함수를 2차로 정밀 기동하는 다단계 아키텍처 설계를 권장합니다
검사기가 지원하는 영역과 전문 인쇄 판독 툴링 간의 경계선
프리플라이트 도구 검사 수준을 다룰 때는 솔직한 기능 한계 전달이 매우 중요하므로 경계를 명확히 설명해 드립니다. ValidatePdfX는 인쇄 규격용 식별 메타 마커 정보, 불법적인 구조 요소 금지 여부, 재단 상자 기하 키의 유무, 트래핑 표식 정보 설정 상태 및 개별 글자 개체의 서체 임베딩 여부를 전수 검사합니다. 그러나 잉크 전체 보급률(total ink coverage)을 직접 측정해 주거나, 각 색상 프로파일이 규정된 표준 요구사항에 부합하는지(예컨대 X-1a의 엄격한 CMYK 및 별색 전용 규칙 적합성 여부), 수록된 삽화 이미지의 해상도 배율이 출력 스크린 밀도에 맞는지 확인하거나, 혹은 오버프린트 가공 상태 및 투명도 플래트닝(transparency flattening) 연산을 직접 시뮬레이션해 주지는 않습니다. 이러한 정합성들은 컬러 보정이 지원되는 별도의 그래픽 판독 엔진을 병행 연동해야 하며, 컴포넌트 자체 매뉴얼 문서에서도 최종 품질 인증 완료를 위해서는 종합 프리플라이트 서버와 연결해 사용하라고 안내하고 있습니다. 당사의 2단계 검사 모듈이 주는 가장 확실한 성과는 인쇄소 반려 사유의 약 80%를 차지하는 파일 포맷 규약 불합격 요인들을 원격지에서 미리 필터링해 준다는 점입니다. 무겁고 비싼 외부 서비스를 거치지 않고 내 델파이 애플리케이션 안에서 수 밀리초 만에 안전하고 가볍게 결함을 사전 교정해 줍니다
소개해 드린 2단계 검사 엔진 모듈과 표준 규격 적합성 메타데이터 삽입용 빌더 API, 그리고 동일 설계 아키텍처 하에 작동하는 PDF/A, PDF/UA, PDF/E, PDF/VT 형식 규격 검사 도구들은 모두 PDFium Component 제품군 배포 사양에 일체화되어 탑재되어 있습니다. 뷰어 화면 렌더링부터 인쇄 전처리 프리플라이트 진입 통제 장치 구현까지, 단 하나의 컴포넌트로 완벽하게 완수하십시오