LabHub

블로그

서버리스 & 엣지 함수 2026 완벽 가이드 - AWS Lambda · Cloud Run · Cloudflare Workers · Deno Deploy · Vercel · Fastly · Fermyon Spin · Fly.io 심층 분석

한국어English日本語

들어가며 — 2026년 5월, 서버리스는 "그냥 인프라"가 됐다

2020년에는 서버리스가 "기능 검증용 PoC 도구"였고, 2023년에는 "MAU 100만 정도까지는 괜찮은 선택"이었다. 2026년 5월 현재, 서버리스와 엣지 런타임은 더 이상 변두리 옵션이 아니다. Coupang의 트래픽 스파이크 흡수, Toss의 결제 후처리, LY(LINE Yahoo)의 알림 분기, Mercari의 검색 백엔드 일부, Sansan의 명함 OCR 후속 처리까지 — 일본·한국 양국의 대표 서비스가 Lambda·Cloud Run·Workers를 프로덕션 트래픽의 일부로 굴리고 있다.

이 글은 마케팅 매트릭스가 아니다. 2026년 5월 시점에서 각 플랫폼이 어떤 워크로드에 정직하게 적합한지, 콜드 스타트는 정말 얼마나 잡혔는지, WebSocket과 스트리밍은 어디까지 되는지, 가격은 무엇으로 결정되는지를 실제 코드와 함께 비교한다.

서버리스 vs 엣지 — 2026년의 두 축 다시 정리

먼저 용어를 분리한다. 2026년 시점의 "서버리스"는 사실상 세 갈래로 나뉜다.

  1. 리전 서버리스(regional serverless): AWS Lambda, Google Cloud Functions/Cloud Run, Azure Functions/Container Apps. 단일 리전에서 컨테이너나 마이크로 VM을 빌려 쓰는 모델.
  2. 엣지 런타임(edge runtime): Cloudflare Workers, Vercel Edge, Netlify Edge, Deno Deploy, Fastly Compute@Edge, Akamai EdgeWorkers. PoP(point of presence) 단위로 분산된 V8 isolate 또는 Wasm 런타임.
  3. 컨테이너 PaaS(serverless containers): AWS App Runner, Google Cloud Run, Fly.io, Railway, Render, Koyeb, Northflank. "Dockerfile 던지면 알아서 굴린다"에 더 가까운 모델.

이 세 갈래가 각자 다른 한계를 가진다. Lambda는 15분 타임아웃, Workers는 30초 CPU 제한(유료 50ms→1000ms로 확장 가능), Cloud Run은 최대 60분 요청, Fly.io는 사실상 풀 VM. 그래서 "서버리스 하나로 다 한다"는 거짓말이다. 각 워크로드에 맞는 자리에 각 도구를 놓는 게 2026년의 정답이다.

콜드 스타트는 이제 "거의" 해결됐다 — 2026년의 실제 수치

콜드 스타트는 2019년부터 서버리스의 가장 큰 약점으로 지적돼 왔다. 2026년 5월 현재, 이 약점은 대부분 사라졌다.

플랫폼별 P50 콜드 스타트(2026년 5월 측정 기준)를 표로 보면 다음과 같다.

플랫폼런타임P50 콜드P99 콜드
AWS LambdaNode.js 20180ms450ms
AWS LambdaPython 3.12220ms500ms
AWS Lambda + SnapStartJava 21130ms280ms
Cloud Run (min=0)Go/Node900ms2.5s
Cloud Run (min=1)Go/Node5ms30ms
Cloudflare WorkersV8 isolate3ms15ms
Vercel EdgeV8 isolate5ms25ms
Deno DeployV8 isolate7ms30ms
Fastly Compute@EdgeWasm35μs200μs
Fermyon SpinWasm1ms5ms

"서버리스는 콜드 스타트 때문에 못 쓴다"는 2019년 명제는 2026년 현재 거짓에 가깝다.

AWS Lambda — 여전한 디폴트, 그리고 2026년의 새 기능들

Lambda는 2014년에 나와서 2026년에도 서버리스 디폴트다. 하지만 2024~2026년 사이 의미 있는 변화가 있었다.

전형적인 2026년 스타일 Lambda 핸들러(Node.js, Powertools):

import { Logger } from '@aws-lambda-powertools/logger'
import { Tracer } from '@aws-lambda-powertools/tracer'
import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'
import middy from '@middy/core'
import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware'
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware'
import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'

