Cloudflare 무료 플랜에서의 MCP 서버: 10ms CPU 제한을 기준으로 측정하다
요약
Model Context Protocol(MCP)의 무상태(stateless) 전환에 따라 Cloudflare Workers 무료 플랜에서 MCP 서버를 운영할 수 있는 환경이 마련되었습니다. 프로토콜 개정으로 세션 관리가 불필요해지면서, 10ms CPU 제한 내에서 효율적인 서버 구현이 가능해졌습니다.
핵심 포인트
- MCP 프로토콜이 무상태(stateless)로 전환되어 세션 및 핸드셰이크 과정이 제거됨
- Cloudflare Workers 무료 플랜의 10ms CPU 제한 내에서 MCP 서버 운영 가능
- 새로운 프로토콜은 버전 및 기능 정보를 요청 메타데이터에 포함하는 방식 채택
- HTTP 전송 시 엄격한 헤더 규율(MCP-Protocol-Version, Mcp-Method 등) 요구
이번 주에 두 가지 사건이 발생하면서, "MCP 서버를 무료로 운영할 수 있을까?"라는 질문은 하나의 측정 가능한 조건하에 타협의 대상에서 명확한 "예"로 바뀌었습니다. 오늘 Model Context Protocol (MCP)이 2026-07-28 개정판을 출시했으며, 가장 주요한 변화는 프로토콜 코어가 무상태(stateless)로 전환되었다는 점입니다. 세션(sessions), Mcp-Session-Id 헤더, 그리고 initialize 핸드셰이크(handshake)가 사라졌습니다. 출시 게시물은 그 결과를 다음과 같이 명시하고 있습니다:
이제 공유 저장소(shared storage) 없이도 일반적인 라운드 로빈(round-robin) 로드 밸런서 뒤에 있는 어떤 서버 인스턴스로든 모든 요청이 도달할 수 있습니다.
그리고 출시 하루 전인 어제, Cloudflare의 자체 문서가 변경되었습니다. 전송 계층(transport)이 세션을 유지할 장소가 필요했기 때문에 모든 MCP 서버를 Durable Object로 지원하던 공식 경로인 McpAgent 클래스는 이제 사용 중단(deprecated) 및 기능 동결(feature frozen)로 표시되었으며, 새로운 서버를 위한 권장 대체제로 무상태 요청 핸들러(stateless request handler)가 지정되었습니다.
이 두 가지 움직임은 양쪽 끝에서 동일한 간극을 메워줍니다. 무료 플랜의 Worker는 단 한 가지 예외를 제외하고는 항상 소규모 MCP 서버를 위한 자연스러운 장소였습니다. 그 예외란 바로 전송 계층이 상태(state)를 요구했고, 상태는 Durable Object와 고정된 인스턴스(sticky instance)를 의미했다는 점입니다. 이제 프로토콜 자체가 모든 요청이 자기 완결적(self-contained)임을 보장합니다. 남은 것은 무료 플랜의 유일한 물리적 한계인 요청당 10ms의 CPU 제한이며, 실제 서버가 이 제한 안에 들어가는지는 논쟁할 문제가 아닙니다. 그것은 측정해야 하는 문제입니다. 그래서 우리는 이 사이트에서 서버를 구축하고 측정했습니다.
이번 개정에서 실제로 제거된 것
기존의 라이프사이클(lifecycle)은 initialize 왕복(round trip)으로 모든 연결을 시작하고, 세션 ID를 생성하며, 클라이언트가 모든 호출에서 이를 지참하도록 요구했습니다. 그 모든 것이 삭제되었습니다. 이제 버전, 클라이언트 식별 정보, 그리고 기능(capabilities)은 각 요청의 _meta 필드 내부로 이동하며, 서버가 반드시 구현해야 하는 단 한 가지는 요청하는 누구에게나 지원되는 버전과 기능을 보고하는 server/discover입니다.
그 대가로 전송(transport) 방식은 더 엄격해졌습니다. 모든 POST 요청은 본문(body) 내부의 버전과 일치하는 MCP-Protocol-Version 헤더를 포함해야 하며, 로드 밸런서와 게이트웨이가 본문을 파싱하지 않고도 라우팅할 수 있도록 JSON-RPC 메서드를 반영하는 Mcp-Method 헤더(도구 호출 시에는 Mcp-Name 포함)를 반드시 갖춰야 합니다. 불일치가 발생하면 엄격한 400 에러가 반환됩니다. 배치(Batching) 기능은 여전히 사라졌고, ping은 완전히 제거되었으며, 알 수 없는 메서드는 이제 HTTP 404가 됩니다. 또한 2024년 시대의 HTTP+SSE 전송 방식은 공식적으로 deprecated(사용 중단 예정)로 분류되었습니다. 메시지를 전혀 푸시(push)하지 않는 서버는 모든 요청에 일반 JSON으로 응답할 수 있으며, 스트리밍 경로에 대해서는 405로 거부할 수 있습니다.
읽기 전용 서버의 경우, 남은 프로토콜 표면(protocol surface)은 매우 작습니다: server/discover, tools/list, tools/call, 그리고 헤더 규율(header discipline)이 전부입니다. 이것이 전체 목록입니다.
이 사이트가 현재 실행 중인 서버
이 블로그는 이미 에이전트 표면(agent surface)을 게시하고 있습니다 — 모든 기사의 마크다운(Markdown) 미러와 posts.json 피드가 그것입니다. MCP 서버는 두 가지 도구 뒤에 있는 동일한 파일들입니다: list_articles는 피드를 반환하고, get_article은 기사의 전체 마크다운을 반환합니다. 이 서버는 사이트의 콘텐츠 협상 (content negotiation)을 수행하는 동일한 Worker 상의 https://301.sh/mcp에 위치하며, 의존성이 전혀 없습니다 — 개정 이후 남은 프로토콜 표면은 손으로 직접 작성할 수 있을 정도로 짧습니다. Cloudflare는 동일한 작업을 위한 SDK 경로(createMcpHandler 및 프로토콜 SDK)를 제공하는데, 이는 리소스(resources), 프롬프트(prompts), 또는 유도(elicitation)가 필요한 시점에는 정답이 되지만, 두 개의 도구만 가진 읽기 전용 서버에는 필요하지 않습니다.
그 형태를 압축한 디스패치(dispatch) 로직은 다음과 같습니다:
switch (message.method) {
case 'server/discover':
return reply(id, { resultType: 'complete', supportedVersions: ['2026-07-28'],
...
이 안에는 계산(compute)되는 것이 아무것도 없습니다. 모든 응답은 에셋 바인딩(assets binding)을 통해 가져오는 이미 배포된 정적 에셋(static asset)이며, 이러한 선택이 바로 측정 결과에서 보상을 받는 핵심입니다.
측정
대부분의 사람들이 그냥 지나치는 부분은 Cloudflare가 정의하는 제한(limit)입니다:
CPU 시간은 CPU가 워커(Worker) 코드를 실행하는 데 소요되는 시간을 측정합니다. 네트워크 요청을 기다리는 것(예: fetch() 호출, KV 읽기 또는 데이터베이스 쿼리)은 CPU 시간에 포함되지 않습니다.
따라서 10ms 예산은 JSON을 구문 분석(parsing), 검증(validating), 조립하는 데 사용되며, 기사 본문을 가져오는 데 사용되는 것이 아닙니다. 우리는 프로덕션 엔드포인트에 40개의 요청을 보냈고, 워커 로그(Workers Logs)가 기록하는 호출당 cpuTime을 읽었습니다:
| Method | CPU, ms (min / median / max) | Wall, ms (min / median / max) |
|---|---|---|
| server/discover | 0 / 0 / 1 | 0 / 1 / 2 |
| ... |
최악의 경우 10ms 예산 중 2ms를 소모하며, 사이트에서 가장 긴 기사를 제공하는 가장 느린 응답(벽 시간 기준 88ms)은 자산 가져오기(asset fetch)를 기다리는 것에 거의 전적으로 의존하며, 이 부분은 측정하지 않습니다. 서비스 도구는 무료 상한선의 5분의 1로 작동하여 여유 공간이 있으며, 무료 플랜의 다른 수치인 하루 100,000 요청은 엔드포인트 에이전트가 대화당 몇 번 호출하는 경우 완전히 다른 종류의 문제입니다.
실제로 10ms가 영향을 미치는 곳
이 상한선은 실제이며, 단지 전송 계층(transport) 외부에 존재할 뿐입니다. 우리가 이 사이트의 에이전트 표면을 감사했을 때에는 서비스로 노출하는 것을 고려했던 템플릿 엔진을 측정했고, 이는 같은 10ms를 8배나 초과했습니다. 이것이 솔직한 구분입니다: 바이트를 제공하는 도구는 1~2밀리초가 걸리는 반면, 문서를 구문 분석하거나(parsing), 템플릿을 렌더링하거나(rendering), 대규모로 해시화(hashing)하는 등 계산하는 도구는 예산을 거의 즉시 소모합니다. Cloudflare는 가끔 초과 사용(
이러한 성능 향상에는 대가가 따르며, 이 사이트의 자체 규칙에 따라 이는 제한 사항(limit) 항목 옆에 배치되어야 합니다. 월 5달러의 Workers Paid 플랜은 요청당 제한 시간을 기본 30초(최대 5분까지 설정 가능)로 높여주며, 매달 3,000만 CPU 밀리초(CPU milliseconds)와 1,000만 건의 요청을 포함합니다. 만약 사용 중인 도구가 연산을 수행한다면, 무료 티어의 10ms가 아니라 이 수치를 기준으로 비교해야 합니다.
직접 시도해보기, 그리고 이것이 필요로 하지 않는 것들
엔드포인트(endpoint)는 활성화되어 있으며, 단 한 번의 요청만으로도 프로토콜의 완전히 새로운 형태를 확인할 수 있습니다:
curl https://301.sh/mcp -X POST \
-H 'Content-Type: application/json' \
-H 'MCP-Protocol-Version: 2026-07-28' \
...
열어야 할 세션도 없고, 유지해야 할 상태(state)도 없으며, 청구서에 Durable Object 비용이 추가되지도 않습니다. 만약 귀하의 사이트가 이미 Markdown 미러(mirrors)나 피드(feed)를 게시하고 있다면 — 그리고 저희의 사이트가 에이전트 준비성 감사(agent readiness audit)를 마친 후 그랬던 것처럼 — "정적 파일(static files)"에서 "MCP 서버"로 가는 거리는 귀하가 이미 실행 중일 수도 있는 Worker 상의 경로 하나일 뿐입니다. 이 스펙은 마침내 소규모 읽기 전용(read-only) 서버가 항상 되고 싶어 했던 모습, 즉 이미 구축된 콘텐츠에 대한 질문에 답하는 단순한 HTTP 엔드포인트(endpoint)의 모습과 일치합니다. 무료 플랜으로도 이를 충분히 감당할 수 있습니다. 결코 무료일 수 없었던 것은 바로 연산 도구들이며, 이제 당신은 이를 결정짓는 수치를 알게 되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기