Skip to content

[3팀 김대현] Chapter 2-2. 나만의 React 만들기 - #43

Open
daehyunk1m wants to merge 9 commits into
hanghae-plus:easyfrom
daehyunk1m:easy
Open

[3팀 김대현] Chapter 2-2. 나만의 React 만들기#43
daehyunk1m wants to merge 9 commits into
hanghae-plus:easyfrom
daehyunk1m:easy

Conversation

@daehyunk1m

@daehyunk1m daehyunk1m commented Nov 17, 2025

Copy link
Copy Markdown

과제 체크포인트

배포 링크

https://daehyunk1m.github.io/front_7th_chapter2-2/

기본과제

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

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

이벤트 위임

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

심화 과제

Diff 알고리즘 구현

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

과제 셀프회고

개인적인 사정으로 이번 과제를 진행하는 주간에 시간을 많이 투입할 수 없었지만
다행히 easy 난이도가 생겨서 과제를 마무리할 수 있었습니다.

이번 과제를 수행하며 AI의 가이드를 따라 최대한 구현하고 리액트가 해결하려고 한 문제를 깊히 경험해보려고 노력했습니다.

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

초기에 updateElement에서 불필요한 자식 노드를 제거할 때 앞에서부터 제거하는 방식으로 구현했습니다.

그런데 "oldChildren이 newChildren보다 많을 때" 케이스가 계속 실패했습니다.
디버깅 결과, 앞에서부터 자식을 제거하면 DOM의 index가 틀어지는 문제를 발견했고 역순으로 제거하여 해결했습니다.

for (let i = minLength; i < oldChildren.length; i++) {
  updateElement(oldChild, null, oldChildren[i], i);
}

// 역순으로 제거
for (let i = oldChildren.length - 1; i >= minLength; i--) {
  updateElement(oldChild, null, oldChildren[i], i);
}

기술적 성장

React의 ReactDOM.render()가 어떻게 효율적으로 DOM을 업데이트하는지 직접 구현하며 이해했습니다.

  • VNode 정규화: 함수형 컴포넌트, primitive 값, 배열 등을 일관된 구조로 변환
  • Diff 알고리즘: Diff 알고리즘으로 효율적인 변경 사항 탐지 (타입 비교 → 속성 비교 → children 재귀)
  • 최소 업데이트 전략: 변경되지 않은 요소는 재사용, 변경된 부분만 패치

또한 과제를 진행하며 적절한 자료구조를 선택하여 로직을 구현할 수 있게 되었습니다.

  • WeakSet/WeakMap: 참조가 사라지면 자동으로 GC 대상이 되는 특성 활용
  • Map vs Object: 비원시형 키 사용 시 Map이 유리함.

updateElement를 구현하며 diff 알고리즘을 명확한 단계로 구조화할 수 있게 되었습니다.

  1. 노드 추가/삭제 처리
  2. 텍스트 노드 비교
  3. 요소 타입 비교
  4. 속성 업데이트
  5. Children 재귀 업데이트

코드 품질

리팩토링이 필요한 부분

1. 이벤트 타입 하드코딩 (eventManager.js:14)
const eventTypes = [
  "click",
  "mouseover",
  "mouseout",
  "focus",
  "blur",
  "keydown",
  "input",
  "change",
  "submit",
  "reset",
];
  • 8개 타입만 지원
  • 새로운 이벤트(drag, scroll 등) 추가 시 코드 수정 필요
  • 이벤트 동적 추출으로 리팩토링 필요함.
2. Style 속성의 카멜케이스 미변환
// `backgroundColor` → `backgroundcolor` (잘못된 변환)
target.style.cssText = Object.entries(value)
  .map(([k, v]) => `${k}: ${v}`)
  .join(";");
  • 개선 방안

    // 카멜케이스 → 케밥케이스 변환
    const toKebabCase = (str) => str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);

학습 효과 분석

좋은 추상화는 복잡도를 감추면서도 필요할 때 제어할 수 있게 합니다.

React가 얼마나 많은 복잡도를 숨기고 있는지 체감했습니다.
쉽게 jsx를 사용하면서 느끼지 못했지만 그 내부에는 이 모든 것이 자동으로 일어납니다.

  • VNode 생성 및 정규화
  • 이전 트리와 diff 비교
  • 최소 DOM 패치 계산
  • 이벤트 위임 관리
  • 속성 타입별 처리

과제 피드백

테스트 케이스가 명확하게 요구사항을 정의하고 있어 과제를 수행해나가면서 로직이 작동하는 프로세스를 쉽게 따라갈 수 있었습니다.

각 단계를 통과할 때마다 성취감을 느낄 수 있었고, 막히는 부분도 명확히 파악할 수 있었습니다.

처음에 렌더링이 되지 않아 흰 화면에서 함수를 작성해 리액트의 기능을 만들어 정상적으로 Virtual DOM으로 렌더링하는 것이 인상적이었습니다.

React 없이 JSX를 직접 처리하고, Virtual DOM을 구현하는 경험이 매우 좋았습니다.

리뷰 받고 싶은 내용

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.

1 participant