GS리테일 DX 블로그

Digital Transformation으로 고객 생활 가치의 이노베이션을 꿈꾸는 IT 사람들의 이야기

Cloud&Security

Flutter 기반의 모바일 앱 재개발 회고

yohany 2021. 11. 22. 09:29

Android 개발자가 개발한 앱과 IOS 개발자가 개발한 앱을 Flutter 로 다시 개발하고 배포한 후 수개월이 지났다.

우리가 Flutter 로 재구축한 모바일 앱은 GS SHOP 이며, GS Retail 에서 운영하는 모바일 커머스 앱 중 하나이다.

 

https://play.google.com/store/apps/details?id=gsshop.mobile.v2 

 

GS SHOP - 고객님의 쇼핑을 더욱 풍요롭게! - Google Play 앱

당신의 가장 좋은 선택, GS SHOP 오직 GS SHOP에서만, 오직 앱에서만 누릴 수 있는 즐거운 경험

play.google.com

https://apps.apple.com/app/gsshop/id365438600

 

‎GSSHOP

‎당신의 가장 좋은 선택, GS SHOP 오직 GS SHOP에서만, 오직 앱에서만 누릴 수 있는 즐거운 경험 ◆ 고객님의 쇼핑을 더욱 풍요롭게! ◆ 내일 방송하는 상품들의 생생한 정보를 영상으로 미리 확인

apps.apple.com

 

프로젝트를 종료하고 난지 수개월이 지난 지금, 우리가 왜 Flutter 를 선택했는지? 그리고 어떤 문제를 해결하고자 했는지 회고해 보고자 한다.

 

이 회고는 그 동안의 노고에 대한 위안이나 칭찬이 아닌, 한동안 현실과 타협하기 위해 애써 외면했던 초심을 다시 찾을 수 있을 것이라는 기대감 때문이다.

 

올해 초 우리는 Native 로 개발한 모바일 앱을 Cross Platform 개발 환경으로 전환을 계획하기로 했다.

 

Cross Platform 개발 환경을 선택하는 것은 단지 개발 비용이나 생산성을 위한 것이 아니어야 한다. 게다가 Cross Platform 으로 생산성이 향상 되었으니 성능은 포기해야하는것 역시 크게 잘못된 의사 결정일 가능성이 크다.

 

심지어 MVP(Minimum Viable Product, 최소한의 핵심 기능을 개발하여 고객의 Feedback 을 받기 위한 Product 라고 할 수 있겠다) 를 개발하자는 것도 아니고, 현재 Native로 운영중이고 MAU가 10M 이 넘는 모바일 앱을 Cross Platform 개발 환경으로 전환한다는것은, 상당한 리스크를 감수해야만 했기에, 왜 모바일 앱을 다시 개발해야 하고 심지어 Cross Platform 으로 해야 하는지 진지하게 고민하고 검증할 수 밖에 없었다.


1. 모바일 앱을 다시 개발해야 했던 이유.

가장 먼저, 모바일 앱을 다시 만들어야 하는 동기는 무엇인가? 몇가지로 요약해 보면 아래와 같다.

 

첫번째, 우리 모바일 앱은 약 10년전에 Android 와 IOS 로 각각 개발한 모바일 앱이었고, 계속해서 Refactoring 하고 있으나, 이미 한계가 보이고 있었다.

아니, Refactoring 보다는 재구축을 검토해야 하는 상황까지 왔다는 것이 맞는 말이겠다.

 

궁극적으로 개발자가 기여하고 싶은 코드여야만 하다. 기술 부채가 쌓이고 쌓여 누구도 건드리고 싶지 않은 코드가 아닌, 잘 구조화 되어 있어 개발하면서 본인의 역량을 쌓을 수 있겠다는 생각이 드는 의미 있는 코드 말이다.

 

두번째, Web과 비교하자면, 모바일 앱의 사용자 비중이 크게 높음에도, Web 보다는 모바일 앱 개선은 빠르지 않았다.

