본문으로 건너뛰기
6분 읽기

Vercel Blob WAF: Traffic 통제, Private Storage와 안전한 Rollout

공개 Blob traffic은 공유 WAF rule로 보호하고 사용자별 접근은 Private Blob으로 분리한 뒤 deny, rate limit, challenge를 client 장애 없이 배포하는 방법을 설명합니다.

Vercel WAF는 이제 운영 환경의 Blob store를 보호할 수 있지만, 공개 object를 private으로 바꾸지는 않습니다. WAF는 traffic이 공개 URL에 도달할 수 있는지 판단합니다. Private Blob과 애플리케이션은 특정 사용자가 파일을 읽을 수 있는지 판단합니다.

Vercel은 2026년 7월 24일 beta로 출시한 WAF for Blob을 8월 3일 정식 제공으로 전환했습니다. Beta의 rule과 설정은 변경 없이 이어집니다. 공개 object traffic 정책에는 WAF를, 데이터 권한에는 Private Blob을 사용하세요.

데이터 요구사항에 맞는 통제를 선택합니다

Public Blob URL은 URL을 아는 누구나 읽을 수 있습니다. WAF rule은 IP address, country, path 같은 속성을 검사할 수 있지만, 애플리케이션 사용자 한 명이 파일을 소유하고 다른 사용자는 소유하지 않는다는 사실은 알지 못합니다.

요구사항적절한 통제
공개 media의 scraper 또는 hotlink traffic 완화Public Blob + WAF
공개 release의 반복 download 제한Public Blob + WAF rate limit
선택한 traffic 지역에서 공개 object 차단Public Blob + WAF deny
인증된 사용자만 파일 열람Private Blob + route 권한 검사
사용자 A가 사용자 B의 object를 읽지 못하게 함Private Blob + ownership 검사
Invoice, 계약서, 개인정보 저장Private Blob

WAF와 private storage는 모두 보안을 높일 수 있지만 서로 다른 identity를 강제합니다. IP, country, path 또는 browser challenge는 애플리케이션의 인증된 주체를 대신하지 못합니다.

WAF action의 경계를 이해합니다

Blob 보호는 application proxy를 추가하는 대신 store를 Vercel firewall에 연결합니다. 기존 Blob URL과 @vercel/blob 코드는 바뀌지 않습니다.

Action결과적합한 사용
Deny403을 반환하고 요청 중단알려진 abuse source 또는 허용하지 않는 지역
ChallengeBrowser challenge 요구사람이 사용하는 공개 download 경로
Rate limit설정 rate 초과 시 429반복적인 공개 download와 scraping
Log차단 없이 관측Baseline과 rule 검증
Redirect다른 위치로 이동폐기된 공개 asset 경로

Vercel에 따르면 deny된 요청은 data transfer 전에 edge에서 거부되므로 그 요청에는 Blob data-transfer 비용이 발생하지 않습니다. 그렇다고 모든 deny rule이 경제적인 것은 아닙니다. False positive는 정상 download를 깨뜨릴 수 있습니다.

Blob 연동은 OWASP Core Ruleset을 지원하지 않습니다. 해당 managed rule은 동적 request 공격을 다루지만 Blob delivery는 저장된 object를 제공합니다.

하나의 공유 Rule set을 고려합니다

Blob store의 Settings 페이지에서 Firewall section의 보호를 활성화합니다. Vercel은 store를 Blob firewall rule이 저장되는 team-wide 전용 project에 연결합니다.

Team에서 보호되는 모든 store는 이 rule set을 공유합니다. 따라서 path 설계가 control plane의 일부가 됩니다.

/public-images/...
/public-downloads/...
/release-artifacts/...
/marketing-video/...

Rule을 추가하기 전에 일치할 수 있는 모든 보호 store와 prefix를 inventory로 만드세요.

# Vercel 설정 문법이 아닌 governance inventory입니다.
stores:
  marketing-assets:
    prefixes:
      - /public-images/
      - /marketing-video/
  product-downloads:
    prefixes:
      - /public-downloads/
      - /release-artifacts/

두 팀이 겹치는 path를 사용하면 한 store를 위한 rule이 다른 store에도 영향을 줄 수 있습니다. Shared project에 owner, reviewer, rollback 기록과 naming convention을 둡니다.

관측부터 시작합니다

Deny나 challenge를 즉시 적용하면 고객, search crawler, social preview, server rendering, image optimization을 차단할 수 있습니다. Log로 시작해 평상시와 peak 기간을 포함한 대표 traffic을 수집하세요.

다음을 확인합니다.

  • Path와 file type
  • IP, country, user agent
  • Request rate와 burst 크기
  • Cache hit와 miss 동작
  • Transfer가 큰 object
  • 정상 bot과 machine client

그다음 enforcement를 하나의 prefix와 client behavior로 좁힙니다. 확대하기 전에 403, 429, challenge 성공, download completion과 support report를 측정하세요.

Client 동작에 맞춰 Rate limit을 정합니다

