Flutter Hook 입문하기

HyunHo Shin·2023년 6월 3일
3

Dart & Flutter

목록 보기
2/2

한줄 요약

  • Hook 패키지는 자주 사용하는 로직을 Hook으로 추상화하여 쉽게 쓸수 있게 만들어주는 패키지이다.

Hook이란?

Hook 라이브러리는 Flutter의 StatelessWidgetStatefulWidget을 대신하는 HookWidget을 제공하는 라이브러리 입니다. HookWidget을 사용하면 해당 위젯이 가진 Hook 함수를 사용할 수 있습니다.

StatefulWidget 내부에서 setState함수를 사용할 수 있는 것과 유사하다고 보면 됩니다.

Hook의 등장 배경

StatefulWidget의 단점 중 하나는 기본적인 로직을 재사용하기 힘들다는 점 입니다. 대표적인 예시가 바로 Animation 구현 입니다.

class Example extends StatefulWidget {
  final Duration duration;

  const Example({Key? key, required this.duration})
      : super(key: key);

  
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> with SingleTickerProviderStateMixin {
  AnimationController? _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: widget.duration);
  }

  
  void didUpdateWidget(Example oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.duration != oldWidget.duration) {
      _controller!.duration = widget.duration;
    }
  }

  
  void dispose() {
    _controller!.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Container();
  }
}

Animation을 구현할 때 Flutter은 코더에게 Animation을 구현하는 로직을 세세히 정의할 것을 요구합니다. 이 방식은 코더가 너무 많은 작업을 하게 만든다는 단점을 가지고 있습니다.

코더가 직접 관리해야 하는 부문

  • 위젯의 시작 관리: InitState
  • 위젯의 업데이트 관리: didUpdateWidget
  • 위젯의 삭제 관리: dispose()

또한, 이렇게 만든 로직은 다른 클래스에 재활용할 수 없습니다. 애니메이션을 위젯에 구현할 때마다 프로그래머는 애니메이션을 구현하는 로직을 반복해서 적어주어야 합니다.

로직의 재활용: Hook으로 해결하다

Hook은 이에 대한 해결책으로 ‘자주 사용하는 로직을 미리 정의하여 필요할 때 꺼내다 쓴다’를 제시하고 있습니다. 이렇게 미리 정의한 정의한 로직패턴을 해당 패키지에서는 Hook이라고 부릅니다.

미리 정의된 로직 = Hook

간단한 예시를 살펴보도록 하겠습니다.

class Counter extends StatefulWidget {
  
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _counter = 0;

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => setState(() {
        _counter++;
      }),
      child: Text(_counter.toString()),
    );
  }
}

위 예시는 화면을 탭했을 때 숫자가 늘어나는 간단한 위젯입니다. 해당 로직은 앱을 만들때 너무나도 흔하게 보는 패턴 중 하나입니다.

HookWidget은 해당 패턴을 이미 가지고 있습니다. 우리가 할 일은 HookWidget에 미리 정의된 함수를 가져와 해당 패턴에 적용하는 일입니다. HookWidget이 가진 로직은 다음 사이트에서 확인 가능합니다.

class Counter extends HookWidget {
  
  Widget build(BuildContext context) {
    final counter = useState(0);

    return GestureDetector(
      // automatically triggers a rebuild of the Counter widget
      onTap: () => counter.value++,
      child: Text(counter.value.toString()),
    );
  }
}

위 코드에서 새로운 변수를 만들고 변수의 변화를 추적하는 로직, hook,은 useState입니다. 위의 예시는 useState hook을 사용하여 숫자가 늘어나고, 해당 변화가 화면에 표시되는 로직을 최소한의 코드로 구현햇습니다.

그냥 StatefulWidget을 쓰는게 낫지 않나요?

위 코드를 보고 굳이 hook을 쓸 이유를 찾지 못할 수도 있습니다. 하지만 작성자의 입장이 아니라 코드를 읽는 사람의 입장으로 돌아가 보겠습니다.

int _counter = 0;

위 코드를 봤을 때 우리는 해당 변수의 역할을 오직 이름과 타입에서만 추측할 수 있습니다. 하지만 Hook으로 이를 표시한다면 더 많은 정보를 얻을 수 있습니다.

final counter = useState(0);

해당 counter를 hook으로 표현한다면 counter 변수가 State로서 변화되고, 추적되고 있다는 점을 쉽사리 알 수 있습니다. 한 줄의 코드가 더 많은 정보를 추상화하여 전달해 주고 있습니다.

정리

  • Hook 패키지는 자주 사용하는 로직을 Hook으로 추상화하여 쉽게 쓸수 있게 만들어주는 패키지이다.
  • Hook을 사용하면, 코드를 읽기 쉬워진다.
  • Hook을 사용하기 위해서는 기존의 StatefulWidget/StatelessWidget을 HookWidget으로 바꿔주기만 하면 된다.
profile
관심사가 다양한 사람

0개의 댓글