Hermes — 개념, React Native용 JS 엔진 및 작동 원리

저자: IT Sectr 게시일: 2026-07-06 읽는 시간: 9 분

Hermes는 AOT(Ahead-of-Time) 컴파일을 갖춘 JavaScript 엔진으로, Meta가 React Native용으로 개발하고 제한된 메모리를 가진 모바일 장치에 최적화했습니다. Meta Engineering 공식 블로그(2022)에 따르면, Hermes는 JavaScriptCore와 비교하여 앱 시작 시간을 20-50% 단축하고 번들 크기를 30-40% 줄입니다. V8 또는 JSC와 달리 Hermes는 장치에서 JIT 컴파일을 사용하지 않습니다. 모든 JavaScript는 Hermes CLI를 통해 빌드 단계에서 바이트코드로 컴파일됩니다. 이는 JIT 컴파일이 App Store 정책에 의해 제한되는 iOS에서 특히 중요합니다.

핵심 포인트

  • Hermes — AOT 컴파일을 갖춘 JavaScript 엔진, Meta가 React Native용으로 개발
  • AOT vs JIT — Hermes는 빌드 시 JS를 바이트코드로 컴파일, 장치에서 JIT 불필요
  • 성능 — 앱 시작 20-50% 더 빠름, 번들 30-40% 더 작음
  • Hades GC — 모바일 시나리오에 최적화된 저지연 가비지 컬렉터
  • 표준 — ECMAScript 2020+ (Proxy, BigInt, Reflect 완전 지원 없음)

Hermes란

Hermes는 Meta가 React Native용으로 만든 컴팩트한 오픈 소스(MIT 라이선스) JavaScript 엔진으로, 리소스가 제한된 모바일 장치에서 실행되도록 최적화되었습니다. Hermes의 주요 혁신은 JIT 컴파일을 포기하고 AOT(Ahead-of-Time)를 채택한 것입니다. React Native 앱 빌드 단계에서 Metro Bundler가 컴파일된 JavaScript를 Hermes CLI에 전달하면 HBC(Hermes ByteCode) 바이트코드로 변환합니다. 이 바이트코드는 장치에서 추가 컴파일 없이 엔진에 의해 직접 실행됩니다. 이 접근 방식은 예측 가능한 성능을 제공합니다. JIT 워밍업, 컴파일 일시 중지, 추가 배터리 소모가 없습니다. Hermes는 모바일 장치의 제한 사항을 고려하여 설계되었습니다. 적은 RAM(1-4GB), 제한된 전력 소비, 빠른 콜드 스타트 필요성입니다. Hermes의 첫 번째 공개 릴리스는 2019년이었으며, React Native 0.70(2022)부터 이 엔진은 Android의 표준이 되었습니다.

Hermes vs JavaScriptCore: 엔진 비교

JavaScriptCore(JSC)는 Safari와 React Native(버전 0.70 이전)가 사용하는 표준 WebKit 엔진입니다. JSC는 JIT 컴파일을 지원하여 복잡한 JavaScript 작업에 높은 성능을 제공합니다. 그러나 JIT는 워밍업이 필요합니다. 실행 초기 몇 초는 느리고(인터프리터 모드), 그 후 JIT가 핫 경로를 컴파일합니다. iOS에서는 App Store 정책(동적 코드 생성 금지)으로 인해 JIT를 실질적으로 사용할 수 없으므로 iOS의 JSC는 인터프리터 모드에서만 작동하여 성능이 저하됩니다. JSC는 바이너리 크기가 더 크고(약 10MB) JIT 인프라로 인해 더 많은 RAM을 소비합니다. Hermes는 JIT에 의존하지 않으므로 시작(콜드 스타트) 후 즉시 예측 가능한 성능을 제공합니다. JSC는 ECMAScript 표준을 더 완벽하게 지원하지만(Proxy, BigInt, Reflect 포함), 더 많은 리소스 소비를 대가로 합니다. 콜드 스타트와 작은 크기가 중요한 React Native 프로젝트에서는 Hermes가 선호됩니다. 무거운 JS 계산(게임, WebGL)이 필요한 프로젝트에서는 JSC가 더 높은 피크 성능을 제공할 수 있습니다.

