내가 속해 있는 Campus
팀에서 영양사님과 협업하여 식단의 이미지를 올려 학생들이 볼 수 있는 기능을 개발했다
기존에는 이러한 기능이 학교와 코인
어플에도 없었는데 우리 동아리에서 협업을 해서 만든 기능이라 새로운 사용자를 기대할 수 있었다
하지만 이미지의 특성상 용량이 클 수 밖에 없었다
학식을 직접 촬영하고 용량을 확인해보니 대략 2mb정도 됐고 크면 3mb 근처까지도 갔다
이미지가 크면 로딩시간이 증가하고 그렇게 되면 사용자 이탈률이 증가한다
이를 막고자 이미지 최적화를 시작했다
webp 는 손실/비손실 압축 이미지 파일을 위한 이미지 포맷이다.
웹사이트의 트래픽 감소 및 로딩 시간 단축을 겨냥한 것으로, 사진 이미지 압축 효과가 높다
손실 압축 포맷으로 화질 저하를 최소화하면서 파일 크기를 축소(같은 품질 JPEG 이미지 대비 10% ~ 80% 압축)
이러한 이유로 이미지 최적화를 진행할 때 확장자를 동일 품질 대비 용량의 효율이 좋은 webp
로 정하고 진행하게 되었다
파이썬 코드를 이용해서 리사이징을 진행하다보니 다른 이슈가 생겼다
바로 이미지에 있는 메타데이터
로 인해 발생한 문제였다
이런식으로 이미지 정보에 들어가보면 Exif
라는 메타데이터가 존재한다
사진을 언제, 어디서, 어떻게 찍었는지에 대한 내용, 카메라 설정값 등 다양한 정보들이 들어가있다
그 중 문제가 되는것이 Orientation
이라는 메타데이터다
원본 사진에 회전값이 들어가 있는 경우가 있다
이런식으로 Orientation
에 1부터 8까지 값이 들어가 있으면 해당 하는 값으로 회전이 되어있다
근데 이미지 압축 과정에서 해당 메타데이터가 사라져서 원본의 그대로가 아닌 이미지가 돌아가는 현상이 발생했다
그래서 최적화 하는 과정에서 이미지의 Orientation
값을 뽑아내어 돌려주는 코드를 추가해줬다
이미지 최적화를 하기 전에 적절한 이미지 용량 기준을 세워야했다
아래의 이미지를 보면 웹페이지 로딩시간에 따른 사용자 이탈률을 볼 수 있다.
참고사이트 : 구글 Find out how you stack up to new industry benchmarks for mobile page speed
모바일 웹 사이트의 로딩 시간이 3초 이상일때는 32%, 5초 이상은 90%, 6초 이상은 106% 그리고 10초 이상은 123%의 이탈률이 발생하는것을 볼 수 있다
이번 이미지 최적화는 웹페이지가 아닌 이미지 자체의 로딩 시간을 측정하여 적절한 이미지 리사이징 용량의 기준을 정하고 진행했다
다른사항을 제외하고 이미지 로딩 시간이 3초 이하인 용량을 찾는것을 목표로 진행했다
로딩시간 측정은 웹페이지, 동일한 네트워크 환경에서 측정했다
no throttling
, fast 3G
, slow 3G
이 3가지의 throttling이 있는데 slow 3G
는 사용하는 사람이 거의 없다고 생각하고 제외하고 측정했다
그리고 캐시가 남아있을 수 있으니 Disable cache
상태로 측정했다
1.4mb
기준 → 563ms 걸림
4.2mb
기준 → 1.77s 걸림
업로드 된 사진을 보는 방법은 영양사 페이지
로 보는 방법과 실제 서비스 되는 페이지(https://koreatech.in/cafeteria)
가 있어 두 페이지 모두 측정을 해봤다.
5번 평균 1.50s 걸림
5번 평균 2s 걸림
동일한 이미지를 불러오지만 영양사
페이지와 코인
페이지에서 이미지를 로딩하는 속도가 다르다
1.4mb
기준 → 8.71s 걸림
4.2mb
기준 → 24.36s 걸림
5번 평균 16.36s 정도 걸림
5번 평균 28.8s 정도 걸림
no throttling
은 충분히 빨라서 fast 3G
로 기준을 세워봤다
다른 사항을 고려하는 것은 어려워 이미지 로딩시간만을 측정하여 기준을 세워봤다
285kb의 이미지를 업로드 한 경우 5s 정도가 걸리는것을 볼 수 있고 이는 원하는 목표에 부합하지 않는다.
212kb의 이미지를 업로드한 경우 4.1s 정도의 시간이 소요되는것을 볼 수 있다.
목표에 맞지는 않지만 용량의 최대 기준으로 잡아도 될 정도의 로딩시간으로 생각했다.
3번을 진행하였는데 전부 동일하여 한번 더 진행해도 3.14s가 나왔다.
3번을 진행하였는데 2.04s로 동일한 결과가 나왔다.
2.04s 정도면 목표에 부합하다고 판단하였다
처음 기준 용량은 200kb, 150kb, 100kb로 정하게 되었다.
Fast 3G 기준 4s, 3s, 2s 정도 걸리는데 사용자의 이탈을 줄일 수 있을것으로 보인다.
하지만 이렇게 정한 기준은 이미지의 규격이 일정하지 않아서 클라이언트가 사용하기 불편하다고 생각했다
그래서 변경을 생각하며 얘기를 해보다가 나온 방식이 가로를 고정으로 정해놓고, 세로는 가로가 변경된 비율로 재조정되는 방식을 생각하게 되었다
위의 사이트에서 다양한 사이즈로 나뉘어져 있어서 해당 width
사이즈를 따라가기로 했다
width
→ 320, 640, 800, 1024, 2560
원본 이미지의 width
와 정해진 width
의 비율을 알아내서 height
의 비율을 맞춰 리사이징 해줬다
원래 1024까지만 하려고 했는데
처음에 나는 반대하는 입장이었는데 선권이의 이야기를 들어보니 원본이 너무 큰 경우도 있어서 2560으로 하나 만들어 놓는것 정도는 괜찮다고 생각했다
극단적인 예시로 6000 * 4000 사이즈의 17.0mb 이미지로 실험해봤다
적용해봤는데 확장자가 .webp
로 바뀌기도 하고 width
도 줄어 유의미한 압축률을 보여 그대로 진행하기로 했다
2560을 제외한 나머지 width
들은 첫번째 기준 때 정한 사이즈에 적합하다고 판단하여 원본 포함 총 6개의 이미지를 저장하기로 확정이 됐고 이제 실제 서비스에 적용을 기다리고 있다
처음에 이 작업을 맡았을 때는 고려할게 많지 않아보였는데 막상 맡아서 작업을 진행하다보니 메타데이터, 로딩시간, 확장자 등 고려할게 많았다
그 동안 코딩을 하면서 그냥 주어진 요구사항이 있으면 그에 맞게 코드를 짜왔는데 이렇게 직접 내가 throttling을 걸어 로딩시간을 측정하고 근거를 찾아가면서 작업을 진행하니 재밌었다.
유의미한 차이를 찾을때마다 개발에 대한 의욕도 올라가고 더욱 열심히 할 수 있어서 좋은 경험이었던 것 같다.
앞으로도 요구사항에만 맞춰서 코드를 짜지 말고 근거를 찾고 차이를 분석하면서 코드를 짜면 더욱 즐거운 개발을 할 수 있을것 같다
멋있어요