DEV Community

Cover image for Expo와 EAS
Chan
Chan

Posted on

Expo와 EAS

expo

  • expo는 react native framework이다. 해당 프레임워크에서 대표적으로 지원하는 기능은 다음과 같다.
    • autolinking
    • deep linking
    • debug(development) build app compilation
    • expo-router
    • development server와 devtools

expo로 개발하는 이유

expo로 react native 앱을 개발하는 대표적인 이유는 다음과 같다.

  • 직접 native / iOS directory의 의존성을 관리하고 유지보수를 할 필요 없이 npm package와 native module을 자동 연결시킨다.(autolinking)
  • expo dev server를 통해 앱을 다시 실행하거나, 서버를 reload하는 작업이 간단해진다. 생각보다 fast refresh가 잘 적용되지 않는 경우가 있어 유용하다.
  • expo SDK에서 사용하는 라이브러리의 버전이 서로 호환되는지 확인할 수 있다.(expo doctor)

expo cli

expo는 개발 환경을 지원해주기 위한 cli tool도 지원한다. 대표적인 명령어는 다음과 같다.

  • npx expo start: 개발 서버를 실행한다.
  • npx expo prebuild: app config file에 기반하여 native directory를 생성한다.
  • npx expo run:android: debug mode로 안드로이드 앱을 빌드하고 개발 서버를 실행한다.
  • npx expo run:ios: debug mode로 iOS 앱을 빌드하고 개발 서버를 실행한다.
  • npx expo-doctor : expo SDK의 버전 검증, app config file 검증 등을 진행한다.

Autolinking

  • react native 패키지 중에는 native code를 사용하는 package를 다운로드 받을 경우, package.json(javascript), build.gradle(android), podfile(iOS)에 의존성을 추가해야 한다.
  • autolinking을 사용하면, 각 실행 환경에 따른 세 개의 package managers를 사용하는 대신에 npm으로 패키지를 설치하고 pod install을 하는 것만으로 해당 프로세스를 자동화시킬 수 있다.
  • expo에서는 expo-modules-autolinking package로 autolinking을 구현하고 있는데, 해당 package는 세가지 요소로 구성되어 있다.
    • javascript cli tool
    • gradle build system과 통합되는 코드
    • iOS의 의존성 관리 툴 Cocoapods에 통합되는 Ruby 스크립트

개발 프로세스

  • javascript 코드를 작성하는 경우, fast refresh 또는 수동 reload를 통해 적용 결과를 확인한다.
  • app config file을 수정하거나, native code 또는 native directory의 설정 파일을 수정하거나, 네이티브 코드가 담긴 라이브러리를 추가하는 경우 npx expo prebuild --cleannpx expo run 으로 build 파일을 다시 만들어낸다.

core development loop

Continuous Native Generation

