EAS의 역사: 앱 빌드에서 모바일 배포 플랫폼까지
EAS를 eas build 명령어의 이름으로만 이해하면 서비스의 절반만 보게 됩니다. EAS는 Expo Application Services의 약자입니다. 소스 코드를 앱 바이너리로 만들고, 스토어에 전달하고, 이미 설치된 앱에 호환되는 업데이트를 보내는 모바일 배포 과정을 여러 서비스로 나눈 플랫폼입니다.
저도 처음에는 기존 expo build 명령이 이름만 바뀐 것으로 생각했습니다. 공식 발표와 현재 구조를 따라가 보니 EAS가 해결하려던 문제는 빌드 서버 교체보다 컸습니다. 초기 Expo의 편리한 빌드 경험을 사용자 네이티브 코드가 있는 React Native 앱까지 확장하고, 빌드 이후의 제출과 업데이트까지 같은 프로젝트 모델로 연결하려는 변화였습니다.
Classic 서비스가 먼저 있었습니다
EAS 이전에도 Expo에는 원격 빌드와 OTA 업데이트가 있었습니다. expo build:android, expo build:ios로 서버에서 앱을 만들고 expo publish로 JavaScript 번들을 배포할 수 있었습니다. 지금은 이 흐름을 Classic Build와 Classic Updates라고 부릅니다.
Classic 서비스는 초기 Managed Workflow와 잘 맞았습니다. Expo가 지원하는 네이티브 구성을 사용하면 인증서와 빌드 환경을 직접 준비하는 작업을 많이 줄일 수 있었습니다. 하지만 커스텀 네이티브 코드, 다양한 빌드 변형, 기존 React Native 프로젝트를 같은 방식으로 다루기는 어려웠습니다.
EAS는 이 제한을 없애는 쪽으로 설계됐습니다. 프로젝트의 네이티브 코드와 빌드 설정을 그대로 받아 표준 Android와 iOS 빌드 과정을 실행하고, Expo 프로젝트뿐 아니라 일반 React Native 프로젝트도 대상으로 삼았습니다.
2021년 Build와 Submit이 출발점이었습니다
Expo는 수개월의 프리뷰를 거쳐 2021년 11월 10일 EAS를 정식 출시했습니다. 당시 정식 서비스는 EAS Build와 EAS Submit이었습니다.
EAS Build는 Android의 AAB와 APK, iOS의 IPA처럼 설치하거나 제출할 수 있는 바이너리를 만듭니다. eas.json의 프로필로 development, preview, production 같은 목적별 설정을 나눌 수 있고, 원하면 코드 서명 자격 증명도 서비스가 관리합니다. EAS Submit은 완성된 바이너리를 Google Play와 App Store Connect에 업로드합니다.
여기서 Submit이 스토어 심사를 대신해 주는 것은 아닙니다. 업로드와 제출에 필요한 반복 작업을 자동화할 뿐, 앱 심사 정책과 최종 출시는 각 스토어가 관리합니다.
| 시기 | EAS의 변화 |
|---|---|
| 2021년 11월 | EAS Build와 EAS Submit 정식 출시 |
| 2022년 8월 | EAS Update 정식 출시 |
| 2023년부터 2024년 | Classic 서비스 전환, Update Rollout과 Rollback, 사용자 정의 빌드 확대 |
| 2024년 이후 | Workflows와 Hosting으로 CI/CD와 웹 배포 범위 확장 |
| 현재 | Build, Submit, Update, Workflows, Hosting 등을 하나의 프로젝트와 대시보드에서 연결 |
Build와 Update는 서로 다른 층을 배포합니다
EAS Update는 2022년 8월 정식 출시됐습니다. 이 서비스를 이해하려면 React Native 앱을 네이티브 층과 업데이트 층으로 나눠 봐야 합니다.
네이티브 층에는 Swift, Kotlin, React Native 런타임, 설치된 네이티브 모듈과 권한 설정이 들어갑니다. 이 층이 바뀌면 EAS Build로 새 바이너리를 만들고 스토어나 내부 배포를 통해 다시 설치해야 합니다.
업데이트 층에는 JavaScript 번들과 이미지 같은 에셋이 들어갑니다. 네이티브 층과 호환된다면 EAS Update로 새 번들을 배포할 수 있습니다. 앱 안의 expo-updates 모듈이 서버에서 업데이트를 확인하고 내려받은 뒤 다음 실행 시 적용합니다.
EAS Build
소스 코드 + 네이티브 설정 + 서명 정보 -> 설치 가능한 앱 바이너리
EAS Update
JavaScript + 에셋 -> 호환되는 기존 앱이 내려받을 업데이트호환성 판단의 핵심은 플랫폼과 runtimeVersion입니다. Android용 업데이트는 iOS 빌드에 적용되지 않으며, 업데이트의 런타임 버전은 앱 바이너리에 기록된 값과 정확히 맞아야 합니다. 네이티브 라이브러리를 추가하고도 JavaScript 업데이트만 보내면 새 코드가 기대하는 네이티브 API가 기기에 없을 수 있습니다. EAS Update가 앱 스토어 빌드를 완전히 대체할 수 없는 이유입니다.
Branch와 Channel은 Git과 비슷하지만 같지 않습니다
EAS Update의 Branch에는 시간순으로 여러 업데이트가 쌓입니다. Channel은 앱 빌드가 어떤 Branch의 업데이트를 받을지 연결하는 안정적인 이름입니다. 예를 들어 production 채널을 검증된 Branch에 연결해 두고, 배포 대상을 바꿀 때 채널의 연결만 옮길 수 있습니다.
Git Branch는 소스 코드의 이력을 가리키고, EAS Branch는 이미 번들링해 업로드한 업데이트의 이력을 가리킵니다. 이름을 같게 지을 수는 있지만 자동으로 같은 개념이 되지는 않습니다. 이 차이를 놓치면 소스 브랜치를 병합했는데 왜 특정 앱이 업데이트되지 않는지 추적하기 어려워집니다.
SDK 50에서는 Classic Updates 지원이 제거됐고 EAS Update가 기본 경로가 됐습니다. 이후에는 일부 사용자에게만 업데이트를 보내는 Rollout, 내장 번들로 되돌리는 Rollback, 채널 일시 정지 같은 운영 기능도 추가됐습니다.
Workflows는 빌드 명령을 배포 과정으로 묶습니다
Build, Submit, Update가 각각 한 작업을 수행한다면 EAS Workflows는 그 순서를 자동화합니다. .eas/workflows 아래의 YAML 파일에서 Git 이벤트나 수동 실행, 일정 실행을 시작점으로 삼고 빌드, 테스트, 제출과 업데이트 작업을 연결합니다.
최근 흐름에서 중요한 도구는 프로젝트 Fingerprint입니다. JavaScript만 바뀌어 현재 개발 빌드와 호환되면 새 네이티브 빌드를 생략하고 Update를 만들 수 있습니다. 네이티브 의존성이나 앱 설정이 달라져 Fingerprint가 바뀌면 새 Build를 생성합니다. 모바일 CI가 모든 커밋에서 비싼 네이티브 빌드를 반복하던 방식에서, 필요한 산출물만 만드는 방식으로 이동한 것입니다.
EAS를 사용하기 위해 Expo의 모든 부분을 채택할 필요는 없습니다. EAS Build는 기존 React Native 프로젝트를 지원하고 로컬 실행도 제공합니다. 반대로 Expo 앱도 EAS 대신 자체 CI와 빌드 환경을 선택할 수 있습니다. Expo는 오픈소스 프레임워크이고 EAS는 그 프레임워크와 깊게 통합된 클라우드 서비스라는 구분이 중요합니다.
제가 EAS를 한 문장으로 설명한다면 "Expo용 클라우드 빌더"보다 "네이티브 앱의 배포 수명 주기를 나눈 서비스 집합"이라고 하겠습니다. Build는 실행 환경을 만들고, Submit은 스토어까지 운반하며, Update는 그 환경과 호환되는 JavaScript를 전달합니다. Workflows는 이 판단과 순서를 반복 가능한 배포 과정으로 묶습니다.
공식 자료
함께 읽기
- Expo의 역사: SDK 0에서 CNG와 개발 빌드까지Expo를 설명할 때 가장 자주 붙는 말은 "React Native를 쉽게 쓰게 해 주는 도구"입니다. 틀린 설명은 아니지만 지금의 Expo를 이해하기에는 범위가 너무 좁습니다. Expo는 미리 만들어진 앱에서 JavaScript를 실행하던 초기 경험을 출발점으로 삼았고, 지금은 네이티브 프로젝트 생성과 모듈 개발, 라…
- Expo SDK 56 iOS 빌드 오류와 Swift weak let 호환성저는 견적킷을 iPhone에서 실행하려다 xcodebuild 코드 65를 만났습니다. 빌드 화면에는 Reanimated와 Worklets 컴파일 로그가 길게 지나갔고, 마지막에는 오류 15개가 있다는 메시지만 남았습니다.
- 모바일 앱 백업 설계: 암호화를 걷어내고 이미지 복원을 고친 과정영업 자료를 단말 안에 보관하는 앱에 백업 기능을 붙였습니다. 저장 대상은 멘트, 사진, 문서, 링크, 정보 카드였습니다. 처음에는 백업 파일 전체를 비밀번호로 암호화했습니다. 백업이 앱 밖으로 나가니 당연한 선택처럼 보였습니다.
- Expo 앱을 통째로 복사해 새 프로젝트 만들기: 그대로 가는 파일과 고쳐야 하는 파일성경 지도라는 앱을 만들면서 npx create-expo-app을 치지 않았습니다. 이미 두 스토어에 배포되고 있는 다른 앱의 폴더를 통째로 복사해서 시작했습니다.
- EAS 배포 구조: Build·Submit·Update 는 왜 따로인가앱 하나를 두 스토어에 올리면서 EAS 를 처음 제대로 썼습니다. 그 전까지는 "배포 명령을 돌리면 스토어에 올라간다" 정도로만 알고 있었는데, 실제로 해보니 그 한 문장 안에 서로 다른 세 가지 일이 섞여 있었습니다. 그걸 구분하고 나서야 어디서 막혔는지가 보였습니다.