Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
HOJOON07 committed Feb 1, 2024
2 parents e8dbdd6 + fbdd6eb commit a886226
Show file tree
Hide file tree
Showing 21 changed files with 2,649 additions and 14 deletions.
2 changes: 1 addition & 1 deletion pages/1week/jkyeun/study.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## 리액트의 역사

# 리액트 개발을 위해 꼭 알아야 할 자바스크립트
# [1장] 리액트 개발을 위해 꼭 알아야 할 자바스크립트

## 자바스크립트의 동등 비교

Expand Down
69 changes: 68 additions & 1 deletion pages/1week/yeonsuu21/study.mdx
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 메모이제이션
49 changes: 49 additions & 0 deletions pages/2week/0uizi0/about.mdx
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와 같은 **복잡한 구조**의 데이터의 경우에는 얕은 비교에는 한계가 있다. > 라고 이해했는데 맞나?
180 changes: 180 additions & 0 deletions pages/2week/0uizi0/study.mdx
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를 하지 않았을 때 발생할 수 있는 문제는
- 렌더링을 함으로써 발생하는 비용
- 컴포넌트 내부의 복잡한 로직의 재실행
- 그리고 위 두 가지 모두가 모든 자식 컴포넌트에서 반복해서 일어남
- 리액트가 구 트리와 신규 트리를 비교
- 메모이제이션은 하지 않는 것보다 메모이제이션했을 때 더 많은 이점을 누릴 수 있다.
6 changes: 6 additions & 0 deletions pages/2week/doyeon/about.mdx
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 사용에 대하여 다들 어떻게 생각 하시나요? 저는 무거운 연산이 있을 경우에만 사용하는 편이 좋을 거 같다고 생각해요.
Loading

0 comments on commit a886226

Please sign in to comment.