Flutter로 앱을 개발하다 보면 Key라는 개념을 마주치게 됩니다. Key는 Flutter 위젯 시스템의 중요한 부분이며, 특히 위젯 트리를 효율적으로 관리하기 위해 사용됩니다. 이 글에서는 Key가 무엇인지, 왜 중요한지, 그리고 어떻게 사용하는지를 이해하기 쉽게 설명해보겠습니다.
Key란 무엇인가요?
Key는 Flutter 위젯 트리에서 각 위젯을 고유하게 식별할 수 있는 값입니다. Flutter는 UI를 렌더링할 때 기존 위젯 트리를 재사용하려고 합니다. 이때 Key는 Flutter가 어떤 위젯이 어떤 데이터와 연결되어 있는지 추적하도록 도와줍니다.
간단히 말해, Key는 다음과 같은 상황에서 유용합니다:
- 상태를 유지해야 할 때
- 리스트나 컬렉션이 변경될 때
Key가 왜 필요한가요?
Flutter는 성능을 위해 Hot Reload와 Stateful 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를 사용할 때 주의사항
- Key는 고유해야 합니다.
- 같은 Key를 여러 위젯에 사용하면 Flutter가 혼란스러워합니다.
- Key를 과도하게 사용하지 마세요.
- Key는 꼭 필요한 경우에만 사용해야 합니다. 불필요한 Key는 오히려 성능에 영향을 줄 수 있습니다.
- 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 |