Fastlane 으로 코드사이닝, 빌드, 테스트 배포 하기

yozi
15 min readAug 5, 2021

--

안녕하세요, 라이클 FE 팀 장효진 입니다.

현재 라이클 팀의 새로운 프로젝트로 react-native 기반의 앱과 react 프레임워크의 웹을 준비하고 있습니다.

react-native 프로젝트로 환경을 구축 하던 중 fastlane을 사용하면서 느낀점 및 기본적인 구성을 정리해 보았습니다.

fastlane 이란

앱개발을 진행중, 앱의 테스트 배포 혹은 스토어 배포를 해야할때

혹은 ios 같은 경우 개발을 진행 할 경우 키를 관리 해야하는 경우

버전이 변경되고, 빌드, 테스트 배포 등 모든 과정을 정리하고 쉽게 관리하여야 할때 사용 할 수 있는게 fastlane 이라고 볼 수 있습니다.

  • fastlane 설치
  • fastlane 시작하기
  • fastlane을 이용한 코드사이닝 (match)
  • fastlane을 이용한 빌드 (gym)
  • fastlane을 이용한 firebase app distribution (plugin)

fastlane 설치

fastlane을 이용한 설치방법은 ruby를 사용하여 rubygems를 이용하거나, homebrew를 이용 할 수 있는데 저는 ruby를 사용 하여 처리 하였습니다.

ios cocoapods 사용 등 다양한 이유와 github action을 이용한 ci/cd 를 구성하는데 ruby를 이용한 버전관리가 편해서 ruby를 사용 했습니다.

ruby로 진행하기전, mac에 기본적으로 설치된 시스템 ruby를 사용하면 이후 모든 권한을 sudo로 관리해야하는 등 문제가 생길 수 있습니다.

