Flutter 위젯 트리 개념 및 상태 관리 적용하기
이번 포스팅에서는 Flutter 개발을 위한 위젯 트리(WIDGET TREE) 개념과 상태(State) 관리 방식을 살펴보고, 이를 활용하여 게임 프로젝트에서 UI를 효율적으로 업데이트하는 방법을 정리합니다.
1. 위젯 트리(WIDGET TREE)란?
Flutter에서 모든 화면 요소는 위젯(Widget)으로 구성되며, 이 위젯들은 계층 구조(Tree 구조)로 연결됩니다.
📌 위젯 트리 구조
- Flutter 앱은 최상단의 부모 위젯부터 하위 위젯을 계층적으로 포함하는 구조
- 특정 위젯이 변경되면 그 위젯과 관련된 하위 위젯만 다시 렌더링
- 불필요한 전체 UI 업데이트를 줄여 **성능 최적화** 가능
📌 위젯 트리 예시 (카드 게임 앱)
MyApp (최상위 위젯)
├── HomeWidget (홈 화면)
│ ├── HeaderWidget (헤더 영역: 점수 및 시도 횟수)
│ │ ├── ScoreWidget (점수 표시)
│ │ ├── TryCountWidget (시도 횟수 표시)
│ │ ├── NewGameButton (새 게임 버튼)
│ │
│ ├── CardBoardWidget (카드 보드 영역)
│ ├── 여러 개의 CardWidget (각 카드 위젯)
2. 상태 관리 (State Management)
Flutter에서 UI 업데이트는 상태(State) 변경을 기반으로 수행됩니다.
📌 상태(State) 관리 개념
- **Stateful Widget**: 상태 변경이 가능하며,
setState()
를 사용하여 UI를 업데이트 - **Stateless Widget**: 상태가 변하지 않는 정적인 위젯
- 부모 위젯이 상태를 관리하면 **자식 위젯에 상태를 전달하여 UI 변경 가능**
📌 상태 관리 예제
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State {
int count = 0;
void increment() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("카운트: $count"),
ElevatedButton(
onPressed: increment,
child: Text("증가")
),
],
);
}
}
3. 카드 게임 프로젝트에서 상태 관리 적용
이제 카드 게임 프로젝트에서 트라이 카운트(Try Count)와 점수(Score)를 업데이트하는 과정을 구현합니다.
📌 1) 부모(HomeWidget)에서 상태 관리
class HomeWidget extends StatefulWidget {
@override
_HomeWidgetState createState() => _HomeWidgetState();
}
class _HomeWidgetState extends State {
int score = 0;
int tryCount = 0;
void updateTryCount() {
setState(() {
tryCount++;
});
}
void updateScore() {
setState(() {
score += 100;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
HeaderWidget(score: score, tryCount: tryCount),
CardBoardWidget(
onUpdateTryCount: updateTryCount,
onUpdateScore: updateScore
),
],
);
}
}
📌 2) HeaderWidget에서 부모 데이터 받기
class HeaderWidget extends StatelessWidget {
final int score;
final int tryCount;
HeaderWidget({required this.score, required this.tryCount});
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("점수: $score"),
Text("시도 횟수: $tryCount"),
],
);
}
}
📌 3) CardBoardWidget에서 부모 함수 호출
class CardBoardWidget extends StatelessWidget {
final Function onUpdateTryCount;
final Function onUpdateScore;
CardBoardWidget({required this.onUpdateTryCount, required this.onUpdateScore});
void onCardTapped(bool isMatched) {
onUpdateTryCount();
if (isMatched) {
onUpdateScore();
}
}
@override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: 12,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => onCardTapped(true), // 임시로 항상 짝이 맞는다고 가정
child: Card(child: Center(child: Text("카드 $index"))),
);
},
);
}
}
4. 새로운 게임(New Game) 기능 추가
사용자가 새 게임 버튼을 클릭하면 점수와 시도 횟수를 초기화해야 합니다.
📌 1) 새 게임 버튼 추가
class NewGameButton extends StatelessWidget {
final Function onNewGame;
NewGameButton({required this.onNewGame});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => onNewGame(),
child: Text("새 게임 시작")
);
}
}
📌 2) HomeWidget에서 초기화 로직 추가
void resetGame() {
setState(() {
score = 0;
tryCount = 0;
});
}
5. 결론
- Flutter 앱은 위젯 트리(WIDGET TREE) 구조로 되어 있으며, 부모-자식 관계를 통해 데이터 전달 가능
- Stateful Widget과 setState()를 활용하여 UI 업데이트 최적화
- 부모(HomeWidget)에서 상태 관리 → 자식(HeaderWidget, CardBoardWidget)과 데이터 및 이벤트 공유
- 새 게임 버튼(New Game Button)을 활용하여 점수 및 시도 횟수 초기화 기능 구현
이제 다음 시간에는 Flutter에서 클래스를 활용하여 프로젝트를 리팩토링하는 방법을 배워보겠습니다! 🚀
'스파르타 코딩 클럽 내일배움캠프 6기 > [Flutter 트랙] 앱개발 종합반' 카테고리의 다른 글
[Flutter 트랙] 앱개발 종합반 2-1 - Flutter 기본기 (2) | 2025.03.04 |
---|---|
[Flutter 트랙] 앱개발 종합반 1-14 - 클래스 객체 (0) | 2025.03.04 |
[Flutter 트랙] 앱개발 종합반 1-12 - 동기 / 비동기 (2) | 2025.03.04 |
[Flutter 트랙] 앱개발 종합반 1-11 - 조건문 (0) | 2025.03.04 |
[Flutter 트랙] 앱개발 종합반 1-10 - 반복문 (0) | 2025.03.04 |