리액트가 랜더링을 최적화하는 원리 파헤쳐보자

이주영·2023년 1월 18일
0

ReactJs : 사용자 UI를 만들기 위한 JS 라이브러리

브라우저의 랜더링 원리

브라우저에서 화면을 그리기 위해 일어나는 일련의 과정들은 변화가 발생했을 때 일어난다.

여기서 말하는 변화는 유저와의 상호작용을 말하는데, 혹여나 상호작용 중 자바스크립트가 브라우저의 메인 스레드를 차지하면 block 현상이 일어난다.

그래서 중요하게 여겨지는 것이 60fps.

브라우저는 60fps를 가능하도록 하기 위해서 자바스크립트의 동작을 작게 쪼갠다.

https://developer.chrome.com/blog/inside-browser-part3/#updating-rendering-pipeline-is-costly

window.requestAnimationFrame(() => {
	const main = document.querySelector(".todoapp")
	const newMain = view(main, state)
	main.replaceWith(newMain)
})

위에서 살펴본 Web API의 requestAnimationFrame()과 같은 역할을 react에선 스케줄러(scheduler)cloneNode의 아이디어가 합쳐져 랜더링 최적화가 이루어진다.

리액트의 랜더링

리액트는 상태가 변화할 때마다 실제 DOM을 업데이트 하지 않고 in-memory에 올려둔 가상 돔을 업데이트한다. 이런 변화가 잦을때를 대비해서 스케쥴러를 통해서 관리한다. 한데 모인 변화는 스케줄러에 의해 배치(batch)로 모아져 원리에 의해 비동기적으로 처리된다.

// react-reconciler/src/ReactFiberHooks.js#L1358
function dispatchAction(...) {
  if (...) {
    /* Render phase update... */
  } else {
    /* idle update... */
    scheduleWork(fiber, expirationTime);
  }
}

여기서 중요한 개념이 재조정(reconciliation)

재조정 (reconciliation)

공식 문서를 통해 정리해보니 아래 두 가지 기준을 소개하고 있다.

  • 서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다. (Elements Of Different Types)
  • 개발자가 key를 활용하여 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 않아야 할지 표시해 줄 수 있다.

엘리먼트 혹은 컴포넌트에 부여하는 key의 역할

여기서 key가 얼마나 중요한지를 알 수 있다. 여러 컴포넌트 혹은 리스트들을 만들때 고유한 key를 부여하여 변화를 감지하여 효율적인 재조정 과정을 통해 렌더링을 시킨다.

여기서 기초적인 지식을 점검하고 가보자.

  1. 키를 사용하지 않았을때

  1. 키에 index를 사용할때

key에 index는 최후의 수단!이며 리스트를 추가하거나 삭제할때 형제 엘리먼트 모두를 불필요하게 업데이트 시켜 성능에 악영향을 끼치게 된다.

  1. 키에 고유한 id를 사용할때
<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

Connecticut이 삽입되었지만 형제 요소인 Duke와 Villanova는 변경되지 않는다. 위에서 정리한대로 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 않아야 할지 표시해준다는게 이런 뜻이었다.

다시 주제로 돌아가보면, 가상돔이 무엇이 변경되었는지 알아내는 기준이 두개가 있다고 한다. 이 기준으로 비교하면서 부모 트리에 변화가 있다면 자식 요소 모두 폐기하고 가상 DOM에 업데이트된 요소들로 교체한다는 것이 핵심.

이렇게 동작할 수 있는 이유는 바로바로 불변성을 전제하고 있기 때문에 가능하다고 하는데...

Q. 불변성을 전제로 리액트가 어떻게 최적화를 하고 있는지에 대해서 지금까지 이해한 것들을 토대로 다음 블로그에 정리해보겠습니다.

참고자료

:: 자바스크립트 역사

:: 브라우저 랜더링

:: 리액트 랜더링

글감 저장소

profile
https://danny-blog.vercel.app/ 문제 해결 과정을 정리하는 블로그입니다.

0개의 댓글