Skip to main content

Command Palette

Search for a command to run...

[JavaScript] 이미지 사이즈 압축해서 용량 줄이기

Published
2 min readView as Markdown
[JavaScript] 이미지 사이즈 압축해서 용량 줄이기

이미지를 받아서 저장하는 기능을 구현하고 며칠이 지난 후 한 가지 이슈를 발견하였다. 바로 이미지 업로드가 되지 않는 아주 치명적인 문제였다! 분명 테스트도 수 없이 진행하고 배포한 후에도 잘만 동작했는데 갑자기 이런 일이 왜 벌어진걸까?

문제 해결의 원인을 찾기 위해 다양한 방법을 시도하였다:

  1. 갤럭시의 갤러리에 있는 이미지 업로드

  2. 갤럭시의 카메라로 직접 찍어서 업로드

  3. 아이폰의 갤러리에 있는 이미지 업로드

  4. 아이폰의 카메라로 직접 찍어서 업로드

3, 4번에서 문제를 발견하였다. 하지만 모든 아이폰 기종에서 발생한 문제는 아니였기 때문에 기종 간에 어떤 차이가 있는 살펴본 결과,

아이폰 기종이 업그레이드 되면서 카메라 성능이 좋아지고, 그에 따라 카메라로 찍힌 이미지의 용량이 커진 것이다.

서버 측에서 설정한 이미지 용량 제한을 넘어선 이미지가 전달되어 저장에 실패한 것이다.

해결 1

우선 서버 측에서 이미지 용량 제한을 늘려주었다. 이제 아이폰에서 찍힌 이미지의 용량은 거뜬하게 저장할 수 있게 되었다.

그러나 매우 좋은 카메라로 찍은 이미지를 업로드하면 용량 제한이 다시 걸릴 수 있다는 불안감이 아직 남았다.

해결2

프론트엔드에서 이미지 사이즈를 압축해서 서버에 전달하면 어떨까? 아무리 큰 이미지를 받아와도 문제 없을 것이다.

다양한 이미지 압축 라이브러리가 있었는데, 이 중 browser-image-compression를 선정하였다. 해당 라이브러리가 동작하는 방식은 maxSizeMB 를 설정하여 이미지가 maxSizeMB 값보다 작아질 때까지 루프를 돌려 퀄리티를 조금씩 낮추는 것이다. 이러한 동작 방식은 항상 서버에서 제한한 이미지 용량보다 작은 이미지를 저장할 수 있게 하여 내가 원하는 의도에 정확하게 부합하는 기능을 구현한다.

browser-image-compression 사용법

공식문서는 다음과 같다.

const sizeToMB = (size: number) => size / 1024 / 1024;

export const resizeFile = async (file: File) => { // 1
  const MAX_SIZE_MB = 4;
  const options = { // 2
    maxSizeMB: MAX_SIZE_MB,
  };

  if (sizeToMB(file.size) > MAX_SIZE_MB) { // 3
    try {
      const compressedFile = await imageCompression(file, options); // 4
      return compressedFile;
    } catch (error) {
      console.error('Image compression error:', error);
      return file;
    }
  }

  return file;
};
  1. File 타입을 가진 이미지 파일을 받아온다.

  2. maxSizeMB 에 최대 이미지 용량을 MB 단위로 넣는다.

  3. 파일 사이즈를 MB 단위로 변환했을 때 최대 이미지 용량보다 크다면 압축을 진행한다.

  4. 라이브러리에서 제공하는 imageCompression 비동기 함수로 이미지가 최대 이미지 용량보다 작아질 때까지 압축한다.

의도한 대로 압축이 잘 되는지 확인해보았다.

16MB였던 이미지가 3MB로 압축된 걸 확인할 수 있다.

자, 이제 아이폰에서 사진을 찍어서 업로드 해볼까?

이미지 사이즈 압축이 되지 않는다.

이러한 문제가 발생한 이유와 해결방법은 다음 포스트에서💨

More from this blog

시맨틱하게 다이얼로그 만들기

웹에서 양식을 제출하기 위한 다이얼로그를 작성할 때 시맨틱 태그를 무시하고 div 태그를 활용해 css로 스타일링을 하는 경우가 많다. 이렇게 작성할 경우, 동작에는 전혀 무리가 없지만 하지 않아도 될 스타일링 작업을 하는 데 시간을 쏟을 수 있고 웹접근성 측면에도 좋지 않다. 웹에서 다이얼로그는 모달, 대화상자, 알림창, 검사기와 같은 상호작용 가능한 컴포넌트를 말한다. HTML에서는 dialog 라는 태그를 사용하면 핵심적인 다이얼로그의 기...

Jan 13, 20262 min read

[JavaScript] 이미지 수정 시 브라우저 캐싱 방지하기

웹 개발을 하면서 한 번쯤 겪어볼 수 있는 이슈가 있다. A 사용자가 이미지를 업로드하면 B 사용자가 그 이미지를 확인하고, 재업로드를 요청하는 플로우다. A 사용자가 새로운 이미지를 업로드 했는데도 B 사용자는 여전히 처음 이미지를 볼 수 있다. 이 문제는 서버 측에서 "이미지 경로는 그대로 유지하고 이미지를 덮어씌운다"는 구조와 관련이 있다. 브라우저는 URL이 동일하면 캐싱된 이미지를 가져와 네트워크 요청을 줄인다. 따라서 새로운 이미지가...

Oct 3, 20242 min read
[JavaScript] 이미지 수정 시 브라우저 캐싱 방지하기

[React] 렌더링 관점에서 보는 react-hook-form (feat. useRef)

평소 한땀한땀 기능을 만들어나가는 걸 좋아해서 유명한 라이브러리들을 사용해보지 않았는데, 회사에서 프로젝트를 진행하며 다양한 라이브러리를 사용해보았다. 그 중 React-Hook-Form을 사용하며 평소에 리액트로 폼을 작성하며 겪은 불편한 점을 많이 해소했다. 코드 길이, 예외 처리, 렌더링 등 다양한 관점에서 개선할 수 있게 되었다. 오늘은 다양한 폼 상태 관리 방법을 비교하여 React-Hook-Form의 장점을 알아보자. useState...

Sep 5, 20243 min read
[React] 렌더링 관점에서 보는 react-hook-form (feat. useRef)

Untitled Publication

53 posts