거의 업데이트 시에만 1초, 잔상이 보이는 현상만 0.5초로 해서 총 1.5초의 시간이 소요된다.
원인 - useEffect 지옥
원인을 탐색한 결과, useEffect에서 비동기가 동시에 호출되는 것이 원인이었다.
useTaskHIstories는 다양한 블록에서 나온다.
이때 useEffect가 초기에 발생하는 로직이 함수 내부에 존재하는데, 이 함수가 async - await로 호출하는 것이 문제였다.
따라서 약 11개의 블록이 존재하면, await 로직에서의 값 * 11이 반드시 소요 시간에 반영되는 것이었다.
그러나 useTaskHistories를 삭제하기에는, 재사용하는 컴포넌트들에서 요긴하게 쓰여지고 있어서, 이를 해결해야 했다.
해결 - 모듈의 세부 역할에 따른 분리 및 전역 상태 관리
useTemplateTasksInit이라는 커스텀 훅을 추가로 만들었다.
이는 초기에 만들어질 tasks를 딱 한 번만 렌더링하기 위함이다.
(indexedDB에 필요한 건데, react-query를 쓸지말지는 고민 중이다. 흠.)
또한, atom으로 pageDB에 관한 상태들을 전역에 관리함으로써 재사용하는 곳에서 굳이 비동기로 호출하지 않도록 만들었다.
결과적으로 업데이트할 때마다 약 22번씩 나오는 useEffect의 side effect를 초기 4번까지 줄여냈으므로 성능 개선이라고도 할 수 있다.
💌 설명
어떻게 보면 성능 개선일 수도 있고, 버그 개선일 수도 있는 아이러니한
feature
였다. 사실 버그로 보는 것이 타당하다. 이유는, 첫 렌더링이 느린 이유를 탐색한 결과,pageDB.current
의 렌더 여부가 먹지 않았던 것이 원인이었다.TL;DR
📎 관련 이슈
💡 논의해볼 사항
What is problem?
여태까지 모르고 있었는데, 초기 생성이 느리다고 판단한 것은 순전히 버그 때문이었다. 지금까지의 버그는 다음과 같이 렌더링이 마치 자동으로 되는 것처럼 착각하게 만들었다.
pageDB
가 마운트가 된다. 이때null
값을 갖고 있다.null
이다.db
에 접근 가능한 주소값을 가지고 있다.useRef
는 리렌더링을 유발하지 않는다. 따라서 리턴 값을 반환하지 않는다.mousemove
를 할 때 window의 값을 가져와야 되고, 이것이 적힌 page의 상태 전체가 리렌더링된다. 이때ref
값을 다시 가져와서 db에서tasks
를 꺼내게 되는 것이다.보통 테스트를 할 때 마우스를 움직이기 때문에, 자동으로 되는 줄 알았던 블록 렌더링이, 알고 보니 수동으로 되던 상황이었다. 따라서 6번을 최대한 빠르게 작동하도록 마우스를 요리조리 움직이면, 사실 지금의 성능보다 더 빠른 상황이 나온다(?!)
하지만 버그는 버그.
pageDB
의 업데이트를 알리는isMount
를 넣는다면?이는 생성에서 매우 빠르게 렌더링된다. 즉 여기까지만 보면 생성 로직에 관한 업데이트 로직은 최적화할 필요가 없다는 결론이 나온다 하지만 진짜 문제는 다음이다.
잠깐, 수정하는 데 뭔가 이상한 걸...?
이는 영상으로 대체하려 한다. 보면 알 것이다. 매우 끊기는 현상과 업데이트 직전에서의 상태들이 잔상처럼 보이는 게 반복되어, 매우 불편한 UX를 가져오고 있다.
https://user-images.githubusercontent.com/78713176/220877583-99e8da43-fa6f-4974-9da9-b32da8fba8f8.mov
거의 업데이트 시에만 1초, 잔상이 보이는 현상만 0.5초로 해서 총 1.5초의 시간이 소요된다.
원인 -
useEffect 지옥
원인을 탐색한 결과,
useEffect
에서 비동기가 동시에 호출되는 것이 원인이었다.useTaskHIstories
는 다양한 블록에서 나온다. 이때useEffect
가 초기에 발생하는 로직이 함수 내부에 존재하는데, 이 함수가async - await
로 호출하는 것이 문제였다. 따라서 약 11개의 블록이 존재하면,await
로직에서의 값 * 11이 반드시 소요 시간에 반영되는 것이었다. 그러나useTaskHistories
를 삭제하기에는, 재사용하는 컴포넌트들에서 요긴하게 쓰여지고 있어서, 이를 해결해야 했다.해결 - 모듈의 세부 역할에 따른 분리 및 전역 상태 관리
useTemplateTasksInit
이라는 커스텀 훅을 추가로 만들었다. 이는 초기에 만들어질tasks
를 딱 한 번만 렌더링하기 위함이다. (indexedDB
에 필요한 건데,react-query
를 쓸지말지는 고민 중이다. 흠.)또한,
atom
으로 pageDB에 관한 상태들을 전역에 관리함으로써 재사용하는 곳에서 굳이 비동기로 호출하지 않도록 만들었다. 결과적으로 업데이트할 때마다 약 22번씩 나오는useEffect
의 side effect를 초기 4번까지 줄여냈으므로 성능 개선이라고도 할 수 있다.변경 결과를 보면, 변경 시 깔끔한 것을 알 수 있다! https://user-images.githubusercontent.com/78713176/220882062-e5cd2e05-d935-4ea3-aa8b-ac208a925184.mov
추가 1. 타입 재사용
models
에,indexedDB
를 사용하면서 반복되어 사용될 것 같은 타입들을 모두 넣어 재사용하였다.추가 2.
useEffect
최적화8번 렌더링되는 로직을,
useEffect
가 넣어지는 렉시컬 환경을 고려하며 최적화한 결과 약 50%(4번)만 리렌더링되도록 성능을 개선했다. (useEffect를 한데 모으기에는 초기에 설정되어야 하는 상태값들이 독립적이어서, 더이상 최적화는 불가능하다.)📝 참고자료
⚠️ 잠깐! 한 번 체크해주세요.