안드로이드 릴리즈 버그 없이 3.5주 cut 하는 법

안드로이드 릴리즈 버그 없이 3.5주 cut 하는 법
Photo by Tim Foster / Unsplash

안녕하세요, 열정에기름붓기 cto 새발입니다. (우리 팀은 2글자 닉네임으로 서로를 부릅니다.)

블랙스완 안드로이드 첫 버전이 릴리즈 되었습니다. 개발 기간은 3.5주 밖에 되지 않습니다. 어떤 방식으로 프로젝트에 접근하고, 협업하고, 개발했는지 한번 적어보려 합니다.


코로나로 인해 크리에이터클럽이 문을 닫고, 팀원들이 떠나가는 와중에 남아있는 팀원들은 새로운 서비스를 준비했습니다.
새로운 비전을 찾고, 피벗할 서비스를 구체화 하며, 디자인과 개발을 밀고 나갔습니다. 4개월만에 ios 버전이 세상에 나왔고, 2개월 동안 앱스토어 심사를 반려 당하며 서비스의 방향성과 포지션, 핵심 가치를 견고하게 다졌습니다.
그리고 2021년 9월 20일, 드디어 심사가 통과됐고, 서비스가 굴러가기 시작했습니다.

개발팀은 저 포함 총 3명이었는데, 출시 직후 ios 개발자분이 퇴사 하셔서 2명 뿐인 개발 듀오가 되었습니다. 우리는 서비스 출시 후 밀려 들어오는 유지보수와 리디자인 작업, 백오피스 개발에 시간을 쏟았습니다.
힘든 시간이었습니다.

날씨가 조금씩 추워질 무렵, 팀에서는 안드로이드 버전에 대한 필요성을 점점 크게 느끼고 있었습니다.
개발 리소스가 부족하단 걸 아는 팀원들은 외주 개발사를 고려했지만, 코드 퀄리티와 제품 퀄리티 측면 때문에 망설였습니다.
사실 안드로이드 버전 개발을 우선순위 1순위로 찍고 달릴 수 있었습니다만 최소 4주에서 6주 정도의 시간을 온전히 안드로이드 개발에 쏟기엔 대표와 PO 입장에서 불안한 마음이 더 컸던 것 같습니다.

저는 11월 1주차 쯤인가 개발을 하다 갑자기 불안감에 휩쌓였습니다.
팀에 안드로이드 버전이 꼭 필요해 보이는데, 있으면 너무나 좋을 거라는 걸 모두가 아는데 선뜻 결정을 내리지 못하는 그런 분위기.
개발 리소스가 부족하단 게 문제의 원인인지 아니면 핑계인지, 정말 단순하게 불안감 때문에 우선순위를 찍고 달리지 못하는 건지 아리송 했었습니다. 이건 굳이 길게 끌며 고민할 문제가 아닌 것 같았습니다.

새로운 액션이 필요했고, 이는 개발팀이 이끌고 싶었습니다.
주말에 스타벅스에서 간단하게 생각을 정리했습니다.
그때 노션에 정리했던 것은 -

  • 안드로이드 버전이 꼭 필요한데, 모든 걸 잘하기 위해 필요한 것은 무엇인가
  • 팀원(대표, PO) 설득 / 마음 케어하기 (일정과 리소스에 대한 불안감 최소화)
  • 기존 개발 업무 일정 문제 없이 진행하기
  • 안드로이드 개발에 대한 불확실성 제거
  • 삽질, 학습, 테스트, 개발 환경
  • 개발 잘하기
  • 개발팀 동기부여와 컨디션 관리하기

이것들을 효과적으로 실현하기 위해 했던 고민들과 액션을 공유해보고자 합니다.


1. 작게 시작하기