이것은 여러가지 이유가 있겠지만, 모바일 앱 개발 생산성이 상대적으로 좋은 방법이 없을까 고민해야 했다.

 

그리고 근본적으로 모바일 개발자가 부족한 것이 가장 큰 이슈일 것이다. 그래서 Android 와 IOS 개발자 뿐 아니라, 서버 또는 웹 개발자도 모바일 앱을 개발할 수 있는 이상적인 환경도 꿈꾸고 있었다. 물론 개발자 본인의 Career Path 를 고려하여 희망하고자 하면 언제든 모바일 개발을 할 수 있는 환경을 개발자 분들에게 만들어 드리고 싶었다.

 

세번째, 품질을 올릴 수 있는 개발 프로세스를 다시 고민해야 할 때이다.

서비스의 품질은, 개발자의 역량과 개선된 개발 환경 만으로 해결할 수 있는 것이 아니다. 서비스 기획 부터 UI/UX 디자인 그리고 개발까지 전반적인 프로세스를 다시 잡아야 할 때인 것이다.

 

디자인 요소의 모듈화는 코드와 직접적인 연결이 되어 있어야 하고, 디자이너와 개발자가 사용하는 Tool 역시 다시 고민해야만 했다.

즉, Design System Language 를 통해 UI/UX 디자이너와 개발자가 서로 동일한 수단과 방식으로 커뮤니케이션 할 수 있는 환경이 필요했다.

 

네번째, 모바일 앱 사용성의 개선이 필요한 상황이다.

모바일 커머스 앱에서는, 가장 많이 접속하는 화면인 메인 화면과 상품 페이지 만큼은 네이티브 정도의 로딩 속도가 요구될 수 밖에 없다. 하지만, 기존 모바일 앱은 일부 화면을 제외하고는 많은 화면이 내장된 WebView 에 HTML 파일이 로딩되는 형태로 구현되어 있는 상황이다.

 

HTML 로도 충분히 로딩 속도를 개선할 수는 있지만, WebView 의 DOM Rendering 에 드는 비용은 무시할 수 없었다

 

이러한 몇가지 주요한 이슈로 인해 모바일 앱을 재구축하기로 하고, Cross Platform 을 검토하고 Flutter 를 기반으로한 앱 재구축을 계획하기 시작했다.


2. Cross Platform 그리고 Flutter 의 특징.

