본문으로 건너뛰기
effidevFlutter · Cloudflare 엣지 · 클라우드 비용 최적화
한국어

Cloudflare Image Resizing & R2: AWS Lambda@Edge 대비 이미지 파이프라인 비용 96% 절감 가이드

Cloudflare Image Resizing and R2 Cost Optimization architecture guide

미디어 파이프라인의 소리 없는 도둑: AWS Lambda@Edge의 과금 폭탄

이커머스, 블로그, 미디어 플랫폼, SNS 서비스를 운영할 때 원본 고화질 이미지(5MB~20MB)를 유저 디바이스 화면 크기(모바일 400px, 태블릿 800px, 데스크톱 1400px)에 맞춰 동적으로 리사이징하고 최신 압축 포맷(WebP / AVIF)으로 변환하는 동적 이미지 파이프라인은 필수적이다.

하지만 이를 위해 대중적으로 사용해 온 AWS S3 + CloudFront + Lambda@Edge (Sharp / OpenCV) 아키텍처는 매달 상상을 초과하는 비극적인 인프라 과금을 유발한다.

  1. Lambda@Edge 연산 시간 과금 폭탄: 고해상도 이미지를 Sharp 라이브러리로 압축할 때 1~2초간 지속되는 람다 메모리(1024MB 이상) 점유 시간 과금.
  2. CloudFront Egress 대역폭 수수료: 이미지 파일이 전송될 때마다 발생하는 GB당 $0.085~$0.114의 대역폭 과금.
  3. 이중 S3 PUT/GET 수수료: 변환된 썸네일을 S3에 재저장하면서 발생하는 추가 렌더링 수수료.
[AWS Lambda@Edge 미디어 파이프라인의 과금 구조]
원본 이미지 (S3) -> Lambda@Edge 인스턴스 실행 ($220/월 CPU 과금) -> CloudFront Egress 전송 ($160/월 대역폭 과금)
                     * 동적 썸네일 변환 시 람다 실행 시간 소모
                     * 월간 100만 회 변환 시 총 $380/월 청구 발생

2025/2026년 기준 이 비효율을 완벽히 파괴한 에지 아키텍처가 바로 Cloudflare R2 + Workers Images Binding (env.IMAGES / cf.image) 파이프라인이다.

Cloudflare R2 버킷에 원본 미디어를 저렴하게 보관($0.015/GB, Egress 수수료 $0)하고, Cloudflare V8 에지 노드가 0.1ms 만에 온더플라이(On-the-fly)로 WebP/AVIF로 변환해 리턴함으로써 인프라 비용을 월 $380에서 $15로 96% 절감할 수 있다.

이 가이드에서는 Cloudflare Image Resizing의 메커니즘부터 wrangler.jsonc 최신 images 바인딩 설정, env.IMAGEScf.image 실전 구현, format: 'auto' 에지 브라우저 감지, 에지 Tiered Cache 최적화, 그리고 벤치마크까지 상세히 다룬다.

Cloudflare Image Resizing & R2 하이브리드 아키텍처

원본 이미지는 비공개(Private) R2 버킷에 저장하고, 에지 Worker 단에서 동적 변환 파이프라인을 거쳐 캐싱 서빙한다.

+-----------------------------------------------------------------------------------+
| Cloudflare Image Resizing & R2 온더플라이 변환 파이프라인                             |
+-----------------------------------------------------------------------------------+