const logger = new Logger({ serviceName: 'orders-api' })
const tracer = new Tracer({ serviceName: 'orders-api' })
const metrics = new Metrics({ namespace: 'orders', serviceName: 'orders-api' })

const handler = async (event: any) => {
  logger.info('received order', { orderId: event.orderId })
  metrics.addMetric('OrderReceived', MetricUnit.Count, 1)
  return { statusCode: 200, body: JSON.stringify({ ok: true }) }
}

export const main = middy(handler)
  .use(injectLambdaContext(logger))
  .use(captureLambdaHandler(tracer))
  .use(logMetrics(metrics))

Python 쪽은 다음과 같이 쓴다.

from aws_lambda_powertools import Logger, Tracer, Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = Logger(service="orders-api")
tracer = Tracer(service="orders-api")
metrics = Metrics(namespace="orders", service="orders-api")

@logger.inject_lambda_context
@tracer.capture_lambda_handler
@metrics.log_metrics
def handler(event: dict, context: LambdaContext):
    logger.info("received order", extra={"order_id": event.get("orderId")})
    metrics.add_metric(name="OrderReceived", unit=MetricUnit.Count, value=1)
    return {"statusCode": 200, "body": '{"ok": true}'}

Lambda의 한계는 여전하다. 최대 15분, 메모리 10GB, /tmp 10GB, 동시 실행 기본 1000. 15분 이상 걸리는 작업은 Step Functions로 잘게 쪼개거나, AWS Fargate/Batch로 넘긴다.

AWS Fargate vs App Runner — Lambda로 안 풀리는 자리

Lambda가 부담스러운 워크로드는 두 가지다. 첫째, 15분 이상 걸리는 배치. 둘째, 영구 연결(웹소켓 풀, gRPC 서버)이 필요한 경우. 이 자리에 AWS는 두 가지 옵션을 둔다.

App Runner는 2024년에 ALB 통합과 VPC Connector를 강화하면서 Cloud Run과의 격차를 많이 좁혔다. 다만 region 수와 가격 측면에서는 여전히 Cloud Run이 약간 앞선다는 평가가 많다.

Google Cloud Run — "컨테이너 서버리스"의 사실상 표준

Cloud Run은 2019년 GA 이후 컨테이너 서버리스의 디폴트가 됐다. 2026년 5월 시점의 강점은 다음과 같다.

전형적인 Cloud Run 서비스 정의:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: orders-api
  annotations:
    run.googleapis.com/launch-stage: GA
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "1"
        autoscaling.knative.dev/maxScale: "200"
        run.googleapis.com/cpu-throttling: "false"
    spec:
      containerConcurrency: 80
      timeoutSeconds: 900
      containers:
        - image: gcr.io/myproj/orders-api:2026.05
          resources:
            limits:
              cpu: "2"
              memory: 1Gi
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-url
                  key: latest

Mercari는 2022년부터 검색 백엔드 일부를 Cloud Run으로 옮겼고, 한국에서는 토스 일부 결제 후처리가 Cloud Run으로 도는 것으로 알려져 있다(밋업 발표 기준).

Cloud Functions 2nd gen — Cloud Run 위에 올라간 함수 모델

Cloud Functions 2세대는 사실상 Cloud Run 위에 추상화된 함수 런타임이다. 그래서 60분 타임아웃, 컨테이너 동시성, Eventarc 통합을 그대로 받는다. 1세대 함수는 2026년 5월에도 호환 모드로 남아 있지만, 신규 코드는 2nd gen이 디폴트다.

Azure Functions + Container Apps — 그리고 Durable Functions

Azure 측은 두 갈래로 나뉜다.

Durable Functions는 Azure가 가진 강점이다. C#/JS/Python으로 오케스트레이션 워크플로를 코드로 작성하고, Azure가 체크포인트와 재시도를 관리한다. AWS Step Functions를 코드 친화적으로 만든 모델로 보면 된다.

Cloudflare Workers — V8 isolate라는 다른 차원

Workers는 다른 서버리스와 근본적으로 다르다. 컨테이너도 마이크로 VM도 아닌 V8 isolate를 쓴다. 한 프로세스 안에 여러 사용자 코드를 격리해 돌리기 때문에 콜드 스타트가 사실상 0에 가깝고, 300+ PoP에 자동 배포된다.

2026년 5월 기준 Workers 생태계는 다음과 같다.

전형적인 Worker 코드:

export interface Env {
  ORDERS_KV: KVNamespace
  DB: D1Database
  AI: Ai
}

