Skip to content

PDF/A 검증

PDF/A(ISO 19005)는 전자 문서를 장기 보존하기 위한 국제 표준입니다. PDF Oxide는 주요 PDF/A 레벨을 모두 검증하며, 준수하지 않는 문서를 준수 상태로 변환할 수도 있습니다.

바인딩 지원 현황. PDF/A 검증은 Python(doc.validate_pdf_a(level)), Rust(validate_pdf_a + PdfAValidator 빌더), WASM(doc.validatePdfA(level)), Go(doc.ValidatePdfA(level))에서 사용할 수 있습니다. 공개된 C# 래퍼는 아직 제공되지 않습니다. Rust CLI(pdf-oxide validate --pdfa 2b doc.pdf)를 사용하거나 지원되는 바인딩 중 하나를 통해 호출하세요. PDF/A 변환(PdfAConverter)은 현재 Rust와 Python에서만 공개되어 있습니다.

지원 레벨

레벨 표준 구조 Unicode 투명도 임베디드 파일
1a ISO 19005-1 필수 필수 불가 불가
1b ISO 19005-1 불필요 불필요 불가 불가
2a ISO 19005-2 필수 필수 가능 불가
2b ISO 19005-2 불필요 불필요 가능 불가
2u ISO 19005-2 불필요 필수 가능 불가
3a ISO 19005-3 필수 필수 가능 가능
3b ISO 19005-3 불필요 불필요 가능 가능
3u ISO 19005-3 불필요 필수 가능 가능

레벨 “a”(접근성)는 태그가 지정된 구조 트리와 Unicode 문자 매핑을 요구합니다. 레벨 “b”(기본)는 시각적 재현성만 요구합니다. 레벨 “u”(Unicode)는 전체 구조 트리 없이 Unicode 텍스트 매핑을 요구합니다.

빠른 검증

한 번의 호출로 확인하려면 편의 함수를 사용하세요.

from pdf_oxide import PdfDocument

doc = PdfDocument("document.pdf")
result = doc.validate_pdf_a("2b")
print(f"Valid: {result.valid}")
print(f"Level: {result.level}")
for error in result.errors:
    print(f"  Error: {error}")
const doc = new WasmPdfDocument(bytes);
const result = doc.validatePdfA("2b");
console.log(`Valid: ${result.valid}`);
console.log(`Errors: ${result.errors.length}`);
doc.free();
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_a, PdfALevel};

let mut doc = PdfDocument::open("archive.pdf")?;
let result = validate_pdf_a(&mut doc, PdfALevel::A1b)?;

if result.has_errors() {
    println!("Not PDF/A-1b compliant:");
    for error in &result.errors {
        println!("  [{}] {} (clause {})",
            error.code, error.message,
            error.clause.as_deref().unwrap_or("n/a"));
    }
} else {
    println!("Document is PDF/A-1b compliant");
}
package main

import (
    "fmt"
    "log"
    pdfoxide "github.com/yfedoseev/pdf_oxide/go"
)

func main() {
    doc, err := pdfoxide.Open("archive.pdf")
    if err != nil { log.Fatal(err) }
    defer doc.Close()

    // Level encoding: 0 = 1b, 1 = 1a, 2 = 2b, 3 = 2a, 4 = 2u, 5 = 3b, 6 = 3a, 7 = 3u
    result, err := doc.ValidatePdfA(0) // PDF/A-1b
    if err != nil { log.Fatal(err) }

    if result.Valid {
        fmt.Println("Document is PDF/A-1b compliant")
    } else {
        fmt.Println("Not PDF/A-1b compliant:")
        for _, e := range result.Errors {
            fmt.Printf("  %s\n", e)
        }
    }
}

검증기 API

PdfAValidator는 세밀한 제어를 위한 빌더 패턴을 제공합니다.

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAValidator, PdfALevel};

let mut doc = PdfDocument::open("report.pdf")?;

let result = PdfAValidator::new()
    .stop_on_first_error(false)
    .include_warnings(true)
    .validate(&mut doc, PdfALevel::A2b)?;

