.wasm
바이너리 파일의 크기를 더 작게, 더 빠르게 만들어 빠른 네트워크 로딩을 달성할 수 있다.cargo-generate
로 wasm 프로젝트의 템플릿을 다운로드 받는다.
cargo install cargo-generate # if don't have
cargo generate --git <https://github.com/rustwasm/wasm-pack-template>
cargo-generate
는 복붙하려는 새 프로젝트 이름을 물어본다. 이때 내가 원하는 이름 (예를 들어 game-of-life-wasm
)을 입력하면 자동으로 보일러 플레이트를 생성해준다.
이제 wasm-pack
프로그램으로 패키지를 빌드 및 웹 어셈블리 코드 생성을 동시에 진행한다.
wasm-pack build
create-wasm-app JS 프로젝트 템플릿을 다운로드 받는다.
rust wasm 패키지를 webpack에 담가주는 템플릿. 단순히 내가 배포하려는 패키지 루트에서 다음 명령어를 실행하면 된다. 그러면 www
라는 이름의 새 디렉토리가 생성되고 그 안에 node.js 패키지를 위한 파일들이 생성된다.
npm init wasm-app www
incremental build를 위해서 사전 작업을 수행했다. www/package.json
파일에 루트 폴더의 wasm 바이너리가 들어있는 폴더를 의존하도록 만들었다.
..."dependencies": { "game-of-life-wasm": "file:../pkg" }
그리고 index.js
파일에 placeholder로 달려있던 임포트 구문을 자연스럽게 game-of-life-wasm
으로 바꾸어 주었다.
import * as wasm from "game-of-the-life-wasm";
wasm.greet();
npm install
, npm run start
명령으로 간단하게 웹을 띄울 수 있다. 다음 캡처는 기본 템플릿에 제공된 함수의 작동을 보여준다.
WA는 단지 선형 메모리 공간을 JS에게 제공할 뿐이다. WA는 반대로 JS가 점유하는 힙 영역의 공간을 참조할 수 없다. 상당히 제약적인 것이다! JS는 오직 WA의 배열버퍼(u8
, i32
, f64
, 등)만 가지고 WA의 메모리 공간을 참조할 수 있다. WA 함수는 오직 스칼라 값들만 리턴할 수 있다. WA는 JS의 전역 객체(Math, Intl, JSON, Array, BigInt 등등) 를 참조할 수 있다고 한다. [[js-sys crate]]를 이용하면 된다고..
wasm_bindgen
은 우리가 처음에 cargo generate
를 통해 불러온 템플릿 패키지가 이미 의존하던 크레이트다. wasm_bindgen
은 Rust 영역과 JS 영역간에 경계를 넘나드는 공통 인터페이스를 제공해준다. Rust 구조체 인스턴스를 #[wasm_bindgen]
attribute로 JS 객체로 활용할 수 있게 만들어주고, 반대로 JS 객체를 JsValue
인터페이스를 경유해 사용가능하도록 만든다.
graph LR
Rust -- "#[wasm_bindgen]" --> JavaScript
JavaScript -- "JsValue" --> Rust