요금 폭탄 막기
내 웹사이트에 사람이 많이 들어올수록 요금이 오릅니다. 트래픽이 곧 돈이거든요. 문제는 두 가지 — 평상시 조금씩 새는 '누수'(주범은 큰 이미지)와, 어느 날 갑자기 터지는 '폭탄'(봇 공격). 원인은 다르지만 청구서에는 똑같이 찍혀요. 둘 다 막는 법을 다룹니다.

실제로 있었던 일 — 하루아침에 $100 넘게 청구
먼저 확인 — 내 Vercel 플랜이 Hobby(무료)인가요, Pro인가요?
Hobby(무료)는 무료 한도를 넘겨도 요금이 청구되지 않아요. 대신 프로젝트가 일시정지돼요(보통 최대 30일). 그래서 ‘청구서 폭탄’은 못 맞지만, 사이트가 한동안 멈출 수는 있어요.
Pro(월 $20/명, 사용 크레딧 $20 포함)는 한도를 넘으면 종량제로 요금이 붙어요.결제 상한(Spend Management)도 Pro에서만 쓸 수 있고요. 아래에서 플랜별로 나눠서 알려드릴게요.
요금이 오르는 두 가지 길
평상시 느린 누수
정상 방문자 × 큰 이미지 = 대역폭이 서서히 쌓임. 대응: 효율화(압축·리사이즈·next/image·CDN)
갑작스런 폭탄
봇의 비정상 트래픽이 순식간에 폭증. 대응: 방어(봇 차단·rate limit) + 회로차단(한도·상한)
연결 지점: 이미지가 최적화 안 돼 있으면, 봇 공격 때 폭탄(Hobby는 일시정지, Pro는 청구액)이 더 커집니다. 그래서 둘 다 챙겨야 해요.
평상시 새는 비용 — 이미지·대역폭
큰 이미지가 요금의 숨은 주범
왜 이미지가 돈이 되나요
방문자가 페이지를 열 때마다, 거기 있는 이미지 파일이 그 사람 기기로 전송돼요. 이 전송량(대역폭)에 요금이 붙습니다. 이미지 하나가 5MB인데 하루 1,000명이 보면 5GB가 나가는 거예요. 폰으로 찍은 원본을 그대로 올리면 이게 계속 쌓입니다.
이 강의 사이트를 점검해 봤더니
고치는 순서 — 위에서부터가 효과 큼
1. 리사이즈 — 표시 크기에 맞게 줄이기 (효과 가장 큼)
4000px 원본을 400px 자리에 넣지 않는다. 비용의 90%가 여기서 새요. 압축 품질 조절보다 이게 먼저.
2. 포맷 바꾸기 — PNG/JPEG → WebP/AVIF
같은 화질에 30~50% 작아져요. 사진·스크린샷에 특히 효과적.
3. next/image로 자동화 (Vercel/Next 사이트의 정답)
이 컴포넌트 하나면 리사이즈 + WebP/AVIF 변환 + 기기별 크기 + lazy load(스크롤 전엔 안 받기) + 엣지 캐시를 자동으로 해줍니다.
4. (대부분 여기까진 안 가도 됨) 이미지가 수백~수천 장이면 — Cloudflare
‘또 다른 CDN’이 아니라 대역폭 요금을 아끼는 우회로예요. Vercel은 전송량에 요금이 붙지만 Cloudflare 저장소 R2는 전송량(egress)이 무료라, 미디어가 아주 많아 Vercel 대역폭 요금이 실제로 아플 때만 이미지 저장·배달을 R2로 분리해요. 1~3번이면 대부분 충분합니다.
'CDN 따로 붙이기'는 필요 없어요 — 단, 두 가지를 구분하세요
① 엣지 네트워크(CDN)는 자동입니다.Vercel에 배포하면 정적 파일이 전 세계 엣지에서 서빙돼요. 흔히 헷갈리는 “엣지 서버를 따로 켠다”는 보통 Edge Functions(코드를 엣지에서 실행) 얘기인데, 그건 별개의 선택 기능이에요 — 이미지 캐시와는 다른 층입니다.
② 그런데 캐시 ‘강도’는 파일마다 달라요. next/image가 만드는 최적화 이미지(_next/image)는 1년 immutable로 강하게 캐시되지만, public 폴더에 넣고 그냥 <img>로 부른 이미지는 기본이 max-age=0, must-revalidate라 브라우저가 매번 다시 확인해요.
실제로 이 사이트의 terminal.webp도 지금 그 상태였어요(CDN 위엔 있지만 캐시가 약함). 그래서 결론은 같습니다 — 원본을 작게 만들고 next/image로 넘기면 최적화 + 강한 캐시가 한 번에 붙어요.
이 프로젝트 이미지 비용을 줄여줘. 1. public 폴더에서 큰 이미지(500KB 이상)를 찾아 목록으로 보여줘. 2. PNG/JPEG를 WebP로 변환하고, 표시 크기에 맞게 리사이즈해줘. 3. <img> 태그를 Next.js의 next/image 컴포넌트로 바꿔서 자동 최적화·lazy load가 되게 해줘. 바꾸기 전에 무엇을 어떻게 바꿀지 먼저 요약해서 보여줘.
함정 — Vercel 이미지 최적화도 종량제예요
올리기 전 직접 압축: squoosh.app · tinypng.com
갑자기 터지는 폭탄 — 봇 공격
원인 줄이기 + 회로차단, 두 겹으로
봇이 왜 요금 폭탄이 되나요
봇은 사람과 달리 초당 수백~수천 번 요청을 자동으로 날려요. 그때마다 내 사이트의 함수가 실행되고, 이미지가 변환되고, DB가 조회되고, 대역폭이 나갑니다 — 전부 종량제죠. 특히 AI 호출·로그인·결제 같은 ‘비싼’ 엔드포인트를 봇이 반복해서 때리면, 요금이 순식간에 폭발해요. 방어는 세 겹으로 합니다.
1겹 — 봇 차단 (Vercel BotID)
보이지 않는 봇 감지. 비싼 엔드포인트(API·로그인·AI 호출) 앞에 세워서, 봇으로 판별되면 막아요. 코드에 심는 방식이라 AI가 해줍니다. 기본(Basic) 보호는 모든 플랜에서 무료예요. 더 정교한 Deep Analysis는 Pro 전용이고 1,000번 검사에 $1이에요.
2겹 — 요청 제한 (Rate limit)
같은 IP가 짧은 시간에 너무 많이 요청하면 잠시 차단. Vercel 프로젝트 왼쪽 메뉴의 Firewall에서 규칙을 만들거나, 코드에서 @vercel/firewall로 걸어요. Hobby는 프로젝트당 규칙 1개까지 만들 수 있어요.
3겹 — 한도 걸기 (회로차단, 가장 중요)
앞의 방어를 뚫려도 여기서 끊겨요. Hobby는 무료 한도를 넘으면 청구 없이 프로젝트가 일시정지돼요. Pro는 정해둔 금액을 넘으면 프로젝트를 자동으로 멈추게 설정할 수 있어요.
Pro라면 꼭 알아야 할 함정 — 금액만 설정하면 '안 멈춥니다'
Hobby(무료)는 어떻게 되나요

