Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"printWidth": 120,
"tabWidth": 4,
"singleQuote": true,
"trailingComma": "all",
"semi": false
}
78 changes: 77 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,77 @@
# 리액트 투두 앱 만들기 미션 레포
# ✅ React Todo App

![Todo App Preview](./preview.svg)

<br/>

## 📌 프로젝트 소개

React의 핵심 개념인 **컴포넌트 분리**, **Custom Hook**, **상태 관리(useState/useRef)** 를 직접 구현해보는 Todo 앱입니다.
할 일 추가 / 완료 토글 / 삭제 기능을 갖추고 있으며, 관심사 분리 원칙에 따라 로직과 UI를 구분하여 작성했습니다.

<br/>

## 🛠 기술 스택

| 구분 | 사용 기술 |
| ---------- | ------------------------------ |
| 프레임워크 | React 18 |
| 빌드 도구 | Vite |
| 언어 | JavaScript (JSX) |
| 상태 관리 | useState, useRef (Custom Hook) |

<br/>

## ⚙️ 구현 기능

- ✅ 할 일 **추가** — 입력 후 등록 버튼 또는 Enter 키
- ✅ 할 일 **완료 토글** — 체크박스 클릭으로 완료/미완료 전환
- ✅ 할 일 **삭제** — 항목별 삭제 버튼
- ✅ 빈 입력 **유효성 검사** — 공백 입력 시 경고 알림
- ✅ 최신 항목이 **목록 상단**에 표시

<br/>

## 🗂 컴포넌트 구조

```
src/
├── App.jsx # 루트 컴포넌트 — 상태·핸들러 배분
├── hooks/
│ └── useTodos.js # Custom Hook — 상태 및 비즈니스 로직
└── components/
├── TodoWriteForm.jsx # 할 일 입력 폼
├── TodoList.jsx # 할 일 목록 렌더링
└── TodoItem.jsx # 개별 할 일 아이템
```

### 데이터 흐름

```
useTodos (Custom Hook)
↓ todos, addTodo, toggleTodo, removeTodo
App.jsx
├─→ TodoWriteForm (addTodo)
└─→ TodoList (todos, toggleTodo, removeTodo)
└─→ TodoItem × N
```

| 컴포넌트 | 역할 |
| --------------- | ---------------------------------------------- |
| `useTodos` | `todos` 상태 및 CRUD 로직 관리 |
| `App` | Hook에서 받은 상태·함수를 하위 컴포넌트에 전달 |
| `TodoWriteForm` | 폼 제출 이벤트 처리 및 `addTodo` 호출 |
| `TodoList` | 배열을 순회하며 `TodoItem` 렌더링 |
| `TodoItem` | 체크박스·삭제 버튼 UI 및 이벤트 처리 |

<br/>

## 🚀 실행 방법

```bash
# 패키지 설치
npm install

# 개발 서버 실행
npm run dev
```
29 changes: 29 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{js,jsx}'],
extends: [
js.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
rules: {
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
},
},
])
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>[AIBE6/2팀/임현호] TODO APP</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
Loading