Expo 앱에서 EAS를 이용하여 Testflight에 올리기까지 (feat. 고난과 역경)

Derhon·2023년 9월 22일
4

오늘따라 회사 일도 엄청 많았는데, 사이드로 진행하던 배포마저 잘 안되니 하루종일 저 표정이었다... 출근 전에 끝내는게 목표였는데...
그치만 출근 전 퇴근 후 갈아넣어서 기가막히게 성공!!

Expo의 빌드와 배포

이 문서는 iOS 기준으로 작성되었습니다.
또한, Xcode는 이용하지 않습니다!

시작하기 앞서, 나는 앱 개발 경험은 몇 번 있지만...
하필 자바 기반 안드로이드코틀린 기반 안드로이드, 그리고 리액트 네이티브 기반 안드로이드 (...) 뿐이다.
일단 웹 개발 경험이 압!!!도적으로 많다보니 누가보면 '휴대폰은 갤럭시인가보네~' 라고 할 수 있겠지만 나름 아이폰8을 7년째 사용 중이다.

iOS보다 비교적 빌드와 배포가 간단한 웹과 안드로이드만 경험하다보니, 빌드가 이렇게 어려울 수 있다니 살짝 충격받았다. 역시 앱개발자 아무나 하는게 아니다...

우선 창업 지원을 받긴 하지만, 피봇 가능성도 있고 사실 BM이 명확하지 않아서.. 특히나 프론트 개발자 두명이서 엄청나게 꽤 큰 규모의 앱 서비스를 만들어야 했다보니, Expo와 EAS를 아주 적극적으로 활용하였다.

배포까지의 구조도

사실 나 보려고 쓰는거라 나중에 보고 이해하려고 그려봅니다.

간략한 구조는 위와 같습니다.

  1. Appple Developer에서 개발자 계정 등록 및 Identifiers 정도만 설정.
  2. 프로젝트 내부에서 app.json을 올바르게 작성하고, 앱 아이콘 설정 후 eas-cli 로그인 및 빌드 요청
  3. 빌드 과정에서 EAS와 나의 애플 개발자 계정을 연동.
    • 똑똑한 EAS가 필요한 것들을 알아서 세팅해줌.
    • 이 과정에서 무수히 다양한 에러가 발생한다.
  4. 빌드가 성공하면 IPA 다운로드 (선택)
  5. eas-cli를 통해 앱 등록을 요청할 수 있다.
    • 이 때, EAS에서 빌드한 앱을 선택하면 된다!
  6. 마지막으로 App Store Connect에 들어가서 테스트플라이트에 테스터 초대하면 끝이난다.

여기서 가장 어렵고 복잡한 부분이 3번이다. 사실 그 부분 말고는 뭔가 잘못되거나 에러날 일이 없어서...!
우선 각 순서 속 자세한 방법과 내가 3번에서 겪은 문제들에 대하여 공유하겠다.

Expo 빌드

1️⃣ 애플 개발자 계정

개 비싼 연회비를 내고 애플 개발자 계정을 등록한다.
그리고, Apple Developer에서 Identifier를 등록한다.

Identifier에서 중요한 것은, Capabilities를 잘 설정해야한다는 것인데...
일단 오늘의 배포 과정에서 가장 오랜 시간 동안 방황했던 것이 이거였다.

우리 프로젝트에서는 expo-notifications를 사용하고 있었는데, 사실 원격 푸시는 구현조차 하지 않았고 내부에서 타이머를 체크하여 동작하는 로컬 푸시 알람만 구현한 상태였다.
게다가 애플 개발자 계정 초기 세팅을 우리 팀의 서버 개발자가 했기에, 푸시 알람에 대한 설정이 제대로 등록되어있지 않은 상태였다.

만약 Identifier 이름을 제대로 설정하지 않거나, 본인 프로젝트에서 사용하나 제대로된 Capacity를 체크하지 않으면 아래와 같은 에러를 만나게 된다.

Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -workspace ./your-app.xcworkspace -scheme your-app -configuration Release -destination generic/platform=iOS -archivePath "/Users/expo/Library/Developer/Xcode/Archives/2023-09-22/your-app 2023-09-22 04.29.36.xcarchive" archive