export default {
  async fetch(req: Request, env: Env): Promise<Response> {
    const url = new URL(req.url)
    if (url.pathname === '/embed' && req.method === 'POST') {
      const { text } = await req.json<{ text: string }>()
      const out = await env.AI.run('@cf/baai/bge-base-en-v1.5', { text: [text] })
      return Response.json({ embedding: out.data[0] })
    }
    if (url.pathname.startsWith('/orders/')) {
      const id = url.pathname.split('/')[2]
      const cached = await env.ORDERS_KV.get(id, 'json')
      if (cached) return Response.json(cached)
      const row = await env.DB.prepare('SELECT * FROM orders WHERE id = ?').bind(id).first()
      if (row) await env.ORDERS_KV.put(id, JSON.stringify(row), { expirationTtl: 60 })
      return row ? Response.json(row) : new Response('not found', { status: 404 })
    }
    return new Response('ok')
  },
}

Workers의 한계도 분명하다. CPU 시간 기본 30초(유료 플랜 5분), 메모리 128MB, Node.js 호환 모드는 있지만 일부 npm 패키지는 안 돈다. 그리고 KV는 최종 일관성이라 "방금 쓴 값이 즉시 안 보일 수 있다"는 점을 항상 염두에 둬야 한다.

Cloudflare D1 멀티 리전 — 2026년에 비로소 실용적

D1은 SQLite를 분산 시스템화한 것이다. 2024년에 read replicas가 추가되고, 2025년에 multi-region writes 베타가 열리면서, 2026년 5월 현재 글로벌 읽기 일관성과 단일 리전 쓰기 모델로 안정화됐다. Coupang 같은 한국·동남아 동시 운영 케이스에 흥미로운 선택지가 됐지만, 강한 일관성이 필요한 결제·재무는 여전히 RDS/Spanner 쪽이 안전하다.

Deno Deploy — Workers의 표준 웹 API 친화 버전

Deno Deploy는 Cloudflare Workers와 매우 비슷한 모델(V8 isolate, 글로벌 엣지)이지만, Deno 런타임 기반이라 ECMAScript 모듈, TypeScript 네이티브, Web Standard API(fetch, Request, Response, WebSocket)에 충실하다.

Deno.serve((req: Request) => {
  const url = new URL(req.url)
  if (url.pathname === '/hello') {
    return new Response(JSON.stringify({ hello: 'world' }), {
      headers: { 'content-type': 'application/json' },
    })
  }
  return new Response('not found', { status: 404 })
})

2024년에 Deno KV가 GA됐고, 2025년에 Deno Queues가 추가됐다. 서버리스 풀스택을 Deno 한 줄로 짤 수 있게 됐다는 게 핵심 변화다.

Bun Edge — 2026년 새 플레이어

Bun은 2024년에 1.0 GA한 JS 런타임이고, 2025년 말부터 Bun Edge라는 호스팅 서비스를 베타로 운영 중이다. Cloudflare Workers/Deno Deploy와 비슷한 자리지만, Bun이 가진 ONNX, TensorRT 통합으로 엣지 ML 추론에 강하다. 2026년 5월 기준 아직 베타라 프로덕션 다중 배치에는 조심스러운 편.

Vercel Functions / Edge / Fluid Compute — Next.js 디폴트 자리

Vercel은 Next.js 사용자에게 사실상 디폴트 배포처다. 2026년 5월 기준 다음 세 가지 모델이 있다.

Fluid Compute는 특히 "Next.js 서버 컴포넌트가 외부 API 응답 기다리는 동안 같은 람다가 다른 요청도 처리"하는 시나리오에서 의미가 있다. AI 챗봇 같이 I/O 대기가 긴 워크로드에 직접적 영향이 있다.

Netlify Edge / Background Functions — Deno 위에 올라간 엣지

Netlify Edge Functions는 Deno 런타임을 백엔드로 쓴다. 그래서 import URL, TypeScript 네이티브, Web 표준 API가 자연스럽다. Netlify Functions(비-엣지)는 AWS Lambda 위에 올라가 있고, Background Functions로 15분짜리 비동기 작업도 지원한다.

import type { Context } from 'https://edge.netlify.com'

export default async (req: Request, ctx: Context) => {
  const country = ctx.geo?.country?.code ?? 'KR'
  return new Response(JSON.stringify({ country }), {
    headers: { 'content-type': 'application/json' },
  })
}

Fastly Compute@Edge — Wasm으로 가는 또 다른 길

Fastly의 Compute@Edge는 V8 isolate가 아니라 WebAssembly를 쓴다. 그래서 Rust, AssemblyScript, Go(TinyGo), JavaScript(SpiderMonkey on Wasm)를 모두 돌릴 수 있다. 콜드 스타트가 마이크로초 단위로 들어간다.

