Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3c974ab
[SETTING] React + TS + Vite 프로젝트 초기세팅
waldls Mar 19, 2026
a81a8cf
[MOD] 파비콘 추가 및 불필요한 파일 삭제
waldls Mar 20, 2026
28b946c
[FEAT] TailwindCSS 전역 스타일 설정
waldls Mar 20, 2026
9554c17
[ADD] 타입 및 날짜 유틸 추가
waldls Mar 20, 2026
adadb5d
[FEAT] useTodoStore, useCalendar 커스텀 훅 구현
waldls Mar 20, 2026
8f0c1fc
[FEAT] 캘린더 컴포넌트 구현
waldls Mar 20, 2026
bd1f343
[FEAT] Todo 컴포넌트 구현
waldls Mar 20, 2026
ad591ef
[FEAT] 통계 컴포넌트 및 페이지 레이아웃 구현
waldls Mar 20, 2026
577db67
[REFACTOR] 공통 버튼 컴포넌트 분리
waldls Mar 20, 2026
8a87857
[REFACTOR] memo/useCallback으로 렌더링 최적화
waldls Mar 20, 2026
6bd15b4
[FIX] 불필요한 memo 제거
waldls Mar 20, 2026
d17e1df
[REFACTOR] CSS 네이밍 개선 및 폰트 유틸 정리
waldls Mar 20, 2026
20ae98a
[REFACTOR] CalendarDay fontClass 제거 및 레이아웃 간소화
waldls Mar 20, 2026
445eae1
[RENAME] 파일명 index -> todo로 변경
waldls Mar 20, 2026
7f5249d
[REFACTOR] 통계 및 입력 컴포넌트 memo/useMemo 최적화
waldls Mar 20, 2026
d8efdfa
[FIX] useCalendar today를 모듈 레벨 상수에서 hook 내부 useState로 이동
waldls Mar 20, 2026
afe673e
[DEPLOY] 2주차 과제 배포
waldls Mar 20, 2026
c1e004e
[CHORE] 폰트 수정
waldls Mar 20, 2026
1ad9962
[DOCS] 리드미 수정
waldls Mar 20, 2026
50ad711
[DOCS] 리드미 주요 기능 내용 추가
waldls Mar 20, 2026
6f0270b
[REFACTOR] font-sans 중복 제거하고 타이포 유틸로 폰트 책임 이동
waldls Mar 20, 2026
673106a
[REFACTOR] useTodoStore id를 UUID로 변경 및 persistStore 에러 핸들링 추가
waldls Mar 20, 2026
29af023
[FIX] 타입 에러 해결
waldls Mar 20, 2026
595927e
[FIX] TODO id 타입 string으로 변경
waldls Mar 20, 2026
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?
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
build
.env
7 changes: 7 additions & 0 deletions .prettierrc
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://tailwindcss.com/blog/automatic-class-sorting-with-prettier
유민님 tailwind 클래스 자동정렬 플러그인 써보셔도 좋을거 같습니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
}
145 changes: 71 additions & 74 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,71 @@
# 2주차 과제: React Todo
# 서론

안녕하세요 🙌🏻 23기 프론트엔드 운영진 **원채영**입니다.

다들 1주차 미션인 Vanilla Todo를 만드시느라 수고 많으셨습니다! 1주차 미션을 통해 Vanilla JS로 SPA를 구현하면서 React를 사용하지 않을 때의 불편함을 느껴보셨을 것이라 생각합니다.

그리하여 이번 미션은, 1주차 스터디 미션으로 주어진 Todo list 만들기를 **React**로 리팩토링하는 것입니다❗️

기존에 React를 어느 정도 사용해보신 분들께는 더 효율적인 구조와 디자인 패턴을 고민해보는 주차가 될 것이고,
아직 React를 깊게 접해보지 못한 분들께는 기존 애플리케이션을 React로 포팅하는 과정을 통해 왜 React가 등장하게 되었는지, 그리고 React의 방식이 왜 Vanilla JS보다 효율적인지 체감해보는 주차가 될 것이라 생각합니다.

비교적 가벼운 미션인 만큼 코드를 짜는 데 있어 여러분의 **창의성**을 충분히 발휘해보시기 바랍니다. _❕작동하기만 하면 되는 것보다 같은 코드를 짜는 여러가지 방식과 패턴에 대해 많이 고민해보시고, 본인이 작성할 수 있는 가장 창의적인 방법으로 코드를 작성해주셨으면 합니다.❕_ 여러분이 미션을 수행하면서 한 고민과 선택들이 많을수록, 이번 스터디에서 더 많은 것을 얻어가실 수 있을 거라 기대합니다.

