[Flutter] Helper Method vs Widget Class

Minji Jeong·2025년 8월 30일
0

Flutter/Dart

목록 보기
15/15
post-thumbnail

Flutter Decoding - Helper method vs Widget class

사실 Helper method는 이미 오래전부터 지양되어 왔던 방식이라 알고는 있었지만, 이번에 위젯 빌드 관련해서 공부하다가 관련된 지식이기도 하고 한번 정리해보는것이 좋을 것 같아 이렇게 글로 남기게 되었습니다.

영상에서도 얘기하지만 결론부터 말하면, Helper Method 보단 Separate 위젯을 생성하는 방식이 권장되고 있습니다.

Helper Method

class BigUIElementState extends State<BigUIElement> {
  
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        _expensiveWidget1(),
        _expensiveWidget2(),
        _favoriteIcon()
      ]
    )
  }
  
  Widget _favoriteIcon() {
    return Positioned(
      top: 10,
      bottom: 10,
      child: IconButton(
        icon: ...,
        onPressed() => 
          setState(...)
      )
    )
  }
}

_favoriteIcon의 setState가 호출될 경우 부모 위젯인 BigUIElementState의 build()가 호출되며 불필요한 부분까지 리빌드됩니다.

BigUIElementState (State)
│
└── Stack
     ├── _expensiveWidget1()
     ├── _expensiveWidget2()
     └── _favoriteIcon()

Separate Widget

class BigUIElementState extends State<BigUIElement> {
  
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        _expensiveWidget1(),
        _expensiveWidget2(),
        const FavoriteIcon()
      ]
    )
  }
}

class FavoriteIcon extends StatefulWidget {
  const FavoriteIcon({super.key});
  
  _FavoriteIconState createState() => _FavoriteIconState();
}

class _FavoriteIconState extends State<FavoriteIcon> {
  bool isFav = false;

  
  Widget build(BuildContext context) {
    return Positioned(
      top: 10,
      bottom: 10,
      child: IconButton(
        icon: Icon(isFav ? Icons.favorite : Icons.favorite_border),
        onPressed: () => setState(() => isFav = !isFav),
      ),
    );
  }
}

FavoriteIcon을 별도의 클래스로 생성하면 FavoriteIcon은 위젯 트리에 속한 노드가 되어 별도의 build()를 가집니다. 때문에 setState가 호출되어도 부모 위젯에 영향을 미치지 않습니다.

BigUIElementState
│
└── Stack
     ├── _expensiveWidget1()
     ├── _expensiveWidget2()
     └── FavoriteIcon (StatefulWidget) 
          └── IconButton

더 정확한 이해를 위해 플러터의 화면 렌더링 방식에 대해 간략하게 얘기해보자면, 위젯 트리와 1대1로 매치된 엘리먼트 트리는 기존의 위젯 트리와 새로 생성된 위젯 트리의 각 위젯(노드)들을 비교하고, 변경된 부분이 있을 경우 필요한 부분에 한해서만 렌더 트리를 갱신합니다. 헬퍼 메서드의 경우 별도의 위젯이 아닌 하나의 위젯에 속해있기 때문에 상태가 변경되면 (setState가 호출되면) 헬퍼 메서드를 호출하는 위젯이 리빌드가 됩니다. 하지만 separate 위젯의 경우 고유의 타입, key를 가진 독립적인 노드로 위젯 트리에 존재하기 때문에 상태가 변경되어도 부모 위젯에 영향을 주지 않습니다.

그리고 또 하나의 장점은 가능한 경우 const 생성자를 사용할 수 있습니다. const 선언된 위젯의 경우 컴파일 타임에 생성된 인스턴스가 런타임에 재사용되기 때문에 성능에 이점을 줍니다.

References

https://docs.flutter.dev/perf/best-practices

profile
Software Engineer

0개의 댓글