TIL

Flutter의 Key는 무엇인가요?

kimw746 2025. 1. 15. 16:19

Flutter로 앱을 개발하다 보면 Key라는 개념을 마주치게 됩니다. Key는 Flutter 위젯 시스템의 중요한 부분이며, 특히 위젯 트리를 효율적으로 관리하기 위해 사용됩니다. 이 글에서는 Key가 무엇인지, 왜 중요한지, 그리고 어떻게 사용하는지를 이해하기 쉽게 설명해보겠습니다.


Key란 무엇인가요?

Key는 Flutter 위젯 트리에서 각 위젯을 고유하게 식별할 수 있는 값입니다. Flutter는 UI를 렌더링할 때 기존 위젯 트리를 재사용하려고 합니다. 이때 Key는 Flutter가 어떤 위젯이 어떤 데이터와 연결되어 있는지 추적하도록 도와줍니다.

간단히 말해, Key는 다음과 같은 상황에서 유용합니다:

  • 상태를 유지해야 할 때
  • 리스트나 컬렉션이 변경될 때

Key가 왜 필요한가요?

Flutter는 성능을 위해 Hot ReloadStateful Widgets에서 기존의 위젯을 재사용하려고 합니다. 하지만 다음과 같은 상황에서는 문제가 발생할 수 있습니다:

 

1. 리스트의 아이템이 추가되거나 삭제될 때

리스트에서 새로운 아이템을 추가하거나 기존 아이템을 삭제하면, Flutter는 어떤 위젯이 새로 추가되었고 어떤 위젯이 삭제되었는지 구분하지 못할 수 있습니다. 이로 인해 예기치 않은 동작(예: 상태가 잘못된 아이템에 할당됨)이 발생할 수 있습니다.

 

2. 상태를 유지해야 할 때

예를 들어, TextField에 사용자가 입력한 텍스트를 유지하려고 할 때, Key를 사용하지 않으면 기존 상태가 사라질 수 있습니다.


Key의 종류

Flutter에서는 몇 가지 Key 유형을 제공합니다. 상황에 맞는 Key를 선택하는 것이 중요합니다.

1. GlobalKey

  • 위젯의 상태에 전역적으로 접근해야 할 때 사용합니다.
  • 한 번에 한 위젯에서만 사용할 수 있습니다.
final GlobalKey<FormState> formKey = GlobalKey<FormState>();

Form(
  key: formKey,
  child: Column(
    children: [
      TextFormField(),
      ElevatedButton(
        onPressed: () {
          if (formKey.currentState?.validate() == true) {
            // 유효성 검사 통과
          }
        },
        child: Text('Submit'),
      ),
    ],
  ),
);

 

2. UniqueKey

  • 고유한 Key를 자동으로 생성합니다.
  • 리스트 아이템이 항상 새로 생성되어야 할 때 사용합니다.
ListView(
  children: [
    Container(key: UniqueKey(), child: Text('Item 1')),
    Container(key: UniqueKey(), child: Text('Item 2')),
  ],
);

 

3. ValueKey

  • 특정 값에 기반한 Key를 제공합니다. 값이 같으면 동일한 Key로 간주됩니다.
  • 리스트에서 특정 아이템을 추적해야 할 때 유용합니다.
ListView(
  children: items.map((item) {
    return Container(
      key: ValueKey(item.id),
      child: Text(item.name),
    );
  }).toList(),
);

 


Key를 사용하는 예시

다음은 Key를 사용하여 리스트를 관리하는 간단한 예제입니다.

문제 상황

위젯 리스트에서 새로운 아이템을 추가할 때 상태가 유지되지 않는 문제:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Key Example')),
        body: MyWidgetList(),
      ),
    );
  }
}

class MyWidgetList extends StatefulWidget {
  @override
  _MyWidgetListState createState() => _MyWidgetListState();
}

class _MyWidgetListState extends State<MyWidgetList> {
  List<String> items = ['Item 1', 'Item 2', 'Item 3'];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: ListView(
            children: items.map((item) {
              return ListTile(
                key: ValueKey(item), // Key를 추가하여 상태를 유지
                title: Text(item),
              );
            }).toList(),
          ),
        ),
        ElevatedButton(
          onPressed: () {
            setState(() {
              items.add('Item ${items.length + 1}');
            });
          },
          child: Text('Add Item'),
        ),
      ],
    );
  }
}

Key를 사용하지 않으면 새로 추가된 아이템 때문에 기존 아이템의 상태가 초기화될 수 있습니다. 하지만 위 코드에서는 ValueKey를 사용하여 이를 방지합니다.

 


Key를 사용할 때 주의사항

  1. Key는 고유해야 합니다.
    • 같은 Key를 여러 위젯에 사용하면 Flutter가 혼란스러워합니다.
  2. Key를 과도하게 사용하지 마세요.
    • Key는 꼭 필요한 경우에만 사용해야 합니다. 불필요한 Key는 오히려 성능에 영향을 줄 수 있습니다.
  3. GlobalKey는 신중히 사용하세요.
    • GlobalKey는 성능 비용이 크기 때문에 꼭 필요한 상황에서만 사용하세요.
 

'TIL' 카테고리의 다른 글

Flutter의 Stream에 대해서..  (1) 2025.01.15
Flutter의 const 키워드  (0) 2025.01.15
Dart의 Garbage Collector란?  (0) 2025.01.13
클래스 내에서 static 키워드  (0) 2025.01.10
Flutter의 빌드 모드에는 무엇이 있는지 알아보자  (0) 2025.01.10