User defaults from command line:
    IDEArchivePathOverride = /Users/expo/Library/Developer/Xcode/Archives/2023-09-22/your-app 2023-09-22 04.29.36.xcarchive
    IDEPackageSupportUseBuiltinSCM = YES

Prepare packages

Computing target dependency graph and provisioning inputs

Create build description
Build description signature: 
Build description path: /Users/expo/Library/Developer/Xcode/DerivedData/your-app-aayjvfubgxlwpngfkfniryefzhxi/Build/Intermediates.noindex/ArchiveIntermediates/your-app/IntermediateBuildFilesPath/XCBuildData/d3e360e2a74d40007a3f6946cdaf3afa-desc.xcbuild

note: Building targets in dependency order
warning: Run script build phase '[CP-User] Generate app.config for prebuilt Constants.manifest' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'EXConstants' from project 'Pods')
/Users/expo/workingdir/build/TERMTERM/ios/your-app.xcodeproj: error: Provisioning profile "*[expo] io.sociallogin.your-app AppStore 2023-09-22T01:26:19.288Z" doesn't support the Push Notifications capability. (in target 'your-app' from project 'your-app')
/Users/expo/workingdir/build/TERMTERM/ios/your-app.xcodeproj: error: Provisioning profile "*[expo] io.sociallogin.your-app AppStore 2023-09-22T01:26:19.288Z" doesn't include the aps-environment entitlement. Profile qualification is using entitlement definitions that may be out of date. Connect to network to update. (in target 'your-app' from project 'your-app')
warning: Run script build phase 'Start Packager' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'your-app' from project 'your-app')
warning: Run script build phase 'Bundle React Native code and images' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'your-app' from project 'your-app')

반드시! 올바른 Identifier 이름을 등록하고, 사용하는 Capacity는 꼭꼭 체크하자!

2️⃣ app.json / eas-cli

본격적으로 빌드할 때 필요한 app.json을 수정한다.
아래에서 필수적인 부분은 주석처리해놓았다.

