해당 페이지의 내용으로 08월 29일 TIL의 내용 중 일부를 가져왔다.
이 때는 이 전에 진행했던 투두리스트 정도의 스펙만 생각을 하고 CSS를 신경 쓰지 않고 기능 구현에만 초점을 두고 구현을 시작하였다!
실제로 구현을 많이 했다고 했지만.. API 요청 부분
과 트리 구조를 그리는 기능
만 구현되어 있었다..ㅎㅎ
기능 구현 도중, 추후 CSS를 입힐 생각을 하니 아래와 같은 문제점이 생겼다.
노션은 생각보다 복잡한 UI로 이루어져 있었고, html에 태그를 작성하여 개발하는 환경이 아닌 오로지 JS로만 태그들을 생성하고 스타일링 해야하는 상황이기 때문에 복잡한 UI일 수록, 컴포넌트 코드의 길이가 길어지고 추후 유지보수의 문제가 생길 것 같다는 생각을 했다.
하루동안 열심히 삽질을 하고 30일인 바로 다음날 프로젝트의 구조 자체를 전부 다시 정의하고 새롭게 만들기로 마음먹었다!
오로지 UI를 위해 리팩토리를 결정한 터라, 명확한 UI의 구조를 짜는 것을 목표로 했다. 하지만 마크업에 대한 이해도가 아직 부족하고 잘 못하는 상황에서 짜야했기 때문에 처음 시작은 막막했다.
"이런 경우 어떤걸 참고해야할까?" 고민을 하였고 그 결과, 부트스트랩
이라는 UI 라이브러리를 떠올렸다!
물론 부트스트랩을 가져다 사용하면 좋겠지만, 되도록이면 라이브러리 사용없이 진행을 해보고 싶어서 CSS 명과 태그들의 구조들을 참고하여 컴포넌트들의 구조를 생각하기 시작했다.
전체적인 틀을 먼저 생각을 하고, 각 컴포넌트의 역할과 구조를 분명히 정의함과 동시에 클래스 명까지 반영된 프로젝트의 초안을 작성했다!
< 이벤트 흐름을 표현한 이미지 >
< state 흐름을 표현한 이미지 >
그런데 위와 같이 너무 세분화를 시켜서 그런지.. 컴포넌트 갯수와 관계없이 이벤트를 계속 위로 올리는 형태의 구조가 되어 버렸다.. 나는 이러한 구조를 비효율적이라 생각을 했고 프로젝트에 잘못 접근했다는 생각이 들어 현재 React에서는 어떻게 관리하고 있는지 찾아보게 되었다.
찾아보니 Redux
라는 개념이 있었고 이걸 이해하고 코드로 구현을 하고 싶었지만..^^ 아쉽게도 리액트는 해본 적이 없어 짧은 시간내에 해당 형태로 구현하기는 힘들었다.. 대신 잠시 배웠던 Vuex
와 EventBus
를 차용하면 어떨까? 라는 생각을 했다!
"상태 관리"라는 키워드에서 Store
를 떠올렸고, "이벤트 전달"이라는 키워드에서 EventBus
를 떠올렸다.
Vuex와 EventBus를 떠올린 이유
dispatchEvent
와 addEventListener
를 이용하여 App컴포넌트로 바로 이벤트를 주는 방법이 있었지만, 이렇게 되면 이벤트의 흐름과 로직 파악이 어려워질 것 같다고 생각을 했다.위의 과정을 거쳐 생각해낸 스토어의 역할은 하위 컴포넌트와 APP 컴포넌트를 연결시켜주는 일종의 미들웨어 같은 역할을 하고 있다. 하위 컴포넌트에서 해당하는 액션을 호출하면 store는 데이터를 가공하여 app에게 전달해주는 형태로 구현하였다.
다양한 이벤트를 보내야 하기 때문에 이벤트를 받는 쪽은 on
, 이벤트를 보내는 쪽은 emit
이라는 객체를 만들어 이벤트를 받는 쪽인지 보내는 쪽인지 더 명확하게 표현하고 단위를 구분지었다.
store를 활용하여 변경된 이벤트 로직은 아래와 같다.
emit
(발생)on
(감지)action
을 호출action
을 통해 상태를 가공commit
하위 컴포넌트에서 이벤트가 발생하여 store
로 이벤트를 실행
해당하는 액션을 dispatch
라는 함수를 통해 호출
2_1. API Request option
을 getter
함수에 전달하여 호출
2_2. Store
는 option이 반영된 Next State
값을 받음
Setter
함수에 Next State
통신 이후 동기적으로 결과를 반영 + App
의 상태를 업데이트 시킬 수 있는 mutation
에 결과를 commit
mutation
은 다시 emit
을 이용하여 App
컴포넌트로 바뀐 상태 값을 전달전체적인 순서는 아래와 같다.
App
은 전달받은 state
를 현재 state
값으로 변경하고 하위 컴포넌트들에게 전달하게 된다.
위와 같이 데이터를 다루는 부분의 레이어를 나눠두어 예외처리, 방어코드, 디버깅을 보다 쉽게 하였다!
API 통신을 기다린 뒤, UI에 반영하면 살짝 딜레이가 발생하기 때문에 낙관적 업데이트
를 진행하였다.
낙관적 업데이트? 서버요청이 성공한다는 가정하에 변경 사항을 반영한 화면의 렌더링을 먼저 하고 서버요청을 보내는 방식
문서가 생성되고 생성된 문서의 번호를 받은 뒤, 번호를 부여하는 부분과 같이 비동기로 처리되어야 하는 로직은 setter
함수에 정의하였다.
Store
생성APP
에서 전달받은 데이터에 의해 선택적 렌더링UI
동기 처리store
에 emit
으로 이벤트 전달element
요소에 addEventListener
로 부모의 이벤트 바인딩state
변경을 위한 모든 이벤트들을 관리UI
로직 실행App
에 변경된 최신 상태값을 전달UI
로직에서의 방어코드 강화API, LocalStorage
사용 등 실제 데이터 처리하는 부분의 방어코드 강화결국 목표했던 방향으로 구현하고 멘토님께 칭찬의 말씀도 들었다...!! 🥰🥰
컴포넌트 방식의 바닐라JS로는 처음 프로젝트를 진행해보았는데 Vuex
나 Eventbus
와 같은 개념들을 차용하여 내 손으로 직접 구현했다는 것이 너무 신기했고 많이 성장했다는 것이 느껴지는 프로젝트였다! 멘토님께 받은 피드백을 반영하여 앞으로도 꾸준히 디벨롭할 예정이다!!
우와 열심히하신게 느껴지네요~
공부하신 부분을 잘 설명하실 수 있다는 것도 멋집니다!
수고하셨습니다 ~~~😊👍