[Canvas] Tainted canvas 이슈 완벽하게 해결하기

profile
마릴린벅시
2024. 11. 21. 15:03프론트엔드

 

Tainted Canvas 에러와 CORS: 원인과 해결 방법


canvas에서 작업하다 보면 "Tainted canvases may not be exported"라는 에러를 종종 접할 수 있다.

이 에러를 제대로 이해하고 수정하려면, CORS(교차 출처 리소스 공유)와 관련된 동작 원리를 알아야 한다.

아래에서는 Tainted canvas 에러가 발생하는 이유와 해결 방법, 그리고 관련된 `crossOrigin` 속성과 서버 설정의 관계를 정리해봤다.



Tainted Canvas 에러 발생 상황

에러가 발생하는 맥락
1. canvas데이터를 추출하려 할 때
   예: toDataURL() 메서드를 호출해 canvas 데이터를 이미지로 저장하려는 경우.


2. crossOrigin="anonymous"설정 후
   `crossOrigin` 속성을 설정했더니 로드되던 이미지가 갑자기 CORS 에러로 로드되지 않는 경우.


해결 방법

일반적인 해결책

`canvas`에 이미지를 로드할 때 crossOrigin="anonymous"를 설정하면 문제가 해결될 수 있다.

      const imageObj = new Image();
      imageObj.src = src;
      imageObj.setAttribute("crossOrigin", "anonymous"); // => 이 부분

 

하지만 이 방법은 완벽하지 않다.

서버에서 Access-Control-Allow-Origin 헤더를 올바르게 설정하지 않으면 여전히 에러가 발생한다.

서버에서 이 헤더를 추가하려면 : 

  1. 서버 개발자가 직접 추가하거나
  2. 서버 관리자에게 해당 헤더 설정을 요청해야 한다.

 


 

CORS와 `crossOrigin` 속성

CORS란?


CORS(Cross-Origin Resource Sharing)은 브라우저가 다른 출처의 리소스를 요청할 때, 보안 규칙을 따르게 하는 메커니즘이다.

같은 출처(origin)간 요청 : 허용됨

다른 출처 간 요청 : 서버의 허가 필요

>> 출처가 다르다는 것은 도메인, 프로토콜, 또는 포트가 다른 경우를 의미.


왜 필요한가?

사용자가 네이버의 리소스를 구글의 서버에서 요청해도, 브라우저는 네이버 서버의 허락이 없다면 데이터를 가져올 수 없다. 이는 보안상의 이유 때문이다. (내집에서 내 물건 쓰는 것은 허락이 필요 없지만 남의 집 물건을 쓸 땐 허락이 필요한 것과 같음)

 

서버가 허락을 표현하는 방법

서버는 응답 헤더에 다음과 같은 값을 포함하여 요청을 허용할 수 있다 :

1. 모든 출처를 허용 :

   Access-Control-Allow-Origin: *

 

2. 특정 출처만 허용 :

   Access-Control-Allow-Origin: yourdomain.com

 



crossOrigin="anonymous"의 의미

기본 동작

`crossOrigin` 속성을 설정하지 않으면 :

  • 브라우저는 서버의 Access-Control-Allow-Origin 헤더를 확인하지 않음
  • 대부분의 경우 단순한 리소스 로드에는 crossOrigin 속성을 설정하지 않아도 문제가 없음


`canvas`와 `toDataURL`에서의 차이

하지만 toDataURL()을 호출하여 canvas 데이터를 추출하려면 :

  • CORS를 만족하는 리소스만 사용할 수 있음
  • 그렇지 않으면, 브라우저는 보안을 위해 Tainted canvas에러를 발생시킴

 

anonymous와 use-credentials의 차이

그럼 왜 '익명'이라는 뜻의 anonymous를 사용하는 것일까?

crossOrigin="use-credentials"를 사용해도 CORS검사를 수행한다.

하지만 use-credentials은 CORS검사를 할 때

서버의 Access-Control-Allow-Origin헤더 검사 뿐만 아니라,

요청 측에서 보낸 쿠키나 세션과 같은 추가적인 데이터를 더 받아서 요청한 사용자의 정보라든가, 세션정보 등을 검사한다.

만약 이미지 사용 검사를 더 까다롭게 수행하고 싶다면 use-credentials를 사용해도 된다.

그리고 이 경우 Access-Control-Allow-Credentials: true 헤더를 추가로 붙여줘야 한다.

예를 들어 사용자별로 사용할 수 있는 이미지를 제한하고 싶을 경우에 말이다.

하지만 보통의 경우라면 자원 CORS검사를 할 때 Access-Control-Allow-Origin 헤더만 검사하는 것이 일반적이다.

그리고 Access-Control-Allow-Origin 헤더만 검사할 때는 쿠키, 세션과 같은 '사용자 정보'가 없기 때문에

이를 '익명'이라고 표현하는 것이다.



Tainted Canvas에러 해결 방법

toDataURL() 호출 시

이미지가 CORS를 통과하지 못한 경우 발생한다.

해결책:

  1. crossOrigin="anonymouse"를 설정
  2. 서버에서 Access-Control-Allow-Origin 헤더를 올바르게 설정.

 

crossOrigin="anonymouse" 설정 후 CORS에러

원인 :

  • 단순 이미지 로드는 CORS검사를 통과하지 않아도 되지만, crossOrigin을 설정하면 CORS검사를 수행하게 됨.
  • 서버가 올바른 Access-Control-Allow-Origin 헤더를 반환하지 않으면 로드에서부터 막히게 됨.

해결책:

  • crossOrigin을 제거하거나, 서버에서 Access-Control-Allow-Origin 헤더를 추가.

요약

1. Tainted canvas에러의 발생 원인 :

  • CORS 정책 위반으로 인해 외부 리소스를 canvas에서 안전하게 사용할 수 없기 때문.

2. CORS 검사를 통과하려면 :

  1. 클라이언트 측에서는 crossOrigin="anonymouse"를 설정
  2. 서버 측에서는 Access-Control-Allow-Origin 헤더를 올바르게 설정

3. crossOrigin="anonymous"의 의미 :

  • 브라우저가 리소스를 로드할 때 인증 정보를 포함하지 않고 서버의 허가 여부를 확인한다. 일반적인 리소스 요청에서 주로 사용됨.


4. 서버와 협력 :

  • CORS에러는 서버와 협력하여 적절한 CORS 헤더를 설정하는 것이 가장 확실한 해결 방법이다.


반응형