이미지 최적화

허준기·2024년 6월 19일
14

BCSD

목록 보기
6/8
post-thumbnail
post-custom-banner

개요

내가 속해 있는 Campus 팀에서 영양사님과 협업하여 식단의 이미지를 올려 학생들이 볼 수 있는 기능을 개발했다
기존에는 이러한 기능이 학교와 코인 어플에도 없었는데 우리 동아리에서 협업을 해서 만든 기능이라 새로운 사용자를 기대할 수 있었다

하지만 이미지의 특성상 용량이 클 수 밖에 없었다
학식을 직접 촬영하고 용량을 확인해보니 대략 2mb정도 됐고 크면 3mb 근처까지도 갔다
이미지가 크면 로딩시간이 증가하고 그렇게 되면 사용자 이탈률이 증가한다
이를 막고자 이미지 최적화를 시작했다

webp

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 상태로 측정했다

no throttling 이미지 없는 경우


1.4mb 기준 → 563ms 걸림

no throttling 이미지 2.8mb


4.2mb 기준 → 1.77s 걸림

업로드 된 사진을 보는 방법은 영양사 페이지로 보는 방법과 실제 서비스 되는 페이지(https://koreatech.in/cafeteria)가 있어 두 페이지 모두 측정을 해봤다.

영양사 페이지 2.8mb 이미지 로딩시간

5번 평균 1.50s 걸림

실제 서비스(코인) 페이지 2.8mb 이미지 로딩시간

5번 평균 2s 걸림

동일한 이미지를 불러오지만 영양사 페이지와 코인 페이지에서 이미지를 로딩하는 속도가 다르다

fast 3G 이미지 없는 경우

1.4mb 기준 → 8.71s 걸림

fast 3G 이미지 2.8mb

4.2mb 기준 → 24.36s 걸림

영양사 페이지 2.8mb 이미지 로딩시간

5번 평균 16.36s 정도 걸림

실제 서비스(코인) 페이지 2.8mb 이미지 로딩시간

5번 평균 28.8s 정도 걸림

첫번째 기준 정하기

no throttling 은 충분히 빨라서 fast 3G 로 기준을 세워봤다
다른 사항을 고려하는 것은 어려워 이미지 로딩시간만을 측정하여 기준을 세워봤다

285kb 이미지

285kb의 이미지를 업로드 한 경우 5s 정도가 걸리는것을 볼 수 있고 이는 원하는 목표에 부합하지 않는다.

212kb 이미지

212kb의 이미지를 업로드한 경우 4.1s 정도의 시간이 소요되는것을 볼 수 있다.
목표에 맞지는 않지만 용량의 최대 기준으로 잡아도 될 정도의 로딩시간으로 생각했다.

154kb 이미지

3번을 진행하였는데 전부 동일하여 한번 더 진행해도 3.14s가 나왔다.

87kb 이미지

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을 걸어 로딩시간을 측정하고 근거를 찾아가면서 작업을 진행하니 재밌었다.

유의미한 차이를 찾을때마다 개발에 대한 의욕도 올라가고 더욱 열심히 할 수 있어서 좋은 경험이었던 것 같다.
앞으로도 요구사항에만 맞춰서 코드를 짜지 말고 근거를 찾고 차이를 분석하면서 코드를 짜면 더욱 즐거운 개발을 할 수 있을것 같다

profile
나는 허준기
post-custom-banner

4개의 댓글

comment-user-thumbnail
2024년 6월 19일

멋있어요

1개의 답글
comment-user-thumbnail
2024년 6월 19일

멋있어요!

1개의 답글