println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());

개별 검사

전체 스위트 대신 개별 검증 범주를 실행합니다.

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAValidator, PdfALevel};

let mut doc = PdfDocument::open("report.pdf")?;
let validator = PdfAValidator::new();

// Check only metadata
let result = validator.check_metadata(&mut doc, PdfALevel::A1b)?;

// Check only fonts
let result = validator.check_fonts(&mut doc, PdfALevel::A1b)?;

// Check only color spaces
let result = validator.check_colors(&mut doc, PdfALevel::A1b)?;

// Check only transparency
let result = validator.check_transparency(&mut doc, PdfALevel::A2b)?;

// Check only structure tags
let result = validator.check_structure(&mut doc, PdfALevel::A1a)?;

독립 실행형 검증기

최대한의 유연성을 위해 각 검증 범주는 독립 실행형 함수로도 제공됩니다.

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::validators::*;
use pdf_oxide::compliance::{PdfALevel, ValidationResult};

let mut doc = PdfDocument::open("document.pdf")?;
let mut result = ValidationResult::new(PdfALevel::A1b);

// Run each validator independently
validate_xmp_metadata(&mut doc, PdfALevel::A1b, &mut result)?;
validate_fonts(&mut doc, PdfALevel::A1b, &mut result)?;
validate_colors(&mut doc, PdfALevel::A1b, &mut result)?;
validate_encryption(&mut doc, PdfALevel::A1b, &mut result)?;
validate_transparency(&mut doc, PdfALevel::A1b, &mut result)?;
validate_structure(&mut doc, PdfALevel::A1b, &mut result)?;
validate_javascript(&mut doc, PdfALevel::A1b, &mut result)?;
validate_embedded_files(&mut doc, PdfALevel::A1b, &mut result)?;
validate_annotations(&mut doc, PdfALevel::A1b, &mut result)?;

println!("Total errors: {}", result.errors.len());

검증기 요약

함수 검사 내용
validate_xmp_metadata() XMP 스트림 존재 여부, pdfaid:partpdfaid:conformance 항목 존재 여부, 메타데이터 일관성
validate_fonts() 모든 글꼴 임베딩 여부, 글리프 폭 존재 여부, Unicode 매핑 사용 가능 여부(레벨 “a” 및 “u”용)
validate_colors() output intent 없이 장치 종속 색상 연산자(rg, RG, k, K, g, G)를 사용하지 않음
validate_encryption() PDF/A 문서에서는 암호화가 허용되지 않음
validate_transparency() PDF/A-1에서는 투명도 불가, PDF/A-2 이상에서는 허용
validate_structure() 유효한 역할 매핑을 갖춘 태그된 구조 트리 존재(레벨 “a”에서 필수)
validate_javascript() JavaScript 동작이나 트리거가 존재하지 않음
validate_embedded_files() PDF/A-1 및 PDF/A-2에서는 허용되지 않음, PDF/A-3은 각 파일 사양에 AFRelationship 키 필요
validate_annotations() 해당 ISO 19005 파트에 따라 주석 유형이 제한됨

ValidationResult

ValidationResult 구조체는 검증 실행의 전체 결과를 담고 있습니다.

pub struct ValidationResult {
    pub level: PdfALevel,
    pub errors: Vec<ComplianceError>,
    pub warnings: Vec<ComplianceWarning>,
    pub stats: ValidationStats,
}
필드 타입 설명
level PdfALevel 대상 준수 레벨
errors Vec<ComplianceError> 준수를 가로막는 차단성 위반
warnings Vec<ComplianceWarning> 품질에 영향을 줄 수 있는 비차단성 문제
stats ValidationStats 검사한 페이지, 글꼴, 객체의 수

ComplianceError

pub struct ComplianceError {
    pub code: ErrorCode,
    pub message: String,
    pub location: Option<String>,
    pub clause: Option<String>,
}