그러므로 ruby를 rbenv를 이용하여 새로 구성해 두는게 좋습니다. (https://yozi.tistory.com/entry/mac에서-ruby-재설정설치-하기-rbenv)

모든 설명은 ruby는 이미 설정된 상태로 진행하게 됩니다.

#gem 을 이용한 fastlane 설치
gem install fastlane

fastlane 시작하기 (iOS 기준)

설치된 fastlane 을 이용하여 프로젝트에 초기 환경 설정을 해야합니다. 해당 프로젝트 폴더로 이동후 init 을 우선 진행하여 줍니다.

fastlane init
fastlane init

iOS에서 프로젝트에서 진행 하였기 때문에, 해당 프로젝트가 발견 되었다는게 콘솔에서 확인이 됩니다.

자동으로 fastlane 설정 폴더를 생성 하였고, 기본적인 설정이 된 상태를 사용 할 건지 확인하게 됩니다.

testflight나 앱스토어 배포를 사용 할 예정이라면 2,3 번을 이용하여 직접 세팅하여도 되지만, 이 글에서는 4번을 선택하여 필요 한 부분을 직접 추가할 예정입니다.

4번을 선택하면 fastlane에 대한 설명 및 설정 내용이 나오며 환경 설정이 종료됩니다.

그 후/fastlane 폴더에 파일이 추가된 것을 확인 할 수 있습니다.

Appfile에는 fastlane을 이용한 기능을 사용하기 위한 정보를 담아야 하여 우선 설정을 진행하여 줍니다.

iOS의 경우는 app bundle id, apple id 등을 담아야 하며, android는 package name등을 작성 하여야 합니다.

# Appfile
app_identifier('me.unpa')
apple_id('apple@id.co.kr')team_id('TEAM_ID')

fastlane을 이용한 코드사이닝

iOS 개발에는 인증서가 필요 합니다.

이 인증서는 앱을 서명하여 배포하거나 테스트하는 등 iOS 개발에 있어서는 지속적으로 필요합니다.

인증서는 애플 개발자 사이트에서 발급하여서 관리하고, 사용자가 추가되면 추가된 사용자의 키를 또 추가 변경 한다거나 공통키를 운용하여야 한다면.. 번거로운일이 굉장히 많이 생깁니다.

예를들면 만약 발급받은 키로 개발을 하다가 갱신 혹은 새로 발급받아야하는 상황이라면 모두가 다시 키를 받거나 적용해야하는 등 많은 귀찮은 일과 관리 포인트가 생기게 됩니다.

fastlane의 match를 사용하면 이 공통적인 키 관리를 private한 repo에서 관리 할 수 있게 됩니다.

그렇게 되면, 같은 팀 개발자 끼리도 match를 이용하여 local에 저장하면서 사용하고, CI에서 빌드 하는 상황 등 키가 필요한 순간에 같은 방법으로 match를 이용하여 받아서 사용 할 수 있습니다.

해당 기능을 사용하기 위해 우선 인증서를 담을 private repo을 github에서 만들어 줍니다.

그다음 iOS프로젝트에서 fastlane match init를 입력하여 match 를 설정 을 진행합니다.

fastlane match init# 어느저장소를 사용할지 확인한다. github을 사용중 이므로 1번
fastlane match supports multiple storage modes, please select the one you want to use:
1. git
2. google_cloud
3. s3
# 만들어둔 private repo를 등록합니다
Please create a new, private git repository to store the certificates and profiles there
URL of the Git Repo: **<https://github.com/teamlycl/sample_match**>
#...# 이렇게 되면, 프로젝트에 해당 match 기본 설정은 끝이 나게 됩니다
Successfully created './fastlane/Matchfile'. You can open the file using a code editor.
You can now run `fastlane match development`, `fastlane match adhoc`, `fastlane match enterprise` and `fastlane match appstore`
On the first run for each environment it will create the provisioning profiles and
certificates for you. From then on, it will automatically import the existing profiles.

설정이 끝나고 Matchfile을 열어보면, 입력한 값이 적용되어져 있습니다.

해당 파일안에 애플 번들 아이디와, 애플 개발자 계정도 직접 추가해 주어야 합니다.

git_url("https://github.com/teamlycl/sample_match>")storage_mode("git")# type은 원하는대로 adhoc등 변경 가능 합니다
type("development")
# 여기부터 추가 후 입력
app_identifier('me.unpa')
username('test@lycl.co.kr')

이렇게 되면 기본 세팅은 끝이 나게 됩니다!

앞으로는 fastlane match 명령어로 인증서를 생성, 삭제, 갱신 등을 진행 할 수 있습니다.

만약 이미 만들어진 인증서가 있다면 인증서를 지워도 상관없습니다. 인증서중 일부는 만들수 있는 개수가 제한이 되기도 하고, match통해서 인증서를 추가해도 기존 인증서를 지우지는 않기 때문에 누적되서 쌓이기 때문에 기존껄 지우고 진행하여도 됩니다.

# nuke 명령어를 이용하여 app bundle id 구분없이 developmanet, distribution 인증서를 모두 삭제해 줍니다
fastlane match nuke development
fastlane match nuke distribution

참고: 이미 출시된 앱의 인증서를 폐기해도, 다시 같은 app id의 인증서를 받으면 되므로 걱정 하지 않아도 됩니다!

# 이제 match를 통해서 인증서를 만들 수 있습니다
fastlane match development
fastlane match adhoc

명령어를 통하면 해당 종류의 키를 발급 받을 수 있습니다.

이때, github 인증에 대한 키나 passphrase 값을 요구 할 수 있는데,

passphrase 는 만들어진 키를 암호화 하기 위한 값입니다. 해당 값을 입력후 반드시 메모 해 두어야 합니다.

만약 이후팀원이 추가되거나, 키를 받아야 하는 경우 에는 아래의 명령어로 받을 수 있습니다.

fastlane match development --readonly

명령어를 통해 로컬에 키를 입력받고, git에 키가 올라가게 되는데 해당 기능은 테스트용 기기나 사용자가 추가되어서 프로비저닝 프로파일을 새로 갱신해야 할때는 다시 시도 하여야 합니다.

fastlane을 이용한 빌드 (gym)

fastlane 에 다양한 도구중 gym 이란 도구가 있습니다.

gym 이란 iOS 프로젝트를 아카이브 시켜 줄때 사용할 수 있습니다.

android는 gradle 명령어 만으로도 충분하지만, iOS는 gym을 사용함으로써 match를 통해 키를 관리도 했고, ipa를 만들때 줄수 있는 옵션으로 xcode를 켜서 수정해야하는 여러 단계들을 더더욱 쉽게 만들어 줍니다.

# gym init 명령으로 만으로 세팅은 끝나게 됩니다
fastlane gym init
# 여기서 바로 gym 만 실행하여도 ipa파일을 추출할 수 있습니다 (올바른 키 설정이 끝났을 경우)
fastlane gym

만들어진 Gymfile 을 열어보면 사용할 scheme, sdk 등을 고를 수 있는데 빌드 단계에서 옵션으로 정할 예정이라면 작성 하지 않아도 상관 없습니다.

실제 명령어를 입력 할 수 있는 환경을 만들기 위해 Fastfile 에서 gym을 이용한 빌드를 설정 하여야 합니다.

Fastfile은 lane이란 단위로 task 들이 묶여있습니다. 이 lane에 gym을 이용한 build 로직을 추가하여 ipa파일을 만들 수 있습니다.

gym을 로컬에서 진행하는 로직은 fastlane gym_build ⇒ clear derived data ⇒ clean project ⇒ gym 으로 진행 되게 됩니다.

default_platform(:ios)platform :ios do
desc "ios build"
lane :gym_build do
# 여기서 lane 이름인 gym_build가 명령어가 됩니다(fastlane gym_build)
clear_derived_data
gym(
clean: true,
export_method: "development"
)
# gym으로 프로젝트 clean을 진행하고, 가장 기본형태로 빌드를 시도 합니다
# 이때 인증서 옵션을 development으로 했는데, 그렇다면 딱 맞는 키가 빌드 하는곳에 존재 하여야 합니다
end
end

clear_derived_data 는 iOS 개발을 진행하면 DerivedData 폴더가 생기는데, 개발중 빌드를 하는등 캐시나 인덱싱 파일이 쌓이게 됩니다. 해당파일을 지워주는게 clear_derived_data 입니다.

이렇게 설정해두고 fastlane gym_build 를 실행한다면 기본 빌드 경로에 IPA와 dSYM 파일이 같이 추출 되게 됩니다.

fastlane을 이용한 firebase app distribution (plugin)

앱 테스트 환경을 배포할 때 testflight 등 선택지가 다양하지만, 현재 라이클 팀은 firebase를 이용하여 테스트 환경을 배포하고 있습니다.

그런 환경도 fastlane을 이용하여 구축 할 수 있게 되어있는데, fastlane에는 미리 만들어진 다양한 plugin들이 있고 해당 플러그인들을 이용하여 구축 할 수 있습니다.

모든 기준은 fastlane의 설정이 이미 끝난 상태입니다.

프로젝트 폴더에서 아래의 명령어를 이용하여 fastlane에 plugin을 설치합니다.

fastlane add_plugin firebase_app_distribution

그럼 fastlane 폴더에 plugin파일 속에 설치한 내역에 추가가 되고, Fastfile에서 해당 플러그인을 사용 할 수 있게 됩니다.

firebase 테스트 환경을 사용하기 위해서는 firebase 에 프로젝트와 같은 id를 가진 앱을 우선 만들어져 있어야 합니다.

앱이 만들어 져 있다면, 필요한건 App id(firebase app id), firebase token 만 있으면 fastlane 상에서 테스트 배포를 진행 할 수 있습니다.

firebase

우선 firebase 에서 해당프로젝트의 해당 os를 선택하여 app id를 미리 챙겨 둡니다.

token은 가져올수 있는 여러 방법중 이미 설치 해둔 fastlane plugin으로 가능 하기 때문에 해당 방법을 이용해 줍니다.

아래의 명령어를 터미널에서 실행하여 토큰발급을 진행 합니다. (플러그인을 설치한 폴더에서 실행하여야 한다!)

bundle exec fastlane run firebase_app_distribution_login

그럼 무언가의 키를 입력하라는 창이 나오는데, 알려주는 아래의 주소로 접속하여 구글 계정으로 로그인 후 나오는 코드를 복사하여 입력 하여 주면 됩니다.

그 이후 나오는 refresh token을 이후 fastlane에서 사용 하여 테스트 배포를 진행 할 수 있습니다.

Fastfile 을 작성하는 순서는, 빌드 이후 firebase plugin을 넣어주면 됩니다.

그 이유는, GYM을 이용하여 빌드할 경우 그 이후 생성되어져 나온 파일을 알아서 진행해 주기 때문 입니다.

default_platform(:ios)platform :ios do
desc "ios beta app distribution"
lane :beta do
clear_derived_data
gym(
clean: true,
export_method: "development"
)

# 우선 빌드를 진행하고 firbase app distribution 을 진행 하여야한다.
# 빌드된 apk, ipa 파일을 올리기 위함이다.
firebase_app_distribution(
app: {firebase app id},
firebase_cli_token: {firebase token})
end
end

만약 다른 빌드 파일 경로를 갖고 있거나, 일부 테스터 혹은 그룹에게 테스트를 요청 할 때는 옵션을 이용하여 처리 할 수 있습니다.

....
firebase_app_distribution(
app: {firebase app id},
firebase_cli_token: {firebase token},
testers: {테스터의 이메일들},
groups: {미리 firebase에 설정 해둔 groups 이름},
ipa_path: {설정과 다른 ipa파일 경로}
)
...

옵션을 필요한 부분에 맞게 사용하여 넣어 주면 됩니다.

왜 우리는 fastlane을 이용하여 빌드를 하고 테스트 배포를 진행하고 있는걸까?

보통 앱을 만들게 되면 회사의 스타일에 맞게 빌드, 배포를 진행 하고 있을것이고 우리도 우리가 생각한 괜찮다고 생각하는 환경에 맞게 진행 하고 있습니다.

신규 프로젝트는 react-native로 작업중에 있는데, 그중에서 fastlane을 선택하게 된 이유는 모든 과정을 비슷한 과정으로 묶어내기 위함도 있습니다.

gym이나, 명령어를 이용해서 빌드를 하는 과정 자체는 android, iOS 둘다 같은데 이 로직을 이용해서 빌드 할때 주는 옵션도 비슷하고 이때 빌드 후에 나오는 결과에 따라서 firebase app distribution에 보내는 과정도 모두 비슷하게 흘러 가기 때문에 누가 작업을 하여도 서로 관계에 대해서 이해하기 쉽고 관리 포인트가 많이 줄어들 수 있다고 판단 했습니다.

그리고 무엇보다 fastlane은 iOS에서 힘을 발휘한다고 느꼈습니다.

어느 환경 보다 귀찮고 포기하기 쉬운 키 관리 부분을 fastlane으로 관리함으로 팀 내 개발자 간의 관리 포인트가 줄어들고, iOS앱은 테스트 배포를 진행 하면서도 코드사이닝을 해야하기 때문에 (adhoc으로 진행 중) 이때 provisioning profile에 등록된 기기와 사용자만 해당 앱 테스트를 할 수 있습니다.

fastlane의 match를 통해서 인증서를 관리하기 때문에 신규 사용자가 추가 되더라도 apple 개발자 페이지에 신규 사용자 등록만 해주고, fastlane 커맨드로 빌드만 해주면 provisioning profile은 자동적으로 관리가 됩니다.

만약 ci/cd 가 구성 되어져 있다면, 해당 워크플로우를 재시작만 해주면 된다는 뜻이 되게 됩니다.

게다가 iOS 심사에는 기기에 맞는 스크린샷도 제출하여야 하는데, 스크린샷을 자동으로 생성하고 스토어 배포 까지도 fastlane으로 깔끔하게 처리 할 수 있습니다.

모든 환경과 과정을 비슷하게 묶어내는것,

react-native 프로젝트를 이용하면서 자칫 부족 할 수 있는 native 관리 포인트를 조금이라도 줄이는것 등

다양한 환경에 무난하게 잘 묶이고, 라이클 팀에서는 배포 관련된 ci/cd를 구성하여 사용중 인데, 잘 사용하면 깔끔한 로직과 보기편한 자동화된 순차적인 흐름을 구성 할 수 있다고 생각합니다.

--

--