시리즈

[Flutter] GetX (사용법 설명 글 아님)

20210331
dart
flutter
getx

오늘 (3월 31일), GetX 가 pub.dev에서 최고 like 수가 많은 패키지가 되었다.


 

내가 like 몇 백 일때 부터 사용했던 플러그인이 불과 1~2년만에 이렇게 성장해서 기쁘다. (당시에는 비슷한 이름, 기능의 플러그인인 get_it 보다도 like가 낮았다.)


앞으로도 2위와 격차는 점점 벌어질 것이다.

코드 무단 표절이나 라이크 수 조작 같은 여러 논란들이 있지만 그런 이야기는 여기서는 할 필요가 없을 것 같다.


GetX

GetX의 최대 장점은 편의성이다. 바꿔 말하면 플러터의 귀찮은 것들을 한꺼번에 해결 해준다.

context로 부터 해방. 간편한 문법. 큰 사용자 커뮤니티. pubspec.yaml 에 의존성 라인이 짧아지고, 

문서도 깔끔하게 정리되어 있는 편이다.

주변을 보면 사용할 때의 만족도도 상당히 높았다.

초보자가 상태 관리를 처음 시작할 때 provider보다도 접근하기가 편하고, 한 번에 많은 기능을 얻게 된다는 점에서 추천할 만하다.

 

GetX를 사용하는 이유는 마치 플러터로 처음 앱 개발을 시작하는 이유와 비슷해 보인다.

안드로이드, iOS 뿐만 아니라 일상적으로 접하게 되는 거의 모든 플랫폼에서 사용 가능한 앱을 한꺼번에 개발하는 것.


Get 광신도

나는 플러터도 좋아하고, GetX도 좋아하고 실 서비스 개발에서도 사용하고 있다.

하지만 광신도들이 생겨나고 있는 것 같아서 안타깝다.


이 광신도들의 주장은 이거다.

어차피 플러터랑 GetX로 다 되는데 다른거 왜 함?

 

사실 이게 완전히 허무맹랑한 소리였다면 자연스럽게 정화되었겠지만,

플러터와 GetX가 정말로 만능에 가까운 걸출한 툴 들이기 때문에 이 논리가 먹혀들어간다. 

특히, 플러터를 시작한 지 얼마 안된 사람들이 Provider 쓸까요? GetX 쓸까요? 물으면 광신도들이 저 주장을 하는데,

이걸 반박하기에는 해야 할 말이 많고, 사실 실제로 웬만한 프로젝트에서는 GetX로 충분하고, KISS 원리에 의해서 단순함이 아주 큰 미덕이기 때문에

결국 결론이 GetX 무조건! 최고! 로 끝나게 된다. 어설프게 반박하다가는 "GetX 안 써보고 또 저러네..." 이런 소리 듣기 십상이다.

국밥을 좋아하는 그 분들이 생각난다.

 

놀랍게도 레딧이나 플러터 공식 디스코드에서도 허구하면 riverpod vs Get 대결이 벌어진다.

빠가 까를 만든다고 했던가... 나는 열렬한 GetX 비밀신도이지만, 저런 광신도들은 너무 싫다. 무조건적으로 GetX가 옳다고 주장하기 때문에 건전한 토론을 못하게 하고 순수한 입문자들을 또 다시 광신도로 만든다. 

반대로 무조건 GetX는 싫다고 하는 사람들(Get 혐오자) 도 너무 싫다.

우린 모든 것에 장단점이 있다는 것을 인정하고, 필요한 곳에 알맞는 도구를 이용해서 만들어야 한다.


장점은 굳이 여기서 더 설명할 필요 없이 써보면 알게 되므로 한계점만 말하겠다.


Get의 한계

GetX의 단점은 여러 가지가 있다. Cargo Cult 프로그래밍 을 하지 않으려면 사용하는 도구의 세부적인 구현을 알거나

최소한 한계점 정도는 명확히 알고 있어야 한다.

GetX/lib


