lechuck.dev

Go를 사용해 WASM 개발하기

마지막 업데이트:

특징

개발 환경

WASM 모듈 작성

여기서 작성할 WASM 모듈은 스터디 발표 순서를 정하기 위한 제비 뽑기를 하는 함수를 만들어 보겠습니다.

package main

import (
    "encoding/json"
    "math/rand"
    "syscall/js"
    "time"
)

func main() {
    done := make(chan struct{}, 0)
    // drawLots 함수를 자바스크립트 전역 스코프에 wasmDrawLots 라는 이름으로 등록합니다.
    js.Global().Set("wasmDrawLots", js.FuncOf(drawLots))
    // 채넗을 사용해 main 함수가 종료되지 않도록 합니다.
    <-done
}

// drawLots 함수는 1개의 파라미터를 입력값으로 받습니다.
// 파라미터 1:
// - 'Record<string, number>' 형식의 값을 JSON.stringify()를 적용한 값
// - 키: 이름, 값: 가중치             
// 반환값: 발표자 이름 (string 타입))
func drawLots(this js.Value, args []js.Value) interface{} {
    // dlqfur 파라미터 개수 확인
    if len(args) != 1 {
        panic("invalid argument count")
    }

    // 파라미터 1 을 map[string]uint32 형식으로 파싱
    jsonArg := args[0].String()
    var targets map[string]uint32
    if err := json.Unmarshal([]byte(jsonArg), &targets); err != nil {
        panic(err)
    }

    return drawLotsImpl(targets)
}

// ...

JavaScript -> Go 타입 변환

Go -> JavaScript 타입 변환

빌드

바이너리는 GOOS, GOARCH 환경변수를 js, wasm으로 설정해 빌드합니다.

$ GOOS=js GOARCH=wasm go build -o main.wasm

배포

빌드된 *.wasm 파일을 배포할 때, 빌드한 Go 버전에서 제공하는 wasm_exec.js 파일을 같이 배포해야 합니다.

$ cp -f "$(go env GOROOT)/misc/wasm/wasm_exec.js" ../frontend/
$ cp -f main.wasm ../frontend/

웹 브라우저에서 사용

HTML 파일에서 다음과 같이 wasm_exec.js 파일을 로드해 초기화 작업을 수행합니다. 좀 더 자세한 내용은 https://github.com/golang/go/wiki/WebAssembly#getting-started 에서 확인할 수 있습니다.

<!DOCTYPE html>
<html lang="ko-KR">

<head>
  <title>WASM</title>
  <meta charset="utf-8" />
  <script src="wasm_exec.js"></script>
  <script>
    const go = new Go();
    WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
      const wasm = result.instance;
      go.run(wasm);
    });
  </script>
</head>

<body>
  <button onclick="onRun()">Run</button>
  <script>
    function onRun() {
      const result = wasmDrawLots(JSON.stringify({
        "foo": 10,
        "bar": 10,
        "foobar": 10,
      }));
      console.log("result:", result);
    }
  </script>
</body>

</html>

실행방법

위의 HTML 파일이 동작화도록 하려면 웹 서버를 띄운 상태에서 index.html 파일을 열어야 합니다.

여기서는 간단하게 파이썬에 내장되어 있는 HTTP 서버를 사용해 실행해보겠습니다.

# wasm 빌드 -> html 디렉토리에 배포
$ task dist-go
$ cd html
# HTTP 서버 실행
$ python3 -m http.server
  1. http://localhost:8000 접속
  2. 개발자 도구 콘솔 창 표시
  3. “Run” 버튼을 눌러 결과가 표시되는지 확인

참고문서