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

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

프로젝트 소개 및 목표

30분만에 만드는 Todo App 완성 가이드는 웹 개발 초보자부터 중급자까지 누구나 따라할 수 있는 실전 프로젝트입니다. 바닐라 JavaScript와 HTML, CSS만으로 완전히 동작하는 할 일 관리 애플리케이션을 만들어봅니다. 이 가이드를 통해 DOM 조작, 이벤트 핸들링, 로컬 스토리지 활용 등 실무에서 필수적인 기술들을 익힐 수 있습니다. 완성된 프로젝트는 포트폴리오에 바로 추가할 수 있으며, 확장 가능한 구조로 설계되어 있어 추가 기능을 자유롭게 구현할 수 있습니다.

필요한 기술 스택

이 프로젝트는 별도의 프레임워크 없이 순수 웹 기술만 사용합니다:

  • HTML5: 시맨틱 마크업으로 구조 작성
  • CSS3: Flexbox를 활용한 반응형 디자인
  • JavaScript (ES6+): 할 일 추가, 삭제, 완료 기능 구현
  • LocalStorage API: 데이터 영구 저장
  • 코드 에디터: VS Code 권장
  • 웹 브라우저: Chrome, Firefox 등 모던 브라우저

프로젝트 셋업

먼저 프로젝트 폴더를 생성하고 기본 파일 구조를 만듭니다:

mkdir todo-app
cd todo-app
touch index.html style.css app.js

프로젝트 구조는 다음과 같습니다:

todo-app/
├── index.html
├── style.css
└── app.js

이 간단한 구조로 시작하여 모든 기능을 구현할 수 있습니다. 별도의 빌드 도구나 패키지 매니저가 필요 없어 즉시 개발을 시작할 수 있습니다. VS Code에서 Live Server 확장을 설치하면 실시간으로 변경사항을 확인할 수 있습니다.

단계별 구현 과정

Step 1: HTML 구조 작성

index.html 파일에 기본 구조를 작성합니다:

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>30분 Todo App</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1>📝 나의 할 일 목록</h1>
        <div class="input-section">
            <input type="text" id="todoInput" placeholder="할 일을 입력하세요...">
            <button id="addBtn">추가</button>
        </div>
        <div class="filter-section">
            <button class="filter-btn active" data-filter="all">전체</button>
            <button class="filter-btn" data-filter="active">진행중</button>
            <button class="filter-btn" data-filter="completed">완료</button>
        </div>
        <ul id="todoList"></ul>
        <div class="stats">
            <span>전체: <span id="totalCount">0</span></span>
            <span>완료: <span id="completedCount">0</span></span>
        </div>
    </div>
    <script src="app.js"></script>
</body>
</html>

Step 2: CSS 스타일링

style.css에 깔끔한 디자인을 적용합니다:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    min-height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 20px;
}

.container {
    background: white;
    border-radius: 15px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    padding: 30px;
    width: 100%;
    max-width: 500px;
}

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

.input-section {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
}

#todoInput {
    flex: 1;
    padding: 12px 15px;
    border: 2px solid #e0e0e0;
    border-radius: 8px;
    font-size: 16px;
    transition: border-color 0.3s;
}

#todoInput:focus {
    outline: none;
    border-color: #667eea;
}

#addBtn {
    padding: 12px 25px;
    background: #667eea;
    color: white;
    border: none;
    border-radius: 8px;
    font-size: 16px;
    font-weight: bold;
    cursor: pointer;
    transition: background 0.3s;
}

#addBtn:hover {
    background: #5568d3;
}

.filter-section {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
    justify-content: center;
}

.filter-btn {
    padding: 8px 16px;
    background: #f5f5f5;
    border: 2px solid transparent;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.3s;
}

.filter-btn.active {
    background: #667eea;
    color: white;
}

#todoList {
    list-style: none;
    margin-bottom: 20px;
}

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

.todo-item:hover {
    transform: translateX(5px);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.todo-item.completed {
    opacity: 0.6;
}

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

.todo-item input[type="checkbox"] {
    margin-right: 12px;
    width: 20px;
    height: 20px;
    cursor: pointer;
}

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

.delete-btn {
    background: #ff6b6b;
    color: white;
    border: none;
    padding: 6px 12px;
    border-radius: 5px;
    cursor: pointer;
    transition: background 0.3s;
}

.delete-btn:hover {
    background: #ee5a52;
}

.stats {
    display: flex;
    justify-content: space-around;
    padding: 15px;
    background: #f5f5f5;
    border-radius: 8px;
    font-weight: bold;
    color: #666;
}

Step 3: JavaScript 기능 구현

이제 30분만에 만드는 Todo App 완성 가이드의 핵심인 JavaScript 기능을 구현합니다. app.js에 다음 코드를 작성하세요:

// DOM 요소 선택
const todoInput = document.getElementById('todoInput');
const addBtn = document.getElementById('addBtn');
const todoList = document.getElementById('todoList');
const filterBtns = document.querySelectorAll('.filter-btn');
const totalCount = document.getElementById('totalCount');
const completedCount = document.getElementById('completedCount');

// 전역 변수
let todos = [];
let currentFilter = 'all';

// LocalStorage에서 데이터 로드
function loadTodos() {
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
        todos = JSON.parse(savedTodos);
        renderTodos();
    }
}

// LocalStorage에 데이터 저장
function saveTodos() {
    localStorage.setItem('todos', JSON.stringify(todos));
}

