[Video Summary]카카오 모빌리티 팀의 안드로이드 CI 개선 사례

[Video Summary]카카오 모빌리티 팀의 안드로이드 CI 개선 사례

안드로이드 개발 환경 개선을 위한 노력들: Jenkins CI 파이프라인과 리모트 빌드 소개 / if(kakao)2022

안드로이드 분야의 CI/CD 포스팅 을 작성하기 위해 학습한 내용을 따로 요약하기 위한 포스팅입니다.

목차

  • Branch 안정성을 검증해주는 Jenkins CI 구축과정

  • 빠른 빌드를 도와주는 remote build

  • 기존 PR을 통해 리뷰 후 기능을 합치는 방식 사용. 하지만 한계 존재.

Branch 안정성을 검증해주는 Jenkins CI 구축과정

Compile, Test, Lint 에서 생기는 문제를 코드 리뷰로 검증하기 어려웠음.

문제가 된 코드 찾기, 누가 작성했는지, 어느 팀 담당인지, 해당팀에 수정요청, 수정 요청이 완료된 이후 작용 진행 과 같은 번거로운 절차 각각이 작업을 지연시키는 병목이 됨.

여러 도구 중 파이프라인 커스텀이 쉽고 대중적으로 사용하는 도구인 Jenkins를 검토하였고 사내 망에서 사용하기 적합한 툴임을 확인.

안드로이드 빌드는 느린 편이라 많은 리소스를 사용하도록 해야 했음.

DevOps 팀을 통해 클라우드 환경으로 구성된 Jenkins 를 세팅받아 쿠버네티스 기반에서 컨테이너 단위로 충분한 리소스를 받아 CI 에서 사용할 수 있게 됨.

이후 안드로이드 팀에 맞게 파이프 구성.

CI 가 또 다른 지연 병목이 되지 않게 하는 것이 중요했음

파이프 라인을 크게 2개로 나눔.

첫 번째, PR 시 사용되는 PR 파이프라인.

빠르게 검사할 수 있는 PR syntax 체크와, debug variant 의 컴파일과 테스트 태스크를 실행함.

그 결좌에 따라 PR 의 상태를 갱신했고 이 과정에서 문제가 생기면 구체적으로 알 수 있는 코멘트를 남김.

두 번째는 확인이 오래 걸리거나 자주 발생하지 않는 문제들을 검사하는 Push 파이프라인.

PR 이 머지되어 업스트립에 브랜치 갱신이 생기면 동작함

PR 파이프 라인에서 했던 작업을 머지된 브랜치에서 한 번 더 수행

오래 걸리는 release 컴파일과 lint 등의 작업을 수행

이 단계에서 추가 문제가 발생하면, 슬랙으로 마지막에 커밋한 인원을 태그해 빠르게 문제를 수정할 수 있도록 함.

빌드는 매번 새로운 컨테이너 환경에서 실행됨

따라서 캐시도 초기화되고 플러그인이나 디펜던시 다운이 매번 생김

파이프라인의 빌드 속도를 높이고자

빌드가 성공하면 캐시 정보를 Remote Cache Server 에 공유해 다음 CI 빌드와 로컬 빌드에서 재활용 할 수 있도록 함

또 빌드 수행시 매번 다운받던 각종 의존성들을 변경이 있을 때만 받도록 의존성이 세팅된 이미지를 만들어 해당 컨테이너에서 빠르게 빌드할 수 있도록 함.

이런 노력들 덕에 CI 에서 빠르면서 안전에하게 코드 통합을 할 수 있었고

Stable 브랜치에서 문제가 생기는 경우가 눈에 띄게 줄었다

빠른 빌드를 도와주는 remote build

안드로이드 개발의 가장 큰 병목 중 하나는 매우 많은 리소스를 사용함에도 매우 느린 빌드 속도

클린(풀) 빌드를 하면 많게는 16분, 증분 빌드를 하더라도 1분 이상 소요.

