💡 불변성이 필요한 이유는 무엇일까?
- 렌더링 최적화
- React.memo()
- useCallback()
- useMemo()
- 상태 변경 추적
- Redux(immer)
- Zustand(immer)
- Recoil(immutable)
✔️ 여기서 immer는 불변성 라이브러리 이다.
1. 렌더링 최적화에 불변성이 필요한 이유
- 컴포넌트 트리에서 상태, 속성이 변경된 것이 있을 때만 가상 DOM에 대한 렌더링을 해야 한다.
- 이전 상태 객체와 현재 상태 객체를 비교하여 렌더링 여부를 판단
- Deep Compare(X) → Shallow Compare(O)
- 불변성을 사용하지 않았다면 Shallow Compare 는 불가능 했을 것
- ✨불변성 라이브러리를 이용하면 shallow compare로 결정한다.
💡 Deep Compare란?
re-render 할지 여부를 결정하기 위해 객체의 트리를 따라 내려가면서 모두 비교한다. → 성능 저하
💡 shallow compare
re-render 할지 여부를 결정하기 위해 속성으로 전달받은 객체의 메모리 주소만 비교한다.
2. 상태와 렌더링
- 리액트에서 상태(state)가 변경되면 UI가 렌더링 된다.
- 상태를 변경하기 위해 setter 메서드를 사용한다.
- setter 메서드는 상태만 변경하는 것이 아니라 상태를 보유한 컴포넌트가 re-render되게 한다.
- 자식 컴포넌트가 사용하는 데이터(특히 props)에 변경된 것이 없다하더라도 부모 컴포넌트에서 re-render가 일어나면 모든 자식 컴포넌트들이 re-render 된다.
- 렌더링 최적화는 자식 컴포넌트 중 props가 동일하다면 (데이터가 변경되지 않았다면) re-render가 일어나지 않도록 하는 것이지만 상태 데이터가 객체라면 쉽지 않다.
- Virtual DOM이란? 가상의 돔으로 전체를 렌더링 하는 것이 아닌 이전 렌더링 결과와 현재의 렌더링 결과를 비교해서 바뀐 부분만 브라우저 DOM에 업데이트한다.
- 하지만 Virtual DOM에 불필요하게 re-render 하는 것도 성능에 영향을 준다.
💡불변성과 shallow copy
shallow copy는 객체의 메모리 주소를 복사하기 떄문에 기존 원본 객체가 변경된다. 따라서 불변성을 갖지 않는다.
💡 불변성을 위한 전개 연산자 사용
전개연산자(...)는 아주 간단한 사용한 수준의 속성까지만 불변성을 제공한다. 하지만 복잡한 트리구조의 객체에서 사용할 때는 불변성을 유지하기 어렵다.
3. immer 라이브러리
npm install immer
- 복잡한 트리구조의 불변성을 지키기 위해 사용
- 쉬운 불변성 확보 방법을 제공한다.
- 자바스크립트 객체, 배열의 접근방식을 그대로 사용한다.
- 객체 트리 끝단의 값을 변경하면 Root로 올라가는 경로 상의 객체를 모두 새로운 것으로 생성한다. 이때 경로상이 아닌 것은 기존 객체를 유지한다.
💡 immer는 반드시 사용해야 할까?
- 그렇지 않지만 바람직하다.
- 간단한 객체는 전개 연산자를 이용할 수 있다.
- 하지만 복잡한 트리구조 특히 UI 렌더링 성능 최적화를 위해서는 반드시 필요하다.
- 상태 데이터에대해 불변성을 확보하는 것이 중요하다는 걸 알아야한다.
4. 렌더링 최적화
4.1 React.memo() 고차 함수 이용
- 컴포넌트의 렌더링 결과를 캐싱한다.
- 상태나 속성이 변경된 것이 없다면 렌더링하지 않고 메모이징된 캐시를 사용한다.
- Shallow Compare 이용
✨ 이때, memo로 최적화를 시켰음에도 계속 렌더링이 일어나는 현상이 발생할 수 있음
만약 props로 전달 받는 값이 원시 값이라면 값 자체를 저장하는 불변성을 가지고 있기 때문에 리렌더가 발생하지 않지만 전달 받는 값이 함수같은 객체값이라면 주소값이 계속 변하게 되어 최적화 해준다 하더라도 새로운 값이라고 인식해 계속 리렌더가 발생하는 것!
이때 사용할 수 있는 방법이 있음!
4.2 useCallback()
- 컴포넌트 내부의 함수를 캐싱한다.
함수와 훅을 사용하는 것이 아닌 근본적인 해결책은?
- 바뀌는 속성과 바뀌지 않는 속성을 구분하여 컴포넌트를 분할해주는 것
- 상태관리를 사용하고 액션 메서드를 자식 컴포넌트에 직접 바인딩하는 것
📌
원형섭 강사님 실시간 강의
'Front-end > React' 카테고리의 다른 글
[React] 상태관리 라이브러리 - zustand (0) | 2024.01.17 |
---|---|
[React] 상태관리 라이브러리 - Redux (0) | 2024.01.16 |
리액트에서 checkbox 오류 해결하기 (0) | 2023.12.28 |
[React] CSR (클라이언트 사이드 렌더링) 과 SSR (서버 사이드 렌더링) (0) | 2023.03.07 |
[React] React Hooks : useReducer (0) | 2023.03.03 |