기술 문서

PDFium Component를 사용한 Delphi에서의 XFDF 내보내기 및 가져오기

Delphi 및 Lazarus용 PDFium Component는 ISO 19444-1 표준에 정의된 XML 교환 형식인 XFDF를 통해 양식 데이터 및 주석을 교환합니다. TPdf.ExportXFDF는 로드된 문서 내 모든 양식 필드 값과 지원되는 모든 주석을 XFDF 파일 또는 TStream으로 직렬화하고, TPdf.ImportXFDF는 XFDF 문서를 다시 읽어 들여 주석을 페이지 상에 복원하고 필드 값을 적용합니다. 이 한 번의 라운드 트립 처리는 문서 관련 프로그램에서 구현해야 할 두 가지 주요 워크플로를 해결해 줍니다: 리뷰어가 Acrobat에서 PDF에 주석을 달고 수정한 내용을 개발 팀에 보내 통합하거나, 혹은 규정 준수를 위해 양식 데이터를 PDF 자체에 직접 저장하지 않고 수정 이력 추적 및 감사가 가능한 별도의 파일로 격리해 관리하는 프로세스입니다

PDFium은 XFDF 가져오기 및 내보내기를 지원합니까?

네이티브 PDFium 라이브러리 자체는 이를 지원하지 않습니다. 네이티브 C API에는 XFDF 또는 FDF 관련 함수가 전혀 존재하지 않으며 공개 헤더에서도 두 형식을 읽거나 쓰는 기능을 제공하지 않으므로, 단순히 래핑만 해서는 이 기능을 구현할 수 없습니다. 따라서 PDFium Component는 Pascal 언어를 사용하여 전체 XFDF 엔진을 구현하였습니다. 기존 TPdf 주석 및 양식 필드 데이터 모델을 토대로 XML 데이터를 직접 생성하고 파싱하는 전용 유닛을 갖추고 있습니다. 작성기는 XML 데이터를 직접 생성하고 리더 모듈은 직접 구현된 상태 머신 파서를 사용하여, Delphi XMLDoc 또는 FPC DOM 유닛에 대한 추가 종속성 없이 Delphi 및 Lazarus 환경 모두에서 완전히 동일하게 동작합니다

이러한 설계 방식은 다른 대안을 검토할 때 중요한 차이점이 됩니다. 만약 Pascal에서 직접 원시 FPDF_* 함수들을 직접 호출해 활용하고 있었다면 XFDF 구현이라는 거대한 장벽에 직면했을 것입니다: 해당 DLL 파일에는 관련 기능 자체가 없기 때문입니다. 이 컴포넌트는 XFDF 처리를 순수 직렬화 문제로 접근해 장벽을 극복합니다 — 즉 래퍼가 이미 읽는 방법을 알고 있는 필드 값 및 주석 레코드를 수집하여 표준 XML로 출력하고, 가져오기 시에는 이 과정을 역순으로 수행하는 방식입니다

XFDF 파일에는 어떤 내용이 포함되어 있습니까?

ISO 19444-1 표준은 XFDF를 FDF의 XML 표현형으로 정의하며, 그 페이로드는 두 개의 최상위 블록으로 나뉩니다. <fields> 요소는 계층적 형태의 양식 필드 이름과 값을 담고 있습니다 — 즉 사용자가 AcroForm 양식에 직접 타이핑하거나 선택 및 체크한 모든 데이터입니다. <annots> 요소는 주석 데이터를 포함합니다: TPdf.ExportXFDF는 text, highlight, underline, strikeout, squiggly, line, circle, square, caret, polygon, polyline, stamp, ink, freetext, fileattachment, sound, link, redact 등 18가지 주석 하위 유형을 생성해 출력합니다. 위젯 주석의 경우 해당 데이터가 <fields>를 통해 전송되므로 <annots>에는 의도적으로 포함되지 않으며, Popup과 같은 뷰어 내부 하위 유형은 XFDF 규격 어휘에 포함되지 않습니다

