canvas란 무엇인가?
<canvas>는 HTML5에서 도입된 그래픽 요소이다. 브라우저 화면에 픽셀 기반의 그래픽을 그릴 수 있게 만들어진 "캔버스(도화지)"이다. 화가가 캔버스에 그림을 그리듯이, 브라우저 안에서 Javascript 코드로 그림을 그릴 수 있도록 만들어주는 요소이다.
- HTML 코드 안에서 <canvas> 태그를 선언
- JavaScript를 통해 <canvas>에 그리기 컨텍스트(CanvasRenderingContext2D 혹은 WebGL)를 연결
- 선, 도형, 텍스트, 이미지 등을 픽셀 단위로 직접 그리기
<canvas id="myCanvas" width="400" height="300"></canvas>
<script>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
// 빨간 사각형 그리기
ctx.fillStyle = "red";
ctx.fillRect(50, 50, 200, 100);
// 파란 선 그리기
ctx.strokeStyle = "blue";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(250, 150);
ctx.stroke();
</script>
canvas는 왜 사용하는가?
- 자유롭게 2D 또는 3D 그래픽을 표현할 수 있다.
• 게임 그래픽 (예: 2D 게임, 미니맵)
• 데이터 시각화 (차트, 그래프)
• 이미지 편집 도구
• 애니메이션 효과
• 시뮬레이션 (예: 물리 엔진) - 고성능 렌더링 지원
• canvas는 DOM 요소가 아니라 단순한 픽셀 그리드에 그림을 그리는 구조라서, 많은 수의 요소를 그릴 때 DOM보다 효율적이다.
• 빠르게 움직이는 객체(예: 게임 캐릭터)를 자주 업데이트하거나 애니메이션을 할 때, DOM 요소를 많이 추가/제거하는 것보다 canvas에서 직접 그리는 것이 성능상 유리하다. - API 지원의 유연성
• canvas는 JavaScript의 CanvasRenderingContext2D API 또는 WebGL을 통해 2D/3D 그래픽을 제어 가능
• WebGL은 브라우저에서 GPU 가속을 사용해 3D 그래픽을 처리할 수 있어서 복잡한 그래픽, 효과를 구현 가능
이미지의 가로/세율 비율을 유지한 채 이미지 가운데 텍스트를 추가하는 예제
<canvas id="myCanvas" width="500" height="500"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 이미지 객체 생성
const img = new Image();
img.src = 'https://example.com/your-image.jpg'; // 이미지 경로 넣기!
img.onload = function() {
// 캔버스 크기
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
// 이미지 원본 크기
const imgWidth = img.width;
const imgHeight = img.height;
// 이미지 비율 유지 계산
const scale = Math.min(canvasWidth / imgWidth, canvasHeight / imgHeight);
const scaledWidth = imgWidth * scale;
const scaledHeight = imgHeight * scale;
// 중앙 위치 계산
const x = (canvasWidth - scaledWidth) / 2;
const y = (canvasHeight - scaledHeight) / 2;
// 이미지 그리기
ctx.drawImage(img, x, y, scaledWidth, scaledHeight);
// 텍스트 설정
ctx.font = "bold 40px Arial";
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// 중앙에 텍스트 그리기
const textX = canvasWidth / 2;
const textY = canvasHeight / 2;
// 텍스트 외곽선 (가독성)
ctx.strokeText("Fighting!", textX, textY);
ctx.fillText("Fighting!", textX, textY);
};
</script>
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported 오류
이미지를 불러오다보면 Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported 오류가 발생할 때가 있다.
CORS (Cross-Origin Resource Sharing) 정책과 관련된 문제로, canvas에 외부 도메인의 이미지를 그리고 그걸 toDataURL()로 export(저장)하려고 할 때 발생하는 오류다.
브라우저는 보안을 위해 외부 도메인(예: 다른 서버의 이미지)을 canvas에 그린 경우, 그 canvas는 tainted(오염됨) 상태가 되는데 이 상태에서는
- canvas.toDataURL()
- canvas.toBlob()
- getImageData()
같은 메서드로 캔버스 데이터를 추출할 수 없다.
이유는 Cross-Origin 공격 방지 때문인데 만약 허용되면, 해커가 사용자의 다른 사이트의 데이터를 몰래 가져올 수도 있기 때문이다.
해결방법은
img.crossOrigin = "anonymous";
img.src = "https://example.com/image.jpg"; // CORS가 허용된 이미지
crossOrigin을 허용하면 된다. 이 코드의 단점은 자신이 직접 운영하는 서버가 아니면 이 방법을 사용할 수 없다는 점이다. 직접 운영하는 서버의 경우에는 아래의 코드처럼 작성해주면 된다.
img.src = "/images/my-local-image.jpg";
외부 이미지를 프록시 서버로 중계
외부 이미지를 받아오는 백엔드 프록시 서버를 만들고, 그 서버가 이미지를 받아서 브라우저에 CORS 헤더를 포함해 전달하도록 하면 가능하다.
- 브라우저 → 프록시 → 외부 이미지 서버
- 프록시에서 Access-Control-Allow-Origin 헤더 추가
- 브라우저에서 CORS 문제 없이 이미지 로드
'TECH' 카테고리의 다른 글
| SSR / CSR / SSG / ISR 🖥️ (2) | 2025.06.14 |
|---|---|
| Vue / React / Angular 🛜 (6) | 2025.06.13 |
| CSS에서 사용되는 단위들 (0) | 2025.05.28 |
| as const (0) | 2025.05.27 |
| setHTMLUnsafe (2) | 2025.05.26 |