빌드가 필요할 때마다 app config file을 바탕으로 native directory를 생성하여, 개발자가 직접 각 생태계의 도구로 빌드 설정을 하는 노력을 없애주는 툴이다.

  • 개발자 스스로 생성된 native directory(/android , /ios 를 관리하지 않는다.
  • 기존에는 react native에서 native 의존성 및 빌드 설정을 각 네이티브 생태계의 툴로 관리를 해야 했다. android 빌드를 하기 위해 gradle을 직접 세팅하고, iOS 빌드를 하기 위해 Cocoapods를 직접 세팅하였다.
  • expo에서는 app config file(app.config.js 또는 app.json)을 참고하여 명시적으로 네이티브 설정을 통일하여 관리하고, native directory를 만들어낼 수 있기 때문에 직접 native 설정 파일을 수정할 필요가 없다.

EAS

  • eas는 expo로 작성된 app을 build, update, submit하기 위한 cli tool이다.
    • eas build는 production 또는 다른 이름의 build profile(빌드 설정 기준)으로 build 파일을 생성할 수 있다.
    • eas update는 스토어 심사를 거치지 않고 OTA 업데이트를 할 수 있다.
    • eas submit은 빌드 파일을 플레이스토어 또는 앱스토어에 전달할 수 있다.

expo는 react native 개발에 필요한 오픈소스 툴 집합이고, eas는 expo app을 production build, update, submit해주는 서비스이다.

Commands

eas build

  • expo가 제공하는 eas server에서 원격으로 빌드를 실행하는 명령어이다.
  • 2025년 4월 기준으로 free plan의 경우 1달에 30 크레딧을 제공한다. 안드로이드 빌드시 1크레딧, iOS 빌드시 2 크레딧 소모한다.
  • free plan에서 실행시킬 경우 대기 우선순위가 낮기 때문에 빌드를 하는데 최대 1시간 이상 대기할 수도 있다.
  • 유료 플랜의 경우 빌드 한번에 android medium 기종에서 1달러, iOS medium 기종에서 2달러가 지출된다.

앱을 업데이트할 때마다 ci pipelint에서 빌드를 실행시킬 예정이라면 1달에 30번 이상 빌드를 시도할 것이므로 local build를 하지 않으면 많은 비용이 청구될 수 잇다.

eas build --local

  • 로컬 환경에서 빌드를 실행시키는 명령어이다.
  • app signing에 필요한 credentials 같은 경우 루트 디렉토리에 존재하는 credentials.json을 참조한다.
  • github actions의 경우 public repository의 경우 ubuntu-latest, macos-latest 환경 runner 무제한 제공한다. eas build --local 을 원하는 만큼 돌릴 수 있다.
  • 원활한 빌드 속도를 보인다. job이 queue에 대기하는 시간이 관측 결과 10초 이내로 이루어진다. 그리고 총 빌드 시간도 25분 이내로 견딜만하다.

eas submit

eas submit

eas submit의 경우 구독 종류에 관계 없이 무제한으로 제공한다. 따라서 걱정 없이 사용할 수 있을 것으로 보인다.

eas update

  • eas 서버를 활용하여, 원격으로 javascript bundle 및 static asset을 업데이트하는 명령어이다.
  • eas update 가 MAU 1000까지는 무료이다. 따라서 작은 규모의 비즈니스가 적극적으로 활용할 수 있다.

    custom build

  • 만약 eas update 의 비용이 부담되기 시작한다면 다음과 같은 대안을 고려할 수 있다.

EAS Update을 사용하는 이유

플레이스토어나 앱스토어 앱을 제출하는 대신에, javascript를 원격으로 다운로드 받을 수 있게 만드는 매커니즘이 다음과 같은 이유로 필요하다.

  • 업데이트 시기의 통제 불가능

    업데이트를 반영되는 시기를 제어할 수 있는 권한이 개발자가 아닌 play store에게 있어 업데이트를 한 뒤에 이슈가 발생했을 때 바로 대응하기가 어렵다.

  • 치명적인 버그 수정 지연

    버그가 발생하고 고쳐지는 기간이 길어지면 길어질 수록 유저가 버그를 마주할 확률이 높아진다. 버그를 고쳐서 새로운 버전을 스토어에 제출하더라도 심사 기간이 길어질 수 있다. 버그를 마주한 사용자는 불편함을 느끼게 되기 쉬워진다.

  • OTA update

    OTA(over-the-air) update로 스토어 심사가 필요 없는 javascript 및 static asset을 서버에 업로드하고, 이를 사용자의 디바이스에서 다운로드 받아 업데이트를 우회하는 방식으로 해당 문제를 해결한다.

Version Management

appVersion

  • expo의 app.json 또는 app.config.js 에 의해 관리된다.
  • 사용자에게 보여지는 앱 버전이다.
  • android에서는 versionCode라고 부르고, iOS에서는 CFBundleVersion이라고 부른다.
  • iOS에서는 업데이트를 위해 업로드한 앱의 appVersion이 기존에 제출한 앱의 appVersion보다 높아야 한다. android에서는 심사에서 강제하지 않으나 스토어에 제출할 때마다 올리는 것이 관례이다.

native version number

  • expo에서 native version number 또는 native build number라고 부른다.
  • playstore/appstore에서 내부적으로 업데이트 순서를 판단할 때 사용한다.
  • 사용자에게 직접적으로 보여지지 않는다.
  • android에서는 versionName 으로 부르고, iOS에서는 CFBundleShortVersionString이라고 부른다.
  • 설치된 앱의 native version number와 스토어에 올라온 앱의 native version number를 비교하여, 스토어에 올라온 앱의 native version number가 높으면 업데이트를 적용한다.
  • android에서든 iOS에서든 업데이트를 위해 업로드한 앱의 native version number가 기존에 제출된 앱의 native version number보다 높아야 한다.
  • eas.json 에서 autoIncrement: true option을 설정하여 스토어에 제출할 때마다 자동으로 native version number가 올라가게 설정할 수 있다.

custom build 설정하기

  • 기존에 있는 빌드 과정에서 추가적으로 파일을 생성하거나 테스트 코드를 실행하는 과정을 추가할 수 있다.
  • .eas/build 디렉토리에 yml파일을 등록하고, eas.json 에서 해당 yml파일의 이름을 config option에 등록하여 사용할 수 있다.
  • custom build 설정을 안 했을 때 eas build 에서 수행하는 빌드는 다음과 같은 단계로 이루어진다.
    1. eas/checkout: 프로젝트의 소스 코드를 checkout한다. checkout을 하게 되면, 해당 소스코드를 임시 디렉토리로 복사한다. 빌드는 해당 디렉토리에서 이루어진다.
    2. eas/install_node_modules: 의존성을 다운로드 받는다.
    3. eas/resolve_build_config: app config file을 기반으로 build 설정을 확정짓는다.
    4. eas/prebuild: native directory를 만든다.
    5. eas/inject_android_credentials: app signing에 필요한 android credentials를 집어넣는다.
    6. eas/configure_android_version: android app version name을 설정한다.
    7. eas/run_gradle: gradle을 통해 빌드를 수행한다.
    8. eas/find_and_upload_build_artifacts: build output을 원래 프로젝트에 집어넣는다.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.