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

[12팀 배성규] [Chapter 1-2] 프레임워크 없이 SPA 만들기 #34

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

Conversation

pangkyu
Copy link

@pangkyu pangkyu commented Dec 26, 2024

과제 체크포인트

기본과제

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

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

이벤트 위임

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

심화 과제

1) Diff 알고리즘 구현

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

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

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

과제 셀프회고

가상 돔에 대해 성능 개선을 위한 도구로 막연히 알고 있었지만, 이번 발제를 통해 가상 돔이 항상 성능 향상을 보장하지는 않는다는 점을 배울 수 있었습니다.
과제를 통해 vNode 생성, 정규화, 이벤트 매니저 처리 등을 직접 구현하면서 렌더링 과정에 대한 내용을 학습할 수 있었습니다.

비록 테스트 케이스와 구현을 완벽히 완료하지 못해 이번 과제를 통과하지는 못했지만, 발제 내용과 스스로의 학습 과정, 그리고 다른 팀원의 코드를 분석하며 많은 것을 배울 수 있었습니다.
이러한 경험을 통해 가상 돔을 활용한 SPA 구현의 핵심 원리와 그 한계점에 대해 한층 더 이해하게 되었습니다.

기술적 성장

  • 가상 돔에 대한 전반적인 이해 향상
    • createVNode 함수 구현 시, 왜 평탄화를 진행해야 하는 지?
      -> 평탄화 작업을 통해 효율적이고 동일하게 렌더링 로직을 처리하기 위해
    • 정규화를 해야하는 이유
      -> 불필요한 값을 제거하여 일관되고 최적화된 가상 돔 트리를 만들기 위해
  • 이벤트 위임을 사용하는 이유
    • 자식 요소마다 개별적인 이벤트 리스너를 등록하면 메모리 사용량이 늘어나는 문제를 해결하여 성능을 개선하기 위해
    • 부모 요소에서 한번에 이벤트를 관리하여 중복 코드를 줄이기 위해

학습 효과 분석

과제 구현 시 테스트 케이스가 통과하지 못하여 디버깅으로 문제의 원인을 찾는 과정을 학습했습니다.
그 과정에서 가상 돔에서 어떤 값들이 사용/처리되는 지 확인할 수 있었습니다.

과제 피드백

가상 돔이 동작하는 방식을 직접 구현하는 경험으로 기본적인 동작 이해를 할 수 있었습니다.
u

리뷰 받고 싶은 내용

베이직 테스트 "이벤트 핸들러가 제거되면 더 이상 호출되지 않아야 한다"에서 아래 에러와 함께 통과되지 않는 문제가 있었습니다.

   × Chapter1-2 > 기본과제 > 가상돔 만들기 >  > renderElement > 이벤트 핸들러가 제거되면 더 이상 호출되지 않아야 한다 11ms
     → expected "spy" to not be called at all, but actually been called 1 times

Received: 

  1st spy call:

    Array [
      MouseEvent {
        "isTrusted": false,
      },
    ]

문제점을 찾는 중에 removeEvent함수에서 !eventMap.has(element)가 조건에 걸려 내용을 수행하지 못하는건가? 라는 생각을 하였습니다.
https://github.com/hanghae-plus/front_4th_chapter1-2/blob/99e7430f994d6e3b24fb64a114da5afdba481620/src/lib/eventManager.js

하지만 addEvent()에서는 정상적으로 추가되는 것을 확인했는데 removeEvent()에서는 어떤 이유 때문에 빈 값으로 들어오고 있었고, 이에 대해 명확하게 문제점을 파악하지 못한 상태입니다.
어떤 부분으로 인해 removeEvent()가 정상적으로 호출되지 못한건지에 대한 피드백을 주시면 감사드리겠습니다

@9yurilee
Copy link

성규님 어제 넘 고생하셨어요 ! 도대체! 왜! eventMap에 데이터가 사라졌을까요... 어디서 사라진건지 아직도 너무 궁금해요🙄

