2018.08.03

"속도 만으로도 치명적 매력"··· 차세대 웹 플랫폼 '웹어셈블리'

Serdar Yegulalp | Network World
지난 20여년간 웹 브라우저에서는 단 하나의 프로그래밍 공용어만 허용됐다. 바로 자바스크립트다. 특히 서드 파티 바이너리 플러그-인의 사망 선고와 함께 다른 언어를 사용할 가능성조차 완전히 사라졌다. 웹 개발에 있어서 자바나 플래시의 액션 스크립트 같은 다른 언어의 싹을 잘라 버린 것이다. 커피스크립트(CoffeeScript) 같은 다른 웹 언어가 있지만 근본적으로 자바스크립트로 컴파일된다.



그런데 이제 새로운 길이 열렸다. 웹어셈블리(WebAssembly), 또는 WASM이라 불리는 어셈블리 언어 덕분이다. 웹어셈블리는 웹 애플리케이션의 거의 네이티브로 실행되며 빠르고 간결한 바이너리 포맷 역할을 한다. 뿐만 아니라 자바스크립트는 물론이고 모든 언어를 컴파일 할 수 있도록 설계됐다. 거의 모든 메이저 브라우저가 웹어셈블리를 지원하므로, 이제는 웹어셈블리를 통해 컴파일 할 수 있는 클라이언트 측 앱 개발에 대해 진지하게 생각해 보아야 할 시점이다.

그렇다고 웹어셈블리 앱이 자바스크립트 앱을 대체하는 것은 아니다. 적어도 지금까지는 그렇다. 웹어셈블리는 자바스크립트의 동반자에 더 가깝다. 자바스크립트가 유연하고 역동적이고, 인간이 읽을 수 있는 소스코드를 통해 전달된다면, 웹어셈블리는 더 빠르고 강력하며, 컴팩트한 바이너리 형식으로 전달된다. 개발자는 이제 게임이나 음악 스트리밍, 비디오 편집, 그리고 CAD 애플리케이션 같이 무거운 작업을 할 때 웹어셈블리를 당연히 고려해야 한다.

웹어셈블리 작동 원리
W3C에서 개발한 웹어셈블리는 (그 제작자들의 표현대로) '컴파일링 타깃(compilation target)'이다. 즉, 개발자가 직접 웹어셈블리를 사용하지 않는다. 개발자는 자신이 원하는 언어로 소스코드를 작성하고, 그 후에 이를 웹어셈블리 바이트코드로 컴파일하게 된다. 이후 이 바이트코드는 클라이언트(아마도 웹 브라우저)에서 기기 고유의 코드로 해석된 후 더 빠르게 실행된다.

웹어셈블리 코드는 로드와 파스(parse), 그리고 실행에서 자바스크립트보다 빠르다. 웹 브라우저에서 웹어셈블리를 사용하면 WASM 모듈을 다운로드하고 설정하는데 시간이 걸리지만, 그럼에도 불구하고 다른 모든 조건이 동일하다면 웹어셈블리가 자바보다 더 빠르다. 웹어셈블리는 또한 자바스크립트와 같은 보안 모델에 기반한 샌드박스 실행 모델을 제공한다.

현재는 웹 브라우저에서 웹어셈블리를 사용하는 것이 가장 일반적인 활용 사례지만, 앞으로 웹어셈블리는 웹 기반 솔루션을 넘어 다양하게 활용될 것이다. 궁극적으로 웹어셈블리 표준이 확정되고 이런 저런 기능이 더해지면 모바일 앱, 데스크톱 앱, 서버, 그리고 기타 다양한 실행 환경에서 널리 사용될 것이다.

웹어셈블리의 다양한 활용 사례
웹어셈블리의 가장 기본적인 활용 사례는 인-브라우저 소프트웨어 개발이다. 웹어셈블리로 컴파일 된 요소는 아무 언어로나 쓸 수 있다. 최종 웹어셈블리 페이로드는 자바스크립트 형식으로 클라이언트에 전달된다. 웹어셈블리는 상당히 부담되는 작업과 브라우저 기반의 활용을 염두에 두고 개발됐다. 게임, 음악 스트리밍, 비디오 편집, CAD, 암호화, 이미지 인식 같은 것이다.

