Fastlane. 시작한 김에 PR까지.

최근 iOS 앱 개발을 맡게 되었다. 아마 iOS 앱 개발을 시작할 때 누구나 그러했겠지만 code signing과 관련된 부분이 지나치게 복잡하다고 느꼈다.

처음에는 인증서와 프로비저닝 프로파일(provisioning profile) 자체를 이해해야했다. 인증서는 iOS 개발이라고 해서 딱히 특별할 게 없었는데 프로비저닝 프로파일이 뭔지는 자료를 좀 봐야했다. 프로비저닝 프로파일은 인증서의 공개키, 그리고 해당 앱의 설치가 허용된 기기목록에 관한 정보를 담고 있는데, ipa 파일에 포함되어 앱이 설치될 때 이 기기가 프로비저닝 프로파일에 포함되어있는지, 코드가 올바른 인증서로 서명된 것인지를 확인하는 데에 사용된다. (앱스토어에 배포될 때는 앱스토어 인증서, 프로파일로 교체되어 배포된다.)

문제는 인증서와 프로비저닝 프로파일에는 만료기한이 있다는 점이었다. 인증서는 개발자마다, 프로비저닝 프로파일은 앱마다 달라서 만료되는 기간이 제각각이었다. 여러 사람이 여러 앱을 유지보수하다보면 인증서와 프로비저닝 프로파일 만료 시점이 수시로 돌아오는데 이걸 대응하면서 낭비되는 시간이 너무 많았다. 이게 자주하는 작업도 아니다보니 할 때마다 새롭고, 이게 뭔지 잘 모르는 상태에서는 Xcode가 경고창 띄울 때 그냥 ‘Reset’버튼을 눌러버리는 바람에 다른 개발자들이 개인키를 다시 다 받아야하는 상황이 발생한다. 밤늦게 업데이트 코드를 마무리하고 이제 배포용 빌드를 하려는데 12시가 지나면서 하필 딱 그 날이 인증서 만료일이 되면 스트레스가 심하다. 작업 자체가 어렵고 복잡한 건 아니지만 어쨌든 신경이 쓰이고 손이 간다는 것 자체가 스트레스였다.

fastlane match

이런 말도 안되게 불편한 상황이라면 누군가 해결책을 만들어놨을 것이라는 생각이 들어서 찾아보니 fastlane match라는 게 있었다. 사실 fastlane이라는 툴은 예전에 잠깐 보기는 했었다. (iOS 개발 관련 자동화 툴로는 가장 유명하니…) 그 때는 cert와 sigh라는 툴로 관리하는 방식이었던 것 같은데 match라는 툴이 새로 나온 것 같았다.

동작 방식은 개발자들이 공유하는 계정을 하나 만들고, 그 계정의 인증서와 개인키를 암호화해서 git repo에 보관했다가 필요할 때 가져다쓰고 만료되면 업데이트하는 식이다.

처음에는 내가 작업하는 프로젝트에만 적용을 해보려고 했는데, 내 인증서가 다른 프로젝트의 프로비저닝 프로파일에도 들어가있고, 서로 엮여있는 부분이 많다보니 다른 개발자들의 양해를 구하는 메일을 몇 번 썼다. 이러이러한 툴을 시험삼아 적용해보는 중이고 어떠어떠한 작업을 하려고 하는데 발생할 수 있는 문제가 어떤 게 있고 혹시라도 문제가 생기면 알려달라고 했다. 특히 기존 프로비저닝 프로파일을 전부 nuke하는 작업을 어떻게든 피해보려고 수작업으로 암/복호화도 해봤지만 너무 효율이 떨어져서 그냥 다른 개발자들에게 양해를 구하고 진행하기로 했다. 최악의 경우라고 해봤자 실제 배포된 앱의 서비스에는 지장이 없고 좀 번거로운 수작업 한 번 하는게 전부인데, 수동 암/복호화로 테스트하기에는 배보다 배꼽이 더 크다는 판단이었다.

우려와는 달리 생각보다 매끄럽게 처리되었다. 뭔가 사고가 터져서 수습을 해야한다거나 하는 상황은 발생하지 않았다. 문제가 생기면 걱정없이 nuke하면 된다. match가 알아서 다시 다 만들어주고 알아서 공유된다. 그럭저럭 잘 동작하는 것 같아서 전사적으로 도입하기 위한 준비를 시작했다.

확대 적용

