프로젝트를 반년 간 했지만 기능을 개발하는 것에 급해서 리액트의 작동원리를 제대로 모르고 있다는 생각이 들었다. 이번 기회에 한번 정리를 하고자 한다. (내가 헷갈렸던 것만 모아모아 정리)
props, children으로 받은 컴포넌트는 자식 컴포넌트가 아닌 점을 이용하여 리액트 렌더링 최적화를 해줄 수 있다는 점!
리액트는 리렌더링을 할 때 변경된 부분만 리렌더링한다는 정도만 알고 있었다. 하지만 렌더링의 과정에는 리액트 렌더링과 브라우저 렌더링으로 구분된다.
렌더링을 하는 두가지 이유가 있다.
⇒ 만약 자식 컴포넌트가 존재한다면 recursive하게 계속 호출
리액트는 DOM을 수정한다.
DOM이 왜 필요한가?
DOM은 브라우저 상에서 자바스크립트가 HTML 문서를 조작하기 위한 API
자바스크립트가 직접 HTML을 동적으로 바꾸는데에는 한계가 있으니 JS가 조작하기 편하게 DOM이라는 형태로 바꾸어 놓은 것
Virtual Dom의 기본적인 원리
1. real dom으로 부터 virtual dom을 만든다 (virtual dom은 메모리 상에 존재하는 하나의 객체이다)
2. 변화가 생기면 새로운 버전의 virtual dom을 만든다
3. 구 버전의 virtual dom과 새로운 버전의 virtual dom을 비교한다
4. 차이가 있으면 차이점을 real dom에 적용한다
왜 React는 Virtual Dom을 만들었는가
리액트는 상태가 변하면 관찰자에게 알림을 보내주는 방식이다. 효율적이지만, 전체를 렌더링시키기 때문에 비용이 커진다. 그래서 나온 것이 virtual dom이다.
브라우저를 렌더링 시키는 비용 vs 객체를 새로 만드는 비용
후자가 더 저렴하기 때문이다.
react fiber이 나온 이유?
virtual dom은 구 버전의 virtual dom과 새로운 virtual dom을 비교할 때 재귀적으로 비교한다. 즉 한번 시작하면 끝날 때까지 순회를 무조건 해야한다. 이때 이 시간이 길어지면 프레임 드롭이 발생하고 유저 이벤트에 즉각적으로 대응하는 것이 어려워진다.
따라서 react fiber는 이 문제를 해결한다.
1. 작업을 멈추고, 나중에 다시 시작한다
2. 다양한 종류의 작업에 따라 우선순위를 부여한다
3. 더 이상 필요하지 않은 작업물이면 버릴 수 있다.
이 세가지 스텝이 끝나고 DOM이 업데이트되면 브라우저 렌더링이 시작되게 된다.
브라우저 렌더링은 예전에 정리해두었다. https://velog.io/@coddingyun/브라우저-렌더링과-최적화
state나 props가 변경되면 리렌더링이 발생한다.
리렌더링할 때, 바뀌지 않은 props를 자식 컴포넌트에게 전달해주어도 해당 자식 컴포넌트는 리렌더링 된다.
그 이유는, 함수형 컴포넌트가 다시 호출될때 다시 모든 것이 호출되기 때문에, 바뀐 것으로 인식되는 것이다.
어떻게 렌더링을 최적화할 수 있을까?
왜?
객체가 매번 새로 생성 → 매번 다른 참조값을 가진 객체를 props로 전달 → React.memo 작동 x
const app = () => {
console.log('yes')
return (
<div>
</div>
)
}
https://react.dev/learn/render-and-commit
https://velog.io/@mogulist/understanding-react-rerender-easily
https://velog.io/@yesbb/virtual-dom의-성능이-더-좋은이유#4render-함수-내부에서-일어나는-일--react-fiber
https://www.youtube.com/watch?v=1YAWshEGU6g