인간의 두뇌의 단기기억은 30초 정도를 기억함

업무를 하면서 빌드를 굉장히 자주하게 되는데 매번 이런 빌드 시간을 기다리는 것은 업무를 어렵게 만듬

안드로이드 팀에선 이미 빌드 시간을 개선하기 위해 잘 알려진 방법들을 사용중

모듈 분리, gradle 최적화 설정, CI 에서 빌드 캐시를 리모트 저장소로 공유

또 다른 개선 방식을 찾아보다. 리모트 빌드 방식을 찾게 되었다

이를 코틀린으로 구현한 미라클 프로젝트를 찾게 되었음.

미라클 프로젝트의 리모트 동작 방식

개발자의 맥북에서 gradle 스크립트가 실행되면 미라클이 스크립트를 후킹해 트리거 됨

리모트 빌드 서버에 접속해 소스코드를 업로드하고 후킹했던 스크립트를 고성능 장비에서 그대로 실행시킴

그 후 빌드 결과물만 다시 맥북으로 다운 받아 빌드를 끝내게 됨

파일 업로드와 다운로드 과정은 SSH 기반의 변경된 파일만 동기화하는 Rsync 를 이용해 효율적으로 수행

스크립트를 통해 모든 과정이 진행되기 때문에 한 번 세팅되면 이용하는 사람은 로컬인지 리모트인지 전혀 신경쓰지 않고도 심리스하게 사용할 수 있음

안드로이드 스튜디오를 사용하던 CLI 도구를 사용하던 관계 없음

맥미니를 리모트 서버로 환경을 세팅함

빌드 과정에서 사내 레포로 관리중인 여러 의존성에 접근해야 했는데 mac mini 로는 어려웠고 우회가 필요 했음

이후 DevOps 팀의 지원을 받아 환경 세팅을 개발자도구로 지원 받을 수 있도록 함

이후 개선 정도를 파악하려고 빌드시간 수집 서버를 만들어 실제 빌드 시간을 측정함

가장 걱정되었던 부분은 Rsync 로 소스코드와 빌드 결과를 업로드하고 다운로드 받는 작업

변경된 내용과 필요한 결과물 만을 받았기 때문에 각각 평균 1~11초 정도로 빠른 속도를 보여줌

빌드 시간 역시 30코어 cpu 와 30gb 램을 가진 고성능 pod 에서 수행했기 때문에 평균 45초로 매우빠른 속도를 보여줌

약 69% 의 시간이 줄어듬

무엇보다 리모트에서 사용되는 30GB 만큼의 메모리를 로컬에서 절약할 수 있어서 빌드 과정중 FIgma 나 다른 도구를 사용함에 따라 버벅이던 문제, 발열과 팬소리로부터 벗어날 수 있었음

아쉬운 점

디펜턴시를 받아오기 위한 nexus 프록시 레포지토리를 설정할 때 경로명에 따라 오류가 발생하는 버그가 있엇고

미라클로 리모트 빌드를 수행할 때 테스트 코드 묶음을 못 찾거나 한글이 깨지는 문제, 컴포즈 프리뷰가 동작하지 않는 버그가 생겼었음

Nexus, Miracle 모두 오픈소스여서 컨트리뷰트 하여 해결

정리하면

Jenkins CI 를 통해 브랜치의 안정성을 확보하고

확장 가능한 클라우드 환경의 리모트 빌드로 69% 의 빌드 시간을 줄여 개발 병목을 매우 크게 줄일 수 있었음

향후 계획

로컬에서 많은 리소스를 잡아먹고 있는 안드로이드 에뮬 또한 리모트 머신에서 동작시키고 원격으로 화면만 공유 받을 수 있는 원격 에뮬을 구상 중

지금은 리모트 빌드 서버가 업무 시간 내내 구동되고 있는데 빌드 시에만 리소스를 사용하고 그 외에는 리소스를 반납해 비용을 최적화 하도록 유용하게 구성하는 걸 고려하고 있다.