목표
- 로딩 성능 최적화
- 렌더링 성능 최적화
- Layout Shift 피하기
- useSelector 렌더링 문제 해결
- Redux Reselect를 통한 렌더링 최적화
- 병목 함수에 memoization 적용
- 병목 함수 로직 개선하기
실습툴
성능 최적화
Layout Shift 피하기
Layout Shift란?
🤔 Layout Shift
화면상에서 요소들이 어떤 요인에 의해서 사이즈가 바뀌거나 위치가 바뀌는 현상 (=위치나 사이즈를 다시 계산해야 한다는 것. 사용성 저하)

Layout Shift 원인?!
- 사이즈가 정해져 있지 않은 이미지
- 사이즈가 정해져 있지 않은 광고
- 동적으로 삽입된 컨텐츠
- Web font(FOIT, FOUT)
Lighthouse에서 Layout Shift 확인해보기
- 0~1 사이의 수치를 가지는데, 1은 모든 것이 변했다 라는 의미..

- 이미지의 사이즈가 정해지지 않은 것도 확인이 된다
- 💡이미지 요소에 명시적인 너비 및 높이를 설정하면 레이아웃 변경 횟수를 줄이고 누적 레이아웃 변경을 개선할 수 있다 (=Layout Shift 개선!)

코드 개선하기
정적 사이즈를 적용하게 되면 반응형에서는 개선하기 어렵기 때문에 이미지의 사이즈를 비율에 맞게 변경하기
-
변경 전

-
변경 후
- 이미지가 로딩되기 전 이미지가 위치해야 할 자리만큼 패딩이 자리하기 코드를 개선하고
- 이미지가 로딩되면 패딩의 위치 위에 올리게끔 코드 개선

이미지 지연(lazy) 로딩
스크롤이벤트로 동작하는 라이브러리
npm install --save react-lazyload
코드 개선하기

useSelector 렌더링 문제 해결
components 탭으로 렌더링 시점 체크해보기
어떤 타이밍에 어떤 컴포넌트가 렌더링 되는지 확인 가능
불필요한 재렌더링 원인 파악하기
- 자세히 살펴보면 모달창을 띄웠을 때 의도하지 않게 모달 뒤의 이미지들도 재렌더링 되고 있는 것이 확인된다 😰
- 이렇게 불필요한 렌더링이 발생하는 이유는
- 이미지들과 모달이 redux로 연결되어 있고
- redux의 상태가 바뀌면서 구독하고 있는 이미지와 모달이 변경되기 때문..

useSelector 문제 해결 방법
- Object를 새로 만들지 않도록 State 쪼개기
- 새로운 Equality Function 사용
- 기본적으로 useSelector는 단순 비교를 한다
- object 형태로도 비교가 가능하게끔 두 번쨰 인자로 Equality Function 사용할 수 있다
코드 개선하기
Object를 새로 만들지 않도록 State 쪼개기
새로운 Equality Function 사용
- 변경 후: react-redux에서 제공하는 shallowEqual 함수를 두 번째 인자로 추가

그외
- useSelector 내부에서 filter 함수를 처리하지 말고! 밖으로 빼서 처리해야 불필요한 렌더링을 방지할 수 있다

Redux Reselect를 통한 렌더링 최적화
개선점 파악
- category는 렌더링에 불필요한 값. 꼭 useSelector로 가져와야 하나?
- category, allPhotos, loading 외의 값이 추가되어 추가된 값으로 렌더링이 필요할 경우, photos를 계산하는 값이 필요하지 않는 상황임에도 photos는 연산하게 되는 문제점 발생

Reselect는 memoization 기법을 사용해서 함수에 똑같은 인자가 들어오면 결과값을 미리 캐싱된 값으로 반환해주는 라이브러리
설치
npm install reselect
yarn add reselect
사용법
const selectFilteredPhotos = createSelector(
[가져올 값들],
(가져온 값들) => {
로직
}
);
코드 개선하기