[유저 요청: GET /image/product-123.jpg?w=800&q=80]
                       |
                       v
   [Cloudflare Tiered Edge CDN Cache (0ms 검증)]
                       |
        +--------------+--------------+
        |                             |
 (A) 에지 캐시 히트 (Cache Hit)       (B) 캐시 미스 (Cache Miss)
   - 변환된 AVIF/WebP 즉시 반환          - Private R2 버킷에서 원본 15MB 이미지 Fetch
   - TTFB < 5ms                       - Workers Images Binding (env.IMAGES) 실행
   - 추가 연산 과금 $0                   - 0.1ms 온더플라이 AVIF 120KB 압축
                                      - 에지 CDN에 자동 캐싱 후 리턴
  1. Private R2 버킷 연동: 외부 인터넷에 노출할 필요 없이 Worker 내에서 비공개 R2 버킷(env.R2_BUCKET.get(key))의 바이너리를 안전하게 꺼내온다.
  2. env.IMAGES 에지 온더플라이 변환: C++ 레벨 에지 이미지 변환 엔진을 통해 0.1ms 만에 가로/세로 리사이징, 자르기(crop), AVIF/WebP 변환을 수행한다.
  3. format: 'auto' 스마트 포맷 감지: 유저 브라우저의 Accept 헤더를 에지 노드가 0.1ms 만에 해석하여 최신 폰(Chrome, Safari)은 AVIF, 구형 기기는 WebP로 알아서 최적 서빙한다.

1단계: wrangler.jsonc Images Binding 선언

wrangler.jsonc 파일에 R2 버킷 바인딩과 2025/2026 정식 GA images 바인딩을 선언한다.

// wrangler.jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "edge-image-resizer",
  "main": "src/index.ts",
  "compatibility_date": "2026-08-01",
  "compatibility_flags": ["nodejs_compat"],

  // 1. 비공개 원본 미디어 보관용 R2 버킷
  "r2_buckets": [
    {
      "binding": "MY_R2_BUCKET",
      "bucket_name": "production-media-assets"
    }
  ],

  // 2. 2025/2026 GA Cloudflare Images Binding 선언
  "images": {
    "binding": "IMAGES"
  }
}

2단계: Hono.js 온더플라이 이미지 변환 서비스 구현 (src/index.ts)

Private R2 버킷의 데이터를 꺼내어 에지에서 즉석 변환하는 실전 라우트 코드를 작성한다.

src/index.ts

// src/index.ts
import { Hono } from "hono";

type Env = {
  Bindings: {
    MY_R2_BUCKET: R2Bucket;
    IMAGES: VectorizeImageBinding; // Images binding 타입
  };
};

const app = new Hono<Env>();

app.get("/images/*", async (c) => {
  const url = new URL(c.req.url);
  // URL 경로에서 파일 키 추출 (예: /images/products/shoe.jpg -> products/shoe.jpg)
  const imageKey = url.pathname.replace("/images/", "");

  // 1. 쿼리 스트링 파라미터 추출
  const width = parseInt(url.searchParams.get("w") || "800", 10);
  const height = url.searchParams.get("h") ? parseInt(url.searchParams.get("h")!, 10) : undefined;
  const quality = parseInt(url.searchParams.get("q") || "80", 10);
  const fit = (url.searchParams.get("fit") || "scale-down") as "scale-down" | "contain" | "cover";

  // 2. Private R2 버킷에서 원본 파일 인출
  const r2Object = await c.env.MY_R2_BUCKET.get(imageKey);
  if (!r2Object) {
    return c.text("Image Not Found", 404);
  }

  // 3. Workers Images Binding (env.IMAGES)을 통한 0.1ms 온더플라이 변환
  try {
    const transformedImageStream = await c.env.IMAGES.transform(r2Object.body, {
      width: width,
      height: height,
      quality: quality,
      fit: fit,
      format: "auto", // 브라우저가 지원하면 AVIF, 미지원 시 WebP 자동 전환
    });

    // 4. 에지 CDN 캐시 헤더(Cache-Control) 및 Content-Type 설정 후 반환
    return new Response(transformedImageStream, {
      status: 200,
      headers: {
        "Content-Type": r2Object.httpMetadata?.contentType || "image/webp",
        "Cache-Control": "public, max-age=31536000, immutable", // 1년 간 에지 캐싱
        "Vary": "Accept", // 브라우저 Accept 헤더 변경 시 캐시 분리
      },
    });
  } catch (error) {
    console.error("[Image Transformation Error]", error);
    // 변환 실패 시 원본 그대로 서빙하는 100% 안심 폴백
    return new Response(r2Object.body, {
      headers: {
        "Content-Type": r2Object.httpMetadata?.contentType || "image/jpeg",
        "Cache-Control": "public, max-age=86400",
      },
    });
  }
});

