Content is user-generated and unverified.

Virtual DOM 상세 수도코드 (테스트 기반)

1. createVNode.js

function createVNode(type, props, ...children):
  1. children 배열을 flat()으로 평탄화
  2. null, undefined, false 값들을 필터링 제거
  3. true는 빈 문자열로 변환
  4. 나머지(문자열, 숫자, 객체)는 그대로 유지
  5. { type, props: props || null, children: 정제된children } 반환
  
별칭 함수 h = createVNode

2. normalizeVNode.js

function normalizeVNode(vnode):
  IF vnode가 null/undefined/boolean:
    RETURN 빈 문자열 ''
  
  IF vnode가 string/number:
    RETURN String(vnode)
  
  IF vnode가 배열:
    각 요소를 normalizeVNode로 재귀 처리
    빈 문자열 필터링 후 반환
  
  IF vnode.type이 함수(컴포넌트):
    함수 실행: component(vnode.props)
    결과를 normalizeVNode로 재귀 처리하여 반환
  
  ELSE (일반 VNode):
    children만 재귀적으로 정규화하여 새 객체 반환

3. createElement.js

function createElement(vnode):
  IF vnode가 null/undefined/boolean:
    RETURN document.createTextNode('')
  
  IF vnode가 string/number:
    RETURN document.createTextNode(String(vnode))
  
  IF vnode가 배열:
    DocumentFragment 생성
    각 요소를 createElement로 재귀 변환하여 추가
    RETURN fragment
  
  IF vnode.type이 함수:
    ERROR 발생 (정규화 후 사용하라고 안내)
  
  ELSE (HTML 태그):
    element = document.createElement(vnode.type)
    updateAttributes(element, vnode.props) 호출
    각 child를 createElement로 재귀 변환하여 appendChild
    RETURN element

function updateAttributes(element, props):
  props의 각 [key, value]에 대해:
    IF key가 'on'으로 시작하고 value가 함수:
      eventType = key에서 'on' 제거 후 소문자화
      addEvent(element, eventType, value) 호출
    
    ELSE IF key가 'className':
      IF value 존재: element.setAttribute('class', value)
      ELSE: element.removeAttribute('class')
    
    ELSE IF key가 'style'이고 value가 객체:
      Object.assign(element.style, value)
    
    ELSE IF key가 boolean 속성들 (checked, disabled, selected):
      IF value가 true: element[key] = true, setAttribute도 설정
      ELSE: element[key] = false, removeAttribute 호출
    
    ELSE IF 일반 속성:
      IF value 존재: element.setAttribute(key, value)

4. updateElement.js (가장 복잡한 Diff 알고리즘)

function updateElement(container, newVNode, oldVNode, index = 0):
  
  // Case 1: 삭제 (oldVNode만 있음)
  IF !newVNode && oldVNode:
    container에서 index번째 자식 제거
    RETURN
  
  // Case 2: 추가 (newVNode만 있음)  
  IF newVNode && !oldVNode:
    createElement(newVNode)로 새 요소 생성
    container에 appendChild
    RETURN
  
  // Case 3: 둘 다 텍스트
  IF 둘 다 문자열/숫자:
    IF 내용이 다름:
      container.childNodes[index].textContent = newVNode
    RETURN
  
  // Case 4: 타입이 다름 (div → span)
  IF newVNode.type !== oldVNode.type:
    새 요소 = createElement(newVNode)
    container.replaceChild(새요소, container.childNodes[index])
    RETURN
  
  // Case 5: 같은 타입 → 속성과 children 업데이트
  target
Content is user-generated and unverified.
    Virtual DOM 핵심 함수들 수도코드 | Claude