Skip to content

[9팀 박상수] Chapter 1-2. 프레임워크 없이 SPA 만들기 (2) - #50

Open
parksangsoo wants to merge 4 commits into
hanghae-plus:mainfrom
parksangsoo:main
Open

[9팀 박상수] Chapter 1-2. 프레임워크 없이 SPA 만들기 (2) #50
parksangsoo wants to merge 4 commits into
hanghae-plus:mainfrom
parksangsoo:main

Conversation

@parksangsoo

@parksangsoo parksangsoo commented Jul 17, 2025

Copy link
Copy Markdown

과제 체크포인트

배포 링크

https://parksangsoo.github.io/front_6th_chapter1-2/

기본과제

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

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

이벤트 위임

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

심화 과제

Diff 알고리즘 구현

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

과제 셀프회고

기술적 성장

가상돔이 실제로 어떻게 생성되고 어떻게 실제돔과 비교해서 바뀐 부분만 렌더링 하는 지 과정에 대해 좀 더 자세히 알게 된 거 같다

코드 품질

테스트 코드가 원하는 값을 받을 수 있도록 구현에만 초점 둬서 코드 품질에 대해서는 어떻게 하면 좋은 품질의 코드가 될 지 고민은 못해본 거 같다

학습 효과 분석

과제 피드백

리뷰 받고 싶은 내용

가상돔이 어떻게 작동하는 지에 대한 과제인 거 같아 뭘 리뷰를 받아야 할 지 모르겠습니다;

@parksangsoo parksangsoo changed the title 박상수 과제제출 [9팀 박상수] Chapter 1-2. 프레임워크 없이 SPA 만들기 (2) Jul 17, 2025

@susmisc14 susmisc14 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상수님! 요번주도 고생하셨습니다. 과제 항상 열심히 하시는 모습에 저도 많은 자극을 받고 있어요! 다음 3주차 과제도 지난 주차들 처럼 화이팅입니다!

Comment thread src/lib/createElement.js
Comment on lines +1 to +3
function flatten(arr) {
return arr.reduce((acc, val) => (Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val)), []);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flatten 함수를 도입해서 중첩된 children 배열까지 유연하게 처리하도록 설계하신 점이 정말 돋보여요! 다만 임포트문 아래에 작성하는게 코드 가독성 면에서 좋을 것 같습니다!

Comment thread src/lib/createElement.js
Comment on lines +16 to +23
if (Array.isArray(vNode)) {
const fragment = document.createDocumentFragment();
flatten(vNode).forEach((child) => {
if (child === null || child === undefined || child === false || child === true) return;
fragment.appendChild(createElement(child));
});
return fragment;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el.append(...elements)로 한번에 DOM에 추가하면 forEach 안에서 appendChild를 반복하는 것보다 브라우저 리페인트 횟수를 줄여 성능상 이점이 있다고 합니다. 이 방식도 함께 고려해보면 좋을 것 같아요!

Comment thread src/lib/createVNode.js
Comment on lines +2 to +12
// 평탄화 함수: 중첩 배열을 1차원 배열로
function flatten(arr) {
return arr.reduce((acc, val) => {
if (Array.isArray(val)) {
acc.push(...flatten(val));
} else if (val !== null && val !== undefined && val !== false) {
acc.push(val);
}
return acc;
}, []);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flatten 함수를 createVNode 함수 밖으로 빼서 헬퍼 함수로 분리하면 createVNode가 호출될 때마다 함수가 새로 생성되는 것을 막을 수 있을 것 같아요.

Comment thread src/lib/eventManager.js
Comment on lines +27 to +45
DELEGATED_EVENTS.forEach((eventType) => {
root.addEventListener(
eventType,
(e) => {
let target = e.target;
while (target && target !== root) {
const events = eventRegistry.get(target);
if (events && events[eventType]) {
for (const handler of events[eventType]) {
handler.call(target, e);
}
if (e.cancelBubble) return;
}
target = target.parentNode;
}
},
eventType === "focus" ? true : false, // focus는 캡처링 필요
);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

focus 이벤트를 처리하기 위해 useCapture 옵션을 사용하신 부분과, handler.call(target, e)로 this 컨텍스트를 맞춰주시는 디테일이 좋은 것 같습니다!

Comment thread src/lib/eventManager.js
Comment on lines +12 to +15
const events = eventRegistry.get(element);
if (!events[eventType]) {
events[eventType] = new Set();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

핸들러를 {[eventType]: Set} 구조로 관리해서 이벤트 탐색의 시간 복잡도를 O(1)로 만드신 점도 돋보입니다!

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