단순하게 “안드로이드 개발 빨리 잘 해줄게!”라고 할 수 있었음에도 그렇지 못한 이유는 개발팀 조차 일정과 일감 예측에 대해 확신이 없어서 였습니다. 기존 개발 업무도 있고 자칫 큰소리 쳤다가 일정 관리에 실패하면 개발팀 신뢰도와 분위기에 그닥 좋지 않기 때문입니다. 개발팀 리드로서 부담감도 느껴졌구요.

그래서 당장은 개인 프로젝트로 시작했습니다. 아주 가볍게. 팀원들에게도 알리지 않았습니다. 책임과 부담감을 느끼고 싶지 않았습니다.
평일에 꾸준히 저녁 시간을 내 취미 삼아 진행했습니다. 가입 퍼널까지 구현되면 팀에 공유하고 안드로이드 개발 하자고 설득하려 했습니다.
이 기간 동안 저는 느긋하게 즐겼습니다. 개발을 해도 그만 안해도 그만이고, 코딩 안하고 그동안 놓쳤던 문서를 읽을 때도 있었고, 삼천포로 빠질 때도 있었습니다.

그럼에도 한가지 규칙은 지키려고 했는데 “주 단위 목표로 뒀던 정량적 시간은 꼭 채우자” 였습니다.

2. 측정하기

대표와 PO은 일정과 개발 리소스에 대해 불안감을 가지고 있었습니다. 종종 회의때마다 “다 하려다가 이도저도 아니게 되면 어쩌지”라는 말을 했었습니다. 저는 이게 막연함에서 오는 불안감이라 생각했습니다.

저는 정량적인 개발 시간을 측정해 대표와 PO를 설득하려 했습니다. 그러면서 저 스스로도 확신을 가질 수도 있구요.
앞서 말한 주 단위 목표였던 “정량적 시간 채우기”는 이 시간 측정을 위함입니다.

