Flutter Clone_Munto 포트폴리오

2023. 12. 27. 16:23카테고리 없음

반응형

2023.10 ~ 2023.12

 

GitHub Repository : https://github.com/wonjong214/Clone_Munto

 

#Flutter #Dart #AndroidStudio #Git #GitHub

 

프로젝트 개요

소셜링 APP인 MUNTO를 클론 코딩한 개인 프로젝트입니다. 프로젝트를 진행하면서 Provider와, State의 생애주기를 활용하여 데이터 관리하는 방법을 배웠습니다. 또한 ScrollView, TabBar, BottomNavigationBar, PageView, GridView 등의 위젯들을 이용하여 UI 스킬을 향상하였습니다.

 

 



아토믹디자인 패턴 적용으로 코드 반복성 ↓ 컴포넌트 재사용성 ↑

아토믹디자인 패턴을 적용하여 클린 구조를 구축하였습니다.

 

프로젝트 진행 초기에는 UI 작업할 때 비슷한 컴포넌트 들은 모듈화하지 않고, 그저 복사 붙여넣기 하면서 UI를 작업해 나갔습니다. 그렇게 가독성이 떨어져 코드를 작성하는 시간보다 코드를 읽는 시간과 코드를 수정하는 시간이 많아졌습니다. 개선이 필요하다는 생각이 들어 디자인 패턴을 찾아보다가 React에서 많이 사용되는 Presentation & Container 패턴과 Atomic 디자인 패턴에 대해 알게 되었습니다.

 

Presentation & Container 패턴을 사용하면 UI 관련 로직과 데이터 처리 로직을 분리하여 각 컴포넌트의 역할과 기능이 명확해져 코드를 이해하기 쉽고, 유지 보수성이 좋아지고, Presentation 컴포넌트를 재사용할 수 있습니다. 하지만 UI 관련 로직과 데이터 처리 로직 분리는 MVVM 패턴을 적용시킴으로써 해결이 되고, Presentation 단위 하나로는 Clone_Munto의 복잡한 화면을 재사용성이 좋은 컴포넌트로 분할할 수 없다고 생각했습니다.

 

따라서 UI를 atoms, molecules, organisms, templates, pages로 총 5단계로 나눌 수 있는 Atomic 디자인 패턴을 선택하였습니다. 

 

비슷한 모양과 동작을 하는 Button, Container, Text 등의 최소 단위 컴포넌트들을 일반화하여 재사용성이 높은 attom을 만들었습니다. 단 하나의 일을 수행하는 컴포넌트의 집합을 molecule, 사용자에게 공통된 기능을 제공하는 컴포넌트의 집합을 organism으로 정하였습니다. 작은 단계에서부터 컴포넌트를 조립해가면서 page를 완성하여 가독성이 좋고, 수정이 간단한 코드를 만들 수 있었습니다.



비동기 통신으로 생기는 에러 예외처리 및 Skeleton 컴포넌트 적용

 

비동기 통신으로 생기는 에러를 처리하고 사용자의 UX를 향상시켰습니다.

 

통신 기능과 page에 데이터를 바인딩 하는 기능을 한 thread에서 구현하면 thread가 통신 중일 때 사용자가 입력을 해도 화면이 동작을 안 하게 됩니다. 따라서 통신 기능을 주 thread에서 분리된 별도의 tread에서 비동기 통신을 구현하였습니다. 하지만 실행시켜보니 처음에 빈 화면을 출력하거나, Invalid value error가 발생하였습니다.

 

통신부터 tread flow를 따라가며 통신함수 내부, 위젯에 데이터를 할당하는 page widget 등에 중단점을 걸어 디버깅 한 결과 통신함수가 비동기 처리되어 데이터를 가져오기 전에 widget에 데이터를 할당하는 원인을 발견하였습니다.

 

해결책으로 bool형 flag를 하나 세워서 통신함수가 끝나면 flag의 값을 바꾸는 로직을 작성하였습니다. 데이터가 바인딩 되는 위젯은 flag의 값이 바뀌기 전에 Skeleton 컴포넌트로 대체되고 flag 값이 바뀌면 위젯에 데이터를 바인딩 시키도록 코드를 수정하였습니다.



TDD 방식 적용

테스트 코드 작성으로 개발의 생산성과 유지보수성 향상

 

보통 테스트는 90% 정도 거의 개발이 완료되었을 때 테스트를 하게 됩니다. 하지만 거의 완성된 상태에서 테스트를 하면 서버에서 데이터를 잘못 보내줬는지, 바인딩 로직에서 데이터 처리를 잘못했는지, UI에서 데이터를 잘못 바인딩 시켰는지 알아내기가 쉽지 않습니다.

 

각 페이지에 데이터를 바인딩 하는 Provider 클래스를 각 단위별로 유닛 테스트를 진행하여 에러가 발생할 경우 에러 발생 지점을 빠르게 파악할 수 있었습니다.




Provider를 사용하여 상태관리

 

프로젝트 규모와 BuildContext에 대한 학습을 하기 위해 선택

처음 상태 관리 패키지를 고를 때 사람들이 많이 이용하고 레퍼런스가 많은 패키지인 Provider, Bloc, GetX 3개 중에 고민했었습니다. 

 

우선 Bloc은 View와 비즈니스 코드의 분리가 확실한 대신 이벤트, 상태 클래스, cubit을 사용할 경우 상태별 cubit 클래스 작성 등 보일러플레이트 코드가 많습니다. 따라서 프로젝트의 규모가 클 경우 관리해야 될 이벤트 및 상태가 많으면 아예 분리해서 관리하는 것이 유지 보수성이 좋았겠지만, Clone Munto의 경우 상위 위젯에서 하위 위젯으로 상태를 공유하는 간단한 로직이면 충분했기 때문에 Bloc은 선택지에서 제외했습니다.

 

GetX는 Rx 타입과 obs 등의 반응형 상태 관리와 BuildContext에 대한 의존성이 없어 개발 편의성이 뛰어납니다. 하지만  flutter는 BuildContext를 사용한 의존성 주입이 주요 작동 원리이기 때문에 이를 사용 안 할 시 예상치 못한 곳에서 오류가 발생할 위험성이 있고, BuilContext를 통한 위젯 트리 구조를 학습하기 위해  GetX 또한 선택지에서 제외했습니다.

 

따라서 Bloc보다는 코드 수가 적으면서 BuildContext를 이용한 의존성 주입이 가능한 Provider를 선택하였습니다. Provider는 위젯 트리에서 최상단에 있는 위젯에 선언하여 그 하위에 있는 위젯에서 BuildContext를 통해 상태 클래스에 접근하여 상태를 관리하도록 설계하였습니다.



MVVM 패턴 적용

 

Provider를 활용하여 Model, ViewModel, View 간 의존성을 줄이고 유지보수성 향상

 

폴더 구조를 Model - ViewModel(provider) - View(screen)으로 나누고 Model은 ViewModel에서만 접근이 가능하고, ViewModel은 View에서만 접근이 가능하도록 구조를 설계하였습니다. 

 

Model은 데이터 구조와 데이터 변환, ViewModel은 이벤트 처리 및 데이터 처리, View는 UI 구성 역할을 맡게 되었습니다. 각 모듈의 역할이 명확해져 코드 변경 중에 오류가 생겨도 그 발생 지점을 쉽게 찾아 디버깅하기 용이했습니다.

 

반응형