Vercel 요금 절감: FastAPI 정적 파일이 Function을 건너뛴다

Vercel이 FastAPI의 app.frontend()와 StaticFiles 요청을 CDN에서 직접 처리하기 시작했습니다. Function 호출·컴퓨팅 사용량은 줄지만 CDN 요청과 전송량은 남습니다. 적용 조건, 보안 예외, 실제 Vercel 요금 절감 범위를 정리합니다.

Sunday, September 13, 2026Omid Saffari
Tools
Vercel 요금 절감: FastAPI 정적 파일이 Function을 건너뛴다

2026년 9월 10일, Vercel은 FastAPI 앱의 Vercel 요금 구조에서 한 항목을 바꿨습니다. 이제 적용 대상 프런트엔드 및 정적 파일 요청은 Vercel CDN에서 방문자에게 곧바로 전달되므로 Function 호출과 컴퓨팅 사용량이 발생하지 않습니다. 다만 CDN 요청과 전송량은 그대로 남습니다. 따라서 이번 변경은 정적 파일 전송을 무료로 만드는 것이 아니라 Function 사용량을 줄이는 조치입니다.

Vercel FastAPI 배포 후 요청이 Function을 건너뜁니다

정적 파일은 HTML 파일, 스타일시트, JavaScript 번들, 폰트, 이미지처럼 서버가 수정 없이 보낼 수 있는 파일입니다. Vercel Function은 동적 요청을 처리하기 위해 실행되는 FastAPI 프로세스입니다. CDN은 방문자 가까이에서 콘텐츠를 전달하는 계층입니다.

변경 전에는 FastAPI를 통해 마운트한 파일도 Function 경로를 거칠 수 있었습니다. 요청이 Vercel 네트워크에 도착하면 FastAPI Function을 호출하고, Python이 파일을 반환하는 방식이었습니다.

이제 Vercel은 빌드 과정에서 app.frontend()와 FastAPI의 StaticFiles 뒤에 있는 적용 대상 파일을 찾아냅니다. 해당 파일을 CDN으로 올리고, 일치하는 요청은 Function을 호출하지 않고 처리합니다.

요청 경로는 다음과 같이 바뀝니다.

visitor → CDN → FastAPI Function → file → visitor

에서

visitor → CDN file → visitor

로 짧아집니다.

동적 API까지 정적으로 바뀌는 것은 아닙니다. 조건에 맞는 파일만 이동합니다. 프로젝트 수준의 public/ 디렉터리에 둔 파일은 이미 CDN에서 제공되고 있었으므로, 모든 공개 에셋을 그곳에 둔 앱이라면 이번 릴리스로 새롭게 절감되는 사용량은 없습니다.

프로모션된 디렉터리도 기본적으로 Function 번들 안에 남습니다. tool.vercel.fastapi.static.exclude = true를 설정하면 중복 사본을 제거할 수 있지만, 이는 별도의 번들 구성 문제입니다. CDN 요청 경로를 활성화하기 위해 반드시 필요한 설정은 아닙니다.

공개 FastAPI 에셋은 방문자에서 CDN으로 이어지는 짧은 경로를 택하고, 보호된 에셋은 보안 검사를 거쳐 Function으로 전달되는 모습을 나타낸 아키텍처 단면도
공개 에셋은 CDN에서 처리를 끝낼 수 있습니다. 요청을 FastAPI에서 검사해야 하는 보호 에셋은 계속 Function을 거쳐야 합니다.

Vercel 요금에서 빠지는 것은 컴퓨팅이지 전송이 아닙니다

Vercel은 요청을 여러 계층으로 나눠 측정합니다. Function Invocations는 코드에 도달한 요청 수를 셉니다. Active CPU와 Provisioned Memory는 해당 호출에 사용된 연산 작업과 런타임 리소스를 측정합니다. Fast Origin Transfer는 CDN과 Function 사이에서 오간 트래픽을 측정합니다.