Thumbnail과 수 GB 크기의 release에 같은 traffic 기대값을 적용하면 안 됩니다.

/public-images/thumbnails/*
└─ 더 높은 request rate; 한 page가 여러 object를 가져올 수 있음

/public-downloads/releases/*
└─ 더 낮은 request rate; 성공한 요청 하나가 더 많은 data를 전송할 수 있음

/marketing-video/previews/*
└─ range request, reconnect, 여러 rendition 고려

IP만 기준으로 제한하면 office, school, mobile carrier 또는 corporate NAT를 하나의 client로 묶을 수 있습니다. 임계값을 정하기 전에 IP당 정상 사용자, browser concurrency, range request, retry와 resume 동작을 검토하세요.

Machine client를 Browser challenge에서 제외합니다

Browser challenge는 interactive browser를 위한 기능입니다. Server-side fetch, build job, webhook consumer, CLI 또는 image pipeline은 이를 풀지 못할 수 있습니다.

명시적인 호환성 테스트 없이 다음 경로에 Challenge를 적용하지 마세요.

  • Server가 fetch하는 Blob object
  • Build-time asset
  • Webhook이 소비하는 파일
  • 자동화가 download하는 release artifact
  • Optimization service가 가져오는 source image

비-browser traffic에는 Log, 좁은 deny 조건 또는 rate limit을 사용하세요. Challenge는 사람이 browser로 여는 공개 경로로 제한합니다.

민감한 데이터는 Private Blob에 둡니다

Blob store의 public/private access mode는 store를 만들 때 선택합니다. 공개 URL 주변에 복잡한 WAF rule을 쌓는 대신 데이터 민감도에 따라 store를 분리하세요.

public-assets
├─ 제품 이미지
├─ 공개 영상
└─ release download

private-user-files
├─ 사용자 upload
├─ invoice와 계약서
└─ 내부 보고서

Private Blob은 인증된 read를 요구합니다. 데이터 접근이 멀리 떨어진 middleware에만 의존하지 않도록 get() 호출 옆에서 권한을 검사하세요.

import { get } from '@vercel/blob';
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  const user = await requireUser(request);
  const pathname = new URL(request.url).searchParams.get('pathname');

  if (!pathname) {
    return new Response('Missing pathname', { status: 400 });
  }

  await assertCanReadBlob(user.id, pathname);

  const result = await get(pathname, { access: 'private' });

  if (!result || result.statusCode !== 200) {
    return new Response('Not found', { status: 404 });
  }

  return new NextResponse(result.stream, {
    headers: {
      'Content-Type': result.blob.contentType,
      'X-Content-Type-Options': 'nosniff',
      'Cache-Control': 'private, no-store',
    },
  });
}

requireUserassertCanReadBlob은 애플리케이션 함수입니다. 이 예제는 Vercel의 현재 Private Blob delivery 형태에 맞춰 검토했으며 store credential로 실행하지 않았습니다.

민감도가 낮은 private content에는 Vercel이 ETag revalidation과 private, no-cache를 문서화합니다. Token, banking data 또는 개인정보에는 private, no-store를 안내합니다.

Rule을 통제된 변경으로 Rollout합니다

Shared-rule 제약을 변경 검토 절차로 만드세요.

  1. 현재 rule과 영향받는 prefix inventory를 저장합니다.
  2. 새 조건을 Log로 추가합니다.
  3. 정상, peak, bot, machine-client traffic을 비교합니다.
  4. 하나의 좁은 prefix에 deny 또는 rate limit을 적용합니다.
  5. 차단 traffic, transfer와 정상 사용자 성공을 함께 봅니다.
  6. Rollback owner가 근거를 승인한 뒤에만 확대합니다.

Rule은 code deployment 없이 적용됩니다. 대응 시간은 짧아지지만 repository diff 없이 firewall 변경이 여러 store를 깨뜨릴 수도 있습니다.

보호 효과와 사용자 성공을 함께 측정합니다

최소한 다음을 추적합니다.

  • Prefix별 request와 Blob data transfer
  • 403429 비율
  • Challenge 시도와 실패
  • Cache miss와 Simple Operations
  • 상위 IP, country, user agent
  • Download completion과 broken-asset 비율
  • 각 rule 변경 뒤 고객 문의

Traffic을 줄이면서 정상 download를 반복해서 깨뜨리는 rule은 성공한 통제가 아닙니다.

권고

광범위한 URL 접근이 허용될 때만 public media를 공개로 유지하세요. WAF rule은 Log로 도입한 뒤 prefix와 관측한 behavior에 따라 deny 또는 rate limit을 좁게 적용합니다. Challenge는 browser가 사용하는 경로에만 두고, team-wide 공유 rule set을 production infrastructure처럼 관리하세요.

접근이 사용자 identity나 ownership에 달렸다면 공개 traffic rule 조정을 멈추고 delivery 시점의 authorization 검사와 Private Blob을 사용해야 합니다.

공식 자료