매개변수HermesJavaScriptCore
컴파일AOT(빌드 시)JIT + 인터프리터(장치에서)
콜드 스타트20-50% 더 빠름기준 수준
번들 크기30-40% 더 작음기준 수준
RAM 사용량20-30% 더 적음기준 수준
ECMAScriptES2020(제한 있음)ES2022+(완전)
iOS JIT필요 없음사용 불가(인터프리터 전용)
바이너리~3MB~10MB

AOT 컴파일: 사전 빌드 작동 방식

AOT 컴파일(Ahead-of-Time)은 Hermes에서 두 단계로 이루어집니다. 첫 번째 단계에서 Metro Bundler는 JavaScript 파일을 단일 번들로 수집하여 Hermes CLI(유틸리티 hermesc)에 전달합니다. 두 번째 단계에서 hermesc는 JavaScript AST를 파싱하고 중간 표현 HIR(Hermes Intermediate Representation)을 생성한 후 바이너리 HBC 바이트코드를 내보냅니다. 결과는 원본 JavaScript 없이 바이트코드만 포함하는 .hbc 파일입니다. Hermes 런타임은 파싱 및 컴파일 없이 HBC를 직접 로드합니다. 이는 시작을 획기적으로 가속화합니다. 수천 줄의 JS를 파싱하는(비동기) 대신 엔진이 사전 컴파일된 바이너리 형식을 읽습니다. AOT는 크기도 줄입니다. 바이트코드는 JavaScript AST보다 평균 30% 더 컴팩트합니다. AOT의 단점은 런타임에 eval, new Function 또는 동적 require를 실행할 수 없다는 것입니다. 모든 모듈은 빌드 시점에 알려져 있어야 합니다.

bash
# Hermes CLI를 독립 실행형으로 설치
npm install hermes-engine

# JS를 HBC 바이트코드로 컴파일
npx hermesc -emit-binary -out bundle.hbc bundle.js

# 바이트코드 통계
npx hermesc -dump-bytecode bundle.hbc  # shows HBC instructions

# 원본 JS와 HBC 크기 비교
wc -c bundle.js      # 2,300,000 bytes
wc -c bundle.hbc     # 1,450,000 bytes (37% reduction)

Hermes 성능 지표

Hermes의 성능은 세 가지 주요 지표로 측정됩니다: TTI(Time-To-Interactive), APK/IPA 크기 및 RAM 소비량입니다. Meta 데이터에 따르면, Android에서 Hermes는 JSC와 비교하여 TTI를 34% 감소시킵니다. 중간급 장치(Moto G7)에서 4.2초에서 2.8초로 단축됩니다. 컴팩트한 바이트코드와 JIT 라이브러리 부재로 APK 크기가 28% 감소합니다. 동일한 부하에서 RAM 소비량은 평균 22% 낮습니다. 이는 특히 2-3GB RAM을 가진 장치에서 중요합니다. iOS에서는 JSC가 JIT를 사용할 수 없기 때문에 이점이 더욱 두드러집니다. Hermes는 TTI를 최대 45%까지 개선합니다. 지표는 Meta가 Facebook Lite 앱으로 수행한 테스트를 기반으로 합니다. 실제 프로젝트에서는 이점이 다양합니다. 단순한 화면(목록, 텍스트)에서는 Hermes의 개선 효과가 더 크고, 무거운 애니메이션에서는 더 작습니다. 프로파일링 도구: React Native Profiler + hermes profile --heap.

Hermes로 메모리 프로파일링

Hermes에는 Chrome DevTools를 통해 액세스할 수 있는 내장 메모리 프로파일러가 포함되어 있습니다. Metro를 통해 앱에 연결하고 메모리 탭을 열어 스냅샷 유형에서 Hermes(JavaScript)를 선택합니다. Hermes는 세 가지 스냅샷 유형을 지원합니다: Heap Snapshot(모든 객체), Allocation Timeline(객체 수명), Allocation Sampling(샘플링 프로필)입니다. Hades GC는 GC 일시 중지를 최소화합니다. 10초 작동당 평균 2-5ms의 일시 중지 한 번으로, 동일 기간 JSC의 10-20ms 일시 중지와 비교됩니다.

