React가 렌더링 최적화를 위해서 어떤 걸 하고 있나요?

2025년 11월 19일 08:59|개발 / React
요즈미나의 프로필 사진요즈미나

Fiber는 몸에 좋아요. React Fiber는 과연...?Fiber는 몸에 좋아요. React Fiber는 과연...?

기술면접 단골로 등장하는 이 질문은 SPA(Single Page Application)의 변천사와도 밀접한 관련이 있어요. 단어 뜻 그대로 한 페이지 안에 모든 기능이 있는 SPA는 그 페이지 자체만으로도 많은 기능이 있고, 여러 State의 변경이 있으며, 그만큼 레이아웃 업데이트도 많이 일어나는 애플리케이션이었죠. 일단 기존방식인 DOM이 뭐하는 녀석인지 살펴볼 필요가 있어요.

🌲 DOM(Document Object Model)이란?

HTML 요소들의 구조화된 표현으로, 웹 애플리케이션의 UI들을 나타내요. 각각의 태그를 노드(Node)라고 부르며, 이 노드들이 모여서 DOM Tree가 되어요. 이 DOM Tree는 웹 개발자에게 JavaScript를 통해 콘텐츠를 수정할 수 있게 해줘요. 또한 Tree 형식으로 구조화되어있기 때문에 특정 대상을 선택할 수도 있고(getElementBy~), 모든 코드에 대한 작업을 더 수월하게 할 수 있어요.

그런데 이 DOM에는 큰 단점이 있답니다.

🤔 DOM이 가진 단점?

Tree 구조이다 보니까, 페이지의 UI를 업데이트 하기 위해 업데이트 된 요소 뿐만 아니라 그 자식 요소들까지 다시 렌더링되어야 한다는 단점이 있어요. 예를 들어 list 라는 id를 가진 div안에 \<ul>\<li>가 들어있다고 치면, list id를 가진 div를 업데이트 하려면 다음과 같은 과정을 거쳐요.

  1. 브라우저는 list라는 id를 가진 노드를 찾기 위해 HTML을 파싱해서 CSSOM 트리를 생성해요.

  2. 특정된 요소에서자식 요소들을 제거해요.

  3. DOM 요소를 업데이트 할 값으로 업데이트해요.

  4. 부모, 자식 노드에 대한 CSS를 다시 계산해요(Reflow).

  5. 레이아웃을 업데이트해요.

  6. 마지막으로, 트리를 가로지르며 브라우저 디스플레이에 업데이트된 레이아웃을 페인트해요(Repaint).

여기서 등장하는 키워드인 ReflowRepaint는 따로 글을 할애해서 써야 할 정도의 내용을 갖고 있지만, 이 글에서는 간략하게 4번과 6번처럼 설명했어요. 이 Reflow와 Repaint는 변경점이 있는 하위 노드와 상위 노드간의 레이아웃을 모두 재계산하기 떄문에 계산과정이 매우 비싼데요, 심지어 현대의 기능이 많고 애니메이션이 화려해지는 웹사이트들은 이 렌더트리 재생성 - Reflow - Repaint 과정이 계속 반복되기 때문에, 기존 DOM 업데이트 방식으로는 이 렌더 수요를 따라갈 수가 없었죠. 그래서 React는 똑똑한 방법으로 레이아웃의 변경점을 갱신한답니다.

🫥 Virtual DOM의 등장

Virtual DOM은 JavaScript 객체(JSON이 아님에 유의하세요) 형태로 메모리 안에 저장되어 있으며, 아래와 같이 두 개의 가상 DOM 객체를 기반으로 실제 DOM을 조작해요.

  1. 렌더링 이전 화면 구조를 가진 가상 DOM

  2. 렌더링 이후에 변경사항이 적용된 구조를 가진 가상 DOM

노드에 업데이트 사항이 있으면 이를 반영할 떄마다 리렌더링이 발생하는데, 이 때마다 새로운 변경사항이 적용된 가상 DOM을 생성해 메모리에 저장하죠. 그래서 1번과 2번을 비교해서(Diffing) 차이가 발생한 부분만 실제 DOM에 적용해요.

