Elli-Lee 님의 상세페이지[4팀 이유진] Chapter 1-2. 프레임워크 없이 SPA 만들기 (2)

과제 체크포인트

배포 링크

https://elli-lee.github.io/front_6th_chapter1-2/

기본과제

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

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

이벤트 위임

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

심화 과제

Diff 알고리즘 구현

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

과제 셀프회고

이번 과제의 가장 어려웠던 점은 각 함수들을 구현하는 과정에서 이 함수가 왜 필요한지, createVNode가 object를 return하는데 왜 normalizeVNode에서 한번 더 null / undefined를 처리하는지, 함수 내에서 각 분기처리를 그렇게 처리하는 이유 등등의 납득의 과정이었습니다. 과제의 목표를 명확히 이해하고 과제를 시작하고자 노력했고, 이를 위해 Virtual DOM이 필요한 이유, 동작 원리, Virtual DOM이 해결하고자 한 문제를 이해하기 위해 Vue 공식문서와 github 레포에 해당부분을 찾아보기도 하고, AI와 대화도 많이 나누는 등, 시간을 많이 투자했습니다. 이러한 노력이 과제 수행 시 덜 헤매는데 도움이 되었다고 생각합니다. 그 다음으로 어려웠던 점은 재귀의 늪이었습니다... 원하는 결과를 내고 싶어도 이를 재귀로 구현하는게 익숙하지 않아서 여러번 테스트를 돌리고 콘솔도 찍으면서 방향을 잡았습니다. 알고리즘 학습의 필요성을 느끼기도 했습니다. 여전히 코드를 깔끔하게 짜고 함수를 분리하고.. 등등은 매우 부족합니다. 그래도 최대한 이해하며 과제를 수행하려고 노력했다는 점에서는 저번주보다는 과제를 조금 더 만족스럽게 수행한 것 같습니다.

기술적 성장

새로 학습한 개념:

  • Virtual DOM의 내부 구현 메커니즘과 diff 알고리즘의 핵심 원리
  • 이벤트 위임 패턴을 활용한 효율적인 이벤트 관리 시스템

코드 품질

이벤트 관리자의 깔끔한 구조: WeakMap 기반의 계층적 이벤트 저장과 자동 정리 updateElement의 체계적인 분기 처리: 각 케이스별 명확한 로직 분리

가장 큰 배움이 있었던 부분

Virtual DOM의 동작 원리를 직접 구현하면서 이해하다보니, Vue등의 SPA 프레임워크들이 해결하고자 했던 문제가 조금은 보이는 것 같습니다. 이번 과제를 통해 Virtual DOM의 내부 구현 메커니즘과 diff 알고리즘의 핵심 원리에 대해 명확히 알게 되었습니다. 이번주에 실무에서 급하게 해결해야 했던 이슈 중 하나가 사실 "이미 A페이지에 위치한 사용자가 알림 등을 클릭해서 다른 페이지로 router push가 발생할 때, 만약 이동하려는 페이지가 이미 사용자가 위치한 A 페이지라면, 화면상에서는 아무런 렌더링이 발생하지 않아 사용자 입장에서는 클릭 이벤트에 버그가 있어서 router를 이동하는 것에 실패했다고 여긴다." 였습니다. 이번 과제를 수행하면서 해당 이슈를 접하니, 아무런 렌더링이 발생하지 않는 이유가 router 이동이 있어도 이동 전 후에 달라진 점이 없기 때문에 Vue의 Virtual DOM이 실제 DOM 업데이트를 진행하지 않아서임을 금방 이해할 수 있게 되었습니다. 덕분에 문제를 빨리 해결할 수 있었고, 이렇게 근본적인 동작 원리까지 아는 것의 중요성을 다시 한번 느낄 수 있었습니다.

추가 학습이 필요한 영역

  • 아직 이벤트 위임에 대해 스스로 누군가에게 설명할 정도로의 이해를 하지 못했습니다. 이번주 내용을 복습하고 여러번 읽으면서 추가학습을 할 예정입니다.
  • WeakMap 자료구조를 사용하는 것이 좋을거라고 추천받아 일단 사용하긴 했으나, 어떤 점에서 좋은지, Map과의 차이점은 무엇인지에 대해 아직 학습하지 못해서 추가학습이 필요합니다.
  • 아직은 배포가 쉽지 않습니다.. 왜 그렇게 수정하는지 이해하지 못한채로 AI가 시키는대로 배포를 수정하다보니 어떤 걸 수정해서 배포를 성공한건지 모르겠습니다..