Cross Platform 그리고 Flutter 에 대한 특징 부터 몇가지만 알아보자.

  1. Native vs. Cross Platform

    Android 개발자와 IOS 개발자가 각각 개발한 모바일 앱을 운영하는 일은 어느 기업이든 감당할 수 밖에 없는 당연한 현실이다.
    Cross Platform 기반의 개발환경은, Native 로 개발할때 보다는 생산성이 높을 수 밖에 없다. 그렇다고 생산성이 2배가 된다고 할 수는 없지만, 충분히 성과를 낼 수 있을 것으로 기대했다.

    우리가 구현하고자 하는 서비스가 속도나 Computing 에 상당히 민감하거나 Device 에서 제공하는 기능에 민감하게 반응해야 하는 Feature 가 필요한 상황이라면, Cross Platform 보다는 Native 가 더 적합할 것이다.

    반면에, 모바일 커머스 서비스를 구현하는 우리는, Computing 이나 민감한 디바이스의 특정 기능을 요구하는 것이 아니므로, 반드시 Native 가 필수일 필요는 없었다.

    그렇다고, Cross Platform 으로 모든 기능을 다 구현할 수 있는 것은 아니다. 필요에 따라서는 Native 코드로 기능을 구현하고 이를 Cross Platform 코드에서 호출해 사용하는 경우도 있을 것이다.

  2. React Native vs. Flutter

    Cross Platform 기반의 개발 환경은 대표적으로 React Native와 Flutter 가 있다. React Native 는 범용적인 Front-end 구현 기술인 React 개발자라면, 당장에라도 모바일 앱을 개발할 수 있을 정도로 learning curve 가 좋은 편이다.

    반면에 Dart 언어를 사용하는 Flutter 는 Dart 언어에 어느정도 학습이 필요한 만큼 상대적으로 접근성이 떨어질 수 밖에 없으나, React Native에 비하여 Native 에 충분히 근접할 만한 성능을 낼 수 있는 점에 있어서 큰 장점이 있었다.

    실제로 검증 당시 두가지 환경에서 동일한 기능을 구현 했을 때 성능의 차이를 체감할 수 있었다.

  3. 향후 선호하게 될 개발 플랫폼 또는 개발 언어인가?

    Flutter 플랫폼은 Dart 언어를 사용하여 개발하게 된다.

    한때 개발자들에게 비인기 언어 였던 Dart 는 수년 동안 변화를 거쳐 비교할 수 없을 만큼 편리해졌고, 가독성도 상당히 높아졌다. 게다가 Null Safety 코드를 작성할 수 있는 환경을 제공하여 Runtime Exception 을 빌드하기 전에 방지할 수 있어 안정적인 코드를 작성할 수 있었다.

    Dart 언어는 생소해 보일 수 있지만, 다른 객체지향 프로그래밍과 거의 동일하기에 어렵지 않게 익숙해 질 수 있었다. 개인적으로 한달정도면 충분하지 않을까 생각한다. 우리팀에서 실제로 신입사원이 프로젝트에 투입되어 개발하는데에도 전혀 문제되지 않았다. 충분한 역량을 보유한 우리 신입사원님들 존경하지 않을 수 없다.

  4. 이 플랫폼의 향후 기대되는 전망이 있는가?

    Flutter는 Skia 엔진 위에 UI를 그려내고 있으며, Google 에서 개발하고 있는 fuchsia OS 위에 동작할 수 있다. 최근 일부 자동차 제조사는 차량 Display 가 fuchsia OS 로 동작하고 있으며, 여기에 Skia 엔진을 통해 화면을 그려낸 차량이 출시되고 있다. 초경량 fuchsia OS 기반의 다양한 소형 단말 부터 대형 스크린까지 향후 다양한 디바이스에 Flutter 로 화면을 랜더링할 기회는 더욱 많아 질 것이라 기대한다.

    Google I/O 2021 에서는 주요 Agenda 5건 중 하나로 flutter 가 포함되기도 했고, Google Flutter 팀에서는 안정성과 성능 중심의 개선이 꾸준히 되고 있다. 그리고, 한때 Cross Platform 중 개발자가 가장 선호하는 React Native 보다 더 많은 관심을 보이고 있는 트랜드 지표도 확인할 수 있을 것이다.

    또한 Android 와 IOS 뿐 아니라, Web 으로 빌드하는 것 역시 상당히 안정화 되어 있는 상태이다. 우리팀 역시 향후 Web 까지 Flutter 기반으로 전환하는 부분도 중장기적으로 검토하고 계획 중이다.

2. 프로토타입 개발부터 시작.

본격적인 프로젝트가 시작되기 전, 나는 현재 IOS 개발자와 Android 개발자에게 Cross Platform 이 현재 우리가 구현하고 운영하는 서비스는 충분히 수용 가능하고 이슈가 없다는 것을 설득해야 만 했다.

 

그렇다고, 프로젝트를 시작하기 전에 PoC (Proof of Concept) 프로젝트 부터 해야 할까? 기능 구현 항목을 나열하고, 모두 구현 가능한지 검토하는 과정 말이다.

 

사실, 그 어떤 언어나 환경이 주어지더라도 개발자 입장에서는 구현해내지 못하는 기능은 존재하지 않을 가능성이 크다. 더구나 새로운 환경에서 모바일 앱을 새로 개발하는 상황이라면, 기존 코드나 라이브러리에 종속되지 않기 때문에 더욱 그렇다.
즉, 개발 환경보다 개발자의 의지가 구현 가능성에 미치는 영향이 더 클 수밖에 없다.

 

