[ React ] 이미지 리사이징 (react-file-image-resizer)

exceed_96·2024년 2월 26일
1

React

목록 보기
8/18
post-thumbnail

저번 프로젝트에서 유저의 이미지를 업로드 하기 위해 유저로부터 이미지 업로드 받고 해당 이미지를 리사이징하여 컴포넌트에 렌더링, 서버에 전송하였던 과정을 회고하기 위한 포스팅이다.



1. 이미지 리사이징이 필요한 이유

서버부담과 db의 용량이 아주 넉넉하다는 전제가 깔려있다면 이미지 리사이징은 필수적인 과정이 아니다.

하지만 자원은 한정적이고 주어진 자원을 효율적으로 쓰기 위해서는 줄일 수 있는 부분에서는 줄이는게 좋다.

그래서 이미지를 업로드 한 그대로 사용하지 않고 리사이징을 통해서 이미지의 크기를 줄여 서버의 부담과 db용량에 대한 부담을 줄이는게 통상적인 과정이다.

따라서 이번 프로젝트에서는 고화질을 이미지를 사용하는 프로젝트도 아니고 단지 사용자의 프로필 이미지를 렌더링 하기 위해서 이미지를 사용하기 때문에 리사이징을 통해서 서버, db 부담을 줄이기로 결정했다.



2. react-image-file-resizer

react-image-file-resizer는 이미지 리사이징과 인코딩을 위해 사용하는 라이브러리이다.

base64혹은 blob으로 변환 가능하다.


base64

base64는 이진데이터를 문자열 기반의 텍스트로 저장하는 인코딩 방식이다.

알파벳 대 소문자, 숫자, +, / 기호로 이루어져 있다.

다만 base64는 문자열이 매우 길어서 가독성이 떨어진다.

또한 base64로 인코딩 시 사이즈가 원본에 33%정도로 커져서 로딩 속도가 저하될 수 있다.

서버에서 받아오는 이미지의 개수가 적은 개수 면 그 차이는 심하지 않겠지만 이미지의 개수가 많아지면 많아질수록 로딩 속도가 심각하게 저하된다.

위와같이 base64로 이미지를 인코딩 하면 data:image/파일형식;base64으로 시작하는 형태를 보인다.


blob

blobBinary Large Object의 약자로 이진 데이터를 나타내는데 사용된다.

base64의 텍스트 형태로 저장한 포맷과는 다르게 객체(object)에 저장한다.

또한 브라우저 메모리에 저장하여 사용안할시에는 꼭 메모리에서 해제해줘야 한다.

위와같이 blob로 이미지를 인코딩 하면 blob:으로 시작하는 형태를 보인다.



3. react-image-file-resizer 사용법

1. 이미지 리사이징을 할 컴포넌트에서 해당 라이브러리를 import해준다.

import Resizer from "react-image-file-resizer";

2. input요소를 이용하여 이미지 파일을 받을 요소를 정의해준다.

<input
    type="file"
    id="profileImage"
    className={styles.inputImage}
    accept="image/*"
    onChange={onImageHandler}
/>

type="file"

input요소를 "file"타입으로 정의하여서 로컬에 있는 데이터를 업로드 할 수 있게 한다.

accept="image/*"

이미지 파일만 업로드 가능하게 한다.

onChange={onImageHandler}

onChange이벤트 핸들러를 이용하여 업로드 한 이미지를 후 처리 할 함수를 지정한다.


3. 업로드한 이미지를 리사이징 및 후 처리할 함수를 만들어준다.

onImageHandler

const onImageHandler = async (e) => {
    const file = await e.target.files[0];                                  //사용자가 업로드한 이미지를 비동기적으로 가져온다.
    console.log("imgae incoding before : ", file);
    const suppertedFormats = ["image/jpeg", "image/png", "image/svg+xml"]; //허용한 이미지 형식 정의
    if (!e.target.files[0]) {                                              //만약 업로드한 이미지가 존재하지 않는다면 함수를 종료
      return;
    }
    if (!suppertedFormats.includes(file.type)) {                           //업로드한 이미지가 정의된 형식에 맞지 않는다면 경고창 띄우기
      alert(
        "지원되지 않은 이미지 형식입니다. JPEG, PNG형식의 이미지를 업로드해주세요."
      );
      return;
    }
    try {
      const compressedFile = await resizeFile(e.target.files[0]);          //"resizeFile"함수를 통해서 업로드한 이미지 리사이징 및 인코딩
	  console.log("imgae incoding after : ", compressedFile);
      setImagePreview(String(compressedFile));                             //인코딩한 이미지를 브라우저에 프리뷰 하기 위해 state 정의
      setUploadImage(String(compressedFile));                              //인코딩한 이미지를 서버에 전송하기 위한 state 정의
    } catch (error) {                                                      //리사이징에 실패했을시 console에 출력하게 한다.
      console.log("file resizing failed");
    }
  };

resizeFile

const resizeFile = (file) =>
    new Promise((resolve) => {                     //비동기 작업을 위해서 "Promise"를 통한 비동기 작업 정의
      Resizer.imageFileResizer(                    //Resizer의 "imageFileResize"메서드를 통해서 이미지 리사이징 및 인코딩 옵션 정의
        file,                                      
        200                                        //이미지 너비
        200                                        //이미지 높이
        "SVG"                                      //파일 형식
        100                                        //이미지 퀄리티(100으로 해도 이미지 리사이징시 상당히 깨지긴 한다)
        0 /* rotation */,
        (uri) => {
          /* resize new image with url*/
          resolve(uri);
        },
        "base64" /* output Type */                 //"blob"으로 정의할 수 있다.
      );
    });

위와같이 인코딩 전에는 파일객체로 업로드된 이미지 파일이 인코딩 후에는 base64로 변경된걸 확인할 수 있다.

인코딩 된 이미지가 클라이언트에 렌더링과 백엔드로 이미지 전송도 문제없이 되는걸 확인할 수 있다.



4. 마치며

이미지 리사이징은 아마도 이미지를 다루는 기능이 프로젝트 내에 존재한다면 필수적으로 알아야 하는 개념이 아닐까 생각 든다.

다만 이번 프로젝트에서는 blob으로 인코딩한게 아닌 base64로 인코딩 하였는데 다음 프로젝트에서 이미지 처리 프로세스가 필요하면 blob으로도 한번 진행해 보고 싶다.

다만 브라우저의 메모리에서 직접 다 해제해줘야 한다는게 흠이긴 하지만 더 적은용량으로 이미지를 처리할 수 있다는 점이 큰 장점이 아니였을까 생각한다.



5. Reference

https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-Base64-Blob-ArrayBuffer-File-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EC%A0%95%EB%A7%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%84%A4%EB%AA%85

profile
개발진행형

0개의 댓글

관련 채용 정보