Go 언어 - 웹 어셈블리

검프·2021년 10월 30일
0

Go 언어 학습

목록 보기
9/9
post-thumbnail

Go 언에 버전 1.11부터 웹 어셈블리Web Assembly^{Web\ Assembly}를 지원합니다. 여기서는 간단히 웹 어셈블리 코드를 빌드하고 실행하는 방법에 대해서 살펴봅니다.

웹 어셈블리 샘플 코드 준비

우선 웹 어셈블리로 빌드 할 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로 용량 줄이기

TinyGoLLVM을 기반으로 하는 Go 언어 컴파일러입니다. 임베디드 환경이나 웹 어셈블리를 위한 더 작은 Go 언어 바이너리를 만들 수 있도록 지원해 줍니다.

TinyGo 설치

> 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로 컴파일 & 실행

> tinygo build -o main.wasm -target wasm main.go
> cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js .

결과 확인

결과는 같지만, 용량이 58KB 가량으로 무려 1/23로 줄어듭니다.

profile
권구혁

0개의 댓글