🛠️ 30분만에 만드는 Todo App 완성 가이드 – 완성까지 한번에!

개발 에러 해결 가이드 - FixLog 노트

30분만에 만드는 Todo App 완성 가이드

이번 30분만에 만드는 Todo App 완성 가이드에서는 초보자도 쉽게 따라할 수 있는 실전 Todo 애플리케이션을 처음부터 끝까지 구현해봅니다. React와 LocalStorage를 활용하여 실용적인 할 일 관리 앱을 만들어보세요. 이 가이드는 실제 프로젝트 경험을 쌓고 포트폴리오를 강화하고 싶은 분들에게 완벽한 실습 자료입니다.

프로젝트 소개 및 목표

이 프로젝트는 실무에서 자주 사용되는 CRUD(Create, Read, Update, Delete) 기능을 모두 포함한 Todo 애플리케이션입니다. 사용자는 할 일을 추가하고, 완료 상태를 변경하며, 수정하고, 삭제할 수 있습니다. LocalStorage를 활용하여 브라우저를 새로고침해도 데이터가 유지되도록 구현합니다. 이 프로젝트를 통해 상태 관리, 이벤트 핸들링, 데이터 영속성 등 프론트엔드 개발의 핵심 개념을 익힐 수 있습니다. 완성된 앱은 즉시 사용 가능하며, 취업 포트폴리오로도 활용할 수 있습니다.

필요한 기술 스택

이 프로젝트를 완성하기 위해 필요한 기술 스택은 다음과 같습니다:

  • React 18+: 컴포넌트 기반 UI 개발을 위한 라이브러리
  • JavaScript (ES6+): 최신 자바스크립트 문법 활용
  • CSS3: 반응형 디자인 및 스타일링
  • LocalStorage API: 브라우저 기반 데이터 저장
  • Vite: 빠른 개발 환경 구축 도구

Node.js와 npm이 설치되어 있어야 하며, 기본적인 React Hooks(useState, useEffect) 지식이 있으면 더욱 좋습니다.

프로젝트 셋업

먼저 Vite를 사용하여 React 프로젝트를 생성합니다. 터미널에서 다음 명령어를 실행하세요:

npm create vite@latest todo-app -- --template react
cd todo-app
npm install
npm run dev

프로젝트 구조를 정리합니다. src 폴더 내에 다음과 같은 구조를 만들어주세요:

src/
├── components/
│   ├── TodoItem.jsx
│   ├── TodoList.jsx
│   └── TodoForm.jsx
├── App.jsx
├── App.css
└── main.jsx

이제 기본 설정이 완료되었습니다. 본격적으로 각 컴포넌트를 구현해봅시다. Vite는 핫 리로딩을 지원하므로 코드 변경 시 즉시 브라우저에 반영됩니다.

단계별 구현 과정

1단계: App 컴포넌트 – 상태 관리 설정

App.jsx에서 전체 애플리케이션의 상태를 관리합니다. LocalStorage와 연동하여 데이터를 영구 저장하는 로직을 구현합니다:

import { useState, useEffect } from 'react';
import TodoForm from './components/TodoForm';
import TodoList from './components/TodoList';
import './App.css';

function App() {
  const [todos, setTodos] = useState(() => {
    const savedTodos = localStorage.getItem('todos');
    return savedTodos ? JSON.parse(savedTodos) : [];
  });

  useEffect(() => {
    localStorage.setItem('todos', JSON.stringify(todos));
  }, [todos]);

  const addTodo = (text) => {
    const newTodo = {
      id: Date.now(),
      text,
      completed: false,
      createdAt: new Date().toISOString()
    };
    setTodos([newTodo, ...todos]);
  };

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  const editTodo = (id, newText) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, text: newText } : todo
    ));
  };

  return (
    

📝 My Todo App

); } export default App;

2단계: TodoForm 컴포넌트 – 입력 폼 구현

새로운 할 일을 추가하는 폼 컴포넌트입니다. 입력 유효성 검사와 엔터키 제출 기능을 포함합니다:

import { useState } from 'react';

function TodoForm({ onSubmit }) {
  const [input, setInput] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (input.trim()) {
      onSubmit(input.trim());
      setInput('');
    }
  };

  return (
    
setInput(e.target.value)} placeholder="새로운 할 일을 입력하세요..." className="todo-input" maxLength="100" />
); } export default TodoForm;

3단계: TodoList 컴포넌트 – 목록 렌더링

Todo 항목들을 렌더링하고, 완료/미완료 필터링 기능을 제공합니다:

import { useState } from 'react';
import TodoItem from './TodoItem';

function TodoList({ todos, onToggle, onDelete, onEdit }) {
  const [filter, setFilter] = useState('all');

  const filteredTodos = todos.filter(todo => {
    if (filter === 'active') return !todo.completed;
    if (filter === 'completed') return todo.completed;
    return true;
  });

  return (
    
{filteredTodos.length === 0 ? (

할 일이 없습니다!

) : ( filteredTodos.map(todo => ( )) )}
); } export default TodoList;

4단계: TodoItem 컴포넌트 – 개별 항목 구현

각 Todo 항목을 표시하고 편집, 삭제, 완료 처리 기능을 제공합니다:

import { useState } from 'react';

function TodoItem({ todo, onToggle, onDelete, onEdit }) {
  const [isEditing, setIsEditing] = useState(false);
  const [editText, setEditText] = useState(todo.text);

  const handleEdit = () => {
    if (editText.trim() && editText !== todo.text) {
      onEdit(todo.id, editText.trim());
    }
    setIsEditing(false);
  };

  return (
    
onToggle(todo.id)} className="todo-checkbox" /> {isEditing ? ( setEditText(e.target.value)} onBlur={handleEdit} onKeyPress={(e) => e.key === 'Enter' && handleEdit()} className="todo-edit-input" autoFocus /> ) : ( !todo.completed && setIsEditing(true)} > {todo.text} )}
{!todo.completed && !isEditing && ( )}
); } export default TodoItem;

