개요
최근 취미로 작성중이던 프로그램에서 주 콘텐츠를 3D 렌더링으로 테마를 잡았다. 작성 중에 수십에서 수백메가는 기본이고 기가급을 넘나드는 다양한 3D 모델 파일들도 보게 되면서 자연스럽게 대용량 네트워크 트래픽에 대한 문제와 그 해결방식에 대해 호기심을 갖게 되었다.
이러한 호기심을 가진 상태로 다양한 3D 모델 파일을 공유하는 사이트들의 트래픽을 뜯어보게 되었는데 희한하게도 대용량이어야할 모델 파일이 쉽게 눈에 띄지 않았다. 아주 적은 용량의 파일을 수신하여 깨끗한 3D 모델을 렌더링하는 것을 보고 흥미를 느끼게 되었다.
Draco 압축
구글에서 만든 Draco 도형 압축으로 3D 데이터 최적화드레이코 압축은 오픈소스 라이브러리로 누구나 무료로 사용할 수 있다.
설정에 따라서 압축률은 다르지만 적당히 설정하면 육안으로는 쉽게 구분이 불가능할 정도의 수준에서 높은 압축률을 보여주기 때문에 아주 유용하게 사용할 수 있다. 80MB 모델을 거의 10MB 수준으로 압축할 수 있는 이게 되는 거였나 싶은 수준이다.
물론, 다른 압축 알고리즘도 극한의 설정으로 높은 압축률을 끌어올릴 수 있지만 긴 시간이 필요한 것에 비해 Draco압축은 80메가를 80%에 가까운 압축으로 거의 3초 안에 끝이 났다.1 3D 도형 압축에 특화된 압축이라 그렇겠지만 처음 모델 압축을 완료했을 때에는 박수를 치지 않을 수 없었다.
사용법
Nodejs에서는 Cesium 팀에서 만든 gltf-pipeline을 사용하여 압축을 할 수 있다.
sudo npm i -g gltf-pipeline
설치 후에는 글로벌 명령으로 사용할 수 있는데 압축할 GLTF 파일이 있는 곳에서 실행하면 된다. 압축해볼 대상 파일은 80메가 파일로 텍스쳐 23.6메가 까지 합치면 100메가 정도 된다.
gltf-pipeline -i scene.gltf -o build/scene.gltf -d \
--draco.compressionLevel 10 \
--draco.quantizePositionBits 14 \
--draco.quantizeNormalBits 10 \
--draco.quantizeTexcoordBits 12 \
--draco.quantizeColorBits 8 \
--draco.quantizeGenericBits 10
이 명령은 draco압축만을 위한 명령이 아니기 때문에 -d 옵션을 통하여 draco 압축 알고리즘을 사용하겠다고 명시해야한다. 더 자세한 옵션과 설정법들은 깃헙 저장소에서 확인할 수 있다.
뒤 옵션들은 모델에 영향을 주기 때문에최적화 압축을 해제한 결과가 뭉게지는 등 영향을 받을 수 있다. 모델마다 적절한 옵션값을 찾아서 육안으로는 쉽게 구분이 불가능하면서 높은 압축률을 가지는 옵션을 찾는 것이 좋다.
용량이 반으로 줄었다. 이렇게 한 번 압축하고 나면 압축된 gltf가 생성되는데 여기서 glb 옵션으로 한 번 더 압축하여 크기를 더 줄일 수 있다.
gltf-pipeline -i build/scene.gltf -o build/scene.glb
추가로 10메가를 더 확보했다. 결과적으로 100메가 파일을 거의 70% 가까이 압축하였다. 이렇게 압축된 파일을 텍스쳐 파일도 하나로 묶이기 때문에 여러번 응답해줄 필요도 없고 네트워크 입장에서 아주 바람직한 결과가 되었다.
그러나 10명만 붙어도 300메가 트래픽이기 때문에 웹 서비스를 하기에는 부담스러운 용량으로 보인다만, 영상 스트리밍과 같은 대용량 트래픽이 일반적이된 요즘 시대에서는 그렇게 큰 일이 아니지 않을까 하는 생각도 한다.2
용량 더 줄이기
나의 경우처럼 1메가의 트래픽도 아까운 경우라면 텍스쳐 파일을 최적화하는 방법도 적용할 수 있다. 텍스쳐 파일은 보통 jpg, png로 구성된 경우가 많은데 웹 브라우저에서 보여주는 것이 목적이라면Chrome 계열 webp로 변환하여 최적화 하는 것도 좋은 선택지 중에 하나이다.
imagemagick을 사용하면 쉽게 변환할 수 있다. webp의 경우도 압축시 품질 옵션을 줄 수 있는데 80% 이하로 내려갈 수록 압축률이 크게 차이가 나지 않기 때문에 가장 합리적이라고 한다.
convert -quality 80 textures/face.jpg textures/face.webp
webp도 높은 압축률을 제공하기 때문에 거의 60 ~ 80% 까지 용량을 줄일 수 있다. 텍스쳐 파일을 변경했다면 원본 gltf 파일을 열어서 해당 텍스쳐 파일을 참조하는 값을 변경해준다.
webp로 변환한 파일로 경로를 바꾸고 바뀐 정보로 다시 압축을 진행해보자.
100메가 파일이 12.7메가가 되었다. 1차 작업 결과인 30메가보다 더 부담이 없어졌고 이 정도면 3D 서비스라는 점을 고려하여 네트워크 트래픽과 비용에 대해서도 충분히 납득할 수 있겠다.
원본과 비교한 사진이다. 좌측이 100메가 모델이고 우측이 방금 압축한 12.7메가 모델이다. 서로 렌더링 효과가 다르기 때문에 색이나 질감이 조금 차이가 있지만 동일하게 맞춰준다면 나같은 막눈들은 육안으로 식별이 불가능했다. 많이 확대하였을 때에도 적당히 효과가 주어지면 분간하기 힘들 것이라 생각한다. 감각이 좋아서 분간이 가능하더라도 이 압축률이라면 충분히 감당할 수 있을 정도라 생각하고 3D 모델을 다운로드 받는 시간도 많이 줄어들어 좋은 점들이 더 매력적으로 다가왔다.