Cloudflare Workers 무료 할당량 최적화: 10만 건을 한 달 버티게 하는 7가지 방법

지난달 Workers와 R2 스토리지를 조합해 이미지 호스팅 서비스를 만들었습니다. 꽤 완벽하다고 생각했지만 사흘도 지나지 않아 Cloudflare에서 무료 할당량이 거의 소진됐다는 메일을 받았습니다.
매일 10만 건이라고 했는데 작은 이미지 호스팅 서비스에 트래픽이 얼마나 된다고 벌써 한도에 닿았을까요? Analytics를 열어 보니 일일 평균 요청이 12만 건이었습니다. 이미지도 수십 장밖에 올리지 않았는데 이해하기 어려운 수치였습니다.
이틀 동안 문서와 커뮤니티 토론을 살펴본 뒤에야 Workers 과금에 어떤 함정이 있는지 알게 됐습니다. 하위 요청, KV 읽기, 캐시 적중 같은 항목이 모두 눈에 띄지 않게 할당량을 소모하고 있었습니다.
그래도 규칙을 이해한 뒤 몇 가지 최적화 방법을 적용해 일일 요청을 12만 건에서 3만 건으로 줄였습니다. 이제 무료 할당량으로 충분하고 30%가 남습니다. 여기서는 제가 직접 적용한 방법을 공유합니다. 월 5달러인 유료 플랜 비용을 아끼는 데 도움이 될 수 있습니다.
Workers의 ‘10만 건’은 생각한 방식으로 계산되지 않습니다
Cloudflare 문서의 ‘하루 요청 10만 건’이라는 표현은 오해하기 쉽습니다. 저도 처음에는 Worker가 10만 번 호출되면 한도에 도달한다고 생각했지만 실제 계산 방식은 달랐습니다.
사실 1: 하위 요청은 별도로 과금되지 않지만 개수 제한이 있습니다
Worker에서 fetch()로 다른 API를 호출하거나 R2를 읽고 KV를 조회하는 작업을 모두 하위 요청이라고 합니다. 하위 요청은 별도로 과금되지 않지만 무료 플랜은 요청당 50개까지만 보낼 수 있고 유료 플랜에서는 1,000개까지 가능합니다.
예를 들어 사용자가 이미지 호스팅 URL에 접속하면 과금 요청 1건이 발생합니다. Worker에서 권한 확인을 위해 KV를 조회하고 R2에서 이미지를 가져오면 하위 요청은 2개지만 과금 요청은 1건으로 계산됩니다.
집계 서비스를 만들고 요청 한 번에 API 10개를 호출한다면 하위 요청이 10개입니다. 무료 플랜의 50개 제한은 넉넉해 보이지만 실제 프로젝트에서는 생각보다 쉽게 상한에 닿습니다.
사실 2: 10만 건은 Worker 하나가 아니라 계정 전체의 제한입니다
이 부분은 특히 헷갈립니다. 저도 처음에는 Worker를 여러 개 만들어 트래픽을 분산할 수 있다고 생각했지만 10만 건은 계정 전체에 적용되는 제한이었습니다. Worker를 10개 등록해도 합산 할당량은 여전히 10만 건입니다.
여러 Worker로 한도를 피할 수는 없습니다. 커뮤니티에서도 시도한 사례가 있지만 Cloudflare의 제한은 계정 단위입니다. 한도를 늘리려면 유료 플랜을 사용하거나 요청 횟수를 최적화해야 합니다.
사실 3: KV 읽기·쓰기와 Cache API 작업도 요청으로 계산됩니다
이 부분은 가장 놓치기 쉽습니다. Worker가 KV.get()으로 데이터를 읽을 때 하위 요청 제한에는 포함되지 않지만 요청 횟수는 소모됩니다. 사용자 접속마다 권한 확인을 위해 KV를 읽는다면 접속 1회마다 KV 작업 1회가 추가로 소모됩니다.
Cache API도 마찬가지입니다. 캐시를 사용하면 원본 서버 요청은 줄일 수 있지만 Cache의 match()와 put() 작업 자체에도 비용이 듭니다.
가장 흔히 빠지는 세 가지 함정
당시 제 요청 수가 급증한 원인도 다음 세 가지였습니다.
- 함정 1: 리버스 프록시가 캐시 없이 매번 하위 요청을 보냅니다
API 중계 서비스를 만들면서 매번 원본 API를fetch()했습니다. 캐시를 고려하지 않아 사용자 요청마다 하위 요청이 발생했습니다. Cache API를 추가한 뒤 적중률이 80%가 되었고 요청 횟수가 절반으로 줄었습니다. - 함정 2: KV를 자주 읽으면서 cacheTtl 매개변수를 모릅니다
이미지마다 권한 확인을 위해KV.get()을 호출했습니다.cacheTtl매개변수로 KV 데이터를 엣지 노드에 캐시할 수 있다는 사실을 몰랐습니다.cacheTtl: 600(10분)으로 바꾼 뒤 KV 읽기가 70% 줄었습니다. - 함정 3: 리디렉션 체인의 각 이동이 모두 계산됩니다
단축 URL 서비스에서 Worker가302리디렉션을 반환하도록 했습니다. 그런데 A→B→C→최종 목적지처럼 세 번 이동하면 각 이동이 하위 요청 1개로 계산됐습니다. 최종 주소를 바로 반환하도록 바꿔 요청 2개를 줄였습니다.
이 세 가지가 겹쳐 10만 건을 넘어 12만 건까지 늘었습니다. 할당량이 부족하다면 먼저 같은 문제를 겪고 있는지 확인해 보세요.
무료 할당량을 한 달 더 버티게 하는 7가지 최적화 방법
과금 규칙을 이해한 뒤 여러 최적화 방안을 시험했습니다. 다음 7가지는 실제로 효과가 컸고 구현도 어렵지 않았습니다.
방법 1: 캐시를 활용해 중복 요청의 80% 줄이기
제가 시험한 방법 중 효과가 가장 빨랐습니다. 많은 Worker 프로젝트는 매번 실시간으로 계산할 필요 없이 결과를 캐시할 수 있습니다.
최적화 전에는 이미지에 접근할 때마다 권한 확인→R2 읽기→응답의 전체 과정을 거쳤습니다. 최적화 후에는 Cache API를 추가했습니다.
const cache = caches.default;
const cacheKey = new Request(request.url, request);
// 먼저 캐시 확인
let response = await cache.match(cacheKey);
if (response) {
return response; // 캐시 적중 시 바로 반환
}
// 캐시 미적중 시 요청 처리
response = await handleRequest(request);
// 캐시 설정(정적 이미지는 하루 동안 캐시)
response = new Response(response.body, {
...response,
headers: {
...response.headers,
'Cache-Control': 'public, max-age=86400',
},
});
await cache.put(cacheKey, response.clone());
return response;
변경 후 캐시 적중률은 85%가 됐습니다. 일일 요청 12만 건 가운데 실제로 Worker 로직을 거치는 요청은 1만 8,000건으로 줄어 10만 2,000건을 절약했습니다.
방법 2: KV 최적화의 세 가지 핵심
KV는 Workers에서 가장 자주 쓰는 스토리지이지만 요청 횟수를 많이 소모하기도 합니다. 제가 정리한 세 가지 최적화 지점은 다음과 같습니다.
-
cacheTtl 매개변수 늘리기
KV는 기본적으로 엣지 노드에 60초 동안 캐시됩니다. 데이터가 자주 바뀌지 않는다면 이 값을 늘릴 수 있습니다.// 최적화 전 const value = await KV.get('key'); // 최적화 후(10분 캐시) const value = await KV.get('key', { cacheTtl: 600 });제 권한 확인 데이터는 30분에 한 번만 갱신되므로
cacheTtl: 1800으로 설정했고 KV 읽기가 70% 줄었습니다. -
Cache API로 KV 결과 캐시하기
설정 파일이나 블랙리스트처럼 더 천천히 바뀌는 데이터라면 Worker 계층에 캐시를 하나 더 둘 수 있습니다.const cacheKey = `kv-cache:${key}`; let cached = await caches.default.match(cacheKey); if (!cached) { const value = await KV.get(key); cached = new Response(value); await caches.default.put(cacheKey, cached.clone()); } return cached.text(); -
waitUntil로 비차단 쓰기 처리하기
결과를 기다릴 필요 없이 KV에 써야 한다면waitUntil을 사용해 응답을 차단하지 않을 수 있습니다.// KV 쓰기 완료를 기다리지 않고 응답 반환 event.waitUntil(KV.put('key', 'value')); return new Response('OK');
이 세 가지를 조합해 일일 KV 작업을 3만 회에서 8,000회로 줄였습니다.
방법 3: 불필요한 하위 요청 줄이기
하위 요청도 상당 부분 줄일 수 있습니다.
예전에 집계 서비스를 만들면서 외부 API 5개를 호출하고 결과를 합쳐 반환했습니다. 요청 한 번에 하위 요청 5개가 발생했습니다. 이후 다음과 같이 바꿨습니다.
- 호출 빈도가 높은 API 결과는 5분 동안 캐시
- 호출 빈도가 낮은 API 결과는 KV에 24시간 저장
- 가능하면 데이터를 미리 처리해 R2에 저장
최적화 후에는 요청의 80%가 하위 요청 없이 캐시에서 바로 반환됩니다.
방법 4: Request.cache로 캐시 동작 제어하기
Cloudflare는 2024년 11월에 Request.cache 속성을 추가해 캐시 동작을 더 세밀하게 제어할 수 있게 했습니다.
// 캐시 건너뛰기(민감한 데이터에 적합)
const response = await fetch(url, { cache: 'no-store' });
// 기본 캐시 정책 사용
const response = await fetch(url, { cache: 'default' });
사용자의 비공개 이미지를 처리할 때는 cache: 'no-store'를 사용해 CDN에 캐시되지 않도록 했습니다. 공개 이미지는 default를 사용해 Cloudflare가 자동으로 최적화하도록 했습니다.
방법 5: 리디렉션 체인 최적화하기
Worker가 302/301 리디렉션을 반환한다면 리디렉션 체인의 각 이동이 하위 요청으로 계산된다는 점에 주의해야 합니다.
단축 URL 서비스의 최적화 전 코드는 다음과 같았습니다.
// 최적화 전: 302 리디렉션 반환
return Response.redirect(targetUrl, 302);
최적화 후 코드는 다음과 같습니다.
// 최적화 후: 대상 주소를 캐시해 리디렉션 줄이기
const cached = await cache.match(shortUrl);
if (cached) {
return cached; // 캐시된 최종 주소를 바로 반환
}
bit.ly → t.co → 최종 URL처럼 여러 번 이동하는 링크는 최종 주소를 직접 저장해 매번 리디렉션 체인을 거치지 않게 합니다.
방법 6: 요청 분포를 모니터링해 할당량을 잡아먹는 경로 찾기
Cloudflare Analytics는 무료이므로 반드시 활용하는 편이 좋습니다.
요청량의 80%가 경로의 20%에서 발생하는 경우가 많습니다. Workers Analytics에서는 다음 항목을 확인할 수 있습니다.
- 요청이 가장 많은 경로
- 캐시 적중률이 낮은 경로
- 처리 시간이 가장 긴 경로
요청량이 큰 경로를 찾아 집중적으로 최적화합니다. 당시 /api/status 상태 확인 엔드포인트가 모니터링 서비스에서 분당 100회 호출돼 일일 요청의 15%를 차지한다는 사실을 발견했습니다. 이 엔드포인트에 60초 캐시를 추가하자 하루 1만 5,000건을 바로 줄일 수 있었습니다.
방법 7: 긴급하지 않은 작업을 시간대별로 처리하기
Workers는 Cron Triggers로 예약 작업을 실행할 수 있습니다. 통계, 정리, 캐시 예열처럼 실시간일 필요가 없는 작업은 사용량이 적은 시간대로 옮길 수 있습니다.
제 이미지 호스팅 서비스에는 매시간 접속량을 집계하는 기능이 있습니다. 이전에는 접속할 때마다 KV 카운터에 썼지만 다음과 같이 바꿨습니다.
- 접속 시 메모리에서만 집계하고 KV에는 쓰지 않음
- Cron Trigger로 한 시간마다 한 번씩 집계
이렇게 자주 발생하던 KV 쓰기를 시간당 1회의 일괄 작업으로 바꿨습니다. 일일 KV 쓰기는 2만 회에서 24회로 줄었습니다.
실제 사례: 이미지 호스팅 프로젝트의 일일 요청을 12만 건에서 3만 건으로 줄이기
앞에서 소개한 방법을 조합하면 효과가 어느 정도일까요? 제 이미지 호스팅 프로젝트의 전체 최적화 과정을 사례로 살펴보겠습니다.
프로젝트 배경
다음 기술 스택으로 만든 간단한 이미지 호스팅 서비스입니다.
- Cloudflare Workers로 요청 처리
- R2에 이미지 파일 저장
- KV에 이미지 메타데이터와 권한 저장
- 일일 평균 약 2,000회의 이미지 조회(실제 사용자 트래픽)
출시 사흘째 Cloudflare에서 일일 평균 요청이 12만 건으로 무료 할당량 상한에 가깝다는 알림을 받았습니다.
문제 진단
Analytics와 코드 리뷰를 반나절 진행해 세 가지 주요 문제를 찾았습니다.
- 이미지 요청마다 KV 조회
이미지에 접근할 때마다 Worker가KV.get()으로 파일명, 크기, 업로더 같은 메타데이터를 조회했습니다. 이미지 조회 2,000회는 KV 읽기 2,000회를 뜻합니다. 거의 바뀌지 않는 메타데이터라 매번 조회할 필요가 없었습니다. - 브라우저 캐시 없음
응답 헤더에Cache-Control을 설정하지 않아 사용자가 페이지를 새로고침할 때마다 브라우저가 다시 요청했습니다. 같은 사용자가 같은 이미지를 10번 요청하면 Worker도 10번 호출됐습니다. - 실시간 썸네일 생성
이미지 목록에서 썸네일을 표시하기 위해 Worker에서 실시간으로 잘라 생성했습니다. 한 페이지에 이미지가 30장이면 이미지 처리 요청도 30건이었습니다. 사용자가 여러 페이지를 넘기면 요청 수가 급증했습니다.
이 세 가지 문제 때문에 실제 유효 접속 2,000회가 Worker 호출 12만 건으로 늘었습니다.
최적화 방안
세 가지 문제를 우선순위에 따라 최적화했습니다.
1단계: KV 캐시 최적화(효과가 가장 빠름)
KV 읽기에 cacheTtl 매개변수를 추가했습니다.
// 최적화 전
const metadata = await IMAGE_KV.get(imageId);
// 최적화 후
const metadata = await IMAGE_KV.get(imageId, {
cacheTtl: 600 // 10분 캐시
});
효과: KV 읽기가 하루 2,000회에서 약 300회로 감소(-85%)
2단계: 브라우저 캐시 추가
이미지 응답에 캐시 헤더를 추가했습니다.
return new Response(imageData, {
headers: {
'Content-Type': 'image/jpeg',
'Cache-Control': 'public, max-age=86400', // 하루 동안 캐시
'CDN-Cache-Control': 'public, max-age=2592000' // CDN에서 30일 동안 캐시
}
});
효과: 반복 접근이 60% 줄고 요청이 12만 건에서 4만 8,000건으로 감소
3단계: 썸네일 사전 생성
실시간 생성을 중단하고 업로드할 때 미리 생성해 R2의 thumbnails/ 디렉터리에 저장했습니다.
// 업로드 시 썸네일 생성
const thumbnail = await generateThumbnail(image);
await R2.put(`thumbnails/${imageId}`, thumbnail);
// 접근 시 바로 읽기
const thumbnail = await R2.get(`thumbnails/${imageId}`);
효과: 썸네일 요청이 더 이상 Worker 처리 로직을 실행하지 않아 요청이 4만 8,000건에서 3만 2,000건으로 감소
4단계: Worker 캐시 계층
마지막으로 전체 응답에 Cache API를 추가했습니다.
const cache = caches.default;
let response = await cache.match(request);
if (response) return response;
// 요청 처리...
await cache.put(request, response.clone());
return response;
효과: 캐시 적중률 78%, 최종적으로 일일 평균 약 3만 건에서 안정화
최적화 결과
| 지표 | 최적화 전 | 최적화 후 | 변화 |
|---|---|---|---|
| 일일 요청 | 12만 건 | 3만 2,000건 | -73% |
| KV 읽기 | 2,000회 | 300회 | -85% |
| 캐시 적중률 | 0% | 78% | +78% |
| 비용 | 한도 20% 초과 | 70% 여유 | 연간 60달러 절약 |
현재 이 이미지 호스팅 서비스는 두 달 동안 안정적으로 운영 중이며 일일 평균 요청은 3만~4만 건이라 무료 할당량으로 충분합니다. 유료 플랜이 월 5달러라고 계산하면 연간 60달러를 절약한 셈입니다.
경험에서 얻은 결론
이번 최적화를 돌아보며 다음 네 가지 핵심을 정리했습니다.
- 병목을 먼저 찾고 최적화하기: 무작정 최적화하지 말고 Analytics로 실제 문제를 찾습니다.
- 캐시를 우선하기: 최적화 효과의 80%는 브라우저 캐시, CDN 캐시, Worker 캐시에서 나옵니다.
- KV를 신중하게 사용하기: 캐시할 수 있다면 반드시
cacheTtl을 설정하고, 미리 계산할 수 있다면 실시간으로 조회하지 않습니다. - 점진적으로 최적화하기: 저는 네 단계로 나눠 최적화했고 한꺼번에 너무 많이 바꾸지 않아 단계마다 뚜렷한 효과를 확인할 수 있었습니다.
유료 플랜과 최적화 중 무엇을 선택할까? 비용 계산하기
여기까지 읽으면 시간을 들여 최적화할지 바로 유료 플랜으로 업그레이드할지 고민될 수 있습니다. 저도 같은 고민을 했지만 비용을 계산해 보니 판단하기 쉬웠습니다.
무료 플랜과 유료 플랜 비교
| 항목 | 무료 플랜 | 유료 플랜(월 5달러) |
|---|---|---|
| 일일 요청 | 10만 건 | 약 33만 건(월 1,000만 건) |
| 분당 제한 | 1,000건 | 명확한 제한 없음 |
| 하위 요청 수 | 요청당 50개 | 요청당 1,000개 |
| KV 읽기 | 하루 10만 회 | 월 1,000만 회 |
| CPU 시간 | 10ms | 50ms |
| 연간 비용 | 0원 | 60달러 |
수치만 보면 유료 플랜은 일일 요청량이 3배, 하위 요청 제한이 20배로 늘어납니다. 하지만 실제로 필요한지가 핵심입니다.
유료 플랜으로 업그레이드해야 하는 경우
다음 세 가지 상황이라면 바로 결제하는 편이 좋습니다.
- 일일 요청이 안정적으로 10만 건을 넘는 경우
‘안정적으로’ 넘는지가 중요합니다. 일시적인 트래픽 급증이라면 최적화로 해결할 수 있지만 일주일 내내 초과한다면 실제 사용량이 늘어난 것이므로 유료 플랜이 편합니다. - 하위 요청이 많이 필요한 경우
크롤러, 집계 서비스, API 게이트웨이처럼 요청 한 번에 외부 API를 10개 이상 호출한다면 무료 플랜의 50개 제한으로는 부족할 수 있습니다. 최적화 여지가 제한적이므로 유료 플랜의 1,000개 제한이 더 적합합니다. - 상업 프로젝트에서 안정성이 비용보다 중요한 경우
고객 프로젝트나 상용 제품이라면 무료 할당량에서 비용을 아끼지 않는 편이 낫습니다. 유료 플랜은 SLA가 더 안정적이고 문제가 생기면 지원 티켓을 열 수 있습니다. 5달러로 얻는 안정성이 절약액보다 중요합니다.
최적화의 한계는 어디인가?
반대로 최적화가 시간 낭비가 되는 경우도 있습니다.
- 과도한 최적화로 코드가 복잡해지는 경우
요청을 줄이려고 캐시 로직, 사전 계산 스크립트, 예약 작업을 많이 추가하면 코드 유지보수가 어려워집니다. 시간 비용이 5달러를 훨씬 넘을 수도 있습니다. - 최적화가 이미 한계에 도달한 경우
필요한 캐시와 최적화를 모두 적용해도 부족하다면 사용량 문제입니다. 억지로 버티지 말고 유료 플랜을 선택합니다. - 시간 비용과 5달러 비교
자신의 시급을 계산해 보세요. 최적화에 3시간이 걸리고 시급이 20위안을 넘는다면 바로 결제하는 편이 경제적입니다.
제 제안은 다음과 같습니다.
- 개인 프로젝트와 학습 프로젝트: 비용 절약과 학습을 위해 먼저 최적화
- 소규모 팀과 초기 제품: 최대한 최적화한 뒤 유료 플랜 검토
- 상업 프로젝트와 고객 프로젝트: 비용을 아끼려 하지 말고 바로 유료 플랜 사용
유료 플랜을 사용한 뒤에도 최적화해야 할까?
그렇습니다. 유료 플랜의 할당량이 더 크더라도 과금 규칙은 같습니다. 최적화하지 않으면 1,000만 건 할당량도 모두 소진할 수 있습니다.
유료 플랜의 초과 요청은 100만 건당 0.50달러로 과금됩니다. 일일 평균 요청이 100만 건이면 한 달 초과 비용이 15달러이고 기본 요금 5달러를 더하면 월 20달러입니다. 이때 최적화의 가치가 드러납니다.
결론
핵심은 한 문장입니다. Workers의 과금 방식을 이해하고 알맞은 방법으로 최적화해야 합니다.
Workers의 무료 10만 건 할당량은 처음에는 넉넉해 보이지만 실제로는 쉽게 초과할 수 있습니다. 대부분은 사용량이 너무 많아서가 아니라 최적화가 부족해서 생깁니다.
제 이미지 호스팅 프로젝트가 대표적인 사례입니다. 실제 접속은 2,000회에 불과했지만 요청은 12만 건이나 발생했습니다. 캐시, KV 최적화, 사전 계산을 적용해 최종적으로 3만 건까지 줄였고 무료 할당량 안에서 여유도 확보했습니다.
할당량이 부족하다면 다음 순서로 진행해 보세요.
- Workers Analytics를 열어 어느 경로가 할당량을 많이 소모하는지 확인합니다.
- 효과가 가장 빠른 캐시와 KV부터 최적화합니다.
- 하위 요청, KV
cacheTtl, 리디렉션 체인이라는 세 가지 함정에 빠졌는지 확인합니다. - 앞의 7가지 방법을 모두 조합해 적용합니다.
- 최대한 최적화해도 부족하면 유료 플랜을 검토합니다.
마지막으로 Cloudflare는 상업 회사이므로 무료 할당량을 합리적으로 사용해야 합니다. 지나치게 무료 자원을 이용하려 하면 속도 제한이나 계정 정지를 당할 수도 있습니다. 최적화의 목적은 편법이 아니라 자원을 더 효율적으로 쓰는 것입니다.
이 글로 5달러를 아꼈다면 좋아요를 누르거나 Workers를 사용하는 친구에게 공유해 주세요. 무료 할당량을 최대한 효율적으로 활용해 봅시다.
Cloudflare Workers 무료 할당량 최적화 전체 과정
과금 규칙 이해부터 7가지 최적화 방법까지 설명하며, 이미지 호스팅 프로젝트의 일일 요청을 12만 건에서 3만 건으로 줄이고 캐시 적중률을 80% 높인 실제 사례를 다룹니다.
Estimated time: PT2H
-
1
Step 1: Workers 과금 규칙과 흔한 함정 이해하기
Workers 과금 규칙의 실제 내용: -
2
Step 2: 7가지 최적화 방법: 캐시, KV 최적화, 하위 요청 줄이기
방법 1: 캐시를 활용해 중복 요청의 80% 줄이기 -
3
Step 3: 실제 사례: 이미지 호스팅 프로젝트의 최적화 전후 비교
최적화 전: -
4
Step 4: 유료 플랜과 최적화 중 무엇을 선택할까? 비용 계산하기
무료 플랜과 유료 플랜 비교: 무료 플랜은 일일 요청 10만 건, 분당 제한 1,000건, 요청당 하위 요청 50개, KV 읽기 하루 10만 회, CPU 시간 10ms, 연간 비용 0원입니다. 유료 플랜(월 5달러)은 일일 요청 약 33만 건(월 1,000만 건), 명확한 제한 없음, 요청당 하위 요청 1,000개, KV 읽기 월 1,000만 회, CPU 시간 50ms, 연간 비용 60달러입니다. 수치만 보면 유료 플랜은 일일 요청량이 3배, 하위 요청 제한이 20배로 늘어나지만 실제로 필요한지가 핵심입니다. 유료 플랜으로 업그레이드해야 하는 경우는 다음과 같습니다. 1) 일일 요청이 안정적으로 10만 건을 넘는 경우(일시적인 트래픽 급증이라면 최적화로 해결할 수 있지만 일주일 내내 초과한다면 실제 사용량이 늘어난 것이므로 유료 플랜이 편합니다.) 2) 하위 요청이 많이 필요한 경우(크롤러, 집계 서비스, API 게이트웨이처럼 요청 한 번에 외부 API를 10개 이상 호출한다면 무료 플랜의 50개 제한으로는 부족할 수 있습니다. 최적화 여지가 제한적이므로 유료 플랜의 1,000개 제한이 더 적합합니다.) 3) 상업 프로젝트에서 안정성이 비용보다 중요한 경우(고객 프로젝트나 상용 제품이라면 무료 할당량에서 비용을 아끼지 않는 편이 낫습니다. 유료 플랜은 SLA가 더 안정적이고 문제가 생기면 지원 티켓을 열 수 있으므로 5달러로 얻는 안정성이 절약액보다 중요합니다.) 최적화의 한계는 다음과 같습니다. 1) 과도한 최적화로 코드가 복잡해집니다(요청을 줄이려고 캐시 로직, 사전 계산 스크립트, 예약 작업을 많이 추가하면 코드 유지보수가 어려워지고 시간 비용이 5달러를 훨씬 넘을 수 있습니다.) 2) 최적화가 한계에 도달했습니다(필요한 캐시와 최적화를 모두 적용해도 부족하다면 사용량 문제이므로 억지로 버티지 말고 유료 플랜을 선택합니다.) 3) 시간 비용과 5달러를 비교합니다(최적화에 3시간이 걸리고 시급이 20위안을 넘는다면 바로 결제하는 편이 경제적입니다.) 개인 프로젝트와 학습 프로젝트는 비용 절약과 학습을 위해 먼저 최적화하고, 소규모 팀과 초기 제품은 최대한 최적화한 뒤 유료 플랜을 검토하며, 상업 프로젝트와 고객 프로젝트는 바로 유료 플랜을 사용하는 것이 좋습니다. 유료 플랜을 사용한 뒤에도 최적화해야 합니다. 과금 규칙은 같아서 최적화하지 않으면 1,000만 건 할당량도 모두 소진할 수 있습니다. 초과 요청은 100만 건당 0.50달러로 과금되므로 일일 평균 요청이 100만 건이면 한 달 초과 비용 15달러와 기본 요금 5달러를 합쳐 월 20달러입니다. 이때 최적화의 가치가 드러납니다. -
5
Step 5: 최적화 단계와 모범 사례
할당량이 부족하다면 다음 순서로 진행합니다. 1) Workers Analytics를 열어 어느 경로가 할당량을 많이 소모하는지 확인합니다. 2) 효과가 가장 빠른 캐시와 KV부터 최적화합니다. 3) 하위 요청, KV cacheTtl, 리디렉션 체인이라는 세 가지 함정에 빠졌는지 확인합니다. 4) 앞의 7가지 방법을 모두 조합해 적용합니다. 5) 최대한 최적화해도 부족하면 유료 플랜을 검토합니다. Cloudflare는 상업 회사이므로 무료 할당량을 합리적으로 사용해야 합니다. 지나치게 무료 자원을 이용하려 하면 속도 제한이나 계정 정지를 당할 수도 있습니다. 최적화의 목적은 편법이 아니라 자원을 더 효율적으로 쓰는 것입니다. 핵심은 Workers의 과금 방식을 이해하고 알맞은 방법으로 최적화하는 것입니다. Workers의 무료 10만 건 할당량은 처음에는 넉넉해 보이지만 실제로는 쉽게 초과할 수 있습니다. 대부분은 사용량이 너무 많아서가 아니라 최적화가 부족해서 생깁니다. 제 이미지 호스팅 프로젝트도 실제 접속은 2,000회에 불과했지만 요청이 12만 건 발생했습니다. 캐시, KV 최적화, 사전 계산을 적용해 최종적으로 3만 건까지 줄였고 무료 할당량 안에서 여유도 확보했습니다.
FAQ
Workers의 무료 ‘10만 건’ 할당량은 어떻게 계산하나요?
사실 1: 하위 요청은 별도로 과금되지 않지만 개수 제한이 있습니다.
• Worker에서 fetch()로 다른 API를 호출하거나 R2를 읽고 KV를 조회하는 작업을 모두 하위 요청이라고 합니다.
• 하위 요청은 별도로 과금되지 않지만, 무료 플랜은 요청당 하위 요청을 50개까지만 보낼 수 있고 유료 플랜에서는 1,000개까지 가능합니다.
• 예를 들어 사용자가 이미지 호스팅 URL에 접속하면 과금 요청 1건이 발생합니다. Worker에서 권한 확인을 위해 KV를 조회하고 R2에서 이미지를 가져오면 하위 요청은 2개지만 과금 요청은 1건으로 계산됩니다.
사실 2: 10만 건은 Worker 하나가 아니라 계정 전체의 제한입니다.
• 저도 처음에는 Worker를 여러 개 만들어 트래픽을 분산할 수 있다고 생각했지만, 10만 건은 계정 전체에 적용되는 제한이었습니다.
• Worker를 10개 등록해도 합산 할당량은 여전히 10만 건이므로 여러 Worker로 제한을 우회할 수 없습니다.
사실 3: KV 읽기·쓰기와 Cache API 작업도 요청으로 계산됩니다.
• Worker가 KV.get()으로 데이터를 읽을 때 하위 요청 제한에는 포함되지 않지만 요청 횟수는 소모됩니다.
• Worker가 사용자 접속마다 권한 확인을 위해 KV를 읽는다면 접속 1회마다 KV 작업 1회가 추가로 소모됩니다.
• Cache API도 마찬가지입니다. 캐시를 사용하면 원본 서버 요청은 줄일 수 있지만 Cache의 match()와 put() 작업 자체에도 비용이 듭니다.
가장 흔히 빠지는 세 가지 함정은 무엇이며 어떻게 피할 수 있나요?
함정 1: 리버스 프록시가 캐시 없이 매번 하위 요청을 보냅니다.
• API 중계 서비스를 만들면서 매번 원본 API를 fetch()했고 캐시를 고려하지 않아 사용자 요청마다 하위 요청이 발생했습니다.
• Cache API를 추가한 뒤 적중률이 80%가 되었고 요청 횟수가 절반으로 줄었습니다.
• 해결 방법: 캐시를 활용해 중복 요청의 80%를 줄입니다. 많은 Worker 프로젝트는 매번 실시간으로 계산할 필요 없이 결과를 캐시할 수 있습니다.
함정 2: KV를 자주 읽으면서 cacheTtl 매개변수를 모릅니다.
• 이미지 호스팅 프로젝트에서 이미지마다 권한 확인을 위해 KV.get()을 호출했는데, cacheTtl 매개변수로 KV 데이터를 엣지 노드에 캐시할 수 있다는 사실을 몰랐습니다.
• cacheTtl: 600(10분)으로 바꾼 뒤 KV 읽기가 70% 줄었습니다.
• 해결 방법: KV 최적화의 세 가지 핵심을 적용합니다.
1) cacheTtl 매개변수 늘리기(KV는 기본적으로 엣지 노드에 60초 동안 캐시되므로 데이터가 자주 바뀌지 않으면 값을 늘립니다.)
2) 일괄 읽기(한 요청에서 여러 KV 값을 읽어야 한다면 직렬 처리 대신 Promise.all로 병렬 처리합니다.)
3) 쓰기 줄이기(KV 쓰기는 읽기보다 비싸므로 미리 계산할 수 있는 데이터는 실시간으로 쓰지 않습니다.)
함정 3: 리디렉션 체인의 각 이동이 모두 계산됩니다.
• 단축 URL 서비스에서 Worker가 302 리디렉션을 반환하도록 했는데, A→B→C→최종 목적지처럼 세 번 이동하면 각 이동이 하위 요청 1개로 계산된다는 사실을 뒤늦게 알았습니다.
• 최종 주소를 바로 반환하도록 바꿔 요청 2개를 줄였습니다.
• 해결 방법: 리디렉션을 합리적으로 사용하고 체인을 피합니다. 여러 번 이동하는 리디렉션 체인은 각 이동이 하위 요청 1개로 계산되므로 최종 주소를 직접 반환합니다.
7가지 최적화 방법과 효과는 무엇인가요?
• 제가 시험한 방법 중 효과가 가장 빨랐습니다.
• 최적화 전에는 이미지에 접근할 때마다 권한 확인→R2 읽기→응답의 전체 과정을 거쳤습니다.
• Cache API를 추가한 뒤 캐시 적중률이 85%가 되었고, 일일 요청 12만 건 가운데 실제로 Worker 로직을 거치는 요청은 1만 8,000건으로 줄어 10만 2,000건을 절약했습니다.
방법 2: KV 최적화의 세 가지 핵심
1) cacheTtl 매개변수 늘리기: KV는 기본적으로 엣지 노드에 60초 동안 캐시되므로 데이터가 자주 바뀌지 않으면 값을 늘립니다.
2) 일괄 읽기: 한 요청에서 여러 KV 값을 읽어야 한다면 직렬 처리 대신 Promise.all로 병렬 처리합니다.
3) 쓰기 줄이기: KV 쓰기는 읽기보다 비싸므로 미리 계산할 수 있는 데이터는 실시간으로 쓰지 않습니다.
방법 3: 하위 요청 수 줄이기
• API 호출 합치기: 한 요청에서 여러 API를 호출해야 한다면 가능한 한 하나로 합칩니다.
• R2 직접 접근 사용하기: R2 파일을 읽기만 한다면 Worker를 거치지 않고 R2 공개 URL을 사용할 수 있습니다.
방법 4: 리디렉션 합리적으로 사용하기
• 리디렉션 체인 피하기: 여러 번 이동하는 리디렉션 체인은 각 이동이 하위 요청 1개로 계산되므로 최종 주소를 바로 반환합니다.
방법 5: 코드 로직 최적화하기
• 불필요한 계산 줄이기: 미리 계산할 수 있는 것은 실시간으로 계산하지 않고, 캐시할 수 있는 것은 매번 조회하지 않습니다.
방법 6: 모니터링과 분석
• Analytics를 정기적으로 확인합니다. Workers Analytics에서 어느 경로가 할당량을 많이 소모하는지 살펴보고 실제 문제를 찾습니다.
방법 7: 유료 플랜 검토하기
• 최적화를 모두 적용해도 부족할 때 유료 플랜을 고려합니다.
• 유료 플랜은 월 5달러이며 일일 요청량은 3배, 하위 요청 제한은 20배로 늘어납니다.
실제 사례에서 최적화 효과는 어느 정도였나요?
최적화 전:
• 일일 요청 12만 건
• KV 읽기 2,000회
• 캐시 적중률 0%
• 비용 한도 20% 초과
최적화 후:
• 일일 요청 3만 2,000건(73% 감소)
• KV 읽기 300회(85% 감소)
• 캐시 적중률 78%(78%p 상승)
• 할당량 70% 여유(연간 60달러 절약)
현재 이 이미지 호스팅 서비스는 두 달 동안 안정적으로 운영 중이며 일일 평균 요청은 3만~4만 건이라 무료 할당량으로 충분합니다. 유료 플랜이 월 5달러라고 계산하면 연간 60달러를 절약한 셈입니다.
경험에서 얻은 결론:
1) 병목을 먼저 찾고 최적화하기(무작정 최적화하지 말고 Analytics로 실제 문제를 찾습니다.)
2) 캐시를 우선하기(최적화 효과의 80%는 브라우저 캐시, CDN 캐시, Worker 캐시에서 나옵니다.)
3) KV를 신중하게 사용하기(캐시할 수 있다면 반드시 cacheTtl을 설정하고, 미리 계산할 수 있다면 실시간으로 조회하지 않습니다.)
4) 점진적으로 최적화하기(저는 네 단계로 나눠 최적화했고 한꺼번에 너무 많이 바꾸지 않아 단계마다 뚜렷한 효과를 확인할 수 있었습니다.)
제 이미지 호스팅 프로젝트가 대표적인 사례입니다. 실제 접속은 2,000회에 불과했지만 요청은 12만 건이나 발생했습니다. 캐시, KV 최적화, 사전 계산을 적용해 최종적으로 3만 건까지 줄였고 무료 할당량 안에서 여유도 확보했습니다.
언제 유료 플랜을 선택하고 언제 최적화해야 하나요?
무료 플랜:
• 일일 요청 10만 건
• 분당 제한 1,000건
• 하위 요청 수 요청당 50개
• KV 읽기 하루 10만 회
• CPU 시간 10ms
• 연간 비용 0원
유료 플랜(월 5달러):
• 일일 요청 약 33만 건(월 1,000만 건)
• 명확한 제한 없음
• 하위 요청 수 요청당 1,000개
• KV 읽기 월 1,000만 회
• CPU 시간 50ms
• 연간 비용 60달러
수치만 보면 유료 플랜은 일일 요청량이 3배, 하위 요청 제한이 20배로 늘어납니다. 하지만 실제로 필요한지가 핵심입니다.
유료 플랜으로 업그레이드해야 하는 경우:
1) 일일 요청이 안정적으로 10만 건을 넘습니다. 일시적인 트래픽 급증이라면 최적화로 해결할 수 있지만 일주일 내내 초과한다면 실제 사용량이 늘어난 것이므로 유료 플랜이 편합니다.
2) 하위 요청이 많이 필요합니다. 크롤러, 집계 서비스, API 게이트웨이처럼 요청 한 번에 외부 API를 10개 이상 호출한다면 무료 플랜의 50개 제한으로는 부족할 수 있습니다. 최적화 여지가 제한적이므로 유료 플랜의 1,000개 제한이 더 적합합니다.
3) 상업 프로젝트에서 안정성이 비용보다 중요합니다. 고객 프로젝트나 상용 제품이라면 무료 할당량에서 비용을 아끼지 않는 편이 낫습니다. 유료 플랜은 SLA가 더 안정적이고 문제가 생기면 지원 티켓을 열 수 있으므로 5달러로 얻는 안정성이 절약액보다 중요합니다.
최적화의 한계:
1) 과도한 최적화로 코드가 복잡해집니다. 요청을 줄이려고 캐시 로직, 사전 계산 스크립트, 예약 작업을 많이 추가하면 코드 유지보수가 어려워지고 시간 비용이 5달러를 훨씬 넘을 수 있습니다.
2) 최적화가 한계에 도달했습니다. 필요한 캐시와 최적화를 모두 적용해도 부족하다면 사용량 문제이므로 억지로 버티지 말고 유료 플랜을 선택합니다.
3) 시간 비용과 5달러를 비교합니다. 최적화에 3시간이 걸리고 시급이 20위안을 넘는다면 바로 결제하는 편이 경제적입니다.
제 제안은 다음과 같습니다.
• 개인 프로젝트와 학습 프로젝트는 비용 절약과 학습을 위해 먼저 최적화합니다.
• 소규모 팀과 초기 제품은 최대한 최적화한 뒤 유료 플랜을 검토합니다.
• 상업 프로젝트와 고객 프로젝트는 비용을 아끼려 하지 말고 바로 유료 플랜을 사용합니다.
유료 플랜을 사용한 뒤에도 최적화해야 하나요?
유료 플랜의 초과 요청은 100만 건당 0.50달러로 과금됩니다. 일일 평균 요청이 100만 건이면 한 달 초과 비용이 15달러이고 기본 요금 5달러를 더하면 월 20달러입니다. 이때 최적화의 가치가 드러납니다.
핵심은 한 문장입니다. Workers의 과금 방식을 이해하고 알맞은 방법으로 최적화해야 합니다.
Workers의 무료 10만 건 할당량은 처음에는 넉넉해 보이지만 실제로는 쉽게 초과할 수 있습니다. 대부분은 사용량이 너무 많아서가 아니라 최적화가 부족해서 생깁니다.
마지막으로 Cloudflare는 상업 회사이므로 무료 할당량을 합리적으로 사용해야 합니다. 지나치게 무료 자원을 이용하려 하면 속도 제한이나 계정 정지를 당할 수도 있습니다. 최적화의 목적은 편법이 아니라 자원을 더 효율적으로 쓰는 것입니다.
할당량이 부족하다면 다음 순서로 진행해 보세요.
1) Workers Analytics를 열어 어느 경로가 할당량을 많이 소모하는지 확인합니다.
2) 효과가 가장 빠른 캐시와 KV부터 최적화합니다.
3) 하위 요청, KV cacheTtl, 리디렉션 체인이라는 세 가지 함정에 빠졌는지 확인합니다.
4) 앞의 7가지 방법을 모두 조합해 적용합니다.
5) 최대한 최적화해도 부족하면 유료 플랜을 검토합니다.
2분 읽기 · 게시일: 2025년 12월 1일 · 수정일: 2026년 9월 4일
Cloudflare 풀스택
검색으로 들어왔다면 같은 시리즈의 이전 글이나 다음 글로 이동하는 것이 가장 빠릅니다.
이전
프런트엔드에 노출된 API Key 도용 방지: Workers 프록시로 5분 만에 키 보호, 하루 10만 회 무료
프런트엔드에서 API를 직접 호출하면 키가 노출되어 무단 사용될 수 있습니다. Cloudflare Workers로 무료 API 프록시를 5분 만에 배포하고, API Key를 서버 측 환경 변수에 안전하게 보관하면서 CORS 문제까지 해결하는 방법을 설명합니다.
15편 중 12편
다음
Astro를 Cloudflare에 배포하는 방법: SSR 설정과 중국 내 접속 속도 3배 개선
Astro를 Cloudflare Pages에 배포하고 SSR 어댑터 세 모드를 설정하는 방법을 설명합니다. 최적 IP, CNAME, 회선별 DNS로 중국 내 지연 시간을 3배 줄이는 방법도 다룹니다.
15편 중 14편



댓글
GitHub로 로그인하여 댓글을 남기세요