diff --git a/README.md b/README.md
index 3c0710d2..e8b27d7f 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,26 @@
-# react-todo-list-precourse
\ No newline at end of file
+# react-todo-list-precourse
+
+## 할 일 목록 애플리케이션
+
+- 이 프로그램은 사용자가 할 일을 입력하여 todo list를 관리할 수 있습니다.
+
+### 사용 방법
+
+1. 입력 필드에 할 일을 입력하고 엔터를 눌러 추가합니다.
+2. 체크박스를 클릭하여 할 일을 완료로 표시합니다.
+3. "All", "Active", "Completed" 버튼을 클릭하여 할 일을 필터링합니다.
+4. "Clear completed" 버튼을 클릭하여 완료된 할 일을 삭제합니다.
+5. 입력 필드 왼쪽의 화살표 버튼을 클릭하여 모든 할 일을 완료로 표시합니다.
+
+### 구현된 기능 목록
+
+- 사용자 인터페이스 구성
+- 새로운 할 일 추가 기능
+- 할 일 완료 표시
+- 완료된 할 일 삭제 버튼
+
+### 구현할 기능 목록
+
+- 완료되지 않은 할 일 개수 출력
+- 할 일을 상태별로 필터링(All, Active, Completed)
+- 모든 할 일 완료로 표시
\ No newline at end of file
diff --git a/index.html b/index.html
index b021b5c8..d669e6c3 100644
--- a/index.html
+++ b/index.html
@@ -1,12 +1,12 @@
-
+
-
+ todo-list
-
+
diff --git a/src/App.css b/src/App.css
new file mode 100644
index 00000000..d1ace32b
--- /dev/null
+++ b/src/App.css
@@ -0,0 +1,63 @@
+body {
+ background-color: #fce4ec;
+}
+
+.inner {
+ width: 600px;
+ margin: 0 auto;
+}
+
+h1 {
+ font-size: 70px;
+ font-family: "Helvetica Neue", "Helvetica", "Arial", "sans-serif";
+ font-weight: 300;
+ text-align: center;
+}
+
+input#todoInput {
+ display: block;
+ width: 400px;
+ height: 60px;
+ padding: 0 50px;
+ margin: 0 auto;
+ font-size: 25px;
+}
+
+ul {
+ width: 500px;
+ margin: 20px auto;
+ padding: 0;
+}
+
+li {
+ display: flex;
+ align-items: center;
+ position: relative;
+ border-bottom: 1px solid black;
+ list-style: none;
+ padding: 15px 0px 15px 20px;
+}
+
+li:last-child {
+ border: none;
+}
+
+li .todo {
+ position: absolute;
+ width: 350px;
+ margin: auto 70px;
+ font-size: 25px;
+ font-weight: 200;
+ flex-grow: 1;
+}
+
+li img {
+ width: 50px;
+ height: 50px;
+ margin-left: auto;
+}
+
+.completed .todo {
+ text-decoration: line-through;
+ text-decoration-color: #f06292;
+}
diff --git a/src/App.js b/src/App.js
new file mode 100644
index 00000000..62d9ea5c
--- /dev/null
+++ b/src/App.js
@@ -0,0 +1,6 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import Main from './main';
+
+const root = ReactDOM.createRoot(document.getElementById('app'));
+root.render(React.createElement(Main));
\ No newline at end of file
diff --git a/src/components/CheckBox.css b/src/components/CheckBox.css
new file mode 100644
index 00000000..f9dd45f3
--- /dev/null
+++ b/src/components/CheckBox.css
@@ -0,0 +1,5 @@
+input#checkbox {
+ width: 50px;
+ height: 50px;
+ margin: 0;
+}
diff --git a/src/components/CheckBox.jsx b/src/components/CheckBox.jsx
new file mode 100644
index 00000000..41ad5c1d
--- /dev/null
+++ b/src/components/CheckBox.jsx
@@ -0,0 +1,14 @@
+import "./CheckBox.css";
+
+const CheckBox = ({ isChecked, onChange }) => {
+ return (
+
+ );
+};
+
+export default CheckBox;
diff --git a/src/components/DeleteButton.jsx b/src/components/DeleteButton.jsx
new file mode 100644
index 00000000..8888e317
--- /dev/null
+++ b/src/components/DeleteButton.jsx
@@ -0,0 +1,18 @@
+import deleteImg from "../img/deleteImg.png";
+import deleteTodo from "../utils/deleteTodo";
+
+function DeleteButton({index, todos, setTodos}) {
+ const handleClick = () => {
+ deleteTodo(index, todos, setTodos);
+ };
+
+ return(
+
+ )
+}
+
+export default DeleteButton;
\ No newline at end of file
diff --git a/src/components/Input.jsx b/src/components/Input.jsx
new file mode 100644
index 00000000..10424e3f
--- /dev/null
+++ b/src/components/Input.jsx
@@ -0,0 +1,14 @@
+function Input({ value, onChange, onKeyPress }) {
+ return (
+
+ );
+}
+
+export default Input;
diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx
new file mode 100644
index 00000000..b85fe05b
--- /dev/null
+++ b/src/components/TodoList.jsx
@@ -0,0 +1,25 @@
+import { useState } from "react";
+import CheckBox from "./CheckBox";
+import toggleTodo from "../utils/toggleTodo";
+import DeleteButton from "./DeleteButton";
+import deleteTodo from "../utils/deleteTodo";
+
+const TodoList = ({ todos, setTodos}) => {
+ const [completedTodos, setCompletedTodos] = useState([]);
+
+ return (
+
+ {todos.map((todo, index) => (
+
+ toggleTodo(index, completedTodos, setCompletedTodos)}/>
+ {todo}
+
+
+ ))}
+
+ );
+};
+
+export default TodoList;
diff --git a/src/img/deleteImg.png b/src/img/deleteImg.png
new file mode 100644
index 00000000..db96e100
Binary files /dev/null and b/src/img/deleteImg.png differ
diff --git a/src/main.js b/src/main.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/main.jsx b/src/main.jsx
new file mode 100644
index 00000000..7760e662
--- /dev/null
+++ b/src/main.jsx
@@ -0,0 +1,27 @@
+import React, { useState } from "react";
+import "./App.css";
+import Input from "./components/Input.jsx";
+import TodoList from "./components/TodoList.jsx";
+import handleInputChange from "./utils/handleInputChange.jsx";
+import handleKeyPress from "./utils/handleKeyPress.jsx";
+import addTodo from "./utils/addTodo.jsx";
+
+function Main() {
+ const [todos, setTodos] = useState([]);
+ const [inputValue, setInputValue] = useState("");
+ return (
+
+
🎀 todos
+ handleInputChange(e, setInputValue)}
+ onKeyPress={(e) =>
+ handleKeyPress(e, todos, setTodos, inputValue, setInputValue)
+ }
+ />
+
+
+ );
+}
+
+export default Main;
diff --git a/src/utils/addTodo.jsx b/src/utils/addTodo.jsx
new file mode 100644
index 00000000..53e75827
--- /dev/null
+++ b/src/utils/addTodo.jsx
@@ -0,0 +1,6 @@
+const addTodo = (todos, inputValue) => {
+ if (inputValue.trim() === "") return todos;
+ return [...todos, inputValue];
+};
+
+export default addTodo;
\ No newline at end of file
diff --git a/src/utils/deleteTodo.jsx b/src/utils/deleteTodo.jsx
new file mode 100644
index 00000000..b36a77f3
--- /dev/null
+++ b/src/utils/deleteTodo.jsx
@@ -0,0 +1,5 @@
+const deleteTodo = (index, todos, setTodos) => {
+ setTodos(todos.filter((_, i) => i !== index));
+};
+
+export default deleteTodo;
diff --git a/src/utils/handleInputChange.jsx b/src/utils/handleInputChange.jsx
new file mode 100644
index 00000000..96ea24e9
--- /dev/null
+++ b/src/utils/handleInputChange.jsx
@@ -0,0 +1,5 @@
+const handleInputChange = (e, setInputValue) => {
+ setInputValue(e.target.value);
+};
+
+export default handleInputChange;
diff --git a/src/utils/handleKeyPress.jsx b/src/utils/handleKeyPress.jsx
new file mode 100644
index 00000000..6e217906
--- /dev/null
+++ b/src/utils/handleKeyPress.jsx
@@ -0,0 +1,12 @@
+const handleKeyPress = (e, todos, setTodos, inputValue, setInputValue) => {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ const newTodo = inputValue.trim(); // 입력된 값의 앞뒤 공백 제거
+ if (newTodo !== "") { //입력된 값이 공백이 아닌 경우에만
+ setTodos((prevTodos) => [...prevTodos, newTodo]); // 이전 할 일에 새로운 할 일 추가하여 리스트 업데이트
+ setInputValue(""); // 입력값 초기화
+ }
+ }
+};
+
+export default handleKeyPress;
diff --git a/src/utils/toggleTodo.jsx b/src/utils/toggleTodo.jsx
new file mode 100644
index 00000000..b79312d5
--- /dev/null
+++ b/src/utils/toggleTodo.jsx
@@ -0,0 +1,11 @@
+const toggleTodo = (index, completedTodos, setCompletedTodos) => {
+ //index의 할 일이 이미 완료된 할 일인지 확인
+ const isCompleted = completedTodos.includes(index);
+ if (isCompleted) {
+ setCompletedTodos(completedTodos.filter((item) => item !== index));
+ } else {
+ setCompletedTodos([...completedTodos, index]);
+ }
+};
+
+export default toggleTodo;
diff --git a/vite.config.ts b/vite.config.ts
index 5a33944a..d1fa1aef 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,6 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
-// https://vitejs.dev/config/
export default defineConfig({
- plugins: [react()],
-})
+ plugins: [react({})],
+});