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

프로젝트 소개 및 목표

30분만에 만드는 Todo App 완성 가이드는 웹 개발 입문자부터 중급 개발자까지 누구나 따라할 수 있는 실전 프로젝트입니다. 단순해 보이지만 CRUD(Create, Read, Update, Delete) 기능을 모두 구현하며, 상태 관리와 로컬 스토리지 활용까지 경험할 수 있습니다. 이 가이드를 통해 실제 동작하는 웹 애플리케이션을 완성하고, 포트폴리오에 추가할 수 있는 프로젝트를 만들어보세요. 모던 자바스크립트 문법과 DOM 조작, 이벤트 핸들링 등 실무에서 필수적인 기술들을 자연스럽게 익힐 수 있습니다.

필요한 기술 스택

이 프로젝트는 순수 바닐라 자바스크립트로 구현됩니다. 별도의 프레임워크나 라이브러리 설치 없이 시작할 수 있어 초보자에게 적합합니다.

  • HTML5: 시맨틱 마크업 구조
  • CSS3: Flexbox를 활용한 반응형 디자인
  • JavaScript (ES6+): 화살표 함수, 템플릿 리터럴, 배열 메서드
  • Local Storage API: 데이터 영구 저장

텍스트 에디터(VS Code 추천)와 최신 브라우저만 있으면 바로 시작할 수 있습니다.

프로젝트 셋업

먼저 프로젝트 폴더를 생성하고 기본 파일 구조를 만들어봅시다.

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

이제 index.html 파일에 기본 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>My Todo List</h1>
        <div class="input-section">
            <input type="text" id="todoInput" placeholder="할 일을 입력하세요">
            <button id="addBtn">추가</button>
        </div>
        <ul id="todoList"></ul>
    </div>
    <script src="app.js"></script>
</body>
</html>

단계별 구현 과정

1단계: CSS 스타일링 (5분)

사용자 경험을 높이는 깔끔한 디자인을 만들어봅시다. Flexbox를 사용하여 중앙 정렬하고, 부드러운 애니메이션 효과를 추가합니다.

* {
    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;
}

.container {
    background: white;
    padding: 2rem;
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    min-width: 400px;
}

h1 {
    color: #333;
    margin-bottom: 1.5rem;
    text-align: center;
}

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

#todoInput {
    flex: 1;
    padding: 0.8rem;
    border: 2px solid #e0e0e0;
    border-radius: 5px;
    font-size: 1rem;
}

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

#addBtn {
    padding: 0.8rem 1.5rem;
    background: #667eea;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 1rem;
    transition: background 0.3s;
}

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

#todoList {
    list-style: none;
}

.todo-item {
    display: flex;
    align-items: center;
    padding: 1rem;
    background: #f8f9fa;
    margin-bottom: 0.5rem;
    border-radius: 5px;
    transition: all 0.3s;
}

.todo-item:hover {
    background: #e9ecef;
    transform: translateX(5px);
}

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

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

.todo-item span {
    flex: 1;
}

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

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

2단계: 자바스크립트 기본 구조 (5분)

DOM 요소를 선택하고 기본 변수들을 선언합니다. 로컬 스토리지에서 기존 할 일 목록을 불러오는 초기화 로직도 포함됩니다.

// DOM 요소 선택
const todoInput = document.getElementById('todoInput');
const addBtn = document.getElementById('addBtn');
const todoList = document.getElementById('todoList');

// 할 일 목록 배열
let todos = JSON.parse(localStorage.getItem('todos')) || [];

// 초기 렌더링
renderTodos();

3단계: 할 일 추가 기능 (7분)

30분만에 만드는 Todo App 완성 가이드의 핵심 기능인 할 일 추가를 구현합니다. 사용자 입력을 검증하고, 고유 ID를 생성하여 중복을 방지합니다.

// 할 일 추가 함수
function addTodo() {
    const todoText = todoInput.value.trim();
    
    // 입력 값 검증
    if (todoText === '') {
        alert('할 일을 입력해주세요!');
        return;
    }
    
    // 새 할 일 객체 생성
    const newTodo = {
        id: Date.now(),
        text: todoText,
        completed: false
    };
    
    // 배열에 추가
    todos.push(newTodo);
    
    // 로컬 스토리지에 저장
    saveTodos();
    
    // 화면 업데이트
    renderTodos();
    
    // 입력 필드 초기화
    todoInput.value = '';
    todoInput.focus();
}

