본문 바로가기
TECH

canvas

by Stella-Park 2025. 5. 31.
728x90

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는 왜 사용하는가?

  1. 자유롭게 2D 또는 3D 그래픽을 표현할 수 있다.
    • 게임 그래픽 (예: 2D 게임, 미니맵)
     데이터 시각화 (차트, 그래프)
     이미지 편집 도구
     애니메이션 효과
     시뮬레이션 (예: 물리 엔진)
  2. 고성능 렌더링 지원
    canvas는 DOM 요소가 아니라 단순한 픽셀 그리드에 그림을 그리는 구조라서, 많은 수의 요소를 그릴 때 DOM보다 효율적이다.
     빠르게 움직이는 객체(예: 게임 캐릭터)를 자주 업데이트하거나 애니메이션을 할 때, DOM 요소를 많이 추가/제거하는 것보다      canvas에서 직접 그리는 것이 성능상 유리하다.
  3. 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 헤더를 포함해 전달하도록 하면 가능하다.

  1. 브라우저 → 프록시 → 외부 이미지 서버
  2. 프록시에서 Access-Control-Allow-Origin 헤더 추가
  3. 브라우저에서 CORS 문제 없이 이미지 로드
728x90

'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