[React] Virtual DOM의 동작 방식

jiny·2025년 2월 7일

기술 면접

목록 보기
55/78

🗣️ 리액트에서 사용되는 Virtual DOM의 동작 방식을 설명해주세요.

  • 의도: 지원자가 React의 Virtual DOM의 개념과 그 동작 방식을 이해하고 있는지 평가

    • Virtual DOM의 정의와 필요성을 설명한다.
    • Virtual DOM이 실제 DOM과 어떻게 다른지 설명한다.
    • Virtual DOM의 업데이트 과정을 언급한다.
  • 나의 답안

    리액트에서 사용하는 Virtual DOM은 말 그대로 실제 DOM을 메모리상에 가볍게 만들어 둔 가상의 DOM 트리입니다.
    브라우저의 실제 DOM은 조작 비용이 크기 때문에, 상태가 자주 변하는 SPA에서 직접 조작하면 성능이 크게 떨어질 수 있습니다.
    이를 해결하기 위해 리액트는 직접 DOM을 건드리는 대신 Virtual DOM을 이용해 변경 사항을 계산하고 최소한으로만 실제 DOM에 반영하는 방식을 사용합니다.

    state나 props가 변경되면 리액트는 새로운 Virtual DOM을 다시 생성합니다.
    그리고 이전 Virtual DOM과 새로운 Virtual DOM을 비교해서 어떤 부분이 바뀌었는지 계산합니다.
    바뀐 부분만 실제 DOM에 패치하여 브라우저에 반영합니다.

    이렇게 하면 전체 DOM을 다시 그리는 대신 필요한 부분만 업데이트하기 때문에 성능이 훨씬 효율적이고, 렌더링 최적화에도 유리합니다.
    즉, Virtual DOM은 리액트가 변경 최소화 전략으로 UI를 빠르게 업데이트할 수 있도록 돕는 핵심 메커니즘이라고 할 수 있습니다.

  • 주어진 답안 (모범 답안)

    Virtual DOM은 실제 DOM의 가벼운 복사본으로, React에서 상태 변화에 따른 UI 업데이트를 효율적으로 처리하기 위해 사용됩니다.

    Virtual DOM은 메모리에서 작동하며, 변경 사항을 실제 DOM에 반영하기 전에 비교(diffing)하고 최소한의 변경만 실제 DOM에 적용(patching)합니다.
    이를 통해 성능을 최적화하고 빠른 렌더링을 제공합니다.


📝 개념 정리

Virtual DOM(V-DOM)은 React와 같은 라이브러리에서 사용되는 개념으로, UI 업데이트를 효율적으로 처리하기 위해 실제 DOM 대신 메모리에 가상의 DOM을 만들어 변경 사항을 최소화하는 방식이다. 이를 통해 브라우저 성능을 최적화하고 렌더링 비용을 줄일 수 있다.

🌟 Virtual DOM의 개념

Virtual DOM은 실제 DOM의 가벼운 사본(객체 형태)이다. 이 사본은 JavaScript 객체로 표현되며, UI의 현재 상태를 나타낸다.
React에서는 UI를 변경할 때 직접 DOM을 조작하지 않고, Virtual DOM을 수정한 후 이를 실제 DOM과 비교하여 변경이 필요한 부분만 반영한다.


🌟 Virtual DOM의 동작 과정

Virtual DOM은 일반적으로 다음 3단계로 동작한다.

  1. Render(렌더링) - Virtual DOM 생성
    컴포넌트가 렌더링될 때, React는 render() 메서드를 실행하여 Virtual DOM을 생성한다.
    이 Virtual DOM은 메모리에 존재하며, 실제 DOM과 연결되지 않는다.

    • 예제: JSX 코드가 React.createElement()를 통해 Virtual DOM 객체로 변환됨
      const element = <h1>Hello, world!</h1>;
      console.log(element);
      // 결과 (실제 React 내부 변환 구조)
      {
        type: "h1",
        props: { children: "Hello, world!" }
      }
  1. Diffing(비교) - Virtual DOM 간 변경 사항 확인 (Reconciliation 과정)
    Virtual DOM을 갱신해야 할 상황이 오면, React는 새롭게 생성된 Virtual DOM과 기존 Virtual DOM을 비교하여 달라진 부분을 찾는다.
    이 과정은 Diffing 알고리즘을 사용하여 수행된다.

    • React의 Diffing 알고리즘 최적화 방식

      1. 동일한 타입의 요소 비교
        • 같은 태그(divdiv)이면 속성만 비교하여 변경된 부분만 업데이트
        • 다른 태그(divp)이면 기존 요소를 삭제하고 새로운 요소로 교체
      2. 자식 요소 비교
        • key 값을 사용하여 리스트 업데이트를 최적화
        • 새롭게 추가/삭제된 요소만 업데이트
    • Diffing 예제

      const element1 = <h1>Hello, world!</h1>;
      const element2 = <h1>Hello, React!</h1>;

      1) h1 태그는 그대로 유지된다.
      2) Hello, world!Hello, React!로 텍스트가 변경된다.
      React는 전체 h1을 리렌더링하는 것이 아니라, 텍스트 노드만 변경하는 방식으로 최소한의 업데이트를 수행한다.

  1. Patching(업데이트) - 실제 DOM 반영
    변경 사항이 확인되면, React는 Batching(일괄 처리) 기법을 이용하여 필요한 부분만 실제 DOM에 반영한다.
    React는 ReactDOM.render() 또는 useState(), useReducer() 등을 통해 상태가 변경될 때 Virtual DOM을 새롭게 만들고, 이를 비교하여 실제 DOM을 수정한다.

    실제 DOM 업데이트는 React의 Batch Update(일괄 업데이트) 기법을 사용하여 성능을 최적화한다.

    • 여러 개의 변경 사항을 한 번에 묶어서 적용
    • 불필요한 렌더링 방지