또한 이번 과제에서는 React 프로젝트 생성 시 **Vite 사용이 필수입니다.**
기존 React 프로젝트 생성 방식 중 하나였던 Create React App(CRA) 은 2025년에 공식적으로 지원 종료가 발표되었습니다.
추가로 공식 문서에서도 Vite 기반의 프로젝트 생성을 권장하고 있으며, 과제를 진행하면서 Vite를 활용한 프로젝트 환경 세팅, 빌드 툴, 번들링 등에 대해 자연스럽게 익혀보는 경험이 도움이 될 것이라 생각합니다.

과제를 진행하다가 막히는 부분이 있더라도, 우선은 스스로 공부하고 찾아보며 해결해보는 과정을 권장드립니다.
다만 미션과 관련해 운영진의 도움이 필요하다면, 언제든 프론트엔드 카카오톡방에 질문 남겨주세요!

# 미션

## 예시

- [리액트 투두 예시](https://react-todo-21th-snowy.vercel.app/)

## 미션 목표

- VSCode, Prettier를 이용하여 개발환경을 관리합니다.
- React의 기초를 이해합니다.
- React를 통한 어플리케이션 상태 관리 방법을 이해합니다.
- React Hooks에 대한 기초를 이해합니다.
- Vite를 통한 React 프로젝트 개발환경 구축을 익힙니다.
- Tailwind CSS를 활용한 유틸리티 클래스 기반 스타일링 방식을 익힙니다.

## 기한

- 2026년 3월 21일 토요일 23:59까지

## Review Questions

- Virtual-DOM은 무엇이고, 이를 사용함으로서 얻는 이점은 무엇인가요?
- React.memo(), useMemo(), useCallback() 함수로 진행할 수 있는 리액트 렌더링 최적화에 대해 설명해주세요. 다른 방식이 있다면 이에 대한 소개도 좋습니다.
- React 컴포넌트 생명주기에 대해서 설명해주세요.

## 필수 요건
- 1주차 미션의 결과물을 그대로 React로 구현합니다. (‼️ todo / done 개수 잊지 마세요 ‼️)
- Tailwind CSS를 사용합니다
- React Hooks만을 사용해 상태를 관리합니다.(전역 상태관리 라이브러리 사용 XX)
- Vite를 활용하여 React 프로젝트 환경 구축을 진행합니다

## 선택 요건

- 기존 Todo-list에 여러분들이 추가하고 싶은 기능과 디자인을 자유롭게 추가해보세요.
- TypeScript를 활용하여 프로젝트를 진행해보세요.

## 로컬 실행방법
`npm run dev`: Vite 개발 서버를 실행하고, 변경 사항이 저장될 때마다 자동으로 반영됩니다.

# 링크 및 참고자료

- [create react app (CRA)](https://create-react-app.dev/docs/getting-started/)
- [리액트 docs 주요 개념 1-12](https://react.dev/learn)
- [리액트 docs Hook 1-3](https://react.dev/reference/react)
- [리액트 useEffect 완벽 가이드](https://overreacted.io/ko/a-complete-guide-to-useeffect/)
- [컴포넌트 네이밍을 위한 자바스크립트 네이밍 컨벤션](https://velog.io/@cada/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8A%A4%ED%83%80%EC%9D%BC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EB%84%A4%EC%9D%B4%EB%B0%8D-%EC%BB%A8%EB%B2%A4%EC%85%98-%ED%8E%B8)
- [useState, useEffect hooks](https://velog.io/@velopert/react-hooks#1-usestate)
- [tailwind 공식 문서](https://tailwindcss.com/docs/installation/using-vite)
- [vscode prettier 설정](https://velog.io/@gangk_99/VS-Code-Prettier-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0)
- [create react app (CRA) 지원종료 공식문서](https://react.dev/blog/2025/02/14/sunsetting-create-react-app)

- [create react app 지원종료관련 okky 커뮤니티 게시글](https://okky.kr/articles/1527414)
- [cra 대신에 vite로 React 프로젝트 시작하기](https://www.daleseo.com/vite-react/)
- [Vite 실무 적용기 - 설명 + 프로젝트 설정](https://blog.hectodata.co.kr/bonjour-vite/)
# [CEOS 23rd Week2] - React Todo

캘린더를 기준으로 날짜별 할 일을 관리하고, 오늘과 이번 달 진행 상황을 함께 확인할 수 있는 [React Todo](https://react-todo-23rd-eta.vercel.app/) 프로젝트입니다.

[Vanilla Todo](https://vanilla-todo-23rd.vercel.app/)를 React 기반으로 마이그레이션한 버전입니다.

## 주요 기능

- 날짜 선택 기반 Todo 추가, 완료, 삭제
- 월간 캘린더에서 날짜 이동 및 선택
- 오늘/월별 Todo 통계 제공
- `localStorage` 기반 데이터 저장
- 모바일과 데스크톱에 대응하는 반응형 UI

## 폴더 구조

```text
src/
├─ components/ # 컴포넌트
│ ├─ Calendar/ # 캘린더 영역 컴포넌트
│ │ ├─ CalendarDay.tsx
│ │ ├─ CalendarGrid.tsx
│ │ ├─ CalendarHeader.tsx
│ │ └─ CalendarSection.tsx
│ ├─ Common/ # 공통 컴포넌트
│ │ └─ Button.tsx
│ ├─ Stats/ # 통계 영역 컴포넌트
│ │ ├─ MonthStats.tsx
│ │ └─ TodayStats.tsx
│ └─ Todo/ # 할 일 영역 컴포넌트
│ ├─ TodoInputArea.tsx
│ ├─ TodoItem.tsx
│ ├─ TodoList.tsx
│ └─ TodoSection.tsx
├─ hooks/ # 캘린더와 할 일 로직을 관리하는 커스텀 훅
│ ├─ useCalendar.ts
│ └─ useTodoStore.ts
├─ pages/ # 화면 단위 페이지 컴포넌트
│ └─ TodoPage.tsx # 메인 Todo 페이지
├─ types/ # 타입 정의
│ └─ todo.ts
├─ constants/ # 상수
│ └─ date.ts
├─ utils/ # 유틸 함수
│ └─ date.ts
├─ App.tsx # 최상위 App 컴포넌트
├─ main.tsx # React 앱 마운트 진입점
└─ index.css # 글로벌 스타일
```

## 기술 스택

| 구분 | 기술 | 사용 이유 |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Framework | <img src="https://img.shields.io/badge/react-20232A.svg?style=for-the-badge&logo=react&logoColor=61DAFB" /> | 컴포넌트 기반으로 UI를 구성하고, 상태 변화에 따라 화면을 효율적으로 렌더링하기 위해 사용 |
| Language | <img src="https://img.shields.io/badge/typescript-3178C6.svg?style=for-the-badge&logo=typescript&logoColor=white" /> | Todo 데이터와 props를 명확한 타입으로 관리해, 개발 중 오류를 줄이기 위해 사용 |
| Build Tool | <img src="https://img.shields.io/badge/vite-9135FF.svg?style=for-the-badge&logo=vite&logoColor=FFD62E" /> | 빠른 개발 서버와 간단한 빌드 환경으로 개발 효율을 높이기 위해 사용 |
| Styling | <img src="https://img.shields.io/badge/tailwindcss-06B6D4.svg?style=for-the-badge&logo=tailwindcss&logoColor=white" /> | 유틸리티 클래스 기반으로 스타일을 빠르고 일관되게 적용하기 위해 사용 |
| Linting | <img src="https://img.shields.io/badge/eslint-4B32C3.svg?style=for-the-badge&logo=eslint&logoColor=white" /> | 코드 스타일을 일정하게 유지하고, 잠재적인 실수를 미리 찾기 위해 사용 |
| Formatting | <img src="https://img.shields.io/badge/prettier-1A2B34.svg?style=for-the-badge&logo=prettier&logoColor=F7B93E" /> | 코드 포맷을 자동으로 통일해, 가독성과 유지보수성을 높이기 위해 사용 |
| Git Hooks | <img src="https://img.shields.io/badge/husky-2E2E2E.svg?style=for-the-badge" /> <img src="https://img.shields.io/badge/lint--staged-4B5563.svg?style=for-the-badge" /> | 커밋 전에 린트와 포맷 검사를 자동화해, 코드 품질을 안정적으로 유지하기 위해 사용 |
| Deploy | <img src="https://img.shields.io/badge/vercel-000000.svg?style=for-the-badge&logo=vercel&logoColor=white" /> | 배포 후 실제 동작을 빠르게 확인하고 결과를 바로 테스트하기 위해 사용 |

## 실행 방법

```bash
git clone -b waldls https://github.com/waldls/react-todo-23rd.git
cd react-todo-23rd
npm install
npm run dev
```
37 changes: 37 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
import { defineConfig, globalIgnores } from 'eslint/config';
import eslintConfigPrettier from 'eslint-config-prettier';
import eslintPluginPrettier from 'eslint-plugin-prettier';

export default defineConfig([
globalIgnores(['dist', 'node_modules', 'build', 'eslint.config.js', 'vite.config.ts']),
{
files: ['**/*.{ts,tsx,js,jsx}'],
extends: [js.configs.recommended, ...tseslint.configs.recommended],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parser: tseslint.parser,
parserOptions: {
project: ['./tsconfig.app.json', './tsconfig.node.json'],
tsconfigRootDir: import.meta.dirname,
},
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
prettier: eslintPluginPrettier,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'prettier/prettier': 'error',
'@typescript-eslint/no-unused-vars': 'warn',
},
},
eslintConfigPrettier,
]);
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>React Todo</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading