문제 상황해결 방안1) 헤더 렌더 최적화2) 몸상태 카테고리 렌더 최적화3) 선택된 몸상태 목록 렌더 최적화4) 몸상태 목록 렌더 최적화단일 몸상태 셀 렌더 최적화자주 선택한 몸상태 렌더 최적화결론
[Feature/#580] 몸상태 선택 스크린 퍼포먼스 최적화
문제 상황
나열되어 있는 몸상태 목록 중에서 선택을 하는 로직이다.
선택된 셀에만 변화가 생기면 되는데도 불구하고 몸상태를 하나 선택할 때마다 전체 목록이 다 리렌더링 되고 있는 상황이다.

세번의 몸상태 선택이 있었고, 따라서 총 세번의 몸상태 전체 리스트가 리렌더링 되었다.
한번당
59ms
가 소요되었다.몸상태 종류가 더 다양해질수록 더 큰 부하를 가져올 것이 분명하다.
그리고 알고케어 태블릿 사양인
Samsung A7 Light
태블릿 기준으로는 현재도 버벅임이 심한 상황이므로, 반드시 개선되어야 한다.해결 방안
UserMain
스크린의 전체적인 렌더링을 최적화 시키고자 한다. 하나씩 최적화 시켜보자.1) 헤더 렌더 최적화
프롭이 한번 설정된 후 바뀌지 않으니까
React.memo
로 감싸도록 하고 넘기면 되겠다.

헤더 타이틀과 GobackButton이 메모이징 된 것을 재활용하는 것을 확인할 수 있다.

UserMain
스크린 전체 관점에서 봤을 땐 아주 조금 최적화 되었다.2) 몸상태 카테고리 렌더 최적화

현재 보고있는 몸상태 카테고리를 나타내는
CategorySelector
컴포넌트를 렌더 최적화 시켜보자.카테고리를 선택하거나, 몸상태 목록 스크롤 시에 최상단에 위치한 카테고리 명으로 동기화 시킨다.
카테고리를 선택하거나, 스크롤 시 최상단에 위치한 카테고리명이 변경되기 전까지는 기존의 상태가 유지되기 때문에 메모이징된 컴포넌트를 쓰도록 변경하면 최적화의 의미가 충분히 클 수 있다.

몸상태만 선택했고, 따라서 카테고리 컴포넌트와 몸상태 선택 여부와는 연관성이 없다.
결과적으로 카테고리 컴포넌트에는 아무런 변화가 없는데도 몸상태 선택 시마다 계속 리렌더링 되고 있다는 의미다.
카테고리 컴포넌트의 코드를 보니 이미
React.memo
로 감싸진 상태임에도 왜 리렌더링이 될까?이유는
Memo
란에 마우스를 올려보면 알 수 있다. categories
라는 프롭이 변경되었기 때문이라고 한다.하지만 UI 상으로 봤을 땐 실제로 카테고리 개수나 텍스트가 변경되지 않았고 완전히 동일한 상태이므로, 매번 새로운 프롭으로 인식하도록 코드가 잘못 짜여있을 가능성이 크다.

아니나 다를까 매번 새로운 배열이 생성되며 레퍼런스가 달라지므로 compare 알고리즘 결과 프롭이 바뀌었다고 판단하고 리렌더링을 시키고 있었다.
따라서
categories
값을 useMemo
를 통해 메모이징된 연산결과를 프롭으로 전달하도록 수정하면 개선시킬 수 있다.
이젠 몸상태를 선택할 때에도, 스크롤을 할 때에도 메모이징된 결과물을 사용하도록 개선되었고,
categoryIndex
가 바뀌는 경우에만 리렌더링 된다.
UserList 스크린 전체 관점에선 빨간 부분이 개선되었다. 계속 개선시켜 보자.
3) 선택된 몸상태 목록
렌더 최적화

이번엔 선택된 몸상태 목록을 보여주는 컴포넌트의 렌더링을 개선시켜 보자.

선택된 몸상태를 취소시키는 목적으로 사용되는
unselectBodyCondition
함수가 useCallback
으로 감싸져있긴 하지만, 디펜던시를 보면 selectedConditionList
상태가 담겨있다.setSelectedConditionList
로 인해 상태를 변경시키므로 당연히 selectedConditionList
상태가 변경되는데, 상태값이 디펜던시에 포함되어 있으므로 useCallback
함수가 매번 새로운 함수가 생성되고, 함수의 reference가 변경되었으므로 새로운 프롭으로 간주하고 리렌더링하게 되는 것이다.일반적으로 setter 목적으로 쓰는 경우 따로 값을 참조할 이유가 없다.
setter 함수를 통해서도 이전 상태값을 얻을 수 있으므로, 직적접인 상태에 대한 디펜던시를 주지 않고도 이전 상태값을 참조하여 값을 변경하는 것이 가능하다. 이 점은 항상 유의해야 한다.

새로 추가되는 몸상태만 새롭게 렌더링되고, 나머지는 메모이징된 컴포넌트를 재활용하는 것을 볼 수 있다!
4) 몸상태 목록
렌더 최적화

렌더링 최적화가 가장 필요한 핵심 요소다.
몸상태 목록을 나열하며, 각각의 셀은 터치하여 선택할 수 있다.
선택된 단일 몸상태 셀 하나만 리렌더링이 되고, 나머지 몸상태 셀들은 메모이징된 컴포넌트를 재활용 하도록 하는 것이 이상적이다.

하지만 Profiler로 결과물에는 단일 셀을 선택할 때마다 전체 몸상태 리스트가 다시 렌더링 되는 끔찍한 모습이 담겨있다.
단일 몸상태 셀 렌더 최적화

선택하지 않은 몸상태들은 왜 리렌더링 될까? Profiler에서 보면
onPressCell
함수가 변했기 때문이라고 한다.사실상 몸상태 선택에 따른 동작이 바뀌는 건 아니라서 함수는 동일해야하는데 왜 다르다고 인식하는 걸까?
useCallback
은 당연히 선언해서 넘겨줬는데 왜 이런지 원인을 찾아보자.…

유저의 선택에 의해 심각도가 변경되는 몸상태만 리렌더링 되고, 나머진 메모이징된 컴포넌트를 재활용하는 것을 볼 수 있다! 최적화 완료!
자주 선택한 몸상태 렌더 최적화
자주 선택한 몸상태는 다른 몸상태 카테고리의 값을 참조하도록 하는 별도의 가공 로직을 거친다.
그 과정의 영향이 렌더링에도 영향을 주는 것 같다.

자주 선택한 몸상태 셀의
info
프롭이 바뀌어서라고 한다. 왜 바뀌는지 확인해서 메모된 데이터를 쓰도록 바꾸자.
…
이하 생략
…