모바일 이미지 자르기 이슈 -2

Imnottired·2023년 5월 21일
0

어제 모바일 이미지에 문제가 있어서 수정하였는데, 초기 값이 문제였었다.
하지만 수정하였음에도 같은 파트에서 문제가 발생하였다. ㅠㅠ


일반 브라우저에서 잘 작동하지만


모바일에서 계속해서 문제가 발생하였다.

현재 이상형 월드컵에서는 2가지가 가능하다.

  1. 검색을 통한 이미지 업로드
  2. 로컬 이미지 가져오기

이 2가지가 가능하다.

그런데 1번과 모바일이 합쳐지면 빈번하게 자르기 오류가 생긴다.

그래서 첫번째 의심한 방법은 파일 유형이었다.

모바일 & 외부 url일 떄 오류 발생하였다.
이후에도 같은 패턴에서 오류가 발생하였다.

이번에는 모바일 & 로컬을 확인해보았다.

모바일 & 로컬은 문제 없이 잘돌아갔다.

로컬(blob)과 외부 url는 파일 유형이 달라서 여기에 문제가 있을 수도 있겠다고 생각했다.

현재 파일을 디버깅해보면,

  function onSelectFile(e: React.ChangeEvent<HTMLInputElement>) {
    if (e.target.files && e.target.files.length > 0) {
      // console.log(e.target.files);
      // setCrop(undefined); //이미지 간 자르기 미리보기를 업데이트합니다
      const reader = new FileReader();
      reader.readAsDataURL(e.target.files[0]);
      reader.addEventListener("load", () => {
        setImgSrc(reader.result?.toString() || "");
      });
    }
  }

로컬은 Base64 인코딩된 이미지 데이터를 넘겨주고,
검색창은 url로 넘겨주었다.
이 둘을 같은 방식으로 넘겨주니 문제가 생겼다고 생각하였다.

  • Encoding : 특정 방식으로 변환하는 것
  • Base64 : 특수문자와 제어 문자를 제외한 64개의 문자로 인코딩 하는것

그래서 고민 끝에 url을 base64로 변경해서 처리하는 방법을 고민하였다.
(사실 캔버스를 디버깅해서 수정하는 방식도 고려해볼 수 있었는데,
순수 디버깅으로 그 값을 조율할 자신이 없었다.)

먼저 A binary file, base64 data, or a URL for an image에 대한 개념이 필요하다.
내용이 어렵고 주제와 맞지 않다고 생각하여서 따로 글을 작성하였다.

이미지 파일 다루는 방법

외부 url -> base64로 수정하기

async function fetchImage(url: string): Promise<string> {
  try {
    const response: Response = await fetch(url);
    const blob: Blob = await response.blob();

    return new Promise<string>((resolve, reject) => {
      const reader: FileReader = new FileReader();

      reader.onloadend = () => resolve(reader.result as string);
      reader.onerror = reject;
      reader.readAsDataURL(blob);
    });
  } catch (error) {
    throw new Error("이미지를 가져오는 동안 오류가 발생했습니다: " + error);
  }
}

Fetch를 통해서 url 불러오면 Blob(binary file) 형태로 치환할 수 있다.

그러면 2진법 데이터라서 이미지 편집이 수월해진다.

하지만 이 프로젝트에서는 naver 크롤링을 사용하였고 네이버에서 막아 놓았기 때문에 실패하였다.
구글 이미지는 가능하지만 횟수 제한이 있다.

그래서 고려한 방법이
외부이미지 url을 image 서버에 올린 후 이를 base64로 변환해 사용하는 것을 통해서 cors오류를 피하고 base64 data or binary file로 변환하고자 하였다.
(next 서버를 이용하여 해결하는 방법도 고려해볼 수 있었지만 불확실했고, 어려워보였다)

  const uploadHandler = async (image: string) => {
    try {
      const response: imgbb_result = await uploadImageToServer(image);

      convertToBase64(response.data.image.url).then((base64) => {
        setImgSrc(base64);
        console.log("짠");
      });
    } catch (error) {
      // 에러 처리를 위한 로직 추가
      console.error(error);
    }
  };

uploadImageToServer를 통해 서버에 올렸고,
이후에 base64로 바꾸어서 올렸다.

하지만 시간이

6초나 걸렸다.
고화질은 8초가 걸리는 것도 있었다.

최적화가 필요해보이지만 현재로서 방법이 보이지 않았다.

그래서 고려해볼 사항들은

  1. 로컬 파일만 권장하기
  2. 로딩 오래걸리는 것을 고려해서 로딩 화면 넣어주기
    를 고려하고 있다.

최적화는 쉽지 않아보인다.
서버리스 함수를 사용하여서 구축 하면 더 빨리 가능할까? 라는 생각도 하여서,
추후에 도전할 것으로 보인다.




마무리

이미지 파일을 다루면서 fetch를 통해 blob 데이터로 바꾸는 것이 가장 신기했다.
그리고 인코딩이니.. Blob이니 base64가 뭔지 몰라서 생소했는데,
이번 기회에 알 수 있었고,
원하는 과정과 결과가 나와서 만족하지만
최적화까지 성공하는 개발자가 되려면 더 노력을 해야겠다.

이미지 다운로드에 대한 시간 단축에 대해 벽을 느꼈고, 어떠한 방식으로 단축해야할지는 무지하기때문에 이것도 해보고 저것도 해보면서 고생해야할 것같다..
화이팅!

profile
새로운 것을 배우는 것보다 정리하는 것이 중요하다.

5개의 댓글

comment-user-thumbnail
2023년 5월 28일

blob은 큰 데이터 다룰 때 진짜 효율적이네요! 최적화는 진짜 어려운 거 같아요.. 기본적인 이해도가 필요하다보니까

답글 달기
comment-user-thumbnail
2023년 5월 28일

끝까지 해결하시는 모습이 멋있습니다!

답글 달기
comment-user-thumbnail
2023년 5월 28일

어우 시도조차 못하겠네요... 갈 길이 멉니다...

답글 달기
comment-user-thumbnail
2023년 5월 28일

여러가지를 시도해서 방법을 찾으시려고 하는 고민이 느껴지네요.. 화이팅입니다!!

답글 달기
comment-user-thumbnail
2023년 5월 28일

저도 이미지업로드 구현하려다 오류때문에 포기했던적이 있어 열심히 읽었네요ㅠㅠ 포기하지말아볼 걸 그랬습니다! 잘 봤어용 고생하셨습니다 :D

답글 달기