이번주 새롭게 알게 된 내용
Diffing 알고리즘
SPA를 구현을 떠올리면, Part 1에서 진행했던 라우팅 처리 방법이 핵심적이긴 하지만 필요한 부분만 업데이트하는 것도 큰 특징 중 하나이다. 이번 과제에서는 Diffing 알고리즘을 통해 업데이트되는 부분만 부분적으로 렌더링을 하는 기능을 구현했다. 사실 좀 막막한 부분도 있기는 했는데, 참고 자료랑 과제 구현 파일에 달린 주석들을 참고로 해서 생각보다는 금방 적용할 수 있었다. 중간에 돔 객체로 만드는 과정에서 children을 제대로 업데이트해주지 않아 파일이 제대로 적용되지 않는 문제가 있었는데, 집단지성의 힘으로 해결할 수 있었다. (3기 17팀...💖)
1. 렌더링 가능한 형태로 풀어주고
2. oldNode, newNode를 비교해서 여러 케이스들에 대해 적절한 element를 생성하고
3. 필요 없는 노드들은 제거해 주는
이런 과정들을 순차적으로 접근하다 보니 점차 이해도도 높일 수 있었다.
createVNode 동작방식
createVNode.js를 만들고 babel을 통해 jsx 형식에 대해서 createVNode 로직을 거친 후 객체 형태로 만들어질 수 있었는데, 이 동작 원리가 잘 이해가 가지 않았다. babel 설정을 통해 jsx에 있는 요소들이 객체로 만들어진다는 것까지는 알겠지만, createVNode에는 type, props,... children이 있는데 어떻게 각 요소가 이 형식에 맞춰서 들어갈 수 있지?라는 생각이 들었다. 팀원 한 분께서 라이브러리가 알아서 해주는 거 아닐까요?라는 답을 주셨지만 구체적으로 왜 동작하는지가 궁금해졌다.
그래서 설정된 값을 기준으로 찾아보니, React.createElement로 되어있는 것을 환경설정을 통해 createVNode로 바꾸기 때문에 동작한다는 사실을 알게 되었다. createElement의 인자로 넘기는 것들이 type, props,... children인데 이걸 createVNode라는 커스텀 파일로 바꾸게 되면 동일하게 type, props,... children이 파라미터로 들어오게 되는 것이다. 때문에 따로 type, props,... children을 넘기지 않아도 동작할 수 있었다는 것을 알 수 있었다.
이벤트 위임 방식 (eventManager.js)
기존에는 이벤트를 적용하고자 하는 태그에 직접적으로 주고 있었다. 하지만 이번에는 과제 요구사항에 따라 모든 이벤트들을 eventMap이라는 Map에 저장해 두었다가, root 엘리먼트에 한 번에 등록/삭제를 하면서 이벤트 등록을 하는 방식으로 구현을 했다. 이 방식이 처음에 구조를 잡기가 어렵긴 했지만, 모든 이벤트들에 대해 한 곳에서 처리가 가능하다는 사실이 새롭기도 했고 또 이런 방법을 통해서 메모리 낭비를 막을 수 있다는 사실도 새롭게 다가왔다.
lib/utils의 차이
과제를 마무리하고 리팩터링을 하는 과정에서 갑자기 lib, utils 폴더가 눈에 들어왔다. 보통 회사에서는 utils를 많이 사용했었기 때문에 lib로 나누어진 이유가 궁금했고, 이를 확인하기 위해 여기저기 검색한 결과 lib는 좀 더 큰 범위, utils는 좀 더 작고 범용적인 폴더라는 것을 확인할 수 있었다. 하지만 '크다', '작다'의 판별은 사람마다 다를 수 있고 심지어 동일한 사람이 본다고 하더라도 그때그때마다 판단이 달라질 수 있을 것 같다는 생각이 들었다.
코치님의 기준을 아는 것이 도움이 될 것 같아 질문을 드렸고, 발제를 담당하신 준일코치님 외에 여러 답변들을 같이 참고하면서 좀 더 기준점을 찾을 수 있었다. lib에 있는 것들은 여러 군데에서 사용이 됨과 동시에 프로젝트에 의존도가 있어 다른 곳에서는 사용하기가 어려운 느낌이 있고, utils는 특정 프로젝트에 한정되지 않고 다른 곳에서도 활용할 수 있는 것이라고 생각하니 조금 더 명확한 기준이 생겼다. 하지만 이 또한 사람마다 판단하는 부분이 다를 수 있을 것이다 보니 좀 더 다양한 코드를 보면서 기준점을 더 확실하게 세울 수 있어야겠다는 생각을 했다.
프레임워크 없이 SPA 만들기 Part2 : https://github.com/soyoonJ/front_3rd_chatper1/tree/chapter1-2
개인 레포 : https://github.com/soyoonJ/front_3rd_chatper1/tree/chapter1-2
팀 리뷰
저번주보다 더 많은 시간을 함께했다. 물론 쉬는 날이 있던 것도 있지만 그거 외에도 첫 주보다 더 가까워진 느낌...? 질문도 서로 자주 하고 막히는 부분도 많이 공유해서 더 많은 내용을 흡수할 수 있었다. 특히 일부 팀 변동이 있어 다른 팀원분이 새롭게 우리 팀으로 들어오시게 됐는데 새로운 정보들을 많이 공유 주시고 열심히 해주시는 분이라 팀에 빠르게 적응하신 것 같아 좋았다!
2주 차 발제 때 저번주에 팀 문화를 처음 만들고 운영하면서 아쉬웠던 부분을 공유하고 반영했는데 점점 완전한 팀이 되어가고 있는 것 같다는 느낌이 들어 든든하다ㅎㅎ (prettierignore 추가, 코드리뷰 다 같이 할 수 있는 환경 만들기!)
참고자료
createVNode 동작원리 관련
https://stackoverflow.com/questions/50629526/what-is-pragma-h-in-transform-react-jsx
https://ko.react.dev/reference/react/createElement
가상 DOM 구현
https://medium.com/@deathmood/how-to-write-your-own-virtual-dom-ee74acc13060
https://medium.com/@deathmood/write-your-virtual-dom-2-props-events-a957608f5c76
lib/utils 구분
https://github.com/erikras/react-redux-universal-hot-example/issues/808
항해 추천인 코드 (20만원 할인) - IXtXJj
'개발' 카테고리의 다른 글
[항해플러스] 클린코드 (진짜진짜 더러운 코드 개선하기) (1) | 2024.10.18 |
---|---|
[항해플러스] React Hooks 직접 구현하기 (useRef, useMemo, useCallback, ...) (2) | 2024.10.12 |
[항해플러스] 프레임워크 없이 SPA 만들기 Part 1 회고 (0) | 2024.09.28 |
[항해플러스] 프론트 3기 과정을 시작하며... (1) | 2024.09.21 |
[HTTP] URL Fragment와 Hash Router (feat. #) (0) | 2024.09.02 |