WebAssembly 입문서 : WebAssembly 시작하기

WebAssembly는 완전히 새로운 종류의 웹을 약속합니다. 사용자에게는 더 빠른 성능, 개발자에게는 더 많은 유연성이 있습니다. 클라이언트 측 웹 상호 작용을위한 유일한 언어로 JavaScript를 사용하는 대신 개발자는 C, TypeScript, Rust, Ruby, Python과 같은 광범위한 다른 언어 중에서 선택하고 가장 편한 언어로 작업 할 수 있습니다. 와.

원래 WebAssembly (또는 줄여서 WASM)를 만드는 유일한 방법은 Emscripten 툴체인을 사용하여 C / C ++ 코드를 WebAssembly로 컴파일하는 것입니다. 오늘날 개발자는 더 많은 언어 옵션을 사용할 수있을뿐만 아니라 개입 단계를 줄이면서 이러한 다른 언어를 WebAssembly로 직접 컴파일하는 것이 더 쉬워졌습니다.

이 글에서는 웹앱에서 WebAssembly 구성 요소를 구현하는 데 필요한 단계를 살펴 보겠습니다. WebAssembly는 진행중인 작업이므로 단계는 사용하는 언어에 따라 크게 달라지며 도구 체인은 한동안 계속 변경 될 수 있습니다. 그러나 지금 당장은 유용한 WebAssembly 애플리케이션을 여러 언어로 작성하고 배포 할 수 있습니다.

WebAssembly 지원 언어 선택

WebAssembly 애플리케이션을 배포하기위한 첫 번째 단계는 WebAssembly로 컴파일 할 수있는 언어를 대상으로 선택하는 것입니다. 프로덕션에서 사용중인 주요 언어 중 하나 이상을 WebAssembly로 변환 할 수 있거나 WebAssembly를 내보낼 수있는 컴파일러가있을 가능성이 높습니다.

선두 주자 :

  • C. 분명히. C 코드를 WebAssembly로 전환하는 일반적인 방법은 Emscripten을 사용하는 것입니다. C-to-Emscripten-to-WebAssembly가 함께 제공되는 최초의 WebAssembly 도구 체인이기 때문입니다. 그러나 다른 도구가 등장하고 있습니다. 전체 컴파일러 인 Cheerp는 C / C ++ 코드에서 WebAssembly 애플리케이션을 생성하도록 특별히 설계되었습니다. Cheerp는 JavaScript, asm.js 또는 위의 조합을 타겟팅 할 수도 있습니다. Clang 도구 모음을 사용하여 WebAssembly 페이로드를 빌드하는 것도 가능하지만 프로세스에는 여전히 많은 수동 리프팅이 필요합니다. (여기에 한 가지 예가 있습니다.)
  • 녹. 안전하고 빠르도록 설계된 Mozilla의 시스템 프로그래밍 언어는 네이티브 WebAssembly 지원 의 주요 후보 중 하나입니다 . Rust 툴체인에 대한 확장을 사용하면 Rust 코드에서 WebAssembly로 직접 컴파일 할 수 있습니다. nightlyWebAssembly 컴파일을 수행 하려면 Rust의 툴체인 을 사용해야 하므로이 기능은 현재 실험적인 것으로 간주되어야합니다.
  • TypeScript . 기본적으로 TypeScript는 JavaScript로 컴파일됩니다. 즉, WebAssembly로 컴파일 될 수 있습니다. AssemblyScript 프로젝트는 관련된 단계 수를 줄여 엄격하게 형식화 된 TypeScript를 WebAssembly로 컴파일 할 수 있도록합니다.