안정적인 라운드 트립 처리를 위해 TPdfAnnotation 레코드 사양이 XFDF가 기대하는 메타데이터 필드를 포함하도록 확장되었습니다: 고유 식별자 Name(NM), Subject, ModificationDate, CreationDate, Icon, Opacity, 라인 종단점 좌표, 다각형 및 폴리라인 정점 좌표, 잉크 그리기 경로 정보 등입니다. 각각의 새로운 필드는 Has* 부울 센티넬(boolean sentinel)과 한 쌍으로 작동하므로, 이전 컴파일러 버전 기준으로 빌드되었던 주석 제어 코드들도 오류 없이 빌드되어 동일한 사전을 안정적으로 출력합니다 — 명시적으로 지정되지 않은 필드는 기록되지 않습니다. 만약 이미 코드를 사용해 동적으로 주석을 생성해 다루고 있다면, 쿼드 포인트 지원 텍스트 마크업 주석 문서에서 다룬 것과 동일한 레코드를 사용해 XFDF 요건들을 충족할 수 있습니다

양식 데이터 및 주석을 XFDF로 내보내는 방법

단 한 번의 호출로 문서 전체에 대해 작업을 처리합니다. 양식 입력(form-fill) 속성이 활성화된 상태로 PDF를 로드하고 ExportXFDF를 호출하면, 컴포넌트 모듈이 모든 페이지를 탐색하며 양식 데이터 및 주석 데이터를 수집해 XML을 구성합니다. 함수는 작성된 UTF-8 바이트 크기를 반환하므로 로그에 안전성 검증 지표로 유용하게 기록할 수 있습니다

var
  Pdf: TPdf;
  Bytes: Integer;
begin
  Pdf := TPdf.Create(Self);
  Pdf.FormFill := True;            // needed so field values are live
  Pdf.FileName := 'expense-report.pdf';
  Pdf.Active := True;
  Bytes := Pdf.ExportXFDF('expense-report.xfdf');
  ShowMessage(Format('%d bytes of XFDF written', [Bytes]));
end;

두 방향 제어 모두 TStream 오버로드를 제공하므로 로컬 디스크 상에 임시 파일을 반드시 쓸 필요가 없습니다. TMemoryStream으로 내보내는 방식은 XFDF 데이터를 HTTP 응답 전송용이나 데이터베이스 blob 컬럼 또는 서명된 아카이브 내에 직접 주입할 때 자연스럽게 활용되는 구조입니다

var
  Buffer: TMemoryStream;
begin
  Buffer := TMemoryStream.Create;
  try
    Pdf.ExportXFDF(Buffer);        // same XML, no file involved
    Buffer.Position := 0;
    // hand the stream to a web response, blob column, or zip entry
  finally
    Buffer.Free;
  end;
end;

ImportXFDF는 어떻게 댓글 주석들을 다시 문서와 병합합니까?

가져오기 기능은 리뷰어 워크플로가 최종적으로 마무리되는 지점입니다. 동료가 Acrobat에서 계약서에 메모를 달아 이를 XFDF 파일로 내보낸 뒤, 용량이 수 메가바이트에 달하는 PDF 복사본 대신 수 킬로바이트 수준의 작은 XML 데이터로 개발자에게 공유합니다. TPdf.ImportXFDF는 해당 파일을 파싱하여 page 속성이 지시하는 대상 페이지에 주석을 복원하고 관련 위젯 주석에 필드 값을 입력합니다. 이 함수는 적용 완료된 주석 및 양식 필드의 개수 합계를 반환하므로 UI 상에서 최종 반영 수량을 명확히 안내할 수 있습니다

var
  Applied: Integer;
begin
  Applied := Pdf.ImportXFDF('review-comments.xfdf');
  StatusBar.SimpleText :=
    Format('%d fields and annotations merged', [Applied]);
end;