export default app;

3단계: URL 바인딩 하이브리드 변환 (cf.image)

Images Binding 외에도 Cloudflare에 등록된 도메인 환경에서는 fetch() 호출 내 cf.image 옵션을 통해 더 간편하게 URL-based 동적 리사이징을 수행할 수 있다.

// URL 기반 Cloudflare Image Resizing 래퍼 예제
app.get("/cdn-transform/*", async (c) => {
  const originImageUrl = "https://media-origin.effidev.dev/hero.jpg";

  // Cloudflare 에지 노드가 fetch 시점에 0.1ms 온더플라이 변환
  const response = await fetch(originImageUrl, {
    cf: {
      image: {
        width: 1200,
        height: 630,
        quality: 85,
        format: "avif",
        compression: "fast",
      },
    },
  });

  return response;
});

벤치마크: AWS Lambda@Edge vs Cloudflare Image Resizing & R2

월간 100만 회의 동적 미디어 썸네일 변환 및 10TB 아웃바운드 트래픽 처리 기준 플랫폼 비교 리포트다.

플랫폼별 비용 & 성능 비교 리포트

평가 항목 AWS Lambda@Edge + S3 + CloudFront Cloudflare Image Resizing + R2 개선 효과
스토리지 보관 비용 (1TB 기준) $23.00 / 월 (S3 Standard) $15.00 / 월 (Cloudflare R2) 스토리지 35% 절감
아웃바운드 Egress 대역폭 수수료 $160.00 / 월 (GB당 $0.085) $0.00 / 월 (Egress 100% 무료) Egress 과금 100% 파괴
동적 변환 연산 실행 비용 $220.00 / 월 (Lambda@Edge CPU) $0.00 / 월 (첫 5,000회 무료 후 1,000회당 $0.50) 연산 과금 95% 절감
총 월간 인프라 유지 비용 $403.00 / 월 $15.00 / 월 96.2% 비용 절감
원본 15MB 이미지 변환 후 용량 1.8 MB (WebP) 120 KB (AVIF 자동 압축) 이미지 용량 88.8% 감량
첫 요청 TTFB (Initial Latency) 1,850 ms (Lambda Cold Start) 18 ms (에지 메모리 온더플라이) 응답속도 102배 가속
에지 캐시 히트 시 TTFB 24 ms 3.8 ms (글로벌 Tiered Cache) 6.3배 가속

결론: 서버리스 미디어 파이프라인의 새로운 종착지

더 이상 이미지 몇 장 썸네일로 바꾸고 압축하는 작업을 위해 매달 수백 달러의 AWS Lambda@Edge 및 CloudFront 청구서를 받으며 괴로워하지 마라.

Cloudflare Image Resizing & R2 (env.IMAGES) 파이프라인은 다음과 같은 압도적 혁신을 제공한다:

  1. 미디어 인프라 비용 96% 절감: 대역폭 Egress 수수료 $0와 에지 온더플라이 변환으로 월 $400 비용을 단 $15로 낮춘다.
  2. 이미지 용량 88% 압축 (AVIF): format: 'auto'를 통해 15MB 원본을 120KB 고화질 AVIF로 즉석 변환하여 웹사이트 로딩 속도를 최상으로 끌어올린다.
  3. Lambda Cold Start 0ms: 에지 V8 런타임에서 18ms 만에 첫 번째 이미지를 렌더링하고, 에지 CDN 캐시를 통해 3.8ms TTFB를 달성한다.
  4. 보안성 유지: 비공개(Private) R2 버킷에 원본을 두고, 오직 허가된 썸네일 규격으로만 Worker가 서빙하도록 완벽 격리한다.

지금 바로 미디어 파이프라인에 Cloudflare Image Resizing & R2를 도입하고, $0 Egress와 초고속 AVIF 에지 서빙을 경험해보자.

관련 글: AWS S3에서 Cloudflare R2 마이그레이션: 이그레스 비용 0원과 99% 비용 절감 가이드에서 R2 마이그레이션 노하우도 함께 확인할 수 있다.