🌟 Virtual DOM의 장점

  1. 성능 최적화
    • 브라우저의 Reflow(레이아웃을 다시 계산), Repaint를 줄일 수 있다.
    • 변경 사항이 적은 경우 전체 DOM을 다시 그리지 않고 필요한 부분만 변경할 수 있다.
    • Batch Update 기법을 활용하여 최소한의 업데이트를 실행할 수 있다.
  1. 코드의 직관성 증가
    • 실제 DOM을 직접 조작하지 않고, 선언형 코드(JSX)를 사용하여 UI를 표현할 수 있다.
    • React.createElement()를 통해 UI를 Virtual DOM으로 쉽게 변환이 가능하다.
  1. 다양한 렌더링 기법 적용 가능
    • React의 ReactDOM.createRoot()useTransition()을 활용하여 성능을 조절할 수 있다.
    • SSR(Server-Side Rendering)과 Hydration을 통해 SEO(검색 엔진 최적화)를 개선할 수 있다.

🌟 Virtual DOM vs. Real DOM

항목Virtual DOMReal DOM
렌더링 속도빠름 (최소한의 변경)느림 (전체 업데이트)
변경 감지 방식Diffing 알고리즘 활용직접 조작
업데이트 방식변경된 부분만 적용모든 요소 업데이트
브라우저 성능최적화됨성능 저하 가능

🌟 Virtual DOM의 한계

  1. Diffing 알고리즘 비용
    • Virtual DOM을 비교하는 과정에서도 연산 비용이 발생한다.
    • React는 이 연산을 줄이기 위해 key 값을 사용하여 리스트 변경을 최적화해야 한다.
  1. 복잡한 애니메이션 성능 문제

    • CSS 애니메이션과 비교하면 Virtual DOM을 통한 애니메이션 구현이 느릴 수 있다.

    • requestAnimationFrame()을 활용하여 성능을 높이는 방식이 필요하다.

      requestAnimationFrame()이란?

      • requestAnimationFrame()브라우저에게 애니메이션을 수행할 것을 요청하는 함수로, 브라우저의 화면 새로고침 주기(Frame Rate, FPS)에 맞춰 최적화된 렌더링을 수행하도록 도와준다.
      • 즉, 자바스크립트의 애니메이션을 부드럽게 실행하면서, 불필요한 Reflow/Repaint를 줄이는 최적화 기법이다.

      기존의 setTimeout() vs. requestAnimationFrame() 차이

      • 과거에는 애니메이션을 만들 때 setTimeout() 또는 setInterval()을 사용했다.
      • 하지만 setTimeout()을 사용하면 프레임이 일정하지 않아 애니메이션이 끊기는 문제가 발생한다.
      function moveBox() {
        box.style.left = box.offsetLeft + 5 + "px";
        setTimeout(moveBox, 16); // 16ms마다 실행 (약 60FPS)
      }
      moveBox();
      • 문제점
        💖 setTimeout()은 브라우저가 렌더링하는 시점을 고려하지 않는다.
        💖 브라우저가 화면을 그리는 주기(보통 60FPS, 즉 16.67ms)와 동기화되지 않아 프레임이 밀리거나 끊길 수 있다.
      • 해결 방법: requestAnimationFrame()
      function moveBox() {
        box.style.left = box.offsetLeft + 5 + "px";
        requestAnimationFrame(moveBox); // 브라우저의 프레임 속도에 맞춰 실행
      }
      moveBox();
      • 장점
        💖 브라우저의 리프레시 속도(보통 60FPS)에 맞춰 실행된다. → 부드러운 애니메이션
        💖 백그라운드 탭에서 자동으로 중지된다. → CPU/GPU 자원이 절약된다.(성능 최적화)

      requestAnimationFrame()의 동작 방식

      1. 브라우저가 화면을 새로고침할 때(refresh rate, 보통 1초에 60번)마다 콜백 함수를 실행할 기회를 준다.
      2. 브라우저가 최적의 타이밍에 애니메이션을 실행하도록 보장한다.
      3. 백그라운드에서 실행 중이면 자동으로 멈춰 자원 낭비를 방지한다.
      • 기본 사용법
      function animate() {
        console.log("애니메이션 실행!");
        requestAnimationFrame(animate); // 다음 프레임에서 실행
      }
      requestAnimationFrame(animate);
  1. 불필요한 렌더링 문제
    • 상태가 변경될 때마다 Virtual DOM이 새롭게 생성된다.
    • useMemo(), useCallback(), React.memo() 등을 사용하여 불필요한 렌더링을 방지해야 한다.

🌟 React에서 Virtual DOM 최적화 방법

  1. 불필요한 렌더링 방지
    • React.memo()를 사용한다.
    • useMemo()useCallback()을 사용하여 컴포넌트 리렌더링을 방지한다.
  1. Key 값 활용
    • 리스트 렌더링 시 key 값을 올바르게 설정하여 Diffing을 최적화한다.
  1. Concurrent Mode 활용
    • useTransition()을 사용하여 렌더링 우선순위를 조절한다.

🌟 결론

Virtual DOM은 UI 변경을 효율적으로 처리하기 위해 메모리에서 변경 사항을 감지하고, 최소한의 실제 DOM 조작을 수행하는 방식이다.
이를 통해 React는 높은 성능을 유지하면서도 선언형 프로그래밍 스타일을 유지할 수 있다.
하지만 Diffing 과정에서 연산 비용이 발생할 수 있으므로 React.memo(), useMemo(), useCallback() 등을 활용하여 최적화하는 것이 중요하다.

0개의 댓글