-
[Flutter] Flutter 쉽게 코딩하기 - flutter_hooks앱개발 2019. 9. 19. 14:51
Flutter Hooks: https://github.com/rrousselGit/flutter_hooks
Flutter Hooks는 React의 Hooks와 이를 분석한 미디엄 글을 보고 영감을 받아 flutter에 맞도록 hook 을 구현한 패키지이다.
Stateful
과Stateless
를 구분할 필요 없이 하나의HookWidget
으로 모든 위젯을 표현할 수 있도록 도와주며, 위젯 lifecycle 및 로컬 state 관리와 관련하여 다양한 편의성을 제공한다.본 글에서는 간단하게
flutter_hooks
패키지를 사용하는 법을 살펴보도록 한다.설치하기
패키지 설치는 여타 다른 패키지나 플러그인 설치와 동일하다. 실제 앱의 위젯을 구성하는데 사용될 위젯 패키지 이므로
pubspec.yaml
의dependencies
섹션에 추가하면 된다.# pubspec.yaml 파일 dependencies: flutter_hooks: any
이후 다른 패키지 설치와 동일하게
flutter pub get
을 수행하면 된다.예제
간단한 샘플 앱 2개를 보면서 사용법을 알아보자. 아래는
AnimationController
의 사용이 필요한StatefulWidget
을 다루는 예제이다.Animation
class AnimationWidget extends StatefulWidget { const AnimationWidget({Key key, @required this.duration}) : super(key:key); final Duration duration; @overrider _AnimationWidgetState createState() => _AnimationWidgetState(); } class _AnimationWidgetState extends State<Example> with SingleTickerProviderStateMixin { AnimationController _controller; @override void initState() { super.initState(); // 로직과 상관없는 코드 #1 - 컨트롤러 초기화 _controller = AnimationController(vsync: this, duration: widget.duration); } @override void didUpateWidget(Example oldWidget) { super.didUpdateWidget(oldWidget); if (widget.duration != oldWidget.duration) { _controller.duration = widget.duration; // 로직과 상관없는 코드 #2 - 업데이트 } } @override void dispose() { _controller.dispose(); // 로직과 상관없는 코드 #3 - 컨트롤러 해제 } @override Widget build(BuildContext context) { return Container(); } }
StatefulWidget
과 그에 따른 state를 정의하기 위한State
클래스, 그리고 애니메이션 사용을 위한 mixin 추가를 위한with
까지, 클래스 생성부터 부가적인 코드가 너무 많이 들어있는 것을 볼 수 있다. 또한AnimationController
의 안전한 할당/해제를 위한 lifecycle 메소드까지 들어가서, 실제 UI나 로직을 위한 코드가 들어가는build
메소드 외에 수십줄이 추가됨을 알 수 있다.flutter_hooks
는 이러한 부가적인 코드를 대신하여 실제 플러터 개발자는 온전히 UI와 로직에만 신경쓸 수 있도록 도와주는 위젯 패키지 이다. 기본적으로 Stateful이나 Stateless 위젯 대신HookWidget
을 상속하여 원하는 위젯을 개발하면 되고, 기타 state 관리나 생명주기 관리 등은 같이 제공 되는 기본Hooks
를 사용하거나,Hooks
를 커스텀하여 사용할 수 있다.위의 코드를 flutter_hooks 를 이용해 간소화 시킨 코드는 아래와 같다.
import 'package:flutter_hooks/flutter_hooks.dart'; class AnimationWidget extends HookWidget { const AnimationWidget({Key key, @required this.duration}):super(key:key); @override Widget build(BuildContext context) { final controller = useAnimationController(duration:duration); return Container( /* controller를 사용하는 코드 추가 */ ); } }
거의 1/3 수준으로 줄어든 코드량을 볼 수 있다. 이는 flutter_hooks가 미리 정의한
useAnimationController
가 필요한 작업을 모두 대신해주기 때문이다. 본 글은 소개를 위한 글이므로 구현에 대한 자세한 설명은 생략한다.데이터 변화에 따른 위젯 업데이트
플러터 기본 예제인 카운터를 비롯하여 다양한 위젯에서 데이터 변경에 따라 위젯을 업데이트 하고 싶은 경우
StatefulWidget
과setState
를 사용한다. 그러나 이러한 코드는 위의 애니메이션 예제에서 보여줬듯이 부수적인 코딩을 요구한다. flutter_hooks를 사용하면 이 또한 간단하게 줄일 수 있다.import 'package:flutter_hooks/flutter_hooks.dart' class CounterWidget extends HookWidget { @override Widget build(BuildContext context) { final counter = useState(0); return GestureDetector( onTap: () => counter.value += 2; child: Text("Counter는 현재 ${counter.value} 입니다."), ); } }
매우 짧은 코드로 카운터를 완성했다! 기본 제공되는
useState
는 실제로는ChangeNotifier
를 이용하여 구현된 것이다.주의점
아래의 코드는 절대로 사용해서는 안되는 flutter_hook 사용법이다. 요약하자면 hook을 사용하는 순서는 항상 동일해야 하고, 조건에 따라 hook 사용은 선택적으로 해서는 안된다는 것이다.
/* 금지 예제 1 ---------------- */ if (condition) { useSomeHooksHere(); // if나 switch 등 조건문을 이용한 선택적 hook사용은 절대 해서는 안된다. } /* ---------------- */ /* 금지 예제 2 ---------------- */ Widget buildOrSomeFunction(BuildContext context) { useSomeHooks(); if (condition) return Container(); useOtherHooks(); // 이 또한 조건에 따라서 사용이 안 될수도 있기 때문에 금지한다. }
이는 flutter_hooks를 사용할 때 발생하는 state 들을 큐나 배열 형태로 차례로 관리하기 때문으로, 자세한 이유나 구현 방식을 알고 싶은 경우 제일 처음 언급한 react hook을 분석한 미디엄 글, 혹은 실제 flutter_hooks 코드를 보길 바란다.
결론
flutter_hooks는 react hooks로부터 영감으로 받아 flutter에 맞게 구현한 것으로, 플러터에 추가적인 기능을 넣은 것이 아니고, 원래 개발자가 추가해야할 코드들을 미리 구현해둔 것이다. 이를 이용하면 매우 짧은 코드로 간결하게 앱을 구현할 수 있으므로, 한번쯤 사용해보는것을 매우 추천한다.
필자는 이걸 알게된 뒤로는 무조건 적으로 사용하며, 같은 개발자가 공개한 functional_widget 과 provider 도 함께 사용한다. provider는 너무 유명하므로 설명이 필요 없을 것이고, functional_widget도 한번 살펴보고 사용하길 바란다.
'앱개발' 카테고리의 다른 글
[Flutter/플러터] flutter_lints 알아보기 - 이쁜 코드 만들기 (1) 2022.02.23