이번에 회사에서 진행한 프로젝트에서 PDF변환 작업이 있었는데 PDF를 다운 받을 경우 3~4MB에 해당하는 용량이 나오는 이슈가 있었다.
해당 프로젝트를 진행할 당시 촉박한 데드라인으로 요구사항인 PDF 다운로드 기능만 구현한 채 배포하게 되었는데, PDF 파일의 용량이 커질수록 업로드/다운로드 속도가 느려지고, 저장 공간도 많이 차지하게 되어 최적화를 진행하게 되었다.
다음은 PDF 용량을 3.2MB에서 220KB까지 줄인 과정과 적용한 최적화 기법들이다.
ps. 현재 프로젝트에서 사용중인 PDF라이브러리 : pdf.js
📌 PDF 저장 시 객체 스트림 사용 최소화
PDF는 기본적으로 객체 스트림(Object Streams)을 사용해 저장되는데, 이를 비활성화하면 용량을 줄일 수 있다.
const pdfBytes = await pdfDoc.save({ useObjectStreams: false });
📌 이미지 용량 최적화
PDF 내부에 포함된 이미지의 용량을 줄이는 것도 중요한 최적화 방법이다.
✅ JPG 품질 조정
기본적으로 quality: 0.8로 설정되어 있는데, 값을 낮추면 용량을 줄일 수 있다.
const imageJpg = await pdfDoc.embedJpg(imageBytes, { quality: 0.6 });
✅ 이미지 포맷 변경
이번 프로젝트에서는 이미지 포맷을 변경 할 경우 앱에서 그린 이미지가 서버에 저장되고, 이를 뿌려주고 있기 때문에 최후의 선택으로 두었다.
실제로 이미지가 차지하는 용량이 많이 크지는 않아서 줄인다고해도 미묘할 것으로 예상되었기 때문이다.
이미지 포맷의 경우 jpg는 카메라로 찍은 사진, png는 만들어진 이미지에 최적화되어있다. 현재 jpg를 사용하고 있는데 우리가 사용하고있는 사인 이미지처럼 만들어진 이미지일 때는 PNG로 저장하는게 용량이 줄어들기 때문에 PNG 혹은 다른 포맷을 사용하면 용량을 더 줄일 수 있다.
📌 기본 PDF 용량 압축
기본적으로 위에 글자를 입히기 전인 기본 pdf 파일의 용량을 압축해주었다.
260kb의 pdf를 압축 프로그램을 통해 172kb까지 압축하였으며 화질이 저하되는 문제는 없었다.
기존에는 PretendardVariable.ttf 전체를 PDF에 임베드했기 때문에 불필요한 글자까지 포함되면서 용량이 커지게 되었다.
이를 해결하기 위해 서브셋을 적용하여 필요한 글자만 포함시키는 방법을 사용했다.
처음에는 pdf.js에서 자체적으로 지원하는 subset 속성을 사용해서 적용하였다.
const customFont = await pdfDoc.embedFont(fontBytes, { subset: true });
하지만 pdf에서 일부 글자가 표시가 되지 않는 등 폰트가 깨지는 문제가 발생했다.
그러나 해당 파일의 용량을 봤을때 용량이 현저히 줄어있었다.
220kb까지 용량이 줄어든 것을 보아 현재 pdf에서 가장 큰 문제점이 바로 폰트임을 알 수 있었다. 실제로 프리텐다드 폰트의 용량을 보니 약3MB였고, pdf에서 폰트를 불러오면서 용량이 커진것을 확인할 수 있었다.
그렇다면 폰트 자체의 용량을 줄이면 해결되지 않을까 싶어서 프리텐다드의 서브셋 폰트를 찾아봤는데 현재 pdf에서 사용가능한 폰트가 없었다.
📌 subset 프로그램으로 폰트 경량화 후 적용
현재 사이트에서는 프리텐다드를 사용중인데 해당글자의 경우 경량화된 폰트를 찾기가 어려워서 직접 경량화 작업을했다.
경량화 작업을 하는방법은 일본 프로그램을 사용했는데 주로 많이 사용되고 있는 것 같았다.
경량화 방법은 해당 블로그에서 자세히 다루고있다.
링크 : https://drybone-developer.tistory.com/72
경량화 작업을 통해 폰트 용량을 400kb대로 줄였으며 최종 pdf의 용량또한 455kb로 줄었다.
📌 서브셋 속성 적용
const customFont = await pdfDoc.embedFont(fontBytes, { subset: true });
아까 적용해보았던 서브셋 속성이 특정 폰트에서만 적용이 안되기때문에 경량화 작업한 폰트에서는 적용이 되는지 확인해보았는데 다행히 폰트가 깨지는 것도 없었으며 용량도 효과적으로 줄어드는 것을 볼 수 있었다.
처음 원본 프리텐다드 폰트에서 속성이 제대로 적용 되지 않았던 것은 원본 폰트가 최적화되지 않았기 때문이었던 것으로 추측한다.
경량화된 폰트를 적용한 후에는 pdf에 폰트 역시 정상적으로 출력되었으며, 용량 역시 대폭 감소하였다.
지금까지 비교한 피디에프의 경우 220kb까지 줄어든 것 을 볼 수 있었다.
글자수나 내용에 따라서 용량이 달라지긴하나 약 190kb ~ 250kb 사이정도의 용량으로 출력되는것을 확인했으며 텍스트를 최대 값으로 넣었을때도 255kb 정도로 확인되었다.
📊 기존 대비 용량 변화
최적화 전 : 3.2MB
최적화 후 : 220KB
감소율 : 93.13% 감소
📌 텍스트 양에 따른 용량 변화:
일반적인 PDF: 190~250KB
텍스트 최대 입력 시: 255KB
최종적으로 약 3.2mb -> 220kb로 용량을 최적화해서 93.13% 의 용량을 줄이게 되었다.
지금까지 프론트엔드 개발을 하면서 데드라인이 촉박하다보니 최적화를 깊게 신경쓰지 못한 부분들이 많았는데 이번 기회를 통해 다시 한 번 최적화의 중요성을 깨닫게 되었다.
이렇게 큰 감소율이 나타나게 된 것이 뿌듯하기도 하면서 한편으로 내가 처음 개발할때 너무 안일하게 생각하고 구현에 급급했던 것 같아 반성하게 되기도 하였다.
앞으로 차근차근 개발 기간때문에 놓친 최적화 부분들을 찾아보며 개선해나가야지! 그리고 새로운 개발을할때도 최적화를 신경쓰며 유저가 사용하는데 불편함 없는 페이지를 개발하도록 노력해야겠다.