외부 전송 계층의 측정 항목은 다릅니다. 대시보드에서 Edge Requests로 표시되는 CDN Requests는 정적 에셋과 Function 트래픽에 모두 적용됩니다. Fast Data Transfer는 CDN에서 방문자에게 전송된 바이트를 측정합니다.

배포 전에는 Function에 도달했지만 배포 후에는 프로모션 조건을 충족하는, 그 밖의 조건이 동일한 에셋 요청 백만 건을 기준으로 장부를 정리하면 다음과 같습니다.

측정 항목프로모션 전프로모션 후
Function Invocations1 million0
해당 요청의 Active CPU측정됨0
해당 요청의 Provisioned Memory측정됨0
해당 응답의 Fast Origin Transfer측정됨0
CDN Requests 또는 Edge Requests1 million1 million
방문자 대상 Fast Data Transfer측정된 바이트측정된 바이트

공개된 Pro 요금은 Function 호출 백만 건당 $0.60입니다. 따라서 이전에는 Function에 도달했던 파일 요청 백만 건이 빠지면 월간 크레딧 적용 전 총 Function 호출 사용료에서 $0.60이 줄어듭니다. 여기에 해당 요청이 실제로 소비한 Active CPU, Provisioned Memory, Fast Origin Transfer도 함께 줄어듭니다.

나머지 절감액은 Usage 데이터로 계산해야 합니다. Python을 거의 거치지 않은 파일 응답이라면 줄어드는 CPU도 적습니다. 응답 파일이 크다면 줄어드는 origin transfer는 더 많을 수 있습니다. 이번 릴리스가 제공하는 것은 새로운 요청 경로이지, 모든 앱에 통용되는 절감률이 아닙니다.

장부 반대편에는 CDN 사용량이 그대로 남습니다. Vercel의 현재 CDN 요금 페이지에 따르면 온디맨드 청구를 사용하는 Pro에서는 최초 천만 건의 Edge Requests와 최초 1 TB의 Fast Data Transfer가 포함되고, 이후에는 지역별 사용 요금이 붙습니다. Flat Rate CDN을 쓰는 팀은 대신 해당 플랜의 요청 및 전송 용량을 소비합니다. 이 별도 예산 결정은 Flat Rate CDN 해설에서 다룹니다.

Hobby에서는 현금 청구액보다 여유 사용량이 늘어나는 효과가 클 수 있습니다. Hobby에는 Function 호출 백만 건, Active CPU 네 시간, Provisioned Memory 360 GB-hours가 포함됩니다. Function에 더 이상 도달하지 않는 공개 파일 트래픽은 이 한도를 소모하지 않지만, 해당되는 CDN 전송 사용량은 계속 집계됩니다.

FastAPI StaticFiles와 프런트엔드의 적용 여부는 라우트와 보안 규칙이 결정합니다

Vercel은 StaticFiles에 대해 FastAPI의 선언 순서를 유지합니다. 정적 마운트보다 먼저 선언한 라우트가 같은 경로에서 우선하며 Function으로 전달됩니다. 마운트 뒤에 선언한 라우트는 CDN 파일보다 우선하지 못합니다.

app.frontend()는 조금 다릅니다. API 라우트는 선언 순서와 관계없이 항상 프런트엔드 파일보다 우선합니다. 덕분에 /에 마운트한 프런트엔드가 실제 API 엔드포인트를 가로채지 않습니다.

보안 요건도 기본 동작을 바꿉니다. CDN 파일은 Python에 진입하지 않으므로 FastAPI 미들웨어와 Depends() 검사가 실행될 수 없습니다. 따라서 Vercel은 다음 경로를 기본적으로 Function에 남겨 둡니다.

  • 앱에 최상위 미들웨어가 있으면 모든 정적 마운트와 프런트엔드.
  • 하위 앱에 미들웨어가 있으면 해당 하위 앱의 정적 마운트.
  • FastAPI 의존성으로 보호되는 프런트엔드.

cdn = false는 반대의 선택입니다. 프로모션을 비활성화하고 일치하는 모든 요청을 Function에 남깁니다. 애플리케이션 코드가 각 요청을 반드시 검사해야 한다면 타당한 선택입니다.

