본문 바로가기
펀잇

좌충우돌 이미지 압축 구현 일대기

by 해-온 2023. 10. 28.

'펀잇'의 경우 리뷰나 꿀조합 등 이미지가 많다.

따라서 이미지의 용량 제한을 하지 않으면 서버에 부하가 가게 된다.

 

서버에서 10MB의 이미지를 제한하고 있지만 이게 궁극적인 해결책은 아니다.

만약 리뷰 1000개가 모두 10MB의 사진을 넣었다고 가정해 보자.

서버 부하가 심해질 뿐만 아니라, 뷰 측면에서도 스크롤 시 버벅거림이 심해 사용성을 떨어트릴 것이다.

 

압축 라이브러리 도입

따라서 우리 프론트 팀은 'browser-image-compression' 라이브러리를 통해 이미지 압축을 실행하기로 했다.

해당 라이브러리를 통해 1MB로 압축을 시키고, 프론트 단에서는 5MB의 이미지 업로드를 제한했다.

주로 상품 사진이 업로드될 것을 감안했을 때, 고화질 사진을 필요로 하는 경우는 드물 것이라 판단해 5MB로 제한했다.(여태까지 올라온 사진의 평균을 내보았을 때, 5MB를 넘지 않았다)

 

 

하지만 라이브러리 로직을 넣고 위 사진과 같이 이미지를 업로드했을 때 바로 보이지 않는 것을 볼 수 있다.

모바일의 경우 지연이 훨씬 심해, 2MB의 이미지를 업로드시켰을 때 10초가 소요된 경우도 있었다.

 

사용자는 미리 보기 이미지가 제대로 로딩되지 않아 업로드가 실패한 것으로 오해하는 경우가 많았다.

이로 인해 리뷰 작성을 중단하고 떠나버리는 이탈 현상이 발생했다.

 

혹시 내 코드 자체의 문제일까 싶어 추후 해당 라이브러리를 도입한 다른 팀에서도 실험을 해보았는데,

역시 이미지 압축에 많은 시간을 소요하고 있었다.

그래도 해당 팀의 경우 프로필 이미지 수정과 같은 부수적 기능이라 타격이 덜했는데,

우리 서비스의 경우 리뷰 데이터가 가장 핵심적이라 그대로 놔둘 수 없었다.

 

당장 서버 부하를 줄이는 것보다 리뷰를 편하게 작성하게 해 데이터를 수집하는 것이 더 급선무라 생각했고

결국 해당 라이브러리 로직을 걷어내고 원본 그대로 업로드할 수 있도록 했다.

 

 

수작업 진행

문제는 리뷰의 양이 쌓이면서 나타났다.

'펀잇'의 경우 좋아요를 가장 많이 받은 리뷰의 이미지가 상품 이미지가 된다.

 

이게 리뷰가 없는 기본 이미지라고 하면

 

 

좋아요가 있는 리뷰가 생겼을 때 작성자의 리뷰 사진으로 썸네일이 교체된다.

 

점점 사용자를 모으고 리뷰 개수가 쌓여가며 많은 상품 이미지가 교체됐는데

압축을 하지 않고 있다 보니 용량이 커 스크롤을 내릴 때 이미지가 불러와지는 속도가 너무 느렸다.

 

따라서, 이미지 압축을 다른 방식으로 시도해 보기로 했다.

 

먼저, 실제 서비스들은 어떤 방식으로 이미지 가공을 하고 있을까 찾아보았다.

당근마켓이나 올리브영 등 많은 회사에서 AWS Lambda를 사용해 이미지 리사이징을 하고 있었다.

이미지를 업로드할 때 특정 함수를 실행시켜 자동화를 할 수 있다는 게 매력적이었다.

하지만, 비용 문제로 기각했다.

 

다음 방안은 이미지 압축 라이브러리를 사용하되, 실행되는 순서를 바꾸는 방법을 생각해 냈다.

업로드를 할 때 압축 시키는 것이 아니라 사용자가 제출 버튼을 누를 때 압축하는 것이다.

하지만 이 방법도 결국 순서만 바뀌었을 뿐 시간이 오래 걸리는 건 똑같아 기각했다.

 

결국, 우리는 수작업으로 직접 webp 변환과 압축을 하기로 했다.

 

 

라이브러리 재도입

이제 기술적인 문제는 사라졌는데, 효율성이 급속도로 떨어지기 시작했다.

AWS S3 권한이 없어 파일을 한 번에 다운로드할 수 없었고,

하나하나 다 다운로드하여 변환을 시켜야 했다.

 

당시에는 사진이 약 150개 정도라 할만했지만,

나중에 리뷰가 더 많아진다면 과연 할 수 있을까 걱정이 생겼다.

 

결국 개발에 집중할 수 있는 환경을 만들기 위해서는

이미지 압축 자동화가 필요할 수밖에 없다는 생각이 들었다.

따라서 삭제했던 라이브러리를 재도입하기로 했다.

 

그전에 다른 팀의 코드를 분석해 보기로 했다.

초기에는 우리 팀이 가장 먼저 압축 라이브러리를 도입하였고, 이를 활용하는 팀이 소수였는데

이제는 많아져 분석 가능한 코드의 양이 증가했다.

따라서 어떻게 압축 기능을 구현했는지 하나하나 뜯어보았다.

 

그리고 해당 기능을 구현한 크루에게 찾아가서 

같은 문제를 겪고 있지 않은지, 혹시 해결했다면 어떻게 해결했는지에 대해 인터뷰를 하고 다녔다.

 

모 크루와 열띤 토론을 하던 중 해결법을 찾아냈는데 바로 눈속임을 하는 것이었다.

사용자가 이미지를 업로드했을 때, 미리 보기 사진은 원본 그대로 보여주고

업로드는 압축한 이미지를 보내는 것이다.

압축이 오래 걸려도 사용자가 밑에 내용을 채우고 있는 사이 완료된다.

 

다양한 유저가 있기 때문에, 맨 마지막에 이미지를 업로드했다고 가정해 보았을 때

압축이 다 완료되지 않았음에도 제출 버튼을 누르는 경우도 있을 것이다.

이 경우 작성이 완료가 되었을 때 사진 없이 올라가게 된다.

이를 막기 위해 압축이 완료되기 전까지 제출 버튼을 비활성화한다.

그리고 이미지 압축이 완료되면 정상적으로 업로드되었다는 알림을 준다.

 

 

이렇게 사용자가 압축 진행을 모르게 하는 방식으로 해결을 했다.

물론 100% 마음에 들지는 않는다.

이미지 압축을 진행한 후 토스트를 띄워서 알리는 게 맞는가 하는 생각도 들고,

차라리 미리 보기 이미지를 반투명하게 한 후, 압축 완료가 되면 원본으로 보이게 할까 고민도 든다.

계속해서 더 나은 방향이 없는지 고민해 볼 예정이다.

 

그래도 문제가 생겼을 때 꼭 기능적으로만 해결을 해야 한다고 생각했는데

눈속임과 같이 다른 방식으로도 해결을 할 수 있다는 것을 알게 돼 색다르고 재미있었다.

 

또, 이미지 압축 때문에 팀원들끼리 많은 고민을 하고 토론도 했는데

그 과정이 너무나 즐거웠어서 기억에 많이 남을 거 같다.

 

댓글