- Published on
WebAssembly 2025: 브라우저를 넘어 서버·엣지·AI까지 — Wasm이 바꾸는 컴퓨팅의 미래
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 들어가며
- 1. WebAssembly 101 — 기초 개념 완전 정리
- 2. WASI의 진화 — 시스템 인터페이스의 표준화
- 3. 2025년 주요 마일스톤 — Wasm 생태계의 대전환
- 4. 서버 사이드 Wasm — 프레임워크와 플랫폼
- 5. Wasm 런타임 비교 — 어떤 것을 선택할까
- 6. Wasm + AI — 엣지에서의 AI 추론
- 7. Wasm vs 컨테이너 vs 서버리스 — 비교 분석
- 8. 실습: Rust로 Wasm 앱 빌드 및 배포
- 9. 언어별 Wasm 지원 현황
- 10. 개발자 채택 로드맵
- 11. 퀴즈
- 12. 마무리 — Wasm의 현재와 미래
- 참고 자료
들어가며
Solomon Hykes(Docker 창시자)가 2019년에 남긴 유명한 트윗이 있습니다. "만약 2008년에 WASM과 WASI가 있었다면, Docker를 만들 필요가 없었을 것이다." 그로부터 6년이 지난 2025년, 그 예언이 현실이 되어가고 있습니다.
WebAssembly(Wasm)는 원래 브라우저에서 C/C++ 코드를 네이티브에 가까운 속도로 실행하기 위해 탄생했습니다. 하지만 2025년 현재, Wasm은 브라우저라는 울타리를 완전히 벗어났습니다. 서버리스 컴퓨팅, 엣지 배포, AI 추론, 플러그인 시스템, 심지어 블록체인 스마트 컨트랙트까지 — Wasm이 닿지 않는 곳이 없습니다.
이 글에서는 WebAssembly의 기초 개념부터 2025년의 주요 마일스톤, 서버 사이드 활용, 런타임 비교, AI 통합, 그리고 실습까지 포괄적으로 다룹니다. Wasm이 왜 "한 번 컴파일하면 어디서나 실행"되는 진정한 유니버설 런타임인지 확인해 보겠습니다.
1. WebAssembly 101 — 기초 개념 완전 정리
1.1 Wasm이란 무엇인가
WebAssembly는 스택 기반(stack-based) 가상 머신을 위한 바이너리 명령어 형식(binary instruction format)입니다. 핵심 특성은 다음과 같습니다.
바이너리 형식: 사람이 읽을 수 있는 텍스트 형식(WAT)과 컴팩트한 바이너리 형식(.wasm) 두 가지로 존재합니다.
;; WAT(WebAssembly Text Format) 예시 - 두 수를 더하는 함수
(module
(func $add (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add
)
(export "add" (func $add))
)
스택 머신: Wasm은 레지스터가 아닌 스택 기반으로 동작합니다. 모든 연산은 스택에서 값을 꺼내고(pop), 결과를 다시 밀어넣는(push) 방식으로 진행됩니다.
타입 안전성: 4가지 기본 타입(i32, i64, f32, f64)과 참조 타입(funcref, externref)을 지원하며, 모든 연산은 타입 체크를 거칩니다.
1.2 샌드박스 보안 모델
Wasm의 가장 강력한 특징 중 하나는 샌드박스 실행입니다.
- 메모리 격리: 각 Wasm 모듈은 자신만의 선형 메모리(linear memory)를 가집니다. 호스트의 메모리에 직접 접근할 수 없습니다.
- Capability-based Security: Wasm 모듈은 명시적으로 부여된 기능(capability)만 사용할 수 있습니다. 파일 시스템, 네트워크, 환경 변수 등에 대한 접근은 호스트가 허용한 범위 내에서만 가능합니다.
- 실행 격리: 무한 루프 방지를 위한 fuel 메커니즘, 스택 오버플로 감지 등 런타임 안전장치가 내장되어 있습니다.
┌─────────────────────────────────────────┐
│ 호스트 환경 (Host) │
│ ┌───────────┐ ┌───────────┐ │
│ │ Wasm 모듈A │ │ Wasm 모듈B │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │ 선형 │ │ │ │ 선형 │ │ │
│ │ │ 메모리 │ │ │ │ 메모리 │ │ │
│ │ └───────┘ │ │ └───────┘ │ │
│ └───────────┘ └───────────┘ │
│ 서로 완전히 격리됨 │
└─────────────────────────────────────────┘
1.3 이식성(Portability)의 진정한 의미
Java의 "Write Once, Run Anywhere"를 기억하시나요? Wasm은 이를 한 단계 더 발전시켰습니다.
| 특성 | Java/JVM | Docker/컨테이너 | WebAssembly |
|---|---|---|---|
| 크기 | 수십 MB (JRE) | 수십~수백 MB | 수 KB~수 MB |
| 시작 시간 | 수백 ms | 수초 | 마이크로초 |
| 보안 모델 | SecurityManager (deprecated) | namespaces/cgroups | 내장 샌드박스 |
| CPU 아키텍처 | JVM 종속 | 이미지별 빌드 | 진정한 크로스 플랫폼 |
| 언어 지원 | JVM 언어 | 모든 언어 | 30개 이상 |
2. WASI의 진화 — 시스템 인터페이스의 표준화
2.1 WASI가 필요한 이유
브라우저 안의 Wasm은 JavaScript와 상호작용하면 충분합니다. 하지만 서버에서 실행하려면 파일 시스템, 네트워크, 시계, 난수 생성기 등 시스템 리소스에 접근해야 합니다.
WASI(WebAssembly System Interface)는 이 문제를 해결하는 표준 인터페이스입니다. POSIX의 Wasm 버전이라고 생각하면 됩니다.
2.2 Preview 1 — 첫 번째 시도 (2019~2023)
WASI Preview 1은 POSIX 스타일의 단순한 API를 제공했습니다.
// WASI Preview 1 스타일 - 파일 읽기
use std::fs;
fn main() {
let content = fs::read_to_string("/data/config.toml")
.expect("파일을 읽을 수 없습니다");
println!("설정: {}", content);
}
제한사항:
- 비동기(async) 미지원
- 소켓 네트워킹 불완전
- 컴포넌트 간 통합 메커니즘 부재
- HTTP 요청 표준화 미비
2.3 WASI 0.2 — 컴포넌트 모델의 등장 (2024)
2024년에 릴리스된 WASI 0.2는 **컴포넌트 모델(Component Model)**이라는 혁신적인 개념을 도입했습니다.
// WIT (Wasm Interface Type) 정의 예시
package my-app:backend;
interface http-handler {
handle-request: func(req: request) -> response;
}
world my-server {
import wasi:http/outgoing-handler;
export http-handler;
}
컴포넌트 모델의 핵심:
- WIT(Wasm Interface Type): 언어 중립적 인터페이스 정의 언어
- 컴포넌트 조합: 서로 다른 언어로 작성된 Wasm 컴포넌트를 링크 타임에 결합
- 리치 타입: 문자열, 리스트, 옵션, 결과(Result), 레코드 등 고수준 타입 지원
- 가상화: 파일 시스템, 네트워크 등을 가상으로 대체 가능
2.4 WASI 0.3 — 네이티브 async의 혁명 (2025)
2025년의 가장 중요한 기술적 마일스톤은 단연 WASI 0.3입니다. 가장 큰 변화는 네이티브 비동기(async) 지원입니다.
// WASI 0.3 - 네이티브 async HTTP 핸들러
use wasi::http::handler;
async fn handle(request: handler::Request) -> handler::Response {
// 비동기 데이터베이스 쿼리
let user = db::query("SELECT * FROM users WHERE id = ?", &[request.user_id]).await;
// 비동기 외부 API 호출
let enriched = external_api::enrich(user).await;
handler::Response::new(200, serde_json::to_string(&enriched).unwrap())
}
WASI 0.3의 주요 혁신:
| 기능 | WASI 0.2 | WASI 0.3 |
|---|---|---|
| 비동기 | poll 기반 (비효율적) | 네이티브 async/await |
| 동시성 | 단일 요청 처리 | 멀티 요청 동시 처리 |
| 스트리밍 | 제한적 | 완전한 스트리밍 I/O |
| HTTP | 동기 핸들러 | 비동기 핸들러 |
| 성능 | 오버헤드 있음 | 네이티브 수준 |
3. 2025년 주요 마일스톤 — Wasm 생태계의 대전환
3.1 Akamai의 Fermyon 인수
2025년 3월, CDN 및 클라우드 보안 기업 Akamai가 Fermyon을 인수했습니다. 이것은 Wasm 생태계의 게임 체인저입니다.
Fermyon이란?
- Spin 프레임워크의 개발사
- Fermyon Cloud(Wasm 전용 서버리스 플랫폼) 운영
- Matt Butcher(Helm 창시자) 등 클라우드 네이티브 베테랑들이 설립
인수의 의미:
- Akamai의 전 세계 4,200개 이상 PoP(Point of Presence)에서 Wasm 실행 가능
- 엣지 컴퓨팅 + Wasm의 본격적인 엔터프라이즈 채택 시그널
- Cloudflare Workers와의 직접 경쟁 구도 형성
- Wasm이 더 이상 실험 기술이 아닌 프로덕션 기술임을 증명
3.2 프로덕션 배포 사례 확산
2025년, 대규모 프로덕션 환경에서 Wasm 채택이 급격히 증가했습니다.
Shopify: 서드파티 앱 확장 시스템을 Wasm 기반으로 전환. 수만 개의 앱이 Wasm 샌드박스 내에서 안전하게 실행됩니다.
Figma: 브라우저 기반 디자인 도구의 핵심 렌더링 엔진을 C++에서 Wasm으로 컴파일하여 네이티브 앱에 필적하는 성능을 달성했습니다.
Fastly: Compute 플랫폼에서 하루 수십억 건의 요청을 Wasm으로 처리. 콜드 스타트 시간이 35마이크로초 미만입니다.
Cloudflare: Workers 플랫폼이 전 세계 300개 이상의 데이터센터에서 Wasm을 실행합니다.
3.3 WASI 0.3 공식 발표
Bytecode Alliance에서 WASI 0.3의 첫 번째 공식 마일스톤을 2025년 상반기에 달성했습니다. 네이티브 async가 가장 중요한 기능이며, 이로 인해 서버 사이드 Wasm의 실용성이 크게 향상되었습니다.
3.4 Component Model의 성숙
2025년은 컴포넌트 모델이 실질적으로 사용 가능해진 해입니다. wasm-tools compose 명령어를 통해 서로 다른 언어로 작성된 컴포넌트를 하나로 조합할 수 있게 되었습니다.
# Rust로 작성된 비즈니스 로직과 Python으로 작성된 ML 모듈을 조합
wasm-tools compose business-logic.wasm -d ml-module.wasm -o combined-app.wasm
4. 서버 사이드 Wasm — 프레임워크와 플랫폼
4.1 Spin Framework (Fermyon)
Spin은 Wasm 네이티브 서버리스 프레임워크의 대표 주자입니다.
# spin.toml - Spin 애플리케이션 설정
spin_manifest_version = 2
[application]
name = "my-api"
version = "1.0.0"
[[trigger.http]]
route = "/api/hello"
component = "hello-handler"
[component.hello-handler]
source = "target/wasm32-wasip2/release/hello_handler.wasm"
allowed_outbound_hosts = ["https://api.example.com"]
// Spin HTTP 핸들러 (Rust)
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
let name = req
.query()
.get("name")
.unwrap_or(&"World".to_string())
.clone();
Ok(Response::builder()
.status(200)
.header("content-type", "application/json")
.body(format!(r#"{{"message": "Hello, {}!"}}"#, name))
.build())
}
Spin의 특징:
- 마이크로초 수준의 콜드 스타트
- 내장 키-밸류 스토어, SQLite, Redis 지원
- Rust, Go, Python, JavaScript, C# 등 다중 언어 지원
spin deploy로 Fermyon Cloud에 즉시 배포
4.2 Cloudflare Workers
Cloudflare Workers는 Wasm을 엣지에서 실행하는 가장 성숙한 플랫폼입니다.
// Cloudflare Worker - Wasm 모듈 사용
export default {
async fetch(request, env) {
// Rust로 컴파일된 Wasm 모듈에서 이미지 처리
const wasmModule = await import('./image-processor.wasm')
const imageData = await request.arrayBuffer()
const processed = wasmModule.resize(
new Uint8Array(imageData),
800, // width
600 // height
)
return new Response(processed, {
headers: { 'Content-Type': 'image/webp' },
})
},
}
Workers의 강점:
- 전 세계 300개 이상 데이터센터
- V8 isolate 기반 + Wasm 하이브리드 실행
- Workers KV, Durable Objects, D1(SQLite), R2(Object Storage) 통합
- 무료 티어: 일 10만 건 요청
4.3 Fastly Compute
Fastly Compute는 순수 Wasm 기반 엣지 컴퓨팅 플랫폼입니다.
// Fastly Compute 핸들러
use fastly::{Error, Request, Response};
#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
// 지리 정보 기반 라우팅
let geo = req.get_client_geo().unwrap();
let country = geo.country_code().unwrap_or("US");
let backend = match country {
"KR" | "JP" => "origin-apac",
"DE" | "FR" | "GB" => "origin-eu",
_ => "origin-us",
};
// 오리진으로 요청 전달
let mut beresp = req.send(backend)?;
beresp.set_header("X-Served-By", "fastly-compute-wasm");
Ok(beresp)
}
Fastly Compute의 차별점:
- 35마이크로초 미만의 콜드 스타트
- 순수 Wasm 실행 (V8 없음)
- Viceroy를 이용한 로컬 개발 환경
- 대역폭 과금 없음 (요청 수 기반)
4.4 플랫폼 비교
| 특성 | Spin/Fermyon | Cloudflare Workers | Fastly Compute |
|---|---|---|---|
| 런타임 | Wasmtime | V8 + Wasm | Wasmtime (커스텀) |
| 콜드 스타트 | 마이크로초 | 밀리초 | 35us 미만 |
| 언어 지원 | Rust, Go, JS, Python, C# | JS, Rust, C, C++ | Rust, Go, JS |
| 스토리지 | KV, SQLite, Redis | KV, D1, R2, DO | KV Store, Object Store |
| 엣지 노드 | 4,200+ (Akamai) | 300+ | 주요 POP |
| 무료 티어 | 있음 | 일 10만 건 | 있음 |
| 오픈소스 | Spin (Apache 2.0) | wrangler (MIT) | SDK (Apache 2.0) |
5. Wasm 런타임 비교 — 어떤 것을 선택할까
5.1 주요 런타임 개요
서버 사이드 Wasm을 실행하는 런타임은 여러 가지가 있습니다. 각각의 설계 철학과 최적화 포인트가 다릅니다.
5.2 상세 비교표
| 특성 | Wasmtime | WasmEdge | Wasmer | wazero |
|---|---|---|---|---|
| 개발사 | Bytecode Alliance | CNCF | Wasmer Inc. | Tetratelabs |
| 언어 | Rust | C++ / Rust | Rust | Go (순수) |
| 컴파일 전략 | Cranelift AOT/JIT | LLVM AOT + 인터프리터 | Cranelift/LLVM/Singlepass | 인터프리터 + 컴파일러 |
| WASI 지원 | 0.2 + 0.3 (선도) | 0.2 | 0.2 | Preview 1 |
| 컴포넌트 모델 | 완전 지원 | 부분 지원 | 부분 지원 | 미지원 |
| 임베딩 | Rust, C, Python, Go, .NET | Rust, C, Go, Python | Rust, C, Python, Go, JS | Go 네이티브 |
| 강점 | 표준 준수, 안정성 | AI/ML 최적화, 경량 | 패키지 매니저, WASI-X | 외부 의존성 제로, Go 통합 |
| 약점 | 상대적으로 큰 바이너리 | 컴포넌트 모델 지연 | 표준 준수 지연 | 기능 제한적 |
| 대표 사용처 | Spin, Fastly | 자동차, IoT, SaaS | 범용, 패키지 배포 | Go 기반 플랫폼 |
5.3 선택 가이드
질문 1: 주요 사용 언어가 Go인가?
├─ YES → wazero (외부 의존성 제로, CGo 불필요)
└─ NO
├─ 질문 2: 최신 WASI 표준 준수가 중요한가?
│ ├─ YES → Wasmtime (Bytecode Alliance, 표준 선도)
│ └─ NO
│ ├─ 질문 3: AI/ML 워크로드가 주요 목적인가?
│ │ ├─ YES → WasmEdge (GGML, TensorFlow Lite 통합)
│ │ └─ NO → Wasmer (범용, wapm 패키지 매니저)
5.4 성능 벤치마크 (2025년 기준)
HTTP "Hello World" 응답 시간 (p99, 마이크로초):
Wasmtime: ████████░░░░░░░░ 45us
WasmEdge: ████████░░░░░░░░ 48us
Wasmer: █████████░░░░░░░ 52us
wazero: ██████████░░░░░░ 62us
Node.js: ████████████████ 120us
Docker+Node: 극히 큰 값 (ms 단위)
6. Wasm + AI — 엣지에서의 AI 추론
6.1 왜 Wasm으로 AI를 실행하는가
AI 모델 추론을 엣지에서 실행하면 다음과 같은 이점이 있습니다.
- 지연 시간 감소: 클라우드로 왕복하지 않으므로 수십~수백 ms 절약
- 데이터 프라이버시: 사용자 데이터가 로컬/엣지에서 처리되어 외부로 나가지 않음
- 비용 절감: GPU 서버 대신 CPU 기반 엣지에서 경량 모델 실행
- 오프라인 지원: 네트워크 없이도 AI 기능 동작
6.2 ONNX Runtime + Wasm
ONNX Runtime은 Wasm 백엔드를 공식 지원합니다.
// ONNX Runtime Web (Wasm 백엔드) 예시
import * as ort from 'onnxruntime-web'
// Wasm 백엔드 설정
ort.env.wasm.numThreads = 4
ort.env.wasm.simd = true
async function classifyImage(imageData) {
const session = await ort.InferenceSession.create('mobilenet-v2.onnx', {
executionProviders: ['wasm'],
})
const tensor = new ort.Tensor('float32', preprocessImage(imageData), [1, 3, 224, 224])
const results = await session.run({ input: tensor })
return postprocess(results.output)
}
6.3 WasmEdge + LLM 추론
WasmEdge는 GGML/llama.cpp 통합을 통해 대형 언어 모델(LLM)을 Wasm 내에서 실행할 수 있습니다.
# WasmEdge로 LLM 실행
wasmedge --dir .:. \
--nn-preload default:GGML:AUTO:llama-2-7b-chat.Q4_K_M.gguf \
llm-chat.wasm
지원 모델:
- Llama 2 / 3 (Meta)
- Mistral / Mixtral
- Phi-2 / Phi-3 (Microsoft)
- Gemma (Google)
- 양자화 모델 (Q4, Q5, Q8)
6.4 Spin + AI 추론
Fermyon Spin은 서버리스 AI 추론을 위한 spin-llm 인터페이스를 제공합니다.
// Spin에서 LLM 추론
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::llm;
#[spin_sdk::http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
let prompt = req.body().as_str()?;
let result = llm::infer(
llm::InferencingModel::Llama2Chat,
prompt,
)?;
Ok(Response::builder()
.status(200)
.header("content-type", "text/plain")
.body(result.text)
.build())
}
6.5 AI 추론 성능 비교
| 환경 | 모델 | 토큰/초 | 첫 토큰 지연 | 메모리 |
|---|---|---|---|---|
| WasmEdge + GGML | Llama-2-7B Q4 | 약 12 | 약 500ms | 약 4GB |
| 네이티브 llama.cpp | Llama-2-7B Q4 | 약 15 | 약 400ms | 약 4GB |
| Spin AI | Llama-2-7B Q4 | 약 10 | 약 600ms | 약 4GB |
| ONNX Wasm | MobileNet-V2 | 약 30 FPS | 약 50ms | 약 20MB |
Wasm 환경에서의 AI 추론은 네이티브 대비 약 70~85% 수준의 성능을 보여주며, 보안과 이식성을 고려하면 충분히 실용적입니다.
7. Wasm vs 컨테이너 vs 서버리스 — 비교 분석
7.1 종합 비교표
| 특성 | Docker 컨테이너 | AWS Lambda | Wasm (Spin/Wasmtime) |
|---|---|---|---|
| 콜드 스타트 | 1~10초 | 100ms~수초 | 마이크로초 |
| 이미지/바이너리 크기 | 수십~수백 MB | 50MB (zip) | 수 KB~수 MB |
| 메모리 오버헤드 | 수십 MB | 128MB 최소 | 수 MB |
| 보안 격리 | 커널 네임스페이스 | Firecracker VM | 내장 샌드박스 |
| 이식성 | CPU 아키텍처 종속 | 클라우드 종속 | 어디서나 실행 |
| 네트워킹 | 완전 지원 | VPC 설정 필요 | WASI 기반 |
| 파일 시스템 | 완전 지원 | 임시 /tmp | WASI 가상 FS |
| 에코시스템 성숙도 | 매우 높음 | 높음 | 성장 중 |
| 디버깅 도구 | 풍부함 | CloudWatch | 개선 중 |
| 프로덕션 실적 | 10년 이상 | 9년 이상 | 2~3년 |
7.2 언제 무엇을 선택해야 하는가
Docker 컨테이너가 적합한 경우:
- 복잡한 시스템 의존성이 필요한 레거시 애플리케이션
- 장시간 실행되는 상태 유지(stateful) 서비스
- 완전한 파일 시스템/네트워크 접근이 필요한 경우
서버리스(Lambda)가 적합한 경우:
- 이벤트 드리븐 아키텍처
- 불규칙한 트래픽 패턴
- AWS 서비스와의 깊은 통합이 필요한 경우
Wasm이 적합한 경우:
- 마이크로초 수준 콜드 스타트가 필요한 엣지 배포
- 멀티 테넌트 환경에서 강력한 격리가 필요한 경우
- 플러그인/확장 시스템 (사용자 코드를 안전하게 실행)
- 크로스 플랫폼 CLI 도구 배포
7.3 하이브리드 접근법
현실에서는 하나만 선택하는 것이 아니라 조합하여 사용합니다.
┌──────────────────────────────────────────────────┐
│ 유저 요청 │
└─────────────┬────────────────────────────────────┘
v
┌─────────────────────────┐
│ 엣지 (Wasm/Spin) │ 인증, 캐시, A/B 테스트
│ - 마이크로초 응답 │ 지리 기반 라우팅
└─────────────┬───────────┘
v
┌─────────────────────────┐
│ 서버리스 (Lambda) │ 비즈니스 로직, API
│ - 이벤트 처리 │ DB 쿼리, 외부 API
└─────────────┬───────────┘
v
┌─────────────────────────┐
│ 컨테이너 (ECS/K8s) │ ML 학습, 배치 처리
│ - 장시간 작업 │ 상태 관리 서비스
└─────────────────────────┘
8. 실습: Rust로 Wasm 앱 빌드 및 배포
8.1 사전 준비
# Rust 설치 (이미 설치되어 있다면 건너뛰기)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Wasm 타겟 추가
rustup target add wasm32-wasip2
# Spin CLI 설치
curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash
sudo mv spin /usr/local/bin/
8.2 새 Spin 프로젝트 생성
# HTTP 핸들러 템플릿으로 프로젝트 생성
spin new -t http-rust my-wasm-api
cd my-wasm-api
8.3 비즈니스 로직 작성
// src/lib.rs
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use spin_sdk::key_value::Store;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct VisitorCount {
path: String,
count: u64,
last_visited: String,
}
#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
let path = req.path().to_string();
let method = req.method().to_string();
match (method.as_str(), path.as_str()) {
("GET", "/api/health") => health_check(),
("GET", "/api/visitors") => get_visitor_count(&path),
("POST", "/api/visitors") => increment_visitor(&path),
_ => Ok(Response::builder()
.status(404)
.body("Not Found")
.build()),
}
}
fn health_check() -> anyhow::Result<impl IntoResponse> {
Ok(Response::builder()
.status(200)
.header("content-type", "application/json")
.body(r#"{"status": "healthy", "runtime": "wasm"}"#)
.build())
}
fn get_visitor_count(path: &str) -> anyhow::Result<impl IntoResponse> {
let store = Store::open_default()?;
let count = store
.get(path)
.map(|bytes| String::from_utf8(bytes).unwrap_or_default())
.unwrap_or_else(|| "0".to_string());
Ok(Response::builder()
.status(200)
.header("content-type", "application/json")
.body(format!(r#"{{"path": "{}", "count": {}}}"#, path, count))
.build())
}
fn increment_visitor(path: &str) -> anyhow::Result<impl IntoResponse> {
let store = Store::open_default()?;
let current: u64 = store
.get(path)
.map(|bytes| String::from_utf8(bytes).unwrap_or_default())
.unwrap_or_else(|| "0".to_string())
.parse()
.unwrap_or(0);
let new_count = current + 1;
store.set(path, new_count.to_string().as_bytes())?;
Ok(Response::builder()
.status(200)
.header("content-type", "application/json")
.body(format!(r#"{{"path": "{}", "count": {}}}"#, path, new_count))
.build())
}
8.4 빌드 및 로컬 테스트
# 빌드
spin build
# 로컬 실행
spin up
# 다른 터미널에서 테스트
curl http://localhost:3000/api/health
# 출력: {"status": "healthy", "runtime": "wasm"}
curl -X POST http://localhost:3000/api/visitors
# 출력: {"path": "/api/visitors", "count": 1}
curl http://localhost:3000/api/visitors
# 출력: {"path": "/api/visitors", "count": 1}
8.5 Fermyon Cloud에 배포
# Fermyon Cloud 로그인
spin cloud login
# 배포
spin cloud deploy
# 출력 예시:
# Uploading my-wasm-api version 1.0.0...
# Deploying...
# Application deployed!
# URL: https://my-wasm-api-xyz123.fermyon.app
8.6 바이너리 크기 비교
빌드 결과물 크기:
Wasm 바이너리: 247 KB
Node.js (node_modules): 45 MB
Go 바이너리: 8.2 MB
Docker 이미지 (Node): 145 MB
Docker 이미지 (Alpine): 52 MB
9. 언어별 Wasm 지원 현황
9.1 Tier 1 — 프로덕션 레디
Rust
Rust는 Wasm 개발의 1등 시민(first-class citizen)입니다.
// Rust - 완전한 WASI 0.2 지원
use std::io::Write;
fn main() {
let mut stdout = std::io::stdout();
writeln!(stdout, "Hello from Rust + Wasm!").unwrap();
}
# 컴파일
cargo build --target wasm32-wasip2 --release
# 실행
wasmtime target/wasm32-wasip2/release/my-app.wasm
장점: 제로 런타임 오버헤드, 최소 바이너리 크기, 최고의 도구 지원 단점: 학습 곡선이 가파름
C / C++
// C - Emscripten 또는 wasi-sdk로 컴파일
#include <stdio.h>
int main() {
printf("Hello from C + Wasm!\n");
return 0;
}
# wasi-sdk로 컴파일
/opt/wasi-sdk/bin/clang hello.c -o hello.wasm
wasmtime hello.wasm
장점: 기존 C/C++ 코드베이스 재활용, 풍부한 라이브러리 단점: 메모리 안전성은 개발자 책임
9.2 Tier 2 — 프로덕션 가능 (일부 제약)
Go
// Go - TinyGo를 사용한 Wasm 컴파일
package main
import "fmt"
func main() {
fmt.Println("Hello from Go + Wasm!")
}
# TinyGo로 컴파일 (표준 Go도 WASI 지원 중)
tinygo build -target=wasip2 -o hello.wasm main.go
wasmtime hello.wasm
장점: 간결한 문법, 동시성 모델 단점: TinyGo 사용 시 표준 라이브러리 일부 미지원, 바이너리 크기가 Rust보다 큼
.NET / C#
// C# - .NET 8+ Wasm 지원
using System;
class Program {
static void Main() {
Console.WriteLine("Hello from C# + Wasm!");
}
}
# .NET 8 WASI 워크로드로 빌드
dotnet workload install wasi-experimental
dotnet build -c Release
wasmtime bin/Release/net8.0/wasi-wasm/my-app.wasm
9.3 Tier 3 — 실험적 / 개발 중
Python
# Python - componentize-py를 이용한 Wasm 변환
# 아직 실험적이지만 빠르게 발전 중
def handle_request(request):
return {
"status": 200,
"body": f"Hello from Python + Wasm!"
}
# componentize-py로 Wasm 컴포넌트 생성
componentize-py -d wit/ -w my-world componentize app -o app.wasm
JavaScript / TypeScript
// JavaScript - StarlingMonkey (SpiderMonkey 기반) 또는 javy
export function handleRequest(request) {
return {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: 'Hello from JS + Wasm!' }),
}
}
9.4 언어 지원 요약표
| 언어 | 도구 | WASI 버전 | 바이너리 크기 | 성숙도 | 비고 |
|---|---|---|---|---|---|
| Rust | cargo + wasm32-wasip2 | 0.2 / 0.3 | 수십~수백 KB | 프로덕션 | 1등 시민 |
| C/C++ | wasi-sdk / Emscripten | 0.2 | 수십~수백 KB | 프로덕션 | 기존 코드 활용 |
| Go | TinyGo / 표준 Go | 0.2 | 수백 KB~수 MB | 프로덕션 가능 | TinyGo 권장 |
| C# | .NET 8 WASI | 0.2 | 수 MB | 프로덕션 가능 | AOT 컴파일 |
| Python | componentize-py | 0.2 | 수십 MB | 실험적 | CPython 포함 |
| JS/TS | StarlingMonkey / javy | 0.2 | 수 MB | 실험적 | 런타임 포함 |
| Kotlin | Kotlin/Wasm | 브라우저 | 수 MB | 실험적 | 서버 지원 예정 |
| Swift | SwiftWasm | Preview 1 | 수 MB | 실험적 | 활발한 개발 |
10. 개발자 채택 로드맵
10.1 2025년 현재 상태
채택 곡선:
혁신가 초기 수용자 초기 다수 후기 다수 지각 수용자
(2019) (2022) (2025) (2027?) (2030?)
| | <<<현재>>> | |
▼ ▼ ▼ ▼ ▼
┌──┐ ┌────────┐ ┌──────────┐
│ │ │ │ │ │
│ │ │ │ │ 여기! │
└──┘ └────────┘ └──────────┘
Wasm MVP WASI P1 WASI 0.2/0.3
브라우저 서버 실험 프로덕션 배포
10.2 개발자를 위한 학습 경로
Phase 1: 기초 (1~2주)
- Wasm 개념 이해 (바이너리 형식, 스택 머신, 샌드박스)
- WAT(텍스트 형식) 읽기 연습
- 좋아하는 언어로 간단한 Wasm 모듈 컴파일
Phase 2: 서버 사이드 (2~4주)
- WASI 개념 이해 (파일, 네트워크, 환경 변수)
- Spin 또는 Cloudflare Workers로 첫 번째 엣지 앱 배포
- KV 스토어, 데이터베이스 연동
Phase 3: 프로덕션 (4~8주)
- 컴포넌트 모델과 WIT 인터페이스 학습
- 기존 서비스의 일부를 Wasm으로 마이그레이션
- 모니터링, 로깅, 에러 핸들링 구축
Phase 4: 고급 (8주 이상)
- 멀티 컴포넌트 아키텍처 설계
- AI 추론 워크로드 통합
- 커스텀 런타임 임베딩
10.3 2026년 이후 전망
- WASI 1.0 안정화: 2026년 말~2027년 초 예상
- 컴포넌트 레지스트리: npm/crates.io와 같은 Wasm 컴포넌트 패키지 매니저
- 디버깅 도구 성숙: 브레이크포인트, 프로파일링, 메모리 분석 도구
- 더 많은 언어 지원: Python, Ruby 등의 Tier 1 지원
- 표준화된 AI 인터페이스: wasi-nn의 안정화로 런타임 간 AI 모델 호환
11. 퀴즈
아래 퀴즈를 통해 WebAssembly에 대한 이해도를 확인해 보세요.
Q1. WebAssembly의 보안 모델에서 "Capability-based Security"란 무엇인가요?
정답: Wasm 모듈은 호스트가 명시적으로 부여한 기능(capability)만 사용할 수 있는 보안 모델입니다. 파일 시스템, 네트워크, 환경 변수 등에 대한 접근은 호스트가 허용한 범위 내에서만 가능합니다. 이는 전통적인 운영체제의 "기본 허용, 필요 시 차단" 방식과 반대로, "기본 차단, 필요 시 허용" 방식입니다.
Q2. WASI 0.3의 가장 중요한 혁신은 무엇이며, 이것이 서버 사이드 Wasm에 왜 중요한가요?
정답: WASI 0.3의 가장 중요한 혁신은 네이티브 비동기(async) 지원입니다. 이전 WASI 0.2에서는 poll 기반의 비효율적인 방식으로 비동기를 흉내 내야 했습니다. 네이티브 async가 지원됨으로써 서버 사이드에서 여러 요청을 동시에 효율적으로 처리할 수 있게 되어, 실제 프로덕션 워크로드를 감당할 수 있게 되었습니다.
Q3. Akamai의 Fermyon 인수가 Wasm 생태계에 어떤 의미를 가지나요?
정답: Akamai의 Fermyon 인수는 여러 의미를 가집니다. 첫째, Akamai의 전 세계 4,200개 이상의 PoP(Point of Presence)에서 Wasm 앱을 실행할 수 있게 됩니다. 둘째, 엣지 컴퓨팅 시장에서 Cloudflare Workers와의 본격적인 경쟁 구도가 형성됩니다. 셋째, 이는 Wasm이 더 이상 실험적 기술이 아닌 엔터프라이즈급 프로덕션 기술로 인정받았음을 의미합니다.
Q4. Wasm, Docker 컨테이너, AWS Lambda를 콜드 스타트 시간 기준으로 비교하세요.
정답: 콜드 스타트 시간 비교: Wasm은 마이크로초(us) 수준으로 가장 빠릅니다. AWS Lambda는 100밀리초에서 수 초 사이이며, Docker 컨테이너는 1초에서 10초 이상 걸릴 수 있습니다. Wasm이 이렇게 빠른 이유는 바이너리 크기가 작고(수 KB~수 MB), VM이나 OS를 부팅할 필요 없이 런타임이 직접 Wasm 모듈을 로드하기 때문입니다.
Q5. 서버 사이드 Wasm 개발에 가장 적합한 언어는 무엇이며, 그 이유는?
정답: 현재 서버 사이드 Wasm 개발에 가장 적합한 언어는 Rust입니다. 이유는 다음과 같습니다: (1) 제로 런타임 오버헤드로 최소 바이너리 크기 달성, (2) WASI 0.2/0.3 최신 표준을 가장 먼저 지원, (3) Spin, Wasmtime 등 핵심 도구가 Rust로 작성되어 도구 지원이 가장 풍부, (4) 메모리 안전성 보장. 다만 Go, C/C++도 프로덕션 수준이며, 팀의 기존 기술 스택에 따라 선택이 달라질 수 있습니다.
12. 마무리 — Wasm의 현재와 미래
2025년은 WebAssembly가 "흥미로운 실험"에서 "프로덕션 필수 기술"로 전환된 해입니다. WASI 0.3의 네이티브 async, Akamai의 Fermyon 인수, 그리고 Cloudflare/Fastly의 대규모 프로덕션 사례는 이를 명확히 보여줍니다.
핵심 요약:
- Wasm은 브라우저를 넘어 서버, 엣지, AI, IoT까지 확장되었습니다
- WASI 0.3의 네이티브 async로 서버 사이드 실용성이 크게 향상되었습니다
- 마이크로초 콜드 스타트와 내장 샌드박스는 컨테이너 대비 명확한 이점입니다
- Rust가 Wasm 개발의 최적 선택이지만, 다양한 언어 지원이 빠르게 확대 중입니다
- 엣지 컴퓨팅과 AI 추론에서 Wasm의 가치가 특히 빛납니다
Docker가 컨테이너로 인프라를 혁신했듯이, WebAssembly는 더 가볍고, 더 빠르고, 더 안전한 방식으로 컴퓨팅의 다음 장을 열고 있습니다. 지금이 바로 Wasm을 배울 최적의 시기입니다.
참고 자료
- WebAssembly 공식 사이트 — Wasm 스펙, 튜토리얼, 커뮤니티
- WASI.dev — WASI 표준 문서 및 로드맵
- Bytecode Alliance — Wasmtime, WASI 표준화 주도 조직
- Fermyon 공식 블로그 — Spin 프레임워크 및 Wasm 생태계 소식
- Cloudflare Workers 문서 — 엣지 Wasm 배포 가이드
- Fastly Compute 문서 — Wasm 기반 엣지 플랫폼
- WasmEdge 공식 사이트 — AI/ML 최적화 Wasm 런타임
- Wasmer 공식 사이트 — 범용 Wasm 런타임 및 패키지 매니저
- wazero GitHub — Go 네이티브 Wasm 런타임
- Component Model 문서 — 컴포넌트 모델 스펙
- ONNX Runtime Web — 브라우저/Wasm에서 AI 추론
- Spin 문서 — Spin 프레임워크 공식 가이드
- TinyGo Wasm 가이드 — Go에서 Wasm 개발
- Akamai의 Fermyon 인수 발표 — 2025년 3월 인수 공식 발표
- WebAssembly Weekly — Wasm 생태계 주간 뉴스레터
- Lin Clark의 Wasm 만화 시리즈 — 시각적 Wasm 입문