{
  "expo": {
    "icon": "./assets/icon.png",
    "ios": {
      "supportsTablet": false,
      "usesAppleSignIn": true,
      "bundleIdentifier": "아까 입력한 identifier 속 번들 id!" //중요중요
    },
    ...
}

번들ID는 Identifier을 클릭해보면 확인할 수 있다. 꼭 올바른 값을 입력해주자...
안그러면 당신은 3시간 연속 빌드 실패 저주에 걸린다...

npm install -g eas-cli

이제 우리의 빌드와 배포를 책임질 EAS(를 cli로 간편하게 사용할 수 있는 툴을) 설치해준다.
굳이 전역으로 설치하는 이유는? 이라고 한다면, 이녀석은 라이브러리가 아니라 커맨드라인에서 직접적으로 활용할 수 있는 도구이기에 그렇다.

eas login //eas 계정이 없다면 가입해주세요! 어차피 프리티어라 무료임
eas build:configure //배포환경 세팅 -> eas.json이 생성됨

3️⃣ 빌드

한 번에 성공한다면 좋겠지만, 에러가 나와도 일단 침착하자!

대망의 3번 과정이다.
우선 빌드 명령어 자체는 굉장히 간단하다!

eas build --platform ios

이후 CLI에서 시키는대로 하면 되는데, 가이드라인은 일단 아래를 확인! 개인마다 차이가 있을 수 있음.

  1. 애플 로그인
  2. 인증서 발급 -> y
  3. 프로비저닝 프로파일 생성 -> y
  4. 푸시알림 키 생성 -> 만약 Identifier에서 Capacity에 체크를 했거나, 프로젝트에 푸시 알림 기능이 있다면 y!
  5. 자동 생성 여부 -> y

이제 빌드가 진행되는데, 빌드 진행되는 과정은 CLI에 등장하는 링크를 통해 확인할 수 있다.
깃허브 액션 같이 생겨서, 간지는 조금 나지만 이제 뭔소린지는 잘 안보이는 느낌이다.

⚠️ 앗, 푸시 알림이 프로젝트에 있는데 Capacity에 체크를 안했어요!

이런 경우, 당장 Capacity를 체크하고 프로비저닝 프로파일을 제거해준다.
그리고 빌드를 다시해보면 정상적으로 될 수도 있다!
안되면 다른 복합적인 문제가 있는 것

⚠️ main.jsbundle이 없대요!

EAS에서는 fastlane이라는 것을 사용하기 때문에, 저런 문구가 나온다면 사실 빌드에 실패했다는 뜻이다.
이런 경우 시도해볼 수 있는 경우가 두 가지로 나뉜다.

✅ metro 버전 확인

npm ls metro

metro 버전을 확인하고, 유독 혼자서 다른 버전의 metro를 사용하는 녀석이 있다면 그녀석이 범인이므로 그 모듈을 제거한다.

나의 경우에는 메트로 버전이 다 동일했기에 이 문제는 아니었다.

✅ 패키지 버전 / expo-cli 버전 최신화

사실 패키지 버전은 그렇다 쳐도, expo-cli 버전을 최신화 하는게 무슨 의미가 있을까 싶었는데... 깃허브 이슈나 스택오버플로를 뒤져보니 생각보다 이 방법으로 해결한 사람이 많았다.

expo upgrade //패키지 버전 맞추기 + 최신화
npm install -g expo-cli //expo-cli 최신화

나에게는 효과가 없었다.

✅ .gitignore 정리

사실 작업 중간에 app.json이나 eas.json을 숨기기 위해 깃 이그노어를 수정하고 커밋했다.
그러자 빌드에 완전히 실패하는 모습!

그때는 몰랐지만... 이후 혹시나 하는 마음에 node_modules를 제외한 모든 것을 주석처리하고 빌드하자... 성공

여기까지 했는데도 안된다 싶으면, 라이브러리를 잘 뜯어봐야한다.
스택오버플로에서 몇 번 봤지만, 지원이 중단된 라이브러리를 사용해서 실패한 사람도 많았다.

4️⃣ IPA 다운로드 (선택)

이제 빌드에 성공하면, EAS에서 링크를 제공해준다.
해당 링크에서 IPA를 다운받아도 되고, 안받아도 된다!
이유는 다음 순서에서

5️⃣ 앱 등록 요청

Expo.dev에 접속하고, 배포하려는 프로젝트 탭으로 이동한다.

좌측 하단에 Credential 탭으로 이동.

이제 다른 것들은 필요 없고, 페이지 최 하단에 존재하는 이 키를 채워야한다.
여기에 들어갈 키를 받으러 App Store Connect로 새탭을 띄워 이동한다!

이제 저 밑에서 키를 하나 생성하고, API 키를 소중하게 보관한다.
그리고 eas에 각각 알맞은 키를 넣어주면 된다!

eas submit -p ios

전부 설정이 완료되었다면, 위 명령어를 입력해서 애플에게 우리의 앱을 제출한다!!
중간에 무엇을 제출할거냐고 물어보는데, EAS에 우리가 빌드한 파일이 올라가 있으니 Select a build from EAS 선택 후, 알맞은 ID값을 선택했다.

이제 거의 다 왔다! 😆

6️⃣ Testflight

TestFlight 참고 문서

Expo로 빌드하고 배포하는 과정은 레퍼런스가 진짜 사막에서 바늘찾기 수준이지만, 테스트플라이트 업로드는 관련된 문서가 많았다.
그 중 가장 읽기 쉬웠던 문서이다!


쩝 또 생각해보니까 그정도로 고난과 역경은 아니었던 것 같..기도...하고...
역시 사람은 글을 적어야한다. 적다보니 별거 아닌 것 같았던 느낌이... 막이래,,ㅋㅋ
여튼 레퍼런스가 엄청나게 없기에 사실 이런 글도 누군가에게 도움이 될 수도 있을 것 같다! 일단 나에게...
테스트플라이트에서 앱을 돌려보는데 너무 신기하고 재미있다ㅋㅋ
이게 또 웹 배포하는거랑은 다른 맛이 있는 것 같다.
얼른 정식 출시하고! 사용자 유치해야지!!!

profile
🧑‍🚀 이사했어요 ⮕ https://99uulog.tistory.com/

1개의 댓글

comment-user-thumbnail
2024년 4월 4일

많은 도움 됐습니다!

답글 달기