[Flutter] Todolist App 만들기

저우웅·2025년 10월 26일

Flutter

목록 보기
5/8

안녕하세요~!
오늘은 간단한 Flutter 앱을 만들어 왔습니다...

아주아주 간단한 Todolist를 소개해드릴게요!



완성 화면



이 앱에 대해서 간단 소개를 한 번 해보겠습니다.



프로젝트 구조

해당 앱은 네 개의 dart 파일로 만들었습니다.

오늘은 해당 파일들 중 메인 로직이 있는 todo_home.dart를 살펴보겠습니다.



todo_home.dart

final List<TodoItem> _items = [];
final TextEditingController _controller = TextEditingController();

먼저 홈화면 내부의 State에서 Todo items와 controller를 선언했습니다.

이 중 TextEditingController는 입력 상태를 직접 관리하는 객체 입니다.

_controller의 내부 역할에 대해서는 아래 addItem에서 자세히 알아보겠습니다.



item 추가 (void _addItem)

final text = _controller.text.trim();
if (text.isEmpty) return;

setState(() {
  // 새로운 할 일 추가
  _items.insert(0, TodoItem(id: _nextId, title: text));
  _nextId ++;
});
_controller.clear();

사용자가 입력한 text는 _controller.text를 통해 접근할 수 있고, 이 값을 새로운 TodoItem으로 리스트에 추가한 뒤 _controller.clear()로 입력창을 초기화합니다.


만약 Vue로 동일한 입력창을 구현한다면

const todoText = ref('') // 이게 Flutter의 controller 역할이야

const addTodo = () => {
  const text = todoText.value.trim()
  if (!text) return
  console.log('할 일 추가:', text)
  todoText.value = '' // 입력창 초기화
}

이런 식으로 구현 가능하겠죠!


추가적으로 _controller.text(사용자가 입력한 내용)에 .trim을 붙여 불필요한 앞뒤 공백을 제거하였습니다.

마지막으로 setState로 인해 item이 추가되면 UI가 다시 렌더링됩니다. 이를 통해 Flutter는 변경된 부분만 다시 렌더링하게 됩니다.



할 일 완료 체크 (void _toggleDone)

void _toggleDone(int index) {
  setState(() {
    _items[index].done = !_items[index].done;
  });
}

toggleDone에서도 마찬가지로 setState를 통해 item에 대해 완료 체크시 UI를 다시 렌더링하도록 설정하였습니다.

글자에 대해서는 TextDecoration을 통해 underline, overline 등의 효과를 줄 수 있습니다.

style: TextStyle(
  decoration: item.done
    ? TextDecoration.lineThrough
    : null,
),

여기서는 TextDecoration.lineThrough를 통해 가운데 줄 효과를 주었습니다.




스와이프시 할 일 삭제

  void _removeItem(int index) {
    setState(() {
      _items.removeAt(index);
    });
  }

todo item을 옆으로 스와이프하면 삭제할 수 있도록 하였습니다.

Flutter에서 스와이프를 통한 삭제는 Dismissible을 통해 구현할 수 있습니다.

return Dismissible(
  key: ValueKey(item.title + index.toString()),
  onDismissed: (_) => _removeItem(index),
  background: Container(
    color: Colors.red,
    alignment: Alignment.centerRight,
    padding: const EdgeInsets.only(right: 16.0),
    child: const Icon(Icons.delete, color: Colors.white),
  ),
  child: CheckboxListTile(
    title: Text(
      item.title,
      style: TextStyle(
        decoration: item.done
          ? TextDecoration.lineThrough
          : null,
        ),
    ),
    value: item.done,
    onChanged: (_) => _toggleDone(index),
  ),
);

Dismissable에서 꼭 필요한 것은 key와 child입니다.

key는 각 item을 식별해주는 역할을 합니다. 어떤 아이템이 삭제되었는지 구분 가능하게 만들고, child에 안에 들어가는 실제 콘텐츠가 전달됩니다.

여기서 onDismissed는 child가 사라지고 난 후에 호출됩니다. 즉, 스와이프를 통해 todo item이 사라지고 난 뒤에 _removeItem이 호출됩니다.

background는 child 뒤에 있어서, child를 스와이프했을 때 보여지는 widget입니다.



정리


이렇게 아주 작고 간단한 Todolist 앱 소개글을 마무리 짓겠습니다...ㅎㅎ
개인적으로 TextEditingController로 입력값을 직접 제어하는 점이 신기했고, Dismissable을 통한 스와이프 구현도 처음 시도해보는 부분이라 재미있었습니다. (이게 앱개발이구나...)


다음에는 해당 앱을 shared_preferences를 이용해
앱을 껐다 켜도 유지되게 만들어볼 예정입니다.


읽어주셔서 감사합니다. 🙂‍↕️

profile
ㅠㅠ

2개의 댓글

comment-user-thumbnail
2025년 11월 2일

간단한 앱이지만, 사용성이 좋아보이네요! Dismissable로 화면에서 사라지게 한 이후에 removeitem을 해서 실제로 해당 아이템을 삭제하는 방식인가봐요!

답글 달기
comment-user-thumbnail
2025년 11월 3일

데이터를 저장하고 수정하고 삭제하고 업데이트하는 연습을 할 때 투두 리스트 구현이 참 좋은 것 같습니다! 또한 실제 구현하신 것을 봤을때 슬라이드로 삭제를 가능하게 하는게 사용감이 좋아보이네요

답글 달기