Go 언에 버전 1.11부터 웹 어셈블리를 지원합니다. 여기서는 간단히 웹 어셈블리 코드를 빌드하고 실행하는 방법에 대해서 살펴봅니다.
우선 웹 어셈블리로 빌드 할 Go 언어 소스코드를 준비합니다. main.go
파일은 웹 어셈블리로 빌드 됩니다. index.html은
빌드 된 웹 어셈블리를 로드하여 실행합니다.
// main.go package main // syscall/js 패키지는 타깃 아키텍처로 wasm을 사용할 때 // Web Assembly 호스트 환경에 Javascript API에 대한 엑세스를 제공합니다. import "syscall/js" func main() { // 런타임에 표준 출력은 웹 브라우저 콘솔에 바인딩 되므로, // WASM 로딩이 완료되면 웹 브라우저 콘솔에 출력됩니다. println("Wasm loaded.") // js.Global() 함수는 Javascript Global 네임스페이스에 엑세스합니다. alert := js.Global().Get("alert") // alert 함수를 호출합니다. alert.Invoke("Hello Wasm!") } // "export add" 주석을 이용해 Javascript에 add 함수를 exports 합니다. // 두 개의 32bit 정숫값을 받아서 하나의 32bit 정숫값을 반환하는 함수입니다. //export add func add(x int, y int) int { return x + y }
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Go+Wasm</title> <!-- 웹 브라우저에서 Go 언어로 작성한 웹 어셈블리 파일을 실행하기 위하여 Go 언어에서 제공하는 Javascript Glue code를 불러옵니다. --> <script src="wasm_exec.js"></script> <script> const go = new Go(); WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject) .then((wasmModule) => { // 웹 어셈블리 로딩 go.run(wasmModule.instance); // 웹 어셈블리에서 제공하는 add 함수 호출 console.log(wasmModule.instance.exports.add(3, 4)); }); </script> </head> <body></body> </html>
Go 언어 버전 1.11 이상에서 GOOS=js GOARCH=wasm
으로 설정하면 WASM으로 컴파일 할 수 있습니다.
> GOOS=js GOARCH=wasm go build -o main.wasm main.go
wasm_exe.js
를 복사합니다.
> cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
확인을 위해서 로컬 웹 서버를 실행하겠습니다. goexec CLI를 사용하겠습니다. goexec를 이용해 로컬 파일 서버를 실행합니다.
> go install github.com/shurcooL/goexec > goexec 'http.ListenAndServe(":1234", http.FileServer(http.Dir(".")))'
몇 줄 안되는 코드로 웹 어셈블리를 만들고 실행할 수 있습니다!
웹 어셈블리의 Content-Type은 application/wasm
입니다. 그런데 용량이? 대략 1.3MB입니다. 많이 크네요. 전송 시 압축을 한다면 용량이 줄어들겠지만, 그래도 기능에 비해서 용량이 너무 큽니다. TinyGo를 이용해 해결해 보겠습니다.
TinyGo는 LLVM을 기반으로 하는 Go 언어 컴파일러입니다. 임베디드 환경이나 웹 어셈블리를 위한 더 작은 Go 언어 바이너리를 만들 수 있도록 지원해 줍니다.
> brew tap tinygo-org/tools > brew install tinygo > tinygo version tinygo version 0.20.0 darwin/amd64 (using go version go1.17 and LLVM version 11.0.0)
> tinygo build -o main.wasm -target wasm main.go > cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js .
결과는 같지만, 용량이 58KB 가량으로 무려 1/23로 줄어듭니다.