웹어셈블리를 사용할 지 고민되는 상황이라면 다음 3가지를 기준으로 판단하면 된다.

- 이미 다른 언어로 작성한 고성능 코드가 있을 때: 예컨대 이미 C 언어로 작성된 고속 수학 함수를 웹 애플리케이션으로 배포할 때 웹어셈블리 모듈을 이용할 수 있다. 성능에 영향을 덜 미치면서 사용자가 직접 제어하는 부분은 기존대로 자바스크립트로 사용할 수 있다.
- 처음부터 새롭게 작성할 고성능 코드가 있는데 자바스크립트가 부적합할 때: 이 경우 기존에는 asm.js를 사용하는 것이 일반적이었다. 지금도 유효한 대안이지만 장기적으로 보면 웹어셈블리가 더 현명한 선택일 수 있다.
- 데스크톱 애플리케이션을 웹 환경으로 이식할 때: asm.js와 웹어셈블리의 테크놀로지 데모 중 상당수가 여기에 속한다. 웹어셈블리는 HTML을 이용한 GUI보다 더 강력한 앱 서브스트레이트(substrate)를 제공한다. 단, 이는 결코 쉬운 작업이 아니다. 데스크톱 애플리케이션과 사용자 간의 모든 인터페이스 접속 경로를 웹어셈블리나 HTML 또는 자바스크립트와 동격인 언어로 매핑해야 하기 때문이다.

기존의 자바스크립트 앱이 그 어떤 실행 외부(performance envelope)도 푸쉬하고 있지 않다면, 기존 대로 사용하는 것이 최선일 수도 있다. 그러나 앱 속도를 더 높여야 하는 상황이라면 웹어셈블리가 안성맞춤이다.

웹어셈블리 언어 지원
웹어셈블리는 사용자가 직접 사용하는 언어가 아니다. 그 이름에서 알 수 있듯 어셈블리 언어에 더 가깝기 때문이다. 즉, 인간 친화적인 다른 프로그래밍 언어와 달리 기기가 이해하는 데 더 최적화됐다. 웹어셈블리는 C나 자바보다 LLVM 랭귀지-컴파일러 인프라스트럭처가 생성하는 IR(Intermediate Representation)과 더 유사하다.

따라서 웹어셈블리를 사용하는 대부분 사례에서 고 수준 언어로 코드를 먼저 작성하고, 이를 웹어셈블리로 전환한다. 구체적인 전환 과정은 다음과 3가지와 같다.

- 다이렉트 컴파일링. 소스 언어를 그 언어의 자체 컴파일러 툴 체인을 통해 웹어셈블리로 변환하는 방식이다. 러스트, C/C++, 코틀린/네이티브, 그리고 D 언어 등은 이제 컴파일러로부터 WASM 언어를 내보내는 자체적인 시스템을 갖추고 있다.
- 서드 파티 툴. 툴 체인이 WASM을 지원하지 않지만, 서드 파티 유틸리티를 사용해 WASM으로 변환할 수 있는 경우다. 자바, 루아(Lua), 그리고 닷넷 언어 등이 이런 방식을 사용한다.
- 웹어셈블리 기반 전환. 이 경우 소스 언어 자체가 웹어셈블리로 번역된다기 보다는 웹어셈블리에 내장된 ‘인터프리터(interpreter)’가 해당 언어로 쓰여진 코드를 구동한다는 표현이 더 정확하다. 이 방식은 셋 중에서 가장 까다로운 방식인데, 이러한 ‘번역’ 과정을 위해 수 메가바이트 크기의 코드가 필요할 수도 있기 때문이다. 하지만 기존 코드를 전혀 바꾸지 않고 구동할 수 있다는 점이 장점이다. 파이썬과 루비가 WASM 인터프리터를 제공하는 대표적 언어다.