작지만 알아둘 예외도 있습니다. StaticFiles 마운트의 슬래시 없는 루트 요청은 FastAPI가 끝에 슬래시가 붙은 형식으로 리디렉션할 수 있도록 계속 Function에 도달합니다. 클라이언트가 이 경로를 반복해서 요청한다면 Function 사용량이 정확히 0이 되리라고 기대해서는 안 됩니다.

실무에서 달라지는 지점

FastAPI 저장소 하나로 SaaS를 운영하는 개인 창업자

app.frontend()로 번들된 웹 앱을 제공하는 창업자는 API를 동적으로 유지하면서 공개 HTML, CSS, JavaScript 트래픽을 Function 경로 밖으로 옮길 수 있습니다. 효과는 컴퓨팅 기준선이 더 명확해진다는 점입니다. 제품 트래픽이 늘어도 브라우저의 에셋 요청 하나하나가 백엔드 작업처럼 잡히지 않습니다.

공개 파일과 고객 전용 파일을 다루는 에이전시 엔지니어

에이전시 엔지니어는 공개 셸은 CDN에 두고, 민감한 라우트는 정적 마운트보다 먼저 선언할 수 있습니다. 이때 효과는 Function 사용량 절감에 그치지 않습니다. 어떤 고객 파일은 Python에서 접근 여부를 판단해야 하고 어떤 파일은 그렇지 않은지 라우트 맵에 명확히 드러납니다.

재무팀과 협업하는 백엔드 리드

백엔드 리드는 재무팀에 두 가지 예측치를 따로 제시할 수 있습니다. Function 항목에는 동적 FastAPI 트래픽을, CDN 항목에는 방문자 대상 전체 트래픽을 반영하는 방식입니다. 덕분에 Function Invocations 감소를 Edge Requests나 전송량의 동일한 감소로 잘못 해석하지 않게 됩니다.

전역 미들웨어를 사용하는 팀

최상위 로깅, 테넌트 확인, 인증 미들웨어를 사용하는 팀이라면 정적 마운트가 기본적으로 Function에 남을 것으로 예상해야 합니다. 이때 필요한 판단은 명확히 공개된 에셋 영역이 해당 미들웨어를 우회해도 되는지 여부입니다. 답이 ‘아니요’라면 이번 변경에서 안전하게 예산에 반영할 절감액은 없습니다.

배포 하나를 점검하는 방법

확장자가 붙은 파일은 모두 공개 파일일 것이라는 가정이 아니라, 실제 라우트 목록에서 시작해야 합니다.

  1. 공개 경로와 보호 경로 구분하기

    모든 app.frontend() 디렉터리와 StaticFiles 마운트를 나열합니다. 어느 방문자에게나 반환해도 되는 파일을 표시합니다. 사용자, 테넌트, 역할, 쿠키 또는 요청 시점의 미들웨어 결과에 따라 응답이 달라지는 파일은 따로 표시합니다.

  2. 선언 순서 확인하기

    Function 라우트가 우선해야 한다면 StaticFiles 마운트보다 앞에 둡니다. 다음은 Vercel 문서에 나온 패턴입니다.

    Python
    from fastapi import FastAPI
    from fastapi.staticfiles import StaticFiles
    
    app = FastAPI()
    
    # Declared before the mount, so this route wins over any CDN file at this path.
    @app.get("/static/protected.json")
    def protected():
        return {"access": "denied"}
    
    app.mount("/static", StaticFiles(directory="static"))
  3. 보호 경로를 Function에 남기기

    설정을 바꾸기 전에 최상위 미들웨어, 하위 앱 미들웨어, 프런트엔드 의존성을 확인합니다. 영향받는 모든 파일이 실제 공개 파일이 아니라면 차트 수치를 낮추기 위해 cdn = true를 설정해서는 안 됩니다. 일치하는 모든 트래픽이 FastAPI를 거쳐야 한다면 cdn = false를 사용합니다.

  4. 번들 크기를 줄일지 결정하기

    실행 중인 앱이 프로모션된 파일을 읽지 않는다면 문서화된 설정으로 해당 소스 디렉터리를 Function 번들에서 제외할 수 있습니다.

    TOML
    [tool.vercel.fastapi.static]
    exclude = true

    런타임 코드에서 해당 파일이 계속 필요하다면 기본값을 유지합니다.

  5. 배포 후 트래픽 분리 검증하기

    vc deploy를 실행합니다. 공개 파일 하나, 보호 파일 하나, API 라우트 하나에 각각 요청을 보냅니다. 보호된 응답이 여전히 올바르게 동작하는지 확인한 다음, Usage에서 프로젝트의 Function Invocations, Active CPU, Provisioned Memory, Fast Origin Transfer, Edge Requests, Fast Data Transfer를 비교합니다. 공개 파일 표본은 Function 경로에서는 빠지되 CDN 합계에서는 사라지지 않아야 합니다.

