Fastlane으로 TestFlight에 앱 업로드하기

peppermint100
PEPPERMINT100
Published in
12 min readMar 14, 2024

서론

소프트웨어 개발에는 CI/CD라는 개념이 있다. CI/CD는 Continuous Integration(지속적 통합)과 Continuous Delivery/Deployment(지속적 제공/배포)를 의미한다.

소프트웨어의 개발이 끝나면 이에 대해서 자동으로 기존 코드와 통합을 진행하고 테스트를 거치며, 자동으로 수정된 코드가 적용된 버전을 제공, 배포하는 것을 의미한다.

이 과정은 소프트웨어 개발의 라이프사이클을 간소화하며 가속화 하기 위해 등장한 개념이다.

이전 회사에서는 AWS Codepipeline을 통해서 CI/CD를 구축했었는데, 모바일 세계에는 Fastlane이라는 유명한 도구가 있다.

Fastlane 홈페이지를 들어가면

이러한 문구를 만날 수 있다. 이전에 다니던 회사의 모바일 클라이언트 개발의 배포에도 모두 fastlane을 이용했어서 단어 자체는 익숙했다.

Testflight는 iOS 앱을 마켓에 릴리즈하기 전에 테스트를 위해 임시 테스트 버전을 배포할 수 있도록 해준다.

Testflight를 통한 테스트 방식은 internal과 external이 있는데, internal은 말 그대로 내부 테스트를 하기 위해 invite only 방식으로 진행할 수 있고 external은 App Connect에서 external test를 위한 URL을 제공받을 수 있으며 이 URL이 있는 사용자는 모두 Testflight를 통해 테스트를 할 수 도 있다.

internal 테스트의 경우에는 현재 테스트 되지 않은 신규 앱 버전이 운영상태에서만 테스트 되야 하거나, 회사 내의 QA팀이 존재하는 경우에 사용할 수 있고,

external 테스트의 경우는 1인 개발자, 작은 규모의 개발사가 사용자들의 테스트를 원하는 경우에 사용할 수 있다.

이번 글은 개발이 끝나고 테스트 버전을 배포하기 위해 Fastlane을 Apple App Sotre Connect에 연결하여 자동으로 Testflight에 업로드 하는 과정을 다뤄보려고 한다.

Testflight

먼저 Testflight에 앱을 업로드 해보자. 준비물은 아래와 같다.

  • 배포 준비된 iOS 어플리케이션
  • 129000원

먼저 개발이 완료된 프로젝트의 설정부터 건드려준다.

프로젝트 설정 Targets에 버전과 빌드넘버를 지정해준다. 위처럼 하면 1.0(4)로 버전이 출시된다.

이 후엔 앱을 하나의 파일로 만들기 위해 Archive를 진행할 예정인데 상단에 앱 프로젝트명 -> Edit Scheme에서 Build Configuration을 Release로 설정해준다.

그리고 빌드를 Any iOS Device로 설정해준다.

상단에 Product 탭에 Archive를 선택해준다.

그러면 앱이 빌드될 것이다. 이 이 후에는 어디에 배포할지 선택하게 되는데 빌드가 완료되고 Distribute App을 선택하고 TestFlight & App Store를 선택해준다.

이 때 Apple Developer 계정을 등록해야 한다. 가격은 2024년 기준 1년에 129000원이다.(친구비)

Apple Developer 가입 및 결제 후 승인까지 최대 48시간이 걸리니 필요하다면 조금 미리 해두도록 하자.

https://developer.apple.com/ 이 페이지에서 우측 상단 Account를 누르고 로그인하면 등록 및 결제 절차를 밟을 수 있다.

가입 후 위 과정을 진행하면

이렇게 업로드 되었음을 확인할 수 있다.

화살표를 눌러서 App Store Connect에 들어가고 상단 사용자 및 액세스 탭에 들어가면

이렇게 상단 + 버튼을 통해 테스트에 필요한 사람을 초대할 수 있다. email과 이름, 역할을 입력하게 되는데 중요한건 상대방의 Apple Id로 사용하고 있는 email을 등록해주어야 한다. 그렇지 않으면 상대가 메일을 받았을 때 Testflight로 연결되지 않는다.

다시 상단 카테고리에서 앱을 클릭하고 프로젝트를 클릭해서 들어가준다.

그리고 TestFlight 탭을 클릭해주면

테스트 버전이 올라간 것을 확인할 수 있다. 수출 규정 관련 문서 누락 옆에 관리를 누르면 어떤 암호화 알고리즘을 사용하는지 물어보는데, 앱에서 복잡한 암호화 알고리즘을 구현한 기억이 없으므로 아무 알고리즘에 해당되지 않음을 선택했다.

좌측 사이드바에서 내부 테스팅 그룹을 설정할 수 있는데, + 버튼을 통해 테스트 그룹을 만들고, 이전에 사용자 및 액세스에서 초대를 한 사용자들을 그룹으로 묶을 수 도 있다. 그룹으로 묶어서 특정 버전에 특정 그룹에 있는 테스터만 버전 설치가 가능하도록 조정할 수도 있다.

이렇게 하면 개발된 버전 배포가 끝났다. 이제 이 과정을 fastlane으로 한방에 진행할 수 있도록 해보자

Fastlane 설치 및 실행

fastlane을 먼저 설치해야 한다. fastlane은 ruby로 작동하기 때문에 먼저 ruby를 설치해야 한다.

brew install ruby
brew install fastlane
// terminal

루비가 설치 되어 있다면 가장 위 코드는 무시해도 된다. fastlane의 설치가 끝나면 프로젝트 파일로 이동해서

fastlane init

fastlane을 초기화 코드를 실행해준다. 실행하다보면 여러 선택지가 나오는데,

여기선 2번 testflight를 선택해준다.