웹어셈블리 기능들
웹어셈블리는 아직 초기 단계다. 웹어셈블리 툴 체인과 배포는 아직 프로덕션 단계의 테크놀로지라기 보다는 개념 증명에 더 가깝다. 웹어셈블리 개발자와 관리자는 여러 가지 이니셔티브를 웹어셈블리를 확산해 나간다는 구상이다.

가비지 컬렉션을 통해 수집한 메모리 모델
먼저 가비지 컬렉션 지원이다. 현재의 웹어셈블리는 가비지 컬렉션(garbage collection)을 통해 수집한 메모리 모델을 사용하는 언어를 지원하지 않는다. 그래서 루아나 파이썬 같은 언어는 기능을 제한하거나 전체 런타임을 웹어셈블리에서 실행할 수 있도록 내장해야 지원된다. 하지만 앞으로 가비지 컬렉션을 통해 수집한 메모리 모델도 언어나 이행 방식에 관계 없이 지원하기 위한 개발이 진행중이다.

쓰레딩(Threading)
러스트나 C++같은 언어는 보통 쓰레딩을 지원한다. 그러나 웹어셈블리는 그렇지 않다. 쓰레딩 지원이 빠져 있다는 것은 광범위한 소프트웨어에서 웹어셈블리를 사용할 수 없음을 의미한다. 따라서 웹어셈블리에 쓰레딩을 넣어야 한다는 주장이 설득력을 얻고 있다. 보통 C++ 쓰레딩 모델을 예시로 든다.

벌크 메모리 오퍼레이션과 SIMD
일부 앱의 경우 산더미 같은 데이터를 파헤쳐 처리하는 벌크 메모리 오퍼레이션과 SIMD(single instruction, multiple data)이 필수적이다. 머신러닝이나 CPU 가속이 필요한 앱이 대표적이다. 이에 따라 웹어셈블리에 이러한 기능을 추가하자는 주장이 나온다.

고 수준 언어구성 요소
이밖에도 웹어셈블리에 고려되는 다른 여러 기능이 있다. 대부분 타 언어의 고 수준 구성 요소들이다.

- 예외(exception): 웹어셈블리에서도 예외를 모방할 수 있지만, 웹어셈블리의 인스트럭션 셋을 통해 직접 실행할 수는 없다. 이 때문에 C++ 예외 모델과 호환 가능한 예외 사항 등이 제안되고 있다. 이러한 예외는 웹어셈블리로 컴파일된 다른 언어에서도 사용할 수 있다.
- 레퍼런스 타입(reference types): 호스트 환경에서 레퍼런스로 사용되는 객체를 우회하는 데 도움이 된다. 이로 인해 가비지 컬렉션을 비롯한 여러 가지 고 수준 기능을 더 수월하게 웹어셈블리에서 실행할 수 있다.
- 테일 콜(Tail calls): 여러 언어에서 사용되는 디자인 패턴인
- 다수의 값을 반환하는 함수들: 예컨대 파이썬이나 C#의 튜플을 통한다.
- 부호 확장(sign-extension) 연산자: 저 수준 수학 연산작업에 유용하다. LLVM은 이 역시 지원한다.

디버깅 및 프로파일링 툴
트랜스파일(transpile)된 자바스크립트의 가장 큰 문제는 디버깅과 프로파일링이 어렵다는 것이다. 트랜스파일 된 코드와 소스가 서로 연계되지 못하기 때문이다. 웹어셈블리 역시 비슷한 문제를 지니고 있으며, 자바스크립트가 이를 해결한 비슷한 방식으로 해법을 찾고 있다. 즉 소스 맵을 지원하는 것이다. 웹어셈블리 프로젝트의 툴 지원 계획은 웹어셈블리 웹사이트에서 확인할 수 있다. ciokr@idg.co.kr 
2018.08.03

