InheritedWidget

샤워실의 바보·2024년 2월 16일
0
post-thumbnail

InheritedWidget은 Flutter에서 상태 관리의 기초를 제공하는 중요한 컨셉 중 하나입니다. 복잡한 위젯 트리에서 특정 위젯의 상태 변경이 필요할 때, 모든 상위 위젯을 거치지 않고도 직접 필요한 데이터에 접근할 수 있게 해주는 기능을 합니다. 이러한 접근 방식은 데이터 전달 과정을 단순화하고, 성능 최적화에 도움을 줍니다.

동작 원리 간략 설명

InheritedWidget을 활용하기 위해, 먼저 InheritedWidget을 확장하는 클래스를 정의해야 합니다. 이 클래스는 반드시 child 위젯을 포함해야 하며, 이를 통해 InheritedWidget의 자손이 되는 모든 위젯은 해당 위젯의 데이터에 접근할 수 있습니다.

예제 코드

class CustomColorProvider extends InheritedWidget {
  const CustomColorProvider({
    Key? key,
    required this.color,
    required Widget child,
  }) : super(key: key, child: child);

  final Color color;

  static CustomColorProvider? maybeOf(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<CustomColorProvider>();
  }

  static CustomColorProvider of(BuildContext context) {
    final CustomColorProvider? result = maybeOf(context);
    assert(result != null, 'No CustomColorProvider found in context');
    return result!;
  }

  
  bool updateShouldNotify(CustomColorProvider oldWidget) => color != oldWidget.color;
}

updateShouldNotify 메서드는 InheritedWidget이 업데이트될 때 자손 위젯에게 알릴지 여부를 결정합니다. 이 메서드는 데이터가 변경되었을 때만 자손 위젯을 다시 빌드해야 하는 경우에 유용합니다.

사용 예

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return CustomColorProvider(
      color: Colors.blue,
      child: Scaffold(
        appBar: AppBar(title: Text('Inherited Widget Example')),
        body: Center(
          child: TextButton(
            onPressed: () {},
            child: Text(
              'Click Me',
              // CustomColorProvider를 통해 색상에 접근
              style: TextStyle(color: CustomColorProvider.of(context).color),
            ),
          ),
        ),
      ),
    );
  }
}

위의 예시에서 CustomColorProvider 위젯은 자손 위젯들에게 color 데이터를 제공합니다. HomePage 내부에서 CustomColorProvider.of(context).color를 호출함으로써, 해당 컬러 데이터에 접근하고 있습니다. 이 방식은 필요한 데이터를 직접 상위에서 받아오는 것이 아닌, InheritedWidget을 통해 접근하므로 효율적인 데이터 관리가 가능합니다.

결론

InheritedWidget은 Flutter에서 데이터를 효율적으로 관리하고, 위젯 트리 전반에 걸쳐 데이터를 공유할 수 있는 강력한 메커니즘을 제공합니다. 상태 관리가 필요한 위젯이 위젯 트리의 깊은 곳에 위치하더라도, InheritedWidget을 사용함으로써 필요한 데이터에 바로 접근할 수 있게 되며, 이는 앱의 성능과 개발 효율성을 높여줍니다.

updateShouldNotify 메서드는 InheritedWidget을 활용할 때 중요한 역할을 수행합니다. 이 메서드는 InheritedWidget이 업데이트될 때 자식 위젯이 재빌드될 필요가 있는지 여부를 결정합니다. 간단히 말해, 이 메서드는 InheritedWidget의 현재 인스턴스와 이전 인스턴스를 비교하여, 관련된 데이터가 변경되었는지 확인합니다. 데이터에 변화가 있을 경우 true를 반환하여 Flutter 프레임워크에 자식 위젯들을 재빌드하도록 지시하고, 변화가 없다면 false를 반환하여 재빌드를 방지합니다.

updateShouldNotify의 역할

  • 재빌드 최적화: updateShouldNotify는 앱의 성능을 최적화하는 데 중요한 역할을 합니다. 불필요한 재빌드를 방지함으로써, 리소스 사용을 줄이고 앱의 반응 속도를 개선할 수 있습니다.
  • 데이터 변화 감지: 이 메서드는 InheritedWidget이 관리하는 데이터가 변경되었는지 확인하는 기능을 수행합니다. 데이터가 변경되었다면, 이는 상태에 의존하는 위젯들이 새로운 데이터로 업데이트되어야 함을 의미합니다.

of 메서드의 사용

InheritedWidget을 사용하는 일반적인 패턴 중 하나는 of라는 정적(static) 메서드를 정의하여, 해당 InheritedWidget의 인스턴스에 쉽게 접근할 수 있도록 하는 것입니다. 이 메서드는 주어진 BuildContext를 사용하여 위젯 트리에서 가장 가까운 InheritedWidget의 인스턴스를 찾아 반환합니다.

of 메서드의 구현

