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

프로젝트 소개 및 목표

30분만에 만드는 Todo App 완성 가이드는 프론트엔드 개발을 시작하는 분들을 위한 실전 프로젝트입니다. Todo 애플리케이션은 CRUD(Create, Read, Update, Delete) 기능을 모두 포함하고 있어 웹 개발의 핵심 개념을 익히기에 완벽한 프로젝트입니다. 이 가이드를 따라하면 할 일 추가, 완료 체크, 삭제, 필터링 기능을 가진 완전한 Todo 앱을 만들 수 있습니다. 로컬 스토리지를 활용하여 데이터를 저장하므로 백엔드 없이도 실용적인 애플리케이션을 완성할 수 있습니다. 초보자도 쉽게 따라할 수 있도록 단계별로 상세히 설명하며, 완성 후에는 포트폴리오에 추가할 수 있는 수준의 프로젝트가 됩니다.

필요한 기술 스택

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

  • HTML5: 애플리케이션의 구조를 만듭니다
  • CSS3: 스타일링과 반응형 디자인을 구현합니다
  • JavaScript (ES6+): 동적인 기능과 상호작용을 처리합니다
  • Local Storage API: 브라우저에 데이터를 저장합니다

별도의 프레임워크나 라이브러리 없이 순수 JavaScript(Vanilla JS)로 구현하므로, 기본기를 탄탄히 다질 수 있습니다. 텍스트 에디터(VS Code 추천)와 최신 웹 브라우저만 있으면 시작할 수 있습니다.

프로젝트 셋업

먼저 프로젝트 폴더를 생성하고 필요한 파일을 준비합니다:

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 확장 프로그램을 설치하여 실시간으로 변경사항을 확인할 수 있습니다. 이제 각 파일을 단계별로 작성해보겠습니다.

단계별 구현 과정

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 id="totalCount">전체: 0</span>
            <span id="activeCount">진행중: 0</span>
        </div>
    </div>
    
    <script src="app.js"></script>
</body>
</html>

HTML 구조는 입력 섹션, 필터 버튼, 할 일 목록, 통계 정보로 구성됩니다.

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;
    padding: 30px;
    width: 100%;
    max-width: 500px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.2);
}

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

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

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

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

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

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

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

.filter-btn {
    flex: 1;
    padding: 8px;
    background: #f5f5f5;
    border: none;
    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 {
    background: #f9f9f9;
    padding: 15px;
    border-radius: 8px;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
    transition: transform 0.2s;
}

.todo-item:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}

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

.todo-checkbox {
    width: 20px;
    height: 20px;
    cursor: pointer;
}

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

.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: #555;
}

3단계: JavaScript 기능 구현

app.js 파일에 핵심 로직을 작성합니다:

// 전역 변수
let todos = JSON.parse(localStorage.getItem('todos')) || [];
let currentFilter = 'all';

// 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 activeCount = document.getElementById('activeCount');

// 초기화
document.addEventListener('DOMContentLoaded', () => {
    renderTodos();
    updateStats();
});

// 할 일 추가
addBtn.addEventListener('click', addTodo);
todoInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') addTodo();
});

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

// 할 일 렌더링
function renderTodos() {
    const filteredTodos = getFilteredTodos();
    todoList.innerHTML = '';
    
    filteredTodos.forEach(todo => {
        const li = document.createElement('li');
        li.className = `todo-item ${todo.completed ? 'completed' : ''}`;
        li.innerHTML = `
            
            ${todo.text}
            
        `;
        todoList.appendChild(li);
    });
}

// 할 일 토글
function toggleTodo(id) {
    todos = todos.map(todo => 
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
    );
    saveTodos();
    renderTodos();
    updateStats();
}

// 할 일 삭제
function deleteTodo(id) {
    if (confirm('정말 삭제하시겠습니까?')) {
        todos = todos.filter(todo => todo.id !== id);
        saveTodos();
        renderTodos();
        updateStats();
    }
}

// 필터링
filterBtns.forEach(btn => {
    btn.addEventListener('click', () => {
        filterBtns.forEach(b => b.classList.remove('active'));
        btn.classList.add('active');
        currentFilter = btn.dataset.filter;
        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 updateStats() {
    const total = todos.length;
    const active = todos.filter(todo => !todo.completed).length;
    totalCount.textContent = `전체: ${total}`;
    activeCount.textContent = `진행중: ${active}`;
}

// 로컬 스토리지 저장
function saveTodos() {
    localStorage.setItem('todos', JSON.stringify(todos));
}

이 코드는 할 일 추가, 완료 체크, 삭제, 필터링, 통계 표시 기능을 모두 포함합니다. Local Storage를 활용하여 페이지를 새로고침해도 데이터가 유지됩니다.

4단계: 고급 기능 추가 (선택사항)

시간이 남는다면 다음 기능을 추가해보세요:

  • 수정 기능: 더블클릭으로 할 일 수정
  • 드래그 앤 드롭: 순서 변경
  • 다크모드: 테마 전환 버튼
  • 우선순위: 중요도 표시

테스트 및 배포

로컬 테스트

브라우저에서 index.html 파일을 열어 다음 항목을 테스트합니다:

  • 할 일 추가가 정상적으로 작동하는지 확인
  • 체크박스 클릭 시 완료 상태가 토글되는지 확인
  • 삭제 버튼이 정상적으로 작동하는지 확인
  • 필터 버튼(전체/진행중/완료)이 올바르게 작동하는지 확인
  • 페이지 새로고침 후에도 데이터가 유지되는지 확인
  • 통계가 정확하게 표시되는지 확인

배포하기

GitHub Pages를 이용한 무료 배포:

git init
git add .
git commit -m "Todo App 완성"
git branch -M main
git remote add origin https://github.com/username/todo-app.git
git push -u origin main

GitHub 저장소 설정에서 Pages를 활성화하면 몇 분 내에 앱이 배포됩니다. NetlifyVercel을 사용하면 더욱 간편하게 배포할 수 있으며, 드래그 앤 드롭만으로 배포가 완료됩니다.

마무리 및 확장 아이디어

축하합니다! 30분만에 만드는 Todo App 완성 가이드를 따라 완전한 Todo 애플리케이션을 만들었습니다. 이 프로젝트를 통해 DOM 조작, 이벤트 처리, Local Storage 활용 등 실무에서 필요한 핵심 기술을 익혔습니다.

확장 아이디어:

  • 백엔드 API 연동 (Node.js + Express + MongoDB)
  • 사용자 인증 기능 추가
  • React나 Vue.js로 리팩토링
  • PWA(Progressive Web App)로 변환
  • 마감일과 알림 기능 추가
  • 카테고리별 분류 기능

이 프로젝트는 포트폴리오에 추가하기 좋으며, 다양한 방향으로 확장하여 더 복잡한 애플리케이션으로 발전시킬 수 있습니다. 계속해서 새로운 기능을 추가하며 실력을 향상시켜보세요!

📚 함께 읽으면 좋은 글

1

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

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

2

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

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

3

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

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

4

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

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

5

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

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

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

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

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

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

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

30분만에 만드는 Todo App 완성 가이드 관련해서 궁금한 점이 더 있으시다면 언제든 물어보세요!

💡
유용한 정보 공유

궁금한 점 질문

🤝
경험담 나누기

👍
의견 표현하기

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

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

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

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

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

💡
최신 트렌드
2025년 기준

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

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

답글 남기기