Continuous delivery cover

안드로이드 앱을 빠르고 지속적으로 전달하기

안드로이드 개발자들을 위한 수준 있는 독립 컨퍼런스인 Droid Knights에서 “빠르고 지속적으로 전달하기: Continuous delivery for Android”이라는 주제로 강연된 세션입니다.


소개

저는 캐시슬라이드를 만든 NBT라는 회사의 아키텍쳐 오너로 전반적인 기술을 담당하고 있습니다. 캐시슬라이드 앱은 2012년 11월 첫 출시 후 대략 2주 간격으로 업데이트를 진행하고 있습니다. 최근 높은 서비스 품질을 위해 사용자의 피드백을 빠르게 반영하고, 잦은 릴리즈를 반복하는 것이 일반화되고 있습니다. 이를 위해 효율적으로 테스트와 빌드, 출시를 수행하는 것이 필수적입니다. 이번 강연에서는 fastlane과 bitrise를 이용하여 인수 테스트 자동화, 사내 베타 배포와 마켓 출시 등 릴리즈 과정을 통합하고 소규모 그룹에서도 빠르고 지속적으로 앱을 전달할 방법을 소개하고자 합니다.

짧은 시간 안에 릴리즈를 하는 것은 반복적인 일이 많습니다. 1-2주마다 테스트를 하고, 피드백을 받아서 버그를 고치는 일의 반복입니다.

Continuous + XXX?

ContinuousDelivery-dev-pipeline

소프트웨어 개발 파이프라인은 테스트와 디플로이의 경우 분기가 있을 수는 있지만 기본적으로 위와 같은 과정을 거칩니다.

ContinuousDelivery-continuous

그 과정에서 지속적인 통합(CI, Continuous Integration)나 Continuous Delivery, Continuous Deployment라는 용어를 많이 듣게 됩니다. 일반적인 개발에도 쓰이는 범위에 따라 사용되는 용어인데, 안드로이드의 경우 이를 나누는 것이 좀 어렵습니다. 하나하나 자세히 살펴보겠습니다.

Continuous Integration

지속적인 통합은 개발자가 체크인할 때마다 새로운 빌드와 단위 테스트를 수행하는 것입니다. 팀에게 요구사항에 대응하고 신속하게 문제를 해결할 수 있도록 빠른 피드백을 제공하는 것이 목적입니다. 핵심은 커밋을 하고 빌드와 단위 테스트까지만 진행해서 코드가 제대로 진행되는지 확인하는 것입니다.

이런 개발 뉴스를 더 만나보세요

Continuous Delivery

지속적인 인도는 소프트가 언제든지 릴리즈될 수 있도록 준비하는 것, 즉 레디 상태로 만드는 것입니다. 지속적인 통합에 더해서 자동화 테스트 및 배포 기능으로 안정적으로 빠르게 개발하고 릴리즈에서의 최소한의 수동 오버헤드로 제품을 전달하는 것입니다.

Continuous Deployment

지속적인 인도에 더해서 배포까지 자동으로 이뤄지는 것이 지속적인 배포입니다. 코드 변경 시 전체 파이프라인을 통해 제품이 자동으로 사용자에게 배포됩니다. 지속적인 인도는 소프트웨어가 항상 릴리즈를 준비하지만, 비즈니스 결정이 필요하며 마지막 배포 단계는 수동이지만 지속적인 배포는 업데이트 작업 버전이 자동으로 푸시된다는 것이 다릅니다.

