20240813. TIL
코드가 복잡하지 않을 때,
페이지를 불러오는 상황에서는 잘 느껴지지 않지만
대형 프로젝트로 넘어가거나, 브라우저가 불러와야 할 JS파일의 크기가
크면 클수록 페이지의 로딩이 느린 것을 우리는 종종 볼 수 있다.
그 이유는 왜 그럴까?
오늘은 React의 성능 최적화에 대해서 알아보자!
💡 React의 성능 최적화?
리액트는 상태가 변화되면 리렌더링이 발생하는 기본적인 작동방식을 가지고 있어 특정 컴포넌트에 리렌더링이 발생하는 것을 흔히 볼 수 있다.
이는, 리렌더링이 되지 않아도 되는 컴포넌트나 표시되는 내용이 바뀌지 않는 컴포넌트도 함께 리렌더링이 되는 것이다.
그리고 페이지를 로딩할 때 JaveScript로 페이지를 그리기 때문에 첫 페이지 로딩이 너무 오래 걸린다는 단점이 있다.
➡️ 결국 React 기본 작동방식으로 인해 비효율적인 상황이 발생한다는 것을 볼 수 있다.
특히, 이는 함수형 컴포넌트를 사용할 때 자주 발생하는데 함수형 컴포넌트의 생명주기를 이해하고 있다면 설명이 된다.
✔️ 함수형 컴포넌트의 생명주기
- 만들어진 함수를 호출
- 함수를 화면에 렌더링
- 만들어진 함수에 상태변경이 발생
- 이전의 호출했던 함수는 사용하지 않고 새롭게 변경된 상태값으로 새롭게 함수를 만들어 호출함
- 상태가 변경되면 상태가 변경되기 이전에 사용되었던 기존의 함수는 사라지고 새로운 함수로 완전히 대체됨
- ➡️ 리렌더링 완료
이렇게 함수를 매번 렌더링 할 때마다 새롭게 호출한다는 것은 함수 내부의 변수들, 함수들이 재선언 되고 재할당 된다는 것이다.
💡 재사용할 수 있는 변수와, 함수들도 새로 만들어지고 사용하는 것이 강제된다.
그래서, 이런 비효율적인 상황에서 조금이나마 성능의 최적화를 하기 위해
변수와 함수를 재사용할 때 리렌더링이 일어나지 않도록 하는
useMemo( ), useCallback( )과 같은 React 최적화 함수들이 등장했다.
💡 useMemo( ) ?
- 함수의 호출 결과를 저장하기 위한 최적화 함수
- 함수 결과 값을 저장하여 결과가 달라진 게 없다면 함수를 호출하지 않고 그대로 사용이 가능하게 하는 함수
- ➡️ useMemo는 함수가 return 한 결과를 저장
- useMemo( ) 도 의존성 배열을 넣지 않을 경우 렌더링이 일어날 때마다 매번 함수가 실행되므로, 의존성 배열을 넣지 않는 것은 의미가 없다.
✔️ useMemo( )의 사용법
const 저장할_호출결과 = useMemo(() => {
return 함수 코드
}, [값])
✅ 배열의 값이 변하지 않았으면 함수를 다시 호출하지 않고, 기존 함수의 결괏값을 그대로 반환
✅ useMemo( )로 전달된 함수는 렌더링이 일어나는 동안 실행된다.
➡️ 렌더링이 일어나는 동안 실행돼서는 안 되는 작업을 useMemo( )에 담으면 안 된다.
ex) 서버에서 데이터를 받아오거나 수동으로 DOM을 변경하는 작업 ➡️ useEffect( ) 훅에서 실행돼야 할 사이드 이펙트
💡 useCallback( ) ?
- 함수를 저장하기 위한 최적화 함수
- 함수를 저장하여 의존성 배열의 값이 달라지면 저장한 함수를 반환한다.
- ➡️ useCallback( )은 함수를 반환한다.
- 함수 컴포넌트를 호출하면 컴포넌트 내부에서 선언되고 할당되는 함수를 새롭게 만드는 과정이 매번 렌더링 할 때마다 진행되기 때문에 이를 막기 위해 사용
✔️ useCallback( )의 사용법
const 저장할_함수 = useCallback(() => {
return 함수 코드
}, [값])
✅ 배열의 값이 변하지 않았으면 함수를 다시 만들지 않는다.
✅ useCallback( ) 훅을 사용하여 특정 변수의 값이 변한 경우에만 함수를 다시 정의하도록 해서 불필요한 반복 작업을 없애주는 것이다.
💡 React.memo( ) ?
- 컴포넌트를 저장하기 위한 함수
- memo( )로 감싸준 컴포넌트를 변수에 담아서 사용한다.
✔️ React.memo( )의 사용법
const 저장할_컴포넌트 = memo((props) => {
함수 컴포넌트 코드
})
✅ 컴포넌트를 호출해야 할 때, 전달받은 Props 값이 변하지 않았으면 함수를 호출하지 않는다.
⇒ props의 값이 변한 것이 아니면 리렌더링 하지 않는다.
✅ 전달받는 props가 같을 때에만 리렌더링을 방지해 준다.
- 참고자료
- 도서 ⎡소플의 처음 만난 리액트 - 리액트 기초와 핵심 개념을 가장 쉽게 알려 주는 입문자 가이드, 2판 - 지은이 이인제 ⎦