[Canvas] Tainted canvas 이슈 완벽하게 해결하기
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 헤더를 올바르게 설정하지 않으면 여전히 에러가 발생한다.
서버에서 이 헤더를 추가하려면 :
- 서버 개발자가 직접 추가하거나
- 서버 관리자에게 해당 헤더 설정을 요청해야 한다.
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를 통과하지 못한 경우 발생한다.
해결책:
- crossOrigin="anonymouse"를 설정
- 서버에서 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 검사를 통과하려면 :
- 클라이언트 측에서는 crossOrigin="anonymouse"를 설정
- 서버 측에서는 Access-Control-Allow-Origin 헤더를 올바르게 설정
3. crossOrigin="anonymous"의 의미 :
- 브라우저가 리소스를 로드할 때 인증 정보를 포함하지 않고 서버의 허가 여부를 확인한다. 일반적인 리소스 요청에서 주로 사용됨.
4. 서버와 협력 :
- CORS에러는 서버와 협력하여 적절한 CORS 헤더를 설정하는 것이 가장 확실한 해결 방법이다.
'프론트엔드' 카테고리의 다른 글
[Canvas] 인스타그램 스토리같은 사진/동영상 편집기 만들기 (0) | 2025.03.10 |
---|---|
[Next.js:에러] 가장 무서운 빌드 에러 : Error occurred prerendering... (0) | 2024.12.28 |
[아키텍처] 기존 프로젝트 구조를 모노레포로 바꾸기 (1) | 2024.09.04 |
[Canvas] 이미지 에디터 만들기 6 : 이미지 저장하기 (0) | 2024.08.26 |
[Canvas] 이미지 에디터 만들기 5 : Redo, Undo기능 구현 (0) | 2024.08.26 |