웹어셈블리로 지금 당장 배포할 수 있는 6가지 언어

웹어셈블리로 지금 당장 배포할 수 있는 6가지 언어

러스트, 고, 자바스크립트, C/C++ 그리고 파이썬은 모두 웹어셈블리에서 실행할 수 있는 언어다. 각 언어의 특징과 배포 시 알아둬야 할 핵심 내용을 정리했다.

Credit: PeopleImages
웹어셈블리(WebAssembly, Wasm)는 브라우저를 포함해 Wasm 런타임을 배포할 수 있는 어떤 환경에서든 네이티브 수준의 속도로 실행되는 프로그램을 만들 수 있는 방법을 제공한다. 하지만 대부분의 경우 Wasm 언어로 직접 코드를 작성하지는 않는다. 대신, 러스트나 C/C++처럼 Wasm으로 바꾸기 쉬운 언어로 프로그램을 만든 다음, 이를 Wasm 형식으로 컴파일해서 실행한다. 즉, Wasm은 일종의 실행용 포맷이고, 실제 코딩은 다른 언어로 한다고 보면 된다.

이 6가지 언어(C와 C++은 별도로 셌다)는 모두 서로 다른 툴을 통해 Wasm 런타임에서 실행할 수 있다. 다만, 언어마다 Wasm과의 호환성이나 배포 난이도는 조금씩 다르다. 만약 자신이 사용하는 언어를 Wasm으로 배포할 수 있을지 고민 중이라면, 해당 언어가 Wasm 환경에 얼마나 잘 맞는지 먼저 살펴보는 것이 좋다. 이 글에서는 언어별로 Wasm에 얼마나 쉽게 배포할 수 있는지, 그리고 배포 과정에서 어느 정도의 작업이 필요한지 소개한다.

러스트
러스트는 여러 면에서 Wasm에 가장 적합한 언어다. 기존 러스트 코드 대부분은 큰 수정 없이 그대로 Wasm으로 컴파일할 수 있으며, 필요한 변경사항도 주로 컴파일 타깃과 설정을 조정하는 정도에 그친다. 또한 관련 툴이 자동으로 자바스크립트 보일러플레이트 코드도 생성해 주기 때문에, 컴파일된 Wasm 모듈을 웹페이지와 바로 연동해 사용할 수 있다.

컴파일된 모듈의 크기는 상황에 따라 달라지지만, 러스트는 비교적 작고 효율적인 코드를 생성할 수 있다. 간단한 “Hello, world” 프로그램은 몇 킬로바이트 정도에 불과하다. 러스트 개발진은 러스트에서 Wasm을 사용하는 방법에 대한 전용 가이드를 작성해두었다. 이 문서에는 바이너리 크기를 최소화하는 방법과 기존 범용 러스트 크레이트에 Wasm 지원을 추가하는 방법 등이 자세히 설명돼 있다.

C/C++
C와 C++는 Wasm로 컴파일된 최초의 언어 중 하나다. 이는 두 언어가 가지고 있는 저수준의 동작 방식이 Wasm의 명령어 집합과 잘 맞아떨어지기 때문이다. Wasm이 처음 주목받기 시작했을 때 선보인 여러 데모도 대부분 C/C++로 작성된 그래픽 데모나 게임을 포팅한 것이었다. 이런 개념 증명 프로젝트는 “브라우저에서 둠(Doom)을 실행할 수 있다!”는 식의 강한 인상을 남기며 Wasm 기술의 가능성을 널리 알리는 데 큰 역할을 했다.

C/C++를 Wasm으로 컴파일하기 위해 개발된 첫 번째 툴 중 하나가 바로 엠스크립튼(Emscripten) 툴체인이다. 현재 엠스크립튼은 C 또는 C++ 코드를 Wasm으로 포팅하는 데 필요한 다양한 기능과 가이드를 갖춘 본격적인 툴체인으로 발전했다. 엠스크립튼은 SIMD(웹어셈블리에서 지원됨), 네트워킹, C++ 예외 처리, 비동기 코드 등 고급 기능도 Wasm으로 옮길 수 있도록 지원하는데 기능별로 포팅 난이도에는 차이가 있다. 예를 들어 pthread 지원은 기본 설정으로는 활성화돼 있지 않으며, 브라우저에서 제대로 작동하려면 웹 서버에 특정 오리진 헤더(origin headers)가 정확히 설정돼 있어야 한다.


클랭(Clang) C/C++ 컴파일러는 버전 8부터 별도의 툴 없이도 Wasm으로 직접 컴파일할 수 있다. 다만, 엠스크립튼도 클랭과 동일한 기반 기술인 LLVM 컴파일러 프레임워크를 사용하며, Wasm 컴파일에 특화된 보다 완성도 높은 도구 세트를 함께 제공하기 때문에 여전히 유용하게 활용할 수 있다.

고랭
고 언어는 2018년 8월 출시된 버전 1.11에서 Wasm을 컴파일 타깃으로 지원하기 시작했다. 처음에는 실험적인 프로젝트로 시작됐지만, 현재는 비교적 안정적으로 Wasm을 타깃으로 설정할 수 있다. 다만 몇 가지 주의할 점은 여전히 존재한다.

