Skip to content

Conversation

@Jihoon-Yoon96
Copy link

@Jihoon-Yoon96 Jihoon-Yoon96 commented Nov 20, 2025

과제 체크포인트

배포 링크

https://jihoon-yoon96.github.io/front_7th_chapter2-1/

기본과제

가상돔을 기반으로 렌더링하기

  • createVNode 함수를 이용하여 vNode를 만든다.
  • normalizeVNode 함수를 이용하여 vNode를 정규화한다.
  • createElement 함수를 이용하여 vNode를 실제 DOM으로 만든다.
  • 결과적으로, JSX를 실제 DOM으로 변환할 수 있도록 만들었다.

이벤트 위임

  • 노드를 생성할 때 이벤트를 직접 등록하는게 아니라 이벤트 위임 방식으로 등록해야 한다
  • 동적으로 추가된 요소에도 이벤트가 정상적으로 작동해야 한다
  • 이벤트 핸들러가 제거되면 더 이상 호출되지 않아야 한다

심화 과제

Diff 알고리즘 구현

  • 초기 렌더링이 올바르게 수행되어야 한다
  • diff 알고리즘을 통해 변경된 부분만 업데이트해야 한다
  • 새로운 요소를 추가하고 불필요한 요소를 제거해야 한다
  • 요소의 속성만 변경되었을 때 요소를 재사용해야 한다
  • 요소의 타입이 변경되었을 때 새로운 요소를 생성해야 한다

과제 셀프회고

아하! 모먼트 (A-ha! Moment)

  1. 가상DOM 적용 과정
  • 내가 import를 따로 한적이 없음에도 실제 렌더링 과정에서 createVNode함수가 어떻게 적용되고 있는지에 대한 의문점이 있었다. 기본으로 제공되는 컴포넌트 소스르 보니 "/** @jsx createVNode */"가 추가돼있었는데, JSX Pragma라고 하는 지시어라는 것을 알게 되었다. 이 지시어가 있으면 바벨이나 TS같은 트랜스파일러 JSX문법을 JS로 변환할 때 지정된 함수 대신 createVNode 함수로 실행시키게 됨을 알았다.
  1. 리렌더링 과정 이해
  • 구현에 AI를 많이 활용하긴 했지만, 어떤 프로세스로 동작되는건지에 대한 이해를 충분히 하고자 했다. 함수별 렌더링 프로세스에서 어떤 역할을 하는지 정리해보았다.

    1. renderElement
    • 컴포넌트 렌더링 과정 총괄
    1. createElement
    • JSX로 작성된 문법을 가상의 노드(Vnode)로 변환
    1. normalizeVNode
    • createVNode함수로 생성된 Vnode를 렌더링하기 쉬운 형태로 변환시킴 (정규화)
    1. createElement
    • 정규화 과정을 거친 Vnode를 실제 DOM 엘리먼트로 변환
    1. eventManager
    • 취상위 DOM요소(root)에 이벤트 리스너 설정
    1. updateElement
    • 이전 Vnode와 신규 Vnode를 비교하여 실제 DOM에 적용시킬 변경점들을 분석 및 적용(Diffing 알고리즘)

기술적 성장

  • 처음 구현 당시에는 basic과 advance를 통과했지만 막상 e2e 테스트를 통과하지 못했다. 서비스 기동시 장상동작하기 때문에 e2e 테스트 코드를 수정해서 강제로 통과시켜 했는데, 멘토링때 관련 질문을해서 "내가 구현한 소스가 잘못됨"을 인정하고 재작업에 들어갔다.
  • updateElement 로직 변경

    • DOM 노드 찾는 방식 변경 : DOM 노드를 찾는 방식이 parentElement와 index를 이용하는 방식에서, 업데이트할 targetNode를 직접 인자로 받는 방식으로 변경
// 변경 전
/**
 * @param {HTMLElement} parentElement - 부모 DOM 요소
 * @param {object} newNode - 새로운 가상 노드
 * @param {object} oldNode - 이전 가상 노드 또는 DOM 요소
 * @param {number} index - 부모 요소 내에서의 현재 노드의 인덱스
 */
export function updateElement(parentElement, newNode, oldNode, index = 0) {
  if (!oldNode) {
    parentElement.appendChild(createElement(newNode));
    return;
  }
const targetNode = parentElement.childNodes[index];

// 변경 후
  /**
   * @param {HTMLElement} targetNode - 변경 대상 노드
   * @param {object} newNode - 새로운 가상 노드
   * @param {object} oldNode - 이전 가상 노드 또는 DOM 요소
   */
export function updateElement(targetNode, newNode, oldNode) {
  // 1️⃣ newNode가 없으면 기존 요소 제거
  if (newNode === null || newNode === undefined || newNode === false) {
    if (targetNode) {
      targetNode.remove();
    }
    return;
  }
  ...
}
  • updaateAttribute 로직 변경 : 모든 속성을 순회하는 대신, 제거할 속성과 추가/변경할 속성을 분리해서 처리
// 변경 전
Object.keys(allProps).forEach((key) => {
  const oldValue = oldP[key];
  const newValue = newP[key];

  // 속성이 완전히 동일하면 아무 작업도 하지 않음
  if (oldValue === newValue) {
    return;
  }
  ...
})

// 변경 후

// 기존 속성 제거
Object.keys(oldProps).forEach((key) => {
  if (!(key in newProps)) {...}
})
// 새 속성 추가/업데이트
Object.entries(newProps).forEach(([key, value]) => {
  if (oldProps[key] !== value) {...}
})

코드 품질

학습 효과 분석

단순히 "리렌더링 시 가상DOM을 활용함! 변경된점만 찾아내어 효율적으로 관리!" 이정도로만 (매우)가볍고 간단하게 알고있던 지식이었는데, 직접 구현해보고 이해하는 과정을 통해서 명확한 지식으로 발전된 것 같다. 최소한 "모르는걸 알게된 단계"로는 진입하지 않았나 생각한다..!

과제 피드백

리뷰 받고 싶은 내용

@joshuayeyo
Copy link

코드 구경 왔습니다👀 지훈님 배포링크 빠져있어용

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants