Skip to main content

Hermes as the Default

· 9 min read
Michael Leon
Michael Leon
Software Engineer at Meta

지난 10월, 우리는 모든 React Native 앱에서 Hermes를 기본 엔진으로 설정하기 위한 작업을 시작했다고 발표했다.

Hermes는 Meta 내부에서 React Native에 많은 가치를 제공해 왔으며, 오픈소스 커뮤니티도 이로부터 혜택을 받을 것이라고 믿는다. Hermes는 리소스가 제한된 장치를 위해 설계되었으며, 앱 시작 시간, 앱 크기, 메모리 소비를 최적화한다. Hermes와 다른 JS 엔진의 주요 차이점은 JavaScript 소스 코드를 사전에 바이트코드로 컴파일할 수 있다는 점이다. 이 사전 컴파일된 바이트코드는 바이너리 내부에 번들로 포함되며, 앱 시작 시 이 비용이 많이 드는 단계를 수행하지 않아도 된다.

발표 이후, Hermes를 더욱 개선하기 위해 많은 작업이 진행되었고, 오늘 우리는 React Native 0.70이 Hermes를 기본 엔진으로 제공하게 될 것임을 발표하게 되어 기쁘게 생각한다. 이는 v0.70부터 시작하는 모든 새 프로젝트에서 Hermes가 기본적으로 활성화됨을 의미한다. 7월에 출시될 이 롤아웃을 앞두고, 우리는 커뮤니티와 긴밀히 협력하여 전환이 원활하게 이루어지고 모든 사용자에게 가치를 제공할 수 있도록 하려 한다. 이 블로그 포스트에서는 이 변화로부터 기대할 수 있는 사항, 성능 벤치마크, 새로운 기능 등을 다룰 것이다. React Native 0.70을 기다리지 않고도 Hermes를 사용할 수 있다는 점을 기억하라. 이 가이드를 따라 기존 React Native 앱에서 Hermes를 활성화할 수 있다.

Hermes가 새 React Native 프로젝트에서 기본적으로 활성화되지만, 다른 엔진에 대한 지원은 계속될 것이다.

성능 측정

앱 개발자에게 중요한 세 가지 주요 지표를 측정했다: TTI, 바이너리 크기, 메모리 사용량. 테스트를 위해 React Native 앱 Mattermost를 사용했다. 2020년 고사양 하드웨어에서 Android와 iOS 모두에 대해 실험을 진행했다.

  • TTI(Time to Interactive)는 앱이 실행된 시점부터 사용자가 앱과 상호작용할 수 있을 때까지 걸리는 시간이다. 이 벤치마크에서는 앱 아이콘을 누르는 순간부터 첫 화면이 렌더링될 때까지의 시간으로 정의했다. Mattermost 시작 과정의 화면 녹화도 함께 제공한다.
  • 바이너리 크기는 Android에서는 APK 크기로, iOS에서는 IPA 크기로 측정했다.
  • 메모리 사용량 데이터는 Mattermost 앱을 몇 분 동안 사용하면서 수집했다. 두 엔진 모두에서 동일한 동작을 수행했다.

안드로이드 벤치마킹 데이터

모든 안드로이드 테스트는 삼성 갤럭시 S20에서 수행했다.

안드로이드 벤치마킹 데이터

TTI 비디오

Android TTI 비디오

iOS 벤치마크 데이터

모든 iOS 테스트는 iPhone 12 Pro에서 수행했다.

iOS 벤치마크 데이터

TTI 비디오

iOS TTI 비디오

느린 속도로 재생한 TTI 동영상, 시작 시간 차이를 더 명확히 보여주기 위해.

느린 속도로 재생한 iOS TTI 동영상

React Native/Hermes 통합

React Native의 새 버전을 출시할 때마다 발생하는 호환성 문제를 해결했다. 기존에는 React Native가 CocoaPods와 npm을 통해 배포된 사전 빌드된 바이너리로 Hermes에 의존했다. 이로 인해 API 또는 ABI 호환성 문제가 발생할 수 있었다. 이 문제를 해결하기 위해 React Native 0.69부터는 Hermes를 React Native의 모든 버전과 함께 빌드한다. 이렇게 하면 각 React Native 버전과 완벽한 호환성을 보장할 수 있다. 또한 더욱 긴밀한 통합이 가능해져, 기능 개발이나 버그 수정을 더 빠르게 반복할 수 있고, Hermes에 대한 큰 변경을 더 안전하게 진행할 수 있다. 새로운 통합 변경에 대한 더 자세한 정보는 여기에서 확인할 수 있다.

iOS Intl

Intl은 언어에 민감한 다양한 기능을 제공하는 ECMAScript 국제화 API다. 이 API의 iOS 버전 구현을 마무리했다. 이전까지는 이 기능이 없어 일부 개발자가 Hermes를 사용하지 못하는 문제가 있었다. 마이크로소프트와 협력해 완성한 안드로이드 버전은 React Native 0.65에서 출시됐다. React Native 0.70부터는 두 플랫폼 모두에서 네이티브 지원을 받을 수 있다.

일반적으로 Intl을 구현하려면 Unicode CLDR과 같은 대규모 데이터를 가져와야 한다. 하지만 이 경우 최대 6MB까지 바이너리 크기가 증가할 수 있다. Hermes의 바이너리 크기를 불필요하게 늘리지 않기 위해 iOS 자체에서 제공하는 API를 호출하는 방식으로 Intl을 구현했다. 이를 통해 iOS에 내장된 로케일 및 국제화 데이터를 모두 활용할 수 있다.

현재 진행 중인 작업

Hermes를 계속 발전시키면서, 우리는 개발자 경험을 개선하고 JavaScript 언어 기능 부족으로 인해 Hermes 사용을 꺼리는 사람이 없도록 하는 데 주력하고 있다. 구체적으로 다음과 같은 작업을 진행 중이다:

  • 개발자가 Chrome 개발자 도구 UI에서 직접 샘플링 프로파일러를 실행할 수 있도록 지원한다.
  • 커뮤니티의 오랜 요청사항인 BigInt 지원을 추가한다. 이 기능은 폴리필로 구현할 수 없어 일부 개발자가 Hermes 사용을 망설이게 하는 요인이었다.
  • 개발자에게 새로운 메모리 관리 기능을 제공할 WeakRef 지원을 추가한다.

마무리

Hermes가 기본 엔진으로 채택된 것은 장기적인 여정의 시작을 의미한다. 앞으로도 커뮤니티가 효율적인 앱을 개발할 수 있도록 새로운 기능을 계속 추가할 계획이다. 또한 GitHub 리포지토리를 통해 버그, 질문, 피드백, 아이디어 등을 공유할 것을 적극 권장한다. Hermes와 관련된 게시물에 사용할 수 있는 hermes 라벨도 마련해 두었다.