안드로이드에서 사진 촬영 후 이미지 썸네일이 안생겨요 - 웹뷰 트러블 슈팅 기록

date
Dec 8, 2024
slug
android-webview-heic-image-thumbnail-issue
author
status
Public
tags
Android
summary
type
Post
thumbnail
denny-muller-HfWA-Axq6Ek-unsplash.jpg
category
updatedAt
Dec 21, 2024 07:32 PM

문제 상황


안드로이드 앱에서 카메라로 촬영한 이미지 업로드 시 썸네일이 생성되지 않는다는 제보가 있었습니다.
이 문제를 겪은 사용자는 갤럭시 S23(Android 13)을 사용중이었습니다.
 

문제가 발생한 기능 📸

notion image
  1. 이미지 촬영 버튼 클릭
  1. 카메라 촬영
  1. 파일 크기 체크
  1. 이미지 압축
  1. 썸네일 생성
  1. 완료 버튼 클릭 시 이미지 업로드
 
썸네일 이미지가 생성되지 않는 원인은 주황색으로 표시한 이 2단계 중에 원인이 있을것이라 예상하면서 디버깅을 진행했습니다.
 

문제를 파헤쳐보자


1. 디버깅을 위한 준비

Chrome inspect 모드와 안드로이드 스튜디오 디버거를 활용해 디버깅을 진행했습니다.
테스트 기기는 갤럭시 Z플립2(Android14)와 갤럭시 폴드2를 사용했습니다.

2. 디버깅 결과 및 원인 분석

디버깅 결과 이미지 파일 압축이 간헐적으로 실패하여 썸네일 생성 실패까지 이어진다는 점과, 사진 촬영 방식에 따라 결과가 달라진다는 점을 인지할 수 있었습니다. 1. ✅ 일반 촬영: 정상 업로드 2. ❌ 확대 촬영: 썸네일 생성 실패 이미지 압축 과정을 면밀히 분석한 결과, 확대 촬영 시 생성되는 이미지 파일의 특징을 발견했습니다. - 일반적인 JPG/JPEG가 아닌 HEIC 포맷으로 저장 - 파일 크기가 1MB 이하로 압축

🤔 HEIC 포맷이란?

HEIC(High Efficiency Image Format)는 Apple이 개발한 차세대 이미지 압축 포맷으로, 최근 안드로이드 기기에서도 널리 사용되고 있습니다. 특징 1. 뛰어난 압축 효율 - JPEG 대비 50% 작은 용량으로 동일한 화질 구현 - 고해상도 이미지 처리에 최적화 2. 지원 현황 - iOS: 11버전부터 기본 포맷으로 채택 - 안드로이드: 9.0(Pie) 이상부터 지원 - 제조사별 구현 차이 존재
 

디버깅 코드

// 파일 정보 디버깅 const debugFileInfo = (file) => { console.group('📸 촬영된 이미지 정보'); console.log('파일명:', file.name); console.log('타입:', file.type); console.log('크기:', `${(file.size / 1024 / 1024).toFixed(2)}MB`); console.log('확장자:', file.name.split('.').pop()); console.groupEnd(); }; /* 일반 촬영 시: 📸 촬영된 이미지 정보 파일명: IMG_20240315_123456.jpg 타입: image/jpeg 크기: 2.34MB 확장자: jpg 확대 촬영 시: 📸 촬영된 이미지 정보 파일명: IMG_20240315_123456.heic 타입: image/heic 👈 여기가 핵심! 크기: 0.89MB 확장자: heic */
 
부가적으로 궁금했던 점
Q. 파일 크기가 줄어드는 건 화질 저하 때문인가? 확대 촬영하면 화질 저하가 일어나는걸까? A. 아니다. 파일 크기가 줄어드는 건 HEIC 포맷의 우수한 압축 기술 때문이다.
 

웹뷰와 모바일 웹의 차이점

그런데 말입니다. 동일한 기능이 모바일 웹에서는 정상 작동했습니다. 🤔
이는 환경의 차이에서 비롯된다는 점을 유추할 수 있었습니다. 어떤 차이일까요?
 
웹뷰 환경 - 네이티브 카메라 API 직접 사용 - 시스템 설정에 종속 - 이미지 포맷 제어 불가 모바일 웹 환경 - 브라우저의 독립적인 이미지 처리 - 시스템 설정과 독립적 동작 - JPEG 포맷 유지
 

썸네일 생성에 실패하게 만드는 근본적인 원인

핵심적인 문제는 우리 서비스에서 사용 중인 browser-image-compression 라이브러리였습니다.
이 라이브러리는 HEIC 포맷을 지원하지 않아 이미지 처리에 실패하고 있었습니다.
 

해결 방안


1. heic2any 라이브러리 도입

HEIC 파일을 JPEG로 변환하기 위해 heic2any 라이브러리를 도입했습니다.
// HEIC → JPEG 변환 로직 const convertHeicToJpeg = async (file: File): Promise<File> => { if (file.type === 'image/heic') { const blob = await heic2any({ blob: file, toType: 'image/jpeg', quality: 0.8 }); return new File([blob], file.name.replace('.heic', '.jpeg'), { type: 'image/jpeg' }); } return file; };
 

2. 사용자에게 안내사항 전달

HEIC 포맷으로 인한 문제를 완전히 피하고 싶은 사용자들을 위해 카메라 설정 변경 방법도 안내했습니다.
  • 카메라 앱 설정 열기
  • '고급 사진 옵션' 메뉴로 이동
  • '고효율 사진' 옵션을 찾아 비활성화
이렇게 설정하면 모든 사진이 기본적으로 JPEG 포맷으로 저장됩니다.
 

맺음말


이번 HEIC 이슈 해결을 통해 중요한 교훈을 얻었습니다. 특히 "it works on my machine"이라는 관점에서 벗어나는 것의 중요성과 다음 세 가지를 잘 챙겨야 한다는 점을 재차 인지했습니다.
 
철저한 호환성 테스트
  • 단순히 "내 환경"에서 테스트하는 것을 넘어서야 한다
    • 다양한 안드로이드/IOS 버전, 제조사별 기기 테스트가 필수
  • 특히 최신 기기의 새로운 기능들 주시하자
 
다양한 사용자 환경에 대한 이해
  • 각기 다른 설정과 사용 패턴 고려
  • '확대 촬영'처럼 특정 상황에서 발생하는 문제도 놓치지 않기
  • 예상치 못한 사용 케이스 발굴
 
대체 솔루션 준비
  • 문제가 발생했을 때 "안 됩니다"가 아닌 "이렇게 하면 됩니다” 가 되도록 하자
  • 사용자가 선택할 수 있는 옵션을 빠르게 제공하자
 
이러한 노력들이 모여 더 견고한 서비스가 만들어집니다. 새로운 기술은 계속해서 등장하겠지만, 이런 기본기를 잘 챙긴다면 어떤 변화가 와도 잘 대응할 수 있을 것이라고 생각합니다. 결국 좋은 서비스는 기술적 완성도와 함께, 사용자를 깊이 이해하고 배려하는 마음에서 시작된다는 걸 다시 한 번 배웠습니다. 🚀