Rerendering & Diffing algorithm
June 28, 2024
Rerendering
→ 리액트 컴포넌트는 그 state나 props가 변경될 때 rerendering이 발생. Rerendering은 다음과 같은 과정을 거침:
- State 변경: 컴포넌트의 state 또는 props가 변경되면 리액트는 해당 컴포넌트를 리렌더링할 준비를 함.
- Virtual DOM 생성: 변경된 컴포넌트에 대한 Virtual DOM 트리가 생성됨.
- Diffing 과정: Diffing 알고리즘을 사용하여 Virtual DOM과 이전 DOM을 비교하여 차이점을 계산.
- 실제 DOM 업데이트: 계산된 차이점을 바탕으로 실제 돔이 최소한으로 업데이트 됨.
💡 그렇다면, 언제 리렌더링이 되고, 리렌더링의 조건은 무엇일까?
- 부모/자식 관계와 형제 관계
const Parent = () => {
return (
<Child1>
<Child2>
<Child3 />
</Child2>
</Child1>
)
}
const Child1 = ({ children }) => <div>{children}</div>;
const Child2 = ({ children }) => <div>{children}</div>;
const Child3 = () => <div>막내</div>;
- 자신 컴포넌트들은 부모 컴포넌트가 리렌더링되면 똑같이 리렌더링됨.
- 자식 컴포넌트란 부모 컴포넌트의 JSX 안에서 사용된 모든 컴포넌트.
- 형제 관계 (Child1, Child2, Child3) 컴포넌트들끼리는 서로 리렌더링에 영향이 없음.
function App() {
return (
<Parent lastChild={<ChildC />}>
<ChildB />
</Parent>
);
}
function Parent({ children, lashChild }) {
return (
<div className="parent">
<ChildA />
{children}
{lastChild}
</div>
);
}
...
위의 코드에서 Parent 컴포넌트가 리렌더링되면 ChildA, ChildB, ChildC 중에서 어떤 컴포넌트가 리렌더링 될까요?
우선 자식 컴포넌트의 정의에 따르면, ChildB와 ChildC는 App의 자식이 되는 것이기 때문에, ChildA만 리렌더링됨. App의 자식은 Parent, ChildB, ChildC이고, Parent의 자식은 ChildA가 됨.
Diffing Algorithm
→ Virutal DOM 트리의 각 노드를 순회하며 변경사항을 업데이트 하는 것은 리액트의 핵심 알고리즘.
Diffing Algorithm이란, Virtual DOM 엘리먼트와 실제 브라우저에 등록되어 있는 DOM 엘리먼트를 비교하여 dirty
체크된 엘리먼트들을 처리. 처리하는 과정에서 props 값만 변경된 경우, props 값만 업데이트하고, 해당 엘리먼트의 태그 혹은 컴포넌트가 변경된 경우라면 해당 노드를 포함한 하위 모든 노드를 언마운트한 뒤에 새로운 Virtual DOM 으로 대체.
💡 Diffing Algorithm에서는 어떻게 각 노드를 순회하여 비교할 수 있을까?
→ Diffing algorithm은 heuristics algorithm
이라는 알고리즘을 이용하여 DOM 트리를 순회하고 있음.
Heuristics algorithm 이란?
→ 모든 것을 순회하는 것은 비용이 너무 높으니, 중요하지 않은 정보들을 고려하지 말고 중요한 정보들만 고려해서 최선의 값을 찾아내는 방법.
리액트는 순회과정에서 어떠한 값을 중요하다고 판단하는지?