개발 공부/React

220605 [React] 이미지 리사이징 업로드 사이즈 축소 압축 / browser-image-compression

U_D 2022. 6. 5. 22:04

프로젝트를 진행함에 있어 최대 3장까지 이미지 업로드가 가능한 다중 업로드 기능이 있었다.

그러다 보니 고화질의 이미지가 다수 올라가는 경우가 있었는데 이 때 이미지 업로드 속도가 느려지는게 느껴질 정도로

등록하기를 누른 후 유저가 느끼기에 꽤 오랜시간이라고 느껴질 만큼의 시간이 걸렸다.

그래서 유저가 업로드 한 이미지를 축소하는 방법을 검색하였고 라이브러리 중 browser-image-compression가 나와 선택하게 되었다.

 

사이트 이미지 업로드 화면

 

1. 설치

yarn add browser-image-compression
or
npm install browser-image-compression --save

사이트 : https://www.npmjs.com/package/browser-image-compression

 

browser-image-compression

Compress images in the browser. Latest version: 2.0.0, last published: 2 months ago. Start using browser-image-compression in your project by running `npm i browser-image-compression`. There are 79 other projects in the npm registry using browser-image-com

www.npmjs.com

2. 모듈 import

import imageCompression from 'browser-image-compression';

3. 사용법 

사용법은 각자의 상황마다 다양하나 기본적으로 리사이징을 위한 함수를 만들어 줘야 한다.

const handleFileOnChange = async (e) => {
  let file = e.target.files[0];	// 입력받은 file객체
  
  // 이미지 resize 옵션 설정
  const options = { 
  	maxSizeMB: 1, 
  	maxWidthOrHeight: 1920
  }
  
  try {
    const compressedFile = await imageCompression(file, options);
 	//resize된 이미지를 이 이후부터 각자의 상황에 맞게 useState or 전역관리로 저장을 하여 서버로 보내주어야 한다.
   
  } catch (error) {
  	console.log(error);
  }
}

 

나의 경우에는 이미지 업로드가 필수가 아니었고 다중 이미지 업로드이다 보니 경우의 수가 여러가지 존재했다.

이미지가 없을 경우, 1장인 경우, 2장인 경우, 3장인 경우가 있었고 이에 따라 예외처리를 해주었다.

 

if문을 네번 쓰게 되었는데 이것이.. 하드코딩인가 싶은 생각이 들었다.

map을 돌린다면 코드를 더 축소시킬 수 있지 않을까 하는 생각이 드는데 이후에 다시 리펙토링을 해야할거 같다.

const addGroupPost = async () => {
    const options = {
      maxSizeMB: 2,
      maxWidthOrHeight: 1920,
      useWebWorker: true,
    };
    if (thumbnail.length === 0) {
      dispatch(addGroupDB(location, thumbnail, contents, address, distance));
    }

    if (thumbnail.length === 1) {
      try {
        const compressedFile1 = [await imageCompression(thumbnail[0], options)];

        dispatch(
          addGroupDB(location, compressedFile1, contents, address, distance)
        );
        dispatch(imgActions.resetFile());
      } catch (error) {
        // console.log(error);
      }
    }

    if (thumbnail.length === 2) {
      try {
        const compressedFile1 = await imageCompression(thumbnail[0], options);
        const compressedFile2 = await imageCompression(thumbnail[1], options);
        let resizeImage = [];

        resizeImage.push(compressedFile1, compressedFile2);

        dispatch(
          addGroupDB(location, resizeImage, contents, address, distance)
        );
        dispatch(imgActions.resetFile());
      } catch (error) {
        // console.log(error);
      }
    }

    if (thumbnail.length === 3) {
      try {
        const compressedFile1 = await imageCompression(thumbnail[0], options);
        const compressedFile2 = await imageCompression(thumbnail[1], options);
        const compressedFile3 = await imageCompression(thumbnail[2], options);
        let resizeImage = [];

        resizeImage.push(compressedFile1, compressedFile2, compressedFile3);

        dispatch(
          addGroupDB(location, resizeImage, contents, address, distance)
        );
        dispatch(imgActions.resetFile());
      } catch (error) {
        // console.log(error);
      }
    }
  };

4. 결과 

- 업로드 속도 (고화질 5mb 이상 기준) 632ms -> 274ms

- 이미지 사이즈 5mb 이상 → 1mb 이하

- 여기에 추가로 사진이 업로드 되는 동안은 등록하기 버튼을 다시 누르지 못하게 로딩중(업로드중)임을
  유저에게 알려주는게 더 좋을거 같아 추후 적용이 필요해 보인다.