Hades GC 가비지 컬렉터

Hades GC는 Hermes의 가비지 컬렉터로, 최소한의 일시 중지로 모바일 시나리오를 위해 설계되었습니다. JSC의 mark-sweep GC와 달리 Hades는 동시(concurrent) 수집을 사용합니다. 수집기는 메인 실행 스레드와 병렬로 작업하며 짧은 간격으로만 중지합니다. Hades GC는 힙을 세대로 나눕니다. 젊은 세대(nursery)는 자주 그리고 빠르게 수집되고(Scavenge), 오래된 세대는 덜 자주 그리고 더 짧은 일시 중지로 수집됩니다. 힙 크기는 구성 가능합니다. 기본값은 앱 사용 가능 RAM의 2/3, 최소 임계값은 32MB입니다. Hades는 stop-the-world 방식을 사용하지 않습니다. 오래된 세대의 완전한 수집도 5-8ms를 넘지 않습니다. 수집기는 일반적인 모바일 시나리오에 최적화되어 있습니다. 수명이 짧은 객체(임시 문자열, React Fiber 객체)가 많고 수명이 긴 객체는 적습니다. 집중적인 객체 생성(목록, 애니메이션)이 있는 애플리케이션의 경우 Hades는 JSC보다 더 부드러운 FPS를 제공합니다.

React Native 프로젝트에서 Hermes 활성화 방법

Hermes 활성화는 React Native 버전과 플랫폼에 따라 다릅니다. React Native 0.70부터 새 프로젝트에서 Android용 Hermes가 기본적으로 활성화됩니다. iOS의 경우 Hermes는 선택 사항입니다. Android에서 활성화하려면 android/app/build.gradle 파일의 project.ext.react.enableHermes 블록에서 enableHermes: true를 설정합니다. iOS의 경우: use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true)를 통해 Podfile에서 hermes_enabledtrue로 설정합니다. 활성화한 후 pod install을 실행합니다. 기존 프로젝트의 경우 라이브러리 호환성을 확인하세요. Hermes는 Proxy, eval 및 일부 ES2021 기능을 지원하지 않습니다. 구성을 확인하려면 npx react-native info를 사용하세요. Hermes와 JSC 간 전환하려면 플래그를 변경하고 클린 리빌드를 수행하세요.

groovy
// android/app/build.gradle — Hermes 활성화
project.ext.react = [
    enableHermes: true,
    cliPath: "node_modules/react-native/cli.js"
]

// iOS/Podfile — iOS에서 Hermes 활성화
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

target 'MyApp' do
  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    :hermes_enabled => true
  )
end

Hermes 제한 사항: 지원되지 않는 기능

Hermes의 주요 제한 사항은 JIT 부재와 관련이 있습니다. Hermes는 다음을 지원하지 않습니다: ProxyReflect API(MobX, Vue, 일부 상태 관리자에서 사용), BigInt(큰 숫자), Symbol.toStringTag, WeakRefFinalizationRegistry. eval 및 new Function 함수는 런타임에 예외를 throw합니다. this 인수가 있는 Array.prototype.flatflatMap 메서드의 콜백은 제한적으로 작동합니다. 시간대가 있는 ISO 8601 날짜 형식이 완전히 처리되지 않습니다. 이러한 제한 사항의 대부분은 일반적인 React Native 애플리케이션에 영향을 미치지 않습니다. React와 React Native는 제한된 ES 기능 세트를 사용합니다. 라이브러리에 Proxy가 필요한 경우(예: Proxy를 사용하는 MobX 6+), configure({ useProxies: false })를 사용하거나 대안을 선택하세요. 기존 코드의 호환성을 확인하려면 번들에서 npx hermesc -check를 실행하면 지원되지 않는 기능 목록이 표시됩니다.

  • Proxy / Reflect — 구현되지 않음; Proxy가 필요한 라이브러리는 폴백 모드 필요
  • BigInt — 사용 불가; 큰 숫자에는 bignumber.js 라이브러리 사용
  • eval / new Function — 호출 시 예외 발생; 모든 모듈은 정적이어야 함
  • WeakRef / FinalizationRegistry — 지원되지 않음; 대안 없음
  • Symbol.toStringTag — 무시됨; instanceof는 정상 작동