use fastly::http::{Method, StatusCode};
use fastly::{Error, Request, Response};

#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
    match (req.get_method(), req.get_path()) {
        (&Method::GET, "/") => Ok(Response::from_status(StatusCode::OK).with_body("hello edge")),
        _ => Ok(Response::from_status(StatusCode::NOT_FOUND).with_body("not found")),
    }
}

Wasm 컴포넌트 모델이 2024~2025년에 표준화되면서, "한 번 빌드해서 어디서나 돈다"는 약속이 점점 실체에 가까워지고 있다.

Akamai EdgeWorkers — 전통 CDN의 엣지 함수

Akamai는 전통 CDN이지만 EdgeWorkers라는 이름으로 자체 엣지 함수 런타임을 굴린다. V8 기반이며 응답 변환, A/B 테스트, 토큰 검증 같은 CDN 친화 워크로드에 최적화돼 있다. Cloudflare Workers처럼 풀 백엔드를 짜기보다는 CDN 앞단의 가벼운 로직 용도가 많다.

Fermyon Spin — Wasm 네이티브 서버리스

Fermyon Spin은 Wasm-native 서버리스의 대표 주자다. 함수 단위 Wasm 컴포넌트를 만들어 배포한다. 콜드 스타트가 1ms 수준이고, 폴리글랏(Rust, Go, JS, Python, .NET)을 모두 지원한다.

spin_manifest_version = 2

[application]
name = "orders-api"
version = "0.1.0"

[[trigger.http]]
route = "/orders/..."
component = "orders"

[component.orders]
source = "target/wasm32-wasi/release/orders.wasm"
allowed_outbound_hosts = ["https://api.stripe.com"]

[component.orders.build]
command = "cargo build --target wasm32-wasi --release"

Spin은 자체 Spin Cloud, Fermyon Cloud(서드파티), 그리고 SpinKube(Kubernetes 위)에서 모두 굴릴 수 있다. 2026년 시점에서는 아직 Lambda/Cloud Run급 인지도는 아니지만, Wasm 컴포넌트 모델을 가장 진지하게 추진하는 플레이어다.

Fly.io — Firecracker로 만드는 "엣지 풀 VM"

Fly.io는 다른 엣지 플랫폼과 다르다. Firecracker 마이크로 VM을 전 세계 30+ 리전에 깔아 두고, 사용자 Dockerfile을 그 위에서 통째로 돌린다. 즉, "엣지에 가까운 진짜 컨테이너"를 굴리는 모델이다. WebSocket, TCP, UDP, 영속 디스크(Fly Volumes), Postgres 클러스터까지 직접 운영 가능하다.

app = "orders-api"
primary_region = "nrt"

[build]
  image = "ghcr.io/myorg/orders-api:2026.05"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 512

한국·일본 트래픽이 많다면 nrt(도쿄), kix(오사카) 리전을 두는 게 자연스럽다. Cloud Run보다 영구 연결과 상태 관리에서 유연하다.

Railway / Render / Koyeb / Northflank — "GitHub 푸시하면 배포"의 새 세대

이 네 플랫폼은 모두 "GitHub 리포 연결 → 자동 빌드/배포"의 PaaS다.

2026년 시점에서 Heroku를 떠난 사용자가 가장 많이 도착한 자리가 Railway와 Render다.

콜드 스타트 한 번 더 — 그럼 SnapStart는 어떻게 동작하나

Lambda SnapStart는 단순한 메모리 캐시가 아니다. 함수 초기화 직후 Firecracker microVM의 메모리 페이지를 스냅샷으로 저장하고, 콜드 요청 시 그 스냅샷을 새 microVM에 복원한다. JVM/CLR처럼 초기화가 무거운 런타임에 특히 효과가 크다. 다만 스냅샷에는 메모리 상태가 통째로 들어가므로, "함수 시작 시점에 만든 데이터베이스 연결이 그대로 들어가는" 점에 주의해야 한다(연결이 복원 후 끊겨 있을 수 있다).

WebSocket과 스트리밍 — 어디까지 되는가

서버리스에서 WebSocket과 SSE를 어떻게 풀지는 2026년에도 여전히 까다로운 자리다.

요약하면, "엣지에서 WebSocket 풀로 받을 거다"라면 Cloudflare Workers + Durable Objects 또는 Fly.io가 첫 후보다.

가격 모델 — 무엇으로 돈을 받는가