이 과정을 안드로이드에서 생각해보면 커밋과 빌드, 유닛 테스트까지 마쳐서 이 상태를 유지할 것이고, 패키징 과정으로 모아서 배포하는 것이 안드로이드 개발의 일반적인 모습일 겁니다. 2주에 한 번 배포할 때 나갈 기능을 적당하게 모아서 인수 상태의 것일 배포하게 됩니다. 코드가 동작하도록 하는 것이 Continuous Integration의 핵심이라면 기능이 잘 되게 하는 것은 Continuous Delivery에서 담당하게 되는 것이죠. 이 사이의 화살표들은 자동화할 수 있는 부분이고, 사람은 이 사이에서 문제가 발생하면 해결하게 됩니다. 2주에 한 번씩 릴리즈가 일어난다면 직접 해야 하는 일을 최소화해야 합니다. 하지만 자동화가 모든 문제를 해결해 주는 것은 아닙니다.

CI != CI 시스템

이미 아시겠지만, CI는 CI 시스템이 아닙니다. CI 시스템은 자동화를 도와주는 Jenkins 같은 도구고, CI란 자동화 과정을 통해 점진적으로 개선하는 것에 중점을 두는 것입니다. CI, CD, CP 모두 사람이 더 적게 일하고 덜 실패할 수 있는 것에 집중한 자동화입니다. 이제부터는 캐시슬라이드에서 어떻게 CI를 쓰고 있고 앞으로 어떻게 사용하려고 하는지 설명하겠습니다.

Jenkins

많은 분이 이미 Jenkins를 알고 계시겠지만, Jenkins에는 몇 가지 작은 단점이 있습니다. UI가 예쁘지 않다는 작은 문제는 넘어가더라도, 중요한 문제는 Jenkins를 서버에 설치하고 플러그인을 설정하고 프로젝트에 설정하는 등 매우 많은 일을 사람이 직접 해줘야 한다는 점입니다. 캐시슬라이드의 경우에는 서버보다 앱 환경을 고치는 것에 더 많은 문제가 발생했는데, 예를 들어 안드로이드 버전이 새로 나온 경우 누군가가 직접 관련한 내용을 해줘야 했습니다. 서버 개발자로서는 유용하다고 생각할 수 있겠지만, 안드로이드 개발자로는 이것이 최선인가 하는 생각이 들었습니다.

fastlane

그 대안으로 찾은 것이 fastlane입니다. iOS 빌드 툴로 많은 역할을 하고 있으므로 Jenkins에서 fastlane으로 바꾸면 많은 변화가 있을까 생각했지만 그렇지는 않았습니다. deliver, snapshot 등 정말 많은 기능을 제공하고 있는데 실제로 안드로이드에 사용할 수 있는 것은 supply뿐이었습니다. 그 이유는 iOS는 좀 더 제한된 빌드 환경와 Xcode를 사용하고 있기 때문이었습니다. 따라서 Gradle이 이미 좋은 환경을 제공하고 있는 안드로이드에서는 fastlane을 잘 활용할 수는 없었습니다.

ContinuousDelivery-fastlane

어쨌든 fastlane의 supply를 사용해 봤습니다. 위와 같이 Google Play에 APK를 자동으로 올려주는 기능을 합니다. 안드로이드에서는 앱을 빨리 올릴 수는 있지만, 근본적으로 원하던 앱이 배포되는 전체적인 흐름을 만드는 것은 어려웠습니다.

circleci

그래서 클라우드에서 동작하는 CI로 바꾸기로 했습니다. 약간의 비용이 들더라도 관리하는 포인트를 낮춰서 그 시간을 보다 의 미있는 시간에 사용할 수 있다고 생각했기 때문입니다. 제일 먼저 고려했던 것은 오픈소스에서 많이 사용하는 Travis CI였는데 생각보다 비싸고 안드로이드에서 생각보다 느렸기 때문에 모바일 플랫폼에서는 많이 쓰이지 않았습니다. 그래서 다시 찾은 것이 상용으로 많이 사용되는 circleci입니다.

ContinuousDelivery-circleci

각 빌드가 독립적으로 동작하고 UI가 모던하며 다양한 서드 파티와 연동하는 웹훅을 지원하고 가격도 적절하며 Github과 연동도 유기적으로 돼서 만족스러운 도구였습니다. 가장 중요한 것은 circle.yml에서 설정 파일을 수정하는 것만으로도 적용이 가능한 점이었습니다.