다른 여러 언어가 WebAssembly를 대상으로하기 시작했지만 초기 단계에 있습니다. 다음 언어는 WebAssembly 구성 요소를 빌드하는 데 사용할 수 있지만 C, Rust 및 TypeScript보다 더 제한된 방식으로 만 사용할 수 있습니다.

  • D . D 언어는 최근 WebAssembly에 직접 컴파일하고 링크하는 지원을 추가했습니다.
  • 자바 . Java 바이트 코드는 TeaVM 프로젝트를 통해 WebAssembly로 미리 컴파일 될 수 있습니다. 즉, Java 바이트 코드를 내보내는 모든 언어 (예 : Kotlin, Scala 또는 Clojure)를 WebAssembly로 컴파일 할 수 있습니다. 그러나 리플렉션 및 리소스 API와 같이 WebAssembly에서 효율적으로 구현할 수없는 많은 Java API가 제한되어 있으므로 TeaVM (및 WebAssembly)은 JVM 기반 앱의 하위 집합에만 사용됩니다. 
  • Lua . Lua 스크립팅 언어는 JavaScript처럼 임베디드 언어로 오랫동안 사용되어 왔습니다. 그러나 Lua를 WebAssembly로 전환하는 유일한 프로젝트는 브라우저 내 실행 엔진을 사용하는 것입니다. wasm_lua는 브라우저에 Lua 런타임을 포함하고 Luwa JIT는 Lua를 WebAssembly로 컴파일합니다.
  • Kotlin / Native . 자바의 파생물 인 Kotlin 언어의 팬들은 독립 실행 형 바이너리를 생성 할 수있는 Kotlin 컴파일러 용 LLVM 백엔드 인 Kotlin / Native의 전체 출시를 간절히 기다리고 있습니다. Kotlin / Native 0.4는 WebAssembly를 컴파일 대상으로 지원하지만 개념 증명으로 만 도입했습니다.
  • .Net . .Net 언어는 아직 완전한 WebAssembly 지원이 없지만 일부 실험이 시작되었습니다. C # 및 Microsoft의 "Razor"구문을 통해 .Net에서 단일 페이지 웹 앱을 빌드하는 데 사용할 수있는 Blazor를 참조하세요.
  • . 이 떠오르는 언어는 C로 컴파일되므로 이론적으로 결과 C를 WebAssembly로 컴파일 할 수 있습니다. 그러나 nwasm이라는 Nim의 실험적인 백엔드가 개발 중입니다.
  • 기타 LLVM 기반 언어 . 이론적으로 LLVM은 WebAssembly를 여러 대상 중 하나로 지원하므로 LLVM 컴파일러 프레임 워크를 활용하는 모든 언어를 WebAssembly로 컴파일 할 수 있습니다. 그러나 이것이 반드시 LLVM 컴파일 된 언어가 WebAssembly에서있는 그대로 실행된다는 것을 의미하지는 않습니다. 이는 LLVM이 WebAssembly를 더 쉽게 타겟팅 할 수 있음을 의미합니다.

위의 모든 프로젝트는 원본 프로그램 또는 생성 된 바이트 코드를 WebAssembly로 변환합니다. 그러나 Ruby 또는 Python과 같은 해석 언어의 경우 다른 접근 방식이 있습니다. 앱 자체를 변환하는 대신 언어 런타임  을 WebAssembly 로 변환합니다 . 그런 다음 프로그램은 변환 된 런타임에서있는 그대로 실행됩니다. 많은 언어 런타임 (Ruby 및 Python 포함)이 C / C ++로 작성되기 때문에 변환 프로세스는 기본적으로 다른 C / C ++ 애플리케이션과 동일합니다.

물론 이것은 변환 된 런타임을 브라우저로 다운로드해야 응용 프로그램을 실행할 수 있으므로로드 및 구문 분석 시간이 느려집니다. 앱의 "순수한"WebAssembly 버전은 더 가볍습니다. 따라서 런타임 변환은 더 많은 언어가 WebAssembly를 내보내기 또는 컴파일 대상으로 지원할 때까지 기껏해야 임시 방편입니다.

WebAssembly를 JavaScript와 통합

다음 단계는 선택한 언어로 코드를 작성하고 해당 코드가 WebAssembly 환경과 상호 작용하는 방식에주의를 기울인 다음 WebAssembly 모듈 (WASM 바이너리)로 컴파일하고 마지막으로 기존 모듈과 통합하는 것입니다. 자바 스크립트 애플리케이션.

코드를 WebAssembly로 내보내는 방법에 대한 정확한 단계는 도구 체인에 따라 엄청나게 다릅니다. 또한 해당 언어에 대해 일반 네이티브 바이너리가 빌드되는 방식과 다소 차이가 있습니다. 예를 들어, Rust에서는 몇 가지 단계를 따라야합니다.

  1. 툴체인을 nightly 사용하여 Rust 용 빌드를 설정합니다 wasm32-unknown-unknown.
  2. 로 선언 된 외부 함수를 사용하여 Rust 코드를 작성합니다 #[no-mangle].
  3. 위의 도구 모음을 사용하여 코드를 빌드합니다.

