-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2주차] 강다혜 미션 제출합니다. #9
Open
psst54
wants to merge
46
commits into
CEOS-Developers:master
Choose a base branch
from
psst54:psst54
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
8ff0d9c
chore: add prettierrc & apply formatter & update gitignore
psst54 24a4642
style: add reset.css file
psst54 a5edded
chore: support absolute path
psst54 0b78b9c
docs: add feature list
psst54 bc81d43
fix: fix no-line-at-the-end error
psst54 6766055
Merge pull request #1 from psst54/feature/setup
psst54 f1e2947
feature: make basic ui
psst54 4a68345
feature: add styled-components
psst54 3359b8b
feature: make board ui
psst54 4b18d9d
feat: make subject list
psst54 9be52ae
style: apply styles
psst54 d2b556f
Merge pull request #2 from psst54/feature/basic-layout
psst54 58ae455
feat: add useSubject hook
psst54 c99fea8
feat: split Subject component
psst54 aeb1253
feat: make subject input form
psst54 77820c5
Merge pull request #3 from psst54/feature/add-subject
psst54 2c8fc68
feat: add uuid for dependency
psst54 73c0a79
feat: make subject delete button
psst54 0c4b733
style: add icon color
psst54 9622e60
Merge pull request #4 from psst54/feature/remove-subject
psst54 7c2d63b
fix: move custom hook to parent component
psst54 088a3df
fix: fix svg prop names
psst54 24dedb9
feat: make hook/component for task
psst54 7d59b3d
feat: make Task component & addTask hook
psst54 7765b3b
Merge pull request #5 from psst54/feature/add-task
psst54 0b27b35
feat: remove task
psst54 1dddbd8
Merge pull request #6 from psst54/feature/remove-task
psst54 f20fd1e
feat: function to toggle task
psst54 b15d025
refactor: refactor task related function
psst54 467337a
feat: change state based on its taskList
psst54 4e03010
chore: rename function for detail
psst54 288d6d8
Merge pull request #7 from psst54/feature/toggle-task
psst54 0680b3b
feat: handle empty input submit
psst54 f11b891
feat: add column counter
psst54 2cd1232
chore: fix color constants
psst54 c26da25
feat: add task counter
psst54 12ab354
Merge pull request #8 from psst54/feature/error-handle
psst54 263ecbe
chore: add pretendard font
psst54 51a2fb4
feat: load/save local storage
psst54 dc8de48
fix: add key to task
psst54 6dacefe
fix: edit return form of subject hook
psst54 9c40838
fix: remove state property in subject
psst54 80da612
fix: split state toggle function
psst54 cb94281
Merge pull request #9 from psst54/feature/use-local-storage
psst54 0ef65f2
Merge pull request #10 from psst54/refactor/codebase
psst54 6232a9a
docs: update readme
psst54 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,3 +21,5 @@ | |
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"printWidth": 80, | ||
"tabWidth": 2, | ||
"useTabs": false, | ||
"semi": true, | ||
"singleQuote": true, | ||
"trailingComma": "es5", | ||
"bracketSpacing": true, | ||
"arrowParens": "always", | ||
"htmlWhitespaceSensitivity": "css", | ||
"cssWhitespaceSensitivity": "css" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,209 @@ | ||
# 2주차 미션: React-Todo | ||
# 서론 | ||
|
||
안녕하세요 🙌🏻 20기 프론트엔드 운영진 **이지인**입니다. | ||
# 결과물 | ||
|
||
다들 1주차 미션 Vanilla Todo 만드시느라 수고 많으셨습니다! 1주차 미션을 통해 여러분들께서 본격적인 React 사용에 앞서 Vanilla JS로 SPA를 만들때의 불편한 점을 느끼셨을 것 이라 생각합니다. | ||
배포 링크 : | ||
[https://react-todo-20th-six.vercel.app/](https://react-todo-20th-six.vercel.app/) | ||
|
||
그리하여 이번 미션은, 1주차 스터의 미션으로 주어진 Todo list 만들기를 **React**로 리팩토링하는 것 입니다! | ||
기존에 리액트를 잘 아시던 분들께는, 조금 더 효울적인 디자인 패턴에 대해 고민할수 있는 주차가 될 것이고, 리액트를 제대로 접해보지 못하신 분들께는 기존의 어플리케이션을 리액트로 포팅하는 과정을 통해 왜 프론트엔드 시장에 리액트가 등장하게 되었고, 리액트에서 사용하는 여러가지 방식들이 왜 바닐라에 비해 효율적인지 꺠닫는 주차가 될 것이라 생각합니다. | ||
## 기능 구현 | ||
|
||
비교적 가벼운 미션인 만큼 코드를 짜는 데 있어 여러분의 **창의성**을 충분히 발휘해보시기 바랍니다. _❕작동하기만 하면 되는 것보다 같은 코드를 짜는 여러가지 방식과 패턴에 대해 많이 고민해보시고, 본인이 작성할 수 있는 가장 창의적인 방법으로 코드를 작성해주셨으면 합니다.❕_ 여러분이 미션 수행을 하는 과정에서 한 생각과 고민만큼 스터디에서 더 많은 것을 얻어가실 수 있을 거라 기대합니다! | ||
- Open, In Progress, Done column별로 목표를 확인할 수 있다. | ||
- 각 Column에서 input field를 통해 새로운 목표를 추가할 수 있다. | ||
- 목표는 X 버튼을 통해서 삭제할 수 있다. | ||
- 목표 내에서 input field를 통해 새로운 할 일을 추가할 수 있다. | ||
- 할 일은 삭제 버튼을 통해서 삭제할 수 있다. | ||
- 할 일 요소의 체크박스틀 통해 할 일을 완료/해제할 수 있다. | ||
|
||
막히는 부분이 있더라도 우선 스스로 공부하고 찾아보면서 미션을 진행하는 방식을 권고드리지만, 미션과 관련하여 운영진의 도움이 필요하시다면 얼마든지 슬랙 Q&A 채널이나 프론트엔드 카톡방에 질문을 남겨 주세요! | ||
# Key Questions | ||
|
||
# 미션 | ||
## Virtual-DOM은 무엇이고, 이를 사용함으로서 얻는 이점은 무엇인가요? | ||
|
||
## 예시 | ||
**Virtual DOM**은 UI의 **가상**적인 표현이 메모리에 저장되고, 브라우저의 **실제** DOM과 동기화하는 프로그래밍 개념이다. | ||
|
||
- [리액트 투두 예시](https://react-todo-19th-dh-1.vercel.app/) | ||
### 장점 | ||
|
||
## 미션 목표 | ||
- 브라우저 리소스 절약 | ||
- 실제 DOM을 조작한다면 브라우저에서 render tree 재계산, reflow(레이아웃 재계산), repaint(화면 다시 그리기) 작업이 일어날 수 있기 때문에 리소스가 소모된다. | ||
- Virtual DOM을 사용한다면 브라우저의 실제 DOM을 조작하기 전에, 메모리상에 존재하는 가상의 DOM을 먼저 조작한 뒤, 변경된 부분만 실제 DOM에 반영한다. | ||
- 변경 사항이 있을 때 실제 DOM의 모든 부분을 다시 렌더링하지 않고, 변경된 부분만 효율적으로 업데이트할 수 있다. | ||
- 추상화 | ||
- DOM 조작을 직접 하지 않기 때문에 DOM 관련 복잡성을 관리하지 않아도 된다. | ||
- 기존에는 아래처럼 DOM을 직접 조작해야 했지만, | ||
```js | ||
// 명령형 코드 | ||
if (isActive) { | ||
document.getElementById('example-element').classList.add('active'); | ||
} else { | ||
document.getElementById('example-element').classList.remove('active'); | ||
} | ||
``` | ||
- Virtual DOM을 사용하면 이처럼 `isActive` 상태를 기반으로 `class`를 적절하게 변경할 수 있다. | ||
```js | ||
// 선언적 코드: React를 이용하는 경우 | ||
const ExampleComponent = ({ isActive }) => { | ||
return <div className={isActive ? 'active' : 'inactive'}>예시</div>; | ||
}; | ||
``` | ||
|
||
- VSCode, Prettier를 이용하여 개발환경을 관리합니다. | ||
- React의 기초를 이해합니다. | ||
- React를 통한 어플리케이션 상태 관리 방법을 이해합니다. | ||
- React Hooks에 대한 기초를 이해합니다. | ||
- Styled-Components를 통한 CSS-in-JS 및 CSS Preprocessor의 사용법을 익힙니다. | ||
### 과정 | ||
|
||
## 기한 | ||
가상 DOM을 실제 DOM에 동기화하는 과정을 **재조정(reconciliation)** 이라고 하고, 여러 방법이 있다. React에서는 내부적으로 `ReactDom`이라는 라이브러리를 사용해서 가상 DOM과 실제 DOM을 동기화시킨다. Vanilla JS에서도 Virtual DOM을 이용하고 싶다면 `Snabbdom`같은 라이브러리를 이용할 수 있다. | ||
|
||
- 2024년 9월 14일 토요일 | ||
| ||
|
||
## Key Questions | ||
재조정은 아래와 같은 방식으로 진행된다. | ||
|
||
- Virtual-DOM은 무엇이고, 이를 사용함으로서 얻는 이점은 무엇인가요? | ||
- React.memo(), useMemo(), useCallback() 함수로 진행할 수 있는 리액트 렌더링 최적화에 대해 설명해주세요. 다른 방식이 있다면 이에 대한 소개도 좋습니다. | ||
- React 컴포넌트 생명주기에 대해서 설명해주세요. | ||
1. 상태 변경(State Change): 상태가 변경될 때마다 (setState 등을 통해) DOM 트리가 다시 생성된다. 즉, 메모리에는 두 개의 가상 DOM 트리가 동시에 존재하게 된다. | ||
|
||
## 필수 요건 | ||
- 1주차 미션의 결과물을 그대로 React로 구현합니다. (‼️ todo / done 개수 잊지 마세요 ‼️) | ||
- Styled-Component를 사용합니다. | ||
- React Hooks만을 사용해 상태를 관리합니다.(전역 상태관리 라이브러리 사용 XX) | ||
2. 비교(Diffing): 전의 Virtual DOM과 새로운 Virtual DOM을 비교하여 어떤 부분이 변경되었는지 확인한다. | ||
|
||
## 선택 요건 | ||
3. 리렌더링(Re-render / Patching): 변경 사항이 실제 DOM에 적용된다. 이때 React는 실제 DOM을 업데이트하는 데 필요한 최소한의 작업 수를 찾아내고, 변경 사항을 한 번에 모아서 처리한다. | ||
|
||
- 기존 Todo-list에 여러분들이 추가하고 싶은 기능과 디자인을 자유롭게 추가해보세요. | ||
## React.memo(), useMemo(), useCallback() 함수로 진행할 수 있는 리액트 렌더링 최적화에 대해 설명해주세요. 다른 방식이 있다면 이에 대한 소개도 좋습니다. | ||
|
||
## 로컬 실행방법 | ||
`memo()`, `useMemo()`, `useCallback()` 을 이용하면 컴포넌트의 불필요한 렌더링을 방지함으로써, 성능을 높일 수 있다. | ||
|
||
--- | ||
### `memo` | ||
|
||
`npm start` : 로컬에서 react application을 자동으로 리로드하여 실행시켜줍니다. | ||
`memo`를 사용하면 컴포넌트의 props가 변경되지 않은 경우, 리렌더링을 건너뛸 수 있다. | ||
|
||
# 링크 및 참고자료 | ||
React는 일반적으로 부모 컴포넌트가 리렌더링될 때, 자식 컴포넌트도 함께 리렌더링된다. 하지만 자식 컴포넌트로 전달되는 props가 이전과 동일하다면, 자식 컴포넌트는 리렌더링되지 않도록 할 수 있다. | ||
|
||
--- | ||
#### 호출 | ||
|
||
- [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) | ||
- [styled-component](https://styled-components.com/docs/basics#getting-started) | ||
```js | ||
const MemoizedComponent = memo(SomeComponent, arePropsEqual?) | ||
``` | ||
|
||
- `SomeComponent`: 첫 번째 인자로는 메모제이션하고자 하는 컴포넌트를 넘겨준다. | ||
- `arePropsEqual`: 필요한 경우, 두 번째 인자로는 **사용자 정의 비교 함수**를 넘겨줄 수 있다. | ||
- props가 동일해 리렌더링이 필요하지 않은 경우 `true`를, 아닌 경우 `false`를 반환한다. | ||
|
||
#### 주의점 | ||
|
||
`memo`는 기본적으로 props를 얕은 비교(shallow comparison)로 비교한다. 따라서 객체나 배열을 props로 전달한 경우, 내용이 같더라도 참조가 변경되면 다시 렌더링이 발생할 수 있다. | ||
|
||
이런 경우, 위에서 언급한 **사용자 정의 비교 함수**를 통해 이전 배열과 새로운 배열을 비교하도록 정할 수 있다. | ||
|
||
### `useMemo` | ||
|
||
`useMemo`는 리렌더링 사이에 계산 결과를 캐싱할 수 있게 해주는 React Hook이다. | ||
|
||
#### 호출 | ||
|
||
```js | ||
useMemo(calculateValue, dependencies); | ||
``` | ||
|
||
- `calculateValue`: 캐싱할 값을 계산하는 함수이다. | ||
- 초기 렌더링 시에 `calculateValue`함수가 호출된다. | ||
- 이후 `dependencies`가 변경되지 않았다면 다음 렌더링에서는 `calculateValue` 함수 호출 없이 동일한 값을 반환하도록 값을 저장한다. | ||
- `dependencies`: `calculateValue` 함수 안에서 참조된 모든 값들의 목록이다. 해당 값들이 변경된 경우, 다음 렌더링에서는 새로 `calculateValue` 함수를 호출해 값을 재계산하게 된다. | ||
|
||
#### 주의점 | ||
|
||
- `useMemo`는 Hook이기 때문에 컴포넌트의 최상위 레벨 또는 자체 Hook에서만 호출할 수 있다. | ||
- 복잡한 계산이 있는 경우나 값이 자주 변경되지 않는 경우에 사용하면 좋다. | ||
|
||
### `useCallback` | ||
|
||
리렌더링 사이에 함수 정의를 캐싱할 수 있게 해주는 React Hook이다. | ||
|
||
#### 호출 | ||
|
||
```js | ||
useCallback(fn, dependencies); | ||
``` | ||
|
||
- `fn`: 캐싱할 함수이다. | ||
- 초기 렌더링 시에 `fn` 함수를 반환한다. (호출하는 것은 아니다.) | ||
- 이후 `dependencies`가 변경되지 않았다면 다음 렌더링에서는 같은 함수를 다시 반환한다. | ||
- 변경되었다면 함수를 새로 반환하고, 재사용할 수 있도록 저장한다. | ||
- `dependencies`: `fn` 함수 안에서 참조된 모든 값들의 목록이다. | ||
|
||
#### 주의점 | ||
|
||
- `useCallback`는 Hook이기 때문에 컴포넌트의 최상위 레벨 또는 자체 Hook에서만 호출할 수 있다. | ||
|
||
## React 컴포넌트 생명주기에 대해서 설명해주세요. | ||
|
||
컴포넌트의 생명주기(LifeCycle)이란, 컴포넌트가 생성되고 제거되기까지의 여러 단계를 이른다. | ||
|
||
각 생명주이게서는 특정한 메소드가 호출되며, 이러한 메소드들을 오버라이딩할 수도 있다. | ||
|
||
### Mouting (생성 단계) | ||
|
||
- `constructor` | ||
- 컴포넌트가 생성될 때 호출되는 생성자 메소드 | ||
- 초기 상태의 설정 및 이벤트 핸들러의 바인딩이 주로 이루어진다. | ||
- `static getDerivedStateFromProps` | ||
- props로부터 상태를 동기화하기 위해 호출되는 메소드 | ||
- React 16.3부터 도입됨 | ||
- `render` | ||
- 컴포넌트의 UI를 렌더링한다 | ||
- `componentDidMount` | ||
- 컴포넌트가 실제 DOM에 삽입된 후 호출되는 메소드 | ||
- 초기 데이터 로딩 등의 작업에 사용된다. | ||
|
||
### Updating (업데이트 단계) | ||
|
||
- `static getDerivedStateFromProps` | ||
- props로부터 상태를 동기화하기 위해 호출된다. | ||
- `shouldComponentUpdate` | ||
- 컴포넌트의 리렌더링 여부를 결정한다. | ||
- `render` | ||
- UI를 렌더링한다. | ||
- `getSnapshotBeforeUpdate` | ||
- 컴포넌트가 업데이트되기 직전에 호출된다. | ||
- `componentDidUpdate` | ||
- 컴포넌트의 업데이트가 완료된 후 호출된다. | ||
|
||
### Unmouting (제거 단계) | ||
|
||
- `componentWillUnmount` | ||
- 컴포넌트가 제거되기 직전에 호출된다. | ||
- 리소스 정리나 이벤트 해제 등의 작업을 수행한다. | ||
|
||
### Error Handling | ||
|
||
- `static getDerivedStateFromError` | ||
- 자식 컴포넌트의 렌더링 중에 오류가 발생했을 때 호출된다. | ||
- `componentDidCatch` | ||
- 자식 컴포넌트에서 오류가 발생했을 때 호출된다. | ||
|
||
함수 컴포넌트에서는 Hook을 이용하여 상태 및 생명주기 기능을 사용할 수 있다. | ||
|
||
- `useState` | ||
- state를 생성한다. | ||
- 현재 state값과 해당 state를 업데이트할 수 있는 setFunction을 반환한다. | ||
- `useEffect` | ||
- 함수 컴포넌트에서 부수 효과(side effect)를 수행할 때 사용한다 | ||
- `useContext` | ||
- React의 context를 사용할 때 사용한다. 컴포넌트 트리 전체에서 전역적인 값을 공유할 때 유용하다. | ||
- `useReducer` | ||
- 복잡한 상태 로직을 효과적으로 관리하기 위해 사용한다. | ||
- 상태 업데이트 로직을 외부 함수로 분리할 수 있다. | ||
- `useMemo` | ||
- 계산 비용이 많이 드는 함수의 결과값을 기억한다. | ||
- 의존성 배열에 있는 값이 변경될 때만 해당 값을 다시 계산한다. | ||
- 불필요한 연산을 방지하고 성능을 최적화할 수 있다. | ||
- `useCallback` | ||
- 메모제이션된 콜백 함수를 생성한다. | ||
- 자식 컴포넌트가 불필요하게 다시 렌더링되는 것을 방지한다. | ||
- `useRef` | ||
- 상태 업데이트를 트리거하지 않는 값을 생성하거나, DOM 요소에 대한 참조를 생성한다. | ||
- `useLayoutEffect` | ||
- 렌더링이 발생하기 전에 **동기적**으로 실행된다. | ||
- 브라우저의 레이아웃을 읽어오고, 그에 따른 사이드 이펙트를 처리한다. | ||
|
||
## 참고 | ||
|
||
- https://legacy.reactjs.org/docs/faq-internals.html | ||
- https://bitsofco.de/understanding-the-virtual-dom/ | ||
- https://legacy.reactjs.org/docs/react-dom.html | ||
- https://simsimjae.gitbook.io/simsimreact/snabbdom | ||
- https://medium.com/@priyabratapanda.13/working-of-virtual-dom-in-react-1ad8779fe922 | ||
- https://react.dev/reference/react/memo | ||
- https://react.dev/reference/react/useMemo | ||
- https://react.dev/reference/react/useCallback#usecallback | ||
- https://legacy.reactjs.org/docs/state-and-lifecycle.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"compilerOptions": { | ||
"baseUrl": "src" | ||
}, | ||
"include": ["src"] | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프리티어 속성 찾아보면서 못 봤던 속성값인데 덕분에 찾아보고 알아갑니다👍👍