봇 차단(BotID)은 어떻게 작동하나요
import { checkBotId } from "botid/server";
export async function POST(req: Request) {
const verification = await checkBotId();
if (verification.isBot) {
return new Response("봇 요청 차단", { status: 403 });
}
// 사람 요청만 여기로 — 결제/AI 호출 등 비싼 작업 실행
}설정은 세 곳 — ① next.config를 withBotId로 감싸고 ② 보호할 경로를 클라이언트에서 initBotId로 등록 ③ 서버에서 checkBotId() 호출. 이 배선을 AI가 해줍니다.
AI에게 이렇게 시키면 됩니다
“봇 차단해줘” 한마디면, AI가 BotID를 코드에 심고, rate limit을 걸고, 결제 상한 설정 위치까지 안내해줘요. (BotID·rate limit은 주로 코드 작업, 결제 상한은 Pro에서 Vercel 대시보드로 — AI가 어디를 눌러야 하는지 짚어줍니다.)
봇 공격으로 요금 폭탄이 날까 걱정돼. 아래를 다 설정해줘: 1. Vercel BotID를 붙여서, 비싼 엔드포인트(로그인·AI 호출·결제·폼 제출)를 봇에게서 보호해줘. - next.config를 withBotId로 감싸고, 보호할 경로를 initBotId로 등록하고, 각 route에서 checkBotId()로 봇이면 403 처리. 2. 같은 IP의 과도한 반복 요청을 막게 @vercel/firewall로 rate limit을 걸어줘. 3. 내 Vercel 플랜(Hobby/Pro)에 맞는 요금 방어 방법을 알려줘. Pro라면 Spend Management(Team Settings → Billing)에서 "Pause Production Deployments" 옵션을 켜는 위치를 정확히 짚어줘. CLI나 API로 할 수 있는 건 명령어까지 적어주고, 대시보드에서 해야 하는 건 클릭 순서로 알려줘.
AI API 요금 한도도 걸어두기
AI 호출 요금은 Vercel이 아니라 Anthropic에서 청구돼요
봇이 내 사이트의 AI 엔드포인트를 계속 두들기면, 그 요청마다 Anthropic API가 호출돼요. 이때 청구서는 Vercel이 아니라 Anthropic에서 나옵니다. Vercel을 아무리 막아도 이쪽은 따로 챙겨야 해요.
Anthropic Console(platform.claude.com)에서 Settings → Limits로 들어가 월 사용 한도(monthly spend limit)를 걸어두세요. 한 달에 쓸 수 있는 최대 금액을 정해두면, 그 이상은 API가 알아서 막혀요.
한도는 ‘내가 감당할 수 있는 금액’으로 낮게 잡으세요. 필요하면 나중에 올리면 돼요. API 키가 유출됐을 때도 이 한도가 피해를 막아줍니다.
“한 달에 이 금액 이상은 안 쓴다”는 한도를 미리 정해두세요. 봇을 막고 이미지를 줄여둬도, 생각지 못한 이유로 요금이 갑자기 크게 나올 수 있어요. 한도를 정해두면 그 금액을 넘는 순간 자동으로 멈추기 때문에, 요금이 더 나가지 않아요.
한도는 두 군데에 걸어요.
- ① Vercel (사이트를 올려둔 곳)
유료(Pro) 플랜이라면 Spend Management 메뉴에서 금액을 적고, ‘Pause Production Deployments’(금액을 넘으면 사이트 멈추기) 옵션도 켜야 해요. 금액만 적어두면 알림만 오고, 사이트는 멈추지 않아요.
무료(Hobby) 플랜이라면 따로 설정할 것이 없어요. 무료로 쓸 수 있는 양을 넘으면 돈이 청구되는 대신 사이트가 한동안(보통 최대 30일) 멈춘다는 것만 알아두세요. - ② Anthropic Console (AI 요금을 내는 곳)
Vercel 플랜과 상관없이, 여기서도 한 달에 쓸 최대 금액을 정해두세요. 그 금액을 넘으면 AI 호출이 자동으로 막혀요.
봇 때문에 요금이 갑자기 늘어나는 것은 세 단계로 막아요.
- ① 봇 차단(BotID): 사람이 아닌 프로그램이 접속하는 것을 처음부터 막아요.
- ② 접속 횟수 제한(rate limit): 한 곳에서 너무 자주 접속하면 잠시 막아요.
- ③ 금액 한도: Vercel과 Anthropic Console에 한 달 최대 금액을 정해두면, 그 금액을 넘는 순간 자동으로 멈춰요.
여기에 Part 1에서 배운 이미지 줄이기까지 해두면, 평소에 조금씩 새는 요금과 갑자기 크게 나오는 요금을 둘 다 막을 수 있어요.