Rust로 Web Assembly 셋업(with wasm-pack)
[wasm
웹어셈블리
rust
wasm-pack
]
wasm을 하기에는 pyodide는 아닌 것 같고, rust로 방향을 틀었다.
여러 가지 방법을 시도해 보았으나 가장 좋은 방법은 wasm-pack을 사용하는 것으로 결론지었다. *.wasm 파일을 바로 만들어 javascript 로 로딩하는 방법을 써 보았지만 application-wasm에 대한 등록 문제 등 생각치도 못한 문제들을 많이 만나게 되었다.
이 글은 wasm-pack에 대한 공식 홈 페이지
https://rustwasm.github.io/docs/book/introduction.html
를 따라 한 것이며, 중간에 발생하는 문제점들을 추가하였다.
내가 테스트한 환경은 다음과 같다.
- ubuntu 20.04 LTS
- 2CPU mem 4G
Setup
1. Rust 설치
- Rust 를 설치한다. 여기서는 ubuntu용 rust를 사용했다.
2. wasm-pack 설치
-
그 다음에 wasm-pack을 설치한다. wasm-pack은
https://rustwasm.github.io/wasm-pack/installer/
를 참조하기 바란다.
3. cargo-generate 설치
-
github 에 있는 여러 rust관련 프로젝트 템플릿을 참조하여 빠르게 Rust 프로젝트를 구성해주는 것이다. 다음 명령으로 설치를 시도했다.
cargo install cargo-generate
-
openSSL관련 오류가 뜨면서 설치가 안되는 경우가 있다. pkg-config가 없어서 발생하는 문제이므로 이를 설치해 준 후에 재시도 한다.
sudo apt install pkg-config
-
이 과정은 시간이 좀 오래 걸린다.
4. npm 설치
-
웹에서 보여주기 위해 node 도 필요하다.
npm install npm@latest -g
이제 Hello World를 찍어보도록 하겠다.
Hello World
1. clone Project Templete
-
cargo-generate를 사용해 Project Templete를 복제한다.
cargo generate --git https://github.com/rustwasm/wasm-pack-template
-
진행하다 보면 프로젝트 명을 입력하는 부분이 있는데 공식 홈페이지에서는 wasm-game-of-life를 사용했으나 여기서는 wasm-example로 하겠다.
2. 프로젝트 폴더
- 프로젝트 폴더에는 다음과 같은 구조로 되어 있다.
wasm-example/
├── Cargo.toml
├── LICENSE_APACHE
├── LICENSE_MIT
├── README.md
└── src
├── lib.rs
└── utils.rs
- 각 파일에 대한 설명은 공식 홈페이지에 잘 나와 있으니 참조하기 바란다.
- wasm 수행 코드는
lib.rs
에 반영시키면 된다.
3. 프로젝트 빌드
-
프로젝트빌드는
wasm-pack
명령으로 수행한다.wasm-pack build
-
그러면 pkg 폴더가 생성되고 거기에 빌드 결과물이 들어있을 것이다.
pkg
├── README.md
├── package.json
├── wasm_example.d.ts
├── wasm_example.js
├── wasm_example_bg.js
├── wasm_example_bg.wasm
└── wasm_example_bg.wasm.d.ts
4. 연결되는 웹 프로젝트 생성
-
wasm_example
폴더에서 npm으로 웹 프로젝트 생성 명령을 실행한다.npm init wasm-app www
-
상황에 따라 다음과 같은 오류가 뜨면서 www 가 생성안되는 경우가 있다.
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ], library: 'digital envelope routines', reason: 'unsupported', code: 'ERR_OSSL_EVP_UNSUPPORTED'
이는 node 버전이 너무 높아 발생하는 경우이다. node 16.x 이하로 낮추어 재시도 한다.
-
정상적으로 완료되면
www
폴더가 생성되며 다음과 같은 파일들이 생성된다wasm-example/www/ ├── bootstrap.js ├── index.html ├── index.js ├── LICENSE-APACHE ├── LICENSE-MIT ├── package.json ├── README.md └── webpack.config.js
5. 웹 프로젝트와 wasm의 연결
-
웹 프로젝트와 위 wasm프로젝트의 연결 포인트는
index.js
파일이다. 여기의 소스코드는 다음과 같다import * as wasm from "hello-wasm-pack"; wasm.greet();
-
현재는 디폴트로
hello-wasm-pack
을 import하고 있는데 우리는 위에서 pkg로wasm_example
로 만들었으므로 이를wasm_example
로 바꾸어 준다.import * as wasm from "wasm_example"; wasm.greet();
-
웹 프로젝트의
package.json
파일에서 위에서 만든 pkg폴더에 종속 관계(dependencies
)를 추가해 준다."devDependencies": { "copy-webpack-plugin": "^5.0.0", ... }, "dependencies": { "wasm_example": "file:../pkg" }
6. 개발 실행
npm install
로 필요 패키지를 다운로드npm run start
로 실행하여 정상적으로alert()
이 수행되면 성공
-
npm run build
를 실행하면/www
밑에/dist
폴더가 생성되며, 배포 버전이 wasm파일과 함께 있는 것을 알 수 있다.. ├── 0.bootstrap.js ├── 83ae667d8fb6fa92a993.module.wasm ├── 8e8fa9289c240ac706a1.module.wasm ├── bootstrap.js └── index.html
Rust로 Web Assembly를 그냥 하면 어렵지만 wasm-pack을 이용하면 큰 설정 없이 쉽게 할 수 있다고 해서 시도를 해 보았지만, 이 역시 여러가지 환경적 문제들(pkg관리자, node버전 등)을 해결해야 했었다.
하지만 vue나 react와 같은 개발 구조를 제공하므로서 좀 더 Web Assembly를 개발하기 쉽게 만들었다는 점은 높이 살 만 하겠다.