본문 바로가기

프론트엔드 개발/React - 이론

React의 랜더링 원리와 과정

1. React Elements의 특징에 대하여 

React의 랜더링 과정과 원리에 대해서 다루기 위해서는 먼저 React Elements의 특징에 대하여 알아야 한다. 이전 포스팅에서 다룬 바와 같이, React Elements는 불변성을 가진다. Elements의 불변성이란,

Elements 생성 후에는 Elements 속 children이나 attributes를 바꿀 수 없다!

이다.  그러면 다음과 같은 질문이 나올 수가 있다. 

어? 그렇다면, 사용자의 입력에 따라 화면을 갱신해야할 경우는 어떻게 해야하나요? 화면 속 Dom Elements의 원본인 React Elements가 불변성이면, 갱신을 구현할 수 없지 않나요?

좋은 질문이다! 
분명 React Elements는 불변하지만, 앞에 조건이 붙었다. 바로 'Elements가 생성된 후' 라는 조건이다. React Elements로 만들려면, 먼저 컴포넌트를 만들어야 함을 알 수 있었다. 다음 예시를 보자 

컴포넌트는 붕어빵 틀이다. 붕어빵 틀은 우리가 원하는 대로 고칠 수 있다. (철이라 힘은 들겠지만...) 하지만 붕어빵 틀로 만든 붕어빵은 고칠 수 없다! 이미 완성된 형태이고, 뜯어 고칠려 들면 부서지지 고친다는 것은 불가능하다. 이때 붕어빵을 Element로 생각하면 될 것 같다. 

 

2. React의 랜더링 원리

그래서 사용자 입력에 따라 갱신되는 화면은 어떻게 구현하나요!!

이제 그 답에 대해서 말해보면, 붕어빵 예시 처럼 우리는 붕어빵을 뜯어 고치려 들지 말고 '교체'해야 한다. 따라서 실제로 우리는 사용자의 입력에 따라 컴포넌트를 고치고, (입력 값에 따른 새로 계산된 결과를 출력하든, 쓰는 컴포넌트 자체를 바꾸든) 그 컴포넌트로 새로운 엘리먼츠를 만들어, Rendering 된 화면을 갈아 끼운다. React의 경우 이러한 'Re-Rendering' 과정이 매우 빠르다. 따라서 사용자에게는 이 갈아끼우는 화면이 입력 값에 따라 화면이 갱신되는 것 처럼 보인다. 

 

3. React의 랜더링 과정

이제 과정에 대해 살펴보자. React가 Rendering 과정이 빠른 이유는 Virtual DOM인 React Elements를 사용하기 때문이다. 계산과 각종 구현은 컴포넌트 형성과 JS 객체인 React Elements 형성 단계에서 다 해놓는다. Browser DOM 부분에서는 바뀐 부분만 다시 랜더링하면 된다.  처음부터 HTML 코드를 고쳐서 랜더링하는 과정은 용량도 무겁고 느린 반면에 위의 과정을 거치면 훨씬 빠르다. (이 이상의 정확한 원리는 모른다.)

따라서 Browser DOM은 이미 완성된 Virtual DOM을 랜더링만 해서 바뀐 부분만 교체하면 된다. 값 변화 인지 -> 값 변화 따른 재 연산 과정은 VirtualDOM 단계(컴포넌트 형성, React Elements로 변환)에서 전부 하는 것이다.

ⓐ 해당 과정 더 자세히 뜯어보기

spa(single page aplication)를 지키는 React 프로젝트에서는 하나의 root DOM elements가 존재한다. 

<div id="root"></div>

 해당 부분 안에 자식 태그로 React 프로젝트의 모든 화면이 구현된다. 따라서 그래프로 나타내면, 

해당 부분이 된다. 이제 완성된 React Elements를 DOM elements로 어떻게 바꾸는지 알아보자. 저번 포스트를 안 보고 오신 분들을 위해 간략하게 설명하자면, React Elements는 우리가 작성한 컴포넌트를 React.createElements()를 통해 바꾼, '화면에 그릴 내용에 대해 기술한 JS 객체'를 뜻한다. 일반 JS 파일에서는 직접 React.createElements() 함수를 써서 일일히 컴포넌트를 변환해줘야 했지만, JSX 파일을 사용한다면, 해당 과정은 뒤에서 React가 다 해줬다. 이제 이 JS 객체를 진짜 화면에 내용을 그리는 DOM Elements로 바꾸려면 다음과 같은 과정을 거쳐야 한다. 

const elements = <h1>안녕, 리액트! </h1>;
ReactDOM.render(element, document.getElementById('root'));

일단 내가 랜더링할 요소가 딱 하나이고, 그게 elements라는 변수라고 할 때, 밑의 함수는 그것을 DOM 요소로 바꾸는 함수이다. 첫번째 인자가 DOM 요소로 바꿀 React Elements를 특정하는 것이고, 두 번째 인자가 그 DOM 요소가 기입될 부모 Elements를 특정하는 것이다. 

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Library />
  </React.StrictMode>
);

이와 같이 작성도 가능하다. 

ⓑ 복잡한 예시 

tick 함수는 현재 시간을 담은 컴포넌트를 종국엔 DOM 엘리먼츠로 바꾸어 화면에 띄우는 함수이다. setInterval 함수는 위의 과정을 1초마다 반복하는 함수이다. 해당 코드를 실행하면, 1초마다 Re-rendering 되어서 화면이 갈아끼워질 것이다. 

F12로 우리가 만든 HTML을 열어보면, 해당 시간 부분이 깜빡거리는 것을 알 수 있다. 해당 부분은 화면이 갈아끼워질 때마다, 변경된 부분을 인지하여 보여주는 모습이다.