yangchanghun 님의 상세페이지[7팀 양창훈] Chapter 1-2. 프레임워크 없이 SPA 만들기

과제 체크포인트

배포 링크

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

기본과제

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

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

이벤트 위임

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

심화 과제

Diff 알고리즘 구현

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

과제 셀프회고

제가 회고를 써본적이 없어서 글이 중구난방입니다. 이해해주시면 감사하겠습니다 .,ㅠ_ㅠ

기술적 성장

새로 학습한 개념
  • 가상DOM -> 실제DOM 변환
  • DOM메서드와 노드조작 API
  • weakSet()

가상DOM이 뭐고 실제DOM은 어떤것인지 알게되었고 가상DOM에서 어떤 과정을 통해 DOM으로 변하는지 이해하게된거 같습니다

eventManager.js를 구현하면서 이벤트가 중복으로 등록되어 2번씩 호출되어서 removeEventListner를 붙여봤는데도 중복으로 등록되었습니다. 해결이 되지 않아 일단 AI의 도움을 받아 WeakSet을 사용하라고 답변받아 WeakSet을 이용해 root를 저장하고 기존 root가 있으면 return이 되어 중복 방지를 하였습니다. 궁금증이 생긴게 다른 변수 Set을 이용해도 되지 않나라는 생각이 들어서 ai한테 물어봤는데 WeakSet은 약한참조로 참조되지 않는 메모리가 생기면 삭제를 해줘서 메모리 누수를 방지하여 사용된다고 하여 WeakSet의 사용이유를 간단하게 이해하였습니다. (WeakSet의 사용이유가 위 내용이외에도 더 있을까요?~ )

후에 학메님을 통해 removeEventListner엔 익명함수를 붙이면 삭제가 되지 않는 다는 사실을 알게되었습니다.

코드 품질

학습 효과 분석

추가 학습이 필요한 영역

document.createElement, container.appendChild 와 같은 dom메서드의 대한 개념이 없어 구글링과 gpt를 통해 이해하면서 과제를 진행하였지만 100% 이해가 되지 않는 부분들이 있어 추가적으로 학습해야할 거같다.

가지비 컬렉션,메모리 누수에 대한 개념을 예전에 공부했었지만 다 까먹은듯 하다.

과제 피드백

리뷰 받고 싶은 내용

const eventMap = new Map(); // eventType => Set of { targetEl, handler }
const setupContainers = new WeakSet();

export function setupEventListeners(root) {
  if (setupContainers.has(root)) return;
  console.log("몇번");
  for (const [eventType, listeners] of eventMap.entries()) {
    root.addEventListener(eventType, (e) => {
      for (const { targetEl, handler } of listeners) {
        if (targetEl.contains(e.target)) {
          handler(e);
        }
      }
    });
  }

  setupContainers.add(root);
}

export function addEvent(element, eventType, handler) {
  if (!eventMap.has(eventType)) {
    eventMap.set(eventType, new Set());
  }

  eventMap.get(eventType).add({ targetEl: element, handler });
}

export function removeEvent(element, eventType, handler) {
  const listeners = eventMap.get(eventType);
  if (!listeners) return;

  for (const listener of listeners) {
    if (listener.targetEl === element && listener.handler === handler) {
      listeners.delete(listener);
      break;
    }
  }

  if (listeners.size === 0) {
    eventMap.delete(eventType);
  }
}

에서 제가 root안에 특정 요소에 이벤트를 어떻게 달지 모르겠어서 ai이용해서 해결 좀 했습니다.. e.target이 제가 누른 요소이고 targetEl은 제가 저장한 요소이고 targetEl안에 e.target이 포함되면 함수를 실행시킨다 라고 이해하면 됄까요???? 그리고 handler안에 매개로 e를 또 주는 이유는 버블링방지하라고 주는 e인가요 ?

과제 피드백

이번 과제를 진행할때는 가상dom원리를 이해하고 테스트코드를 통해서 과제를 해결하려고 했는데 도저히 안되겠어서 다른 분들의 코드 및 ai를 활용해서 진행했습니다. 이게 맞는 방법인지 잘 모르겠습니다! ㅠ

그리고

    it("컴포넌트를 정규화한다.", () => {
      const UnorderedList = ({ children, ...props }) => <ul {...props}>{children}</ul>;
      const ListItem = ({ children, className, ...props }) => (
        <li {...props} className={`list-item ${className ?? ""}`}>
          - {children}
        </li>
      );
      const TestComponent = () => (
        <UnorderedList>
          <ListItem id="item-1">Item 1</ListItem>
          <ListItem id="item-2">Item 2</ListItem>
          <ListItem id="item-3" className="last-item">
            Item 3
          </ListItem>
        </UnorderedList>
      );

요런 테스트 크드를 보고 "아 컴포넌트는 function이니까 얘를 다시 vNode.type({ ...vNode.props, children: vNode.children }) 이렇게 해서 재귀를 돌려야 겠다"와 같은 생각을 하려면 어떤 경험이 필요할까요,,, 사실 과제하면서 코딩테스트푸는거 같다 라는 생각을 했습니다.,,,,, 정상일까요 ㅠㅠ

과제 피드백

Q.  handler안에 매개로 e를 또 주는 이유는 버블링방지하라고 주는 e인가요

A. 버블링 방지 뿐아니라 이벤트 객체를 이벤트핸들러에서 활용하라고 전달하는 e입니다. 이벤트 핸들러는 이벤트 객체를 활용할 수 있어야하니까요~

Q. 요런 테스트 크드를 보고 "아 컴포넌트는 function이니까 얘를 다시 vNode.type({ ...vNode.props, children: vNode.children }) 이렇게 해서 재귀를 돌려야 겠다"와 같은 생각을 하려면 어떤 경험이 필요할까요

A. 테스트 코드를 보고는 저도 모를 것 같아요 :) 다만 테스트를 해결하는 코드를 작성하면서 코드의 흐름상 이것은 재귀호출로 만들어야겠다라고 생각이 들 것 같아요. 저는 멘토링때 말씀드렸듯 알고리즘은 빠삭하게 알달 외울필요는 없다고 생각하는데요. 재귀호출을 이용해 문제를 해결하는 능력은 필요하다고 생각해요. 분할 정복을 구현하는 재료로서의 재귀호출을 충분히 이해하려는 목적으로 알고리즘을 조금 학습해보시면 어떨가 싶습니다. 평소 업무에서의 재귀호출은 그렇게 많이 사용되지 않으니까요!