서론
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 과 비교하여 성능이 비슷하거나 오히려 떨어질 수 있으며,
문서화와 학습 리소스가 부족하다는 단점이 있기 때문에
이 부분을 고려하여 프로젝트에 적용하는 것을 고민하여야 겠습니다.
참고한 공식문서
'FE > React' 카테고리의 다른 글
[React] 리스트 동적 처리(ft. map 메소드) / on- prop / 조건 처리 (0) | 2024.01.17 |
---|