소개
AI 애플리케이션에는 서로 다른 두 가지 트래픽 보호 기능이 필요합니다. **속도 제한 (rate limit)**은 일정 시간 동안의 요청 수를 계산해 갑작스러운 요청 폭주가 모델에 도달하기 전에 차단합니다. **비용 한도 (spend limit)**는 더 긴 시간 동안 예상 모델 비용을 추적해 예산을 보호합니다. 하나는 호출자가 작업을 얼마나 자주 보낼 수 있는지 제어하고, 다른 하나는 해당 작업에 사용할 수 있는 비용을 제어합니다.
이번 실습에서는 일회성 인증 AI Gateway 를 하나 생성합니다. 짧은 슬라이딩 윈도우에서 요청을 두 개만 허용하도록 설정하므로, 작은 요청 세 개로 불필요한 모델 트래픽을 만들지 않고 429 Too Many Requests 응답을 확인할 수 있습니다. 윈도우가 초기화되면 정상적인 추론이 다시 가능해지는 것도 확인합니다. 또한 Workers AI 와 선택한 모델에 범위를 지정한 5 달러 일일 비용 규칙을 추가합니다. 예산을 소진하지 않고 저장된 규칙을 조회합니다.
이 과정을 직접 시작했다면 먼저 LabEx 를 Cloudflare 계정에 연결을 완료합니다. 이 실습에서는 LabEx 터미널, Wrangler 디바이스 인증 및 계정 ID 를 소개합니다. 또한 게이트웨이를 통한 추론 라우팅을 먼저 완료해야 합니다. 이번 실습에서는 해당 실습에서 사용한 별도의 게이트웨이와 업스트림 인증 경계를 재사용하기 때문입니다.
이번 실습에서는 Cloudflare 에서 호스팅하는 @cf/meta/llama-3.3-70b-instruct-fp8-fast 모델과 Standard Workers AI 결제를 사용합니다. Workers Paid, Unified Billing 및 외부 제공업체 인증 정보는 필요하지 않습니다. 모델에 도달하는 요청은 작은 요청 세 개뿐이어야 합니다. 공유된 일일 Workers AI 할당량을 사용할 수 없으면 반복해서 재시도하지 말고 중단합니다.
설정 과정에서는 Node.js 22.22.0 과 프로젝트 로컬 Wrangler 4.132.0 을 /home/labex/project/ai-gateway-limits에 설치합니다. 읽기 전용 확인 작업을 독립적으로 준비하지만, Wrangler 인증, 게이트웨이 생성, 토큰 생성 또는 모델 트래픽 전송은 수행하지 않습니다. 실습이 끝나면 LabEx 가 VM 을 삭제하지만, VM 삭제만으로 원격 리소스를 제거할 수 없으므로 클라우드 게이트웨이와 토큰은 직접 삭제해야 합니다.
VM 인증 및 실험 이름 지정
이번 단계에서는 새 VM 을 학습 계정에 연결하고, 직접 만든 리소스에 사용할 고유한 이름을 기록합니다.
각 LabEx 실습은 새 VM 에서 시작합니다. 이 VM 을 인증하면 Wrangler 가 학습 계정에서 Workers AI 를 호출할 수 있지만, 아직 게이트웨이는 생성되지 않습니다.
준비된 프로젝트로 이동해 고정된 CLI 버전을 확인하고 디바이스 인증을 시작합니다.
cd /home/labex/project/ai-gateway-limits
npx wrangler --version
npx wrangler login --device --browser=false --scopes account:read user:read ai:write
표시된 링크를 열고 코드를 입력한 다음, 사용할 학습 계정을 인증합니다. 그런 다음 구조화된 ID 데이터를 확인합니다.
npx wrangler whoami --json
Wrangler 4.132.0 과 loggedIn: true가 표시되어야 합니다. 사용할 계정에 표시된 실제 32 자리 ID 로 YOUR_ACCOUNT_ID를 바꿉니다.
GATEWAY_ID="labex-c09-g04-$(openssl rand -hex 6)"
TOKEN_NAME="$GATEWAY_ID-token"
cat > .labex/state.json <<JSON
{
"accountId": "YOUR_ACCOUNT_ID",
"gatewayId": "$GATEWAY_ID",
"tokenName": "$TOKEN_NAME"
}
JSON
cat .labex/state.json
이 식별자는 비밀 정보가 아닙니다. 저장해 두면 이후의 모든 조회와 정리 작업이 이번 실습에서 만든 일회성 리소스만 대상으로 수행됩니다.
짧은 요청 한도로 게이트웨이 생성
이번 단계에서는 요청 폭주를 안전하게 확인할 수 있도록 게이트웨이 전체에 적용되는 요청 카운터를 구성합니다.
요청 속도 제한은 특정 시간 윈도우 안에서 요청 수를 세는 카운터입니다. 이번 실습에서는 sliding 윈도우를 사용합니다. 즉, 어느 시점에서든 AI Gateway 는 직전 20 초를 확인합니다. 해당 구간에 요청이 두 개 있으면 다음 요청은 Workers AI 에 도달하기 전에 HTTP 429로 거부됩니다.
Cloudflare Dashboard 를 열고 AI → AI Gateway → Create a custom gateway를 선택합니다. 저장한 gatewayId를 사용합니다. Collect Logs와 Authenticated Gateway는 활성화된 상태로 둡니다. Rate Limit Requests를 켜고 Change를 선택한 다음 다음과 같이 설정합니다.
- limit:
2requests; - interval:
20seconds; - technique:
sliding.
캐싱과 재시도는 끈 상태로 둡니다. Workers AI 결제는 Standard로 유지한 다음 게이트웨이를 생성합니다. 요청 정책을 먼저 생성하면 별도의 비용 정책을 추가하기 전에 안정적인 리소스를 확보할 수 있습니다.
범위가 지정된 비용 한도 추가 및 조회
이번 단계에서는 같은 게이트웨이에 비용 예산을 추가하고, 어떤 요청이 이 예산에 포함되는지 정확히 제한합니다.
비용 한도는 요청 카운터가 아니라 예산입니다. AI Gateway 는 모델 가격과 사용량을 기준으로 각 완료된 요청의 비용을 추정한 다음, 일치하는 규칙에 비용을 더합니다. 이 추정은 최종 일관성 방식으로 반영되므로 동시 요청이 일시적으로 예산을 초과할 수 있습니다. 비용 규칙이 있어도 속도 제한은 여전히 유용합니다.
새 게이트웨이의 Settings 탭을 엽니다. Spend Limits를 활성화하고 Add rule을 선택한 다음 규칙 하나를 구성합니다.
- cost limit:
$5; - window:
1 day; - technique:
Sliding; - provider filter:
workers-ai; - model filter:
meta/llama-3.3-70b-instruct-fp8-fast.
규칙을 저장한 다음 두 제어 기능을 모두 확인합니다. 제공업체가 이미 별도로 선택되어 있으므로 모델 필드는 author/model 형식을 사용합니다. 이후 추론 URL 에서는 여전히 @cf/로 시작하는 전체 Workers AI 이름을 사용합니다.