GetX는 지원하는 기능이 많다. GetX라는  모노레포 안에 저런 패키지들이 다 들어가 있다. 

그렇게 위대한 코드가 들어있는 것은 아니다. Stream와 Rx를 알고 기본적인 다트와 플러터에 대한 지식이 있다면 내부 코드를 쉽게 분석할 수 있는 수준이다. 

 

많은 이슈

ecosystem 자체가 크기 때문에 이슈가 많이 발생하게 된다.





이슈가 많은 만큼 PR도 많지만 결국 개인이 관리하는 레포기 때문에 PR 리뷰를 혼자하게 된다.

이렇게 반론할 수 있다. 기능이 많은 만큼 당연히 이슈도 많은거 아닌가?

맞는 말이다. 그러면 일단 이슈가 많다는 것과 이슈 처리가 상대적으로 늦다는 것을 인정하는 셈이다.

 

모노레포

개인적으로 GetX에 대해서 가장 아쉬운 점은 레포를 분리했으면 어땠을까 하는 것이다. 선택적으로 필요한 만큼 쓰는 거면 Get 혐오자들이 지금보다 많이 줄었을 것이다. 어차피 미들웨어들인데 분리하려면 충분히 분리할 수 있었을 것이다.

지금은 get을 통으로 flutter pub get 해오는 방법 밖에 없다. pub에서 get을 가져온 다음에 import 할때는 기능 별로 분리해서 import 하는 것은 가능하다.

모노레포라서 좋아하는 사람들도 있으니 취향에 맡긴다.


Get Storage

Get_storage 라는 Get 생태계의 key-value 저장소 패키지가 있는데 광신도들은 벤치마크 그래프만 보고 hive 왜 쓰냐고 우리 GS는 너무 빨라서 await도 필요없다~~ 이러는데 문서를 볼 때 그림 말고 글도 읽을 필요가 있다.

 

논란의 벤치마크

 

거기 바로 밑의 문단에 레포 주인이 직접 GS는 데이터베이스가 아니라고 Hive나 Sqflite 쓰라고 해놨다.


 
https://github.com/jonataslaw/getx/issues/744 를 보면 Hive를 대체할 수 없다고 본인이 밝혔다.
 

 GS 코드를 보면 알겠지만 동기적으로 메모리에 캐시하고 ScheduleMicrotask() 를 이용해서 File에다가 쓰는 것 뿐이다. 읽고 쓰기가 동기적으로 메모리에서 이루어지기 때문에 특정 시간에 File와 메모리에 있는 데이터가 같다고 보장하지 못한다.
게다가 메모리 캐시가 static 변수이기 때문에 hive처럼 box를 여러 개 놓고 쓰지도 못한다.


어려움

놀랍게도 GetX는 어렵다.
GetX를 제대로 사용할 만큼 배우고 나면 배우는 데 걸린 시간이 아까워서라도 돌아가지 못한다.
 
우선 Rx는 필수적으로 알아야한다.
 
그리고 몰라도 됐던 수 많은 위젯들, 클래스들...GetView, GetWidget...GetxController, GetMicrotask... 
이런 것들을 사용하지 않더라도 pub get으로 로컬에 침투해있다.
이게 KISS 원리에 맞는걸까...

유틸 사용 넛지

비슷한 맥락에서 모노레포이기 때문에 새로운 기능을 필요로 할 때 Get 생태계 안에서 찾게 된다.
만약에 Get을 사용 중이고 반응형 UI가 필요하다면 뭘 선택하게 될까?


https://flutter.dev/docs/development/ui/layout/adaptive-responsive 에 있는 쉬운 길을두고
 
예제도 거의 없는 GetResponseView 나 ResponsiveScreen을 먼저 찾게 된다.
'Get' 이 붙어있고 별도로 패키지를 찾을 필요가 없기 때문에,
그리고 Get 쓰는데 반응형 UI 어떻게 할까요? 하면 다른 광신도들이 저런거 추천해준다.
 