"속도 만으로도 치명적 매력"··· 차세대 웹 플랫폼 '웹어셈블리'

Serdar Yegulalp | Network World
지난 20여년간 웹 브라우저에서는 단 하나의 프로그래밍 공용어만 허용됐다. 바로 자바스크립트다. 특히 서드 파티 바이너리 플러그-인의 사망 선고와 함께 다른 언어를 사용할 가능성조차 완전히 사라졌다. 웹 개발에 있어서 자바나 플래시의 액션 스크립트 같은 다른 언어의 싹을 잘라 버린 것이다. 커피스크립트(CoffeeScript) 같은 다른 웹 언어가 있지만 근본적으로 자바스크립트로 컴파일된다.



그런데 이제 새로운 길이 열렸다. 웹어셈블리(WebAssembly), 또는 WASM이라 불리는 어셈블리 언어 덕분이다. 웹어셈블리는 웹 애플리케이션의 거의 네이티브로 실행되며 빠르고 간결한 바이너리 포맷 역할을 한다. 뿐만 아니라 자바스크립트는 물론이고 모든 언어를 컴파일 할 수 있도록 설계됐다. 거의 모든 메이저 브라우저가 웹어셈블리를 지원하므로, 이제는 웹어셈블리를 통해 컴파일 할 수 있는 클라이언트 측 앱 개발에 대해 진지하게 생각해 보아야 할 시점이다.

그렇다고 웹어셈블리 앱이 자바스크립트 앱을 대체하는 것은 아니다. 적어도 지금까지는 그렇다. 웹어셈블리는 자바스크립트의 동반자에 더 가깝다. 자바스크립트가 유연하고 역동적이고, 인간이 읽을 수 있는 소스코드를 통해 전달된다면, 웹어셈블리는 더 빠르고 강력하며, 컴팩트한 바이너리 형식으로 전달된다. 개발자는 이제 게임이나 음악 스트리밍, 비디오 편집, 그리고 CAD 애플리케이션 같이 무거운 작업을 할 때 웹어셈블리를 당연히 고려해야 한다.

웹어셈블리 작동 원리
W3C에서 개발한 웹어셈블리는 (그 제작자들의 표현대로) '컴파일링 타깃(compilation target)'이다. 즉, 개발자가 직접 웹어셈블리를 사용하지 않는다. 개발자는 자신이 원하는 언어로 소스코드를 작성하고, 그 후에 이를 웹어셈블리 바이트코드로 컴파일하게 된다. 이후 이 바이트코드는 클라이언트(아마도 웹 브라우저)에서 기기 고유의 코드로 해석된 후 더 빠르게 실행된다.

웹어셈블리 코드는 로드와 파스(parse), 그리고 실행에서 자바스크립트보다 빠르다. 웹 브라우저에서 웹어셈블리를 사용하면 WASM 모듈을 다운로드하고 설정하는데 시간이 걸리지만, 그럼에도 불구하고 다른 모든 조건이 동일하다면 웹어셈블리가 자바보다 더 빠르다. 웹어셈블리는 또한 자바스크립트와 같은 보안 모델에 기반한 샌드박스 실행 모델을 제공한다.

현재는 웹 브라우저에서 웹어셈블리를 사용하는 것이 가장 일반적인 활용 사례지만, 앞으로 웹어셈블리는 웹 기반 솔루션을 넘어 다양하게 활용될 것이다. 궁극적으로 웹어셈블리 표준이 확정되고 이런 저런 기능이 더해지면 모바일 앱, 데스크톱 앱, 서버, 그리고 기타 다양한 실행 환경에서 널리 사용될 것이다.

웹어셈블리의 다양한 활용 사례
웹어셈블리의 가장 기본적인 활용 사례는 인-브라우저 소프트웨어 개발이다. 웹어셈블리로 컴파일 된 요소는 아무 언어로나 쓸 수 있다. 최종 웹어셈블리 페이로드는 자바스크립트 형식으로 클라이언트에 전달된다. 웹어셈블리는 상당히 부담되는 작업과 브라우저 기반의 활용을 염두에 두고 개발됐다. 게임, 음악 스트리밍, 비디오 편집, CAD, 암호화, 이미지 인식 같은 것이다.