그래서 기술로 구현가능한 기능을 하나씩 검증하기 보다는, 향후 개발해야 할 화면을 빠르게 개발해보는 것이 더 설득력 있을 것이라 생각했다.

GS SHOP 앱의 메인 페이지와 상품페이지를 빠르게 구현해보게 되었지만, 반드시 코드의 완성도는 높아야만 한다.

 

검증 작업을 위한 개발 코드는 기술 검증에 중점을 두고 있다고해서, 가독성이나 구조의 설계가 부족해서는 안된다.
개발 코드가 정상적으로 기능 동작하는것 만큼, 코드의 품질도 검증의 중요한 요소이다. 코드는 충분히 확장성 있는 패턴으로 개발이 가능한지? 또는 우리 개발자 모두가 이해할 수 있는지도 반드시 검증되어야 하기 때문이다.
기능은 동작하지만, 우리가 향후 운영하기 어렵거나 만족스럽지 못한 코드라면, 받아들이기 쉽지 않기 때문이다.

 

결국에는 약 3주 동안, 프로젝트 개발 시작할 때 바로 사용가능한 Boilerplate project 를 개발하고, 여기에 프로젝트 메인 페이지와 상품 상세 페이지를 개발하게 되었다. 이 코드는 그대로 실제 개발 프로젝트에 바로 사용될 수 있었다.

 

기본적인 폴더의 구조 정도 간단하게 그려 본다.

gsshop_mobile
|- android
|- assets  <-- 아이콘 및 이미지 파일 저장
|- build
|- docs
|- ios
|- lib  <-- 어플리케이션 소스 코드
|- packages <-- 내부에서 사용하는 package

`flutter create` 명령어로 초기 프로젝트를 만들때 자동 생성되는 폴더 구조와 전혀 다르지 않다. 

 

다만 packages 라는 폴더를 만들고, 이 폴더 안에는 pub.dev에서 공유된 package가 아닌 내부에서 개발한 공통 package 를 생성하도록 했다. 또한 서버와 통신하는 기능과 데이터 Model 파일은 서비스 도메인별로 package 로 만들어 packages 폴더안에 위치하게 된다.

이것은, 화면을 그리는 영역과 상태 관리는 lib 폴더안에서 하고, 서버 통신을 통해 모바일앱에서 사용할 데이터 모델과 로직을 분리하고자 한 것이다.

 

이제 화면 어플리케이션 소스가 위치하는 lib 폴더 안의 구조를 살펴 보자

lib/
|- bloc/
|- constants/
|- router/
|- screens/
|- utils/
|- widgets/
|- main.dart
  1. bloc : 어플리케이션의 상태 제어를 위한 Bloc 패턴이 구현되어 있습니다.
    - xxx_bloc : 이벤트를 특정 상태로 변환하는 로직
    - xxx_event : 이벤트에 대한 정의
    - xxx_state : 상태에 대한 정의
    - app_bloc_observer : 개발에 도움되는 로깅

  2. constants : 어플리케이션 모든 영역에 사용할 수 있는 상수.
    - /assets 디렉토리 하위의 파일 경로를 상수로 생성
    - 어플리케이션에서 사용되는 컬러값을 상수로 생성
    - Design System 의 기본 테마 표준을 코드로 작성한 Theme 정의

  3. router : 화면 Routing 관련 파일들

  4. screens : 화면단위로 디렉토리를 만들고 화면 구성에 필요한 파일들

  5. utils : 앱 내에서 사용될 유틸성 클래스

  6. widgets : 다양한 화면에서 공통으로 사용하는 위젯을 여기에 작성합니다.

  7. main.dart : 초기 어플리케이션 시작 시점

 

flutter 는 선언형 프로그래밍(Declarative programming) 이다.

선언형 프로그램에서는,&amp;amp;amp;amp;amp;amp;amp;nbsp; UI 는 상태 변화에 따라 자동 build 된다

