Cloudflare - R2 Bucket CORS 에러 해결하기
작성일자 : 2024_년 12월 29일
(이미지)
개요
아래와 같은 JS 코드에서 Cloudflare R2 Bucket에 있는 이미지를 불러오려고 할 때, CORS 에러가 발생하였다.
const createImage = (url: string): Promise<HTMLImageElement> => {
return new Promise((resolve, reject) => {
const image = new Image();
image.addEventListener("load", () => resolve(image));
image.addEventListener("error", error => reject(error));
image.setAttribute("crossOrigin", "anonymous");
image.src = url;
});
};
이미 해당 R2 Bucket의 CORS policy
를 설정해주었음에도 불구하고, 여전히 CORS 에러가 발생하였다.
설정하였던 CORS policy
[
{
"AllowedOrigins": [
"http://localhost:3000"
],
"AllowedMethods": [
"GET"
],
}
]
조사
해당 문제의 특별했던 점은, 크롬 개발자 도구에서 Network
탭을 확인해보면 memory cache
또는 disk cache
에서 이미지를 불러오려고 시도하고 있었다는 것이었다.
이를 보고 아래와 같이 Disable cache
를 체크하고 다시 시도해보았더니, CORS 에러가 발생하지 않았다.
위의 증거를 바탕으로 추가 검색을 진행하였으며, 불과 얼마 전에 올라온 아래와 같은 Stackoverflow 글을 찾을 수 있었다.
Only getting CORs issues when caching is enabled
I'm getting a very odd combination of CORs issues when trying to do a fetch request for an object hosted in R2 (Cloudflare S3 equivalent): If I disable cache in devtools: Then, I have no CORs iss...
stackoverflow.com
Configure CORS · Cloudflare R2 docs
Cross-Origin Resource Sharing (CORS) ↗ is a standardized method that prevents domain X from accessing the resources of domain Y. It does so by using special headers in HTTP responses from domain Y, that allow your browser to verify that domain Y permits
developers.cloudflare.com
해결
위의 글을 바탕으로 JS 코드는 아래와 같이 fetch
+ "Cache-Control": "no-cache"
를 사용하여 이미지를 불러오도록 수정하였다.
const createImage = async (url: string): Promise<HTMLImageElement> => {
const response = await fetch(url, {
cache: "no-store",
headers: {
"Cache-Control": "no-cache",
},
});
const blob = await response.blob();
const objectUrl = URL.createObjectURL(blob);
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
URL.revokeObjectURL(objectUrl);
resolve(image);
};
image.onerror = reject;
image.src = objectUrl;
});
};
또한, CORS policy
는 아래와 같이 설정하였다.
[
{
"AllowedOrigins": [
"http://localhost:3000"
],
"AllowedMethods": [
"GET"
],
"AllowedHeaders": [
"Cache-Control"
]
}
]
교훈
잊지 말자! 디버깅 툴은 언제나 개발자에게 답을 말하고 있으며, 고객은 로그를 통해 우리에게 말을 걸고 있다.