웹어셈블리를 사용할 지 고민되는 상황이라면 다음 3가지를 기준으로 판단하면 된다.

- 이미 다른 언어로 작성한 고성능 코드가 있을 때: 예컨대 이미 C 언어로 작성된 고속 수학 함수를 웹 애플리케이션으로 배포할 때 웹어셈블리 모듈을 이용할 수 있다. 성능에 영향을 덜 미치면서 사용자가 직접 제어하는 부분은 기존대로 자바스크립트로 사용할 수 있다.
- 처음부터 새롭게 작성할 고성능 코드가 있는데 자바스크립트가 부적합할 때: 이 경우 기존에는 asm.js를 사용하는 것이 일반적이었다. 지금도 유효한 대안이지만 장기적으로 보면 웹어셈블리가 더 현명한 선택일 수 있다.
- 데스크톱 애플리케이션을 웹 환경으로 이식할 때: asm.js와 웹어셈블리의 테크놀로지 데모 중 상당수가 여기에 속한다. 웹어셈블리는 HTML을 이용한 GUI보다 더 강력한 앱 서브스트레이트(substrate)를 제공한다. 단, 이는 결코 쉬운 작업이 아니다. 데스크톱 애플리케이션과 사용자 간의 모든 인터페이스 접속 경로를 웹어셈블리나 HTML 또는 자바스크립트와 동격인 언어로 매핑해야 하기 때문이다.

기존의 자바스크립트 앱이 그 어떤 실행 외부(performance envelope)도 푸쉬하고 있지 않다면, 기존 대로 사용하는 것이 최선일 수도 있다. 그러나 앱 속도를 더 높여야 하는 상황이라면 웹어셈블리가 안성맞춤이다.

웹어셈블리 언어 지원
웹어셈블리는 사용자가 직접 사용하는 언어가 아니다. 그 이름에서 알 수 있듯 어셈블리 언어에 더 가깝기 때문이다. 즉, 인간 친화적인 다른 프로그래밍 언어와 달리 기기가 이해하는 데 더 최적화됐다. 웹어셈블리는 C나 자바보다 LLVM 랭귀지-컴파일러 인프라스트럭처가 생성하는 IR(Intermediate Representation)과 더 유사하다.

따라서 웹어셈블리를 사용하는 대부분 사례에서 고 수준 언어로 코드를 먼저 작성하고, 이를 웹어셈블리로 전환한다. 구체적인 전환 과정은 다음과 3가지와 같다.

- 다이렉트 컴파일링. 소스 언어를 그 언어의 자체 컴파일러 툴 체인을 통해 웹어셈블리로 변환하는 방식이다. 러스트, C/C++, 코틀린/네이티브, 그리고 D 언어 등은 이제 컴파일러로부터 WASM 언어를 내보내는 자체적인 시스템을 갖추고 있다.
- 서드 파티 툴. 툴 체인이 WASM을 지원하지 않지만, 서드 파티 유틸리티를 사용해 WASM으로 변환할 수 있는 경우다. 자바, 루아(Lua), 그리고 닷넷 언어 등이 이런 방식을 사용한다.
- 웹어셈블리 기반 전환. 이 경우 소스 언어 자체가 웹어셈블리로 번역된다기 보다는 웹어셈블리에 내장된 ‘인터프리터(interpreter)’가 해당 언어로 쓰여진 코드를 구동한다는 표현이 더 정확하다. 이 방식은 셋 중에서 가장 까다로운 방식인데, 이러한 ‘번역’ 과정을 위해 수 메가바이트 크기의 코드가 필요할 수도 있기 때문이다. 하지만 기존 코드를 전혀 바꾸지 않고 구동할 수 있다는 점이 장점이다. 파이썬과 루비가 WASM 인터프리터를 제공하는 대표적 언어다.


