-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
2,649 additions
and
14 deletions.
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 |
---|---|---|
@@ -1,6 +1,6 @@ | ||
## 리액트의 역사 | ||
|
||
# 리액트 개발을 위해 꼭 알아야 할 자바스크립트 | ||
# [1장] 리액트 개발을 위해 꼭 알아야 할 자바스크립트 | ||
|
||
## 자바스크립트의 동등 비교 | ||
|
||
|
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 +1,68 @@ | ||
## 정리하기 파일 | ||
## 2. 리액트 핵심요소 깊게 살펴보기 | ||
|
||
### 2-1 . 'props' 여부에 따라 'children' 요소 만 달라지는 경우 | ||
|
||
굳이 번거롭게 전체 내용을 삼항 연산자로 처리할 필요가 없다. | ||
이 경우 불필요한 코드 풍복이 일어난다. -> 실제로 삼항연산자 처돌이 입니다.. | ||
|
||
```jsx | ||
import { createElement } from 'react’ | ||
function TextOrHeading({ | ||
isHeading , | ||
children , | ||
}: PropsWithChildren<{ isHeading: boolean }>) { | ||
return createElement( | ||
isHeading ? ’hl’ : ’span’, | ||
{ className : ’text' } , children , | ||
)} | ||
``` | ||
|
||
### 2-2 가상 DOM과 리액트 파이버 | ||
- 가상 DOM은 웹페이지가 표시해야 할 DOM을 일단 메모리에 저장하고 리액트가 실제 변경에 대한 준비가 완료됐을 때 실제 브라우저의 DOM에 반영한다. | ||
- 리액트 파이버 : 가상 DOM과 렌더링 과정 최 적회를 기능하게 해주는 것 | ||
- 파이버 트리 : 현재 모습을 담은 파이버 트리 , 작업 중인 상태 를 나타내는 worklnProgress 트리 | ||
|
||
|
||
### 2.3 클래스형 컴포넌트와 함수형 컴포넌트 | ||
|
||
#### 클래스형 컴포넌트 | ||
- | ||
```jsx | ||
class SampleComponent extends React.Component{} | ||
``` | ||
의 형식 | ||
|
||
- 한계 | ||
- 데이터의 흐름을 추적하기 어럽다 | ||
- 애플리케이선 내부 로직의 재사용이 어렵다 | ||
- 기능이 많아질수록 컴포넌트의 크기가 커진다 | ||
- 클래스는 함수에 비해 상대적으로 어렵다 | ||
- 코드 크기를 최적화하기 어럽다 | ||
- 핫 리로딩을 하는 데 상대적으로 불리하다 | ||
|
||
|
||
#### 함수형 컴포넌트 | ||
- | ||
```jsx | ||
export function SampleComponent({ required, text }: SampleProps) {} | ||
``` 형식 | ||
#### 함수형 컴포넌트 vs 클래스형 컴포넌트 | ||
- 생명주기메서드의부재 : 클래스형 컴포넌트의 생명주기 메서드가 함수형 컴포넌트에서는 존재하지 않음 | ||
-> 함수형 컴포넌트는 'props'를 받아 단순히 리액트 요소만 반환하는 함수인 반면, | ||
클래스형 컴포넌트는 'render' 메서드가 있는 'React.Component'를 상속 받아 구현하는 자바스크립트 클래스이기 때문 | ||
### 2.4 렌더링은 어떻게 일어나는가? | ||
리액트의 렌더링 : 'props'와 'state'의 값을 기반으로 어떻게 UI를 구 성하고 이를 바탕으로 어떤 DOM 결과를 브라우저에 제공할 것인지 계산하는 일련의 과정 | ||
### 2.5 메모이제이션 | ||
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 +1,50 @@ | ||
## 이야기해보기 파일 | ||
### p.127 | ||
|
||
> props 여부에 따라 children 요소만 달라지는 경우, 전체 내용을 삼항 연산자로 처리할 필요 없음 | ||
> | ||
> | ||
> → 불필요한 코드 중복이 발생 | ||
> | ||
> ```tsx | ||
> function TextOrHeading({ | ||
> isHeading, | ||
> children, | ||
> }: PropsWithChildren<{ isHeading: boolean }>) { | ||
> return isHeading ? ( | ||
> <h1 className='text'>{children}</h1> | ||
> ) : ( | ||
> <span className='text'>{children}</span> | ||
> ) | ||
> } | ||
> | ||
> // JSX가 변환되는 특성을 활용하여 코드 개선 | ||
> import { createElement } from "react"; | ||
> | ||
> function TextOrHeading({ | ||
> isHeading, | ||
> children, | ||
> }: PropsWithChildren<{ isHeading: boolean }>) { | ||
> return createElement(isHeading ? "hi" : "span", { | ||
> className: "text", | ||
> children, | ||
> }); | ||
> } | ||
> ``` | ||
> | ||
첫 번째 버전의 코드를 아래와 같이 개선한 코드를 보았는데, 실제로 코드 중복을 줄이기 위해 createElement를 사용해 코드를 개선할까? | ||
### p.153 | ||
> PureComponent는 **얕은 비교**만 수행하기 때문에 state 객체와 같은 복잡한 구조의 데이터 변경 감지 X | ||
> | ||
> | ||
> → 컴포넌트가 얕은 비교를 했을 때 일치하지 않는 일이 더 잦다면 비교가 무의미해짐. 성능에 역효과 | ||
> | ||
> → PureComponent는 필요한 곳에만 사용하기 | ||
> | ||
리액트 딥다이브 1장에서 props의 경우, 동등 비교 시 얕은 비교로 충분하다는 내용을 읽었던 기억이 남. | ||
props와 같은 **간단한 데이터 구조**의 경우 얕은 비교로 충분하지만, state와 같은 **복잡한 구조**의 데이터의 경우에는 얕은 비교에는 한계가 있다. > 라고 이해했는데 맞나? |
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 +1,181 @@ | ||
## 정리하기 파일 | ||
### 2.1 JSX란? | ||
|
||
**2.1.1 JSX의 정의** | ||
|
||
- JSXElement : JSX를 구성하는 가장 기본 요소 | ||
- JSXElementName : JSXElement의 요소 이름으로 쓸 수 있는 것 | ||
- JSXAttributes : JSXElement에 부여할 수 있는 속성 | ||
- JSXChildren : JSXElement의 자식 값 | ||
- JSXStrings | ||
|
||
**2.1.3 JSX는 어떻게 자바스크립트에서 변환될까?** | ||
|
||
JSXElement를 렌더링할 때 굳이 요소 전체를 감싸지 않더라도 처리할 수 있음. | ||
|
||
→ props 여부에 따라 children 요소만 달라지는 경우에서 중복 코드 최소화 가능 | ||
|
||
← JSXElement만 다르고, JSXAttributes, JSXChildren이 동일한 상황이기 때문 | ||
|
||
```tsx | ||
import { createElement } from "react"; | ||
|
||
function TextOrHeading({ | ||
isHeading, | ||
children, | ||
}: PropsWithChildren<{ isHeading: boolean }>) { | ||
return createElement(isHeading ? "hi" : "span", { | ||
className: "text", | ||
children, | ||
}); | ||
} | ||
``` | ||
|
||
### 2.2 가상 DOM과 리액트 파이버 | ||
|
||
**2.2.1 DOM과 브라우저 렌더링 과정** | ||
|
||
- DOM 노드에 CSS를 적용하는 과정 | ||
- 레이아웃(layout, reflow) : 각 노드가 브라우저 화면의 어느 좌표에 정확히 나타나야 하는지 계산하는 과정 | ||
- 페인팅(painting) : 레이아웃 단계를 거친 노드에 색과 같은 실제 유효한 모습을 그리는 과정 | ||
|
||
**2.2.2 가상 DOM의 탄생 배경** | ||
|
||
- 레이아웃은 필연적으로 리페인팅이 발생하기 때문에 더 많은 비용이 든다. | ||
- SPA는 하나의 페이지에서 계속해서 요소의 위치를 재계산함 | ||
|
||
→ 페이지 깜빡임 없이 자연스러운 웹페이지 탐색 가능 | ||
|
||
→ DOM을 관리하는 과정에서의 비용 부담이 커짐 | ||
|
||
⇒ 가상 DOM 등장 | ||
|
||
- `가상 DOM` : 웹 페이지가 표시해야할 DOM을 일단 메모리에 저장하고 리액트가 실제 변경에 대한 준비가 완료되었을 때 실제 브라우저의 DOM에 반영 | ||
|
||
⇒ 실제로는 여러 번 발생했을 렌더링 과정을 최소화할 수 있음 | ||
|
||
|
||
**2.2.3 가상 DOM을 위한 아키텍처, 리액트 파이버** | ||
|
||
- 리액트 파이버 | ||
- 리액트에서 관리하는 평범한 자바스크립트 객체 | ||
- `재조정` : 가상 DOM과 실제 DOM을 비교해 변경 사항을 수집하며, 만약 이 둘 사이에 차이가 있으면 변경에 관련된 정보를 가지고 있는 파이버를 기준으로 화면에 렌더링을 요청하는 역할을 함 | ||
- 과거 리액트의 조정 알고리즘은 **스택 알고리즘**으로 구현됨 → 스택이 빌 때까지 동기적 작업 수행 → 비효율 | ||
|
||
⇒ 스택 조정자 대신 **파이버** 라는 개념을 탄생 | ||
|
||
- 렌더링 단계 | ||
1. 렌더 단계 : 파이버의 작업 `finishedWork()`, 우선순위를 지정하거나 중지시키거나 버리는 등의 작업 (비동기) | ||
2. 커밋 단계 : DOM에 실제 변경 사항을 반영하기 위한 작업, `commitWork()` 실행 (동기) | ||
- 리액트 요소는 렌더링이 발생할 때마다 새롭게 생성되지만 파이버는 가급적이면 재사용된다. | ||
|
||
← 최초 렌더링 이후 업데이트가 발생할 경우, 파이버는 이미 존재하므로 되도록 새로 생성하지 않고 기존 파이버에서 업데이트된 props를 받아 파이버 내부에서 처리 | ||
|
||
- 파이버의 주요 속성 | ||
- tag : 하나의 element에 하나가 생성되는 1:1로 매칭된 정보를 가지고 있는 것 | ||
- child, sibling, return : 자식,형제,부모 파이버 | ||
- index : 여러 형제들 사이에서 자신의 위치가 몇 번째인지 숫자로 표현 | ||
- 리액트 파이버 트리 | ||
- `더블 버퍼링` : 리액트 파이버의 작업이 끝난 후, 리액트는 단순히 포인터만 변경해 workInProgress 트리를 현재 트리로 바꿔버린다. | ||
|
||
← 불완전한 트리를 보여주지 않기 위해 | ||
|
||
- 현재는 우선순위가 높은 다른 업데이트가 오면 현재 업데이트 작업을 일시 중단하거나 새롭게 만들거나, 폐기할 수 있다.(비동기) | ||
|
||
**2.2.4 파이버와 가상 DOM** | ||
|
||
- 리액트 컴포넌트에 대한 정보를 1:1로 가지고 있는 것이 파이버, 파이버는 리액트 아키텍처 내부에서 비동기로 이뤄짐. | ||
- 이러한 비동기 작업과 달리, 실제 브라우저 구조인 DOM에 반영하는 것은 동기적으로 일어나야하고, 처리하는 작업이 많아 화면에 불완전하게 표시될 수 있는 가능성이 높음 | ||
|
||
⇒ 이러한 작업을 가상에서, 즉 메모리상에서 먼저 수행해서 최종 결과물만 실제 DOM에 적용 | ||
|
||
- 가상 DOM과 리액트의 핵심은 값으로 UI를 표현하는 것. | ||
- 화면에 표시되는 UI를 자바스크립트의 문자열, 배열 등과 마찬가지로 값으로 관리하고 이러한 흐름을 효율적으로 관리하기 위한 메커니즘이 바로 리액트의 핵심이다. | ||
|
||
### 2.3 클래스형 컴포넌트와 함수형 컴포넌트 | ||
|
||
**2.3.1 클래스형 컴포넌트** | ||
|
||
- `React.Component`와 `React.PureComponent`의 차이, shouldComponentUpdate | ||
- PureComponent는 **얕은 비교**만 수행하기 때문에 state 객체와 같은 복잡한 구조의 데이터 변경 감지 X | ||
|
||
→ 컴포넌트가 얕은 비교를 했을 때 일치하지 않는 일이 더 잦다면 비교가 무의미해짐. 성능에 역효과 | ||
|
||
→ PureComponent는 필요한 곳에만 사용하기 | ||
|
||
- 클래스형 컴포넌트의 생명주기 메서드 | ||
- 생명주기 메서드가 실행되는 시점 | ||
- 마운트 : 컴포넌트가 마운팅(생성)되는 시점 | ||
- 업데이트 : 이미 생성된 컴포넌트의 내용이 변경(업데이트)뙤는 시점 | ||
- 언마운트 : 컴포넌트가 더 이상 존재하지 않는 시점 | ||
- 생명주기 메서드 | ||
- render : 컴포넌트가 UI를 렌더링하기 위해 쓰임 | ||
- componentDidMount : 클래스형 컴포넌트가 마운트되고 준비되는 즉시 실행 | ||
- componentDidUpdate : 컴포넌트 업데이트가 일어난 이후 바로 실행 | ||
- componentWillUnmount : 컴포넌트가 언마운트되거나 더 이상 사용되지 않기 직전에 호출 | ||
|
||
→ 메모리 누수나 불필요한 작동을 막기 위한 클린업 함수를 호출할 때 최적 | ||
|
||
- shouldComponentUpdate : state나 props의 변경으로 리액트 컴포넌트가 다시 리렌더링되는 것을 막고자 할 때 사용 | ||
- getDerivedStateFromError : 자식 컴포넌트에서 에러가 발생했을 때 호출되는 에러 메서드 | ||
|
||
→ 하위 컴포넌트에서 에러 발생 시 자식 리액트 컴포넌트를 어떻게 렌더링할 지 결정 | ||
|
||
- componentDidCatch : 자식 컴포넌트에서 에러가 발생했을 때 실행되며, getDerivedStateFromError에서 에러를 잡고 state를 결정한 후에 실행 | ||
|
||
→ 리액트에서 에러 발생 시 메서드에서 제공되는 에러 정보를 바탕으로 로깅하는 등의 용도로 사용 | ||
|
||
- 클래스형 컴포넌트의 한계 | ||
- 데이터의 흐름 추적 어려움 | ||
- 애플리케이션 내부 로직의 재사용 어려움 : 공통 로직이 많아질수록 이를 감싸는 고차 컴포넌트, props가 많아지는 래퍼 지옥에 빠져들 위험성이 커짐 | ||
- 기능이 많아질수록 컴포넌트의 크기가 커짐 | ||
- 클래스는 함수에 비해 상대적으로 어려움 | ||
- 코드 크기 최적화 어려움 | ||
- 핫 리로딩을 하는데 상대적으로 불리 | ||
- `핫 리로딩` : 코드에 변경사항이 발생했을 때 앱을 다시 시작하지 않고서도 해당 변경된 코드만 업데이트해 변경 사항을 빠르게 적용하는 기법 | ||
|
||
**2.3.3 함수형 컴포넌트 vs 클래스형 컴포넌트** | ||
|
||
- 생명주기 메서드의 부재 | ||
|
||
← 함수형 컴포넌트는 props를 받아 단순히 리액트 요소만 반환하는 함수지만, 클래스형 컴포넌트는 render 메서드가 있는 React.Component를 상속받아 구현하기 때문 | ||
|
||
- 함수형 컴포넌트와 렌더링된 값 | ||
|
||
← 함수형 컴포넌트는 렌더링된 값을 기준으로 렌더링하고, 클래스형 컴포넌트는 시간의 흐름에 따라 변화하는 this를 기준으로 렌더링 | ||
|
||
- 클래스형 컴포넌트 : this에 바인딩된 props 사용. this가 가리키는 객체(컴포넌트의 인스턴스 멤버)는 변경가능한 값 | ||
- 함수형 컴포넌트 : props를 인수로 받음 ⇒ 불변한 값. | ||
|
||
### 2.4 렌더링은 어떻게 일어나는가? | ||
|
||
**2.4.2 리액트의 렌더링이 일어나는 이유** | ||
|
||
- 컴포넌트의 key props가 변경되는 경우, 리렌더링 | ||
- 리액트에서의 key : 리렌더링이 발생하는 동안 형제 요소들 사이에서 동일한 요소를 식별함. | ||
- 리렌더링이 발생하면 current 트리와 workInProgress 트리 사이에서 변경 사항을 구별해야 하는데, 이 두 트리 사이에서 같은 컴포넌트인지 구별하는 값으로 사용됨. | ||
- 변경 사항을 구별하는 작업은 리렌더링이 필요한 컴포넌트를 최소화해야 하므로 반드시 필요한 작업임. | ||
- key가 존재한다면 두 트리 사이에서 통일한 key를 가지고 있는 컴포넌트를 기준으로 구별할 수 있지만, key가 없다면 단순히 파이버 내부의 sibling 인덱스만을 기준으로 판단함. | ||
|
||
**2.4.4 렌더와 커밋** | ||
|
||
- 렌더 단계 : 컴포넌트의 렌더링하고 변경 사항을 계산하는 작업. 렌더링 프로세스에서 컴포넌트를 실행한 결과와 이전 가상 DOM을 비교하는 과정을 거쳐 변경이 필요한 컴포넌트를 체크하는 단계 | ||
- 커밋 단계 : 렌더 단계의 변경 사항을 실제 DOM에 적용해 사용자에게 보여주는 과정 | ||
|
||
### 2.5 컴포넌트와 함수의 무거운 연산을 기억해 두는 메모이제이션 | ||
|
||
**2.5.1 주장 1. 섣부른 최적화는 독이다, 꼭 필요한 곳에만 메모이제이션을 추가하자** | ||
|
||
- 가벼운 작업 자체는 메모이제이션해서 자바스크립트 메모리 어딘가에 두었다가 그것을 다시 꺼내오는 것보다는 매번 작업을 수행해 반환하는 것이 더 빠를 수 있다. | ||
- 메모이제이션에도 비용이 든다. 값을 비교하고 렌더링 또는 재계산이 필요한지 확인하는 작업, 그리고 이전에 결과물을 저장해두었다가 다시 꺼내와야 한다는 두 가지 비용이 있다. | ||
- 항상 메모이제이션은 신중하게 접근해야하며 섣부른 최적화는 항상 경계해야 한다. | ||
|
||
**2.5.2 주장 2. 렌더링 과정의 비용은 비싸다, 모조리 메모이제이션해 버리자** | ||
|
||
- 잘못된 memo로 지불해야하는 비용은 바로 prop에 대한 얕은 비교가 발생하면서 지불해야 하는 비용이다. | ||
- 반면 memo를 하지 않았을 때 발생할 수 있는 문제는 | ||
- 렌더링을 함으로써 발생하는 비용 | ||
- 컴포넌트 내부의 복잡한 로직의 재실행 | ||
- 그리고 위 두 가지 모두가 모든 자식 컴포넌트에서 반복해서 일어남 | ||
- 리액트가 구 트리와 신규 트리를 비교 | ||
- 메모이제이션은 하지 않는 것보다 메모이제이션했을 때 더 많은 이점을 누릴 수 있다. |
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 +1,7 @@ | ||
## 이야기해보기 파일 | ||
|
||
### 2.1 JSX란? | ||
- [p. 119] JSXNamespacedName, JSXMemberExpression을 다들 자주 사용하시는지 궁금해요. | ||
|
||
### 2.5 컴포넌트와 함수의 무거운 연산을 기억해 두는 메모이제이션 | ||
- [p.182] useMemo, useCallback 사용에 대하여 다들 어떻게 생각 하시나요? 저는 무거운 연산이 있을 경우에만 사용하는 편이 좋을 거 같다고 생각해요. |
Oops, something went wrong.