toDataURL에서 발생하는 보안 예외란?
웹 개발 중 캔버스(canvas)에 외부 도메인의 이미지를 그린 뒤 toDataURL() 메서드를 호출하면, 브라우저가 Uncaught SecurityException 오류를 던지는 경우가 있습니다. 이는 동일 출처 정책(Same-Origin Policy) 때문에 발생하는 현상입니다. 다른 출처의 이미지를 캔버스에 그리면 해당 캔버스가 '오염(tainted)' 상태가 되어, 픽셀 데이터를 읽거나 Data URL로 변환하는 작업이 보안상 차단됩니다.
해결 방법: crossorigin 속성 추가
이 문제를 해결하려면 이미지 요소에 crossorigin="anonymous" 속성을 추가하여 교차 출처 리소스를 CORS 방식으로 불러와야 합니다.
<img id="myid" crossorigin="anonymous" src="https://www.tutorialspoint.com/images/seaborn-4.jpg?v=2">
function getBase64() {
var myImg = document.getElementById("myid");
var c = document.createElement("canvas");
c.width = myImg.width;
c.height = myImg.height;
var context = c.getContext("2d");
context.drawImage(myImg, 0, 0);
var dataURL = c.toDataURL("image/png");
alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
}
getBase64();
주의 사항
crossorigin="anonymous" 속성만으로는 충분하지 않습니다. 이미지를 호스팅하는 서버 역시 CORS 헤더(Access-Control-Allow-Origin)를 올바르게 반환해야 합니다. 서버가 이 헤더를 제공하지 않으면 이미지 로딩 자체가 실패하게 됩니다.
또한 이미지가 완전히 로드되기 전에 캔버스 작업을 실행하면 빈 화면이 그려질 수 있으므로, 실제 코드에서는 window.onload 이벤트나 이미지의 load 이벤트를 활용해 로딩 완료 후 함수를 호출하는 것이 안전합니다.