code 필드는 MissingXmpMetadata, FontNotEmbedded, DeviceDependentColor, EncryptionPresent, TransparencyNotAllowed, MissingStructureTree, JavaScriptPresent, InvalidEmbeddedFile와 같은 범주를 가진 ErrorCode 열거형을 사용합니다.

ComplianceWarning

pub struct ComplianceWarning {
    pub code: WarningCode,
    pub message: String,
    pub location: Option<String>,
}

PDF/A 변환

준수하지 않는 문서를 PDF/A 준수 상태로 변환합니다.

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{convert_to_pdf_a, PdfALevel};

let mut doc = PdfDocument::open("input.pdf")?;
let result = convert_to_pdf_a(&mut doc, PdfALevel::A1b)?;

println!("Conversion actions taken:");
for action in &result.actions {
    println!("  - {}: {}", action.action_type, action.description);
}

if result.remaining_errors.is_empty() {
    println!("Document is now PDF/A-1b compliant");
} else {
    println!("{} issues could not be resolved automatically",
        result.remaining_errors.len());
}

변환 구성

변환 과정을 세밀하게 조정합니다.

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAConverter, PdfALevel, ConversionConfig};

let mut doc = PdfDocument::open("input.pdf")?;

let config = ConversionConfig::new()
    .embed_fonts(true)
    .remove_javascript(true)
    .flatten_transparency(true)
    .add_structure(true);

let result = PdfAConverter::new(PdfALevel::A2b)
    .with_config(config)
    .convert(&mut doc)?;

변환기는 다음 작업을 자동으로 수행합니다.

  1. XMP 메타데이터 주입pdfaid:partpdfaid:conformance 항목을 추가합니다
  2. 글꼴 임베딩 – 참조되었지만 임베디드되지 않은 글꼴을 임베딩합니다
  3. JavaScript 제거 – JavaScript 동작과 트리거를 제거합니다
  4. 투명도 평탄화 – 투명 요소를 불투명하게 렌더링합니다(PDF/A-1 전용)
  5. ICC 프로파일 변환 – 장치 종속 색상을 ICC 기반 색 공간으로 변환합니다
  6. 구조 태깅 – 기본 구조 태그를 추가합니다(레벨 “a” 대상)

워크플로: 검증, 수정, 재검증

일반적인 보존 워크플로는 검증을 수행하고, 자동 변환을 시도한 뒤, 다시 검증합니다.

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_a, convert_to_pdf_a, PdfALevel};

let level = PdfALevel::A2b;
let mut doc = PdfDocument::open("input.pdf")?;

// Step 1: Initial validation
let result = validate_pdf_a(&mut doc, level)?;
if !result.has_errors() {
    println!("Already compliant");
    return Ok(());
}

println!("{} errors found, attempting conversion...", result.errors.len());

// Step 2: Automatic conversion
let conversion = convert_to_pdf_a(&mut doc, level)?;
println!("{} actions taken", conversion.actions.len());

// Step 3: Re-validate
let result = validate_pdf_a(&mut doc, level)?;
if result.has_errors() {
    println!("{} errors remain after conversion:", result.errors.len());
    for e in &result.errors {
        println!("  {} -- {}", e.code, e.message);
    }
} else {
    println!("Document is now PDF/A-2b compliant");
}

PdfALevel 메서드

PdfALevel 열거형에는 레벨 기능을 조회하기 위한 도우미 메서드가 포함되어 있습니다.

메서드 반환값 설명
part() PdfAPart ISO 19005 파트(Part1, Part2, Part3)
conformance() char 적합성 문자(‘a’, ‘b’ 또는 ‘u’)
requires_structure() bool 태그된 구조 트리가 필수인지 여부
requires_unicode() bool Unicode 매핑이 필수인지 여부
allows_transparency() bool 투명도 허용 여부
allows_jpeg2000() bool JPEG 2000 이미지 허용 여부
allows_embedded_files() bool 파일 첨부 허용 여부
xmp_part() &str XMP pdfaid:part
xmp_conformance() &str XMP pdfaid:conformance
from_xmp(part, conformance) Option<Self> XMP 메타데이터 값에서 레벨 파싱

다음 단계