실제로 circle.yml은 머신을 정의하고 GRADLE_OPTS에서 Gradle을 정의하고 java 버전도 설치하며 의존성도 정의할 수 있어 간단하게 설정할 수 있습니다. 또한, Test가 끝나기 전과 후에 무엇을 할지도 설정할 수 있어서 편리합니다. 이 파일을 Github의 root에 놓으면 됩니다. 하지만 소스 코드가 아닌 스크립트를 Github에 두기 때문에 푸시가 필요하다는 작은 단점도 있었습니다. 저희 경우에는 마스터에 릴리즈할 때 이 circleci가 돌게 했습니다. 하지만 개발용으로 빌드할 때는 상관없지만, 상용으로 빌드할 경우 필요한 keystore 파일을 다운로드 하기 위해 스크립트를 작성해야 하는 불편함이 있었습니다. 이 문제를 해결하기 위해 주로 Dropbox를 사용한다고 하더군요. 이 경우 curl로 드랍박스의 키스토어를 다운로드해서 빌드할 수 있도록 할 수 있습니다. 이런 로직을 모두 추가하면 다음과 같은 모습이 됩니다.

ContinuousDelivery-circle-config

완전히 환경 변수로 받아올 수 있도록 수정했습니다. 일반적으로 서버와 앱을 같이 쓰는 경우 유용하게 사용할 수 있었지만 KVM 에뮬레이터를 지원하지 않아서 테스트 되지 않는 문제와, CI 코드가 클라우드에 있어서 수정 시 이력이 함께 변경된다는 불편함이 있었습니다. 또한, 일반적인 환경에 적합하므로 안드로이드와 iOS의 경우 예외 상황에 대한 처리가 필요하다는 단점이 있었습니다. 결정적으로 모바일에 더 적합한 다른 도구를 발견했기 때문에 circleci를 최종적으로는 사용하지 않게 됐습니다.

Bitrise

마지막으로 소개할 Bitrise가 그것입니다. circleci만큼 유명하지는 않지만 모바일에 최적화돼 있습니다.

ContinuousDelivery-bitrise-ui

가장 눈에 띄는 장점은 매우 좋은 UI를 가졌다는 점입니다. 관리하기 편하며, 전체적인 CI에서 동작하는 워크플로우를 UI에서 처리할 수 있습니다. 실제로 build를 실행해서 slack에 넘기는 로직을 전체 흐름으로 관리할 수 있으며, 이 사이에 단계를 추가하는 경우에도 중간의 플러스 버튼을 눌러서 추가할 수 있고, 모바일에 맞는 프리셋을 잘 만들어뒀기 때문에 편합니다. 팀 단위로 사용하면 50달러의 비용이 청구되며, 개인으로 사용하면 빌드 시간과 횟수에 제한이 있어서 조심해서 사용하는 것이 좋습니다.

bitrise.yml의 경우 Github 소스가 아닌 bitrise 서버 자체에 가지게 되므로 앞서 말씀드린 문제도 해결되며, 워크플로우가 잘 나타납니다. step에서 단계를 추가할 수 있고 workflow에서 전체 흐름을 관리할 수 있으며 각 단계별 실패와 성공은 builds 탭에서 이력으로 볼 수 있습니다. 또한, 환경 변수로 존재하지만 빌드하는 사람에게 노출하고 싶지 않은 값들은 Secret Environment variables로 설정할 수 있습니다. 트리거도 설정할 수 있어서 편리하지만 앞서 말씀드린 횟수 제한을 넘지 않도록 조심해서 사용하는 것이 좋습니다. workflow에 설정되는 것은 bitrise.yml에서 정의할 수 있습니다. 다양한 workflow를 설정해서 어느 것으로 동작할지 선택할 수도 있습니다. 빌드 성공/실패 시에 설정한 메시지를 slack으로 받을 수도 있습니다.

