일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- CSS
- 웹퍼블리셔
- JS
- 리액트
- github
- jQuery
- 깃
- 세로메뉴바
- 코딩독학
- PROJECT
- web
- JavaScript
- git
- 비전공자
- 웹디자인기능사
- 연산자
- 렛츠기릿자바스크립트
- HTML
- 생활코딩
- Supabase
- 실기
- 프론트엔드
- 웹디실기
- 자바스크립트
- react
- 슬라이드전환
- 타입스크립트
- 웹디자인기능사실기
- 코드공유
- 정보처리기사
- Today
- Total
코딩하는라민
[React] 컴포넌트 최적화를 위한 React.memo 본문
[React] 컴포넌트 최적화를 위한 React.memo
React.memo 란?
`React.memo` 는 고차컴포넌트(HOC)로 컴포넌트 자체를 `메모이제이션`한다.
컴포넌트의 props 가 바뀌지 않은 경우, 리렌더링을 방지해 컴포넌트의 성능을 향상시킬 수 있다. 컴포넌트의 props 가 변한다면 다시 리렌더링된다.
사용방법
사용 방법은 간단하다. 리렌더링을 막고자 하는 컴포넌트를 `memo` 로 감싸주면 된다.
props 가 없는 컴포넌트도 사용이 가능하다.
import { memo } from 'react'
function MyComponent(props) {
return (
<>
<h1>{props.title}</h1>
<p>{props.content}</p>
</>
)
}
export default memo(MyComponent)
memo 를 사용하면 부모 컴포넌트가 리렌더링 되더라도 props 의 변화가 없다면 자식 컴포넌트는 리렌더링되지 않는다.
메모이제이션
memo 는 컴포넌트 자체를 기억해놨다가 props 가 이전과 같다면 기억해둔 컴포넌트의 결과를 반환한다.
즉, props, state, context 가 변경되지 않았다면 동일한 결과를 반환해야한다.
이를 `메모이제이션` 방식이라고 할 수 있다.
memo 를 사용해도 컴포넌트가 리렌더링되는 경우
memo 로 wrapping 된 컴포넌트는 props 가 변경되지 않는 한 리렌더링 되지 않는다.
하지만,
전역 상태 관리 도구를 사용하는 경우 state 가 변경될 때마다 해당 컴포넌트가 리렌더링된다.
이는 컴포넌트가 전역 state 에 의존하기 때문이다.
이 경우 전역 state 를 자식 컴포넌트의 props 로 내려주고, 자식 컴포넌트는 memo 로 감싸주면 된다.
전역 state 는 그 값이 변경되지 않더라도 해당 state 에 영향받는 컴포넌트를 리렌더링한다. 하지만 자식 컴포넌트로 전역 state 를 props 로 내려준다면, 자식 컴포넌트는 props 가 변경되지 않는 경우에는 리렌더링을 막을 수 있다.
// src/App.tsx
import Children from '@/components/Children'
import { useContext } from 'react'
const App = () => {
const { count } = useContext(MyCount)
return (
<div>
<h1>Parent Component</h1>
<Children count ={count} />
</div>
)
}
// src/components/Children.tsx
import { memo } from 'react'
const Children = ({ count }) => {
return (
<div>
<span>props: {count}</span>
</div>
)
}
export default memo(Children)
React.memo 를 사용하지 않아도 되는 경우
정적 컴포넌트
단순한 정적 컴포넌트의 경우에는 memo 를 사용하지 않아도 된다.
정적 컴포넌트란 컴포넌트의 상태가 props 에 의존하지 않고, 항상 동일한 결과를 반환하는 경우를 말한다.
렌더링이 적은 컴포넌트
렌더링이 자주 일어나지 않는 컴포넌트의 경우에도 memo 를 사용할 필요가 없다. 렌더링 비용이 크지 않은 경우에는 memo 를 사용해도 큰 차이가 없기 때문이다.
상위 컴포넌트에서 최적화한 경우
상위 컴포넌트에서 불필요한 리렌더링을 최적화할 수 있는 경우에도 자식 컴포넌트에 memo 를 사용하지 않아도 될 수 있다. 상위 컴포넌트에서 state 를 메모이제이션해서 props 로 넘겨주면 된다.
props 가 계속해서 변경되는 경우
props 가 계속해서 변경되는 경우라면 memo 를 사용해봤자 지속적인 리렌더링이 일어날 것이다. 따라서 이 경우에도 memo 를 사용할 필요가 없다.
오히려 리렌더링이 빈번할 경우 memo 를 사용한다면 불필요한 메모리를 사용할 수 있다.
익명 컴포넌트 ESLint 경고
memo 를 사용하다 아래와 같은 ESLint 경고 문구가 뜨는 경우가 있다.
const Components = () => {
...
}
export default memo(Components) // 💡Fast refresh can't handle anonymous components. Add a name to your export.
이는 익명 컴포넌트를 처리할 수 없을 때 발생하는 오류로 `.eslintrc.cjs` 파일을 조금 수정해주면 해결된다.
rules: {
'react-refresh/only-export-components': "off"
},
만약 ESLint 설정을 바꾸지 않고 싶은 경우 아래와 같이 하면 경고는 사라진다.
const BaseComponents = () => {
...
}
const Components = memo(BaseComponents)
export default Components
마치며
`React.memo` 는 컴포넌트 자체를 메모이제이션한다.
컴포넌트의 props 가 변경되지 않으면 메모이제이션 했던 결과값을 사용하고, props 가 변경되었다면 새로운 값을 반환한다. React.memo 를 사용하지 않아도 되는 경우에 useCallback 으로 해결 가능한 경우가 있다.
`useCallback` 은 함수 자체를 메모이제이션하여 동일한 인스턴스를 재사용한다.
주로 자식 컴포넌트에 전달되는 콜백함수가 자주 변경되는 경우 사용한다.
React.memo 와 이름이 유사한 `useMemo` 는 함수의 결과값을 메모이제이션하여 이전에 계산된 결과를 재사용한다. 주로 복잡한 계산 결과를 저장할 때 사용한다. memo 와 유사하지만 useMemo 는 hook 이고, memo 는 HOC 라는 차이점이 있다.
참고
'Core > React' 카테고리의 다른 글
[React] useModal Hook 여러 개의 모달 관리하기 (58) | 2024.05.02 |
---|---|
[React] React Portal 사용하기 (58) | 2024.04.30 |
[React] React-Router <NavLink> 컴포넌트 VS <Link> 컴포넌트 (61) | 2024.04.23 |
[React] Axios instance 와 interceptors 로 Axios 효율성 높이기 (41) | 2024.02.05 |
[React] React 에서 Axios 사용하기 (75) | 2024.02.04 |