절감액을 과장하지 않으려면

Pro의 직접 호출 요금은 백만 건당 $0.60에 불과합니다. 작은 앱이라면 실제 절감액이 몇 센트에 그치거나 월간 사용 크레딧 안에 흡수될 수 있습니다. 더 큰 이점은 Function 사용량에서 에셋 요청이라는 잡음을 걷어내고 실제 API 작업에 쓸 컴퓨팅 여유를 보존하는 데 있을 수 있습니다.

공개 에셋 트래픽이 많거나, 기존 Function 경로에서 메모리를 점유하는 시간이 충분히 길었거나, 응답이 의미 있는 Fast Origin Transfer를 만들었다면 절감폭이 커집니다. 반대로 파일이 이미 public/에 있었거나, 트래픽이 적거나, 보안 규칙 때문에 해당 경로를 Function에 남기는 것이 맞다면 효과는 작습니다.

이번 변경이 에셋 최적화를 대체하는 것도 아닙니다. 같은 대용량 JavaScript 번들, 이미지, 폰트는 여전히 CDN을 거쳐 방문자에게 전달되어야 합니다. Fast Data Transfer를 줄이려면 파일 자체의 크기를 줄여야 합니다.

월요일에 할 일

app.frontend() 또는 StaticFiles가 공개 파일을 제공하고 해당 요청이 Function 사용량에 잡힌다면 이번 주에 조치합니다. 파일이 보호되어 있는데 접근 규칙을 아직 분리하지 않았다면 기다립니다. 관련 파일이 이미 public/이나 다른 CDN 기반 경로에서 제공된다면 영향을 받지 않습니다.

월요일에는 공개 에셋 경로와 보호 에셋 경로를 구분해 목록을 만들고, 반드시 실행되어야 하는 모든 라우트와 보호 장치를 유지한 뒤, 각 분류에서 요청 하나씩 보내 배포 결과를 검증합니다. Function 사용량에서 실제로 줄어든 수치만 예산에 반영합니다. CDN 요청과 전송량은 장부에 그대로 남겨 둡니다.

운영 비용에 영향을 주는 플랫폼 변경을 더 쉽게 풀어 쓴 글로 받아보고 싶다면 뉴스레터를 구독하세요.

마지막 업데이트
2026년 9월 13일
카테고리
Explained

Google에서 이 사이트를 우선하기

Google 검색에서 omidsaffari.com을 선호 소스로 추가

omidsaffari.com을 선호 소스로 지정하면 Google이 Top Stories, AI Overviews, AI Mode에서 우선적으로 보여 줍니다.

OpenAI API 키 만료, 서비스 중단 없이 교체하는 법

OpenAI API 키 만료, 서비스 중단 없이 교체하는 법

OpenAI API 키 만료에 대비해 서비스 중단 없이 새 키를 배포하는 방법을 설명합니다. 최대 수명 정책의 범위부터 담당자 지정, 교체 비용 산정, 시크릿 저장소 배포, 실제 작업 검증, 기존 키 폐기까지 안전한 API 키 관리 절차를 한 번에 정리했습니다.2026년 9월 13일Explained
Vercel 권한 관리: 공유 커넥터 담당자를 분리하는 법