5단계: 스타일링 – App.css

깔끔하고 현대적인 UI를 위한 CSS 스타일을 추가합니다:

.app {
  max-width: 600px;
  margin: 50px auto;
  padding: 20px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

h1 {
  text-align: center;
  color: #333;
  margin-bottom: 30px;
}

.todo-form {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.todo-input {
  flex: 1;
  padding: 12px;
  border: 2px solid #e0e0e0;
  border-radius: 8px;
  font-size: 16px;
}

.todo-button {
  padding: 12px 24px;
  background: #4CAF50;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-weight: bold;
}

.filter-buttons {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.filter-buttons button {
  flex: 1;
  padding: 10px;
  border: 2px solid #e0e0e0;
  background: white;
  border-radius: 6px;
  cursor: pointer;
}

.filter-buttons button.active {
  background: #2196F3;
  color: white;
  border-color: #2196F3;
}

.todo-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 15px;
  background: white;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  margin-bottom: 10px;
  transition: all 0.3s;
}

.todo-item.completed {
  opacity: 0.6;
  background: #f5f5f5;
}

.todo-item.completed .todo-text {
  text-decoration: line-through;
}

.todo-text {
  flex: 1;
  font-size: 16px;
}

.todo-actions {
  display: flex;
  gap: 5px;
}

.edit-btn, .delete-btn {
  padding: 5px 10px;
  border: none;
  background: none;
  cursor: pointer;
  font-size: 18px;
}

.empty-message {
  text-align: center;
  color: #999;
  padding: 40px;
}

테스트 및 배포

개발이 완료되었다면 로컬에서 충분히 테스트합니다. 다양한 시나리오를 확인하세요:

  • 할 일 추가, 수정, 삭제 기능 테스트
  • 완료 체크박스 토글 기능 확인
  • 필터링(전체/진행중/완료) 동작 검증
  • 브라우저 새로고침 후 데이터 유지 확인
  • 빈 값 입력 방지 검증

배포는 Vercel이나 Netlify를 추천합니다. 빌드 후 배포 명령어:

npm run build
# Vercel 배포
npx vercel --prod

# 또는 Netlify
npx netlify deploy --prod --dir=dist

GitHub Pages를 사용할 경우 vite.config.js에 base 경로를 설정해야 합니다.

마무리 및 확장 아이디어

축하합니다! 30분만에 만드는 Todo App 완성 가이드를 통해 완전히 동작하는 Todo 애플리케이션을 완성했습니다. 이 프로젝트를 확장할 수 있는 아이디어는 다음과 같습니다:

  • 우선순위 기능: 중요도에 따라 색상 라벨 추가
  • 마감일 설정: 날짜 선택기로 데드라인 관리
  • 카테고리 분류: 업무, 개인, 쇼핑 등으로 그룹화
  • 드래그 앤 드롭: 순서 변경 기능 구현
  • 백엔드 연동: Firebase나 Supabase로 클라우드 저장
  • 다크모드: 테마 전환 기능 추가

30분만에 만드는 Todo App 완성 가이드가 여러분의 개발 실력 향상과 포트폴리오 구축에 도움이 되기를 바랍니다!

📚 함께 읽으면 좋은 글

1

React + Node.js 풀스택 앱 배포하기 – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 5.
🎯 React + Node.js 풀스택 앱 배포하기

2

React + Node.js 풀스택 앱 배포하기 – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 3.
🎯 React + Node.js 풀스택 앱 배포하기

3

MongoDB와 Express.js로 블로그 만들기 – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 2.
🎯 MongoDB와 Express.js로 블로그 만들기

4

React + Node.js 풀스택 앱 배포하기 – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 2.
🎯 React + Node.js 풀스택 앱 배포하기

5

REST API 서버 구축 단계별 튜토리얼 – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 1.
🎯 REST API 서버 구축 단계별 튜토리얼

💡 위 글들을 통해 더 깊이 있는 정보를 얻어보세요!

📢 이 글이 도움되셨나요? 공유해주세요!

여러분의 공유 한 번이 더 많은 사람들에게 도움이 됩니다 ✨


📘 페이스북


🐦 트위터


✈️ 텔레그램

🔥 공유할 때마다 블로그 성장에 큰 힘이 됩니다! 감사합니다 🙏

💬 여러분의 소중한 의견을 들려주세요!

30분만에 만드는 Todo App 완성 가이드에 대한 여러분만의 경험이나 노하우가 있으시나요?

💡
유용한 정보 공유

궁금한 점 질문

🤝
경험담 나누기

👍
의견 표현하기

⭐ 모든 댓글은 24시간 내에 답변드리며, 여러분의 의견이 다른 독자들에게 큰 도움이 됩니다!
🎯 건설적인 의견과 경험 공유를 환영합니다 ✨

🔔 블로그 구독하고 최신 글을 받아보세요!

📚
다양한 주제
17개 카테고리

정기 업데이트
하루 3회 발행

🎯
실용적 정보
바로 적용 가능

💡
최신 트렌드
2025년 기준

🌟 프로젝트 아이디어부터 다양한 실생활 정보까지!
매일 새로운 유용한 콘텐츠를 만나보세요 ✨

📧 RSS 구독 | 🔖 북마크 추가 | 📱 모바일 앱 알림 설정
지금 구독하고 놓치는 정보 없이 업데이트 받아보세요!

📱 전체 버전 보기