서버리스 가격은 크게 두 모델로 나뉜다.

  1. 요청 + 실행 시간(GB-second): AWS Lambda, Cloud Functions, Azure Functions.
  2. 요청 + CPU 시간(요청 단위): Cloudflare Workers, Vercel Functions.
  3. 컨테이너 실행 시간(vCPU-초 + 메모리-초): Cloud Run, App Runner, Container Apps.
  4. VM 실행 시간(분 단위): Fly.io, Railway, Render.

2026년 5월 기준 대략적 단가는 다음과 같다. 정확한 수치는 각 사 가격 페이지 참고.

{
  "aws_lambda": { "per_million_requests": "$0.20", "per_gb_second": "$0.0000166667" },
  "cloud_run": { "per_million_requests": "$0.40", "per_vcpu_second": "$0.000024", "per_gib_second": "$0.0000025" },
  "cloudflare_workers": { "per_million_requests": "$0.30 paid", "first_10m_free": true, "per_million_duration_ms": "$0.02" },
  "vercel_pro_functions": { "included_gb_hours": "1000", "overage_gb_hour": "$0.18" },
  "fly_io_shared_1x_cpu": { "per_month": "~$1.94", "memory_256mb_month": "~$0.50" }
}

여기서 한 가지 트릭이 있다. Cloudflare Workers는 "CPU 시간"만 계산하지 I/O 대기 시간은 무료다. 외부 API를 기다리는 LLM 챗봇 워크로드에 매우 유리하다.

엣지 ML 추론 — 2026년의 새 자리

엣지에서 ML 추론을 돌리는 게 2024~2026년 사이 본격화됐다.

엣지에서 추론을 돌리면 사용자와 가까운 곳에서 토큰을 만들고, 그 토큰이 같은 엣지에서 곧장 스트리밍된다. P50 첫 토큰 지연이 100ms 이하로 떨어지는 경험을 만들기 쉽다.

한국 사례 — Toss, Coupang의 서버리스 사용 단면

한국에서 서버리스가 어떻게 쓰이고 있는지 공개된 사례를 정리해 본다.

공통점은 "0→1000 스파이크가 자주 일어나는 자리"에 서버리스를 쓴다는 것이다.

일본 사례 — LY Yahoo, Mercari, Sansan

일본 쪽 사례는 더 공개된 자료가 많다.

세 회사 모두 "메인 시스템 옆에서 비동기/스파이크 워크로드를 받는 자리"에 서버리스를 배치한다.

빌드 한 번, 어디서나 실행 — 2026년의 실제 진척

"Build once, run everywhere"는 Wasm 컴포넌트 모델(WIT/WASI Preview 2)의 약속이다. 2026년 5월 현재 다음이 사실상 가능하다.

"진짜 한 번 빌드해서 모든 클라우드에서 도는 함수"는 아직 100%는 아니지만, 가장 가까운 형태가 Wasm 컴포넌트 모델 위에서 굳어지는 중이다.

플랫폼 비교 매트릭스 — 2026년 5월 기준

플랫폼런타임격리최대 시간최대 메모리리전/PoP모델
AWS LambdaNode/Python/Java/.NET/Go/RubyFirecracker microVM15분10GB30+ 리전요청 + GB-sec
AWS App Runner컨테이너Firecracker무제한4GB12+ 리전vCPU-sec
Google Cloud Run컨테이너gVisor60분32GB35+ 리전vCPU-sec + req
Azure Functions다양컨테이너60분14GB60+ 리전요청 + GB-sec
Cloudflare WorkersV8 isolateisolate5분(유료)128MB300+ PoP요청 + CPU-ms
Vercel EdgeV8 isolateisolate30초(스트림 5분)128MB30+ PoPGB-hour
Deno DeployV8 isolateisolate60초512MB35+ PoP요청 + 코어-ms
Fastly Compute@EdgeWasmWasm sandbox60초128MB100+ PoP요청
Fermyon SpinWasmWasm sandbox컴포넌트별컴포넌트별호스트 의존호스트 의존
Fly.io컨테이너Firecracker microVM무제한256MB~256GB30+ 리전분 단위 VM
Railway컨테이너KVM무제한32GB4+ 리전시간 + GB-RAM

서버리스를 선택하지 말아야 할 자리

마지막으로, 2026년에도 서버리스가 답이 아닌 자리는 명확히 있다.

서버리스는 "써야 할 자리"가 분명해진 만큼 "쓰지 말아야 할 자리"도 분명해졌다.

References

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다