Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9팀 박지수] [Chapter 1-2] 프레임워크 없이 SPA 만들기 #17

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

keyonnaise
Copy link

@keyonnaise keyonnaise commented Dec 25, 2024

과제 체크포인트

기본과제

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

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

이벤트 위임

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

심화 과제

1) Diff 알고리즘 구현

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

2) 포스트 추가/좋아요 기능 구현

  • 비사용자는 포스트 작성 폼이 보이지 않는다
  • 비사용자는 포스트에 좋아요를 클릭할 경우, 경고 메세지가 발생한다.
  • 사용자는 포스트 작성 폼이 보인다.
  • 사용자는 포스트를 추가할 수 있다.
  • 사용자는 포스트에 좋아요를 클릭할 경우, 좋아요가 토글된다.

과제 셀프회고

이번 과제를 하면서 가장 기억에 남는 요소는 이벤트 처리와 단위 테스트에 대한 인식 변화이다.

이벤트 처리 같은 경우는 내 실수로 인해 코드에 문제가 발생했는데, 그 덕분에 존재만 알던 new WeakMap()을 실사용 해보는 등 좋은 경험을 해볼 수 있었다. 이게 새옹지마일까?

단위 테스트에 대해서는 1주차 때 너무 안 좋은 기억(한참을 찾았더니 단순한 classname의 불일치 등의 오류)이 많아서 치가 떨렸지만 그래도 이번 과제에서는 '최대한 많이 활용해 보자' 라고 생각하며 단위 테스트를 시작부터 끝까지 사용해 봤다.

그런데 왠걸? 단위 테스트를 적극적으로 사용하며 과제를 진행했더니 과제를 생각보다 수월하게 진행 할 수 있었다. 후에 멘토링 시간에 이 부분에 대해 이야기를 드렸더니, "테스트 코드는 설계도라고 생각해도 좋고, '스펙' 이라고 생각해도 좋습니다."라고 해 주셔서 앞으로 과제를 진행할 때는 많이 활용해 보려한다.

하지만 내가 IDE로 Cursor를 사용하고 있는데 멘토링 시간 때 말씀해주신 Vitest가 사용이 안 된다. 왜 그런걸까??

기술적 성장

기술적 성장으로는 생각지도 못했던 new Weakmap()의 사용과 이벤트 위임에 있겠다.
이번 과제에서 기술적으로는 저 두 가지가 가장 기억에 남는 듯.

코드 품질

모르겠다. 항상 그 당시에는 최선이라고 생각하는데 뒤돌면 뭔가 불만족스럽다. 《칼의 노래》 김훈 작가도 책의 첫 문장인 "버려진 섬마다 꽃이 피었다."에서 "꽃이 피었다"와 "꽃은 피었다" 사이에서 엄청 고민 했다고 하던데 비슷한 걸까? 특히 이번에는 변수명/함수명으로 한 번 혼나서 다음 과제부터는 신경 좀 쓰려고 한다.

학습 효과 분석

기술적 성장 파트와 내용이 겹치는 것 같다. 하지만 이벤트 위임 같은 경우 실무에 적용할 일이 많지 않을 것 같은데 그래도 element를 컨트롤하는 부분에 WeakMap은 종종 쓸 수 있지 않을까?

과제 피드백

eventUtils.js 파일의 필요성과 createVNode()에서 바로 nomalize를 하면 안 될까? 라는 의문이 있었는데 QnA에서 같은 질문을 한 사람이 있어서 궁금증이 해결됐다.
과제에서 좋았던 점은 updateElement() 부분이었는데 자바스크립트에서 하려니 얘가 무슨 타입이고 어떻게 변할까? 상상하면서 하니까 정말 퍼즐 맞추는 기분이었다. 재밌었음.

리뷰 받고 싶은 내용

많은 부분이 QnA시간과 멘토링 시간에서 해결된 것 같다. 솔직히 안 되는 건 알지만 리뷰라기 보단 전반적으로 내가 작성한 코드를 리터칭? 받아보고 싶은 마음이 있다. 지금 작성된 코드 어느 부분에서 디테일을 더 챙길 수 있을지가 궁금하다.
이게 리뷰일까?

위 내용을 제하면 removeEvent() 부분이 맘에 남는다. 멘토링 때 설명해주신 내용으로 그 당시 궁금했던 점들은 해결 됐는데, 이후 생긴 궁금증으로는 다음이 있다.
이전 코드에서는 모든 이벤트를 root에 직접 등록하고 'removeEvent()'에서는 삭제하는 방식이었는데

export function setupEventListeners(_$root) {
  $root = _$root;

  events.forEach(({ eventType, handler }) => {
    $root.addEventListener(eventType, handler);
  });
}

export function addEvent(element, eventType, handler) {
  const isIncluded = events.some((event) => {
    return isSameEvent(event, { element, eventType, handler });
  });

  if (isIncluded) return;

  events.push({ element, eventType, handler });
}

// ...생략

export function removeEvent(element, eventType, handler) {
  const found = events.find((event) => {
    return isSameEvent(event, { element, eventType, handler });
  });

  if (!found) return;

  event = events.filter((event) => {
    return !isSameEvent(event, { element, eventType, handler });
  });

  $root.removeEventListener(found.eventType, found.handler);
}

이렇게 처리 될 경우 성능적으로 문제가 발생할 수 있거나 내가 모르는 오류가 발생할 수도 있을 지(예를 들어 이벤트가 알 수 없는 이유로 안 지워질 수도 있다거나 뭐 이런거?)와 멘토링 때 질의 했던 것과 비슷한데 과제 코드에 tailwind를 사용하셨는데 실제 코치님이 사용하시는 스타일 라이브러리도 궁금하다. 본인은 emotion, vanilla-extract를 주력으로 사용하고 회사에서는 styled-component를 사용하고 있는데 이 라이브러리들이 영 미래가 없어 보이면 다른 라이브러리로 옮겨보려고 한다. stitches 라이브러리처럼 망해버리면 너무 슬플 것 같다

Comment on lines +65 to +87
Object.entries(newProps).forEach(([key, value]) => {
// 스타일 속성 처리
if (key === "style") {
target.style = value;
return;
}

// 클래스 속성 처리
if (key === "className") {
target.setAttribute("class", value);
return;
}

// 이벤트 핸들러 처리
if (key.startsWith("on") && typeof value === "function") {
addEvent(target, key.slice(2).toLowerCase(), value);
return;
}

// 나머지 속성 처리
target.setAttribute(key, value);
});
}

Choose a reason for hiding this comment

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

직관적으로 잘 정리된거 같아요..! 가독성이 좋네요

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