-
Notifications
You must be signed in to change notification settings - Fork 65
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
[15팀 이규리] [Chapter 1-2] 프레임워크 없이 SPA 만들기 #25
base: main
Are you sure you want to change the base?
Conversation
src/lib/updateElement.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
세상에 뭐라니 nullish(??)아니고 옵셔널체이닝(?)!!!! 입니다!!!!🔨🔨🔨
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이번주 고생 정말 많으셨습니다! 코드에서 많이 배워갑니다
src/lib/eventManager.js
Outdated
const elementMap = eventMap.get(eventType); | ||
|
||
if (!elementMap.has(element)) { | ||
elementMap.set(element, new Set()); // handler의 내용은 중복되면 안되므로 set 사용. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거보니까 저도 애초에 set으로 저장해야했나..? 싶긴하네요
뭔가 콘솔찍다가 add가 2번되고 remove가 1번돌아서 이벤트가 안지워졌다고 나온거같기도하빈다 <- 테오님 설명들으니까 이거마저도 잘못생각했던거같아요,,
고민이 많이 드러나고 유익한 정보가 많은 PR이네요! 늦게까지 고생많으셨습니다 |
src/lib/renderElement.js
Outdated
이벤트를 등록합니다. | ||
*/ | ||
|
||
let prevVNode = new WeakMap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WeakMap을 안써봐서 몰랐었는데, WeakMap을 사용하면 메모리 관리측면에서 우수하군여..!! 한수배워갑니다 👍🏻👍🏻👍🏻
과제 체크포인트
기본과제
가상돔을 기반으로 렌더링하기
이벤트 위임
심화 과제
1) Diff 알고리즘 구현
2) 포스트 추가/좋아요 기능 구현
과제 셀프회고
🐢 회고를 시작하며
과제 목표
가상 DOM을 정의하고 사용할 수 있다.
가상 DOM을 이용하여 이벤트 관리를 최적화할 수 있다.
diff 알고리즘을 이용하여 불필요한 렌더링을 최소화할 수 있다.
개인 학습 목표
기능 구현에 급급하지 말고 동작 원리를 이해하기★★
Fail을 받을 지언정 동작 원리를 이해하자
라고 마음을 먹고 시작한 2주차였다. 이번주의 주제가 특히 나에게 늘 막연한 개념이었던 가상DOM을 직접 구현해보는 주차여서 더욱 그랬던 것도 있었다.그래서 최대한 제공받은 학습자료를 꼼꼼하게 살피려고 했고, 코드를 짜면서도 계속 궁금증을 가지려고 노력했다. 원래 '그러려니'인간이었어서 쉽지만은 않았지만 덕분에 Virtual DOM의 기본 구조, JSX가 Virtual DOM으로 변환하는 과정, Virtual DOM이 실제 DOM으로 어떻게 변환되는지에 대해서 깊게 알아볼 수 있었다.
코드 작성 전 코드 설계에 충분한 시간을 가지기
지난 주에는 급하게 업무 쳐내던 버릇이 툭 튀어나와선 급한 마음에 무작정 코드부터 작성하기 시작했다. 코드를 충분히 생각하지 않고 작업을 시작하니 나의 생각이 들어가 있지 않았고, 나의 생각이 들어있지 않으니 다른 사람의 코드를 봐도 GPT의 힘을 빌려도 내 코드에 쉽게 적용할 수 없었다.
그래서 2주차에는 어떤 파일에서 어떤 코드를 작성해야 할 지 미리 주석과 노트로 정리하고 작업에 들어갔다. 물론 전체의 흐름을 다 파악하기엔 아직 부족하지만 1주차에 2.5일정도 걸렸던 기본과제까지 작업 속도를 1.5일정도로 줄일 수 있었다.
👩💻 기술적 성장
Diffing 알고리즘 (비교 알고리즘)
Diffing 알고리즘이란 두 가상 DOM 트리를 비교하여 차이점을 찾는 과정을 의미한다. 두 개의 트리를 비교할 때, React는 두 엘리먼트의 루트(root) 엘리먼트부터 비교를 시작한다. 그 이후는,
등 루트 엘리먼트의 타입에 따라 달라진다.
노션에 적혀있는 구현 가이드가 어떻게 정해진건지 궁금했는데, 리액트 공식 문서에 이미 나와있었다!
React를 이용할 땐 깊게 생각해보지 못했던 부분을 updateElement 함수를 직접 구현하며 아주 제대로 톺아볼 수 있었다. 특히 다른 조의 분들이 우리 조에 오셔서 같이 공부한 적이 있었는데 마침 Diffing 알고리즘에 대한 부분이었어서 같이 화면을 공유하며 이야기를 나눴던게 큰 도움이 되었다!
🧾 코드 품질
1. 좋아요 토글 버튼 구현 이슈
문제 상황.
원인 분석.
원인은 바로 구조 분해 할당(
const { posts } = globalStore.getState();
)으로 받아 온 posts!posts.map(…)
는 새 배열을 반환하지만, 구조 분해로 가져온 posts가 기존 상태와 분리되지 않고 참조를 유지할 수 있다. 따라서 변경 작업이 예상치 못한 방식으로 동작할 가능성이 있는 것!해결 방법.
구조 분해 할당 대신 전체 상태를 복사하는 방식(
const state = globalStore.getState();
)으로 해결할 수 있었다.state.posts.map(...)
는 기존 상태를 복사한 새로운 배열을 생성하며, 다른 필드와의 연관성을 유지할수 있는 것!globalStore.setState({ ...state, posts: updatedPosts })
는 기존 상태를 유지하며,posts
만 업데이트한다. 따라서 state의 다른 필드(loggedIn
,currentUser
)도 손실 없이 유지된다.결론
const { posts } = globalStore.getState();
를 사용하면 상태 병합 과정에서 다른 상태가 손실될 가능성이 있다. 전체 상태를 가져와(const state = globalStore.getState();
) 필요한 필드를 참조하고 병합하는 방식이 안전하며, 예상치 못한 상태 손실 문제를 방지할 수 있다.주요 차이.
const { posts } = globalStore.getState();
는 posts만 독립적으로 가져오기 때문에 다른 상태와의 병합을 명확히 처리하지 않을 수 있다. 반면const state
를 사용하면 전체 상태를 명확히 병합할 수 있다.posts
만 독립적으로 가져오면, 업데이트된posts
배열을globalStore.setState()
에 병합할 때 다른 필드(loggedIn
,currentUser
등)가 손실될 수 있다.posts
를 수정하면, 기존 상태 객체에 영향을 미칠 수 있다.2. UpdateAttributes 함수의 Util함수화
진행 배경.
해결 방안.
중복된 updateAttributes 함수를 하나의 유틸리티 함수(
handleUpdateAttr
)로 추출하여 코드의 재사용성을 높이고, 유지보수를 용이하게 만들기로 결정했다.추가 고민 사항.
handleUpdateAttr
내 중복 코드가 존재하는데, 이를 어떻게 가독성 좋으면서 중복 코드를 줄일 수 있을 지 고민이 된다.📊 학습 효과 분석
이벤트 위임에 버블링이 이용된다는 사실을 이번 과제를 하면서 깨달았다. 더듬더듬 과제를 진행하긴 했지만 아직 이벤트 위임이라든지, 이벤트 버블링과 캡처링을 활용한 효율적인 이벤트 처리에 대한 이해도가 낮은 것 같아 추가적인 학습이 필요하다.
1. 캡처링 (Capture Phase)
addEventListener
의 세 번째 인수로true
를 전달하면 캡처링 단계에서 이벤트 핸들러가 실행.2. 버블링 (Bubble Phase)
addEventListener
의 세 번째 인수로false
(default)를 전달하면 버블링 단계에서 이벤트 핸들러가 실행.✍ 과제 피드백
너무 어려웠지만 그만큼 배움이 있었던 과제였습니다.
특히 막연한 개념이었던 Virtual DOM을 직접 구현하며 그 원리를 파악할 수 있었던게 좋았습니다.
그리고 구현해야 할 파일들에 기재되어있던 개발 가이드 라인이 개인적으로는 과제의 방향성을 설계하는데에 큰 도움이 되었습니다. (
이런 케이스도 생각해야하는구나
를 생각할 수 있어 좋았습니다!)다만, 다른 수강생분들께 여쭤봐도 updateElement.js와 EventManager.js에서 특히 어려움을 겪었다는 분들이 많았던 것 같습니다. 저의 경우에는 React에서 썼던 기능을 떠올리며 동작 원리를 최대한 이해 및 추론하려고 하는데, EventManager는 뭔가 추론하기가 힘들었습니다. 그래서 다음주 발제 시간에 있는 리뷰 시간의 해당 부분에 대한 설명이 기대됩니다.
🙋♀️ 리뷰 받고 싶은 내용
eventManager.js의 setupEventListener 함수의 주석에서 "주의: 이벤트 캡처링을 사용하여 이벤트를 상위에서 하위로 전파"라고 작성해두셨는데, setupEventListener 함수는 '이벤트 위임'을 구현하기 위한 목적이라고 생각했습니다. 그렇게 하면 이벤트 버블링을 사용해야 하는게 아닌지 궁금합니다! 아니라면 혹시 제가 어디를 잘못 이해하고 있는지 구글링 키워드 힌트라도 부탁드립니다..!
단순 질문인데, 1) main, main.hash, render 파일, 2) 컴포넌트 파일 내 함수 에서만큼은 예외적으로(?) 함수 선언문 형식을 사용하신것 같은데 혹시 이유가 있다면 어떤 이유로 사용하신 건지 궁금합니다!