자주 묻는 질문

앱이 Hermes에서 실행 중인지 확인하는 방법

앱 콘솔에서 console.log(global.HermesInternal)를 실행합니다. HermesInternal 객체가 존재하면 앱이 Hermes에서 실행 중입니다. 대안: console.log(global.HermesInternal?.getRuntimeProperties()) — 엔진 버전 및 GC 매개변수를 출력합니다. Release 빌드에서는 크기 최소화를 위해 HermesInternal을 사용할 수 없을 수 있습니다.

Hermes 활성화 후 iOS에서 앱이 충돌하는 이유

Podfile 설정을 확인하세요. iOS의 Hermes는 New Architecture(Fabric Renderer)가 필요합니다. :hermes_enabled => true를 설정하고 pod install --repo-update를 실행합니다. 프로젝트가 React Native 0.70 미만에서 업그레이드되는 경우 New Architecture와의 라이브러리 호환성을 확인하세요. 타사 라이브러리에 JSC가 필요한 경우 Hermes를 비활성화합니다. 플래그를 false로 변경하고 Pods를 다시 설치하세요.

Hermes가 개발 중 Hot Reload에 영향을 미치나요?

아니요, Hermes는 Hot Reload / Fast Refresh에 영향을 미치지 않습니다. 개발 중 Metro는 Hermes 컴파일 없이 JavaScript 번들을 실행합니다(일반 JS). Hermes 바이트코드는 Release 빌드에서만 컴파일됩니다. Debug 모드에서는 표준 JavaScriptCore 또는 인터프리터 모드의 Hermes가 사용됩니다. 구성에서 Hermes가 활성화되어 있어도 Hot Reload 속도는 변하지 않습니다. 전환은 프로덕션 빌드 단계에서만 발생합니다.

Hermes를 Expo와 함께 사용할 수 있나요?

, Expo SDK 45부터 Hermes는 managed 워크플로에서 지원됩니다. app.json에서 "jsEngine": "hermes"를 지정합니다. bare 워크플로의 경우 Hermes는 일반 React Native 프로젝트처럼 작동합니다. Expo Go는 Hermes를 지원하지 않습니다. Hermes로 빌드하려면 Expo Dev Client 또는 EAS Build를 사용하세요. expo doctor를 통해 라이브러리 호환성을 확인하세요.

내 프로젝트에서 Hermes와 JSC 성능을 비교하는 방법

React Native Performance Monitor(FPS 지표)와 Hermes Profiling Tools를 사용합니다. 동일한 장치에서 Hermes 버전과 JSC 버전, 두 가지 앱 버전을 만듭니다. 콜드 스타트(아이콘 탭부터 첫 번째 인터랙티브 화면까지), TTI(Time-To-Interactive), APK/IPA 크기 및 최대 RAM 소비량을 측정합니다. 각 구성에 대해 최소 3회 테스트를 실행합니다. 일반적인 Hermes 이점: 시작 20-40% 더 빠름, RAM 15-25% 더 적음.

요약

  • Hermes — React Native용 AOT 컴파일을 갖춘 Meta의 JavaScript 엔진, Android 0.70부터 표준
  • AOT 컴파일로 장치에서 JIT 워밍업 없이 예측 가능한 성능 제공
  • 콜드 스타트 20-50% 더 빠름, 번들 크기 JavaScriptCore 대비 30-40% 더 작음
  • Hades GC — JSC의 10-20ms 대신 2-5ms 일시 중지의 동시 가비지 컬렉터
  • 제한 사항: Proxy, BigInt, eval, WeakRef 미지원 — 라이브러리 확인 필요
  • 활성화: build.gradle의 enableHermes(Android) 또는 Podfile의 hermes_enabled(iOS)
  • Hermes CLI로 .hbc 바이트코드 컴파일 및 DevTools를 통한 메모리 프로파일링 가능
  • Hermes는 개발 중 Hot Reload에 영향을 주지 않으며 바이트코드는 Release에서만 컴파일됨

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기