과제 체크포인트
배포 링크
https://adds9810.github.io/front_6th_chapter1-2/
기본과제
가상돔을 기반으로 렌더링하기
- createVNode 함수를 이용하여 vNode를 만든다.
- normalizeVNode 함수를 이용하여 vNode를 정규화한다.
- createElement 함수를 이용하여 vNode를 실제 DOM으로 만든다.
- 결과적으로, JSX를 실제 DOM으로 변환할 수 있도록 만들었다.
이벤트 위임
- 노드를 생성할 때 이벤트를 직접 등록하는게 아니라 이벤트 위임 방식으로 등록해야 한다
- 동적으로 추가된 요소에도 이벤트가 정상적으로 작동해야 한다
- 이벤트 핸들러가 제거되면 더 이상 호출되지 않아야 한다
심화 과제
Diff 알고리즘 구현
- 초기 렌더링이 올바르게 수행되어야 한다
- diff 알고리즘을 통해 변경된 부분만 업데이트해야 한다
- 새로운 요소를 추가하고 불필요한 요소를 제거해야 한다
- 요소의 속성만 변경되었을 때 요소를 재사용해야 한다
- 요소의 타입이 변경되었을 때 새로운 요소를 생성해야 한다
과제 셀프회고
이번 과제를 통해 웹 개발의 핵심 원리를 깊이 있게 이해할 수 있었습니다. React나 Vue 같은 프레임워크 없이 순수 JavaScript로 가상돔, 이벤트 위임, 상태 관리 등을 직접 구현해보면서 "프레임워크가 내부적으로 어떻게 동작하는지"를 체감할 수 있었습니다. 처음에는 "평탄화", "재귀적으로 표준화", "DocumentFragment" 같은 용어들조차 몰랐는데, 이번 과제를 통해 이런 개념들을 실제로 구현해보면서 이해하게 되었습니다. 특히 가상돔의 Diff 알고리즘을 구현하면서 DOM 조작의 비용과 최적화의 중요성을 깨달았습니다. 생소한 단어들과 그 단어들에 대한 얕은 이해도로 AI 의존을 줄이기로 했던 이전의 다짐과 다르게 더욱 많이 사용하였습니다.(바이브 코딩 수준) 직접 구현보다는 AI에게 요구사항과 테스트 항목을 주고 작업하는 과정을 보고 어떻게 작업하는지, 내가 이번에 알게된 개념들이 어떻게 사용되는지 물어보고 확인하는 시간이었습니다. 하지만 이런 높은 AI 의존도에 대해 고민이 생겼습니다. 팀원들이 같은 수강생에게 물어보고 해결할 것을 권하던데, 다음주에는 그 방법으로 시도해보려고 합니다. AI는 빠른 해결책을 제공해주지만, 팀원들과의 소통을 통해 더 깊이 있는 이해와 다양한 관점을 얻을 수 있을 것 같습니다.
기술적 성장
- 가상 DOM 시스템 구현: createVNode, normalizeVNode, createElement, updateElement 함수를 체계적으로 구현하면서 가상 DOM의 생성부터 업데이트까지 전체 생명주기를 이해할 수 있었습니다. 특히 updateElement에서 다섯 가지 케이스를 처리하는 로직을 구성하며 DOM 조작이 얼마나 복잡하고 조건 분기가 중요한 작업인지 체감했습니다.
- 평탄화(flat) 개념 이해: createVNode에서 children.flat(Infinity)를 사용하는 이유를 처음에는 이해하지 못했지만, JSX에서 중첩 배열이 자주 생기기 때문에 이를 평탄화해 일관된 children 배열로 만드는 전처리 과정임을 깨달았습니다.
- 재귀적 표준화 방식 습득: normalizeVNode 함수 내부에서 자기 자신을 다시 호출하는 재귀 구조가 처음에는 낯설고 어려웠지만, 함수형 컴포넌트를 처리하는 과정에서 필요한 핵심 구조라는 것을 이해했습니다.
- DocumentFragment 활용: createElement 함수에서 children이 배열일 때 DocumentFragment를 활용해 여러 DOM 요소를 한 번에 추가하는 방법을 배웠습니다. 단순히 반복문으로 처리하는 것보다, DOM 삽입 시 리플로우를 줄이고 성능을 개선할 수 있는 효율적인 기법임을 알게 되었습니다.
- Map을 활용한 데이터 저장: eventManager.js에서 Map을 사용해 이벤트 저장소를 구현하면서, 객체보다 효율적인 키-값 저장 방식을 배웠습니다. 특히 DOM 요소를 키로 사용할 때 Map의 장점을 이해할 수 있었습니다.
- 이벤트 위임 시스템: eventManager를 통해 이벤트 위임 패턴을 직접 구현하는 과정을 지켜보면서 이벤트 위임의 원리를 이해할 수 있었습니다. 각 요소마다 개별적으로 이벤트를 등록하는 대신, 루트 요소에서 이벤트를 위임받아 처리하는 방식으로 성능을 최적화할 수 있다는 것을 배웠습니다.
코드 품질
이번 과제에서는 작동하는 기능 구현에 집중한 탓에 코드 품질 측면에서는 여러 개선 지점이 있었습니다. 특히 바이브 코딩으로 빠르게 구현하면서 중복 로직, 긴 함수, 모호한 네이밍 등이 발생했고, 이는 유지보수성과 가독성을 크게 떨어뜨렸습니다. 예를 들어 updateElement.js는 하나의 긴 메서드 안에서 다양한 조건 분기를 처리하고 있는데, 이로 인해 코드 흐름 파악이 어려워지고 테스트도 어려운 구조가 되었습니다. 기능별로 분리된 작은 함수로 쪼개거나, 각 조건을 명확히 표현하는 변수명과 함수명을 사용하는 등 클린 코드 원칙을 적용하는 노력이 필요함을 느꼈습니다. AI와 함께 코드를 리뷰하며 구조 개선의 중요성을 체감할 수 있었습니다. 특히 중복된 로직 제거, 이벤트 위임 방식의 정리, 조건 처리 최적화 등에서 AI가 제안한 코드가 더 간결하고 명확했습니다. 이를 통해 단순히 작동하는 코드를 넘어, 읽기 쉽고 확장 가능한 구조를 고민하는 것이 얼마나 중요한지를 다시 생각하게 되었습니다. 또한, 코드를 처음부터 끝까지 다시 읽어보는 과정에서 “어떻게 작동하는가”가 아닌 “왜 이렇게 설계했는가”에 대한 설명이 어려운 코드가 많다는 점을 자각했습니다. 이는 구현 당시 코드 품질에 대한 기준이 부족했음을 보여주는 지점이라고 생각합니다. 앞으로는 기능 구현과 동시에 구조적 일관성, 역할 분리, 의미 있는 네이밍, 리팩토링 가능성을 염두에 두고 작업하는 습관을 들이고자 합니다. 좋은 코드란 단순히 작동하는 것이 아니라, 타인이 읽고 이해하고 수정할 수 있는 코드라는 점을 잊지 않겠습니다.
학습 효과 분석
- 가장 큰 배움이 있었던 부분: 바이브 코딩으로 빠르게 구현하면서도 가상돔 시스템의 전체 생명주기를 이해하게 되었습니다. createVNode로 가상노드 생성부터 normalizeVNode로 표준화, createElement로 실제 DOM 생성, updateElement로 업데이트까지 전체 흐름을 체계적으로 구현해보면서 프레임워크의 내부 동작 원리를 깊이 이해할 수 있었습니다.
- 추가 학습이 필요한 영역: 바이브 코딩으로 구현하다 보니 성능 최적화와 메모리 관리에 대한 고려가 부족했습니다. 현재 updateElement.js는 매우 길고, eventManager.js에서 이벤트 리스너 관리 시 메모리 누수 가능성과 대용량 데이터 처리 시 성능 이슈에 대한 개선이 필요합니다.
- 실무 적용 가능성: 바이브 코딩으로 구현했지만, 가상돔과 이벤트 위임의 기본 개념을 이해하게 되었습니다. 당장 실무에 적용하기는 어렵겠지만, 이런 기초 개념들을 알게 된 것이 앞으로 개발할 때 도움이 될 것 같습니다.
과제 피드백
- 과제에서 어려웠던 부분: 가상돔의 Diff 알고리즘 이해는 했지만 구현이 어려웠습니다. 특히 updateElement에서 5가지 케이스를 모두 처리하는 로직을 구현할 때 재귀 속 재귀가 계속 이어지고, 값에 따라 분류하기가 너무 힘들었습니다. 또한, 마치 암호문 같았던 "평탄화", "재귀적 표준화", "DocumentFragment" 같은 개념이 없어 처음 작업에 막막했었습니다.
- 과제에서 좋았던 부분: 테스트 통과도 있었지만, 개념을 이해할 수 있는 과정이 있어서 좋았습니다. 바이브 코딩으로 빠르게 구현하면서도 테스트 코드를 통과시키기 위해 노력하는 과정을 경험할 수 있었고, 특히 renderElement에서 최초 렌더링과 리렌더링을 구분하여 처리하는 요구사항을 만족시키면서 성능 최적화의 중요성을 깨달았습니다.
리뷰 받고 싶은 내용
- 재귀 함수 최적화: normalizeVNode에서 함수형 컴포넌트를 처리할 때 return normalizeVNode(result);로 재귀 호출을 하는데, 만약 컴포넌트가 깊게 중첩되어 있거나 무한 루프가 발생하면 스택 오버플로우가 일어날 수 있을 것 같습니다. 현재 구현에서는 이런 예외 상황에 대한 처리가 없어서 위험할 수 있다고 생각하는데, 실제로 문제가 될 가능성이 있는지와 개선 방안이 있는지 궁금합니다.
- (코드외 질문)바이브 코딩 후 학습 효과 높이기: 현재 AI 도움으로 빠르게 구현했지만 별로 남는 게 없는 것 같아서 고민입니다. 생소한 단어들을 적어두고, 구현을 다 하고 나서 요구사항이 어떻게 구현되었는지를 보는 식으로 접근했는데, 이런 방식이 효과적인지 확신이 서지 않습니다. 리뷰어님께서 비슷한 상황에 계셨다면 어떤 방식으로 학습을 진행하셨는지 궁금합니다. 이미 구현된 코드를 활용해서 학습 효과를 높일 수 있는 더 나은 방법이 있을까요?
과제 피드백
안녕하세요 지혜, 고생많았습니다. 이번 과제는 React의 핵심 원리인 가상 DOM과 diff 알고리즘을 직접 구현해보면서, 프레임워크가 어떻게 효율적인 렌더링을 수행하는지 이해하는 것이 목표였습니다. 특히 이론을 배우는게 아니라 구현을 통해서 배우는 것의 중요함을 경험했기를 바래요.
회고에서 "평탄화", "재귀적 표준화", "DocumentFragment" 같은 개념들을 처음에는 암호문처럼 느꼈다고 하셨는데, AI와 함께 구현하면서 이런 개념들이 왜 필요한지 체감하신 과정이 인상적이네요. updateElement에서 5가지 케이스를 모두 처리하는 로직을 구현하면서 DOM 조작의 복잡성을 이해하신 점이 좋았습니다.
코드를 살펴보니 이벤트 위임 시스템을 Map을 활용해 구현하고, boolean 속성들을 property로 처리하는 등 DOM API의 세부사항을 잘 이해하고 작성하셨네요. 다만 몇 가지 개선점이 보입니다. 예를 들어 updateChildren에서 Array.from($parent.childNodes)로 NodeList를 배열로 변환한 것은 좋은 판단이었지만, 대량의 DOM 조작 시 성능을 위해 DocumentFragment를 더 적극적으로 활용하면 좋겠습니다.
AI 의존도가 높았다고 고민하셨는데, 많은 친구들이 다들 고민하는 주제라고 생각해요. AI는 도구인데다가 내가 하는게 아니라 외주를 준다라고 생각하게 되면 AI가 어떻게 만들어 오던 관심이 없고 결과가 중요하니까요. 우리가 개발을 하는 거라면 결과중심어도 상관없겠지만 성장과 학습의 측면에서는 내가 직접해야 성장을 할 수 있으니까요. AI 의존적이라는게 나쁜 건 아니지만 본인게 아니라는 느낌이 더 크게 다가온다 생각합니다.
스스로 검증을 해보는 시간을 가벼보세요. 제일 쉬운 검증은 내가 AI를 이용했건 아니건간에 내가 만든걸 얼마나 구체적으로 남에게 설명할 수 있느냐로 확인 할 수 있습니다. 특히 육성으로 말해보는게 필요합니다. 녹음기를 통해 내가 작업한 결과를 말로 설명해보면서 내가 충분히 이해를 했는지 그렇지 않았는데 AI가 해준걸 본인이 이해하고 한 것처럼 착각하는지 판단할 수 있을거에요.
AI라는 멋진 도구를 잘 활용하고 학습하는 방법을 찾아내는 것도 현 시대를 살아가는 중요한 능력이라고 생각해요.
팀원들과의 소통도 좋은 방법입니다. AI는 정답이라 생각하는 것을 주지만, 동료들은 "왜 그게 정답인지", "다른 방법은 없는지" 같은 더 깊은 통찰을 생각하게 만들어주니까요.
수고하셨습니다. 2주차도 화이팅입니다! :)