웹어셈블리 기능들
웹어셈블리는 아직 초기 단계다. 웹어셈블리 툴 체인과 배포는 아직 프로덕션 단계의 테크놀로지라기 보다는 개념 증명에 더 가깝다. 웹어셈블리 개발자와 관리자는 여러 가지 이니셔티브를 웹어셈블리를 확산해 나간다는 구상이다.

가비지 컬렉션을 통해 수집한 메모리 모델
먼저 가비지 컬렉션 지원이다. 현재의 웹어셈블리는 가비지 컬렉션(garbage collection)을 통해 수집한 메모리 모델을 사용하는 언어를 지원하지 않는다. 그래서 루아나 파이썬 같은 언어는 기능을 제한하거나 전체 런타임을 웹어셈블리에서 실행할 수 있도록 내장해야 지원된다. 하지만 앞으로 가비지 컬렉션을 통해 수집한 메모리 모델도 언어나 이행 방식에 관계 없이 지원하기 위한 개발이 진행중이다.

쓰레딩(Threading)
러스트나 C++같은 언어는 보통 쓰레딩을 지원한다. 그러나 웹어셈블리는 그렇지 않다. 쓰레딩 지원이 빠져 있다는 것은 광범위한 소프트웨어에서 웹어셈블리를 사용할 수 없음을 의미한다. 따라서 웹어셈블리에 쓰레딩을 넣어야 한다는 주장이 설득력을 얻고 있다. 보통 C++ 쓰레딩 모델을 예시로 든다.

벌크 메모리 오퍼레이션과 SIMD
일부 앱의 경우 산더미 같은 데이터를 파헤쳐 처리하는 벌크 메모리 오퍼레이션과 SIMD(single instruction, multiple data)이 필수적이다. 머신러닝이나 CPU 가속이 필요한 앱이 대표적이다. 이에 따라 웹어셈블리에 이러한 기능을 추가하자는 주장이 나온다.

고 수준 언어구성 요소
이밖에도 웹어셈블리에 고려되는 다른 여러 기능이 있다. 대부분 타 언어의 고 수준 구성 요소들이다.

- 예외(exception): 웹어셈블리에서도 예외를 모방할 수 있지만, 웹어셈블리의 인스트럭션 셋을 통해 직접 실행할 수는 없다. 이 때문에 C++ 예외 모델과 호환 가능한 예외 사항 등이 제안되고 있다. 이러한 예외는 웹어셈블리로 컴파일된 다른 언어에서도 사용할 수 있다.
- 레퍼런스 타입(reference types): 호스트 환경에서 레퍼런스로 사용되는 객체를 우회하는 데 도움이 된다. 이로 인해 가비지 컬렉션을 비롯한 여러 가지 고 수준 기능을 더 수월하게 웹어셈블리에서 실행할 수 있다.
- 테일 콜(Tail calls): 여러 언어에서 사용되는 디자인 패턴인
- 다수의 값을 반환하는 함수들: 예컨대 파이썬이나 C#의 튜플을 통한다.
- 부호 확장(sign-extension) 연산자: 저 수준 수학 연산작업에 유용하다. LLVM은 이 역시 지원한다.

디버깅 및 프로파일링 툴
트랜스파일(transpile)된 자바스크립트의 가장 큰 문제는 디버깅과 프로파일링이 어렵다는 것이다. 트랜스파일 된 코드와 소스가 서로 연계되지 못하기 때문이다. 웹어셈블리 역시 비슷한 문제를 지니고 있으며, 자바스크립트가 이를 해결한 비슷한 방식으로 해법을 찾고 있다. 즉 소스 맵을 지원하는 것이다. 웹어셈블리 프로젝트의 툴 지원 계획은 웹어셈블리 웹사이트에서 확인할 수 있다. ciokr@idg.co.kr 
X