파서는 엄격한 검증보다는 유연한 수용을 목표로 구현된 핸드메이드 태그 스캐너입니다: 알 수 없는 요소는 무시되고, 처리 명령, DOCTYPE 선언 및 주석문은 배제되며, 파악되지 않는 플래그 이름은 폐기되고, 속성 값들은 UTF-16 대행 서식 쌍(surrogate pairs)을 포함한 XML 엔티티 및 수치형 문자 참조 세트를 거쳐 온전히 복구됩니다. Acrobat이나 웹 뷰어 혹은 다른 타사 도구를 통해 생성된 XFDF 파일도 오류 없이 유연하게 병합됩니다. 주석 데이터가 문서에 반영되면, PDFium Component를 통한 주석 리뷰 워크플로 구축 기사에서 설명한 답글 및 해결 프로세스로 리뷰 단계를 계속 진행할 수 있으며, 주입된 필드 값들은 양식 필드 내비게이션 문서에서 설명한 정상적인 탭 이동 로직에 편입됩니다

XFDF 처리 시 소수점 구분 기호가 중요한 이유

XFDF 주석의 모든 좌표 정보는 rect="70.5,540,200,560"과 같이 쉼표로 연결된 문자열 형태로 제공되며, ISO 19444-1 표준 규격은 소수점 구분 기호로 마침표(.)를 사용하도록 규정합니다. Delphi의 기본 부동 소수점 변환 방식은 Windows 로캘 사양을 따릅니다: 즉 소수점 구분 기호가 마침표로 정규화되고 후행 0은 절사되므로, 미국이나 독일 등 어떤 시스템 환경에서 내보내기 하더라도 바이트 단위로 일치하는 결과물이 생성됩니다. 개발실에서는 정상적으로 돌다가 유럽 고객의 PC 환경에서만 오류를 뿜는 PDF 도구를 조율하며 골머리를 썩여 본 경험이 있다면 이 결함이 매우 와닿을 것입니다. 이 컴포넌트가 이러한 예외 상황을 안전하게 자동 조율해 줌을 참고하십시오

라운드 트립의 기술적 한계

두 가지 기술적 한계를 명확히 밝혀 둡니다. 첫째, XFDF는 최종 렌더링된 모양(appearance)이 아닌 순수 주석 데이터만을 교환합니다 — 즉 모양 스트림 정보는 포맷 사양에 포함되지 않으므로 수신 측 뷰어가 자체 로직으로 주석 데이터를 해석해 모양을 재합성합니다. 형광펜이나 사각형 그리기 등은 모든 곳에서 일정하게 렌더링되지만, 사용자 정의 모양이 지정된 도장(stamp) 주석 등은 타겟 뷰어가 해당 도장 이름에 맞춰 기본 렌더링하는 기본형으로 강제 변환되어 출력될 수 있습니다. 둘째, 내부 PDFium API는 문자열 값의 설정만 제공할 뿐 주석의 세부 수치 값이나 기하학적 패스(path) 정보의 지정을 제공하지 않으므로 Opacity, 라인 종단점 좌표, 다각형 정점, 잉크 그리기 궤적 등은 내보내기 전용으로만 구동됩니다: 즉 XFDF 생성 시에는 이 데이터들을 신뢰성 있게 기록하지만, 가져오기 시에는 해당 정보들을 PDF 내부로 직접 재주입하지 못합니다. 단, 필드 값, 본문 내용, 전경색, 사각 영역(rect), 쿼드 포인트, 작성일 및 소유자 식별 메타데이터 등은 양방향 라운드 트립이 완전히 지원됩니다

기능의 실제 작동을 테스트해 보려면 Delphi, C++Builder 및 Lazarus 예제 디렉터리에 제공되는 XfdfLab 데모 프로젝트를 참고하십시오. 로드된 임의의 PDF 상에서 두 가지 버튼 조작을 통해 기능을 테스트할 수 있습니다. XFDF 연동 기능은 기반 주석 및 양식 처리 API 사양과 함께 최신 버전 PDFium Component의 기본 내장 기능으로 제공됩니다