본문 바로가기
이론/Frontend

Canvas API 사용해보기

by 유세지 2022. 12. 9.

 

이번에 사이드 프로젝트를 다시 설계하는 작업을 진행하며 처음으로 Canvas API를 직접 사용하게 되었습니다. 이전에는 라이브러리를 통해 Canvas를 간접적으로 다루어 잘 몰랐었는데, 참 특이하면서도 재미있는 API라는 생각이 들었습니다. 이번 포스트에서는 Canvas API의 기본적인 사용법부터 사용하면서 직접 겪었던 문제들까지 함께 공유해보도록 하겠습니다.

 

Canvas API

Canvas API는 주로 2D 그래픽 요소를 그리기 위해 사용됩니다. 간단한 도형 뿐 아니라 이미지를 추가하거나 편집하는 용도로도 많이 사용되며, jpg, png, base64 등 다양한 형식으로 출력이 가능합니다. 예시로 이렇게 사용할 수 있습니다.

 

HTML

<canvas id="canvas"></canvas>

 

Javascript

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

// 녹색 사각형 그리기
context.fillStyle = 'green';
context.fillRect(0, 0, 100, 100);

// 텍스트 쓰기
context.font = 'bold 36px NanumBarunGothic';
context.fillText('usageness', 100, 100);

// 내보내기, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby...
canvas.toDataURL('image/png');

 

 

저는 리액트 환경에서 사용했기 때문에, 아래처럼 useRef와 함께 사용해주었습니다.

 

function CanvasComponent() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const canvas = canvasRef.current;
  
  if (!canvas) return;
  
  // ...
  
  return (
    <div>
      <canvas ref={canvasRef} />
    </div>
  )
}

 

 

사실 Canvas API는 MDN 문서에 상당히 자세하게 설명되어있고, 한국어로 된 튜토리얼도 제공하고 있기 때문에 전혀 모르는 상태에서도 익히는데 그리 오랜 시간이 걸리진 않았습니다. 그럼에도 항상 문제는 발생합니다.

 


CORS 문제

Canvas API를 설명하다가 갑작스럽게 "CORS 문제" 라는 제목이 튀어나와 다소 이상하게 느끼실 수도 있을 것 같습니다. 그러나 Canvas를 이용해 외부 이미지를 편집한다면, 그 순간부터 CORS 문제에서 자유로울 수 없습니다.

 

먼저 아래처럼 사용하면 Canvas에 외부 이미지를 그릴 수 있습니다.

 

const img = new Image();
img.src = 'https://externalURL.com/image.png';

// 비동기 처리 코드는 생략하였습니다.

context.drawImage(img, 0, 0, canvas.width, canvas.height);

 

그러나, 이렇게 가져온 이미지를 파일로 내보내려고 시도하면 아래와 같이 오류가 발생합니다.

 

 

외부 리소스 측에서 모든 도메인에 대한 접근을 허용해준게 아니라면 위 사진처럼 CORS 정책에 의한 차단이 발생하며 이미지를 제대로 그릴 수 없게 됩니다.

 

인터넷에는 악의적인 사용자가 공격을 목적으로 특정한 스크립트를 넣은 소스를 무분별하게 배포 할 수 있기 때문에 알 수 없는 출처에 대한 접근을 차단하는 것이 보안상으로 적절하고, 이는 반대로 서버가 클라이언트의 요청을 받는 경우에도 마찬가지 입니다. CORS 정책은 이러한 보안 문제를 방지하기 위해 서버가 허용하지 않은 오리진으로부터 온 요청이라면 브라우저에서 요청 자체를 차단합니다.

 

그러나 toDataURL() 메서드를 통해 데이터나 파일로 따로 내보내지 않고, canvas에 단순히 이미지를 표시만 하는 경우에는 또 괜찮습니다.

 

허용되지 않은 출처의 이미지를 정상적으로 표시하는 모습

 

허용된 출처의 소스가 아니더라도, 예외적으로 허용하는 케이스가 몇 가지 있는데 그 중 하나가 <img /> 태그에 이미지를 표시하기만 하는 경우입니다. 만일 서로 다른 오리진에서 모든 소스들이 각자가 허용된 출처들을 일일히 검증하고 그 결과에 따라 소스를 표시했다고 생각해봅시다. 그렇다면 지금처럼 수 많은 곳에서 거미줄처럼 서로가 얽혀있는 인터넷을 사용하기는 어렵겠죠. 이에 대해서는 CORS 포스팅에서 자세히 다루어보겠습니다.

 

다시 본론으로 돌아와서, 결론적으로 단순히 캔버스에 소스를 표시하기만 하는 경우에는 브라우저가 요청을 차단하지 않습니다. 다만 이 소스를 밖으로 끄집어내려는 시도를 하게되면 CORS 정책에 의해 허용된 오리진에서 요청을 보낸 경우에만 제대로 동작하게 됩니다. 그렇지 않으면 오류를 던지게 되고, 이런 경우를 오염된(Tainted) 캔버스라고 부릅니다.

 

그렇다면 이러한 출처에 신경쓰지 않고 이미지 소스를 불러와 사용하려면 어떻게 하면 될까요?

 

 

마무리

이에 대한 방법은 몇 가지가 있겠지만, 이후에 이어질 썸네일 생성기를 리뉴얼했어요 포스팅에서 이어갈 예정입니다. 다음 포스팅에서 확인해주시면 감사하겠습니다!

 

참고 문서

Allowing cross-origin use of images and canvas - MDN Docs

캔버스(Canvas) 기본 사용법 - MDN Docs

 

반응형

'이론 > Frontend' 카테고리의 다른 글

Web과 Ajax에 대하여  (1) 2022.12.30
리액트에서 기본 컴포넌트를 만들때  (1) 2022.12.22
Context API 개념 잡기  (0) 2022.11.22
Recoil + React-query 삽질기  (6) 2022.10.28
자바스크립트의 index.js  (4) 2022.08.23

댓글