back

Posts

canvas.toBlob이 IOS에서 null을 반환 받는 경우

2024-11-12

회사에서 react-easy-crop 라이브러리와 Canvas API를 사용하다가, iOS에서만 특정 상황에서 canvas.toBlob이 null을 반환하는 현상을 발견했습니다.

1. 문제 발견

증상:

  • iOS에서만 zoom이 1 이하인 경우 canvas.toBlob이 null을 반환합니다
  • 안드로이드와 데스크톱 브라우저에서는 정상 작동합니다

2. 원인 분석

GPT에게 물어보니 다음과 같은 답변을 받았습니다:

GPT 답변 iOS에서 매우 높은 해상도나 대형 캔버스를 사용할 경우 메모리 제한으로 인해 빈 이미지를 생성할 수 있습니다. 이를 해결하려면 캔버스 크기를 줄이거나, 이미지 해상도를 낮추어 메모리 사용량을 줄이는 것이 좋습니다.

실제로 캔버스 크기를 확인해보니, zoom이 1 이하일 때 캔버스 크기가 무지막지하게 커져 있었습니다.

iOS의 메모리 제한

iOS는 웹 브라우저의 메모리 사용을 엄격하게 제한합니다. Canvas가 일정 크기를 초과하면:

  • toBlob() 메서드가 null을 반환합니다
  • 이미지 생성에 실패합니다

3. 해결 방법

해결법은 간단합니다. 이미지 해상도를 낮추거나 캔버스 크기를 줄이면 됩니다.

우리 서비스는 이미지 해상도가 중요하므로, 캔버스 크기를 zoom만큼 줄이는 방법으로 수정했습니다.

const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
newImage.src = imagePath;
newImage.onload = () => {
  const scalefactor = Math.min(zoom, 1);

  canvas.width = width * scalefactor;
  canvas.height = height * scalefactor;

  ctx.scale(scalefactor, scalefactor);
  ctx.drawImage(newImage, 0, 0);

  canvas.toBlob((blob) => {
    ...로직
  }, 'image/png');
};

코드 설명

  1. scalefactor = Math.min(zoom, 1):

    • zoom이 1 이하일 때만 scalefactor를 적용합니다
    • zoom이 1 이상이면 원본 크기를 유지합니다
  2. 캔버스 크기 조정:

    • canvas.widthcanvas.height를 scalefactor만큼 줄입니다
  3. 컨텍스트 스케일 조정:

    • ctx.scale()로 그리기 크기를 조정합니다
    • 이렇게 하면 이미지가 캔버스 크기에 맞게 그려집니다

정리

iOS에서 Canvas 사용 시 주의사항:

문제원인해결 방법
toBlob이 null 반환캔버스 크기가 메모리 제한 초과캔버스 크기 줄이기
이미지 품질 저하해상도를 너무 낮춤적절한 balance 찾기

크로스 브라우징은 항상 어렵지만, iOS의 메모리 제한을 이해하고 있으면 비슷한 문제를 더 쉽게 해결할 수 있습니다!