ContinuousDelivery-crashlytics

마지막으로 추가한 것은 crashlytics 소스인데, 빌드를 할 때마다 폰에서 테스트하기 위해 fabric의 beta를 Gradle에 추가해서 빌드를 추가할 때마다 최신 앱을 올려서 내부 직원들이 테스트할 수 있도록 했습니다.

ContinuousDelivery-bitrise-merit

bitrise의 장점은 기존 circleci가 가진 장점을 모두 갖고 있고 워크플로우를 UI로 조정할 수 있어서 안드로이드나 iOS 개발자도 명시적으로 사용할 수 있다는 점입니다. 앞서 말씀드린 fastlane도 자동화 도구로 대신 사용할 수도 있고, 가장 많은 서드 파티를 웹 훅으로 연결할 수 있도록 지원하고 있고, 웬만한 iOS/안드로이드 관련 도구는 모두 프리셋으로 저장해서 세팅하기 편했습니다. 또한 docker 기반으로 circleci보다 빠른 느낌이 들었습니다.

ContinuousDelivery-ideal

최종적으로 저희가 만들고자 하는 모습은 위 그림과 같습니다. 안드로이드 스튜디오에서 체크인해서 커밋하면 Github에 저장되고, 훅을 받아서 bitrise가 일련의 과정을 거쳐서 빌드하면 디플로이가 되는 모습입니다. 하지만 테스트와 배포가 빠져 있기 때문에 이를 위해 여러 툴을 지정하고 있습니다. 유닛과 통합 테스트를 위해서는 Robolectric을 사용하고 있고 acceptance test에는 calaba.sh를 사용하고 있습니다. 배포는 fabric의 beta를 적용하고 있습니다.

CI의 목적은 자동화 자체가 아니라 자동화된 테스트와 배포로 짧은 주기의 피드백과 개선을 반복하여 빠르고 지속적인 제품, 즉 가치를 전달한다는 것입니다. 그러기 위해 갖춘 시스템을 만드는 과정을 설명했는데, 이런 것을 통해 좀 더 빠른 개발과 배포가 가능해졌습니다. 앞으로는 인수 테스트를 클라우드로 도구를 사용해서 기기 테스트를 하고, AAR과 같은 라이브러리는 bintray를 사용하려고 하고 있습니다. 클라우드가 도입되면서 서비스로 접근할 수 있는 도구들이 많아졌으므로 이런 것을 잘 활용해서 보다 핵심적인 기능 개발에 집중할 수 있는 환경을 만들 수 있다는 점을 마지막으로 말씀드리며 마칩니다.


본 영상과 글은 Droid Knights의 비디오 스폰서인 Realm에서 제공합니다. 모바일 개발자가 더 나은 앱을 더 빠르게 만들도록 돕는 Realm 모바일 데이터베이스Realm 모바일 플랫폼을 통해 핵심 로직에 집중하고 개발 효율을 높여 보세요! 공식 문서에서 단 몇 분 만에 시작할 수 있습니다. 또한 Realm 홈페이지에서는 모바일 개발자를 위한 다양한 최신 기술 뉴스와 튜토리얼을 제공하고 있으니 즐겨찾기하고 자주 들러 주세요!

다음: Realm Java를 사용하면 안드로이드 앱 모델 레이어를 효과적으로 작성할 수 있습니다.

General link arrow white

컨텐츠에 대하여

2017년 3월에 진행한 Droid Knights 행사의 강연입니다. 영상 녹화와 제작, 정리 글은 Realm에서 제공하며, 주최 측의 허가 하에 이곳에서 공유합니다.

남상균

엔비티에서 첫 화면 서비스 ‘캐시슬라이드’의 아키텍쳐 오너로 일하고 있습니다.

4 design patterns for a RESTless mobile integration »

close