저는 일주일에 최소 12시간을 채우려고 했고, 안드로이드 코드 베이스 + 가입 퍼널 구현까지 총 4주가 걸렸습니다. 정확한 시간으로는 51시간 정도 소요했습니다. (시간 측정엔 https://toggl.com/track/을 사용했습니다.)
이미 안드로이드 개발 경험이 있던 지라 러닝커브는 다소 적었고, 대신 코드 베이스 잡는 것과 최신 안드로이드 트렌드를 읽고 학습하는 데 시간을 쏟았던 것 같습니다.

한명이서 워킹타임으로 열심히 1주일(50시간 내외) 개발하면 가입 퍼널이 나오는데, 이정도면 2명이서 안전하게 4주면 되지 않을까?
스스로 확신에 차서 팀원들에게 공유했고, 설득 됐습니다.

살짝 예상에서 벗어난 게 있다면 정량적인 측정 값으로 예측하고 증명하기 보단 제 스스로 가진 확신에 팀원들이 반응했습니다.
검증보다 먼저 앞장서 나가면 해결되는 문제였나 싶었습니다.

어쨌든 드디어 안드로이드 개발 진행이 결정이 났습니다. 이때가 딱 12월 초였네요.

3. 사용한 스택

개인 프로젝트로 진행할 땐 손에 익숙한 kotlin과 rx로 개발했습니다. 프로젝트 진행이 결정된 후 data binding과 kotlin coroutine / flow에 대해 찾아봤었는데 절대적 코드량을 줄이는 데 도움이 돼보였습니다. 때문에 기존 만들어놨던 코드 베이스를 버리고 새로운 베이스를 깔았습니다.

현재 개발팀은 백엔드를 kotlin + spring으로, 백오피스를 kotlin/js + react + antd로 구현 했습니다. 개발팀은 kotlin으로 통합했을 때 따라오는 장점을 톡톡히 느꼈습니다. (팀원의 소감)

때문에 안드로이드도 최대한 kotlin 환경에 붙어 개발하기로 했습니다.

koin으로 의존성 주입을 받고, ktor와 kotlinx-serialization으로 네트워크 레이어를, kotlinx-coroutine과 kotlin flows로 비지니스 로직을 구현했습니다.
kotlin multiplatform에도 욕심이 생겨 ios/android/web 모두 네트워크 레이어를 통합시키려 했지만 아직은 시기상조라 테스트만 해보다가 끝났습니다.

여담이지만 개발팀이 최대한 kotlin에 붙어서 스택을 구성한 이유는 언젠가 안정화될 수도 있는 kotlin multiplatform에 올라타기 위해, 개발팀원들의 개발 환경과 언어를 통합하기 위해서 입니다.

4. 깔끔한 베이스를 깔자

코드베이스

코드 베이스는 중요합니다. 잘 깔려진 코드 베이스는 좋은 예제가 되고 규칙을 가이드 해줍니다. 이는 개발 속도에 직접적인 영향을 주기 때문에, 프로젝트 초기엔 더욱 중요하다 생각합니다.

개발 시작 이후 1주일 정도는 코드 베이스에 시간을 많이 쏟았던 것 같습니다. data binding과 kotlin coroutine / flows를 처음 써보기 때문에 이리저리 실험을 하며 규칙을 만들어 나갔습니다. 모든 Fragment들이 상속하는 BaseFragment는 어떤 모양이어야 하는지, 반복하는 작업(예: 새로운 fragment / view model 만들기)에 코드를 한 줄 이라도 덜 칠 수 있는 방법은 무엇인지, callback과 suspend 중에서 어떤 걸 더 선호해야 할 지, exception은 어떻게 핸들링해야 할지 등.

새로운 코드 베이스와 가입 퍼널을 재구현하며 이정도면 됐다 싶을 정도로 예제와 규칙을 만들었습니다. 충분히 시간을 들이고 신경을 쏟았습니다.

CI/CD

마음 같아선 viewModel만이라도 unit test를 진행하고 싶었지만, 개발 시간이 부족해 메인 화면 viewModel만 unit test를 작성했고, CI에 연동해놓았습니다. 출시 이후 시간이 될 때 언제든지 TDD를 할 수 있도록, 혹은 쉽게 test를 작성할 수 있도록 환경을 만들어놓았습니다. 마지막으로 시간을 조금 더 내 CD와 firebase app distribution을 통한 테스트 환경까지 구축해놓았습니다.

5. 잘 개발하기

개발 일정은 QA 포함 총 4.5주였습니다. 우선순위를 비집고 들어오는 일감 처리를 위한 0.5주, 혹시모를 위험 요소를 대비한 버퍼 0.5주를 제외하고 남은 3.5주를 총 개발 일정으로 잡았습니다. (원래는 이렇게 빡빡하게 일정을 잡으면 안되지만, 상황이 상황인 만큼..)

개발팀은 어떻게 하면 높은 퀄리티의 프로덕트를 3.5주 안에 개발할 수 있을까 고민했습니다.

나름의 전략을 세웠고, 개발을 시작했습니다.

  1. 위험 요소는 미리 앞당겨 해결하자.
  2. 개발팀이 한번도 해보지 못한 작업을 먼저 하자. (예: 인앱 결제)
  3. PO와 협의해 최소 기능을 정한 후, 미리 스토어에 릴리즈 하자.
  4. data binding / kotlin coroutine & flows에 대한 경험이 없으니 빨리 로직 연결을 해보자.
  5. 핵심 기능 / 기타 기능으로 나누어 개발을 진행해 각 개발자 간 작업 흐름이 겹치지 않도록 하자.
  6. 릴리즈 시점에 꼭 필요한 기능이 아니라고 판단되면 과감하게 제외하자.
  7. 먼저 뷰를 모두 구현한 뒤에 로직 구현을 시작하자.
  8. 자주 테스트하자.

1주차엔 핵심 / 기타 기능으로 카테고리를 나눠 각 개발자가 뷰를 그리기 시작했습니다. 저는 가입 퍼널 뷰를 그렸는데, 이때 코드 베이스 작업과 함께 최소한의 로직 연결을 했습니다. data binding 과 kotlin flows & coroutine에 대한 학습이 이때 이루어졌습니다. 결과물로 튼튼한 코드 베이스와 CI/CD, 간략한 test code, 약 80%의 뷰가 구현됐습니다. 팀원들은 실제 기기에서 개발팀이 구현한 뷰를 볼 수 있었습니다.

2주차엔 PO와 이야기해 첫 릴리즈 일정을 앞당겼습니다. 가입 퍼널이 구현된 시점에 조만간 서비스가 오픈된다는 페이지와 함께 스토어에 정식 릴리즈 하기로 했습니다. 가입 퍼널 로직 구현과 함께 안드로이드 버전 릴리즈로 인한 백엔드/백오피스 사이드 이팩트 처리, 정식 릴리즈 준비를 진행했습니다. 결과물로 가입 퍼널까지 구현된 안드로이드 앱이 스토어에 릴리즈 되었으며, 릴리즈 당일부터 조금씩 안드로이드 유저를 받기 시작했습니다.

3주차엔 PO와 함께 2번째 최소 기능에 대해 정의했습니다. 서비스 핵심 기능이라고 생각되는 것 까지만 구현 후 2번째 릴리즈를 진행하기로 했습니다. 가입 쪽 기능은 이미 릴리즈가 되어 굴러가고 있었기 때문에 개발팀은 메인 기능에만 집중할 수 있었습니다. 앞서 세운 전략대로 개발팀은 지금까지 경험해보지 못했던 기능부터 구현했습니다. 저는 스토어 / 인앱 결제 연동을 먼저 했습니다. 그 후 핵심 기능을 구현하기 시작했는데, 개발 초기에 신경써서 쌓아놨던 코드 베이스와 CI/CD 환경이 이때 빛을 발했습니다. 덕분에 코드를 국수가락 뽑듯 쭉쭉 뽑아냈고, 버그와 디버깅 시간은 적었습니다. 결과물로 앞서 정의했던 최소 기능보다 더 많은 기능을 더 추가해 릴리즈를 성공적으로 진행했습니다.

마지막 주차엔 남은 기타 기능들을 구현하며 에러 로깅과 메일로 들어오는 CS를 처리하는 시간을 가졌습니다.

몸과 머리가 좀 힘들었지만, 결과적으로 개발팀은 안전하게 릴리즈 했고, 우리 팀은 잘 굴러가는 안드로이드 앱을 얻었으며, 몇가지 자잘한 버그를 제외하면 앱에 크리티컬한 문제는 없었습니다.


치열했던 기간

예쁜 burn up chart

버그가 없나봐요


6. 개인적인 노력

프로젝트를 성공적으로 마치고 싶어 개인적으로 했던 노력들 입니다.

매일 테스트

일찍이 CI/CD를 구축해 테스트가 용이했습니다. 그래서 매일 출근할 때 지하철에서 앱을 테스트해보고는 했습니다. 문제가 발견되면 출근 직후에 고치고 개발을 진행했습니다. 누군가는 테스트를 해줘야 하는데, 개발에 집중하다 보면 놓치기 쉽상입니다. 덕분에 릴리즈 직전에 자잘한 버그를 수정 하느라 시간을 빼지 않고 온전히 릴리즈에만 집중할 수 있었습니다.

규칙적인 생활

컨디션을 유지하려 최대한 같은 시간에 자고 일어났습니다. 마음이 급해 하루 밤을 새버리면 2~3일 동안 후유증이 남기 때문에, 밤새는 건 최대한 피하고 릴리즈 직전에만 늦게 잤습니다.

집중이 안될 땐 30분 단위의 뽀모도로를 사용했습니다.

밥은 제때 제때 먹었습니다. 회의/개발 시간을 제외하면 머리를 비울 수 있는 시간이 점심/저녁 시간 밖에 없었는데, 이때 같이 밥먹는 팀원들에게 하소연도 하고 힘든 것도 티를 냈습니다. 팀원들이 응원해주면 나름 마음의 위안이 되더군요.

시간날 때마다 타자를 치자

정확하게 예측할 순 없지만, 릴리즈에 필요한 최소한의 코드 라인 수는 어디엔가 정해져 있습니다. 이 라인 수를 미리 미리 채워 놓으면, 릴리즈 직전에 자잘한 버그와 각종 문제에 휘둘릴 확률이 줄어듭니다. 사소한 작업을 따로 뽑아놓고, 시간이 날 때마다 작업을 했었습니다.

빌드 횟수 최소화

로직 구현 때 개발 속도를 최대한으로 내기 위해 구현을 모두 끝내놓고 빌드를 했습니다. 안드로이드 빌드 시 약 10~30초 정도를 소모하는데, 프로젝트 일정이 빠듯한 만큼 빌드 시간이 아까웠습니다. 바보 같은 행동일 수도 있지만, 하루 50번 * 빌드 당 30초 정도라고 가정하면 약 30분의 시간이 빌드 기다리는 동안 낭비됩니다. 이 시간을 아낀다면 릴리즈 전날 밤샐 확률이 줄어들지 않을까? 라는 생각이었습니다.

구현할 건 미리 설계해놓자

종종 출근해서 사무실 올라가기 전에 카페에서 당일에 구현해야 하는 기능을 미리 설계하고 들어갔습니다. 미리 생각을 정리하고 개발에 들어가면 코드 퀄리티에 큰 영향을 주는 듯한 느낌입니다.

7. 팀원들의 호응

개발팀을 제외한 다른 팀원들은 개발하는 동안 정말 많이 응원해주셨습니다. 개발팀이 열심히 하니 다른 팀원들도 같이 열심히 해주는 느낌을 받았습니다.

앱이 릴리즈 됐을 때는 다들 엄청 기뻐했습니다. 대표와 PO에게는 서비스 성장에 아주 큰 장벽 하나가 없어진 것이고, 마케팅 팀은 안드로이드 유저를 데려올 수 있는 가능성과 ios보다 더 정확한 마케팅 전환 지표를 얻었습니다.

명확하게 눈에 보이는 성과라 팀 분위기도 더욱 좋아진 느낌입니다. 개발팀이 팀 전체에 이정도의 영향력을 낼 수 있다는 게 기뻤고, 정말 뿌듯했습니다.

8. 책읽기

기술적인 지식보다는 프로젝트 진행 / 팀 운영 / 자기관리에 대한 지식이 많은 도움이 되었습니다. 개발 기간 동안 다시 꺼내봤던 책들입니다.

  1. 익스트림 프로그래밍
  2. 함께 자라기 - 애자일로 가는 길
  3. 클린 코드
  4. 실용주의 프로그래머

9. 앞으로

그냥 일과 코딩 많이하면 되는 거 아니야? 라고 생각할 수도 있습니다. 하지만 능동적으로 문제 해결에 임하고 적극적으로 나서고 이끌며 성공적인 결과를 내는 건 동기부여, 성취, 자기효능감 측면에서 하늘과 땅차이라 생각합니다.

글 처음에 얘기했 듯 저희 팀은 코로나로 인해 힘든 시간을 겪었고, 긴 시간동안 버텨왔습니다. 그리고 블랙스완을 통해 조금씩 성취와 작은 성공을 쌓아나가고 있습니다.이번 안드로이드 릴리즈는 오랜만에 온전히 개발팀에서 이뤄낸 성취라 더욱 뜻깊습니다.

앞으로도 우리 개발팀에서는 문제 해결에 더욱 적극적으로 뛰어들어 그 누구보다 삽을 먼저 들고 땅을 팔 생각입니다. 삽질에 의미가 있었다면 종종 이렇게 글을 올려보겠습니다.

그리고 이 작은 경험이 누군가에게 도움이 되면 좋겠습니다.
앱도 써봐주시면 감사하겠습니다.