[React] 성능 최적화 전략
메모이제이션
메모이제이션은 비용이 많이 드는 함수 호출의 결과를 저장하고, 동일한 입력이 발생 할 때 재사용하여, 불필요한 리렌더링을 방지하고, 렌더링 성능을 향상시킨다.
- useCallback()
useCallback 을 통해 함수를 만든다면, 해당 함수를 저장해두는 역할을 한다.
아래 예제의 App() 이 재실행되면 해당 함수가 재생성 되지 않는다.
첫번째 인자로 function , 두번째 인자로 useEffect 와 같이 dependency 배열을 넣는다.
빈배열 일 경우, 어떠한 경우에도 해당 함수가 변경되지 않음을 뜻한다.
function App() {
const [callbackTest, setCallbackTest] = useState(false)
// useCallback()
const onHandleClick = useCallback(() => {
setCallbackTest(callbackTest => !callbackTest)
}, [])
return (
<div>
<button onClick={onHandleClick}>버튼</button>
</div>
)
}
- React.memo()
컴포넌트가 가진 props 가 변경되었을 경우에만 재실행한다.
export 시 React.memo() 로 묶어준다.
const MemoComponent(props) => {
return ...
}
export default React.memo(MemoComponent)
리액트는 state 가 변경되면 관련된 모든 컴포넌트가 리렌더링 된다.
부모 컴포넌트가 바뀌게 되면 모든 자식은 리렌더링 된다는 뜻인데, 큰 단위의 프로젝트에서는 성능 저하를 일으 킬 수 있다.
컴포넌트가 리렌더링 되는 경우는 아래 포스팅을 참고하자.
[React] 렌더링
1. 렌더링? 리액트 컴포넌트가 가지고 있는 props , state 등의 상태를 어떻게 UI 를 구성할 지, 컴포넌트에게 작업을 요청하는 행위 리액트가 렌더링 되는 부분은 public/index.html 파일과 src/index.tsx 파
just-take-the-first-step.tistory.com
- useMemo()
useMemo 는 컴포넌트가 리렌더링 될 때, 내부에 있는 모든 코드를 리렌더링 하고 싶지 않을 때 사용한다.
useMemo 는 useCallback 이 함수를 저장 한 것과 같이 특정 값을 저장한다. ( useMemo 리턴 값 저장 )
첫번째 인자로 function , 두번째 인자로 useEffect 와 같이 dependency 배열을 넣는다.
빈배열 일 경우, 마운트 될 때의 값을 게산하고 그 이후로는 메모이제이션 된 값을 계속 사용한다.
function App() {
const memoItem = useMemo(() => {
//할일
return memoObj
}, [])
return ...
}
React.lazy / Suspense
리액트는 코드 분할과 지연 로딩을 지원합니다. 코드 분할은 필요한 경우에만 로드 할 수 있는 작은 정크로 분할 하는데 도움이 주고, 지연 로딩은 컴포넌트가 필요한 경우에만 로드 할 수 있도록 하여, 초기 번들 크기를 줄이고 성능을 향상시킨다.
불필요한 래퍼 요소 줄이기
불필요한 래퍼 요소를 피하고, DOM 노드 수를 줄이려면 React.Fragment 를 사용하자.
컴포넌트 맵핑 Key 값 확인
리액트에서는 반복 렌더링을 진행 할 때 Key 값을 필수로 부여 하게 되어있다. 이 떄 Key 값을 index 를 사용하게 되면, 리스트 데이터가 추가 혹은 삭제 될 경우 index 가 꼬이면서 강제 리렌더링이 발생한다.
데이터의 고유 id 값을 부여하자.
배열이 단순 렌더링만 담당한다면, index 를 사용하여도 무방하다.