(위 단계에 대한 자세한 내용은 GitHub의 The Rust and WebAssembly Book을 참조하세요.)

어떤 언어를 사용하든 코드를 HTML 프런트 엔드와 통합하기 위해서는 최소한 자바 스크립트에 대한 최소한의 숙련도가 있어야합니다. The Rust 및 WebAssembly Book의이 예제에서 페이지 내 JavaScript 스 니펫이 그리스어처럼 보인다면, 거기에서 무슨 일이 일어나고 있는지 이해하기에 충분한 JavaScript를 배우는 데 시간을 할애하십시오.

WebAssembly와 JavaScript의 통합은 JavaScript의 WebAssembly개체를 사용 하여 WebAssembly 코드에 대한 브리지를 생성 함으로써 수행됩니다 . Mozilla에는이를 수행하는 방법에 대한 문서가 있습니다. 여기 Rust에 대한 별도의 WebAssembly 예제가 있고 여기에 Node.js에 대한 WebAssembly 예제가 있습니다.

현재 WebAssembly 백엔드와 JavaScript / HTML 프론트 엔드 간의 통합은 여전히 ​​전체 프로세스에서 가장 번거롭고 수동적 인 부분입니다. 예를 들어 Rust를 사용하는 경우에도 원시 데이터 포인터를 통해 JavaScript에 대한 브리지를 수동으로 만들어야합니다.

그러나 더 많은 도구 모음이이 문제를 해결하기 시작했습니다. Cheerp 프레임 워크를 사용하면 C ++ 프로그래머가 전용 네임 스페이스를 통해 브라우저의 API와 통신 할 수 있습니다. 그리고 Rust는 JavaScript와 Rust 사이, 그리고 JavaScript와 WebAssembly 사이의 양방향 브리지 역할을하는 wasm-bindgen을 제공합니다.

또한 호스트에 대한 바인딩을 처리하는 방법에 대한 높은 수준의 제안이 고려 중입니다. 완료되면 WebAssembly로 컴파일되는 언어가 호스트와 상호 작용할 수있는 표준 방법을 제공합니다. 이 제안의 장기 전략은 브라우저가 아닌 호스트에 대한 바인딩도 포함하지만 브라우저 바인딩은 단기적이고 즉각적인 사용 사례입니다.

WebAssembly 앱 디버깅 및 프로파일 링

WebAssembly 도구가 아직 초기 단계에있는 한 영역은 디버깅 및 프로파일 링 지원입니다. 

자바 스크립트 소스 맵이 나오기 전까지 자바 스크립트로 컴파일 된 언어는 원래 코드와 컴파일 된 코드를 쉽게 상관시킬 수 없기 때문에 디버그하기가 어려웠습니다. WebAssembly에는 몇 가지 동일한 문제가 있습니다. C로 코드를 작성하고 WASM으로 컴파일하면 소스와 컴파일 된 코드간에 상관 관계를 그리기가 어렵습니다.

JavaScript 소스 맵은 소스 코드의 어떤 줄이 컴파일 된 코드의 어떤 영역에 해당하는지 나타냅니다. Emscripten과 같은 일부 WebAssembly 도구는 컴파일 된 코드에 대한 JavaScript 소스 맵을 내보낼 수도 있습니다. WebAssembly의 장기 계획 중 하나는 JavaScript에서 사용할 수있는 것 이상의 소스 맵 시스템이지만 여전히 제안 단계에 있습니다.

현재 WASM 코드를 야생에서 디버깅하는 가장 직접적인 방법은 웹 브라우저의 디버그 콘솔을 사용하는 것입니다. WebAssemblyCode의이 기사에서는 소스 맵을 사용하여 WASM 코드를 생성하고, 브라우저의 디버깅 도구에서 사용할 수 있도록하고, 코드를 단계별로 실행하는 방법을 보여줍니다. 설명 된 단계 emcc는 WASM을 내보내는 도구 사용에 따라 다릅니다 . 특정 도구 체인에 따라 단계를 수정해야 할 수도 있습니다.