일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- Front-End
- 렌더링
- lifting state up
- 배칭
- react rendering
- react code splitting
- 프론트엔드
- Next.js
- NextJS
- 렌더링 동작원리
- mapped types
- 상태 끌어올리기
- 타스
- TypeScript
- 타입스크립트
- React
- useMemo
- 리액트
- 리액트 코드분할
- router dom
- react router dom v6
- useCallback
- state 최적화
- 고급타입
- 자동 배칭
- TS
- Interface
- rendering
- 자바스크립트
- JavaScript
- Today
- Total
서녕이네 개발단지
[React] 렌더링 최적화 본문
React를 사용하면 렌더링 성능에 대해 고민을 해야 하는데,
렌더링 최적화 방법은 다양하겠지만 현재 내가 아는 최적화 방법을 몇 가지 적어보려고 한다.
많이 써보지 않아 익숙하지 않은 친구들이다.
📄 목차
1. map 함수를 사용 시 key값의 중요성
2. React.memo()
3. useMemo()
4. React.memo()와 useMemo()의 공통점, 차이점
5. useCallback()
⭐️리액트 렌더링 최적화 방법?
map함수를 사용 시 key값의 중요성
map함수를 사용시 key값에 index를 넣는 경우가 많다. 하지만 이는 리렌더링을 발생시키기 때문에 좋지 않다.
React에서는 컴포넌트들을 맵핑할 때, 고유의 key 값을 부여할 것을 강제하고 있다. 이때, key값에 index를 사용하는 것을 지양해야 한다.
❗️그 이유를 알아보자!
이유는 간단하다 추가 혹은 삭제를 진행하면 index가 변경하면서 기존의 map에 연결되어 있는 key가 끊어지고 배열의 모든 요소에 리렌더링을 진행한다고 생각하면 이해하기 쉽다.
리스트 데이터에 아이템이 추가/삭제되었을 때를 생각하면 그 이유를 알 수 있다.
아이템이 중간에서 추가/삭제되면, 그 이후의 아이템 컴포넌트들의 index가 바뀌므로 key값이 바뀜에 따라 리렌더링이 발생하게 된다.
또한, 이러한 반복적인 데이터 조작으로 index가 순간적으로 꼬이면서 오류를 유발할 수 있다.
💡 가급적이면 데이터의 id 등 고유값을 key에 넣기를 권장하나, 아래와 같은 경우엔 index를 써도 무방하다.
- 배열과 각 요소가 수정, 삭제, 추가 등의 기능이 없는 단순 렌더링만 담당하는 경우
- id로 쓸만한 unique 값이 없을 경우
- 정렬 혹은 필터 요소가 없어야 함
React.memo()
React.memo()는컴포넌트를 랩핑 하여 메모이제이션 하고, props가 바뀌지 않으면 리렌더링을 방지하는 함수이다.
기본적인 문법은 아래와 같다.
컴포넌트를 React.memo()로 감싸며, 첫 번째 인자는 컴포넌트, 두 번째 인자는 콜백함수(리렌더 조건)를 받는다.
React.memo는 Higher-Order Components(HOC)이다.
❓Higher-Order Components(HOC)란?
컴포넌트를 인자로 받아 새로운 컴포넌트롤 다시 return해주는 함수이다.
React.memo는 오직 props가 변경됐는지 아닌지만 체크한다. 만약 React.memo에 감싸진 함수형 컴포넌트가 함수 내부에서 useState나 useContext 같은 훅을 사용하고 있다면, state나 context가 변경될 때마다 리렌더링 된다.
const ExampleComponent = React.memo(({...props}) => {
return (
//HTML 태그
)
}, (prevProps, nextProps) => {
if('리렌더링 해야하는 조건') {
return false;
}
return true;
})
useMemo()
useMemo는 성능 최적화를 시킬 수 있는 대표적인 리액트 훅이다. useMemo에서 Memo는 메모이제이션(memoization)을 의미한다.
메모이제이션(memoization) 란 컴퓨터가 동일한 계산을 반복해야 할 때, 이전의 값을 메모리에 저장함으로써 불필요한 연산을 줄여 성능 최적화를 한다. 간단하게 말해서 useMemo는 값을 기억한다고 생각하자 컴포넌트는 state가 변경되면 리렌더링이 된다. 하지만 값을 변경하지 않았는데 리렌더링은 불필요하다. 이럴 때 useMemo를 통해 리렌더링을 막아 최적화를 할 수 있다.
💡 하지만 필요할 때만 써야 하는 훅함수이다. 메모이제이션을 하기 때문에 불필요한 저장을 할 수 있다는 점이 있다.
React.memo()와 useMemo()의 공통점, 차이점
❗️ 공통점
React.memo와 useMemo 모두 props가 변하지 않으면(이전 props와 동일하면) 인자로 넘긴 함수는 재실행되지 않고, 이전의 메모이즈 된 결과를 반환한다는 점에서 공통점이 있다.
❗️차이점
React.memo는 HOC, useMemo는 hook이다.
React.memo는 HOC이기 때문에 클래스형 컴포넌트, 함수형 컴포넌트 모두 사용 가능하지만, useMemo는 hook이기 때문에 오직 함수형 컴포넌트 안에서만 사용 가능하다.
useCallback()
useCallback은 메모이제이션된 함수를 반환한다. useCallback은 useMemo와 비슷하다 하지만 다른 점을 보자면, useMemo는 함수의 값을 반환 useCallback은 함수 자체를 반환한다는 차이가 존재한다. 첫 번째 인자에 값을 연산하고 반환하는 함수를 넣고 두 번째 인자에는 의존성 배열을 넣는다.
💡 그러나 useMemo와 useCallback 같은 경우는 언제나 써도 괜찮을까?라는 의문이 생긴다. 그것에 대한 대답은 '아니다'라는 답변이다. kentcdodds blog에서 참고한 글이다. 성능 최적화는 자유롭지 않다. 그들은 언제나 비용이 들지만 항상 비용을 상쇄할 만큼 이익을 가져다주지는 않는다. 잘못사용하면 가독성 부분도 떨어지고, 메모리를 낭비하기 때문에 모든 상황에 어울리는 녀석은 아니다!
참고
'프론트엔드 > React' 카테고리의 다른 글
[React] Code Splitting (코드 분할) (0) | 2023.06.11 |
---|---|
[React] Lazy Loading (지연 로딩), Suspense (서스펜스) (0) | 2023.06.11 |
[React] Rendering (렌더링 동작원리)(2) (0) | 2023.06.10 |
[React] Rendering (렌더링 동작원리)(1) (1) | 2023.06.10 |
[React] Virtual Dom(가상 돔) (2) | 2023.06.09 |