빌드는 성공적이었고(green), 릴리스 노트도 완성되었으며, 고객 포털에서는 문서화 PDF가 오후 4시 57분에 거부되었다. 그 파일은 단순한 매뉴얼에 불과했지만, 갑자기 이번 릴리스에서 마지막으로 해결되지 않은 의존성처럼 여겨졌다.
압축은 분류(Classification)에서 시작된다
PDF는 이미지가 아닌 컨테이너이다
“PDF를 압축한다”라는 문구는 단일 작업처럼 들린다. 하지만 그렇지 않다. PDF는 텍스트 스트림, 임베디드 폰트(embedded fonts), 벡터 드로잉(vector drawings), JPEG 이미지, 무손실 이미지(lossless images), 주석(annotations), 양식(forms), 첨부 파일(attachments), 메타데이터(metadata) 등 여러 세대의 증분 편집을 포함할 수 있다.
두 개의 파일은 페이지 수는 같지만 근본적으로 다른 크기 프로필을 가질 수 있다. 문서 생성기에서 내보낸 100페이지짜리 API 레퍼런스는 대부분 텍스트와 벡터 라인으로 구성되어 있을 수 있다. 반면, 10페이지 분량의 검사 보고서는 전체 해상도의 사진 10장을 포함할 수도 있다. 이 둘을 동일한 파이프라인으로 재작성하는 것은 편리하지만, 편리함이 정확성을 의미하지는 않는다.
따라서 첫 번째 엔지니어링 결정은 분류여야 한다. 문서에 대한 완벽한 의미론적 모델(semantic model)이 필요하지 않다. 안전한 첫 전략을 선택할 수 있는 충분한 증거만 있으면 된다.
유용한 사전 점검(preflight)을 위해 보통 세 가지 신호만 충분하다
가장 실용적인 신호는 추출 가능한 텍스트, 임베디드 폰트, 그리고 페이지 크기 이미지이다. Poppler를 사용하면 사용자 정의 PDF 파서 없이 이 세 가지 모두를 얻을 수 있다.
pdfinfo input.pdf
pdffonts input.pdf
pdftotext input.pdf -
...
만약 pdftotext가 상당한 내용을 반환하고 pdffonts가 폰트를 나열한다면, 해당 문서는 유용한 텍스트 레이어를 가지고 있을 가능성이 높다. 만약 텍스트 출력이 거의 비어 있는데 모든 페이지에 큰 이미지가 포함되어 있다면, 스캔 기반(scan-heavy)일 가능성이 높다. 이 두 가지 모두가 존재한다면, 혼합 문서이거나 OCR 레이어가 있는 스캔 PDF일 수 있다.
이는 의도적으로 확률적이다. 일부 PDF는 텍스트를 벡터 아웃라인으로 변환한다. 일부는 오해의 소지가 있을 만큼 부족한 숨겨진 OCR 레이어를 포함하기도 한다. 사전 점검은 법정 판결이 아니라 라우팅 힌트(routing hint)를 생성해야 한다.
첫 페이지부터 분류하지 마라
실제 워크플로우에서는 혼합 문서가 흔합니다. 첫 페이지는 생성된 표지일 수 있고, 다음 50페이지는 스캔본일 수 있으며, 부록에는 검색 가능한 테이블이 포함될 수 있습니다. 첫 페이지만 보고 판단하면 잘못된 확신을 갖게 됩니다.
작은 셸(shell) 도우미 스크립트는 대표적인 페이지를 샘플링하고 빌드 아티팩트(build artifact)에 증거를 보존할 수 있습니다.
#!/usr/bin/env bash
set -euo pipefail
...
이 스크립트는 의도적으로 지루합니다. 지루한 진단이 좋은 진단입니다. 이는 파괴적인 변환이 발생하기 전에 사람이나 CI 작업에 간결한 스냅샷을 제공합니다.
유용한 속성을 보존하는 전략 선택
구조적 최적화가 가장 덜 극적인 경로입니다
텍스트 중심의 PDF의 경우, 가장 안전한 첫 번째 단계는 일반적으로 구조적 정리(structural cleanup)입니다. 여기에는 개체 스트림 압축(object-stream compression), 도달 불가능한 개체 제거(removal of unreachable objects), 글꼴 서브셋팅(font subsetting), 중복 리소스 통합 등이 포함될 수 있습니다. 가능한 감소 폭은 전체 래스터화(full rasterization)보다 작지만, 검색 가능성, 선택 가능한 텍스트, 벡터 그래픽, 접근성 정보는 살아남을 확률이 더 높습니다.
qpdf와 같은 도구는 정규화 및 스트림 압축에 유용하지만, 이미 압축된 JPEG 바이트로 저장된 이미지 데이터를 마법처럼 줄일 수는 없습니다. 이것은 이해하기 좋은 경계점입니다. 명령어 하나만으로도 PDF를 깨끗하게 다시 작성할 수 있지만 여전히 미미한 크기 차이만 발생합니다.
이미지 중심 문서는 이미지 결정이 필요합니다
사진이나 페이지 스캔본이 파일의 대부분을 차지하는 경우, 가장 큰 이득은 일반적으로 해당 이미지를 다운샘플링(downsampling)하고 재인코딩(re-encoding)하는 것에서 나옵니다. 이는 일반적인 "압축" 기능만으로는 답할 수 없는 질문들을 제기합니다.
목적지가 무엇인가요? 화면 전용 검토본은 인쇄 마스터와 동일한 유효 해상도가 필요하지 않습니다. 색상이 의미를 갖나요? 사진으로 찍은 영수증은 그레이스케일(grayscale)을 허용할 수 있지만, 열 지도(heat map)는 그렇지 않을 수 있습니다. 이미지는 자연 사진인가요 아니면 인터페이스 스크린샷인가요? JPEG는 전자에 잘 작동할 수 있지만 후자에는 보기 싫은 헤일로(halo)를 만듭니다.
적절한 품질 설정은 맥락적입니다. 무작위 코드 스니펫에서 복사하는 것이 아니라 문서의 사용 목적에 따라 선택되어야 합니다.
모든 페이지를 래스터화(Rasterizing)하는 것은 이득이 아닌 상충 관계입니다
각 페이지를 비트맵(bitmap)으로 렌더링하고 PDF를 재구축하는 과정은 복잡한 객체 그래프(object graph)를 예측 가능한 이미지 시퀀스로 변환하기 때문에 매력적입니다. 하지만 이는 검색 가능한 텍스트, 링크, 양식 필드(form fields), 벡터의 선명도(vector sharpness), 태그, 그리고 의미론적 구조(semantic structure)까지 제거할 수 있습니다.
때로는 그러한 상충 관계가 허용될 수 있습니다. 스캔 전용 공유 사본은 이미 이미지 컬렉션처럼 작동합니다. 하지만 코드 샘플, 검색 가능한 제목, 내부 링크를 포함하는 기술 매뉴얼의 경우, 동일한 접근 방식이 문서의 가장 유용한 기능을 손상시키면서 크기 문제를 해결할 수도 있습니다.
이것이 바로 압축 서비스가 최종 바이트 수(byte count)만으로 평가되어서는 안 되는 이유입니다. 파일 크기는 작아지지만, 독자에게 여전히 같은 종류의 도구인가요?
파이프라인에 빌드 검증을 통합하세요 (Build Validation Into the Pipeline)
프로세스가 성공적으로 종료되었다고 해서 문서가 성공적인 것은 아닙니다
PDF 프로세서는 종종 컴파일러(compiler)처럼 취급됩니다. 명령이 성공적으로 종료되면 출력이 수용되는 식입니다. 하지만 그것만으로는 충분하지 않습니다. 유효한 PDF라 할지라도 누락된 페이지, 읽기 어려운 작은 텍스트, 깨진 링크, 중복된 OCR 레이어, 또는 입력보다 큰 출력 크기를 가질 수 있습니다.
최소한의 검증 단계는 페이지 수(page count), 페이지 크기(page dimensions), 파일 크기, 그리고 추출 가능한 텍스트를 비교해야 합니다. 또한 시각적 검토를 위해 소수의 페이지를 이미지로 렌더링해야 합니다.
pdfinfo input.pdf > before.info
pdfinfo output.pdf > after.info
...
대용량 문서의 경우, 일반 본문 페이지 1개, 이미지 위주 페이지 1개, 그리고 표나 작은 라벨이 포함된 페이지 1개를 포함해야 합니다. 무작위 샘플링(Random sampling)도 유용하지만, 위험 기반 샘플링(risk-based sampling)이 더 좋습니다.
입력보다 품질이 낮은 출력은 거부하세요
압축은 때때로 파일 크기를 증가시킬 수 있습니다. 작은 텍스트 PDF가 페이지를 이미지로 렌더링한 후 커질 수 있습니다. 이미 최적화된 문서도 다시 작성될 때 오버헤드를 얻을 수 있습니다. 프로덕션 파이프라인(production pipeline)은 크기를 비교하고 의미 있는 개선이 없을 경우 후보 파일을 게시하는 것을 거부해야 합니다.
이 규칙은 명백하게 들리지만, 팀이 변환 완료 여부에 초점을 맞추기 때문에 종종 누락됩니다. “개선 없음”은 유효한 결과입니다. 더 큰 파일을 자신 있게 전달하는 것보다 원본 파일을 반환하는 것이 낫습니다.
마스터 파일 보관 및 배포용 사본 제작
가장 안전한 워크플로우는 하나의 파일이 모든 목적을 충족하도록 요구하지 않습니다. 편집, 아카이빙(archiving), 인쇄를 위해 원본 또는 고품질의 마스터 파일을 보관하세요. 이메일, 업로드 포털, 모바일 리딩 또는 채팅용으로 별도의 배포 사본(delivery copy)을 제작하세요.
이러한 분리는 논의 자체를 바꿉니다. 더 이상 유일한 사본을 영구적으로 저하시킬지 여부를 결정하는 것이 아닙니다. 진실의 원천(source of truth)을 보존하면서 알려진 목적지에 최적화된 출력을 만드는 것입니다.
자동화가 가치가 있는 시점 결정하기
하나의 업로드 실패가 플랫폼 구축을 요구하지는 않습니다
만약 문제가 단일 PDF이고 마감 기한이 임박했다면, 로컬 처리 스택(local processing stack)을 구축하는 것은 아마도 잘못된 최적화일 것입니다. PDFCompress와 같은 브라우저 기반 옵션은 엔지니어링 환경을 건드리지 않으면서 배포 사본을 처리할 수 있습니다. 유용한 습관은 여전히 동일합니다: 원본을 보관하고 해당 장치나 포털에서 결과를 검사하는 것입니다.
제품 언급(product mention)은 여기에 속합니다. 왜냐하면 이곳이 엔지니어링 판단과 운영 현실이 만나는 지점이기 때문입니다. 모든 파일 문제가 새로운 코드를 받을 자격이 있는 것은 아닙니다.
반복성은 자동화의 신호입니다
자동화는 동일한 원인이 반복적으로 동일한 실패를 낳을 때 가치가 높아집니다. 만약 보고 시스템이 매일 이미지 위주의 PDF를 내보낸다면, 해당 작업에 사전 검사(preflight), 변환(transformation), 유효성 검사(validation), 그리고 대체 방안(fallback)을 구축해야 합니다. 입력 크기, 출력 크기, 페이지 수, 선택된 전략, 그리고 유효성 검사 결과를 기록하세요.
이러한 측정값들은 "PDF 압축"을 신비로운 버튼에서 관찰 가능한 파이프라인으로 바꿉니다. 또한 회귀(regressions)를 눈에 보이게 만듭니다. 템플릿 변경으로 인해 보고서 크기가 두 배로 늘어난다면, 사용자가 업로드 오류를 겪기 전에 팀이 변화를 감지할 수 있습니다.
최선의 기본값은 되돌릴 수 있는 결정이다
보편적인 PDF가 없기 때문에 보편적인 압축 사전 설정값(preset)은 없습니다. 유용한 시스템은 목적지 제약 조건(destination constraint)을 충족하는 가장 덜 파괴적인 변경을 수행하고, 그 결과를 검증하며, 원본 소스를 유지합니다.
오후 4시 57분에 실패했던 배포 매뉴얼은 영웅적인 알고리즘이 필요하지 않았습니다. 그것은 더 작은 전달 사본과 다음 주에 같은 놀라움을 방지할 수 있는 워크플로우가 필요했습니다.
이것이 더 큰 교훈입니다. 압축은 "진짜 작업" 이후의 최종 단계가 아닙니다. 문서가 시스템과 사람 사이를 이동해야 하는 순간, 배포(delivery) 자체가 엔지니어링의 일부가 됩니다.