React Native 빌드 캐싱의 끝판왕: RNEF 도입으로 빌드시간 96% 절감

어디나 코드 변경에 대한 증감 빌드는 생산성 효율성 면에서 늘 이슈죠.
제가 담당하고 있는 프로젝트도 Next.js 모노리포도 마찬가지에요.
아마 다른 프로젝트들도 공통의 관심사를 가지고 있을 것이라 생각됩니다.
이 기사는 Callstack Principal Enginner 인 Michal Pierzchala 와 RNEF 팀에 CI 시간의 비효율성에 대한 문제를 인지하고
해소하는 과정 나온 비하인드 이야기입니다.
대부분의 React Native 팀은 CI에서 시간과 비용을 낭비하고 있습니다. 그 이유는 코드 변경의 종류와 상관없이 매번 프로젝트를 처음부터 전체 빌드하기 때문입니다.
우리는 한 팀이 네이티브 빌드 빈도를 96% 줄이고, 관련 컴퓨트 리소스를 10배 줄이는 데 성공했습니다.
Expensify에서 벌어진 일
Expensify는 미국 샌프란시스코에 본사를 둔 경비 처리 및 비용 보고 자동화 플랫폼입니다.
전 세계 수백만 명의 사용자를 보유하고 있으며, React Native를 기반으로 모바일 앱을 운영하고 있습니다.
Expensify 팀은 모든 커밋마다 전체 네이티브 빌드를 수행하고 있었습니다.
하지만 실제로 분석해보니, 네이티브 빌드가 필요한 커밋은 전체의 4%, 즉 25개 중 단 1개에 불과했습니다.
대부분의 커밋은 JavaScript 변경에 국한되어 있었고, 네이티브 빌드는 불필요했습니다.
우리는 어떻게 해결했을까?
우리는 오픈소스 React Native Enterprise Framework (RNEF)를 통해 원격 네이티브 빌드 캐싱을 도입했습니다.
이 프레임워크는 다음과 같은 핵심 로직을 기반으로 작동합니다:
RNEF 최적화 전략
1. JS-only 변경 탐지 (Smart Build Skipping)
RNEF는 Git diff를 분석하여, 변경된 파일이 android/, ios/, native_modules/ 등 네이티브 영역에 속하는지 판단합니다.src/, App.tsx, *.js/ts(x) 등의 변경만 감지될 경우, native build step을 완전히 생략하고 JavaScript-only pipeline만 실행합니다.
이 판단은 단순한 glob 매칭이 아니라, Git tree와 파일 해시 비교를 통해 의미 있는 변경만 인식합니다.
✅ 적용 팁:
rnef determine-impact같은 커맨드를 GitHub Actions에서 조건문과 함께 사용하면, Job 자체를 skip 할 수 있습니다.
2. Build Artifacts Smart Caching
ccache는 C/C++ 계층의 중간 결과만 캐싱합니다.node_modules나Pods도 부분적 효과밖에 없습니다.
핵심은 .app, .apk, intermediates, build 디렉토리 전체를 포함한 아티팩트를 fingerprint 기준으로 재사용하는 것입니다.
@expo/fingerprint을 통해:
Android:
gradle.properties,build.gradle, Java/Kotlin 소스iOS:
.xcodeproj,.xcworkspace,Podfile.lock, Swift 소스
등의 변경 여부를 해시 기반으로 계산하고, 동일 fingerprint일 경우 캐시 재사용을 보장합니다.
3. Self-hosted Cache 저장소 구성
빌드 캐시는 GitHub Actions의 actions/cache를 쓸 수도 있지만, 대규모 팀에서는 자체 object storage를 쓰는 게 더 효율적입니다.
✅ 추천:
minio혹은 AWS S3를 이용한 캐시 서버 구축
rnef cache push/pull명령어를 통해 CLI 기반 동기화
4. CI 연동 전략 (GitHub Actions 기준)
jobs:
check-impact:
runs-on: ubuntu-latest
outputs:
should_build_native: ${{ steps.impact.outputs.native }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Determine Impact
id: impact
run: |
npx rnef determine-impact > result.json
echo "native=$(jq .native result.json)" >> "$GITHUB_OUTPUT"
그 후 아래처럼 조건부 빌드 실행:
build-native:
needs: check-impact
if: needs.check-impact.outputs.should_build_native == 'true'
🧠 실제 효과
전체 빌드 중 96%는 이제 2분 내에 완료 (기존 40분 → 2분)
GitHub Actions의 컴퓨트 사용량 약 10배 감소
비용은 20배 절감 (macOS + Linux 환경 기준)
벤더 종속 없음, 완전한 셀프 호스팅 가능
Michal Pierzchala는 누구인가?
Michal Pierzchala는 React Native 전문가이자 오픈소스 기여자, 그리고 모바일 빌드 최적화 분야의 리더이고
Callstack에서 테크니컬 리드로 활동하며, Hermes, React Native Performance 등 다양한 핵심 프로젝트에 기여해 왔습니다.
최근에는 React Native의 CI/CD 비용 최적화를 위해 RNEF (React Native Enterprise Framework)를 주도적으로 개발하고 있습니다.
RNEF란?
React Native Enterprise Framework (RNEF)는 대규모 팀이 React Native 프로젝트를 보다 효율적으로 관리하고 배포할 수 있도록 돕는 오픈소스 프레임워크입니다.
주요 기능은 다음과 같습니다:
네이티브 변경 여부 자동 탐지 및 건너뛰기
build artifact fingerprint 기반 캐시 최적화
GitHub Actions와 연동 가능한 CLI 유틸리티
벤더 종속 없는 완전한 셀프 호스팅 지원
📦 GitHub 저장소: https://github.com/callstack/rnef
🌐 공식 사이트: https://www.rnef.dev/
