Flutter Hook 입문하기

HyunHo Shin·2023년 6월 3일

Dart & Flutter

목록 보기
2/2

한줄 요약

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

Hook이란?

Hook 라이브러리는 Flutter의 StatelessWidget와 StatefulWidget을 대신하는 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개의 댓글