선언형 프로그래밍이란 상태 변화에 따라 UI 가 변할 수 있도록 하는 것으로, 상태 관리를 위한 매커니즘을 잘 설계하고 고민해야만 한다.

 

그렇다면, 상태(State) 란 무엇인가?

위젯이 빌드 되는 동시에 읽을 수 있고, 위젯의 생명 주기동안 변경할 수 있는 정보를 말한다. 즉 특정한 상태가 변경되면, 특정한 상태가 변경된 위젯이 re-build 된다.

 

상태 관리 라이브러리는 상당히 많으나, 우리는 Bloc 상태 관리 라이브러리를 사용했다.

provider 와 같은 package 는 참조할 수 있는 문서도 많고 상대적으로 간단할 수 있으니 provider 역시 좋은 선택일 것이다.

 

https://bloclibrary.dev/#/

 

Bloc State Management Library

Official documentation for the bloc state management library. Support for Dart, Flutter, and AngularDart. Includes examples and tutorials.

bloclibrary.dev

React 그리고 React Native 역시 이부분은 마찬가지이다.

그래서 과거 React 경험이 있는 개발자라면, 선언형 프로그래밍과 Flutter 에 익숙해지는데 크게 문제 없을 것이다.


3. Design System to Widgets

flutter는 Google 의 Material Design 과 IOS의 Cupertino 패키지의 UI Components 를 Widget 으로 이미 구현되어 제공하고 있다.

우리는 기본적으로 Google 의 Material Design 기반으로 하고, GS SHOP 서비스만의 디자인으로 커스터마이즈 하였다.

 

https://material.io/develop/flutter

 

Material Design

Build beautiful, usable products faster. Material Design is an adaptable system—backed by open-source code—that helps teams build high quality digital experiences.

material.io

 


GS SHOP 에서 아래 이미지와 같이 커스터마이즈하였고, 이부분이 그대로 Flutter 코드화 하였다.

아래 이미지는 수 많은 UI Component 정의 중에 극히 일부에 해당한다.

 

GS SHOP Color Scheme
GS SHOP Typegraphy
GS SHOP Button Component
GS SHOP Product Component
GS SHOP Carousel Component

 

각 컨포넌트들은 아래와 같은 Hierarchical 구조로 구성되었다.

  • Foundation : Color, Typography, Layout, Icons 등
  • Element : Fundation 을 기반으로 정의된 UI Components (Button, AppBar, Menus, Checkbox, 상품정보 Card 등)
  • Template : Element 들의 묶음 Components (Page 단위)

Design System 에 정의한 모든 요소들은 Flutter 코드와 매핑되어 있어, 디자인 산출물이 실제 모바일 앱에 동일하게 구현될 수 있도록 했다.

이부분은 모바일 앱 사용 고객에게 일관적인 UI/UX 를 제공한다는 점에서 상당히 중요한 부분일 것이다.

게다가, 디자이너의 디자인 결과물이 개발 코드에 틀림 없이 적용되게 하는 수단이 될 것이며, 디자이너 역시 컴포넌트 재사용을 통한 생산성 역시 높아질 것으로 기대한다.


아직 하고 싶은 이야기가 많이 남아 있다.

 

개발하면서 골치 아팠던 Memory leak 문제, 이미지 로딩이 많은 서비스이다보니 고민해야 하는 부분이 너무 많았다

향후 계속 이야기 하기로 하고, 이제 최종 Flutter 로 개발된 화면을 보자

 

 

 

Landing 페이지, 로그인 페이지, 메인 전시 영역 (Tab 의 모든 전시 매장)과 상품 페이지등이 Flutter 로 되어 있고, 그외는 WebView 에서 HTML 페이지를 로딩하고 있는 상태이다.

 

점차 Flutter 영역을 늘려가고 있는 중이고, 더 많은 이야기는 다음에 계속하도록 하겠다.