// 할 일 추가
function addTodo() {
    const text = todoInput.value.trim();
    if (text === '') {
        alert('할 일을 입력해주세요!');
        return;
    }
    
    const newTodo = {
        id: Date.now(),
        text: text,
        completed: false,
        createdAt: new Date().toISOString()
    };
    
    todos.push(newTodo);
    todoInput.value = '';
    saveTodos();
    renderTodos();
}

// 할 일 삭제
function deleteTodo(id) {
    todos = todos.filter(todo => todo.id !== id);
    saveTodos();
    renderTodos();
}

// 할 일 완료/미완료 토글
function toggleTodo(id) {
    todos = todos.map(todo => {
        if (todo.id === id) {
            return { ...todo, completed: !todo.completed };
        }
        return todo;
    });
    saveTodos();
    renderTodos();
}

// 필터링된 할 일 목록 반환
function getFilteredTodos() {
    switch (currentFilter) {
        case 'active':
            return todos.filter(todo => !todo.completed);
        case 'completed':
            return todos.filter(todo => todo.completed);
        default:
            return todos;
    }
}

// 화면에 할 일 렌더링
function renderTodos() {
    const filteredTodos = getFilteredTodos();
    
    todoList.innerHTML = '';
    
    if (filteredTodos.length === 0) {
        todoList.innerHTML = '
  • 할 일이 없습니다.
  • '; } else { filteredTodos.forEach(todo => { const li = document.createElement('li'); li.className = `todo-item ${todo.completed ? 'completed' : ''}`; li.innerHTML = ` ${todo.text} `; todoList.appendChild(li); }); } updateStats(); } // 통계 업데이트 function updateStats() { totalCount.textContent = todos.length; completedCount.textContent = todos.filter(todo => todo.completed).length; } // 이벤트 리스너 addBtn.addEventListener('click', addTodo); todoInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { addTodo(); } }); filterBtns.forEach(btn => { btn.addEventListener('click', () => { filterBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); currentFilter = btn.dataset.filter; renderTodos(); }); }); // 초기 로드 loadTodos();

    이 코드는 할 일 추가, 삭제, 완료 표시, 필터링, 통계 표시 등 모든 핵심 기능을 포함합니다. LocalStorage를 사용하여 브라우저를 닫아도 데이터가 유지됩니다.

    테스트 및 배포

    로컬 테스트

    VS Code에서 Live Server를 실행하거나 index.html 파일을 브라우저에서 직접 열어 테스트합니다. 다음 항목을 확인하세요:

    • ✅ 할 일 추가 기능 (Enter 키 및 버튼 클릭)
    • ✅ 체크박스로 완료 표시
    • ✅ 삭제 버튼 동작
    • ✅ 필터 버튼 (전체/진행중/완료)
    • ✅ 통계 정보 업데이트
    • ✅ 페이지 새로고침 후 데이터 유지

    배포 방법

    완성된 프로젝트는 다음 플랫폼에 무료로 배포할 수 있습니다:

    # GitHub Pages
    git init
    git add .
    git commit -m "Initial commit: Todo App"
    git branch -M main
    git remote add origin [your-repo-url]
    git push -u origin main
    

    또는 Netlify, Vercel에 드래그 앤 드롭으로 즉시 배포 가능합니다. 정적 파일만 사용하므로 별도의 서버 설정이 필요 없습니다.

    마무리 및 확장 아이디어

    축하합니다! 30분만에 만드는 Todo App 완성 가이드를 따라 완전히 동작하는 할 일 관리 앱을 완성했습니다. 이제 다음과 같은 기능을 추가하여 더욱 발전시킬 수 있습니다:

    • 🎨 다크모드 테마 전환
    • 🔍 할 일 검색 기능
    • 📅 마감일 설정 및 알림
    • 🏷️ 카테고리/태그 시스템
    • 📱 PWA로 변환하여 모바일 앱처럼 사용
    • ☁️ Firebase 연동으로 클라우드 동기화
    • ✨ 드래그 앤 드롭으로 순서 변경
    • 📊 생산성 통계 및 차트

    이 프로젝트는 포트폴리오에 추가하기 좋으며, 실무에서 사용하는 JavaScript 패턴과 웹 API를 모두 경험할 수 있습니다. 코드를 자유롭게 수정하고 확장하여 나만의 독특한 Todo 앱을 만들어보세요!

    📚 함께 읽으면 좋은 글

    1

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

    📂 프로젝트 아이디어
    📅 2025. 10. 15.
    🎯 30분만에 만드는 Todo App 완성 가이드

    2

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

    📂 프로젝트 아이디어
    📅 2025. 10. 10.
    🎯 30분만에 만드는 Todo App 완성 가이드

    3

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

    📂 프로젝트 아이디어
    📅 2025. 10. 5.
    🎯 30분만에 만드는 Todo App 완성 가이드

    4

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

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

    5

    실시간 채팅 앱 만들기 with Socket.io – 완성까지 한번에!

    📂 프로젝트 아이디어
    📅 2025. 10. 18.
    🎯 실시간 채팅 앱 만들기 with Socket.io

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

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

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


    📘 페이스북


    🐦 트위터


    ✈️ 텔레그램

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

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

    여러분은 30분만에 만드는 Todo App 완성 가이드에 대해 어떻게 생각하시나요?

    💡
    유용한 정보 공유

    궁금한 점 질문

    🤝
    경험담 나누기

    👍
    의견 표현하기

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

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

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

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

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

    💡
    최신 트렌드
    2025년 기준

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

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

    📱 전체 버전 보기