https://www.youtube.com/watch?v=N0b6zslDuQA
션: 마이클, 토마스, 쇼에 오신 것을 환영합니다!
마이클, 토마스: 정말 감사합니다!
션: 네, 여기 와주셔서 감사합니다. 웹어셈블리 가비지 컬렉션 등 흥미로운 주제에 대해 이야기 나누게 되어 기쁩니다. 자세한 내용은 잠시 후에 다루고, 먼저 두 분의 배경과 경험에 대해 좀 더 알고 싶습니다. 마이클, 구글 워크스페이스 멀티플랫폼 리드를 맡고 계시죠. 구글에서 16년이나 일하셨는데, 일상 업무는 어떤지, 그리고 16년 동안 구글에서 어떤 변화와 발전을 목격했는지 궁금합니다.
마이클: 물론입니다. 저는 뉴욕시에 있는데, 제가 처음 입사했을 때 뉴욕 사무실은 현재 규모의 1/10 정도였습니다. 그래서 사무실이 성장하는 모습과 회사가 성장하는 모습을 지켜봤고, 많은 것들이 정말 많이 달라졌습니다. 저는 워크스페이스에서 멀티플랫폼과 관련된 여러 프로젝트를 진행하고 있습니다. 시트에서 웹어셈블리를 활용하는 프로젝트도 그중 하나였죠. 그래서 여러 가지 일을 조율하고 다니느라 일반적인 하루가 어떤 모습인지 말하기는 어렵습니다.
션: 토마스, 당신도 구글에서 16년 동안 일하셨다고 들었는데, 박사 학위와 포닥 과정을 병행하셨다고요. 학업과 연구를 병행하면서 구글에서 일하는 것은 어떻게 가능했나요?
토마스: 흥미로운 이야기인데요. 2005년 아직 학생일 때 인턴으로 구글에 합류했습니다. 당시 애드워즈 API 관련 업무를 했는데, 평가가 괜찮았는지 졸업할 때까지 임시직으로 일할 수 있었습니다. 저는 좀 나이가 많아서 요즘은 석사 학위라고 부르지만, 그때는 디플로마라고 불렀죠. 어쨌든 디플로마를 마치고 2007년에 구글에 정식 입사했습니다. 그 후 몇 년 동안은 광고 API 관련 업무를 계속 맡았습니다. 하지만 시간이 지나면서 조금 지루해졌다고 할까요, 좀 더 하고 싶은 마음이 생겼습니다. 그래서 박사 과정을 알아보던 중 우연히 마음에 드는 지도 교수님을 만났습니다. 공교롭게도 그 당시 구글은 EU 연구 프로젝트에 참여했지만, 실제로 프로젝트에 참여할 사람을 찾지 못했습니다. 좀 이상하죠. EU 연구 프로젝트는 보통 3년 정도 진행되는데, 구글은 분기별로 계획을 세우는 곳이라 장기 계획과 단기 계획 사이에 갈등이 있었죠. 결국 저는 회사 시간을 이용해 EU 연구 프로젝트를 진행하며 박사 학위를 받기로 결정했습니다. 박사 학위를 마치고 모바일 분야에서 좀 더 일하다가 지금은 웹어셈블리와 웹 AI 관련 업무를 주로 담당하고 있는 크롬 팀에 합류했습니다.
션: 크롬 팀에는 얼마나 계셨나요?
토마스: 2018년에 크롬 팀으로 옮겼습니다.
션: 구글처럼 큰 회사에서 일하는 흥미로운 점 중 하나는 10년 넘게 구글에서 일하는 사람들에게 "무엇이 당신을 여기에 머물게 하나요?"라고 물으면, 그들은 마치 새로운 회사처럼 완전히 새로운 프로젝트를 시작하거나 소프트웨어 엔지니어링에서 제품으로 전환하는 등 다양한 역할을 맡을 수 있다는 점을 이야기합니다. 마치 구글이라는 우산 아래서 매년 새로운 것을 경험하는 것처럼 말이죠. 오랫동안 구글에서 일해 오신 두 분도 그런 경험을 하셨나요?
마이클: 저는 웹 개발자로 시작했는데, 워크스페이스는 세계에서 가장 복잡한 웹 앱 중 일부를 가지고 있습니다. 그래서 저희는 계속 브라우저의 한계에 부딪혔고, 결국 여러 플랫폼을 지원해야 하는 상황에 놓였습니다. 그래서 멀티플랫폼 분야에 뛰어들게 되었고, 크롬 팀과 협업하는 등 흥미로운 기회들이 많이 생겼습니다. 저는 다양한 역할을 맡았다기보다는, 어떤 일을 할 수 있는 한 최대한 해보면 항상 새로운 기회가 기다리고 있었다고 생각합니다.
토마스: 제가 크롬 팀에 합류하고 싶었을 때는 TO가 없었습니다. 지역도 문제였죠. 요즘은 여러 지역에 허브가 생겨서 고용이 좀 더 쉬워졌지만, 허브가 아닌 지역에 있으면 여전히 어렵습니다. 그래서 저는 크롬 팀에 속하지 않은 상태로 크롬 팀을 위해 많은 일을 했습니다. 몇 년 전에 구글에서 17년을 보낸 소감을 블로그에 올렸는데, 그때 그 상황을 좀 직설적으로 표현했습니다.
션: 아마도 거대한 조직이 자연스럽게 진화하는 과정의 일부일 것입니다. 16년 전의 구글은 규모 면에서도 지금과는 완전히 다른 회사였습니다. 제가 구글에 있었던 4년 동안에도 회사 규모가 7만 5천 명에서 15만 명으로 두 배나 커졌습니다. 조직 규모가 이렇게 크게 변하면 회사로서 성장하고 어느 정도 제약을 가해야 하며, 장단점이 있기 마련입니다. 이제 구글 시트 계산 작업자를 JavaScript에서 WebAssembly Garbage Collection으로 이식하는 프로젝트에 대한 기사에 대해 이야기해 보겠습니다. 먼저, 시트에서 계산 작업자가 무엇인지 설명해 주시겠어요?
마이클: 계산 작업자는 웹에서 백그라운드에서 계산을 수행하는 데 사용되는 작업자 스레드를 말합니다. 사용자가 계산 중에도 계속 입력할 수 있도록 하죠. 웹 앱 내부에서 별도의 웹 앱처럼 작동하는, 구글 시트에서 분리된 부분입니다. 계산 작업자의 유일한 역할은 계산입니다. 셀의 내용이 입력되면 계산된 셀의 내용이 출력됩니다.
션: 즉, 수식을 실행해서 셀을 업데이트하는 역할을 하고, 독립적으로 실행되는 것이군요. 맞나요?
토마스: 정확합니다. 1 더하기 1은 2와 같은 간단한 계산이나, 경우에 따라 정렬, 조건부 서식 지정 등 계산과 관련된 많은 작업을 처리합니다.
션: 물론 성능이 중요한 요소일 것입니다. 모든 셀에 수식이 적용된 아주 큰 시트의 경우, 모든 셀이 수식을 실행하고 업데이트되어야 하니까요. 사용자가 편집하는 동안에도 모든 내용이 최신 상태로 유지되어야 하고, 편집 과정에서 사용자 경험에 영향을 미치지 않아야 합니다.
마이클: 네, 사용자의 작업량에 비례해서 계산량이 늘어나기 때문에 이론적으로는 무한한 성능이 필요한 경우입니다.
션: 제가 이해하기로 웹어셈블리는 C, C++, Rust와 같은 언어로 작성된 코드를 웹에서 실행할 수 있는 바이트 코드 형식으로 변환하여 기본 성능에 가까운 성능을 얻을 수 있도록 합니다. Figma, Google Earth, 여러 게임 등이 웹 애플리케이션의 일반적인 성능을 뛰어넘는 성능을 위해 웹어셈블리를 사용하고 있습니다. 웹어셈블리에 대한 제 이해가 맞나요?
토마스: 네, 맞습니다.
션: 그렇다면 웹어셈블리 GC, 즉 Wasm GC에 대해 설명해 주시겠어요? Wasm GC라고 부르는 것이 맞나요?
마이클: 사실 며칠 전에 여러 사람에게 "웹어셈블리 GC를 기술적으로 정확하게 표현하는 방법이 무엇인가?"라고 물어봤습니다. Wasm GC, Wasm Space GC, WebAssembly GC 등 여러 가지 표현이 있는데, 아직 정해진 것은 없습니다.
토마스: 개발자 측면에서는 혼동을 피하기 위해 문서나 출판물에서 일관성을 유지하는 것이 더 중요하다고 생각합니다. 저희는 설명서에서 사용하는 Wasm(공백 없이) GC라는 표현을 사용하고 있습니다. Wasm은 약어가 아니라 WebAssembly의 합성어이기 때문에 모두 대문자로 쓰지 않고 W만 대문자로 쓰는 것도 중요합니다.
션: 웹어셈블리 프로젝트와 관련해서 Wasm GC라는 확장 기능에 대해 설명해 주시겠어요?
토마스: 좀 더 넓은 맥락에서 설명하자면, 웹어셈블리는 단순성을 중요하게 생각하며 설계되었습니다. 초기 웹어셈블리 명세는 단순히 숫자 계산을 위한 것이었습니다. C, C++, Rust 코드를 웹어셈블리로 컴파일하여 실행할 수 있지만, 스레딩과 같은 기능은 JavaScript 브라우저 API를 통해서만 가능했습니다. 매우 작고 단순하며 잘 정의된 숫자 계산기였죠. Wasm GC는 이 숫자 계산기에 가비지 컬렉션 언어를 처리하는 데 필요한 기능을 추가한 것입니다. Java, Dart, Kotlin이 좋은 예입니다. 가비지 컬렉터 자체는 대부분의 구현자가 기존 JavaScript 가비지 컬렉터를 활용할 것으로 예상됩니다.
Java와 같은 언어를 웹어셈블리로 컴파일하려는 경우 기본적으로 가비지 컬렉션을 지원하지 않으면 에뮬레이션해야 하는데, 성능이 좋지 않습니다. 따라서 웹어셈블리가 가비지 컬렉션을 기본적으로 지원해야 효율적인 컴파일이 가능합니다. Wasm GC는 가비지 컬렉션 언어를 효율적으로 컴파일하는 데 필요한 명령어를 제공하기 위해 웹어셈블리 명세를 확장한 것입니다.
토마스: 웹어셈블리 전문가는 아니지만, 기본적으로 가비지 컬렉션 구현에 필요한 하위 수준 기능이라고 이해하고 있습니다. 실제로 가비지 컬렉션 제안서 저장소나 설명서를 보면 가비지 컬렉션에 대한 언급이 없습니다. 구조체 등 가비지 컬렉션 구현에 필요한 하위 수준 개념에 대한 설명만 있죠. 저는 웹 개발자를 위해 쓴 기사에서 Dart나 Kotlin과 같은 언어를 웹으로 컴파일하는 경우를 예로 들어 설명했습니다. 이러한 언어에는 루프, 조건문, 문자열 등의 작동 방식에 대한 코드와 가비지 컬렉션 작동 방식에 대한 코드가 있습니다. 이러한 언어를 웹어셈블리로 컴파일하는 경우 가비지 컬렉션을 담당하는 코드도 컴파일해야 합니다. 하지만 브라우저에는 이미 JavaScript 가비지 컬렉션이 있기 때문에, 이를 활용할 수 있다면 언어 크기를 줄일 수 있습니다.
션: 즉, JavaScript 엔진의 기본 가비지 컬렉션을 활용하는 것이군요?
토마스: 명세에서는 구현 방법을 명시하지 않지만, 브라우저 공급업체 입장에서는 이미 JavaScript에 맞게 조정된 가비지 컬렉터가 있기 때문에 이를 웹어셈블리에도 재사용하는 것이 합리적입니다. 하지만 미래에는 분리될 수도 있겠죠.
토마스: 가비지 컬렉터가 있는 언어로 구현된 Wasm 런타임이 있다면, 이를 활용할 수도 있습니다. 예를 들어, 임베디드 장치에서 실행하도록 최적화된 Wasm 런타임이 있고, 이 런타임이 가비지 컬렉션을 지원하는 언어로 구현되었다면, 이를 사용할 수 있습니다. 웹에서의 구현 방식과는 완전히 별개입니다.
마이클: 덧붙이자면, 가비지 컬렉터는 플랫폼에 맞게 조정해야 하는 경우가 많습니다. 모바일에서의 가비지 컬렉터 동작 방식은 데스크톱에서의 동작 방식과 다를 수 있습니다. 또한 웹어셈블리와 JavaScript 간의 상호 운용성을 위해서는 동일한 가비지 컬렉터를 사용하는 것이 더 쉽고 효율적일 수 있습니다.
션: 이 프로젝트의 목표는 무엇이었나요? 왜 가비지 컬렉션을 사용하는 언어를 웹어셈블리 바이트 코드로 컴파일할 수 있도록 했나요?
마이클: 성능 향상 때문입니다. 계산 엔진은 항상 Java로 작성되었고, JavaScript로 실행하기 위해 Java에서 JavaScript로 변환하는 트랜스파일러를 사용했습니다. 10년 동안 JavaScript 성능을 최적화했지만, 이미 한계에 도달했습니다. JavaScript의 성능 한계에 봉착한 것입니다. 10년 전부터 JavaScript가 JVM보다 계산 엔진을 3배 느리게 실행한다는 것을 알고 있었습니다. 하지만 JavaScript 때문에 성능을 향상시킬 방법이 없었습니다. 웹어셈블리는 이론적으로 이 문제를 해결할 수 있었지만, 초기에는 가비지 컬렉션을 사용하지 않는 언어에만 적용되었습니다. Wasm GC 덕분에 이제 Java에서 Wasm GC로 컴파일할 수 있게 되었고, JavaScript를 거치지 않고도 성능이 두 배로 향상되었습니다.
션: 계산기 코드를 C++와 같은 언어로 다시 작성하여 GC 언어를 지원하기 위한 추가 컴파일 없이 웹어셈블리를 활용하는 것보다 더 쉬운 방법인가요?
마이클: 네, 그렇습니다. 시트 코드베이스가 처음 개발되었을 때 C++로 작성했다면 웹어셈블리를 사용했을 것이고, Wasm GC에 대해 생각하지도 않았을 것입니다. 하지만 당시 서버는 모두 Java로 작성되었기 때문에 계산 엔진도 Java로 작성되었습니다.
매우 크고 복잡하며 성능과 정확성에 민감한 코드를 Java에서 C++로 다시 작성하는 것은 매우 어려운 작업입니다. 가비지 컬렉션 언어에서 다른 가비지 컬렉션 언어로 변환하는 경우 자동화할 수 있는 부분이 많지만, 가비지 컬렉션 언어에서 가비지 컬렉션을 사용하지 않는 언어로 변환하는 경우 거의 처음부터 다시 작성하는 것과 마찬가지입니다. 시간도 오래 걸리고, 검증하는 데도 시간이 오래 걸립니다. 또한 개발자가 C++에 대한 교육을 다시 받아야 하고, 그동안 모든 기능 개발이 중단되어야 합니다.
반면 Wasm GC는 몇 명의 개발자만으로 6개월에서 1년 만에 이식할 수 있었습니다. 메인 팀은 계속해서 기능을 개발할 수 있었기 때문에 사용자 입장에서는 기능 개발 속도가 느려지지 않았습니다. 성능 향상은 거의 공짜로 얻은 셈입니다.
마이클: 구글 내부에서 Wasm GC를 사용하는 또 다른 큰 고객은 플러터 팀입니다. Wasm GC 이전에는 Dart로 작성된 플러터 앱을 JavaScript로 컴파일했지만, 이제는 Wasm GC로 컴파일하여 엄청난 성능 향상을 이루었습니다. 구글 시트 팀과 플러터 팀이 Wasm GC 개발을 주도한 셈입니다.
션: 10년 전부터 JavaScript 성능의 한계에 도달할 것이라는 것을 알고 있었다고 하셨는데, 그 한계가 사용자 경험에 어떤 영향을 미쳤나요?
마이클: 아주 큰 스프레드시트에서 변경 사항을 적용하면 대규모 재계산이 발생하여 몇 초 동안 기다려야 하는 경우가 있습니다. 특히 아주 큰 스프레드시트에서는 더 오래 기다려야 합니다.
션: 그러니까 사용자가 실제로 지연을 느낄 수 있을 정도였군요. Wasm GC에서는 가비지 컬렉션 방식을 명시하지 않고 구현자에게 맡긴다고 하셨는데, 이 프로젝트에서는 어떻게 구현했나요? JavaScript 가비지 컬렉션을 활용했나요, 아니면 다른 방법을 사용했나요?
토마스: 가비지 컬렉터 구현 방식은 브라우저 공급업체가 결정합니다. 제가 이해하기로 구글 크롬의 V8 팀은 JavaScript에 사용하는 것과 동일한 가비지 컬렉터를 사용하고 있습니다. 다른 브라우저 공급업체도 처음에는 기존 가비지 컬렉터를 재사용할 것으로 예상됩니다. 이미 플랫폼에 맞게 조정되어 있으니까요. 하지만 명세에서는 특정 방식으로 구현해야 한다고 명시하지 않습니다.
션: 이 프로젝트를 진행하면서 어떤 기술적인 어려움을 겪었나요?
마이클: 많았습니다. 처음에는 문서 성능을 측정할 수 있는 방법이 있었지만, 개인 정보 보호 때문에 실제 사용자 문서를 볼 수 없었습니다. 그래서 구글 직원이 작성한 문서를 사용했는데, 이 문서에 접근하려면 작성자에게 직접 연락해야 했습니다. 예를 들어, "이 스프레드시트가 느린 이유를 알아보려고 하는데, 문서를 볼 수 있도록 허용해 주시겠어요?"와 같이 말이죠. 성능 문제의 원인을 파악하고 좋은 예제를 확보하는 데 어려움을 겪었습니다.
구현 측면에서도 어려움이 많았습니다. 다른 방식으로 실행되도록 이식하는 경우 대부분의 코드는 그대로 이식할 수 있지만, 이전 플랫폼에 특화된 라이브러리는 다시 작성해야 합니다.
예를 들어, JavaScript에서는 모든 객체가 해시맵이고, 배열도 해시맵입니다. 따라서 모든 배열을 해시맵처럼 처리할 수 있습니다. JavaScript 엔진은 이러한 동작을 효율적으로 처리할 수 있어야 합니다. 하지만 웹어셈블리로 이식하여 JavaScript 없이 실행하면 성능이 매우 떨어집니다. 정규 표현식도 마찬가지입니다. 웹어셈블리가 JavaScript보다 빠르지만, 브라우저 공급업체가 C++로 작성하고 최적화하여 JavaScript에 노출한 브라우저 API보다는 빠르지 않습니다. 처음에는 Java로 작성된 정규 표현식 라이브러리를 웹어셈블리로 컴파일했는데, 성능이 매우 떨어졌습니다. 나중에 크롬의 브라우저 API가 엄청나게 빠르다는 것을 알았습니다. 정규 표현식 엔진이 매우 인상적이었죠.
토마스: JavaScript 내부의 문자열을 활용하는 내장 문자열도 비슷한 예입니다. JavaScript로 구현된 JavaScript 내부 문자열을 활용하는 방식인데, 정규 표현식과 비슷하다고 볼 수 있습니다. 어제 모질라의 라이언 헌트와 인터뷰를 했는데, 그는 내장 문자열 제안의 주요 지지자입니다. 내장 문자열 제안은 정규 표현식과 같이 확장 가능하도록 설계되었습니다.
션: 문자열에 대해 좀 더 자세히 설명해 주시겠어요?
마이클: 네, 문자열도 흥미로운 예입니다. 계산 엔진은 작업자 내부에서 실행되며, 스프레드시트의 상태와 재계산해야 하는 셀을 입력받습니다. 계산을 완료하면 결과를 출력하는데, 이 모든 과정은 메인 스레드와 작업자 스레드 간에 직렬화됩니다. 처음에는 문자열로 직렬화되었던 것으로 기억합니다.
정규 표현식도 문자열로 표현됩니다. JavaScript를 호출하고 문자열을 주고받아야 하는 경우 문자열에 많은 부담이 가해집니다.
그래서 Java와 JavaScript가 동일한 문자열 구현을 사용한다는 점에 착안했습니다. 문자열을 다시 구현하고 웹어셈블리로 컴파일하는 대신, 이미 최적화된 JavaScript의 문자열 구현을 재사용하면 두 가지 문자열 구현 간의 마샬링을 줄일 수 있습니다. 문자열 참조, 가져온 문자열 등 여러 가지 접근 방식이 있었는데, 결국 가져온 문자열을 사용하기로 했습니다. 그 결과 계산 엔진의 전체 성능이 약 10% 향상되었습니다.
마이클: 웹어셈블리와 JavaScript를 직접 비교하면 웹어셈블리가 더 빠르지만, JavaScript에는 해시맵, 정규 표현식 엔진 등 오랜 시간 동안 최적화된 부분이 있습니다. JavaScript에서 많이 사용되기 때문에 최적화된 것이죠. 또한 브라우저에서 이러한 기능을 실행하는 것도 성능에 영향을 미칩니다.
션: 해시맵 성능 문제는 어떻게 해결했나요?
마이클: 적절한 데이터 구조를 사용했습니다. JavaScript에서는 모든 것이 해시맵인데, 이는 최선의 설계는 아니라고 생각합니다. JavaScript를 빠르게 구현할 수 있다는 장점은 있지만, 최적화된 데이터 구조를 작성하려면 적합하지 않습니다. 해시맵이 필요하면 해시맵을 사용하고, 배열처럼 동작해야 한다면 배열을 사용하고, 희소 배열이 필요하면 희소 배열을 사용해야 합니다.
또한 JavaScript가 빠른 문자열 및 정규 표현식 구현을 가지고 있다고 말하지 않고, 브라우저가 빠른 구현을 가지고 있다고 말했습니다. 이러한 구현은 현재 JavaScript를 통해서만 노출됩니다. 따라서 초고속 정규 표현식 엔진을 사용하려면 JavaScript를 통해 요청해야 합니다. 웹어셈블리는 단순한 숫자 계산기라는 개념에서 비롯된 것입니다. 웹어셈블리는 외부 세계와 연결되지 않은 작은 숫자 계산기입니다.
션: 웹어셈블리가 단순한 숫자 계산기 이상의 역할을 할 수 있다고 생각하시나요? 웹 애플리케이션이 점점 복잡해지면서 웹어셈블리가 더 큰 역할을 할 수 있을까요?
토마스: 물론입니다. 저는 개인적으로 웹어셈블리에 큰 기대를 걸고 있습니다. 웹어셈블리가 단순한 숫자 계산기로 설계되었다는 말은 오해의 소지가 있습니다. 웹어셈블리가 처음에는 작고 단순하게 설계된 이유는 합의를 쉽게 이끌어내기 위해서였습니다. 범위를 제한하면 명세를 더 쉽게 발전시킬 수 있습니다. 처음부터 모든 사람을 만족시키려고 하면 논쟁이 많아지고 진전이 어렵습니다. 웹어셈블리가 항상 이런 식으로 유지될 것이라고 생각하지 않습니다.
토마스: 웹어셈블리는 웹에서만 사용되는 것이 아닙니다. 서버에서도 많이 사용됩니다. 웹어셈블리를 사용하려는 클라우드 스타트업이 많이 있습니다. WASI와 컴포넌트 모델을 통해 웹어셈블리는 초기 MVP 구현에서 크게 발전했습니다. 웹에서 웹어셈블리 사용이 증가했고, 기술적으로는 서버에서의 사용이 웹에서의 사용을 능가했을 수도 있습니다. 정확한 수치는 없지만, 최근 컨퍼런스에서 웹 관련 발표보다 서버 관련 발표가 훨씬 많았습니다.
웹에서 웹어셈블리는 단순한 숫자 계산기가 아니라 웹 플랫폼이 성장하고 여러 언어를 사용하여 다양한 사용 사례를 효율적으로 처리할 수 있도록 하는 역할을 합니다. 구글 워크스페이스는 단순한 웹 페이지나 작은 웹 앱이 아니라 수백만 줄의 코드로 이루어진 엔터프라이즈급 생산성 애플리케이션입니다. JavaScript로 작성해야 했지만, 이제는 더 나은 언어로 전환할 수 있게 되었습니다.
마이클: 웹어셈블리는 웹용 숫자 계산기일 뿐만 아니라, 코드를 안전하고 효율적으로 실행하는 방법에 대한 명세입니다. 따라서 다양한 분야에서 활용될 수 있습니다. 예를 들어, 웹어셈블리는 안전하고 빠르게 실행할 수 있기 때문에 작은 함수를 실행하는 데 적합합니다. 웹어셈블리 기술이 유용하게 활용될 수 있는 분야가 많습니다.
션: JavaScript가 웹 애플리케이션 개발의 주요 진입점 역할을 해왔다는 점이 흥미롭습니다. 20년 전으로 돌아가서 JavaScript가 세계에서 가장 많이 사용되는 언어가 되고 수백만 줄의 JavaScript 코드로 작성된 매우 복잡한 애플리케이션을 개발하게 될 것이라고 생각했다면 아마 미쳤다고 했을 것입니다. 하지만 지금은 현실이 되었습니다. 언젠가는 JavaScript의 지속 가능성에 대한 의문이 제기될 것입니다. JavaScript는 기본 웹 페이지에 상호 작용을 추가하기 위해 설계된 언어였지만, 지금은 그 이상으로 발전했습니다.
마이클: 저도 처음에는 JavaScript가 유연한 언어이고 멀티플랫폼 문제를 해결할 수 있는 해결책이라고 생각했습니다. 하지만 7~8년 동안 JavaScript만 사용하여 생산성 애플리케이션을 개발하면서 JavaScript의 단점을 뼈저리게 느끼게 되었습니다. JavaScript만 사용해서 개발할 수는 있지만, 마치 한 손을 등 뒤로 묶고 싸우는 것과 같습니다. Java나 Kotlin과 같은 언어는 개발을 훨씬 쉽게 만들어주는 기능을 제공합니다.
멀티플랫폼 측면에서도 JavaScript로 작성된 코드를 Android나 iOS에서 실행하려면 성능이 떨어질 수밖에 없습니다. 저는 JavaScript를 해결책으로 보는 관점에서 문제로 보는 관점으로 바뀌었습니다.
토마스: JavaScript의 단점을 해결하기 위해 TypeScript가 등장했습니다. 구글에서는 오랫동안 Closure Compiler를 사용했는데, 이번 달에 지원이 중단되었습니다. TypeScript는 JavaScript의 모듈, 타입 안전성, IDE 지원 등을 개선했습니다. 하지만 멀티플랫폼 문제는 해결하지 못했습니다. TypeScript는 성능 면에서는 아무런 도움이 되지 않습니다. 내부적으로는 여전히 JavaScript의 한계에 묶여 있습니다.
마이클: TypeScript는 타입 안전성과 IDE 지원 측면에서 큰 도움이 되지만, 멀티플랫폼 문제는 해결하지 못합니다. TypeScript는 성능 면에서는 아무런 개선이 없습니다. 내부적으로는 여전히 JavaScript의 한계에 묶여 있습니다.
션: Wasm GC가 널리 사용되면 JavaScript 웹 개발 환경에서 흔히 볼 수 있는 문제를 해결하는 데 도움이 될까요? 20년 전에는 프런트엔드에서 많은 작업을 처리하지 않았고, 모든 작업이 백엔드에서 처리되었습니다. 그러다가 SPA 시대가 도래하면서 모든 작업이 프런트엔드에서 처리되기 시작했습니다. 하지만 모바일 성능 문제가 발생했고, 이제는 다시 서버에서 더 많은 코드를 처리하는 방향으로 전환되고 있습니다. 프런트엔드와 백엔드 사이에서 끊임없이 균형을 맞추려고 노력하고 있지만, 근본적인 문제는 프런트엔드의 한계에 있는 것 같습니다.
토마스: 최근에 브라우저 기술 팟캐스트에서 Row Zero라는 회사의 개발자 인터뷰를 들었는데, 그들은 구글 시트와 경쟁하는 제품을 개발하고 있었습니다. 그들은 서버에서 셀 관련 데이터를 스트리밍하고, UI는 로컬에서 DOM으로 실행하는 하이브리드 방식을 사용했습니다. 스트리밍된 데이터는 캔버스에 렌더링되었습니다. 모바일 기기와 저사양 Android 폰에서도 수백만 줄의 스프레드시트를 열어야 하는 경우가 있기 때문에 흥미로운 접근 방식이라고 생각합니다.
마이클: 웹어셈블리의 미래와 다양한 사용 사례, 아키텍처에 대해 이야기했는데, 앞으로는 웹어셈블리를 기반으로 더 큰 애플리케이션을 개발하기 위한 툴킷과 프레임워크가 개발될 것으로 예상됩니다. JavaScript가 모든 사용 사례를 처리하는 대신, 웹에서 다른 언어가 특정 사용 사례를 더 효율적으로 처리할 수 있게 될 것입니다.
또한 멀티플랫폼이라는 개념도 중요합니다. 워크스페이스는 웹뿐만 아니라 Android, iOS에도 배포됩니다. JavaScript로 배포할 수도 있지만, 특히 성능이 중요한 경우 단점이 많습니다. 웹어셈블리는 멀티플랫폼 측면에서 웹을 위한 더 나은 빌드 대상을 제공합니다.
이미 멀티플랫폼 기반을 구축했기 때문에 JavaScript에서 웹어셈블리로 전환하는 것이 비교적 쉬웠습니다. 하지만 기존 JavaScript 애플리케이션을 웹어셈블리로 전환하는 것은 쉽지 않습니다. 언어의 한계 때문입니다. 웹어셈블리를 사용하려면 먼저 모든 코드를 JavaScript에서 다른 언어로 변환하고, 문제를 해결해야 합니다.
션: 서버 측 컴포넌트를 Java로 개발한 다음, 프런트엔드에서 실행할 수 있도록 JavaScript로 변환하는 방법을 구축했기 때문에 컴파일 과정을 Java에서 JavaScript로, Java에서 웹어셈블리로 바꾸는 것이 가능했습니다.
마이클: 저는 지금까지 이러한 변환 작업을 모두 경험해 봤습니다. 구글 문서는 원래 JavaScript로 작성되었는데, 전체 코드베이스를 JavaScript에서 Java로 변환했습니다. 구글 시트는 서버에서 실행되는 계산 엔진 때문에 원래 Java로 작성되었고, 나중에 Google Web Toolkit을 사용하여 Java에서 JavaScript로 변환하여 클라이언트에서 실행했습니다.
이러한 경험을 통해 얻은 교훈은 여러 플랫폼에 배포할 수 있는 좋은 언어로 코드를 작성하면 모든 애플리케이션 아키텍처를 지원하고, 모든 코드를 서버나 클라이언트에서 실행할 수 있다는 것입니다.
예를 들어, 구글 문서는 클라이언트에서 문서를 렌더링합니다. 브라우저에서 실행되는 문서 렌더링 엔진이 있습니다. 하지만 저사양 기기에서는 서버에서 문서의 첫 페이지를 렌더링하는 것이 클라이언트에서 렌더러를 로드하고 페이지를 렌더링하는 것보다 빠를 수 있습니다. 동일한 렌더링 엔진이 Java로 작성되었기 때문에 서버에서도 실행할 수 있습니다.
이러한 경험을 통해 얻은 가장 큰 교훈은 유연한 환경을 구축하는 것입니다. 그러면 새로운 기기, 폼 팩터, 아키텍처가 등장하더라도 모든 기기에서 모든 코드를 최적의 방식으로 실행할 수 있습니다.
션: 이제 다시 이식 프로젝트에 대해 이야기해 보겠습니다. 현재 프로젝트 진행 상황은 어떻고, 성능은 얼마나 향상되었나요?
마이클: 현재 프로젝트는 100% 완료되어 모든 사용자가 웹어셈블리 버전의 시트를 사용하고 있습니다. 웹어셈블리 버전의 계산 엔진을 완성한 후 성능 테스트를 위해 12개 정도의 테스트 시트를 실행했는데, JavaScript 버전보다 2배 느렸습니다. 나쁘지 않은 결과였지만, 1년 동안 최적화 작업을 거쳐 거의 모든 경우에서 2배 빠른 성능을 달성했습니다.
션: 처음 테스트에서 JavaScript 버전보다 2배 느렸다는 결과가 놀랍지 않았나요?
마이클: 저는 이전에도 이식 작업을 하면서 10배 느려지는 경우를 봤기 때문에 2배 느리다는 결과는 나쁘지 않다고 생각했습니다.
션: 성능이 2배 향상되었는데, 앞으로 더 최적화할 여지가 있을까요?
마이클: 아직 한계에 도달하지 않았다고 생각합니다. 목표 성능을 달성할 때까지 최적화 작업을 진행했고, 출시 후에도 계속해서 최적화 작업을 진행할 예정입니다. 쉬운 최적화는 이미 완료되었지만, 아직 개선할 여지가 있습니다.
현재 Java 코드 실행 속도가 JVM과 거의 비슷한 수준입니다. JVM은 Java 코드실행의 황금 표준이죠. 웹어셈블리가 JVM의 성능을 따라잡거나 뛰어넘을 수 있을지는 아직 확실하지 않습니다. 하지만 JVM은 30년 동안 최적화되어 왔다는 점을 기억해야 합니다.
앞으로는 성능 향상 폭이 크지 않을 것으로 예상됩니다. 공유 메모리, 멀티 스레딩 등 아직 Wasm GC에서 지원하지 않는 기능을 추가해야 합니다. 단일 스레드 성능은 천천히 개선될 것으로 예상되며, 결국에는 JVM 성능에 근접할 것입니다.
션: Wasm GC에 관심 있는 사람들이 참여하거나 직접 사용해 볼 수 있는 방법이 있을까요?
토마스: V8 웹사이트에 Wasm GC 관련 문서가 있고, 저는 developer.chrome.com에 Wasm GC 관련 기사를 작성했습니다. 하지만 컴파일러 전문가나 언어 전문가가 아니라면 Wasm GC를 직접 구현하는 것은 매우 어려운 일입니다. 예를 들어, Dart를 Wasm GC로 이식하는 작업은 매우 복잡합니다. Wasm GC의 진정한 가치는 Dart와 같은 언어를 사용하는 개발자가 Wasm GC를 통해 웹에서 Dart 코드를 효율적으로 실행할 수 있게 되는 것입니다. Wasm GC를 직접 구현하는 것보다 Wasm GC를 지원하는 툴체인을 개발하는 것이 더 중요합니다. 그러면 Dart나 Kotlin과 같은 가비지 컬렉션 언어를 사용하는 개발자가 Wasm GC를 쉽게 활용할 수 있습니다.
마이클: Kotlin도 웹어셈블리 컴파일러를 제공합니다. 따라서 개별 웹사이트를 개발하는 개발자가 Wasm GC를 직접 사용할 필요는 없습니다. 하지만 다른 언어용 컴파일러가 출시될 예정이므로, JavaScript를 배우고 싶지 않다면 Wasm GC를 통해 다른 언어를 사용할 수 있게 될 것입니다.
토마스: 컴파일러 작성은 매우 재미있습니다. 많은 사람들이 어렵다고 생각하지만, 실제로 해보면 매우 흥미롭습니다.
마이클: 언어도 매우 재미있습니다. 컴파일러를 직접 작성해 보면 프로그래밍 언어의 작동 방식을 더 깊이 이해할 수 있습니다.
션: 최적화 작업에 대해 이야기했는데, 언어 구조를 생각해 보면 각 줄을 해석하고 웹어셈블리 명령어로 변환해야 합니다. 이 과정을 거치면 해당 언어를 누구보다 잘 이해하게 될 것입니다.
토마스: 저에게는 정말 멋진 경험이었습니다. 컴퓨터 과학에 대한 이해도를 높여줍니다.
션: 마지막으로 하고 싶은 말이 있나요?
토마스: Wasm GC가 어떤 사용 사례를 가능하게 하는지 살펴보세요. 앞서 언급했듯이 플러터는 이제 Wasm GC를 사용합니다. 따라서 플러터 애플리케이션을 웹으로 가져오려는 경우 지금이 좋은 기회입니다.
Kotlin도 Android 애플리케이션을 웹으로 이식할 수 있도록 지원합니다. 아직은 마법 버튼 하나만 누르면 웹에서 작동하는 것은 아니지만, 비교적 간단한 애플리케이션을 실행하려는 경우 지금 시작해도 좋습니다. JetBrains 팀은 JetBrains Multiplatform Compose를 통해 선언적 방식으로 UI를 작성하고, Kotlin 코드로 UI 동작을 구현할 수 있도록 지원하고 있습니다. Kotlin 팀에서 제공하는 몇 가지 흥미로운 예제가 있습니다. 이러한 예제는 Wasm GC를 사용하지만, 일반 개발자는 Wasm GC를 직접 다룰 필요가 없습니다.
마이클: Wasm GC는 멀티플랫폼 환경에서 웹을 훨씬 더 뛰어난 플랫폼으로 만들어주는 마지막 퍼즐 조각입니다. 구글은 플러터와 Kotlin Multiplatform을 모두 지원하고 있으며, 이러한 플랫폼을 통해 Android, iOS, 웹을 동시에 개발할 수 있습니다. Wasm GC 덕분에 웹 지원이 훨씬 쉬워지고 성능이 향상되었습니다.
이전에는 Android와 iOS 빌드가 비교적 간단했지만, 웹은 JavaScript의 한계 때문에 항상 특별 취급을 받아야 했습니다. 웹어셈블리, 특히 Wasm GC는 이러한 제약을 없애줍니다. 앞으로 2~3년 안에 멀티플랫폼 생태계가 웹에서 더 많이 사용될 것으로 예상됩니다.
션: 토마스, 마이클, 오늘 함께해 주셔서 정말 감사합니다. 대화를 즐겁게 들었습니다. 그리고 이 대화와 관련된 훌륭한 블로그 게시물도 감사합니다. 청취자 여러분도 토마스의 블로그 게시물을 읽어보시기 바랍니다.
마이클, 토마스: 초대해 주셔서 감사합니다!