20230721 - Hermes는 블록 스코핑을 지원하지 않는다.

Sol·2023년 7월 21일
1

저번 달 작성한 토스ㅣSLASH 23 - 달리는 토스 앱에 React Native 엔진 더하기 글이 SEO의 선택을 받은 것일까 조회수가 꽤 잘 오르고 있다.
하지만 최근 인터뷰에서 해당 글과 관련한 질문에 대답이 미흡해서 아쉬웠다.
질문은 esbuild와 관련된 내용이었고, 기존 metro 번들러와 차이점, 속도가 더 빠른 이유에 대해 물어봤었다.

esbuild로 react-native 프로젝트를 빌드하는 것이 막연히 복잡하고 어려운 사항이라 생각해 디테일하게 공부하지 않은 점이 화근이었다.

react-native-esbuild

간단히 esbuild로 react-native 프로젝트를 빌드해주는 라이브러리가 존재한다.
사용법 또한 굉장히 간단해서 조금 당황하긴 했다.
물론 커스텀 옵션을 다루기 위해 어느정도 esbuild 사용법도 알아야한다.

그러던중 유일하게 열려있는 이슈 하나를 발견하고, 글을 쓰기 시작했다.

react-native 개발팀은 작년 7월에 Hermes를 기본 엔진으로 사용할 것이라 공지했다.
Hermes는 기존 JSC(JavacriptCore)에 비해 월등히 나은 성능을 보여주고 있다.
하지만 해당 이슈에서 설명하듯이 react-native-esbuild 라이브러리와 Hermes를 같이 사용해도 되지만 빌드 타임 성능에 문제가 생긴다.

Hermes는 ES6 스펙인 let/const를 차용하고 있으나, 실제 let/const의 기능을 충실히 따르지 않는다.
마치 기존의 var처럼 전역 혹은 함수 스코프를 지닌채 컴파일 되어 미묘한? 버그를 발생시키고 있다.
더욱 자세히는 TDZ(Temporal Dead Zone)이라 불리는 선언 단계와 초기화 사이에 ReferenceError가 발생하지 않고, 호이스팅 되는 불상사가 생긴다.

이렇게만 얘기하면 복잡한 JS 수업 같으니 예시를 살펴보자

Lacking support for ES6 block scoping #575

2021년에 열린 ES6 블록 스코핑의 지원이 안된다는 이슈다.

댓글의 내용처럼 Hermeslet/const를 받아들이지만, 의미적으로 그들의 기능을 완전히 충족하진 못하고 있다.

https://hermesengine.dev/playground

function myFunction(arg){
  switch(arg) {
    case "1":{
      function onClick(){
        print("onClick 1")          
      }
      onClick()
      print("1")
      break;
    }
    case "2":{
       function onClick(){
          print("onClick 2")          
        }
        onClick()
        print("2")
    break;
    }
  }
}

myFunction("1");

예시처럼 해당 코드를 작성하고

직접 실행해보면 onClick 2처럼 블록 스코핑이 제대로 구현되지 않아 오류가 발생하는 것을 확인할 수 있다.


I also talked to members of the metro team, but my impression is they are not really aware of the performance issues they are having as their primary reference is webpack, not esbuild/swc, and that some issues stem from watchman which is not in their scope/expertise. I think the fundamental issue is that the main author of hermes is no longer at meta, and that they don't see how it directly benefits their use case (to which I might object to as it should reduce bundle sizes and build times).

Metro 팀은 webpack을 주로 참조하지 esbuild/swc 등을 참조하지 않는다.
그리고 watchman에 의해서 생기는 이슈를 다루며 scope/expertise 등은 관심이 저조하다.
Hermes를 만든 메인 개발자는 더이상 메타에서 일하지 않으며,
(번들 크기와, 빌드 타임을 줄이기 위해 그럴지도 모르지만) 이 사항이 직접적으로 사용 사례에 도움이 되는지 깨닫지 못하고 있다.

react-native-esbuild 메인테이너의 (울분과 절망이 담긴) 댓글을 보며 사태의 심각성을 알 수 있다.
그의 걱정처럼 Hermes는 아직도 ES6 블록 스코프가 적용된 메이저 버전을 내놓지 못하고 있다.


metro-react-native-babel-preset 라이브러리를 사용하면 @babel/plugin-transform-block-scoping 플러그인을 사용할 수 있다.
하지만 esbuild를 사용하는 이점이 사라지는 설정이긴 하다.

profile
야호

0개의 댓글