✨JSY
article thumbnail
서론

 

React 강의를 듣던 중 성능을 최적화할 수 있는 프레임워크인 MillionJS에 대해 알게 되었고,
어떠한 메커니즘으로 성능 개선이 이루어지는 지 궁금해 MillionJS 공식문서를 보고 나서 알게 된 점을 적어보려고 합니다.

 

우선 React의 virtual DOM 방식을 알아보고,
MillionJS이 동작하는 방식이 virtual DOM과 어떠한 차이점이 있는 지 보겠습니다.


 

리액트의 virtual DOM 동작 방식

 

virtual DOM은 컴포넌트가 리렌더될 때 기존의 값과 현재의 값을 비교하고,
값이 바뀐 부분만을 찾아 리렌더하기 때문에,
모든 코드가 재평가의 대상이 되는 실제 DOM에 비해 효율적이라고 볼 수 있습니다.

 

개발자 도구에서 보면 값이 변경된 부분만 깜빡이며 바뀌고 있습니다.

 

예시 코드를 통해 리렌더 과정을 보겠습니다.

import { useState } from "react";

function Counter() {
  const [counter, setCounter] = useState(0);

  function handleClick() {
    setCounter((prevCount) => prevCount + 1);
  }

  return (
    <div>
      <h2>숫자를 증가시켜 보세요</h2>
      <ol>
        <li>시작: 0</li>
        <li>현재: {counter}</li>
      </ol>
      <button onClick={handleClick}>증가</button>
    </div>
  );
}

 

버튼을 클릭하면 클릭 이벤트에 의해 컴포넌트가 리렌더됩니다.

 

(가상 DOM 내부 과정)

1. div, h2, ol(li 각각도 포함), button 까지 모든 요소를 기존의 값과 비교합니다.

2. 그 중 두 번째 li 요소는 기존과 달라졌으므로 리렌더합니다.

 

diff를 체크하는 과정은 총 6번이며, 기존과 값의 차이가 없는 나머지 요소는 리렌더하지 않습니다.

 

이 과정은 리렌더할 때마다 모든 요소를 diff checking 해야 하므로,
소요 시간은 컴포넌트 내부의 크기와 비례하여 증가합니다.


 

Block Virtual DOM (MillionJS 가 렌더하는 방식)

 

MillionJS는 Block Virual DOM이라는 새로운 비교 방식을 사용합니다.

정적 분석(Static Analysis)과 dirty checking(바뀔 부분만 체크) 이 2가지 과정을 거쳐 진행됩니다.

 

정적 분석

 

1. MillionJS의 컴파일러에 의해 모든 요소를 매핑합니다.

2. 동적 요소의 경우 ? placeholder를 부여합니다.

3. ? placeholder를 가진 요소는 Edit Map 에서 값이 변경될 때 바뀌도록 합니다.

import { useState } from "react";

function Counter() {
  const [counter, setCounter] = useState(0);

  function handleClick(how) {
    if (how === "증가시켜") {
      setCounter((prevCount) => prevCount + 1);
    } else if (how === "감소시켜") {
      setCounter((prevCount) => prevCount - 1);
    }
    
  }

  return (
    <div>
      <h2>숫자를 증가시켜 보세요</h2>
      <ol>
        <li>시작: 0</li>
        <li>현재: {counter}</li>
      </ol>
      <p>{counter === 0 ? 최초값과 현재값 일치 : 최초값과 현재값 불일치}</p>
      <button onClick={() => handleClick("증가시켜")}>증가</button>
      <button onClick={() => handleClick("감소시켜")}>감소</button>
    </div>
  );
}

 

살짝 변경된 좀 전의 예시 코드를 보면

정적 분석에서 li의 두번째 요소와 p 요소가 동적 요소이므로 Edit Map으로 그룹핑됩니다.

 

바뀔 부분만 체크

동적 요소를 이미 Edit Mapping 했기 때문에, 리렌더 시 두 개의 요소에 대해서만 변경되었는 지 비교하게 됩니다.

 

 

결론

 

Block Virtual DOM은 리렌더할 때, 동적 요소만 diff check를 하기 때문에 기존 가상 DOM보다 훨씬 렌더 속도가 빨라집니다.

MillionJS의 장점을 요약하자면,
컴포넌트 트리가 거대해 질 수록, 컴포넌트 내부에 정적 요소가 많아질 수록 더 좋은 퍼포먼스를 보여줍니다.

또한 3KB 내외의 가벼운 사이즈로, 진행한 프로젝트에 추가하기에 부담이 적습니다.

 

다만,

대부분의 소규모 프로젝트에서는 MillionJS의 도움 없이도 가상 DOM 만으로도 충분한 성능을 낼 수 있습니다.

또한, 정적 요소에 비해 동적 요소가 압도적으로 많은 경우 가상 DOM 과 비교하여 성능이 비슷하거나 오히려 떨어질 수 있으며,

문서화와 학습 리소스가 부족하다는 단점이 있기 때문에

이 부분을 고려하여 프로젝트에 적용하는 것을 고민하여야 겠습니다.

 

참고한 공식문서

https://million.dev/blog/virtual-dom

profile

✨JSY

@JUNSANG YOO

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!