@pangkyu
Copy link
Author

pangkyu commented Dec 27, 2024

성규님 어제 넘 고생하셨어요 ! 도대체! 왜! eventMap에 데이터가 사라졌을까요... 어디서 사라진건지 아직도 너무 궁금해요🙄

정말.. 뭐가 문제여서 값이 사라진건지 슬픕니다🤦‍♂️ 늦은 시간까지 코드 같이 봐주셔서 정말 감사합니다 ㅎㅎ

$el.setAttribute("class", value);
} else if (key.startsWith("on")) {
const eventType = key.slice(2).toLowerCase(); // 예: onClick -> click
$el.addEventListener(eventType, value); // 이벤트 핸들러 등록

Choose a reason for hiding this comment

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

성규님~! 혹시 이벤트 핸들러 등록하는부분을 eventManager 에서 만드신 addEvent함수를 이용하는것에대해서 어떻게생각하시나요??

Copy link
Author

Choose a reason for hiding this comment

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

함수를 제가 만들어놓고도 쓰지를 않고 있었네요,, ㅋㅋ 피드백 감사합니다 !

Copy link

@feel5ny feel5ny Dec 28, 2024

Choose a reason for hiding this comment

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

안녕하세요 성규님-! 김나영 코치입니다.
리뷰해주신 분의 말씀대로 해당 부분은 매니저에서 만들어둔 addEvent를 사용하셔야 현재 fail나는 테스트코드가 해결될 것으로 보입니다. 아마 addEvent에서 Map자료구조에 이벤트가 등록이 되어있다는 가정하에 removeEvent가 동작했을텐데, 직접 요소에서 이벤트가 관리되고 있어 removeEvent로는 제거처리가 되지 않은듯합니다 :)

수정하시면 다른 TC가 아마 깨지실텐데요, 하나씩 풀어나가시면서 리팩토링을 해보시면 좋을 듯 합니다.

고생하셨습니다 :) @pangkyu

Copy link

@feel5ny feel5ny left a comment

Choose a reason for hiding this comment

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

과제피드백때 요청하셨던 에러 디버깅 내용 코멘트 남겼습니다.

$el.setAttribute("class", value);
} else if (key.startsWith("on")) {
const eventType = key.slice(2).toLowerCase(); // 예: onClick -> click
$el.addEventListener(eventType, value); // 이벤트 핸들러 등록
Copy link

@feel5ny feel5ny Dec 28, 2024

Choose a reason for hiding this comment

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

안녕하세요 성규님-! 김나영 코치입니다.
리뷰해주신 분의 말씀대로 해당 부분은 매니저에서 만들어둔 addEvent를 사용하셔야 현재 fail나는 테스트코드가 해결될 것으로 보입니다. 아마 addEvent에서 Map자료구조에 이벤트가 등록이 되어있다는 가정하에 removeEvent가 동작했을텐데, 직접 요소에서 이벤트가 관리되고 있어 removeEvent로는 제거처리가 되지 않은듯합니다 :)

수정하시면 다른 TC가 아마 깨지실텐데요, 하나씩 풀어나가시면서 리팩토링을 해보시면 좋을 듯 합니다.

고생하셨습니다 :) @pangkyu

Copy link

@feel5ny feel5ny left a comment

Choose a reason for hiding this comment

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

과제피드백때 요청하셨던 에러 디버깅 내용 코멘트 남겼습니다.

@pangkyu
Copy link
Author

pangkyu commented Dec 28, 2024

과제피드백때 요청하셨던 에러 디버깅 내용 코멘트 남겼습니다.

시간 내주셔서 디버깅도 해주시고 정말 감사합니다ㅠㅠ
직접 요소로 접근하는 이벤트가 removeEvent로 제거되지 않는 부분을 제가 생각하지 못했습니다.. 피드백 주신 내용 반영해서 이번주에 완성하지 못한 내용들 꼭 구현해보겠습니다 감사합니다!!

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.

4 participants