이전 설계도와 새 설계도의 비교

352025년 09월 19일4

가상 DOM(Virtual DOM)이라는 개념이 팀에 공유되자, 조던 워크는 곧바로 다음 단계로 나아갔다. 바로 두 장의 설계도, 즉 이전 버추얼 DOM 트리와 새로운 버추얼 DOM 트리를 비교하는 알고리즘의 프로토타입을 만드는 것이었다.

그는 이 과정을 ‘Diffing’이라고 불렀다. 두 파일의 차이점을 보여주는 유닉스(Unix)의 diff 명령어에서 따온 이름이었다.

조던은 간단한 시나리오를 설정하고, 알고리즘이 어떻게 동작해야 하는지를 코드로 구체화하기 시작했다.

시나리오: ‘좋아요’ 버튼 클릭

  • 이전 상태(Old State): { isLiked: false, count: 10 }
  • 새로운 상태(New State): { isLiked: true, count: 11 }
  1. 렌더링 및 두 개의 트리 생성

먼저, 두 상태에 대한 각각의 버추얼 DOM 트리를 생성한다.

  • 이전 트리(Old VDOM):
    {
      tagName: 'button',
      properties: { className: '' },
      children: ['좋아요 (10)']
    }
    
  • 새로운 트리(New VDOM):
    {
      tagName: 'button',
      properties: { className: 'liked' },
      children: ['좋아요 취소 (11)']
    }
    
  1. Diffing 알고리즘 실행

이제 조던이 설계한 diff 함수가 두 개의 트리(객체)를 인자로 받아 비교를 시작한다. 알고리즘은 트리의 최상단 노드부터 재귀적으로 탐색해 내려간다.

비교 1단계: 루트 노드 비교

  • Old VDOMtagName은 ‘button’인가? → Yes
  • New VDOMtagName은 ‘button’인가? → Yes
  • 두 노드의 타입이 같다(buttonbutton). 따라서 이 노드는 파괴하고 새로 만들 필요 없이, 속성과 자식만 비교하면 된다.

비교 2단계: 속성(Properties) 비교

  • 알고리즘은 두 노드의 properties 객체를 비교한다.
  • Old VDOM.properties.className'' (빈 문자열)이다.
  • New VDOM.properties.className'liked'이다.
  • 차이점 발견! → 변경 목록에 추가: [UPDATE_CLASSNAME, 'liked']

비교 3단계: 자식(Children) 비교

  • 알고리즘은 두 노드의 children 배열을 비교한다.
  • Old VDOM.children[0]'좋아요 (10)' 이라는 텍스트 노드다.
  • New VDOM.children[0]'좋아요 취소 (11)' 이라는 텍스트 노드다.
  • 차이점 발견! → 변경 목록에 추가: [UPDATE_TEXT, '좋아요 취소 (11)']
  1. 최종 변경 목록 생성

diff 함수의 실행이 끝나면, 다음과 같은 구체적인 ‘작업 지시서’가 반환된다.

[
  { type: 'UPDATE_PROPERTIES', targetNode: [실제 버튼 DOM 노드], payload: { className: 'liked' } },
  { type: 'UPDATE_CHILDREN', targetNode: [실제 버튼 DOM 노드], payload: ['좋아요 취소 (11)'] }
]

이 목록에는 더 이상 추상적인 버추얼 DOM이 아니라, 실제 DOM 노드를 어떻게 바꿔야 하는지에 대한 명확한 지침이 담겨있다.

  1. 일괄 반영(Batch Update)

마지막으로, 라이브러리의 렌더러는 이 작업 지시서 목록을 받아 실제 DOM에 대한 수정을 딱 한 번만, 일괄적으로 실행한다.

// 실제 DOM 조작
realButtonNode.className = 'liked';
realButtonNode.textContent = '좋아요 취소 (11)';

조던은 이 프로토타입 코드를 팀원들에게 보여주었다. 복잡한 이론이 아닌, 실제로 동작하는 코드 앞에서 모두가 감탄했다. diff 함수는 이전 설계도와 새 설계도를 비교하여, 마치 숙련된 외과 의사처럼 정확하게 바뀐 부분만 도려내고 있었다.

물론, 이것은 단일 노드에 대한 가장 단순한 예시였다. 자식 노드가 여러 개일 때, 목록의 순서가 바뀔 때, 새로운 노드가 추가되거나 기존 노드가 삭제될 때 등 훨씬 더 복잡한 시나리오들을 처리해야 하는 큰 산이 남아 있었다.

하지만 조던과 그의 팀은 마침내, 불가능해 보였던 성능의 벽을 넘을 수 있는 구체적인 무기를 손에 넣은 것이다.