이 후엔 Apple Credential을 입력하도록 하는데 애플 계정의 이메일과 비밀번호를 입력해준다.

완료가 되면 프로젝트 파일내에 fastlane 폴더가 생긴다.

안에 보면 Appfile과 Fastfile이 있다. Appfile은 앱에 대한 정보를 넣고 Fastfile에는 Fastlane으로 배포하는 파이프라인 단계를 넣는다.

이 안에는 API키나 배포에 필요한 Credentials등 민감한 정보가 들어가기 때문에 해당 정보들을 .env 파일로 관리할 수 있다.

.env 파일은

API_KEY=xxxx

이런식으로 작성하고 Appfile, Fastfile에서는

api_key=ENV['API_KEY']

이렇게 불러와서 관리한다. 그리고 프로젝트의 리포지토리가 open 된 상태라면 gitignore에 이 .env파일을 제외하주는 것도 잊지 말자.

빌드 파이프라인 파일 작성

App Store Connect와 Fastlane을 인증해주어야 하는데 가장 좋은 방법이 앱 암호를 받아서 fastlane 설정파일에 입력해주는 것이다.

이곳에 접속해서, 앱 암호 탭에서 앱 암호를 생성하고 생성된 앱 암호를

.env 파일에 아래와 같이 넣어준다

FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD=abcd-efgh-asdf-asdf

이제 Fastfile과 Appfile을 아래와 같이 작성해준다.

app_identifier(ENV['APP_IDENTIFIER']) # The bundle identifier of your app
apple_id(ENV['APPLE_ID']) # Your Apple Developer Portal username
itc_team_id(ENV['ITC_TEAM_ID']) # App Store Connect Team ID
team_id(ENV['TEAM_ID']) # Developer Portal Team ID
// Appfile
desc "build app and upload to testflight"
lane :beta do
get_certificates
get_provisioning_profile
increment_build_number(
build_number: latest_testflight_build_number + 1
)
build_app(
configuration: "Debug"
)
upload_to_testflight
end
// Fastfile

이 과정은 Fastlane을 사용할 때 App Store Connect에 인증하기 위한 방법이다. 사실 인증 방식은 두 가지가 있는데, Cert, Sigh라고 불리는 이 방식과 Match 방식이 있다.

Cert, Sigh는 이렇게 파일로 인증을 하기 때문에 팀에서 한 .env파일을 공유받아서 진행하면 된다.

Match 방식은 제 3자를 이용해서 인증을 진행하는데, github private repository, s3 등 다양한 방식이 있다.

Match를 이용한 방식으로 변경

Match를 이용하기 위해서는 먼저 Credentials를 저장할 리포지토리를 만들어줘야 한다. private repository를 먼저 만들어준다.

그리고 프로젝트 폴더에서

fastlane match init

을 실행해주고 깃 옵션을 선택하자

그리고 리포지토리에 들어가면 자동으로 certificate 파일들이 생성된 것을 확인할 수 있다.

그리고 프로젝트 폴더 내에 Matchfile에는 해당 깃에 대한 정보가 있다.

Match를 하기 전에 먼저 이전에 있던 certificate 정보를 지워준다.

fastlane match nuke development
fastlane match nuke distribution

이 과정은 해당 깃 리포지토리가 다른 프로젝트의 인증에 이용되었을 경우 정보를 초기화 해준다. 이 후에

fastlane match appstore
fastlane match development

새로운 매치 파일 생성을 해준다.

새로운 컴퓨터에서 git으로 match를 시도하면 비밀번호를 묻는데, 깃허브 기준으로 우측 상단 프로필에서 Setting에서 액세스 토큰을 발급받아서 입력해주면 된다.

이렇게 하면 같이 작업하는 팀원들에게 이 리포지토리의 권한을 주면 새로운 certificate 파일을 생성해서 공유하는 수고를 없앨 수 있다.

이렇게 Signing 탭에 새로운 프로파일로 signing을 진행할 수 있게 된다.

Provisionling Profile을 match Appstore … 로 바꿔주자.

그리고 Fastfile을 아래와 같이 수정해주고, Matchfile을 아래와 같이 작성해준다.

default_platform(:ios)

platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
match(type:"appstore")
increment_build_number(xcodeproj: "EightSixteen.xcodeproj")

gym(
clean: true,
export_method: "app-store"
)

build_app(
workspace: "EightSixteen.xcworkspace",
scheme: "EightSixteen",
export_method: "app-store"
)

upload_to_testflight
end
end
// Fastfile
git_url(ENV['MATCH_GIT_REPOSITORY_NAME'])
storage_mode("git")
app_identifier([ENV['APP_IDENTIFIER']])
username(ENV['APPLE_ID'])
team_id(ENV['TEAM_ID'])
type("appstore") # The default type, can be: appstore, adhoc, enterprise or development
// Matchfile

프로젝트 폴더에서

fastlane beta

를 실행해주면 자동으로 Testflight에 새로운 버전의 앱이 업로드 된다.

결론

수동으로 Testflight에 앱을 업로드 해보고 Fastlane을 통해 자동으로 앱을 업로드 하는 방식을 또 두 가지의 인증 방식으로 시도해보았다.

조금 더 디테일 하게 가면 Fastlane을 트리거하는 방식을 github actions나 jenkins를 통할 수도 있고, 앱 실행 scheme마다 다른 프로비저닝 파일을 이용할 수도 있다.

지금까지 Fastlane을 공부하며 사용해본 결과로는 Match 방식으로 certificate와 provisioning profile인증단계를 쉽게 공유할 수 있도록 하는 방식이 업무에 가장 적절해 보인다.

--

--

peppermint100
PEPPERMINT100

기억하기 위해 또는 잊어버리기 위해 작성하는 블로그입니다.