본문 바로가기

Deep Dive

[React] JSX Rendering & Virtual DOM의 동작 원리

 

 

오늘 React의 핵심 동작 원리에 대해 공부했다.

특히 JSX가 어떻게 렌더링되는지, 메모리는 어떻게 관리되는지, 그리고 Virtual DOM은 어떤 역할을 하는지 자세히 살펴보았다.

 

 


 

 

1. JSX의 렌더링 과정

- React 컴포넌트의 반환값(JSX)은 Virtual DOM의 render 함수에 전달된다. 그 다음에 babel 혹은 rollup 등의 컴파일러가 JS로 코드를 변환하는 과정을 거쳐, 최종 반환값은 React Element가 된다.

- 좀 더 정확히 말하면, JSX는 React.createElement를 통해 React Element 객체로 변환되고, 이 객체는 Virtual DOM의 구성 요소가 되는 것이다.

- 변환 순서와 예시 코드는 아래와 같다.

JSX -> JS -> React Element
// JSX
function App() {
  return <div>Hello</div>;
}

// JS : 컴파일러 변환 후
function App() {
  return React.createElement('div', null, 'Hello');
}

// React Element
{
  type: 'div',
  props: { children: 'Hello' },
  key: null,
  ref: null
}

 

 

2. 메모리 구조 (function object vs heap)

- 컴포넌트 자체는 function이기 때문에 function object에 등록된다.

- 그러나 컴포넌트의 반환 값은 일반 객체(Object)이다. 해당 객체는 UI의 가상 표현(Virtual DOM Node)을 담고 있다. 해당 반환 값은 heap 영역에 저장되고, 객체이기 때문에 컴포넌트처럼 function object로 등록되지 않는다.

- 이후 리액트의 내부 알고리즘은 heap 영역을 참조하여 실제 DOM으로 변환(업데이트) 된다.

 

cf. 일반적인 경우에, 함수는 생성 시 function object에 등록되고, 객체는 heap 영역에 등록된다. 

 

cf. React 17에서는 ReactDOM.render()가 해당 과정을 수행했으나, React 18 부터는 createRoot()가 해당 과정을 수행하는 것을 권장한다.

 

 

 

3. Virtual DOM의 diff 알고리즘과 DOM 업데이트 최적화

- Virtual DOM의 역할은 컴포넌트의 반환값을 받아서 이전 Virtual DOM과 비교하여 diff를 뜬 다음, 실제 필요한 DOM 업데이트만 수행한다.

cf. 이는 이전 버전과 현재 버전의 파일의 diff를 떠서 변경 사항만 반영하는 git의 작동 방식과 유사하다.

 

- 리액트에서 Virtual DOM이 있기에, 효율적이고 신속한 작업이 가능하게 되는 것이다.

- 리액트를 깊게 공부한다면, 특히 Virtual DOM에 대해 잘 알아야 할 것 같다는 생각을 했다.

 

 

 

4. 컴포넌트의 메모리 관리

- 컴포넌트는 생성(정의) 시 Function Object 영역에 최초 한 번 등록되고, 메모리 주소를 할당한다. 메모리 주소를 기억하고 있기 때문에 재사용 될 때마다 동일한 메모리 주소를 참조하여 메모리 효율성을 향상 시킬 뿐만 아니라, 성능을 최적화시키고, 일관된 동작을 보장하는 장점이 있다.

 

 

Q. 여기서 생기는 궁금증, 그러면 컴포넌트는 싱글톤인가?

- 메모리에 함수 정의를 한 번만 저장하는 것은 싱글톤과 비슷하지만, 싱글톤의 특징은 단 하나의 인스턴스를 공유한다는 것이다.

하지만 리액트의 인스턴스는 독립적인 state와 props를 가지며, 렌더링될 때마다 새로운 클로저를 생성한다. (개별 상태 관리 가능)

그러므로 리액트의 컴포넌트는 메모리 효율성 측면에서는 싱글톤의 일부 특성을 가지지만, 완벽한 싱글톤이라고 볼 수는 없다.

 

 

 


 

 

 

혹시 제가 잘못 이해한 부분이 있거나, 추가로 알면 좋은 정보가 있다면 댓글로 남겨주세요!

React를 더 깊이 이해하는 데 도움이 될 것 같습니다. 😊