🎭 Diffing

State가 변경되기 이전의 가상 DOM과 이후의 가상 DOM을 비교하는 것을 Diffing이라고 해요. 가상 DOM은 애초에 무거운 DOM API를 통하지 않고 각 노드를 JavaScript 객체로만 변환하여 핸들링하기 때문에 훨씬 빠르고 가볍게 변경점을 반영한 가상 DOM을 만들 수 있어요. 이렇게 만들어진 반영 전과 후의 가상 DOM을 Diffing 알고리즘을 통해 효율적으로 다른 점을 파악할 수 있답니다. Diffing 알고리즘도 또한 내용이 많지만 이 글에서는 이렇게만 다룰게요.

  1. 웹페이지에 콘텐츠가 렌더링되고 DOM 트리가 생성되어요.

  2. State에 변화가 생기면 가상 DOM의 노드를 업데이트해요.

  3. 재조정(Reconciliation)과정에서 이전 트리는 가장 최근 버전 트리와 비교되고 업데이트가 필요한 변경사항의 개수를 판별해요. (이것에 대한 휴리스틱 알고리즘은 밑에서 설명할게요)

  4. 변경사항을 결정한 후에 실제 DOM에서 구현할 수 있도록 최적화된 최소한의 명령어 집합이 생성되어요.

  5. 이러한 변경사항들이 구현된 후 변경된 콘텐츠들만 웹 페이지에서 리렌더링되어요.

여기서 꾸준히 등장하는 JavaScript 객체라는 단어가 있죠?

이것이 바로 Fiber 노드입니다!!

🪢 Fiber 노드란?

React 16부터 추가된 Fiber 노드는 Virtual DOM을 이루고 있는 JavaScript 객체입니다. 각 HTML Element마다 대응되는 Fiber 노드가 있으며, 객체 안에 React 컴포넌트, 입력, 출력에 대한 정보를 담고 있죠. 그래서 우리는 ‘React가 렌더링 최적화를 위해서 어떤 것을 하나요?’라는 질문에 대한 답변 첫 번째를 얻을 수 있어요.

“React Fiber 노드로 이루어진 Virtual DOM을 사용해서 Reflow와 Repaint를 최소화합니다.”

근데!

Fiber는 이것 말고도 하나 더 있어요. 휴리스틱 알고리즘은 밑에서 설명한다는 말 보셨죠? 바로…

🚘 Fiber 엔진

위에 나온 재조정(Reconciliation)이라는 부분에서 등장하는데요, 이 재조정 과정을 거치는 엔진이 있습니다. React 16부터 Fiber 엔진이 추가가 되었는데요, 같은 이름을 써서 헷갈리죠? 저도 그랬어요…

재조정은 Diffing의 3번 이후의 과정을 말합니다. ‘이전 트리는 가장 최근 버전 트리와 비교되고 업데이트가 필요한 변경사항의 개수를 판별해요’라고 써있는데, 이 부분에 대해 자세히 말하자면,

  • 작업을 작은 단위로 분할하고 우선순위를 정합니다.

  • 이 작업은 일시정지할 수 있고, 나중에 다시 시작할 수 있어요.

  • 이전에 했던 작업을 다시 재사용하거나, 필요없을 경우 폐기할 수도 있어요.

이전 Fiber 트리와 변경된 Fiber 트리를 비교하고 변경사항을 결정한 후에 실제 DOM에 Commit하는 과정을 거치는 것이 Fiber 엔진의 알고리즘이에요. 이렇게 질문에 대한 답변 두 번째를 얻을 수 있죠.

“Fiber 엔진을 통해 변경 전의 트리와 변경 후의 트리를 비교하여 변경된 부분만 갱신하는 방식으로 렌더링 최적화를 합니다.”

출처:

<OG 로딩중...

<OG 로딩중...

<OG 로딩중...

<OG 로딩중...

<OG 로딩중...

요즈미나의 프로필 사진
요즈미나

나는 짱쎄다