안녕하세요. LINE+ ABC Studio에서 앱을 개발하고 있는 김종식, 남상혁, 박연호입니다. 저희 팀은 현재 일본에서 운영하는 배달 서비스 '데마에칸(Demaecan, 出前館)' 프로덕트를 개발하고 있습니다. 데마에칸은 2000년부터 서비스를 시작한 일본의 No.1 음식 배달 서비스로 2020년에 LINE에서 인수했고, ABC Studio는 2021년 봄부터 프로덕트 개선에 참여하고 있습니다.
일본 1위 배달 앱, 바닥부터 다시 짠다 - Recode 프로젝트, 멀쩡한 앱을 Flutter 앱으로 다시 짠 이유 - 일본 1위 배달 앱, 두 번째 Recode 글을 통해 각각 React Native(이하 RN)에서 Kotlin Multiplatform Mobile(이하 KMM), KMM에서 Flutter로 기술 전환 사례를 공유드린 적이 있습니다. 이번 글에서는 RN으로 작성되어 있던 데마에칸 ConsumerApp을 Flutter로 변환한 사례를 공유드리고자 합니다.
ConsumerApp(소비자용 앱) | MerchantApp(사장님용 앱) | RetailApp(가맹점용 앱) | DriverApp(배달원용 앱) | ||
---|---|---|---|---|---|
프레임워크 전환(Recode) 이력 | React Native → Flutter (2023. 12. 5 출시) | Xamarin → Native → Flutter (2022. 11. 8 출시) | Native → Flutter (2023. 2. 27 출시) | React Native → KMM → Flutter (2022. 6. 28 출시) | |
주요 기술 스택 | 상태 관리 | flutter_bloc(BLoC) | flutter_bloc(Cubit) | flutter_redux | ChangeNotifier 기반(자체 구현) |
내비게이션 & 라우팅 | Router & Navigator | Single Page(자체 구현) | Router & Navigator | Single Page(자체 구현) | |
모듈화 | △ | X | ○ | ○ |
참고로, 저희는 음식이나 리테일 상품을 주문할 수 있는 소비자용 앱을 'ConsumerApp'이라고 부르고 있습니다. 이후 이 글에서 ConsumerApp이라고 지칭하겠습니다.
이전 Recode 프로젝트와의 차이점 및 프로젝트 방향 설정
ABC Studio는 데마에칸 개발에 참여하면서 더 나은 배달 서비스를 제공하기 위해 '모든 앱을 하나의 기술로 제공한다'라는 목표를 세우고 많은 앱에서 Recode 프로젝트를 시작해 성공적으로 Flutter 전환을 완료했습니다.
하지만 ConsumerApp은 이전에 진행한 Recode 프로젝트와는 조금 차이가 있었습니다. ConsumerApp은 데마에칸 내 다른 도메인의 앱보다 사용자 수가 많고 트래픽도 훨씬 높아서 민첩한 운영 대응이 필요한 앱입니다. 또한 여러 사업 부서에서 집중적으로 요구 사항이 몰려드는 앱이기도 합니다. 따라서 이미 일본 현지에 개발 팀이 갖춰져 오랜 시간 운영돼 왔는데요. 그렇다 보니 제품의 스펙은 서비스가 빠르게 성장하는 동안 시도된 수많은 프로젝트별로 파편화돼 있었고, 히스토리조차 찾을 수 없는 경우도 많았습니다.
또한 2022년 즈음부터 사용자들의 피드백이나 만족도 분석 등을 통해 데마에칸 내부에서 UI/UX 개선이 필요하다는 의견이 대두되기 시작했습니다. 데마에칸 서비스는 앱과 웹을 거의 동일한 경험으로 제공하며, 실제 주문이 발생하는 비율은 약 8:2 정도였고, 향후 앱에 더 집중하는 것으로 방침이 결정됐습니다. 이에 따라 앱 서비스 사용 경험을 향상시키면서 동시에 사업적 목표까지 달성하기 위해서는 ConsumerApp의 기술적 쇄신을 더 이상 미루기 힘든 시점이 되었습니다.
기술 스택 변경이 꼭 필요한가?
기술 쇄신이 필요하다는 것은 확인했지만 그 과정에서 기술 스택을 변경하는 것이 과연 미래를 위해 더 나은 선택일지는 다시 고민해야 했습니다.
ConsumerApp은 RN으로 구현되어 있었고, 나머지 도메인의 앱들은 모두 Flutter로 전환이 완료된 상태였습니다. 이와 같이 기술 스택이 나뉘어 있으면 각 도메인 영역 간 기술 교류가 어려워집니다. 또한 서비스에 범용적으로 사용되는 기술을 불필요하게 두 개로 나눠 개발 및 유지 보수해야 하고, 장기적으로 기술에 대한 이해도나 채용 관점에서도 구분해서 고민해야 하기 때문에 팀 운영 측면에서도 좋지 않습니다.
또한 기술 자체만 놓고 봐도 아래와 같이 RN보다는 Flutter가 점점 더 많은 사람의 관심을 받고 있었습니다.
만약 ConsumerApp도 Flutter로 전환한다면 개발자가 언제든지 Merchant, Retail, Delivery 영역의 제품 개발에 참여할 수 있고, 반대 경우도 가능해집니다. 이렇게 되면 채용할 때도 두 기술로 구분할 필요가 없어지므로 더 효율적입니다. 다만 Recode 프로젝트를 진행하는 동안 RN을 선호하는 엔지니어의 이탈 우려가 있었기에 참여하는 프로젝트 구성원 모두의 공감을 얻고 동일한 목표를 바라보는 것이 특히 중요했습니다.
ConsumerApp의 특성을 고려한 Recode 프로젝트 방향 설정
앞서 소개한 것처럼 ConsumerApp은 다른 앱보다 요구 사항이 많습니다. 비즈니스는 계속 성장해야 하기에 Recode와 상관없이 사업과 마케팅, CS 측에서는 지속적으로 요구 사항을 전달하고 있었으며, 프로덕트 조직 내부에서도 보안이나 기술 관련 이슈를 해결하기 위해 끊임없이 개선 사항이 도출되고 있었습니다.
이와 같은 상황에서 Recode 프로젝트를 진행하기 위해, 여러 부서와 논의해 Recode 완료 후로 미룰 수 있는 과제는 최대한 미루면서 미룰 수 없이 꼭 해결해야 하는 과제를 최소한으로 정리했습니다. 예를 들어, 새로운 쿠폰 시스템 적용이나 주문 시 위치 보정 같은 과제는 매출이나 고객 클레임에 미치는 영향이 커서 차마 미룰 수 없었습니다.
이런 상황을 종합적으로 고려한 결과, 난관이 예상되지만 이번 Recode 프로젝트는 기존 제품(RN 버전)으로 일정이 정해진 과제들을 배포해 나가면서, 동시에 새로운 제품(Flutter 버전)을 병렬 개발하는 것으로 결정했습니다.
진짜 마지막으로, 갈아엎어 봅시다 ㅆ (←웃는 눈 모양입니다)
PoC(Proof of Concept)
Flutter 버전 개발은 Flutter에 좀 더 익숙한 한국 개발 팀에서 시작했습니다. 그 사이 일본 개발 팀은 기존 RN 버전 제품 운영 및 개선 업무와 함께 Flutter 학습에 집중했습니다(일본 개발 팀 전원이 '오늘부터 Flutter 1일'과 같은 학습을 시작했습니다).
기본적으로 RN 버전에서 제공하고 있는 기본 기능은 Flutter 버전에서도 모두 구현할 수 있어야 했습니다. 따라서 PoC를 통해 검색 및 탐색 기능과 주문에서 배달 완료까지의 흐름에서 사용하는 모든 기능을 Flutter로 전환할 수 있는지 확인하는 게 가장 중요했습니다. 아래는 구체적으로 PoC(Proof of Concept) 단계에서 우선적으로 고민하고 확인한 사항 중 일부를 가져온 것입니다.
요구 사항 | 세부 검토 항목 | 검토 결과 |
---|---|---|
최소 기능 요건 | 서드 파티(3rd Party) 로그인이 가능한가? | flutter_line_sdk, sign_in_with_apple로 구현 가능 |
서버와의 통신에 RestAPI와 GraphQL을 사용할 수 있는가? | dio, ferry로 구현 가능 | |
위치 정보와 지도 라이브러리를 사용할 수 있는가? | geocoding, platform_maps_flutter로 구현 가능 | |
... | ||
주문 경험 | 기존에 사용하던 모든 결재 수단을 사용 가능한가? | Apple Pay는 pay로 구현 가능 인앱 브라우저를 통한 결재는 flutter_inappwebview로 활용 가능 |
푸시(push) 통지 표시가 가능한가? | firebase-messaging로 활용 가능 | |
... |
데마에칸 앱에서 제공하는 9가지나 되는 결재 수단을 모두 그대로 사용할 수 있는지 검토했고, 3D Secure 대응이 가능한지도 확인했습니다. RestAPI와 GraphQL을 사용하는 서버와의 통신에서는 기존에 사용하던 인터페이스를 모두 동일하게 Flutter 버전에서 구현할 수 있는지 검토했으며, 기존에 RN에서 제공하던 서 드 파티 연동과 같은 다양한 기능들을 Flutter 버전에서 동일하게 구현이 가능한지도 검토했습니다. 또한 장기적으로 추후 데마에칸에서 제공하는 모든 앱 서비스에서 동일한 UI/UX 경험을 제공하기 위해 모듈화를 통해 디자인 시스템을 공용화해서 사용할 수 있는지도 고민했습니다.
Flutter 모듈화에 대해 궁금하신 점은 ABC Studio에서 발행했던 Flutter 패키지로 공통 모듈 리팩토링하기를 참고하시기 바랍니다.
비기능적 요소 역시 다각도로 검토했습니다. 예를 들어 기존 RN 버전에서는 CodePush를 활용해 앱에서 주문할 수 없는 상황 등의 경우에 빠르게 패치로 대응할 수 있었습니다. 월 3~4회 정도 크고 작은 패치를 진행하고 있었는데요. CodePush를 사용할 수 없는 Flutter 버전에서 이를 대체할 수 있는 방안을 검토해야 했습니다. 이를테면 CodePush에 의존하는 비정기적이고 잦은 배포는 QA 프로세스가 불규칙적으로 진행돼 안정성이 저하될 수 있기 때문에, 보다 규칙적이고 안정적인 QA 시간을 확보하기 위해 정기 배포 프로세스로 전환하는 것 등을 고민할 필요가 있었습니다.
PoC 중 RN 버전과 비교해 개선할 수 있는 점을 발견하기도 했습니다. 예를 들어, RN 버전에서는 Hooks을 이용해 상태를 관리했는데요. Flutter 버전에서는 BloC을 사용하면서 코드 분석이나 유지 보수 측면에서 좀 더 나은 결과를 얻을 수 있었습니다. 물론 UI와 BloC 간 상호작용을 위해 Boilerplate 코드가 많이 필요하다는 단점이 있긴 했지만, build_runner를 통해 코드를 생성하거나 IDE의 도움으로 충분히 해결할 수 있다고 판단했습니다. 인터렉션이나 애니메이션 등 성능 측면에서도 이전보다 낫다는 평가도 있었습니다. 개인적으로는 Flutter SDK와 렌더링 성능이 지속적으로 개선된 것과, Recode 기간 중 Flutter에서 게임 툴킷을 공개한 점이 인상 깊었습니다(Flutter > Casual Games Toolkit).
프로젝트 킥오프 미팅
2023년 5월, ConsumerApp을 개발하는 일본 개발 팀과 한국 개발 팀이 교토에서 오프라인으로 만나 이틀간 워크숍 형태로 Recode 프로젝트 킥오프를 진행했습니다.
일하는 방식과 그라운드 룰 수립
킥오프에서는 가장 먼저 양 팀이 어떻게 협업하며 개발할지 논의했습니다. RN 버전과 Flutter 버전을 병행하면서 스크럼하기에는 인원이 14명(한국 4명, 일본 10명)으로 많았고 언어의 장벽도 있었으며, RN 버전은 과제 단위로 개발을 진행하는 반면 Recode 진행 과정은 출시 버전 단위로 진행해 왔기 때문에 전환 방식에 대해서도 논의해야 했습니다. 이런 모든 장애물을 극복하고 원팀으로 협업하기 위해 커뮤니케이션 및 개발 방법과 코드 리뷰 등 여러 주제에 대해 의견을 나눴고, 논의 결과 아래와 같이 일하는 방식을 정리했습니다.
- Flutter에서 린트(lint) 옵션은 가능한 한 모든 것을 활성화하고, 코딩 컨벤션은 Effective Dart: Style을 지향합니다.
- 코드 리뷰는 Flutter와 관련된 코드라 면 한국 개발자가 주로 맡고, 비즈니스 로직이나 배경지식이 많이 필요한 부분은 일본 개발자도 함께 확인합니다.
- 커뮤니케이션은 기본적으로 영어를 사용하며, 자세한 논의가 필요하다면 Slack에서 번역 봇을 활용해 일본어/한국어/영어 모두 활용합니다.
- 주 3회 스크럼과 주 1회 정기 미팅을 진행합니다. 스크럼은 아침에 15분으로 진행하며, 정기 미팅은 통역을 섭외해 1시간으로 진행합니다.
인력 계획 수립
RN 버전에 참여하는 10명은, 아래와 같이 프로젝트가 진행되면서 각자 담당하던 과제가 마무리되면 한 명씩 Flutter 버전에 참여하는 것으로 계획했습니다.
진행 상황 공유 후 과제 수행 및 검증 방법 수립
Recode 프로젝트의 요구 사항은 기존 앱에서 제공하던 기능을 Flutter 버전으로 온전히 이행하는 것이며, 이를 위해서는 안정성을 유지한 채 최대한 빠르게 개발을 완료하고 QA 일정을 잘 조율하는 것이 중요합니다. 이를 위해 논의했던 주요 내용은 다음과 같습니다.
- 킥오프 이전에 진행된 Recode 진행 상황 상세 공유
- 각 기능별로 일본 개발자와 한국 개발자가 Recode를 진행하면서, 이해하기 어렵거나 확인할 수 없던 히스토리나 개발 단계에서 사용 가능한 테스트용 API, 과제가 병렬로 진행되면서 발생할 수 있는 영향 범위 등을 공유하고 각 사안을 좀 더 구체적으로 확인하며 인식을 맞춰갔습니다. 특히 한국 팀에서 상대적으로 신경 쓰 지 않고 있었던 로깅 영역은 생각보다 작업량이 컸으며, RN 버전에서도 잘 정리되지 않았었는데요. 이번 기회에 로깅 스펙을 복각해 구현하기로 했고, 일본 팀에서 이를 담당하기로 결정했습니다.
- 앞으로 수행할 과제 확인 및 인식 맞추기
- 먼저 우선순위가 가장 높은 9개 과제에 대해서 각 과제별 담당자 및 현재까지의 진행 상황과 출시 예상 일정 등을 확인했습니다. 또한 운영 중 발생하는 크고 작은 이슈에 발 빠르게 대응하기 위해 일본 팀의 대응 방법을 확인하고, 앞으로 누가 어떻게 담당할지 결정했습니다. 한국 팀에서는 RN 버전이 배포될 때마다 Flutter 버전을 최신화하고, RN 버전의 주요 과제가 완료돼 Flutter 버전 개발에 참여할 수 있는 일본 개발자는 이전에 담당했던 과제에 대한 Flutter를 학습하면서 Recode 과정을 진행하는 것으로 논의했습니다. 이렇게 함으로써 스펙을 정확히 아는 분들이 Flutter로 같은 영역을 작업할 수 있었습니다.
- Recode 프로젝트 검증 방법 논의
- 개발 단계에서 필요한 검증은 각 기능별로 상세 스펙을 더 잘 파악하고 있는 일본 개발 팀에서 담당하기로 했습니다. 개발 완료 후 QA는 크게 세 번으로 나눠 진행하기로 결정하고, 검증 범위 및 일정 조정, 진행 방식 논의 등 QA 팀과의 커뮤니케이션은 일본 개발 팀에서 담당하기로 결정했습니다. 또한 QA와 함께 사내 CBT도 고려해 보기로 했습니다(참고로 QA는 일본 현지에서 진행되고 있습니다).
이와 같이 오프라인에서 킥오프를 진행하면서 기존 RN 버전이 어떻게 개발 및 운영되고 있는지 파악할 수 있었습니다. 하나의 팀으로 프로젝트를 진행하고 완료하는 데 가장 큰 도움이 되는 활동이었습니다. 또한 한국 팀이 선제적으로 Recode한 코드를 오프라인에서 다 같이 보면서 코드 리뷰를 진행하거나 회식 등의 활동을 통해 서로 신뢰하고 존중하는 자세를 가질 수 있었습니다.
개발 시작
ABC Studio 앱 개발자의 십시일반 협업
이제 남은 일은 빠른 시간 내에 개발을 완료하는 것입니다. 킥오프 미팅 후 기능 단위로 Jira 티켓을 만들고 담당자를 지정했습니다. 한국의 ABC Studio 팀에는 ConsumerApp 개발자뿐 아니라 MerchantApp과 RetailApp, DriverApp 개발자분들도 있는데요. 아래와 같이 다른 도메인의 개발자까지 모두 참여해서 각 기능 단위로 최대한 빠르게 개발을 완료할 수 있도록 노력했습니다. 예를 들어 DriverApp 개발자가 ItemTop을 비롯한 4개 영역을 담당했고, MerchantApp 및 RetailApp 개발자는 Login/Register 영역에 참여했습니다.
그 외에 CI/CD를 새로 구축하는 일은 RetailApp 개발자분들이 담당했습니다. ConsumerApp은 기존에 CI/CD 환경으로 Bitrise를 사용하고 있었는데 비용 측면에서의 이점을 고려해 다른 Flutter 프로젝트에서 이미 잘 활용할 수 있도록 준비돼 있던 Teamcity로 이전했습니다. 이를 통해 자동화를 위한 공통 스크립트를 만들어 활용 중이고, 점점 더 개선해 나갈 수 있게 되었습니다.
개발 중 발생한 이슈들
물론 모든 과정이 계획대로 순조롭게 진행되지는 않았습니다.
먼저 프로젝트 킥오프 후 미처 작업으로 도출해 작업 목록에 올리지 못한 부분들이 있었습니다. 예를 들어 ConsumerApp에서 사용자가 주소지를 변경하거나 등록하는 흐름에서 놓친 부분이 있었습니다. 아래 그림은 ConsumerApp에서 사용자가 주소지를 변경 혹은 등록할 수 있는 6가지 경로를 나타낸 것인데요. 아래 그림 왼쪽의 '배송지 정보 바', '배송지 등록 안내 UI' 등은 처음부터 제대로 작업으로 도출이 됐는데, 오른쪽 '주소 탐색'과 '우편번호 검색', '지도에서 설정'이 작업으로 도출되지 못하고 누락된 문제가 있었습니다.
이 기능은 처음 앱 구동 시 비회원으로 주문하거나 회원 가입 중 주소지 등록하기, 마이 페이지에서 배송지 목록, 주소 목록 확인이 가능한 모달 등 다양한 경로에서 실행됩니다. 또한 회원 가입 경로에서만 예외적으로(위 그림의 빨간 선) 우편번호 검색만 지원하는 등 미묘한 차이가 있습니다.
그런데 오른쪽 세 가지 작업이 제대로 도출되지 못한 바람에 각 기능을 연계할 때 누군가가 개발하면서 우선 임시로 구현해 놓은 것으로 기능이 연계돼 버렸습니다. 이 문제가 뒤늦게 발견됐는데요. 부랴부랴 담당자를 지정하고 세부 스펙을 확인해 별도로 진행해야 해서 프로젝트 일정을 관리하는 데 어려움을 겪었습니다.
또한 주요 기능 단위로 진행하다 보니 숨겨져 있던 작은 스펙이 발견돼 추가로 구현해야 하는 상황도 있었습니다. 이는 전체 개발 일정을 예측하기 어렵게 만들었는데요. 뒤늦게 발견되는 경우가 종종 발생해서 개발 일정을 지키지 못할까봐 초조한 마음이 들기도 했습니다. 이와 같이 추가로 확인된 작업들은 바로바로 Jira 티켓을 등록하고 담당자를 정리했습니다. 프로젝트에 참여하는 모든 분들께서 협업과 존중의 자세로 최선을 다해 주셔서 큰 공백은 발생하지 않아 결국 일정을 지킬 수 있었지만, 사전에 스펙을 좀 더 꼼꼼하게 파악해 프로젝트를 진행하는 것이 필요하다는 교훈을 얻었습니다.
Recode 중 34번 출시된 RN 버전과 이를 바쁘게 따라간 Flutter 버전
이번 프로젝트는 기존에 출시된 앱을 운영 및 개선하면서 동시에 Flutter 앱을 따라 만드는 프로젝트였습니다. 따라서 처음부터 RN 버전의 배포를 어느 정도 예상했지만, 예상했던 것보다 더 많이 배포됐습니다.
Recode 프로젝트 시작 당시 22.2.0이었던 RN 버전은 28.2.1까지 올라갔습니다. 크고 작은 배포가 총 34회 있었는데요. 주요 과제뿐 아니라 운영 과정에서 발생한 이슈 관련 패치도 예상보다 많았습니다. 이로 인해 각 기능 단위별로 Recode 완료 판단이 모호해지는 부분이 생기거나, Recode 기능 하나를 개발 완료해 코드 리뷰를 진행할 때 작성자와 리뷰어가 바라보는 RN 버전이 달라서 커뮤니케이션 비용이 높아지기도 했습니다.
이와 같은 상황에서 진행하는 Recode에서는 두 앱의 스펙이 동일한 수준이 되도록 개발과 검증을 반복하는 과정이 제일 중요합니다. 일본 팀에서 스펙을 상세히 알고 있어서 회귀 테스트를 맡아 주셨고, 이를 통해 Recode를 진행한 한국 멤버가 코드 수준에서는 미처 파악하지 못한 부분까지 찾아낼 수 있었습니다. 특히, Recode 프로젝트와 기존 앱 기능 개선 및 출시가 병렬로 진행됐기 때문에 RN 버전에 반영된 새로운 기능의 경우 Flutter 버전에 다시 반영하는 부분에서 스펙과 배경을 자세하게 이해할 수 있었습니다(자세한 내용은 Flutter Kaigi 2023 콘퍼런스의 出前館におけるFIutterの現在とこれから(일본어, Demaecan Flutter의 현재와 앞으로) 세션을 참고하세요!).
이 기회에 최소 OS 지원 버전까지 업데이트
Flutter 버전으로 전환하면서 OS 최소 지원 버전도 과감하게 올렸습니다. ConsumerApp 사용자의 OS 현황을 살펴보면 iOS 11부터 iOS 13까지의 점유율은 0.32%, Android 5와 Android 6의 점유율은 0.1% 정도로 매우 낮았습니다. 이를 고려해 이번 기회에 최소 버전을 업데이트하기로 결정하고, 출시 일정을 계획할 때 하위 버전 사용자에게 웹 이용을 안내하는 등 RN 버전의 기존 사용자에게 이와 같은 변경 사항을 충분히 알리기 위한 시간을 함께 고려했습니다.
그 결과, 기존 RN 버전은 iOS 11 이상, Android 5.0 이상에서 사용할 수 있었는데요. Flutter 버전부터는 iOS 14 이상, Android 7.0 이상에서 사용할 수 있게 됐습니다. 참고로 배포 완료 시점에 사용한 Flutter SDK 버전은 3.10.7입니다.
드디어 배포 완료, 과연 사용자들이 눈치챘을까?
앞서 소개 드린 바와 같이 개발 진행 상황 및 검증의 우선순위 등을 고려해 QA를 세 번으로 나눠 진행했고, 어느 정도 안정화된 후에는 사내 CBT를 진행했습니다. 이후 Google Play Store의 단계적 배포 및 Apple App Store의 점진적 출시 기능을 활용해 배포하면서 크래시 발생이나 사용자 반응을 모니터링했는데요. 단계적 출시 과정에서 몇 건의 오류가 발견됐지만 민첩하게 대응해 해결했으며, 다행히 심각한 이슈는 없었습니다.
Recode 프로젝트는 출시 후 사용자들이 눈치채지 못할수록 성공하는 프로젝트인데요. 다행히도 많은 분들이 눈치채지 못했습니다! 일본에서는 일본 최대 Flutter 콘퍼런스인 FlutterKaigi 행사 후 몇몇 분들께서 라이선스 화면이 변경된 것을 SNS에 올리며 공유하시기도 했는데요. Flutter 버전으로 업데이트하고 나서 특별히 큰 이슈가 발생하지 않아 정말 다행이었습니다. 🙂
출시 후 회고
겨울이 끝나갈 즈음 시작했던 프로젝트가 다음 겨울을 맞이하면서 완료됐습니다.
돌이켜 보면, 프로젝트에 참여한 대부분의 멤버들이 빠르게 달려 나가고 있는 제품의 속도를 늦추지 않으면서 기술 기반을 교체해야 한다는 점에 걱정이 많았을 것이라고 생각합니다. 저 역시 프로젝트를 진행하면서 속도를 최우선으로 하다 보니 협업 방식을 정교하게 준비하지 못했던 점이 아쉬움으로 남습니다. 한국 팀에서는 처음부터 모든 인원이 함께 참여한 프로젝트가 아니다 보니 한두 명에게 모든 코드 리뷰가 쏠리는 현상이 발생했습니다. 또한 일본 팀은 도메인별로 어느 정도 역할이 분담돼 있었던 반면 한국 팀은 역할 분담이 명확하지 않았고 배경지식 없이 기능 단위로 몰아쳐서 작업해야 했는데요. 일본 팀의 많은 도움을 받고 있었음에도 배경지식을 모르고 코드 리뷰를 하는 경우가 발생하는 등 특히 프로젝트 초중반에 많은 어려움이 있었습니다. Recode 프로젝트가 중반을 넘어가면서 킥오프 때 결정한 스크럼 방식 등의 협업 활동 룰에 개선할 부분이 보였음에도 시간이 촉박해 차마 깊게 논의할 기회가 없어서 아쉬웠습니다.
하지만 그럼에도 이번 Recode 프로젝트로 달성해 낸 것이 너무 많다고 생각합니다. 이제 데마에칸 내 모든 앱 프로덕트가 Flutter로 전환됐습니다. 한국과 일본의 앱 개발 팀이 기술적으로 원 팀으로 일할 수 있는 기반이 마련됐습니다. 또한 사용자들은 눈치채기 어렵겠으나 내부적으로도 많이 변하고 있습니다. ConsumerApp Recode 프로젝트를 진행하면서 양 팀이 서로 배려하면서 존중하는 자세로 임했기 때문에 서로 부족한 부분을 채워나가면서 문제없이 배포까지 완료할 수 있었다고 생각합니다.
앱을 배포한 후 Miro를 활용해 온라인 KPT(Keep/Problem/Try) 회고를 진행했습니다. 아래와 같이 프로젝트가 진행된 10개월 사이에 일어난 이벤트를 기록한 후 각자가 특정 시점마다 생각난 Keep/Problem/Try 내용을 세 가지 색으로 구분해 붙여봤는데요. 프로젝트가 끝나고 양 팀이 오프라인에서 좀 더 자주 만나서 협업하면 좋겠다는 의견이 가장 많이 나왔습니다.
한국 팀과 일본 팀은 이제 원 팀으로서 좀 더 긴밀하게 프로덕트 개발에 대해 이야기하기 시작했습니다. Flutter의 최신 기술이나 서로 다른 도메인에서 발생한 이슈 및 해결 방법 등을 공유하기도 하고, 협업 방식이나 배포 프로세스 등 개발 외의 활동에 대해서도 이야기하기 시작했습니다. 원 팀으로서 최고의 제품을 만들어 나가기 위한 고민을 함께 할 수 있는 환경이 형성되면서 Recode 프로젝트를 통해 서로 존중과 신뢰를 쌓을 수 있었다는 것은 수치화하기 어려운 소중한 성과라고 생각합니다.
마치며
Recode 프로젝트는 2보 전진을 위한 1보 후퇴입니다. 이번 프로젝트는 모든 Recode 프로젝트 중 가장 긴 호흡이 필요했는데요. 덕분에 이제 ConsumerApp은 UI/UX 개선을 비롯해 사용자에게 필요한 가치를 더 빠르게 전달할 수 있는 기술적, 인적 준비를 마쳤습니다. 이제 2보 전진할 차례입니다. 점점 더 나아지는 제품으로 인사드리겠습니다.