며칠 전, Plasma 데스크톱의 기본 PDF 뷰어인 Okular에서 민감한 정보를 가리는(redact) 방법을 소개했습니다. 이 작업 자체는 비교적 간단하지만, 가려진 정보를 실제로 파괴하는 것이 아니라 단지 화면에서 보이지 않게 숨기는 것에 불과합니다.
오늘 소개할 내용은 이 퍼즐의 두 번째 조각, 바로 PDF 문서의 '평탄화(flattening)'입니다. 여러 레이어로 구성된 이미지를 레이어 없는 형식으로 저장하는 것을 생각해 보세요. 모든 정보가 하나의 레이어로 합쳐지고, 수직으로 쌓인 픽셀 값들이 계산되어 하나의 최종 결과물로 표현됩니다. PDF도 같은 원리이지만, PDF 구조 특성상 더 복잡합니다. 그럼 시작해 보겠습니다.
핵심 도구 - Ghostscript
Ghostscript(gs)라는 이름을 한 번쯤 들어보셨을 겁니다. 저 역시 LaTeX와 LyX 관련 글에서 여러 차례 언급한 적이 있습니다. 이번에는 gs 엔진을 사용해 기존의 '다중 레이어' PDF를 평탄화된 PDF로 변환함으로써, 가려졌던 정보가 제대로 삭제되도록 처리하겠습니다. 작업 환경은 Linux입니다. Linux가 다른 운영체제보다 확실히 뛰어난 분야 중 하나가 바로 파일 형식 처리 같은 구체적이고 집중적인 작업이기 때문입니다. 대부분의 배포판에 Ghostscript가 포함되어 있으며, 설치되어 있지 않더라도 저장소에서 쉽게 찾을 수 있습니다.
gs -sDEVICE=pdfwrite -dPDFSETTINGS=/default -dNOPAUSE -dQUIET -dBATCH -sOutputFile=flattened.pdf input.pdf
바로 이 명령어가 마법을 부립니다. PDF 파일에 포함된 이미지에 추가적인 처리를 하지 않기 때문에 파일 크기가 크게 줄어들 것이라 기대해서는 안 됩니다. 어차피 그것이 목적이 아니니까요. 하지만 사실상 이것만으로 충분합니다.
대안 방법 - ImageMagick과 pdf2ps
위 방법이 어떤 이유로든 만족스럽지 않다면 시도해 볼 수 있는 다른 방법이 두 가지 있습니다. 다만 필자가 테스트한 결과 gs를 사용하는 것이 더 효과적이었으므로, 아래 방법들을 진행하기 전에 이 점을 참고하시기 바랍니다.
먼저 ImageMagick의 convert 유틸리티를 사용해 볼 수 있습니다. 하지만 잠시 기다려 주세요.
convert -density 300 original.pdf flattened.pdf
기본 설정에서는 Ghostscript 엔진의 보안 취약점 때문에 ImageMagick이 PS, PDF, EPS, XPS 등 다양한 파일 형식을 처리하지 않도록 구성되어 있습니다. 따라서 ImageMagick 정책을 수정하지 않은 상태에서 실행하면 다음과 같은 오류가 발생합니다:
convert-im6.q16: attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/408.
convert-im6.q16: no images defined `flattened.pdf' @ error/convert.c/ConvertImageCommand/3258.
이 문제를 해결하려면 다음 파일을 편집해야 합니다. [NUMBER]는 사용 중인 버전에 맞춰 6 또는 7로 변경하세요:
/etc/ImageMagick-[NUMBER]/policy.xml
이 파일에는 보안 정책 목록이 담겨 있습니다:
...
<policy domain="coder" rights="none" pattern="EPS" />
<policy domain="coder" rights="none" pattern="PDF" />
<policy domain="coder" rights="none" pattern="XPS" />
</policymap>
PDF 항목을 찾아 rights="none"을 rights="read|write"로 변경하세요. 보안이 걱정된다면 특정 파일을 평탄화하는 동안에만 일시적으로 변경하고, 작업이 끝난 후 원래의 안전한 설정으로 되돌리는 방법도 좋습니다.
...
<policy domain="coder" rights="none" pattern="EPS" />
<policy domain="coder" rights="read|write" pattern="PDF" />
<policy domain="coder" rights="none" pattern="XPS" />
</policymap>
이제 파일을 처리할 수 있습니다. 일반적으로 gs를 직접 사용하는 것보다 시간이 더 오래 걸립니다. 게다가 매우 큰 파일을 다룰 때는 메모리가 부족해 변환에 실패할 수도 있습니다. 예를 들면 다음과 같습니다:
convert-im6.q16: cache resources exhausted `flattened.pdf' @ error/cache.c/OpenPixelCache/4083 `flattened.pdf' @ error/pdf.c/WritePDFImage/2341.
이 경우에도 XML 설정 파일을 수정해 각 정책의 메모리 제한을 늘려야 합니다. 하지만 시스템의 가용 메모리보다 문서가 너무 커서 어쩔 수 없는 경우도 있을 수 있습니다. 저도 마법처럼 통하는 최적의 설정값을 제시해 드릴 수는 없습니다:
...
<policy domain="resource" name="memory" value="2048MiB"/>
<policy domain="resource" name="map" value="4096MiB"/>
<policy domain="resource" name="width" value="256KP"/>
<policy domain="resource" name="height" value="256KP"/>
<policy domain="resource" name="area" value="1024MB"/>
<policy domain="resource" name="disk" value="4GiB"/>
...
두 번째 도구는 pdf2ps와 ps2pdf의 조합입니다. 기본적으로 PDF를 PS 파일로 변환한 후 다시 PDF로 되돌리는데, 이 과정에서 문서가 효과적으로 평탄화됩니다. 명령어는 다음과 같습니다:
pdf2ps original.pdf - | ps2pdf - flattened.pdf
이 방법도 잘 작동하고 속도도 빠르지만, 기본 설정에서는 공격적인 압축 때문에 이미지 해상도가 낮아지는 단점이 있습니다. 이 점을 고려해 도구의 다양한 옵션을 실험해 보면서 필요한 문서 충실도를 유지하도록 하세요.
마치며
이것으로 PDF 파일을 평탄화하는 방법을 익혔습니다. 이러한 기술이 내부적으로 어떻게 작동하는지에 대한 세부 사항은 이 글의 범위를 벗어나지만, 적어도 작업을 완수할 수 있는 도구는 손에 넣으셨을 겁니다. 필자의 경험상 Ghostscript가 가장 빠르고 효과적이며, 결과물의 품질도 가장 뛰어났습니다.
소개한 다른 두 가지 유틸리티인 ImageMagick과 pdf2ps/ps2pdf 조합도 직접 사용해 볼 수 있습니다. 다만 필자는 그 결과에 크게 만족하지 못했습니다. 어쨌든, 이제 다른 사람들과 PDF 파일을 공유하면서 특정 정보를 안전하게 가리고 싶다면 두 단계로 구성된 이 튜토리얼 시리즈로 문제를 해결할 수 있습니다. 이번 두 번째 가이드로 퍼즐이 완성되었습니다. 그럼 다음 글에서 만나요!
감사합니다.