사내에 새로운 무언가를 도입하려면 저항에 부딪히게 마련이다. 당장 수정해야하는 코드들만 생각하기도 바쁜데, 그런 것과는 직접적으로 연관이 없는 것들을 새롭게 익히는 것도 스트레스이기 때문에 설득과 조율이 필요하다. 사실 예전에 fastlane을 통한 빌드와 배포를 다른 팀으로 전파하려는 시도를 누군가 했었지만, 그 효용과 필요성을 다른 구성원들에게 인지시키는 데에 실패하면서 도입이 무산된 적이 있었기 때문에 이부분에 좀 더 공을 들이기로 했다. 허들을 최소화하기 위해 사내에서 공통적으로 쓸 수 있을만한 일종의 표준 환경을 만들고 이러한 환경을 쉽게 따라서 구성할 수 있는 문서도 만들었다. 루비 설치(rbenv)부터 fastlane 설치 및 환경 설정, 프로젝트별 설정(Matchfile 작성 등)에 관한 문서를 만들었다.

그리고 자동화의 이점을 최대한 살리기 위해 Vault도 활용했다. ‘문서 내용만 한 번 따라하고 나면 이후부터는 스크립트만으로 모두 해결’이 가능하도록 하는 것이 목표였기 때문에 이는 중요한 부분이었다. vault는 그걸 처음 도입했던 팀에서 인증 설정과 사용예시를 정리한 문서를 상세히 작성해둔 것이 있어서 한결 수월했다. 따로 누군가에게서 인증이나 설정 정보를 요청할 필요 없이 혼자서 문서에 있는 코드 스니펫을 그대로 복붙하면서 실행하기만 하면 설정이 완료되도록 구성했다.

여기까지 설명한 내용들을 슬라이드로 정리해서 발표하는 것으로 전사도입을 완료했다. 기존 방식의 문제점, fastlane match를 쓰면 편리해지는 부분들과 함께, 새로운 툴을 사용할 때 예상되는 불안한 점들(예외적인 상황들)을 미리 파악해서 대응방법을 설명한 것이 도움이 되었던 것 같다.

Contribution

fastlane을 도입하고 얼마 지나지 않아 다른 프로젝트에서 10,000개 가량의 인앱결제 항목을 비활성화하는 작업을 도와달라는 요청이 왔다.  iTunes Connect에서 수작업으로 했다가는 수개월이 걸릴 일이다. 따라서 자동화를 해야하는데, 이를 위한 툴이 fastlane spaceship이다. spaceship으로 iTunes Connect에 로그인해서 특정 앱의 인앱결제 항목을 불러오고 상태를 확인하는 루비 스크립트를 작성했다. 그런데  spaceship이 제대로 처리하지 못하는 케이스를 발견했다. 코드를 분석해보니 인앱결제 항목의 상태를 나타내는 문자열들 중에 빠진 것이 몇 개 있었고 어렵지 않게 수정할 수 있을 것 같았다. 수정 후 테스트해보니 잘 동작하는 것 같아서 Pull Request까지 시도해보기로 했다.

잠깐 새어나가는 이야기지만 이 작업을 하면서 루비도 나름 장점이 많은 언어라는 생각이 들었다. 우리나라에서는 완전히 파이썬에 밀린 상황이어서 좀 안타깝다는 생각도 들고…

다시 돌아와서, PR을 보내기 전에 이미 관련 이슈가 제기되어 진행중인 작업이 있는지 검색해봤다. 다행히(?) 이미 등록된 이슈들 중에는 이것과 관련된 것이 없었다. 그래서 이슈를 만들고 다음 날 PR을 올렸다.

일주일 후에 PR approved ㅋ
2.56.0 버전에 포함되어 배포되었다.

spaceship은 웹브라우저를 에뮬레이션하는 방식으로 동작하는 것이어서(iTunes Connect가 따로 API를 제공하거나 하지 않기 때문에) 속도가 매우 느렸다. 처리할 인앱항목 id들을 추출한 후 병렬로 처리하려고 보니 루비 프로세스 개수에 제한도 있고, 같은 id를 여러 프로세스가 가져가지 않도록 동기화 처리를 해야하는데(최악의 경우 n개의 프로세스가 n * 10,000 번의 처리를 하게 될텐데 이렇게 되면 병렬화를 안하느니만 못하다) 이런 것까지 하기에는 무리다 싶어 beanstalk queue에다 집어넣고 EC2 인스턴스들을 활용해서 병렬로 처리했다. 인스턴스 1개로 4시간 걸리는 작업이라면, 인스턴스 4개로 1시간을 써도 요금은 같다. 같은 돈이면 시간을 줄이는 편이 당연히 더 좋다. AWS를 좀 능숙하게 다룰 줄 알았다면 한 1000개 정도 확 띄웠다가 작업 끝나면 소멸시키는 식으로 했어도 재미있었을 것 같은데…

아무튼 대략 2~3개월사이에 새로운 툴 적용도 해보고 vault도 연동하고 문서화도 하고 다른 개발자들과 공유도 하고 코드 분석도 하고  contribution도 해보고 하느라 재미있었다.

Leave a Comment

Your email address will not be published.