back

Posts

HEIF형식 이미지 업로드 대응

2023-10-10

어느날...

어느날 heic(heif) 이미지 파일이 업로드가 되지 않는다는 문의가 왔다. heif형식이 무엇인지 찾아보니 고효율 이미지 파일 포맷(High Efficiency Image Format)으로 동일한 크기의 jpeg보다 2배나 더 많은 정보를 저장할 수 있으므로 화질이 더 좋다고 한다.

그러나 2023년 현재에도 아직 호환성이 떨어지며 웹브라우저에서는 지원하지 않고 있다. IOS의 경우에는 heic파일을 업로드할 때 자체적으로 jpg로 변환시켜주므로 큰 문제는 없지만, AOS및 브러우저에서는 직접 jpg로 변환하는 로직을 구성해줘야 heic이미지 업로드가 대응된다.

따라서 heif형식을 jpg로 변경하는 로직을 구성해서 해당 이슈를 해결하기로 결정했다.

heic2any 라이브러리 도입

처음에는 단순히 jpg타입을 지정해서 blob으로 변환 후 다시 파일로 만들면 되지 않을까 싶었지만 확장자만 변경되고 문서유형은 변경되지 않아서 실패했다.

const blob = new Blob([innerFile[1]], {
  type: 'image/jpeg',
});

const heifToPngFile = new File(
  [blob],
  innerFile[1].name
    .replaceAll('.heif', '.jpg')
    .replaceAll('.heic', '.jpg')
    .replaceAll('.HEIC', '.jpg')
    .replaceAll('.HEIF', '.jpg'),
  {
    type: 'image/jpeg',
  },
);

방법을 찾다가 CTO님이 추천해주신 heic2any를 사용하기로 결정했다 구글링 결과, 해당 라이브러리를 사용해서 heif파일을 변환하는 사례가 몇몇 있어서 해당 사례들을 참고해서 로직을 구현했다.

const blob = new Blob([files[0]]);
const transBlob = await heic2any({
  blob,
  quality: 0.1,
  toType: 'image/jpeg',
});
const trnasFile = new File(
  [transBlob],
  files[0].name
    .replaceAll('.heif', '.jpg')
    .replaceAll('.heic', '.jpg')
    .replaceAll('.HEIC', '.jpg')
    .replaceAll('.HEIF', '.jpg'),
  {
    type: 'image/jpeg',
    lastModified: new Date().getTime(),
  },
);

위의 로직을 사용해서 테스트해 보니 잘 작동하여 안심을 했지만.... 뜻밖의 변수가 발생했다.

AOS버전에 따른 차이점

회사에서 안드로이드폰으로 테스트 중, 안드로이드 8 버전에서는 이미지가 업로드 되지 않는 문제가 발견되어 디버깅을 진행하고 문제점을 발견했다.

특정 안드로이드 버전에서는 Heif 형식을 지원하지 않으므로 해당 파일을 업로드할 때, 파일의 타입이 정해지지 않고 비어있는 상태로 업로드되어 서버 측에서 해당 파일 업로드를 하지 않았던 것이다.

안드로이드 공식 홈페이지에 따르면 안드로이드 10버전부터 Heif 형식을 지원해준다고 한다. 안드로이드 공식 홈페이지

따라서 기존 로직에 안드로이드 버전10버전 미만에서는 blob으로 변경후, 타입을 지정해주는 방법으로 문제를 해결했다.

const userAgent = navigator.userAgent.toLowerCase();
const androidIndex = userAgent.indexOf('android');
const androidVer = Number(
  userAgent
    .substring(androidIndex + 8)
    .split(';')[0]
    .split('.')[0],
);

if (androidVer < 10) {
  const blob = new Blob([innerFile[1]], {
    type: 'image/jpeg',
  });

  const heifToPngFile = new File(
    [blob],
    innerFile[1].name
      .replaceAll('.heif', '.jpg')
      .replaceAll('.heic', '.jpg')
      .replaceAll('.HEIC', '.jpg')
      .replaceAll('.HEIF', '.jpg'),
    {
      type: 'image/jpeg',
    },
  );
}

#개선할 점 heic2any라이브러리를 사용해서 문제를 해결할 수 있었지만.... 해당 라이브러리 번들 사이즈를 확인하니 너무 무지막지한 용량을 가지고 있었다.

이러한 사이즈 문제는 깃헙 이슈에도 이미 올라와 있었는데, 개발자의 답변으로는 heif 변환시 사용하는 libheif 라이브러리 용량 자체가 크므로 해결방법이 없다고한다. 깃헙 이슈

결국 라이브러리를 사용하지않거나 다른 라이브러리가 있는지 찾을 필요가 있어보인다.