제공업체와 모델 필터를 사용하면 게이트웨이의 관련 없는 트래픽까지 포함하는 하나의 공용 예산이 아니라, 이 요청에만 적용되는 좁은 범위의 규칙을 만들 수 있습니다. 이 작은 실습에서 5 달러는 의도적으로 충분히 큰 금액입니다. 예산을 소진하지 않고 정책만 확인합니다.
My Profile → API Tokens를 열고 Create Token → Create Custom Token을 선택한 다음 저장한 tokenName을 사용합니다. 계정 권한 두 개, AI Gateway — Edit와 AI Gateway — Run을 추가하고 사용할 학습 계정만 포함합니다. Edit는 실습에서 정확한 게이트웨이를 조회하고 나중에 삭제할 수 있도록 하며, Run은 추론 트래픽을 인증합니다. 별도의 업스트림 Workers AI 인증 정보는 Wrangler 가 제공합니다.
요약을 확인한 다음 토큰을 생성합니다. Cloudflare 는 토큰을 검증하는 명령 안에 토큰을 한 번만 표시합니다. 주변의 curl 명령은 복사하지 말고 Bearer 뒤의 토큰 값만 복사한 다음, 입력 내용을 화면에 표시하지 않는 방식으로 저장합니다.
bash -c '
while :; do
read -ersp "Paste the AI Gateway token: " GATEWAY_TOKEN
printf "\n"
[ -n "$GATEWAY_TOKEN" ] && break
printf "Token cannot be empty; paste it again.\n" >&2
done
umask 077
printf "%s" "$GATEWAY_TOKEN" > .labex/gateway-token
unset GATEWAY_TOKEN
chmod 600 .labex/gateway-token
'
관리 API 를 통해 중요한 비밀 정보가 아닌 필드를 조회합니다.
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
> .labex/gateway.json
unset GATEWAY_TOKEN
node - <<'NODE'
const b=require('./.labex/gateway.json'), g=b.result||{}, spend=g.spend_limits||{};
console.log(JSON.stringify({
success:b.success,
id:g.id,
rate:{limit:g.rate_limiting_limit,interval:g.rate_limiting_interval,technique:g.rate_limiting_technique},
spend_limits:{enabled:spend.enabled,rules:spend.rules}
},null,2));
NODE
2 개 요청, 20 초 슬라이딩 속도 규칙과 제공업체 및 모델 필터가 설정된 활성화된 5 달러 일일 비용 규칙 하나가 표시되어야 합니다. 이 조회 결과는 구성이 저장되었음을 증명하지만, 예산이 사용되었다는 의미는 아닙니다.
세 번의 호출로 요청 거부 확인
이번 단계에서는 작은 요청 세 개를 사용해 큰 폭주 트래픽을 만들지 않고 요청 수 정책을 확인합니다.
이제 아주 작은 요청을 세 번 순서대로 전송합니다. 처음 두 요청은 허용되고, 세 번째 요청은 429를 받아 모델에 도달하지 않아야 합니다. 이는 큰 트래픽 폭주를 생성하는 것보다 안전하고 비용도 적게 듭니다.
업스트림 Workers AI 인증에 사용할 이 VM 의 단기 Wrangler 토큰을 안전하게 저장합니다.
umask 077
npx wrangler auth token --json \
| node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).token))' \
> .labex/upstream-token
chmod 600 .labex/upstream-token
세 번 호출합니다. 각 요청에는 로그에서 쉽게 식별할 수 있도록 가상의 메타데이터가 포함됩니다. 비용 규칙 자체는 Workers AI 제공업체와 모델 필터를 통해 이 요청에 적용됩니다.
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
MODEL='@cf/meta/llama-3.3-70b-instruct-fp8-fast'
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
for NUMBER in 1 2 3; do
METADATA=$(printf '{"lab":"g04-limits","request":"burst-%s","synthetic":true}' "$NUMBER")
STATUS=$(curl --http1.1 -sS \
-o ".labex/burst-$NUMBER-response.json" -w '%{http_code}' \
-H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
-H "Authorization: Bearer $UPSTREAM_TOKEN" \
-H "cf-aig-metadata: $METADATA" \
-H 'Content-Type: application/json' \
--data "{\"prompt\":\"Reply with the number $NUMBER.\",\"max_tokens\":4}" \
"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
printf '%s\n' "$STATUS" | tee ".labex/burst-$NUMBER-status.txt"
done
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA
다음 결과가 표시되어야 합니다.
200
200
429
429는 보호 기능이 정상적으로 작동했다는 결과입니다. 요청이 게이트웨이에서 중지되었으므로 추가 모델 추론을 소비하지 않았고 비용 카운터에도 반영되지 않았다는 뜻입니다.
슬라이딩 윈도우 초기화 후 복구 확인
이번 단계에서는 짧은 윈도우가 초기화될 때까지 기다린 다음 게이트웨이가 정상적인 추론을 다시 허용하는지 확인합니다.
속도 제한은 애플리케이션을 영구적으로 중지하지 않고 요청 폭주를 보호해야 합니다. 20 초 윈도우보다 조금 더 오래 기다린 다음 작은 요청을 하나 더 전송합니다.
sleep 22
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
MODEL='@cf/meta/llama-3.3-70b-instruct-fp8-fast'
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
STATUS=$(curl --http1.1 -sS \
-o .labex/recovery-response.json -w '%{http_code}' \
-H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
-H "Authorization: Bearer $UPSTREAM_TOKEN" \
-H 'cf-aig-metadata: {"lab":"g04-limits","request":"recovery","synthetic":true}' \
-H 'Content-Type: application/json' \
--data '{"prompt":"Reply only with recovered.","max_tokens":4}' \
"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN
printf '%s\n' "$STATUS" | tee .labex/recovery-status.txt
node -e 'const b=require("./.labex/recovery-response.json"); console.log(b.result?.response ?? b.result)'
HTTP 200과 짧은 생성 응답이 표시되어야 합니다. 복구가 확인되면 429가 잘못된 인증 정보나 고장 난 모델 때문이 아니라 구성된 시간 윈도우 때문에 발생했다는 뜻입니다.
정책과 Dashboard 증거 연결
이번 단계에서는 API 와 HTTP 결과를 Dashboard 에서 보이는 제어 설정 및 로그와 연결합니다.
AI → AI Gateway로 돌아가 저장한 게이트웨이를 선택한 다음 Settings를 엽니다. 속도 제한이 여전히 2 개 요청, 20 초 및 sliding 방식으로 표시되는지 확인합니다. Spend Limits에서 규칙 하나를 확인하고 5 달러 비용, 1 일 슬라이딩 윈도우, 제공업체 및 모델 필터가 설정되어 있는지 확인합니다.

그런 다음 Logs를 엽니다. 초기 성공 요청 두 개와 복구 요청은 일반적인 로그 전파가 완료된 후 표시되어야 합니다. 세 번째 거부 요청은 제공업체 추론 전에 중지되었으므로 다르게 표시될 수 있습니다. 저장된 HTTP 상태가 속도 제한을 확인하는 권위 있는 증거입니다.

다음 작업은 필요하지 않다는 점에 유의합니다. 5 달러를 실제로 사용하거나, 규칙을 위험할 정도로 작은 값으로 낮추거나, 비용 거부가 발생할 때까지 반복할 필요가 없습니다. 관리 API 조회 결과는 비용 정책의 범위를 증명하고, 세 번의 호출 실험은 요청 수 제한이 적용되었음을 별도로 증명합니다.
일회성 게이트웨이 삭제
이번 단계에서는 실습 인벤토리에 기록된 이름의 게이트웨이만 삭제하고, 인증이 유지되는 동안 해당 게이트웨이가 사라졌는지 확인합니다.
관리 토큰으로 정확한 리소스가 삭제되었음을 확인할 수 있는 동안 게이트웨이를 삭제합니다.
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -X DELETE \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
| node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const b=JSON.parse(s);if(!b.success)process.exit(1);console.log("gateway deletion accepted")})'
unset GATEWAY_TOKEN
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways" \
> .labex/gateways-after-delete.json
unset GATEWAY_TOKEN
node -e 'const b=require("./.labex/gateways-after-delete.json"),id=process.argv[1],found=(b.result||[]).some(g=>g.id===id);console.log("gateway absent:",!found);if(found)process.exit(1)' "$GATEWAY_ID"
gateway absent: true가 표시되어야 합니다. 인증된 인벤토리 조회를 사용하면 네트워크 오류나 더 이상 접근할 수 없는 페이지를 실제 삭제와 구분할 수 있습니다.
토큰 폐기 및 로그아웃
이번 단계에서는 남아 있는 Dashboard 토큰을 폐기하고, VM 에 저장된 두 토큰 복사본을 삭제한 다음 Wrangler 연결을 해제합니다.
Cloudflare Dashboard 에서 My Profile → API Tokens를 엽니다. 저장한 정확한 tokenName을 찾아 Actions를 열고 Delete를 선택합니다. 확인 내용을 검토한 다음 해당 토큰만 삭제합니다. 게이트웨이 삭제가 이미 확인되었으므로 이제 토큰을 폐기해도 안전합니다.
두 개의 임시 토큰 복사본을 삭제하고 Wrangler 연결을 해제합니다.
shred -u .labex/gateway-token .labex/upstream-token
npx wrangler logout
npx wrangler whoami --json || true
test ! -e .labex/gateway-token -a ! -e .labex/upstream-token \
&& echo "local token files removed"
loggedIn: false와 local token files removed가 표시되어야 합니다. Dashboard 세션은 별도로 유지되므로 Dashboard 에는 계속 로그인된 상태입니다. 실습이 끝나면 LabEx 가 이 임시 VM 을 보존하지 않고 삭제합니다.
요약
서로 보완되는 두 가지 AI Gateway 제어 기능을 적용했습니다. 2 개 요청 슬라이딩 윈도우는 적은 양의 세 번째 요청을 HTTP 429로 거부한 다음, 윈도우가 초기화되자 트래픽을 자동으로 다시 허용했습니다. 별도의 5 달러 일일 비용 규칙은 Workers AI 와 하나의 모델에 범위를 지정했으며, 모델 사용량을 낭비하지 않고 저장된 구성을 확인했습니다.
다음 실습에서는 또 다른 게이트웨이 안정성 제어 기능인 제한된 폴백을 사용합니다. 정상적인 기본 모델 요청은 첫 단계에서 완료되는 동안, 제어된 기본 모델 오류 하나를 호환되는 두 번째 모델로 라우팅합니다.