Vercel 권한 관리: 공유 커넥터 담당자를 분리하는 법

Vercel Connect의 Connector Permissions로 Pro·Enterprise 팀의 공유 커넥터 관리 권한을 분리하는 방법을 정리했습니다. Connector Manager 지정, Member 역할 점검, 공급자 권한과 런타임 승인 분리까지 인수인계 절차를 확인하세요.2026년 9월 13일Explained
Cloudflare R2 파일, 이름 그대로 AI Search에 인덱싱하는 법

Cloudflare R2 파일, 이름 그대로 AI Search에 인덱싱하는 법

Cloudflare AI Search는 이제 확장자 없는 R2 객체도 HTTP Content-Type으로 인식합니다. 기존 키를 유지한 채 파일을 인덱싱하는 방법, 메타데이터 복구 비용, 동기화 한계, 실제 검색 가능 여부를 확인하는 운영 절차를 한 번에 정리했습니다.2026년 9월 12일Explained
Vercel 코드 샌드박스, 64 GB로 더 큰 에이전트 작업 수용

Vercel 코드 샌드박스, 64 GB로 더 큰 에이전트 작업 수용

Vercel 코드 샌드박스의 기본 작업 저장공간이 32 GB에서 64 GB로 늘었습니다. 대형 저장소, 코딩 에이전트, 빌드 작업이 한 환경에서 끝날 수 있는지, 스냅샷과 Drive 비용은 어떻게 달라지는지, 실제 작업으로 무엇을 측정해야 하는지 정리했습니다.2026년 9월 12일Explained
Cloudflare Workflows의 새 7일 기본값: 성공·오류 기록 설계법

Cloudflare Workflows의 새 7일 기본값: 성공·오류 기록 설계법

새 Workers Paid Workflow의 완료·오류 상태 기본 보존 기간이 30일에서 7일로 줄었습니다. 성공 기록과 오류 기록을 따로 설계하고, 31일 메트릭과 상세 인스턴스 상태를 구분해 실제 스토리지 비용과 조사 가능 기간을 계산하는 방법을 정리합니다.2026년 9월 11일Explained
AI 데이터 분석 실무: ChatGPT Data로 주간 보고 인수인계 줄이기

AI 데이터 분석 실무: ChatGPT Data로 주간 보고 인수인계 줄이기

ChatGPT Data가 승인된 데이터 소스와 지표 정의를 바탕으로 주간 보고서를 갱신하는 방식을 살펴봅니다. 도입 절차부터 비용 계산, 권한 경계, 사람의 검토가 필요한 지점까지 실무 기준으로 정리했습니다. 분석가 인수인계를 줄이면서 의사결정의 통제권을 유지하는 방법을 확인하세요.2026년 9월 11일Explained
Cursor 사용법: Projects로 팀 리뷰 큐 운영하기

Cursor 사용법: Projects로 팀 리뷰 큐 운영하기

Cursor 사용법이 Projects의 공유 컨텍스트와 반복 실행 에이전트로 어떻게 달라지는지 살펴봅니다. 팀 도입 전 확인할 설정 방법, 리뷰 부담, 비용 통제 기준과 한 달 파일럿 운영법을 정리하고, 어떤 팀이 시작해야 하며 어떤 팀은 기다려야 하는지 실무 기준으로 짚습니다.2026년 9월 11일Explained
Codex 사용량, Work의 Deep Research와 한 예산으로 묶였다

Codex 사용량, Work의 Deep Research와 한 예산으로 묶였다

ChatGPT Deep Research가 Work와 Codex의 공용 할당량·크레딧을 어떻게 쓰는지 알아봅니다. Chat의 별도 한도와 무엇이 다른지 비교하고, GPT-5.6 Sol 요율, 팀 예산 계산 예시, 안전한 운영 절차까지 한눈에 정리했습니다.2026년 9월 10일Explained
뉴스레터

매주 일요일, 한 통의 편지.뜨거운 의견이 아닌, 돌아가는 시스템.

주간 발행. 스팸 없음. 언제든 해지 가능합니다.