드라마 실리콘밸리의 진보된 동영상 압축 기술처럼 우리 서비스에서도 이미지 압축이라는 이슈가 존재한다. << 품질은 높이고 싶고, 용량은 줄이고 싶은 불멸의 과제가 있다. >>
사진 콘텐츠를 저장하는 포맷으로 무손실 압축 포맷인 PNG는 일단 매력적인 후보였다.
PNG는 미국 컴퓨서브가 중심이 되어 개발한 그래픽 포맷이다. GIF 의 저작권을 갖고 있던 유니시스사가 저작권료를 부과하려는 움직임에 등장하게 되었는데, 저작권 이슈뿐만 아니라 GIF 가 가진 속도의 한계, 색상의 한계 등 여러 가지 문제점들이 보완되어 나왔다. PNG 는 이후 w3c 표준이 되기도 하였다.
PNG 포맷으로 자체 결정 후, 이미지를 최적화하기 위해 몇 가지 내린 가정과 결론이 있었다.
이 글에서는 그 내용에 대해 소개하려고 한다.
정리한 내용은 아래와 같다.
가정 1. JPEG 은 손실 압축, PNG는 무손실 압축이므로, PNG 가 낫다.
> 물론 그렇다. 하지만 꼭 그렇지는 않더라.
JPEG 포맷은 손실 압축 포맷임에는 틀림없으나 이미지 압축 처리 알고리즘에는 오랜 시간 동안 갈고닦아온 내공도 많고, 다양한 기술이 종합적으로 들어가 있다. JPEG 의 출력 방식은 Sequential과 Progressive 가 있는데 Pregressive는 PNG 의 Interlaced 모드와 비슷하게 하나의 이미지를 여러 번 스캔하여 점진적으로 뚜렷하게 보이도록 하는 방법이다. 차이가 있다면 PNG 의 홀수 짝수의 이미지를 출력하는 형태와는 달리 전체 이미지를 아주 낮은 해상도로 출력하고 서서히 또렷해지는 방법으로 처리한다.
JPEG는 기본 알고리즘은 Huffman이나 Arithmetic 의 압축 방식을 사용한다. 두 방식은 유사하나 Arithmetic 은 특허로 보호받기 때문에 함부로 사용할 수가 없다고 한다. 또한 JPEG는 각 픽셀의 색상을 8bit 또는 12bit로 표현할 수가 있다.
JPEG 의 규격 중에는 Lossless 가 있다. 압축을 하지 않는 대신에 화질 저하를 막는 방법인데, JPEG 포맷이라고 해서 무조건 화질이 떨어진다고는 볼 수 없는 부분이기도 하다.
게다가 포토샵 등의 툴을 이용하면 Quality를 10% 정도 떨어트리는 정도로 육안으로 구분하기 힘들 정도로 차이가 없는 결과물을 만들어 내고 있으며, 신기하게도 Quality 10% 저하는 용량 40%(대략) 감소의 결과를 내주고 있다.
그렇다. JPEG 은 충분히 좋은 포맷인 것이다.
JPEG 의 원리에 대해 좀 더 상세한 자료를 원한다면 여기로 가면 된다.
아래 이미지처럼 적당한 Quality 조절은 차이가 별로 없다.
JPG 에 반해 PNG는 무손실 압축 포맷이다.
콘텐츠 사진의 품질을 중요하게 생각하다 보니 다양한 규격의 변형에도 견딜 수 있는 `무손실`이라는 단어에 꽂혔다. JPG는 이미지 회전만 몇 번 해도 금세 화질이 달라진다. ( 만약 이미지 포맷을 고려할 때 JPEG 의 무손실 방식이 존재함을 알았다면 PNG 에 대한 고민은 적었을지도 모른다. )
이것만으로도 선택하기에 충분한 이유가 되었으며, 한 가지 아쉬운 부분은 저장된 이미지의 용량이 크다는 점이었다. 무손실 압축, 압축! 이라더니.. 크더라.
그래서, 일단 PNG를 선택하고, 이후에 용량을 줄여보기로 했다.
나중에 알게 된 내용은 용량에 있어서 JPG 가 무조건 유리하다고 할 수는 없다는 것이다. 촬영한 사진 이미지처럼 복잡한 형태의 이미지라면 JPG 가 좋지만 인공적으로 만든 이미지인 경우 PNG 압축이 더 유리하기 때문이다.
촬영한 사진을 PNG로 바꾸면 용량이 커지지만, PC 의 화면을 캡처하는 등의 경우에는 PNG 가 훨씬 작다.
결론적으로 콘텐츠 사진은 PNG 가 아니라 JPG를 선택했어야 한다는 것이다.
가정 2. 촬영 이미지의 EXIF 정보를 삭제하면 불필요한 용량을 줄일 수 있다.
> 아니다. PNG는 EXIF 가 없다.
EXIF(EXchangable Image File format ) 디지털카메라에서 이용되는 이미지 파일 포맷이다. 사진 촬영 시 카메라 기종, 렌즈 정보, 저작권, GPS 정보 등을 기록할 수 있다.
큰 용량을 차지하는 것은 아니지만 콘텐츠 하나에 수십 장의 사진을 사용해야 하는 서비스에서는 이런 데이터도 무시할 수 없었다. (티끌 모아 큰 티끌이니..)
사진 촬영 시 저장된 JPEG 파일에는 EXIF 정보가 있다. 그런데 그 파일을 PNG로 변환하면 EXIF 값이 없다.
EXIF는 JPEG, TIFF 에는 있으나 JPEG 2000, PNG, GIF 에는 없는 정보다.
몇 KB라도 줄여보고자 했으나 원래 없는 정보였다.
EXIF 제거는 아이디어는 좋았으나 PNG에서는 의미가 없다.
가정 3. None intelace 방식으로 변경하면 용량이 줄어들 것이다.
> 그렇다. 줄어들더라.
어떤 원리인지는 찾을 수가 없었다. 어쩌면 동일한 색을 종합하여 압축 처리를 할 때, 나뉜 양쪽 프레임에 있는 동일한 색을 각각 압축함으로 인해 용량이 증가하게 되는 것일지도 모르겠다.
인터레이스 방식은 우리나라 HDTV 규격이기도 하다. 홀수와 짝수로 나뉜 30 프레임을 합쳐 초당 60 프레임을 완성하는 형태이다. GIF와 PNG 가 Interlaced 방식을 지원하는데, 이미지 로딩이 느린 경우에는 일부분이 채워지고, 조금 후에 다른 부분이 채워지다 이미지가 완성되는 모습을 볼 수 있다.
None interlaced 방식으로 저장하면 용량이 줄어든다. 약 10~30%.
가정 4. 오픈소스로 공개된 훌륭한 이미지(PNG) 압축 기술이 존재할 것이다.
> 그랬다. 효과적으로 활용 가능한 기술이 상당히 많다.
2016년 7월에 드롭박스가 발표한 Lepton 이라는 기술이 있다. 이미지를 손실 없이 22% 줄일 수 있다는 내용의 오픈소스이다. github 등에서 찾아보면 그래픽 포맷별로 용량을 줄일 수 있는 여러 라이브러리를 쉽게 찾을 수 있다.
그중 내가 선택한 것은 pngquant라는 라이브러리로 현재 2.7.2 버전까지 공개되어 있다. (최신 버전은 구 버전에 비해 압축률과 속도가 굉장히 많이 개선돼있다.)
큰 노력 없이도 17MB PNG 이미지를 8MB로 50% 줄일 수 있으며, 포토샵에서 1000%쯤 확대를 해야지만 두 이미지의 차이를 찾을 수 있을 만큼 손실 없는 압축이 가능하다.
리눅스 물론이고 윈도, 맥 버전도 제공하고 있어서 콘텐츠 사진이 업로드되면 실시간으로 pngquant를 통해 한 번 더 압축을 하는 형태로 계획했다. 당연히 이 하나로 인해 트래픽과 스토리지 모두에 이점이 생겼다.
아래는 compressor.io라는 사이트인데, 원본과 압축 후의 이미지를 비교해 볼 수 있다. 기술에 대한 검증이 필요하면 사이트를 한 번 방문해보시길...
pngquant 등으로 이미지 압축 시 약간의 처리 시간은 필요하지만, 용량과 트래픽, 스마트폰 앱에서의 메모리 관리 부분까지 생각한다면 충분히 의미 있는 작업이 될 수 있다.
가정 5. WebP는 사용이 어렵다.
> 매력은 있지만... 그렇다. 어렵다.
WebP는 구글이 On2 테크놀러지스의 기술을 구매하여 개발한 무손실과 손실을 모두 지원하는 이미지 포맷이다. 애초의 목적은 웹사이트에서 사용되는 JPEG를 대체하기 위한 규격으로 트래픽 감소, 로딩 속도 단축 등을 목적으로 사진에 대한 압축 효과가 높은 것으로 알려져 있다. 실제 테스트를 해보면 JPEG 이미지가 10MB인 경우, 2MB 정도로 용량은 줄이면서 화질은 유지할 수 있다.
다만 모든 브라우저에서 지원하고 있지는 않으며, 크롬과 오페라, IE 의 일부 버전의 브라우저에서만 지원이 된다. WebP 가 개발된 것이 2010년 이므로 그 이전에 개발된 브라우저는 지원이 사실상 어렵다.
그래픽 툴로 유명한 Adobe Photoshop 의 CC 버전에서도 webp 포맷은 열리지 않는다.
그나마 희소식은 iOS 10 에서는 WebP를 지원하고 있다고 한다. (실제로 해보면 잘 안되기는 하던데...)
스마트폰에서만 서비스한다고 해도, iOS 10 만 서비스할 수는 없으므로 아직은 시기상조인 듯.
우리는 결국 품질의 손상이 육안으로 쉽게 식별하기 어려울 정도로 타협하여 JPG를 선택했다.
그리고 서비스 앱에서 저장 시 손실 압축 프레임웍을 활용하여 JPG 용량을 조금 줄여서 세이브한다.
이들은 AWS S3 에 보관하고, 보관된 이미지는 JPEGmini 를 통해 다시 한 번 압축에 들어간다.
그리고 여러 디바이스 규격에 적절한 이미지를 전송하기 위해 몇 가지 규격의 SET을 구성했다.
이렇게 저장된 이미지는 Akamai DD를 통해 서비스가 되고 있다.
JPEG 압축 처리에 대한 솔루션 도입이 바로 필요하다면 JPEGmini 와 kraken.io 가 도움이 될 수 있다.
JEPGmini server 는 AWS 의 Marketplace 에서 간단히 구축할 수 있고, CLI 를 통해 간단히 변환이 가능하며, API 를 통한 처리 또한 가능하다.
이후 상황이 약간 바뀌었는데,
영상의 프레임을 이미지화 시키는 ffmpeg 모듈에서 qscale 조정을 통하여 식별이 어려울 정도의 품질 저하를 용인하면, 거기에서 세이브할 수 있는 이미지 용량이 어마어마하다. (설정만 바꿔도 30% 정도 용량 감소)
이렇게 처리된 이미지는 jpegmini 에서 재압축 시 처리가 되지 않을 정도로 ffmpeg 에서 상당히 최적화 된 상태로 익스포팅된다. ( jpegmini 처리하는데 들이는 비용과 시간도 세이브할 수 있다. )
이후 상황이 또 바뀌었는데,
Akamai 에 Image Converter 라는 서비스가 개선되었다.
아직 도입은 하지 않았으나 하나의 사진 이미지를 등록하면 다양한 규격과 포멧으로 저장하고,
이들은 이 이미지를 호출한 디바이스에 따라 최적화된 이미지를 보내주는 방식이다.
(스마트폰의 해상도에 따라, 플랫폼에 따라 더 적절한 이미지가 알아서 전송된다. 유후.)