// 이벤트 리스너 등록
addBtn.addEventListener('click', addTodo);
todoInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
        addTodo();
    }
});

4단계: 할 일 렌더링 (5분)

배열의 데이터를 화면에 표시하는 함수입니다. forEach 메서드로 각 할 일을 순회하며 HTML 요소를 동적으로 생성합니다.

// 할 일 목록 렌더링
function renderTodos() {
    // 기존 목록 초기화
    todoList.innerHTML = '';
    
    // 각 할 일 항목 생성
    todos.forEach(todo => {
        const li = document.createElement('li');
        li.className = `todo-item ${todo.completed ? 'completed' : ''}`;
        li.dataset.id = todo.id;
        
        li.innerHTML = `
            
            ${todo.text}
            
        `;
        
        todoList.appendChild(li);
    });
}

5단계: 완료 토글 및 삭제 기능 (5분)

이벤트 위임 패턴을 사용하여 동적으로 생성된 요소들의 이벤트를 효율적으로 처리합니다.

// 이벤트 위임으로 완료/삭제 처리
todoList.addEventListener('click', (e) => {
    const todoItem = e.target.closest('.todo-item');
    if (!todoItem) return;
    
    const todoId = parseInt(todoItem.dataset.id);
    
    // 체크박스 클릭 시 완료 토글
    if (e.target.type === 'checkbox') {
        toggleTodo(todoId);
    }
    
    // 삭제 버튼 클릭 시 삭제
    if (e.target.classList.contains('delete-btn')) {
        deleteTodo(todoId);
    }
});

// 완료 상태 토글
function toggleTodo(id) {
    todos = todos.map(todo => 
        todo.id === id ? {...todo, completed: !todo.completed} : todo
    );
    saveTodos();
    renderTodos();
}

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

6단계: 로컬 스토리지 연동 (3분)

데이터를 브라우저에 영구 저장하여 페이지를 새로고침해도 할 일 목록이 유지되도록 합니다.

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

테스트 및 배포

구현이 완료되면 다양한 시나리오로 테스트해봅시다.

  1. 기능 테스트: 할 일 추가, 완료 체크, 삭제가 정상 동작하는지 확인
  2. 데이터 지속성 테스트: 페이지 새로고침 후에도 데이터가 유지되는지 확인
  3. 엣지 케이스 테스트: 빈 값 입력, 특수문자 입력 등
  4. 반응형 테스트: 모바일 화면에서도 잘 보이는지 확인

배포는 GitHub Pages를 활용하면 무료로 쉽게 할 수 있습니다. 리포지토리를 생성하고 Settings > Pages에서 배포 설정을 하면 몇 분 안에 실제 URL로 접속 가능합니다. Netlify나 Vercel을 사용하면 더욱 간편한 배포와 자동 업데이트가 가능합니다.

마무리 및 확장 아이디어

축하합니다! 30분만에 만드는 Todo App 완성 가이드를 따라 완전히 동작하는 Todo 앱을 만들었습니다. 이제 다음 기능들을 추가하여 포트폴리오를 더욱 풍성하게 만들어보세요.

  • 필터링 기능: 전체/완료/미완료 할 일 필터
  • 수정 기능: 기존 할 일 텍스트 편집
  • 우선순위: 중요도에 따른 색상 구분
  • 검색 기능: 할 일 목록에서 키워드 검색
  • 카테고리: 업무/개인/쇼핑 등 분류
  • 마감일: 날짜 관리 기능
  • 드래그 앤 드롭: 순서 변경 기능
  • 다크모드: 테마 전환 기능

이 프로젝트는 React, Vue 등의 프레임워크로 리팩토링하는 연습에도 최적입니다. 상태 관리 라이브러리(Redux, Vuex)를 적용하거나 백엔드 API를 연결하여 풀스택 애플리케이션으로 확장할 수도 있습니다.

📚 함께 읽으면 좋은 글

1

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

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

2

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

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

3

JWT 인증 시스템 구현하기 – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 15.
🎯 JWT 인증 시스템 구현하기

4

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

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

5

JWT 인증 시스템 구현하기 – 완성까지 한번에!

📂 프로젝트 아이디어
📅 2025. 10. 9.
🎯 JWT 인증 시스템 구현하기

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

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

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

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

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

이 글에서 가장 도움이 된 부분은 어떤 것인가요?

💡
유용한 정보 공유

궁금한 점 질문

🤝
경험담 나누기

👍
의견 표현하기

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

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

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

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

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

💡
최신 트렌드
2025년 기준

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

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

답글 남기기