러스트와 마찬가지로, 고 프로그램을 Wasm용으로 만들 때는 코드 자체를 수정하기보다는 컴파일 과정을 변경하는 것이 대부분이다. Wasm용 툴체인은 고 컴파일러에 기본으로 포함돼 있어 별도의 도구나 패키지를 설치할 필요는 없다. 단지 컴파일 시 GOOS와 GOARCH 환경 변수를 변경해주기만 하면 된다. 다만, Wasm으로 컴파일한 고 모듈을 웹에서 사용하려면 자바스크립트 보일러플레이트를 수동으로 설정해야 한다. 하지만 이 작업은 복잡하지 않고 몇 개의 파일을 복사하는 정도로 충분하다. 필요하다면 이 과정을 자동화할 수 있다.

고를 Wasm으로 사용할 때 가장 까다로운 부분은 DOM과의 상호작용이다. 이를 위해 고에서는 syscall/js 패키지를 제공하지만, 기본적인 조작 수준을 넘어서는 작업에서 사용할 때는 다소 불편하다. 복잡한 작업을 하려면 목적에 맞는 서드파티 라이브러리를 사용하는 것이 좋다.

고를 Wasm과 함께 사용할 때의 또 다른 단점은 생성되는 바이너리 파일의 크기다. 고는 런타임이 포함돼 있기 때문에 단순한 “Hello, world” 프로그램조차도 바이너리 크기가 최대 2메가바이트에 이를 수 있다. 물론 Wasm 바이너리를 압축해 용량을 줄일 수는 있고, 타이니고(TinyGo) 같은 다른 고 런타임을 사용하는 방법도 있다. 다만, 타이니고는 고 언어의 일부 기능만 지원하기 때문에 사용에 제한이 따른다.

자바스크립트
자바스크립트를 Wasm로 변환하는 작업은 다소 불필요해 보일 수 있다. 어차피 Wasm의 주요 실행 환경은 브라우저이고, 대부분 브라우저에는 자바스크립트 런타임이 기본으로 탑재돼 있기 때문이다. 그럼에도 불구하고, 원한다면 자바스크립트 코드를 Wasm으로 컴파일할 수 있다.

자바스크립트를 Wasm으로 변환할 수 있는 대표적인 툴은 자비(Javy)다. 이 도구는 웹어셈블리 생태계를 주도하는 바이트코드 얼라이언스(Bytecode Alliance)가 개발 및 지원한다. 자비는 자바스크립트 코드를 Wasm으로 직접 컴파일한다기보다는, Wasm 기반의 자바스크립트 런타임에서 코드를 실행하는 방식이다. 또한 생성된 Wasm 모듈의 크기를 적절하게 줄이기 위해 동적 링킹 전략도 사용한다. 다만 최종 모듈의 크기는 프로그램에서 사용하는 기능에 따라 달라질 수 있다.

파이썬
파이썬의 Wasm 지원 상황은 고와 비슷하지만, 한계는 더 뚜렷하다. 파이썬 프로그램은 파이썬 런타임 없이 실행할 수 없으며, 기본 표준 라이브러리 없이는 실질적인 작업이 거의 불가능하다. 여기에 수많은 서드파티 패키지 생태계까지 고려하면 파이썬을 Wasm에서 실행하는 것은 상당히 부담스러운 작업이다. 현재로서 파이썬은 Wasm 런타임을 통해 실행할 수는 있지만, 실행 환경이 무겁고 다루기 번거롭다. 게다가 파이썬을 Wasm에서 원활히 실행하기 위한 툴체인도 아직 충분히 정돈되지 않아 사용성 면에서도 아쉬움이 있다.

파이썬 애플리케이션을 Wasm 런타임에서 실행하는 대표적인 방법은 파이오다이드(Pyodide)다. 이는 C파이썬(Cpython) 런타임을 엠스크립튼을 통해 Wasm으로 포팅한 프로젝트다. 이 구현체 중 하나인 파이스크립트(PyScript)는 자바스크립트처럼 웹페이지 내에서 파이썬 코드를 실행할 수 있게 해준다. 또한 파이썬과 자바스크립트/DOM 간의 양방향 통신도 지원해 상호작용이 필요한 웹 애플리케이션 개발에 활용할 수 있다.

하지만 파이오다이드에는 여러 한계가 존재한다. 예를 들어 넘파이(NumPy)처럼 C 확장 모듈을 사용하는 패키지는 파이오다이드에서 작동하도록 수동으로 포팅해야 한다. 따라서 PyPI에서 설치할 수 있는 패키지는 순수 파이썬으로 작성된 것에 한정된다. 또한 파이썬 런타임을 포함한 Wasm 패키지를 다운로드해야 하는데, 이 파일 크기가 수 메가바이트에 이른다. 따라서 언어를 실행할 때마다 예상치 못한 대용량 다운로드가 발생할 수 있어 사용자에게 부담이 될 수 있다. | dl-itworldkorea@foundryco.com

0 댓글