지금까지 배운 StatefulWidget, TextField, 버튼, 화면 전환 개념을
실전 앱으로 연결해보는 미니 프로젝트 시간입니다.
이번 글에서는 Flutter로 간단한 To-do List(할 일 목록) 앱을 만들어 보면서
상태 관리 + UI 구성 + 리스트 처리를 한 번에 연습합니다.
🎯 만들 앱 소개
✅ 할 일 입력
✅ 추가 버튼 클릭 시 리스트에 추가
✅ 각 할 일 항목 옆에 삭제 버튼
✅ 상태(State)로 리스트 자동 갱신
🧱 전체 구조 (StatefulWidget)
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: TodoApp()));
class TodoApp extends StatefulWidget {
@override
_TodoAppState createState() => _TodoAppState();
}
class _TodoAppState extends State<TodoApp> {
final TextEditingController _controller = TextEditingController();
List<String> _todoList = [];
void _addTodo() {
String text = _controller.text.trim();
if (text.isNotEmpty) {
setState(() {
_todoList.add(text);
_controller.clear();
});
}
}
void _removeTodo(int index) {
setState(() {
_todoList.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('할 일 목록 앱')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// 입력창
Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
labelText: '할 일을 입력하세요',
border: OutlineInputBorder(),
),
),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: _addTodo,
child: Text('추가'),
),
],
),
SizedBox(height: 20),
// 목록 출력
Expanded(
child: ListView.builder(
itemCount: _todoList.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(_todoList[index]),
trailing: IconButton(
icon: Icon(Icons.delete, color: Colors.red),
onPressed: () => _removeTodo(index),
),
),
);
},
),
),
],
),
),
);
}
}
void main() => runApp(MaterialApp(home: TodoApp()));
class TodoApp extends StatefulWidget {
@override
_TodoAppState createState() => _TodoAppState();
}
class _TodoAppState extends State<TodoApp> {
final TextEditingController _controller = TextEditingController();
List<String> _todoList = [];
void _addTodo() {
String text = _controller.text.trim();
if (text.isNotEmpty) {
setState(() {
_todoList.add(text);
_controller.clear();
});
}
}
void _removeTodo(int index) {
setState(() {
_todoList.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('할 일 목록 앱')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// 입력창
Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
labelText: '할 일을 입력하세요',
border: OutlineInputBorder(),
),
),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: _addTodo,
child: Text('추가'),
),
],
),
SizedBox(height: 20),
// 목록 출력
Expanded(
child: ListView.builder(
itemCount: _todoList.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(_todoList[index]),
trailing: IconButton(
icon: Icon(Icons.delete, color: Colors.red),
onPressed: () => _removeTodo(index),
),
),
);
},
),
),
],
),
),
);
}
}
🔍 기능 설명
기능설명
| TextEditingController | 입력값 관리 |
| List<String> _todoList | 할 일 저장 리스트 |
| _addTodo() | 할 일 추가 로직 |
| _removeTodo() | 할 일 삭제 로직 |
| setState() | 상태 변경 후 UI 자동 갱신 |
| ListView.builder | 할 일 목록을 반복 출력 |
📌 UI 구성 미리보기
css
복사편집
[할 일을 입력하세요] [추가] ---------------------------- ☑️ Flutter 공부하기 [삭제] ☑️ 블로그 글 쓰기 [삭제] ☑️ 산책하기 [삭제]
- 심플하면서 직관적인 UI
- 실시간 추가/삭제 동작
- 앱 형태로 바로 활용 가능
💡 확장 아이디어
할 일 앱을 아래처럼 발전시킬 수 있어요:
- ✅ 체크박스로 완료 상태 표시
- ✅ 로컬 저장 (SharedPreferences)
- ✅ 날짜별로 할 일 관리
- ✅ 다크모드/테마 적용
- ✅ Firebase 연동으로 DB 저장
Flutter 기초만 익혀도 꽤 실용적인 앱을 만들 수 있다는 것을 이 예제로 느껴보세요!
🧠 마무리 요약
개념설명
| StatefulWidget | 상태를 가진 UI |
| TextField + Button | 입력받고 추가 |
| ListView.builder | 리스트 출력 |
| setState() | 상태 변화 시 UI 자동 반영 |
이 To-do 앱 하나로
입력 처리 → 리스트 업데이트 → 상태 기반 UI 변화까지 핵심을 모두 연습할 수 있습니다.