์—ด ๋ฒˆ์งธ ๋ฌธ์ œ: To-Do List ์•ฑ ๋งŒ๋“ค๊ธฐ

2025. 10. 27. 16:07ยทw. Gemini

์š”๊ตฌ์‚ฌํ•ญ

  1. HTML ๊ตฌ์กฐ:
    • ํ•  ์ผ ์ž…๋ ฅ ํ•„๋“œ์™€ ๋ฒ„ํŠผ์„ ํฌํ•จํ•˜๋Š” <form id="todo-form">์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
      • <input type="text" id="todo-input"> (ํ•  ์ผ ์ž…๋ ฅ)
      • <button type="submit">์ถ”๊ฐ€</button>
    • ํ•  ์ผ ๋ชฉ๋ก์ด ํ‘œ์‹œ๋  ๋นˆ <ul> ํƒœ๊ทธ (id="todo-list")๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  2. CSS ์Šคํƒ€์ผ (์„ ํƒ ์‚ฌํ•ญ):
    • ์ถ”๊ฐ€๋œ <li> ํ•ญ๋ชฉ์— ๋งˆ์šฐ์Šค ์˜ค๋ฒ„ ์‹œ ๋ฐฐ๊ฒฝ์ƒ‰์ด ๋ฐ”๋€Œ๋Š” ๋“ฑ ๊ฐ„๋‹จํ•œ ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜์—ฌ ์‹œ๊ฐ์ ์œผ๋กœ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
  3. JavaScript ๊ธฐ๋Šฅ (๊ฐ€์žฅ ์ค‘์š”):
    • ํ•  ์ผ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ:
      • ํผ (#todo-form)์— submit ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
      • ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ์„ ๋ง‰๊ณ  (ํžŒํŠธ: event.preventDefault()) ์ž…๋ ฅ๋œ ํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
      • ์ƒˆ๋กœ์šด <li> ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ ์•ˆ์— ์ž…๋ ฅ๋œ ํ…์ŠคํŠธ์™€ ์‚ญ์ œ ๋ฒ„ํŠผ (<button class="delete-btn">์‚ญ์ œ</button>)์„ ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค.
      • ์ƒˆ๋กœ์šด <li> ์š”์†Œ๋ฅผ #todo-list์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
      • ์ž…๋ ฅ ํ•„๋“œ (#todo-input)๋ฅผ ๋น„์›๋‹ˆ๋‹ค.
    • ํ•  ์ผ ์‚ญ์ œ ๊ธฐ๋Šฅ (์ด๋ฒคํŠธ ์œ„์ž„ ์‚ฌ์šฉ):
      • ๋ชฉ๋ก ์ปจํ…Œ์ด๋„ˆ (#todo-list)์— ํด๋ฆญ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ํ•˜๋‚˜๋งŒ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. (์ƒˆ๋กœ ์ƒ์„ฑ๋˜๋Š” ๋ชจ๋“  ์‚ญ์ œ ๋ฒ„ํŠผ์— ๊ฐœ๋ณ„ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Œ)
      • ํด๋ฆญ๋œ ์š”์†Œ๊ฐ€ .delete-btn ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง„ ๋ฒ„ํŠผ์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
      • ๋ฒ„ํŠผ์ด ๋งž๋‹ค๋ฉด, ํ•ด๋‹น ๋ฒ„ํŠผ์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ถ€๋ชจ <li> ์š”์†Œ๋ฅผ DOM์—์„œ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

 

๋”๋ณด๊ธฐ
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            margin: 0;
        }
        .todo {
            border: 4px solid #000;
        }
        .todo__controls {
            display: flex;
            align-items: center;
            column-gap: 5px;
            padding: 15px;
            border-bottom: 1px solid #333;
        }
        .todo__controls .todo__input {
            height: 25px;
            border: 1px solid #000;
            border-radius: 0;
        }
        .todo__controls .todo__add-btn {
            height: 25px;
            background-color: #333;
            cursor: pointer;
            color: #fff;
        }
        .todo__list {
            margin: 0;
            list-style-type: circle;
            color: #777
        }
        .todo__item {
            padding: 10px 0;
        }
        .todo__item:hover {
            color: #000;
            text-decoration: line-through;
        }
        .todo__item .todo__del-btn {
            margin-left: 5px;
            background-color: tomato;
            border: 1px solid tomato;
            color: #fff;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <form action="" id="todo-form" class="todo">
        <div class="todo__controls">
            <label class="todo__label">ํ•  ์ผ ์ž…๋ ฅ :
                <input type="text" name="" id="todo-input" class="todo__input">
            </label>
            <button type="submit" class="todo__add-btn">์ถ”๊ฐ€</button>
        </div>
        <ul id="todo-list" class="todo__list"></ul>
    </form>

    <script>
        document.addEventListener("DOMContentLoaded", () => {
            const todoForm = document.getElementById('todo-form');
            const todoInput = document.getElementById('todo-input');
            const todoList = document.getElementById('todo-list');


            todoForm.addEventListener('submit', (e) => {
                e.preventDefault();
                
                const taskText = todoInput.value.trim();
                
                if (taskText === '') {
                    alert('ํ•  ์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”!');
                    return;
                }

                const newItem = `
                    <li class="todo__item">
                        ${taskText}
                        <button type="button" class="todo__del-btn">์‚ญ์ œ</button>
                    </li>
                `;

                todoList.insertAdjacentHTML('beforeend', newItem);

                todoInput.value = '';

            })
            todoList.addEventListener('click', (e) => {
                if (e.target.classList.contains('todo__del-btn')) {
                    const listItemToDelete = e.target.closest('li');
    
                    listItemToDelete.remove();
                }
            });
        })
    </script>
</body>
</html>
์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋™์ผ์กฐ๊ฑด (์ƒˆ์ฐฝ์—ด๋ฆผ)

'w. Gemini' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

์—ด๋‘ ๋ฒˆ์งธ ๋ฌธ์ œ: ๋น„๋™๊ธฐ ์ž‘์—… ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ฐ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์ดํ•ด  (0) 2025.10.27
์—ดํ•œ ๋ฒˆ์งธ ๋ฌธ์ œ: ๋ฐฐ์—ด ๋ฐ ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•œ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ณ„์‚ฐ๊ธฐ  (0) 2025.10.27
์•„ํ™‰ ๋ฒˆ์งธ ๋ฌธ์ œ: Light/Dark ๋ชจ๋“œ ํ† ๊ธ€ ๋ฒ„ํŠผ ๋งŒ๋“ค๊ธฐ  (0) 2025.10.27
์—ฌ๋Ÿ ๋ฒˆ์งธ ๋ฌธ์ œ: Grid Area๋ฅผ ํ™œ์šฉํ•œ ๋ธ”๋กœ๊ทธ ๋ ˆ์ด์•„์›ƒ ๋งŒ๋“ค๊ธฐ  (0) 2025.10.27
์ผ๊ณฑ ๋ฒˆ์งธ ๋ฌธ์ œ: Grid์™€ Flexbox๋ฅผ ํ˜ผํ•ฉํ•œ ๋Œ€์‹œ๋ณด๋“œ ๋ ˆ์ด์•„์›ƒ ๋งŒ๋“ค๊ธฐ  (0) 2025.10.27
'w. Gemini' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • ์—ด๋‘ ๋ฒˆ์งธ ๋ฌธ์ œ: ๋น„๋™๊ธฐ ์ž‘์—… ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ฐ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์ดํ•ด
  • ์—ดํ•œ ๋ฒˆ์งธ ๋ฌธ์ œ: ๋ฐฐ์—ด ๋ฐ ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•œ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ณ„์‚ฐ๊ธฐ
  • ์•„ํ™‰ ๋ฒˆ์งธ ๋ฌธ์ œ: Light/Dark ๋ชจ๋“œ ํ† ๊ธ€ ๋ฒ„ํŠผ ๋งŒ๋“ค๊ธฐ
  • ์—ฌ๋Ÿ ๋ฒˆ์งธ ๋ฌธ์ œ: Grid Area๋ฅผ ํ™œ์šฉํ•œ ๋ธ”๋กœ๊ทธ ๋ ˆ์ด์•„์›ƒ ๋งŒ๋“ค๊ธฐ
๋น™๊ณ ๊ตฌ๋ง›ํƒ•
๋น™๊ณ ๊ตฌ๋ง›ํƒ•
  • ๋น™๊ณ ๊ตฌ๋ง›ํƒ•
    ๐•Ž๐”ผ๐”น ๐”ธ๐•ƒ๐•ƒ ๐•ƒ๐•†๐”พ
    ๋น™๊ณ ๊ตฌ๋ง›ํƒ•
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ๋ฐฉ๋ช…๋ก
    • ๊ธ€์“ฐ๊ธฐ
    • ๊ด€๋ฆฌ์ž
    • ์ „์ฒด๋ณด๊ธฐ N
      • w. Gemini N
      • w. GPTs
      • Before. 2021
  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    min-height:100%
    ie collapse ๋ฒ„๊ทธ
    footer ํ•˜๋‹จ์— ๊ณ ์ •
    border-collapse ์˜ค๋ฅ˜
    box-shadow
    css3
    footer ๊ณ ์ •
    input fileํƒœ๊ทธ ๋ฐ”๊พธ๊ธฐ
    ie9 ์„  ๋ฒ„๊ทธ
  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.5
๋น™๊ณ ๊ตฌ๋ง›ํƒ•
์—ด ๋ฒˆ์งธ ๋ฌธ์ œ: To-Do List ์•ฑ ๋งŒ๋“ค๊ธฐ
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”