다른 유틸들도 비슷하다.


마지막에 너무 Get 단점만 말한 것 같지만 Get은 굉장히 편리한 스위스 칼이다. Get을 썼으면 이 글 하나 읽을 시간에 앱 하나 더 만들 수 있었다.

결론은 무조건 좋은 건 없으니 시야를 넓게 보고 여러가지 상황에 맞는 도구를 썼으면 좋겠다는 점.

.

piano (press key Q)

Categories

flutter ( 82 ) dart ( 34 ) android ( 32 ) kotlin ( 11 ) plugin ( 8 ) provider ( 8 ) vim ( 7 ) bloc ( 6 ) iOS ( 6 ) state management ( 6 ) 플러터 ( 6 ) PS ( 5 ) algorithm ( 5 ) architecture ( 5 ) async ( 5 ) getx ( 5 ) java ( 5 ) API ( 4 ) BOJ ( 4 ) class ( 4 ) daily ( 4 ) git ( 4 ) golang ( 4 ) memo ( 4 ) riverpod ( 4 ) state ( 4 ) stream ( 4 ) test ( 4 ) web ( 4 ) widget ( 4 ) windows ( 4 ) HTTP ( 3 ) androidX ( 3 ) app state ( 3 ) context ( 3 ) crash ( 3 ) db ( 3 ) editor ( 3 ) error ( 3 ) extension ( 3 ) github ( 3 ) hive ( 3 ) ide ( 3 ) package ( 3 ) pubspec ( 3 ) python ( 3 ) syntax ( 3 ) vscode ( 3 ) app icon ( 2 ) await ( 2 ) chocolatey ( 2 ) consumer ( 2 ) cp949 ( 2 ) deployment ( 2 ) dev ( 2 ) flavor ( 2 ) gesture ( 2 ) globalkey ( 2 ) go ( 2 ) google ( 2 ) hack ( 2 ) js ( 2 ) json ( 2 ) key ( 2 ) keystore ( 2 ) list ( 2 ) listview ( 2 ) lock ( 2 ) mac ( 2 ) map ( 2 ) navigation ( 2 ) nosql ( 2 ) project ( 2 ) pub ( 2 ) recyclerview ( 2 ) rxdart ( 2 ) sdk ( 2 ) selector ( 2 ) setting ( 2 ) size ( 2 ) soc ( 2 ) synchronized ( 2 ) tdd ( 2 ) tip ( 2 ) version ( 2 ) viewmodel ( 2 ) vundle ( 2 ) webview ( 2 ) xcode ( 2 ) yaml ( 2 ) ( 2 ) 플러터 단점 ( 2 ) 16.0 ( 1 ) 2.0 ( 1 ) 2023 ( 1 ) AATP2 ( 1 ) ChangeNotifierProvider ( 1 ) Example ( 1 ) Guava ( 1 ) ImageReader ( 1 ) Mo's algorithm ( 1 ) OAuth2 ( 1 ) OpenGL ( 1 ) Oreo ( 1 ) ProgressBar ( 1 ) REST API ( 1 ) Trie ( 1 ) activity ( 1 ) adaptive ( 1 ) android P ( 1 ) android context ( 1 ) android11 ( 1 ) apktool2 ( 1 ) app exit ( 1 ) append ( 1 ) appicon ( 1 ) arkit ( 1 ) array ( 1 ) asciidoc ( 1 ) async * ( 1 ) async* ( 1 ) audio ( 1 ) authorization ( 1 ) await for ( 1 ) behaviorsubject ( 1 ) beta ( 1 ) binary ( 1 ) binarysearch ( 1 ) blender ( 1 ) book ( 1 ) bottomsheet ( 1 ) break ( 1 ) broadcast ( 1 ) browser ( 1 ) bubbles ( 1 ) bug ( 1 ) build ( 1 ) buildcontext ( 1 ) buildnumber ( 1 ) bundle ( 1 ) button ( 1 ) bytecode ( 1 ) cache ( 1 ) camera2 ( 1 ) cameramanager ( 1 ) cd ( 1 ) chrome ( 1 ) ci ( 1 ) circle ( 1 ) clean ( 1 ) clean architecture ( 1 ) cli ( 1 ) clip ( 1 ) clipboard ( 1 ) cloud ide ( 1 ) cmdlet ( 1 ) code ( 1 ) coding test ( 1 ) command ( 1 ) comparator ( 1 ) complexity ( 1 ) concurrency ( 1 ) conditional ( 1 ) const ( 1 ) constraint ( 1 ) constraintlayout ( 1 ) controlc ( 1 ) controlv ( 1 ) converter ( 1 ) copy ( 1 ) copy project ( 1 ) coupling ( 1 ) coverage ( 1 ) cp ( 1 ) css ( 1 ) cupertino ( 1 ) cursor ( 1 ) cv ( 1 ) data class ( 1 ) data structure ( 1 ) dataBinding ( 1 ) database ( 1 ) debounce ( 1 ) decompile ( 1 ) delegate ( 1 ) deno ( 1 ) design pattern ( 1 ) development ( 1 ) device ( 1 ) di ( 1 ) dialog ( 1 ) dio ( 1 ) drawable ( 1 ) drug ( 1 ) emmet ( 1 ) encoding ( 1 ) english ( 1 ) entries ( 1 ) environment ( 1 ) equality ( 1 ) equatable ( 1 ) euc-kr ( 1 ) euckr ( 1 ) exit ( 1 ) expand ( 1 ) expanded ( 1 ) export ( 1 ) extension method ( 1 ) facade ( 1 ) fake ( 1 ) field ( 1 ) figma ( 1 ) final ( 1 ) fixed ( 1 ) flutter pub ( 1 ) flutter web ( 1 ) flutter_inappwebview ( 1 ) flutter_test ( 1 ) flutterflow ( 1 ) fold ( 1 ) fonts ( 1 ) form ( 1 ) frame ( 1 ) future ( 1 ) gestureDetector ( 1 ) gestureRecognizer ( 1 ) gesturearena ( 1 ) get-command ( 1 ) get_cli ( 1 ) getbuilder ( 1 ) getx단점 ( 1 ) gitignore ( 1 ) glut ( 1 ) google fonts ( 1 ) gopath ( 1 ) goto ( 1 ) gradient ( 1 ) graphics ( 1 ) gvim ( 1 ) hackaton ( 1 ) hash ( 1 ) hashmap ( 1 ) hot reload ( 1 ) how to ( 1 ) html ( 1 ) i18n ( 1 ) icon ( 1 ) id ( 1 ) impeller ( 1 ) implementation ( 1 ) import ( 1 ) indicator ( 1 ) inkwell ( 1 ) interrupt ( 1 ) intl ( 1 ) introduction ( 1 ) io ( 1 ) isar ( 1 ) iterable ( 1 ) iteration ( 1 ) javascript ( 1 ) julia ( 1 ) juno ( 1 ) jupyter ( 1 ) kakaomap ( 1 ) keytool ( 1 ) korean ( 1 ) kotlin syntax ( 1 ) l10n ( 1 ) lambda ( 1 ) language ( 1 ) layer ( 1 ) layout ( 1 ) lineageOS ( 1 ) localkey ( 1 ) localtoglobal ( 1 ) long list ( 1 ) ls ( 1 ) mac osx ( 1 ) markdown ( 1 ) markup ( 1 ) material ( 1 ) method ( 1 ) microtask ( 1 ) migrate ( 1 ) mintlify ( 1 ) mock ( 1 ) module ( 1 ) monitor ( 1 ) moor ( 1 ) mouse ( 1 ) mouseregion ( 1 ) multiplatform ( 1 ) multiset ( 1 ) multithread ( 1 ) mutable ( 1 ) mvvm ( 1 ) new ( 1 ) node ( 1 ) nodejs ( 1 ) nosuchmethod ( 1 ) null-safety ( 1 ) numberformat ( 1 ) nvim ( 1 ) object ( 1 ) objectbox ( 1 ) objectkey ( 1 ) obx ( 1 ) online ide ( 1 ) operator ( 1 ) orientation ( 1 ) parabeac ( 1 ) parse ( 1 ) paste ( 1 ) path ( 1 ) pattern ( 1 ) pitfall ( 1 ) play store ( 1 ) pod ( 1 ) podfile ( 1 ) pointer ( 1 ) pointers ( 1 ) powershell ( 1 ) private ( 1 ) programming ( 1 ) pull to refresh ( 1 ) puzzle ( 1 ) pycharm ( 1 ) realitykit ( 1 ) recursion ( 1 ) reduce ( 1 ) reference ( 1 ) regex ( 1 ) regular expression ( 1 ) release note ( 1 ) renderbox ( 1 ) renderobject ( 1 ) repl ( 1 ) repository ( 1 ) response ( 1 ) rm ( 1 ) rotue ( 1 ) round ( 1 ) run ( 1 ) scope ( 1 ) scroll ( 1 ) search ( 1 ) server ( 1 ) serverless ( 1 ) service ( 1 ) sharp ( 1 ) singlerepo ( 1 ) singleton ( 1 ) sketch ( 1 ) sliver ( 1 ) sliverlist ( 1 ) snippets ( 1 ) sogae ( 1 ) sorting ( 1 ) source ( 1 ) sparse ( 1 ) sparse array ( 1 ) spec ( 1 ) split ( 1 ) sqflite ( 1 ) sqlite ( 1 ) sqrt decomposition ( 1 ) stateful ( 1 ) statefulwidget ( 1 ) step ( 1 ) stepper ( 1 ) string ( 1 ) stringbuffer ( 1 ) stringbuilder ( 1 ) studio ( 1 ) study ( 1 ) sub-directory ( 1 ) svn ( 1 ) swiftui ( 1 ) swipe to refresh ( 1 ) system_alert_window ( 1 ) system_cache ( 1 ) systemnavigator ( 1 ) tail recursion ( 1 ) tailrec ( 1 ) tap test ( 1 ) text ( 1 ) texteditingcontroller ( 1 ) textfield ( 1 ) texttheme ( 1 ) themedata ( 1 ) then ( 1 ) thread ( 1 ) throttle ( 1 ) time ( 1 ) tool ( 1 ) tools ( 1 ) tooltip ( 1 ) ts ( 1 ) tutorial ( 1 ) typescript ( 1 ) ui ( 1 ) unittest ( 1 ) update ( 1 ) usb ( 1 ) utf8 ( 1 ) ux ( 1 ) valuekey ( 1 ) variable ( 1 ) vector ( 1 ) versioncode ( 1 ) very_good ( 1 ) view ( 1 ) vim plugin ( 1 ) vimrc ( 1 ) virtualenv ( 1 ) wasm ( 1 ) web app ( 1 ) webview_flutter ( 1 ) while ( 1 ) widget tree ( 1 ) window ( 1 ) wsl ( 1 ) yield ( 1 ) 강의 ( 1 ) 개발 ( 1 ) 개발 공부 ( 1 ) 공부법 ( 1 ) 그래픽스 ( 1 ) 꼬리재귀 ( 1 ) 꿀팁 ( 1 ) 데노 ( 1 ) 두줄 ( 1 ) 디노 ( 1 ) 번역 ( 1 ) 블록 ( 1 ) 상태관리 ( 1 ) 실험 ( 1 ) 안드로이드 ( 1 ) 안드로이드프로젝트 ( 1 ) 안드로이드프로젝트복사 ( 1 ) 어이없는 ( 1 ) 조건부 임포트 ( 1 ) 주절주절분노조절실패의식으흐름 ( 1 ) 패키지 ( 1 ) 프로젝트복사 ( 1 ) 플러그인 ( 1 )