WebAssembly 컴포넌트가 코어 Wasm 위에 추가로 존재하는 이유와, ABI/패키징/조합을 표준화해 웹과 웹 밖에서 재사용 가능한 스택을 만드는 방식, 그리고 Rust 생태계에서의 변화 방향을 설명한다.
— 2026-03-12
어제 Making WebAssembly a First-Class Language on the Web가 소셜 미디어에서 화제가 되었고, 나는 이 Wasm Component라는 것에 대해 혼란스러워하는 사람들을 몇몇 보았다. WebAssembly를 만드는 사람들이 왜 WebAssembly 위에 뭔가를 구현하느라 이렇게까지 고생을 하고 있는 걸까? 그리고 왜 Firefox 같은 브라우저 벤더들이 애초에 구현을 시작하는 것이 흥미로운 걸까?
내가 이걸 설명하기 시작한 방식은, WebAssembly와 Linux, Windows 같은 다른 호스트 플랫폼 사이의 유사점을 끌어오는 것이다. Wasm은 대부분의 다른 호스트 플랫폼과 달리 _가상_이라는 점에서 조금 다르다. 플랫폼별 어셈블리를 직접 만들어내는 대신, 나중에 플랫폼별 어셈블리로 변환할 수 있는 가상 어셈블리를 만들어낸다. 그리고 자체 커널을 호스팅하는 대신, Wasm 호스트는 보통 또 다른 호스트 위에서 실행된다.
하지만 WebAssembly 자체는 그저 명령어 집합이다. 숫자, 포인터, 그리고 그다지 많지 않은 것들만 다룰 수 있다. 웹 안팎의 호스트 API와 상호작용하려면, ABI를 정의하고 호스트와 Wasm 게스트 양쪽에 글루 코드를 설정해 둘 사이를 연결해야 한다.
하지만 이는 Wasm에만 해당하는 일이 아니다. 모든 호스트가 해야 하는 일이다. 일반적으로 이를 위해서는 총 네 개의 계층이 정의되어야 한다:
x86, ARM 등.ELF, exe, Mach-O 등.C 헤더, WinMD, Mach IDL 등.Win32, POSIX, Darwin 등.Wasm Components는 코어 Wasm 명령어에 대한 컨테이너 형식 (2)일 뿐이다. 그리고 그 컨테이너가 import/export할 수 있는 API를 정의하기 위해 IDL (3)을 사용한다. 그 시스템 호출(4) 집합 중 하나가 WASI, 즉 WebAssembly System Interfaces다. 하지만 Wasm Components는 WASI에만 묶여 있지 않다. 전체 스택은 웹을 대상으로 재사용될 수도 있다. 그것이 “Making WebAssembly First-Class on the Web”이 말하는 바다.
참고로 Linux, Windows, macOS, WebAssembly를 표로 나란히 놓으면 다음과 같다:
| WebAssembly | Linux | Windows | macOS | |
|---|---|---|---|---|
| Instruction Format | Core Wasm | x86, ARM, etc. | x86, ARM | ARM |
| Container Format | Wasm Components | Executable and Linkable Format (ELF) | Portable Executable (PE) | Mach-O |
| Interface Definition Language | Wasm Interface Types (WIT) | C header files | Windows Metadata (WinMD) | (Objective-)C header files + Mach IDL + Swift Modules |
| System Interfaces | Wasm System Interface (WASI) | POSIX + Linux User-Space APIs | Win32 + UWP | POSIX + Darwin Syscalls |
Wasm Components가 명령어의 패키징, 조합, ABI를 표준화하지 않으면, 각 Wasm 생태계가 그런 것들을 각자 결정해야만 한다. Wasm 초창기에 우리는 이를 보았는데, wasm-bindgen의 출력은 WASI 0.1에서 쓰이던 것과 완전히 다른 형식이었다. 그것이 부분적으로는 Rust 컴파일러에 “wasm-web” 타깃 지원이 들어오지 못했던 이유이기도 하다.
하지만 Wasm Components로 인해 이것이 바뀌고 있다. 우리는 Rust 2026 로드맵에 Wasm Component 프로젝트 목표를 추가했는데, 여기에는 다음이 포함된다:
wasm32-component, wasm32-wasip3).wasm32-wasip3 타깃에 std::thread 지원 추가.wasm32-wasip3 타깃에 async fn main 구현wasm32-component-web 타깃 지원 추가.아이디어는 웹 타깃이 wasm32-component 타깃과 동일하되, 크레이트 생태계를 구축하는 데 중요한 #[cfg(web)] 같은 것에 접근할 수 있다는 점만 다르게 하는 것이다. 그리고 wasm32-component 타깃은 wasm32-wasip3 타깃과 거의 동일하되, std는 구현하지 않고 core와 alloc만 구현한다.
마무리하자면: Wasm 명령어를 위한 표준 패키징 형식이 없이는 이 작업들 중 어느 것도 실용적일 수 없다. 예를 들어 gcc, clang, msvc가 Windows용 바이너리가 어떻게 생겨야 하는지에 대해 서로 합의하지 못한다면 그건 미친 짓일 테니 말이다. Wasm Components는 모든 호스트 시스템이 각자 해결책을 갖고 있는 역할을 채운다. 그리고 개인적으로는 우리가 마침내 이 격차를 메우고 있다는 점이 기쁘다. 웹 안팎에서 모두 동작할 수 있고, 컴파일러가 네이티브로 지원하는 단일 형식으로 천천히 수렴하고 있다.
View all references