과제 피드백

  • Virtual DOM의 동작 원리를 직접 구현하다보니 Virtual DOM의 필요성에 대해 더 잘 이해할 수 있었고, 저번 과제와 비교하여 virtual DOM 덕분에 실제로 필요한 부분만 렌더링 됨을 직접 알 수 있어서 좋았습니다.
  • 촘촘한 테스트케이스로, 제가 처음 구현할 때 생각하지 못한 케이스들을 테스트를 통해 찾아서 계속 추가로 구현 할 수 있어서 좋았습니다.

리뷰 받고 싶은 내용

불리언 속성 처리 방식 중 checked, readonly, selected 같은 불리언 속성을 property only로 다루고 있는데, 이런 처리 방식이 올바른 접근인지 궁금합니다.

updateAttributes에서 속성 처리 순서나 우선순위가 적절한지 궁금합니다. className → 이벤트 → boolean → 나머지 순으로 처리하고 있는데, 이런 순서가 DOM 업데이트 시 예상치 못한 사이드 이펙트를 막는 데 적절한지 궁금합니다.

리뷰 받고 싶은 포인트를 찾기 위해 전체적으로 코드를 되돌아보다보니, createElement와 updateElement의 const booleanProps = ["checked", "disabled", "selected", "readonly", "multiple", "autofocus", "required"]; const propertyOnlyBooleanProps = ["checked", "selected"]; const propToAttributeMap = { readOnly: "readonly", }; 부분을 공통으로 쓸 수 있을것 같아 보입니다. 과제 제출 이후 수정하겠습니다!

과제 피드백

안녕하세요 유진~, 수고하셨습니다! 이번 과제는 React의 핵심 원리인 가상 DOM과 diff 알고리즘을 직접 구현해보면서, 프레임워크가 어떻게 효율적인 렌더링을 수행하는지 이해하는 것이 목표였습니다. 그전에 내가 만들어야 하니까 구현해가면서 필요한걸 공부하는 것과 그냥 공부를 하는것과의 차이를 확실히 느꼈기를 바랍니다. 단순히 "가상 DOM이란 무엇인가"를 읽고 아는 것과, "가상 DOM을 구현하기 위해 무엇이 필요한가"를 고민하며 공부하는 것은 완전히 다른 깊이의 학습이니까요. 잘 했습니다.

회고에서 각 함수의 필요성과 역할을 납득하는 과정이 어려웠다고 했는데요. 그래서 Vue 공식문서와 GitHub 레포를 찾아보며 Virtual DOM의 근본적인 문제를 이해하려 노력하신 점, 그리고 실무에서 Vue의 Virtual DOM이 왜 렌더링을 하지 않는지를 생각할 수 있도록 시야가 깊어진 부분이 아주 좋네요. Vue와 React의 렌더링 전략은 다르기에 Virtual DOM이 아닌 Vue의 Rendering방식도 한번 이해해보면 재밌을거에요.

나아가 코드를 조금 더 개선해본다면 하드코딩된 이벤트 리스트 대신, 실제 사용된 이벤트만 동적으로 등록하는 방식도 한번 시도해보시길 바래요.


Q1. boolean 속성 처리 방식이 올바른지? => 네, 올바른 접근입니다. HTML의 boolean 속성은 attribute와 property의 동작이 다른데, 이를 정확히 구분하여 처리하신 것이 좋습니다. 특히 checkedselected는 property로만 제어해야 하는 것을 잘 파악하셨습니다.

Q2. updateAttributes의 처리 순서가 적절한지? => 네 지금 순서는 큰 문제 없어보입니다. 각 속성 처리가 독립적이기만 하면 되요. 순서보다는 각 처리 로직이 서로 영향을 주지 않도록 설계하는 것이 중요합니다.

이렇게 직접 저수준 라이브러리를 구현해보면서 얻은 깊은 이해는 앞으로 프레임워크를 사용할 때 큰 자산이 될 거에요! 다음 주차도 화이팅입니다! :)