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');
};
코드 설명
-
scalefactor = Math.min(zoom, 1):- zoom이 1 이하일 때만 scalefactor를 적용합니다
- zoom이 1 이상이면 원본 크기를 유지합니다
-
캔버스 크기 조정:
canvas.width와canvas.height를 scalefactor만큼 줄입니다
-
컨텍스트 스케일 조정:
ctx.scale()로 그리기 크기를 조정합니다- 이렇게 하면 이미지가 캔버스 크기에 맞게 그려집니다
정리
iOS에서 Canvas 사용 시 주의사항:
| 문제 | 원인 | 해결 방법 |
|---|---|---|
| toBlob이 null 반환 | 캔버스 크기가 메모리 제한 초과 | 캔버스 크기 줄이기 |
| 이미지 품질 저하 | 해상도를 너무 낮춤 | 적절한 balance 찾기 |
크로스 브라우징은 항상 어렵지만, iOS의 메모리 제한을 이해하고 있으면 비슷한 문제를 더 쉽게 해결할 수 있습니다!