-
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
[10팀 이용] [Chapter 1-2] 프레임워크 없이 SPA 만들기 #30
Open
nogy21
wants to merge
31
commits into
hanghae-plus:main
Choose a base branch
from
nogy21:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- 올바른 구조의 vNode를 생성 - 자식 요소 검증: 숫자 0을 제외한 falsy 값 제거
- null, undefined, boolean일 경우 빈 문자열 반환 - 숫자 또는 문자열일 경우 문자열로 반환
- 유효성 로직 수정 및 검증 함수 추가 - 문자열 반환 함수 추가
- type이 function일 경우 해당 함수 실행하여 type, props, children 반환 - normalizeChildren 함수 구현 - children 요소의 경우 자식 요소가 모두 텍스트 노드일 경우 합치는 로직 추가
- 배열 입력 시 fragment로 감싸서 반환
- 상위 스코프의 eventListeners 사용하여 이벤트 추가 및 등록 관리
- eventListeners의 손쉬운 관리를 위해 배열로 자료구조 변경 - 중복 제거 없이 특정 인덱스에 접근/수정/제거를 쉽게 하기 위함 - 추후 최적화를 한다면 다른 자료구조 사용 - addEventListener와 removeEventListener에 동일한 이벤트핸들러 참조를 위해 boundHandler 구현 및 eventListeners에 갱신
- 정규화된 가상 노드를 DOM 요소로 생성하고 컨테이너에 추가한 뒤 이벤트 등록 - on<event> 핸들러 등록을 위해 createElement의 속성 처리 로직에 조건 추가
- 새로운 노드를 등록할 경우(container에 이미 childNodes 요소가 있는 경우) 기존 노드와 교체 - 상세 비교하여 변경분에 대한 업데이트가 아닌 노드를 통으로 교체함. 추후 updateElement 사용하여 변경분에 대한 업데이트 예정
…도 함수로 추출 - createVNode 불필요한 조건문 및 반환문 제거 - normalizeChildren 함수의 응집도를 높이기 위해 문자열 병합 로직을 mergeStrings 함수로 추출 (역할 분리)
…Event 사용 - 속석 업데이트 로직 updateAttributes 함수로 분리 및 조건문 가독성 개선 - DOM 요소에 이벤트 직접 등록하지 않고 addEvent 함수로 이벤트 리스터 저장소에 저장
- 모듈 스코프 가상 노드인 globalVNode 선언 - 해당 변수로 가상 DOM 트리 상태 관리 - container에 자식 요소 없을 시 null 초기화 - globalVNode가 유효하지 않을 경우 DOM 노드 생성 - 유효할 경우 updateElement 함수를 이용한 DOM 노드 업데이트
- updateElement 함수 구현 - 가상 DOM 비교하여 DOM 조작 - 가상 DOM 속성 변경 시 updateAttributes 함수 호출 - 가상 DOM 자식 요소 비교 시 재귀적 호출 - updateAttributes 함수 구현 - on<event> 등록 및 제거 시 전역 관리를 위한 addEvent, removeEvent 호출 - 속성 비교 후 DOM 반영
- 가독성 개선을 위해 모듈 스코프의 가상 노드인 globalVNode 초기화 로직을 initGlobalVNode 함수로 추출 - container에 자식 요소가 없을 경우 globalVNode 초기화하는 로직 - 해당 로직은 globalVNode 변수의 메모리 관리를 위해 renderElement 실행 시 수행
- createElement, createVNode, eventManager, updateElement, renderElement 함수에 jsdoc 형태 주석 추가
- 함수 타입 처리 및 자식 요소 처리 로직 수정 - 함수 타입일 경우 함수를 호출하며 재귀적으로 함수 타입 확인한 후 vNode 반환 - 자식 요소를 가지고 있는 경우 유효성 검사 후 문자열 또는 숫자일 경우 문자열 값, 그외의 경우 normalizeVNode 함수로 정규화하여 children 반환
- updateElement 함수에서 기존 노드 제거 시 removeOnEvent 호출, 신규 노드 추가 시 addOnEvent 호출하도록 변경
- eventManager - eventListeners 변수를 배열에서 Map으로 자료구조 변경 - 이벤트 타입에 따라 WeakMap을 등록하여 이벤트 리스너 관리 - setupEventListeners 함수에서 중복 방지를 막기 위해 제거 후 등록하도록 개선 - renderElement: container와 연결된 가상돔을 WeakMap으로 관리하도록 개선
- 문제: jsx 컴포넌트 렌더링이 안되는 이슈 - 상황: 함수형 컴포넌트에 대한 호출이 안됨 - 분석: 노드를 정규화하는 과정에서 type이 함수형일 경우 재귀적 호출에 문제가 있는 것으로 파악. 또한, 자식 요소 정규화 과정에서 내부 구조가 적절하게 처리되지 않은 것으로 보임 - 해결: 속성 및 자식 요소 처리 로직 단순화, 재귀 호출 로직 개선
- 전역 정보의 로그인 한 사용자, 현재 사용자 정보를 이용해 권한에 따른 게시물 조작 기능 처리 - 로그인하지 않은 사용자는 게시물 등록 폼을 노출하지 않음 - 로그인하지 않은 사용자가 게시물 좋아요 누를 시 alert 노출 - 로그인한 사용자는 게시물 추가 및 좋아요 클릭 가능
- 문제: 이벤트 핸들러 교체 로직에서 기존 이벤트 제거가 새로운 이벤트가 없는 경우에만 진행됨. 등록 역시 기존 속성이 없는 경우에만 진행되어 잘못된 로직으로 작성됨 - 해결: 두 이벤트가 다를 경우 기존 이벤트가 있다면 지우고 새로운 이벤트가 존재한다면 지워지도록 조건 로직 개선
pitangland
reviewed
Dec 27, 2024
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.
과제를 진행하며 반복되는 코드들이 많아서 비효율적인 것 같다 생각했는데 utils에 반복되는 코드를 따로 작성하고 사용한 것이 인상적이었습니다!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
과제 체크포인트
기본과제
가상돔을 기반으로 렌더링하기
이벤트 위임
심화 과제
1) Diff 알고리즘 구현
2) 포스트 추가/좋아요 기능 구현
과제 셀프회고
1주차에 이어 React가 해결하고자 했던 문제를 조금씩 이해할 수 있는 시간이었습니다.
기존에는 리액트와 Next.js와 같은 프레임워크를 통해 추상화된 렌더링 방식을 사용하며 DOM 조작과 이벤트 관리에 대한 고민은 크게 하지 않았던 것 같습니다.
이번주 과제에서 가상돔을 만들고, Diffing 알고리즘을 구현하며 실제 DOM을 조작하기까지 기존에는 미처 생각해보지 못했던 이벤트 관리의 복잡성과 메모리 관리, 렌더링에 대한 고민을 해볼 수 있었습니다.
기술적 성장
JSX가 실제 DOM으로 그려지는 과정에 대한 이해
가상돔이 실제 성능 향상에 미치는 영향과 오해
: 대규모 DOM 조작이 필요한 복잡한 애플리케이션에서는 확실한 이점이 있지만, 작은 규모의 앱에서는 오히려 오버헤드가 될 수 있다.
대규모 리스트나 복잡한 UI 업데이트 시 VirtualDOM이 효과적
간단한 UI 변경에는 직접적인 DOM 조작이 더 빠를 수 있음
메모리 사용량과 초기 로딩 시간에 대한 고려 필요
특정 유형의 애니메이션에서는 최적의 성능을 내기 어려울 수 있음
(애니메이션처럼 미세하고 연속적인 DOM 변경이 필요한 경우, 이 과정이 비효율적일 수 있기 때문)
이벤트 위임의 목적과 사용 방법에 대한 이해
이벤트 위임과 WeakMap을 활용해 이벤트 리스너 관리와 메모리 누수 문제를 효과적으로 해결했습니다. (해당 커밋, 슬랙에 올라온 동기분들의 지식 공유를 통해 인사이트를 얻었습니다.)
(WeakMap은 객체를 키로 사용하며, 참조가 없어지면 자동으로 제거되어 메모리 누수 방지에 유리함)
eventListeners
)를 Map을 사용해 관리했습니다.메모리 누수 방지
• DOM 요소를 키로 사용하는 WeakMap은 참조가 사라지면 자동으로 메모리를 해제하므로, 수동으로 메모리를 관리할 필요가 없습니다.
• 이를 통해 DOM 요소가 제거된 경우에도 메모리 누수가 발생하지 않도록 설계되었습니다.
효율적인 이벤트 위임
• 이벤트 위임을 활용하여 상위 요소(root)에 이벤트 리스너를 등록하고, 하위 요소에서 발생하는 이벤트를 처리했습니다.
• 이벤트를 setupEventListeners 함수에서 일괄적으로 관리하며, 기존 리스너를 제거한 후 다시 등록하여 불필요한 중복 리스너 등록을 방지했습니다.
• 이벤트 위임 처리 로직
학습 효과 분석
과제 피드백
리뷰 받고 싶은 내용
WeakMap을 활용한 코드에서 현재의 이벤트 관리 구조가 확장성 측면에서 보완할 부분 많다고 생각이 됩니다.
현재 코드는 기본 브라우저 이벤트를 처리하는 데 초점을 맞췄습니다.
그래서 이벤트 흐름 제어(stopPropagation, preventDefault)나 캡처링/버블링 동작을 세밀하게 제어할 수 없습니다.
React의 합성 이벤트(Synthetic Event 객체 활용)와 같은 추상화된 인터페이스를 도입하면 브라우저 호환성이 높을 뿐만 아니라 현재 제 코드와 같은 이벤트 흐름에 대한 조건부 처리, 그리고 유지보수성이나 확장성에 장점이 있을 것 같은데 구현 방식이 떠오르지 않아서 생각에만 그친 상황입니다.
현재의 이벤트 위임 방식(root 요소에 리스너를 등록)에서도 Synthetic Event를 활용하여 캡처링/버블링 제어가 가능할까요?
도입한다면 handleEvent 함수 내에서 Synthetic Event를 생성하는 방식이 옳은 방향일지 고민입니다.
위와 같은 방식으로 처리한다면 이벤트 흐름 제어(stopPropagation, preventDefault)나 캡처링/버블링 처리도 해당 로직에서 처리하는게 맞을까요?
requestAnimationFrame
도입에 대해서도 문의 드립니다. 메인 스레드를 차단하지 않고, 다음 repaint가 이벤트 루프에서 스케줄링되기 직전에 실행되기 때문에 해당 콜백 내에서 DOM 작업을 수행하면 더 효율적이라고 학습을 했는데, 현재 과제에서 적용하면 테스트 코드에서 실패가 발생해서 적용하지 못하였습니다. 시점의 불일치 때문으로 의심을 하고 있지만, 코드 자체에 문제가 있을지도 모르겠어서 문의 드립니다. 브라우저에서 동작은 정상적으로 수행되고 있습니다.