뚝딱뚝딱 모바일

[Flutter] 아키텍처에 대한 고민 (2) - 익숙해지니 보이는 것들 본문

실무 이야기

[Flutter] 아키텍처에 대한 고민 (2) - 익숙해지니 보이는 것들

규석 2023. 12. 7. 20:11
 

[Flutter] 아키텍처에 대한 고민 (1) - 처음 해보는 Flutter

안녕하세요! 이번에 적으려고 하는 내용은 제가 Flutter 개발을 시작하면서, 어떤 아키텍처들을 구성하고, 고민했는지에 대한 내용을 적어보려고 합니다. 한 3편 정도의 글이 나오지 않을까 생각

nkstar-ios.tistory.com

위 글에서 이어집니다.


음... 어... 아...? 뭔가 이상하다

신규로 만드는 앱에서도 이전 글에서 말한 아키텍처를 적용하여, 코드를 짜기 시작하였습니다. Flutter가 익숙해지고, 코드도 손에 익을 무렵, 점차 코드를 작성하면서 불편함이 생기기 시작했습니다.

 

  1. ViewModel이 필요 없는 View에 관해서 생각을 못했다.
  2. bindInput(), bindOutput() 함수들이 비대해지기 시작했다.
  3. 단방향이라 생각하였으나, 어느샌가 양방향적인 잘못된 방법으로 사용하고 있었다. 심지어 인지조차 늦었다.
  4. Riverpod이 가끔씩 State 변경이 안될 때가 있다. 찾아보았지만, 어느 상황에서 일어나는 지조차 모르겠다.
  5. 순차적으로 흘러가는 로직이 있다면, 그중 한 로직만 빼서 사용하기엔, 흐름이 불편해진다.

물론, 제가 조금만 더 신경쓰면 해결되는 문제가 있지만, 아키텍처는 개발자로 하여금 규칙을 강제하여야 한다 생각하였기에, 이러한 구조는 잘못된 상태라고 생각하였습니다. 구조적 문제뿐만 아니라, Riverpod에 대한 자잘한 버그와 제대로 사용하고 있냐는 의문점이 들었습니다. Riverpod에 대한 자료들은 과거 자료들이 많았고, 이는 지금 코드와 비교할 수 없을 정도로 많이 달라있어 코드를 작성함에 있어 확신을 받을 수 없었습니다.

다시 찾아보고 공부하자

다시 처음으로 돌아가자라는 생각으로 다시 상태관리 라이브러리부터 찾아보았습니다. GetXBloc에 대해 공부하였고, Flutter가 익숙해진 만큼 처음과는 다른 시야로 고민을 가지게 되었습니다.

둘 다 괜찮은 것 같은데, 어떤 걸 사용하지?

 

GetX를 사용하게 되면, GetX만으로 처리 가능한 부분이 늘어나니 개발 속도가 빨라지지만 GetX에 대한 의존성이 매우 커질 것입니다.

Bloc을 사용하면, 처음 아키텍처를 고민할 때 얻고자 했던 점을 얻을 수 있지만, 만들어야 하는 파일과 러닝커브로 인해 개발 속도가 느려진다는 단점이 있었습니다.

처음엔 GetX로 진행하려 하였습니다. GetX를 사용하게 되면 Router, Network, State, DI 등 처리가 쉬워지고, 기획이 고정적이지 않고, 자주 바뀌었기에 빠른 개발을 우선하려 하였습니다. 하지만 마음 속 한편에는 찝찝함이 계속 남아있었고, 리팩토링을 시작하기 전까지도 계속 고민하였습니다.

결단을... 결단을...

결국, Bloc을 바탕으로 다시 짜보기로 결정하였습니다! 개발 속도는 손을 좀 더 빨리 놀리면 되는 것이니 (아니면 야근을 하면 됩니다...), 제가 원하는 코드 스타일에 조금 더 가깝게 다가갈 수 있도록 Bloc을 선택하였습니다. 그렇게 전, Bloc을 바탕으로 Android 개발 공부하면서 익혔던 Clean Architecture 개념을 섞어서 더욱 더 탄탄한 아키텍처를 구상하였습니다.

쉽고 간단하게 그러나 탄탄하게

제일 어려운 말을 목표로 삼고 구상을 시작하였습니다. 

Clean Architecture. 이에 대해선 다른 포스팅으로 설명하겠습니다.

Data - Domain - Presentation 3개의 Layer부터 정리해보았습니다.

Data

현재 앱에서는 REST API 통신으로 가져오는 Data와 LocalStorage에 저장된 Data, 이 두 Data를 Data 계층에 두고 사용

Domain

Data 계층의 원시 Data가 가공될 필요가 없고, implement를 통한 추상화를 하기엔 앱의 규모가 작다 판단하여, Data 계층의 Data를 가져오는 Repository를 각 기능에 맞게 만들어 사용. 각 Repository는 DI(get_it 라이브러리)를 사용하여 싱글톤으로 구성.

Presentation

UI와 각 UI들의 로직과 State들을 처리해 줄 Bloc(또는 Cubit)으로 ViewModel을 대신함. 각 Bloc에서는 Data에 접근하기 위해 Repository를 이용.

 

이렇게 구성하여 계층에 대한 의존성을 줄이지만, 코드 추적을 할 수 있을 정도에서 로직과 UI의 분리를 극대화하려 하였습니다. 현재까지는 이렇게 아키텍처를 구성한 것에 대해 매우 좋은 평가를 내리고 있습니다. 코드도 Bloc을 사용함으로써 전보다 깔끔해졌고, 처음 보는 사람이 보더라도, 확실하게 눈에 익히기 쉬워졌습니다.


이렇게 제가 Flutter를 시작하면서 고민했던 아키텍처에 대해 적어보았습니다. 역시 모든 아키텍처에는 정답과 오답이 없고, 본인에게 맞는 상황에 따라 구성하는 것이 가장 좋은 것 같습니다. 또한, 개발자는 좋은 아키텍처를 구성하기 위해서 항상 노력하고, 공부하는 것이 코더가 아닌 개발자가 되는 길 같습니다.