cloudflare 서비스를 사용해 웹개발 시 사용할 이미지를 업로드하고 사용하는 방법을 포스팅
사전준비
우선 cloudflare에 회원가입을하고 대시보드로 들어간 후 메뉴에서 Image를 누른다.
현시점 기준으로 무료 플랜을 선택하고 한 달에 5$를 지불하는 형식으로 선택하면 테스트용으로 충분한 사용량을 제공해 준다.
이미지 업로드 플로우 (Next Js, App router 기준)
- input으로 이미지 받아서 파일형식, 크기 등 체크
- (server action) cloudflare로 이미지 업로드 url, image id 요청
- 해당 Form 제출 시 업로드 url로 이미지 업로드
- 업로드 성공 후 Delivery URL + image id를 DB에 저장
1~2 해당 코드
"use client"
// file 업로드용 Input onChange
const onImageChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const {
target: { files },
} = event;
if (!files) {
return;
}
const file = files[0];
// Check if the file is an image
const validImageTypes = [
"image/jpeg",
"image/png",
"image/gif",
"image/bmp",
];
if (!validImageTypes.includes(file.type)) {
alert("이미지 파일이 아닙니다.");
return;
}
// Check if the file size is less than 3MB
const maxSizeInMB = 3;
if (file.size > maxSizeInMB * 1024 * 1024) {
alert("3MB 이하의 이미지를 사용해주세요.");
return;
}
// 업로드 Url, image id 요청
const { success, result } = await getUploadUrl();
if (success) {
const { id, uploadURL } = result;
setUploadUrl(uploadURL);
// form의 photo 값에 delivery url set
setValue(
"photo",
`https://imagedelivery.net/S5EmZfh9mNC3-3xmENYiiA/${id}`
);
} else {
alert("이미지 업로드에 실패했습니다");
return;
}
// 브라우저에 올라간 이미지 메모리 주소URL
const url = URL.createObjectURL(file);
setPreview(url);
setFile(file);
}
"use server"
// 서버에서 업로드 Url, 이미지 id 받아오기
export async function getUploadUrl() {
const response = await fetch(
`
https://api.cloudflare.com/client/v4
/accounts/${process.env.CLOUDFLARE_ACCOUNT_ID}/images/v2/direct_upload`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDFLARE_TOKEN}`,
},
}
);
const data = await response.json();
return data;
}
3. 이미지 업로드
"use client"
const onSubmit = handleSubmit(async (data: ProductType) => {
...
const cloudflareForm = new FormData();
cloudflareForm.append("file", file); // 이미지 파일 append
// 이미지 업로드
const response = await fetch(uploadUrl, {
method: "POST",
body: cloudflareForm,
});
if (response.status !== 200) {
alert("게시물 생성에 실패했습니다.");
return;
}
...
});
업로드된 이미지 URL DB 저장
"use server"
// Form Data DB 업데이트
export async function uploadProduct(formData: FormData) {
const data = {
photo: formData.get("photo"),
title: formData.get("title"),
...
};
// zod로 validation
const result = productSchema.safeParse(data);
if (!result.success) {
return result.error.flatten();
} else {
const session = await getSession(); // 로그인 여부
if (session.id) {
// 새로운 product를 db에 생성
const product = await db.product.create({
data: {
title: result.data.title,
photo: result.data.photo,
...,
},
select: {
id: true,
},
});
redirect(`/products/${product.id}`);
}
}
}
이미지를 직접 업로드하는 게 아니라 업로드 URL을 받아서 처리하는 이유
Cloudflare에서 이미지 업로드 시 업로드 URL을 따로 요청하는 방식은 보통 보안과 효율성을 위한 것이다.
- 보안 강화
- 서버의 직접 노출 방지: 클라이언트가 Cloudflare의 서버에 직접 업로드하지 않고, 미리 발급된 서명된 URL을 사용하여 이미지를 업로드한다. 이 방식은 클라이언트가 서버의 실제 업로드 경로를 알 수 없게 하여, 서버를 직접 공격하는 가능성을 줄인다.
- 업로드 제한: 이 URL은 제한된 시간 동안만 유효하거나, 특정 조건 하에서만 사용할 수 있다. 이를 통해 업로드 권한이 불필요하게 확산되는 것을 방지하고, 악의적인 업로드를 막을 수 있다.
- 사전 검증 및 요청 제어
- 업로드 전에 서버에서 요청을 검증할 수 있는 기회를 제공한다. 예를 들어, 사용자가 업로드 권한이 있는지, 이미지 크기가 적절한지 등을 확인하고, 검증이 완료된 후에야 업로드 URL을 발급하게 된다.
- 업로드 트래픽 분산
- 직접 업로드가 아닌 Cloudflare를 통해 이미지가 업로드되므로, 트래픽이 분산되어 서버의 부하를 줄일 수 있다. 클라이언트가 여러 파일을 업로드할 때, 서버는 URL을 발급하는 것만 담당하고, 실제 업로드는 Cloudflare의 전용 네트워크에서 처리된다.
- 유연성
- 이 방식은 REST API와 같은 방식으로 작동하므로 다양한 클라이언트(웹, 모바일 앱 등)에서 일관된 방식으로 이미지를 업로드할 수 있다. 클라이언트가 이미지를 직접 Cloudflare에 전송하는 대신, 발급된 URL을 사용하여 업로드를 처리하게 된다.
이미지 Variants 기능

Cloudflare 이미지 서비스의 Variants 기능은 이미지 최적화를 위한 중요한 도구이다. 이 기능을 통해 원본 이미지를 다양한 크기, 형식, 품질로 변환하여 사용자에게 제공할 수 있다. 주로 웹 성능을 개선하고, 네트워크 대역폭을 절약하며, 사용자 경험을 최적화하는 데 사용된다.
- 다양한 이미지 크기 제공
- 원본 이미지를 업로드한 후, Variants를 사용하여 다양한 크기의 이미지를 정의할 수 있다. 이를 통해 동일한 이미지를 여러 크기로 제공하여, 모바일, 태블릿, 데스크탑 등의 각기 다른 디바이스에 맞는 적절한 크기의 이미지를 사용할 수 있다.
- 이미지 형식 변환
- Variants를 이용하면 원본 이미지를 자동으로 다른 포맷(예: WebP, JPEG)으로 변환하여 제공할 수 있다. WebP 같은 형식은 JPEG나 PNG보다 더 작은 용량을 제공할 수 있어 성능을 크게 향상시킨다.
- 이미지 품질 제어
- Variants는 이미지의 품질도 조정할 수 있다. 예를 들어, 고화질 이미지를 필요로 하지 않는 경우 품질을 낮춰 네트워크 비용과 로딩 시간을 줄일 수 있다.
- 응답형 이미지
- 다양한 디바이스에 맞춘 이미지 사이즈를 제공하므로, 화면 크기에 맞는 최적화된 이미지를 제공하여 사용자 경험을 향상시킬 수 있다. 이를 통해 페이지 로딩 시간을 줄이고, 모바일 데이터 사용량도 절약할 수 있다.
- 손쉬운 URL 기반 액세스
- 각 Variant는 고유한 URL을 가지며, 이 URL을 통해 변환된 이미지를 쉽게 요청할 수 있다. 이를 통해 개발자는 복잡한 서버 측 이미지 변환 작업 없이 다양한 이미지 변형을 제공할 수 있다. (Delivery URL + Image Id + Variant)
https://imagedelivery.net/S8EmZfz3mNC1-4xmENYiiA/<image_id>/<variant_name>'WebCommon' 카테고리의 다른 글
| Access Token과 Refresh Token을 활용한 세션 관리 (0) | 2025.12.08 |
|---|---|
| GET, POST 뭐가 더 안전한 요청일까? (0) | 2025.12.05 |
| CSP 'upgrade-insecure-requests' 이슈 (1) | 2024.07.05 |
| 로컬스토리지, 세션스토리지, 세션, 쿠키의 이해 (2) | 2024.02.15 |
| Base64, Blob, ArrayBuffer, File 이해하기 (3) | 2024.01.22 |