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