static MyInheritedWidget of(BuildContext context) {
  final MyInheritedWidget? result = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
  assert(result != null, 'No MyInheritedWidget found in context');
  return result!;
}
  • 접근 용이성: of 메서드를 사용하면, 위젯 트리 어디에서나 손쉽게 InheritedWidget을 통해 공유된 데이터에 접근할 수 있습니다.
  • 안정성 검증: 만약 요청한 InheritedWidget이 위젯 트리 내에서 찾을 수 없는 경우, 즉 반환값이 null인 경우, 프로그램은 즉시 오류를 발생시키며 이는 개발 과정에서 실수를 빠르게 발견하고 수정할 수 있도록 돕습니다.

사용 예시

InheritedWidget의 자식 위젯이 특정 데이터를 필요로 할 때, of 메서드를 호출하여 해당 데이터를 포함하고 있는 InheritedWidget의 인스턴스에 직접 접근할 수 있습니다. 이 방식은 데이터를 필요로 하는 위젯이 위젯 트리의 깊은 곳에 위치해 있어도, 중간에 있는 다른 위젯들을 통해 데이터를 전달할 필요 없이 직접 데이터에 접근할 수 있게 해줍니다.

Widget build(BuildContext context) {
  final myData = MyInheritedWidget.of(context).data;

  return Text(myData);
}

이 예시에서, MyInheritedWidget.of(context) 호출을 통해 현재 BuildContext에 가장 가까운 MyInheritedWidget 인스턴스에 접근하고, 그 인스턴스가 관리하는 데이터를 가져와서 사용합니다. 이러한 방식은 데이터의 흐름을 더 명확하게 하고, 위젯 트리의 재구성 없이도 상태 관리를 용이하게 합니다.

이 코드는 InheritedWidget을 사용하여 Flutter 앱 내에서 데이터를 효율적으로 상속하고 접근할 수 있는 방법의 일부입니다. MyInheritedWidget 클래스 내에 정의된 of 정적 메서드는 특정 BuildContext에 대해 가장 가까운 MyInheritedWidget 인스턴스를 찾아 반환합니다. 이 메서드는 위젯 트리를 통해 데이터를 직접 전달하지 않고도, 상태나 정보를 필요로 하는 위젯이 쉽게 해당 데이터에 접근할 수 있도록 해줍니다.

코드 분석

static MyInheritedWidget of(BuildContext context) {
  final MyInheritedWidget? result = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
  assert(result != null, 'No MyInheritedWidget found in context');
  return result!;
}
  • static MyInheritedWidget of(BuildContext context): 이 메서드는 MyInheritedWidget 타입의 인스턴스를 반환합니다. 정적(static) 메서드이므로 클래스 인스턴스화 없이 직접 호출할 수 있습니다. BuildContext 매개변수는 현재 위젯의 위치를 나타내며, 이를 통해 위젯 트리에서 원하는 InheritedWidget을 찾습니다.

  • final MyInheritedWidget? result = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();: BuildContextdependOnInheritedWidgetOfExactType 메서드를 사용하여, 주어진 타입(MyInheritedWidget)의 인스턴스를 현재 context에서 가장 가까운 위치에 있는 것을 찾습니다. 이 메서드는 요청한 타입의 InheritedWidget이 존재하지 않을 경우 null을 반환할 수 있습니다.

  • assert(result != null, 'No MyInheritedWidget found in context');: assert 문은 개발 모드에서만 활성화되며, 조건이 false일 경우 에러 메시지를 출력하고 실행을 중단합니다. 여기서는 resultnull이 아닌지 검사하여, MyInheritedWidget 인스턴스가 정말로 존재하는지 확인합니다. MyInheritedWidget이 위젯 트리에 없으면 에러 메시지를 출력합니다.

  • return result!;: ! 연산자는 result 변수가 null이 아님을 보증합니다. assert를 통과했다면 이 시점에서 resultnull이 아니므로, MyInheritedWidget 인스턴스를 안전하게 반환할 수 있습니다.

사용 목적 및 이점

  • 직접적인 데이터 접근: 이 패턴을 사용함으로써, 위젯은 중간에 있는 다른 위젯들을 통해 데이터를 전달받지 않고도 필요한 데이터에 직접 접근할 수 있습니다. 이는 코드의 복잡성을 줄이고, 데이터 접근을 더 명확하게 합니다.
  • 성능 최적화: InheritedWidget은 데이터가 변경될 때만 관련된 위젯을 재빌드하도록 할 수 있어, 앱의 성능을 최적화하는 데 도움이 됩니다.
  • 위젯 트리의 유연성: InheritedWidget을 사용하면 상태를 공유하는 구조를 유연하게 관리할 수 있습니다. 데이터를 필요로 하는 위젯의 위치가 변경되더라도, of 메서드를 통해 쉽게 접근할 수 있으므로 위젯 트리의 구조 변경이 용이해집니다.
profile
공부하는 개발자

0개의 댓글