diff --git "a/week-02/\352\271\200\354\244\200\354\227\264.md" "b/week-02/\352\271\200\354\244\200\354\227\264.md"
new file mode 100644
index 0000000..0acb851
--- /dev/null
+++ "b/week-02/\352\271\200\354\244\200\354\227\264.md"
@@ -0,0 +1,801 @@
+# 2장 리액트 핵심 요소
+
+## JSX란?
+
+Javascript XML의 약자로, 자바스크립트 코드 내에서 XML / HTML과 유사한 문법을 사용할 수 있게 해주는 문법적 확장이다. 리액트에서는 엘리먼트를 생성하는 데 사용된다. 하지만 자바스크립트 표준은 아니기 때문에 트랜스파일러를 거치지 않고서는 자바스크립트 엔진이나 브라우저에서 동작하지 않는다.
+
+
+
+> **JSX의 설계 목적**
+
+- 다양한 트랜스파일러에서 다양한 속성을 가진 트리 구조를 토큰화해 ECMAScript로 변환.
+- 즉, JSX 내부에서 작성한 트리 구조의 코드를 트랜스파일이라는 과정을 거쳐 자바스크립트로 변경하는 것이 목표라고 볼 수 있다.
+
+
+
+## JSX의 정의
+
+JSX는 기본적으로 `JSXElement`, `JSXAttributes`, `JSXChildren`, `JSXStrings`라는 4가지 컴포넌트를 기반으로 구성되어 있다.
+
+### 1. JSXElement
+
+JSX를 구성하는 가장 기본 요소로, HTML의 요소와 비슷한 역할을 한다. JSXElement가 되기 위해서는 다음과 같은 형태 중 하나여야 한다.
+
+- JSXOpeningElement
+- JSXClosingElement
+- JSXSelfClosingElement
+- JSXFragment
+
+```jsx
+// 앞에
가 JSXOpeningElement
+// 뒤에
가 JSXClosingElement
+// 둘이 쌍으로 사용되며 Opening이 앞으로 와야 올바른 JSX 문법이다.
+
hello
+```
+
+```jsx
+// JSXSelfClosingElement
+// 내부적으로 자식 요소가 없을 때 사용된다.
+
+```
+
+```jsx
+// JSXFragment
+// 여러 JSX 요소들을 그룹화할 때 사용되며, 추가적인 DOM 요소를 생성하지 않는다.
+<>
+
hello
+>
+```
+
+
+
+> 컴포넌트 이름이 대문자로 시작하는 이유
+
+리액트에서는 대문자로 시작하는 태그를 사용자 정의 컴포넌트로 간주하고, 소문자로 시작하는 태그는 HTML 태그로 해석한다.
+
+
+
+### 1 - 2. JSXElementName
+
+`JSXElement`의 요소 이름으로 쓸 수 있는 것을 의미한다.
+
+> **JSXIdentifier**
+
+JSX 내부에서 사용할 수 있는 식별자를 의미한다. 이는 자바스크립트 식별자 규칙과 동일하다.
+
+숫자로 시작하거나 `$`와 `_` 외의 다른 특수문자로는 시작할 수 없다.
+
+```jsx
+function Valid1(){
+ return <$>$>
+}
+
+function Valid(){
+ return <_>
+}
+
+// 불가능
+function Invalid(){
+ return <1>1>
+}
+```
+
+
+
+> **JSXNamespacedName**
+
+식별자 : 식별자 조합, 즉 `:`을 통해 서로 다른 식별자를 이어주는 것도 하나의 식별자로 취급된다.
+
+단, :로 묶을 수 있는 것은 한 개뿐이다.
+
+```jsx
+function valid1(){
+ return
+}
+
+// 불가능
+function Invalid(){
+ return
+}
+```
+
+
+
+> **JSXMemberExpression**
+
+식별자 . 식별자의 조합이다. `.`을 통해 다른 식별자를 이어주는 것도 하나의 식별자로 취급된다.
+
+`JSXNamesapcedName`과는 다르게 .을 여러 개 이어서 하는 것도 가능하다.
+
+```jsx
+function valid1(){
+ return
+}
+
+function valid2(){
+ return
+}
+
+// 불가능
+function invalid(){
+ return
+}
+```
+
+
+
+### 2. JSXAttributes
+
+`JSXElement`에 부여할 수 있는 속성을 의미한다. 필수값이 아니며, 존재하지 않아도 에러 발생은 하지 않는다.
+
+
+
+> **JSXSpreadAttributes**
+
+자바스크립트의 전개 연산자와 동일한 역할을 한다.
+
+`{…AssignmentExpression}`
+
+- 이 AssignmentExpression에는 단순히 객체뿐만 아니라 자바스크립트에서 AssignmentExpression으로 취급되는 모든 표현식이 존재할 수 있다. 여기에는 조건문 표현식, 화살표 함수, 할당식 등 다양한 것이 포함되어있다.
+
+```jsx
+// 객체를 props로 전달
+const props = { firstName: 'John', lastName: 'Doe' };
+const component = ;
+
+// 조건문 할당식 등의 사용
+const additionalProps = { age: 30 };
+const component = ;
+```
+
+
+
+> **JSXAttribute**
+
+속성을 나타내는 키와 값으로 짝을 이루어서 표현한다.
+
+키는 `AttributeName`, 값은 `AttributeValue`로 불린다.
+
+AttributeName은 JSXIdentifier와 JSXNamespacedName이 가능하다.
+
+`:`를 통해 키를 나타낼 수 있다
+
+JSXAttributeValue는 속성의 키에 할당할 수 있는 값으로, 다음중 하나를 만족해야한다.
+
+- “큰따옴표로 구성된 문자열”
+- ‘작은따옴표로 구성된 문자열’
+- {AssignmentExpression}
+- JSXElement
+
+ ```jsx
+ <>
+
+ >}/>
+
+
+ ```
+
+### 3. JSXChildren
+
+JSXElement의 자식 값을 나타낸다.
+
+> **JSXChild**
+
+- JSXChildren을 이루는 기본 단위다. JSXChildren은 JSXChild를 0개 이상 가질 수 있다.
+
+- JSXText
+ - `{`, `<`. `>`, `}`을 제외한 문자열을 의미한다.
+- JSXElement
+ - 값으로 다른 JSX 요소가 들어갈 수 있다.
+- JSXFragment
+ - 빈 JSX 요소가 들어갈 수 있다.
+- { JSXChildExpression (optional) }
+ - 이 JSXChildExpression은 자바스크립트의 AssingmentExpression을 의미한다.
+ ```jsx
+ // 함수 렌더링 시 "foo" 문자열 출력
+ export default function App() {
+ return <>{(() => 'foo')()}>;
+ }
+ ```
+
+
+
+### 4. JSXStrings
+
+HTML에서 사용 가능한 문자열은 모두 JSXStrings에서 가능하다.
+
+큰따옴표로 구성된 문자열, 작음따옴표로 구성된 문자열, JSXText를 의미한다.
+
+다만, 이스케이프 문자열을 사용할 때는 “\\”와 같이 사용해야한다.
+
+
+
+## JSX는 어떻게 자바스크립트로 변환
+
+JSX는 코드는 브라우저에서 직접 실행될 수 없기 때문에 JSX를 순수 자바스크립트로 컴파일 하는 과정이 필요하다. 대표적으로 Babel과 같은 트랜스파일러를 사용한다.
+
+리액트 17 이전에는 `@babel/plugin-transform-react.jsx` 플러그인을 사용해서 JSX를 자바스크립트로 컴파일하였다. 이 플러그인은 `@babel/preset-react` 내부에 포함되어 있다.
+
+이 플러그인은 JSX를 `React.createElement` 호출로 변화시켰다.
+
+```jsx
+// React를 호출하기 때문에 반드시 작성해주어야했다.
+import React from 'react';
+
+// Before
+const Component = (
+
+ hello
+
+);
+
+// After
+const ComponentC = React.createElement(
+ 'div',
+ null,
+ React.createElement('span', null, 'hello'),
+);
+```
+
+17버전 이후로는 `자동 런타임` 모드를 지원하게 되어 `React`를 호출할 필요가 없어졌다.
+
+
+
+> **React.createElement**
+
+- 리액트 17 이전에 JSX 엘리먼트를 자바스크립트 객체로 변환하는 데 사용되었다.
+- 각 JSX 엘리먼트는 `React.createElement` 함수 호출로 변환되어, 리액트 엘리먼트를 생성한다.
+
+
+
+> **jsx / jsxs 함수**
+
+- 리액트 17 이후, JSX 엘리먼트는 `jsx` 또는 `jsxs` 함수 호출로 변환된다.
+- 이 함수들은 `react/jsx-runtime` 모듈에서 제공되며, `React.createElement`와 유사하게 리액트 엘리먼트를 생성하지만, 성능 최적화 및 코드 간결성 측면에서 개선된다.
+
+
+
+## 가상DOM과 리액트 파이버
+
+> **DOM과 브라우저의 렌더링 과정**
+
+1. 브라우저가 사용자가 요청한 주소를 방문해 HTML 파일을 다운로드 받는다.
+
+2. 브라우저의 렌더링 엔진은 HTML을 파싱해 DOM 트리를 만든다.
+3. 2번 과정에서 CSS 파일을 만나면 CSS 파일도 다운로드한다.
+4. 브라우저 렌더링 엔진은 이 CSS를 파싱해 CSSOM(css 노드 트리)을 만든다.
+5. 브라우저는 DOM 노드를 순회하는데, 여기서 사용자 눈에 보이는 노드만 방문한다.
+ 1. `display:none`과 같은 화면이 보이지 않는 요소는 방문해 작업하지 않는다.
+ 2. 이는, 트리를 분석하는 과정을 조금이라도 빠르게 하기 위해서다.
+6. 눈에 보이는 노드를 대상으로 해당 노드에 대한 CSSOM 정보를 찾고 여기서 발견한 CSS 스타일 정보를 이 노드에 적용한다. 이 DOM 노드에 CSS를 적용하는 과정은 크게 두 가지로 나눌 수 있다.
+ 1. 레이아웃
+ 1. 각 노드가 브라우저 화면의 어느 좌표에 정확히 나타나야 하는지 계산하는 과정. 이 레이아웃을 거치면 반드시 페인팅 과정도 거친다.
+ 2. 페인팅
+ 1. 레이아웃 단계를 거친 노드에 실제 유효한 모습을 그리는 과정
+
+
+
+### **Virtual DOM의 탄생 배경**
+
+> **실제 DOM 조작의 단점**
+
+**`성능 문제`**
+
+- 실제 DOM 요소를 직접 조작하는 것은 비용이 많이 든다. DOM 요소를 변경할 때마다 브라우저는 레이아웃을 다시 계산하고 페이지를 그려야 한다.
+
+**`효율성 문제`**
+
+- 각 변경사항마다 DOM을 업데이트하고 다시 렌더링하는 과정은 많은 자원을 소모하기에 효율적이지 못하다.
+
+
+
+> **Virtual DOM의 장점**
+
+`**성능 향상**`
+
+- Virtual DOM은 실제 DOM을 직접 조작하는 대신 메모리에 가상의 DOM 트리를 유지하여 작동한다. 컴포넌트에 상태가 변경될 때마다 새로운 가상 DOM 트리가 생성되고, 이전 가상 DOM트리와 비교하여 실제 변경사항만 실제 DOM에 반영한다.
+
+**`배치 업데이트`**
+
+- 변경사항을 한 번에 모아서 처리한다. 여러 변경사항이 발생하더라도, 모든 변경사항을 하나의 업데이트로 묶어 실제 DOM에 한 번에 반영한다. 이는 불필요한 렌더링을 줄일 수 있다/.
+
+---
+
+### 리액트 파이버란?
+
+리액트 파이버는 개념적으로 두 가지 측면이 있다. 하나는 React의 내부 구현에 관한 것이고, 다른 하나는 그 구현을 가능하게 하는 알고리즘에 관련된 것이다.
+
+> **파이버 객체**
+
+- 리액트에서 관리하는 평범한 자바스크립트 객체다.
+- `React element`에 생명 주기, 상태, hook등의 정보를 `확장한 객체`이다.
+- VDOM의 노드 객체이며, VDOM에 올리기 위해 사용된다.
+
+
+
+> **파이버 알고리즘**
+
+- `비동기 렌더링`을 가능하게 하며, 작업의 우선 순위 지정과 같은 기능을 제공한다.
+- React가 어떻게 컴포넌트 트리를 순회하고, 변경사항을 어떻게 감지하며, 업데이트를 어떻게 스케줄링하는지에 대한 기본적인 메커니즘을 정의한다.
+
+
+
+> **Stack vs Fiber**
+
+이전에 React의 조정 알고리즘은 스택 알고리즘으로 이뤄져 있었다. 즉, 작업 순서가 동기적으로 작동하며 작업 순서에 대해 유연하지 못했다. 하지만 파이버는 비동기적으로 작동하여 작업 순서를 유연하게 정할 수 있게 한다.
+
+
+
+---
+
+### 리액트의 렌더링 과정
+
+리액트의 렌더링 과정은 크게 `render phase`, `commit phase`로 나뉜다.
+
+> **Render 단계**
+
+- VDOM을 재조정(reconciliation)하는 단계.
+- 두 렌더 트리를 비교하면서 실제 DOM에 반영할 변경사항을 파악하는 단계이다.
+- stack에서 fiber로 변경되었다는 것은 reconciler의 변경을 의미한다. 이를 통해 abort, stop, restart 등 렌더링 우선순위 변경이 가능해졌다.
+
+
+
+> **Commit 단계**
+
+- 재조정한 VDOM을 DOM에 적용하는 단계.
+- 동기적으로 실행되며, DOM 조작 일괄 처리 후에 리액트 콜스택을 비워주고 브라우저가 paint를 시작한다.
+
+[[React 까보기 시리즈] Virtual DOM 이 자바스크립트 객체라고? render phase 와 commit phase 로 나누어서 동작 원리 살펴보기](https://www.youtube.com/watch?v=2EbCEluOO9Y&list=PLpq56DBY9U2B6gAZIbiIami_cLBhpHYCA&index=3)
+
+[React의 렌더 단계와 커밋 단계](https://www.moonkorea.dev/React-렌더단계-커밋단계)
+
+---
+
+### Virtual DOM 트리
+
+Virtual DOM트리는 react element를 확장한 객체인 fiber 노드로 구성되어 있다. 또한 DOM에 마운트 된 정보들을 나타내는 `current` 트리와 작업(render phase) 중인 트리인 `workInProgress` 트리로 구성되어 있다.
+
+workInProgress 트리는 current의 자기 복제로 생성된 트리이며, 이 둘은 `alternate` 로 서로를 참조하고 있다. commit phase에서 이 workInProgress트리는 current 트리가 되고 다시 자기 복제로 workInProgress 트리를 생성한다.
+
+
+
+> **더블 버퍼링**
+
+위와 같이 Virtual DOM은 두 개의 트리를 사용한다. 이를 더블 버퍼링 구조라고 한다. 이를 통해 변경사항을 한 번에 화면에 반영할 수 있으며 작업 순서를 유연하게 가져갈 수 있다.
+
+
+
+> **파이버 트리의 특징과 작업 순서**
+
+- 각 노드들은 작업을 시작할 때 `beginWork()`를 수행한다.
+- 각 노드들은 작업이 종료되거나, 모든 자식 노드들의 작업이 수행되었을 때 `completeWork()`를 수행하고 형제 노드가 존재한다면 형제 노드로 이동, 존재하지 않는다면 부모 노드로 이동한다.
+- 루트 노드가 완성되는 순간, 최종적으로 `commitWork()`가 실행되고 변경 사항을 비교해 업데이트가 필요한 변경 사항이 DOM에 반영된다.
+- 부모 노드는 첫 번째 자식만을 `child` key로 참조한다.
+- 형제 노드들은 `sibling` key로 참조하고 있다.
+
+
+
+## 클래스형 컴포넌트
+
+> **클래스형 컴포넌트 구조**
+
+기본적으로 클래스형 컴포넌트를 만들려면 클래스를 선언하고 extends로 만들고 싶은 컴포넌트를 확장해야한다.
+
+- `React.Component`
+- `React.PureComponent`
+
+```jsx
+import React, { Component } from 'react';
+
+class MyComponent extends Component {
+ constructor(props) {
+ super(props);
+ // 초기 상태 설정
+ this.state = {
+ count: 0,
+ };
+ }
+
+ render() {
+ return (
+
+
{this.state.count}
+
+
+ );
+ }
+}
+
+export default MyComponent;
+```
+
+- `constructor()`
+ - 이 생성자 함수는 컴포넌트가 초기화되는 시점에 호출된다. 여기서 state를 초기화할 수 있다.
+ - `super()`는 컴포넌트를 만들면서 상속받은 상위 컴포넌트, 즉 React.Component의 생성자 함수를 먼저 호출해 필요한 상위 컴포넌트에 접근할 수 있게 도와준다. 호출하지 않을 경우 `this` 키워드를 사용할 수 없게 되어 상태나 메서드를 정의하고 사용하는 데 문제가 발생할 수 있다.
+- `props`
+ - 컴포넌트에 특정 속성을 전달하는 용도로 사용된다.
+- `state`
+ - 클래스형 컴포넌트 내부에서 관리하는 값이다. 이 값은 `반드시 객체`여야한다. 이 값에 변화가 발생할 때마다 리렌더링이 발생한다.
+- `메서드`
+ - 렌더링 함수 내부에서 사용되는 함수이다. 보통 DOM에서 발생하는 이벤트와 함께 사용된다.
+
+
+
+> **this 바인딩**
+
+- 일반적인 함수로 메서드를 만든다면 `this`가 `undefined`로 나온다. 생성자가 아닌 일반 함수로 호출하게 되면 this에 전역 객체가 바인딩 되기 때문이다. 따라서 생성자 함수에 bind로 this를 강제 바인딩 해야한다.
+- `화살표 함수`를 사용하면 작성 시점에 this가 상위 스코프로 결정되어 굳이 바인딩을 하지 않아도 된다.
+- **콜백에서 화살표 함수를 사용하여 메서드를 호출**하면 this는 항상 컴포넌트 인스턴스를 참조한다.
+
+```tsx
+import { Component } from 'react';
+
+class Sample2 extends Component {
+ private constructor(props: Props) {
+ super(props);
+
+ this.state = {
+ count: 0,
+ };
+
+ // 강제로 this 바인딩
+ this.reset = this.reset.bind(this);
+ }
+
+ private reset() {
+ console.log('this is:', this);
+ this.setState({ count: 0 });
+ }
+
+ // 일반 함수로 선언
+ incrementCount() {
+ this.setState({ count: this.state.count + 1 });
+ }
+
+ // 일반 함수로 선언
+ decrementCount() {
+ this.setState({ count: this.state.count - 1 });
+ }
+
+ render() {
+ return (
+
+
{this.state.count}
+ {/* this는 undefined로 에러 발생*/}
+
+
+ {/* 잘 작동하지만 매 렌더링마다 함수가 새로 생성된다 */}
+
+
+
+
+ );
+ }
+}
+
+export default Sample2;
+```
+
+
+
+> **왜 this는 undefined를 참조하는가?**
+
+이벤트 핸들러로 일반 함수를 전달할 경우, 함수의 호출 방식이 달라져 this의 바인딩이 변경될 수 있다. 이는 this의 컨텍스트가 **함수 호출 방식**에 따라 결정되는 특성 때문이다.
+
+메서드는 이벤트 발생 시 React에 의해 직접 호출되는 콜백 함수로서 작동된다. 이 때, 함수는 메서드가 속한 객체의 메서드로서 호출되는 것이 아니라, 단순히 **독립된 함수로서 호출**되기때문에, 기본적으로 `this`는 전역 객체(브라우저 `window`, 엄격모드 `undefined`)를 가리키게 된다
+
+```jsx
+
+```
+
+
+
+아래와 같이 메서드 내부에서 새롭게 화살표를 만들어서 전달하는 방법인 경우에는 어떻게 this가 정확히 컴포넌트 인스턴스를 참조하는걸까?
+
+```jsx
+// Sample2 {props: {…}, context: {…}, refs: {…}, updater: {…}, squareCount: ƒ, …}
+
+```
+
+화살표 함수가 컴포넌트 클래스 내에서 정의되었기 때문에, 이 함수 내의 `this`는 해당 컴포넌트 인스턴스를 정확히 가리키며, 결과적으로 `incrementCount` 메서드도 컴포넌트 인스턴스의 `this` 컨텍스트 내에서 실행된다.
+
+
+
+## 클래스형 컴포넌트의 생명주기 메서드
+
+생명주기 메서드는 컴포넌트의 **생성부터 소멸**까지 여러 시점에 호출되는 메서드들이다. 이러한 메서드들은 컴포넌트들의 상태를 관리하고, 컴포넌트가 화면에 렌더링 되기 전후의 작업을 처리하는 데 사용된다.
+
+> **생명주기 메서드가 실행되는 시점**
+
+- `마운트(mount)`
+
+ - 컴포넌트가 마운팅(생성)되는 시점
+
+- `업데이트`
+ - 이미 생성된 컴포넌트의 내용이 변경되는 시점
+- `언마운트`
+ - 컴포넌트가 더 이상 존재하지 않는 시점
+
+
+
+> **render()**
+
+- 리액트 클래스형 컴포넌트의 유일한 **필수 값**으로 항상 쓰인다.
+
+- 컴포넌트가 **UI를 렌더링**하기 위해 쓰인다.
+- **마운트와 업데이트** 과정에서 일어난다.
+- 부수효과가 없는 순수 함수여야한다.
+ - `this.setState()`를 호출하면 안된다. state를 변경하는 일은 컴포넌트의 메서드나 다른 생명주기 메서드 내부에서 발생해야한다.
+
+
+
+> **componentDidMount()**
+
+- 클래스형 컴포넌트가 **마운트된 직후에 호출**되는 생명주기 메서드다.
+
+- `this.setState()`로 state를 변경하는 것이 가능하다.
+- 외부 데이터 요청 후 상태 업데이트, DOM에 의존적인 작업 등을 할 때 주로 사용된다.
+
+
+
+> **componentDidUpdate(prevProps, prevState, snapshot)**
+
+- 컴포넌트 **업데이트가 일어난 이후 바로 실행**된다.
+
+- `this.setState()`를 사용할 수 있다.
+- 매개변수
+
+ - `prevProps`: 업데이트 되기 전의 props
+
+ - `prevState`: 업데이트 되기 전의 state
+ - `snapshot`: **getSnapshotBeforeUpdate**에서 반환된 값이며, 업데이트가 일어나기 직전의 DOM 상태에 대한 데이터를 포함할 수도 있다.
+
+
+
+> **componentWillUnMount()**
+
+- 컴포넌트가 **언마운트되거나 더 이상 사용되지 않기 직전에 호출**된다.
+
+- `this.setState()`를 사용할 수 없다.
+- 메모리 누수나 불필요한 작동을 막기 위한 **클린업 함수를 호출**하기 위한 최적의 위치다.
+ - `clearInterval()` 등
+
+
+
+> **shouldComponentUpdate()**
+
+- props나 state가 변경되었을 때 호출된다.
+- 컴포넌트의 props나 state가 변경되었을 때 리렌더링을 할지 말지 결정하는데 사용된다.
+- `false`를 리턴하는 경우 리렌더링을 발생시키지 않는다.
+
+ ```jsx
+ shouldComponentUpdate(nextProps, nextState) {
+ // 현재 state와 다음 state를 비교하여 count 값이 변경되었는지 확인
+ if (this.state.count !== nextState.count) {
+ return true; // count 값이 변경되었다면 리렌더링
+ }
+ return false; // 변경되지 않았다면 리렌더링하지 않음
+ }
+ ```
+
+- React 16.3 버전 이후에는 `PureComponent`를 사용하여 `shouldComponentUpdate`와 유사한 최적화를 더 간단하게 적용할 수 있다.
+ - `PureComponent`는 컴포넌트의 props와 state에 대한 얕은 비교를 자동으로 수행하여, 변경이 없을 경우 리렌더링을 방지한다. 얕은 비교가 충분하지 않은 경우에는 shouldComponentUpdate를 직접 구현해야한다.
+
+
+
+> **static getDerivedStateFromProps(nextProps, prevState:State)**
+
+- 이 메서드는 `render()`를 호출하기 직전에 호출된다.
+
+- 주로 부모 컴포넌트로부터 받은 props를 기반으로 컴포넌트의 state를 업데이트할 필요가 있을 때 사용된다.
+- `static`으로 선언되어 있어 this에 접근할 수 없다.
+- 이 메서드는 객체를 반환하거나 null을 반환해야한다.
+ - 반환된 객체는 state에 병합된다.
+ - state를 업데이트할 필요가 없다면 null을 반환한다.
+
+
+
+> **getSnapShotBeforeUpdate()**
+
+- DOM이 업데이트 되기 직전에 호출된다.
+
+- 여기서 반환되는 값은 `componentDidUpdate()`의 세 번째 인자(snapshot)로 전달된다.
+
+```jsx
+class MyComponent extends React.Component {
+ getSnapshotBeforeUpdate(prevProps, prevState) {
+ // 업데이트가 이루어지기 전에 현재 스크롤 위치를 캡처
+ if (prevProps.list.length < this.props.list.length) {
+ const list = document.getElementById('list');
+ return list.scrollHeight - list.scrollTop;
+ }
+ return null;
+ }
+
+ componentDidUpdate(prevProps, prevState, snapshot) {
+ // 스냅샷 값이 있다면, 스크롤 위치를 조정하여 스크롤 위치를 유지
+ if (snapshot !== null) {
+ const list = document.getElementById('list');
+ list.scrollTop = list.scrollHeight - snapshot;
+ }
+ }
+
+ ...
+}
+
+```
+
+
+
+> **getDerivedStateFromError(error)**
+
+- 자식 컴포넌트에서 오류가 발생했을 때 호출되는 에러 메서드다.
+
+- `static` 메서드이며 오류를 인자로 받으며 반드시 state를 반환해야한다.
+- 렌더링 과정에서 발생하는 메서드이기 때문에 부수효과를 발생시키는 것을 권장하지 않는다.
+
+
+
+> **componentDidCatch(error, info)**
+
+- 자식 컴포넌트에서 에러가 발생했을 때 실행되며, `getDerivedStateFromError`에서 에러를 잡고 state를 결정한 이후에 실행된다.
+
+- 두 개의 인자를 받는다.
+
+ - `error`: 발생한 오류 객체. getDerivedStateFromError와 동일하다.
+
+ - `info`: 오류에 대한 추가 정보를 담고 있는 객체. `componentStack` 속성을 통해 오류가 어떤 컴포넌트에서 발생되었는지 알 수 있다.
+
+ ```jsx
+ {
+ componentStack: '\n at Sample4 (http://localhost:3000/static/js/b…(http://localhost:3000/static/js/bundle.js:31:76)';
+ }
+ ```
+
+
+
+> **클래스형 컴포넌트의 한계**
+
+- 데이터의 흐름을 추적하기 어렵다.
+- 애플리케이션 내부 로직의 재사용이 어렵다.
+- 기능이 많아질수록 컴포넌트의 크기가 커진다.
+- 클래스틑 함수에 비해 상대적으로 어렵다.
+- 코드 크기를 최적화하기 어렵다.
+- 핫 리로딩을 하는 데 상대적으로 불리하다.
+
+
+
+---
+
+### 리액트의 렌더링이란?
+
+리액트에서의 렌더링이란 리액트 어플리케이션 트리 안에 있는 모든 컴포넌트들의 props와 state의 값을 기반으로 어떻게 UI를 구성하고 이를 바탕으로 어떤 DOM 결과를 브라우저에 제공할 것인지 계산하는 일련의 과정을 의미한다.
+
+### 리액트의 렌더링이 일어나는 이유
+
+> **최초 렌더링**
+
+사용자가 처음 애플리케이션에 진입하면 브라우저에 결과물을 제공하기 위해 최초 렌더링을 수행한다.
+
+
+
+> **리렌더링**
+
+리렌더링은 최초 렌더링 이후에 발생하는 모든 렌더링을 의미한다. 다음과 같은 경우 리렌더링이 발생한다.
+
+- 클래스형 컴포넌트의 setState가 실행되는 경우
+
+- 클래스형 컴포넌트의 forceUpdate가 실행되는 경우
+- 함수형 컴포넌트의 상태를 변경하는 setter, dispatcher가 실행되는 경우
+- 컴포넌트의 key props가 변경되는 경우
+- props가 변경되는 경우
+- 부모 컴포넌트가 렌더링될 경우
+
+
+
+### 재조정이란?
+
+리액트의 재조정(Reconciliation)은 DOM을 효율적으로 업데이트하기 위해 사용하는 프로세스다.
+
+리액트 컴포넌트의 상태가 변경되었을 때 재조정 과정은 가상 DOM 트리의 변경 전과 후를 비교하여 실제 DOM을 최소한으로 수정하는 방법을 결정하는 과정이다.
+
+
+
+### 렌더 단계란?
+
+렌더 단계(Render Phase)는 컴포넌트를 렌더링하고 변경사항을 계산하는 모든 작업을 말한다. 즉, 렌더링 프로세스에서 컴포넌트를 호출하여 이 결과와 이전 가상 DOM을 비교하는 과정을 거쳐 변경이 필요한 컴포넌트를 체크하는 단계다. 여기서 비교하는 것은 크게 type, props, key다.
+
+렌더 단계에서는 아래와 같은 과정을 거친다.
+
+1. 가상 DOM 생성
+
+2. 재조정(Reconciliation)
+3. 컴포넌트의 호
+
+
+
+### 커밋 단계란?
+
+커밋 단계(Commit Phase)는 렌더 단계의 변경 사항을 실제 DOM에 적용해 사용자에게 보여주는 과정을 말한다. 즉, 리액트가 DOM을 업데이트하고, 필요한 경우 생명주기 메서드를 호출한다. 커밋 단계는 리액트가 UI를 실제로 업데이트하는 유일한 시점이다.
+
+커밋 단계의 주요 작업
+
+1. DOM 업데이트
+
+2. 생명주기 메서드 실행
+3. hooks 실행
+
+리액트의 렌더링이 일어난다고 해서 무조건 DOM 업데이트가 일어나는 것은 아니다. 변경 사항을 계산했는데 아무런 변경사항이 감지되지 않는다면 이 커밋 단계는 생략될 수 있다.
+
+---
+
+## 컴포넌트와 함수의 무거운 연산을 기억해두는 메모이제이션
+
+- useMemo, useCallback, memo 등 렌더링을 최소화하기 위한 방법들을 모두가 알고있지만, 언제 사용을 해야하는지에 대한 답변을 하는건 어려워한다.
+
+### useMemo
+
+- 비용이 큰 계산 결과를 메모이제이션
+
+- 사용하기 좋은 경우
+
+ - 계산 비용이 큼
+ - 배열/객체 참조 안정성 필요
+ - memo와 함께 사용
+ - dependency 변경 빈도 낮음
+
+- 굳이 필요 없는 경우
+
+ - 단순 문자열 계산
+ - 단순 숫자 계산
+ - 렌더 비용보다 memo 비용이 더 큼
+
+### useCallback
+
+- 함수 재생성 방지
+
+- 사용하기 좋은 경우
+
+ - memo child에 함수 전달
+ - effect dependency 안정화
+ - custom hook 반환 함수
+ - 함수 참조 동일성 중요
+
+- 굳이 필요 없는 경우
+
+ - 내부 로컬 이벤트 함수
+ - 리렌더 영향 거의 없음
+
+### React.memo
+
+- props 변경 없으면 컴포넌트 리렌더 방지.
+
+- 언제 사용해야하는가 ?
+
+ - 부모가 자주 리렌더되는 경우
+ - 리스트 아이템 최적화 ( 리스트가 수백개인 경우 )
+
+- memo만 쓰면 안 되는 이유
+
+ - props가 객체/함수면 매번 새 참조 생성됨. -> 그렇기에 memo가 의미가 없음
+
+- 실제 사용 패턴
+
+```tsx
+const Child = memo(({ onClick, items }) => {});
+
+function Parent() {
+ const items = useMemo(() => expensiveFilter(data), [data]);
+
+ const handleClick = useCallback(() => {}, []);
+
+ return (
+
+ );
+}
+```