본 시리즈는 저의 기술면접 경험을 토대로 질문 받았던 내용을 직접 코드를 구현해보면서 이해하자는 목표로 작성한 글입니다 ! 😀
🎤 시작하는 말
지난 포스트에서 불변성이 무엇인지, 왜 필요한지, Shallow Equality 란 무엇인지 알아 보았습니다.
만약 아직 이 내용에 대해 잘 모르시거나 아직 보지 못하셧다면, https://yoonocean.tistory.com/14 를 클릭해주세요
이번 포스트에서는 Redux 에서 Shallow Equality 를 어떻게 사용하는지에 대해 알아 보겠습니다.
❓ Redux 에서 Shallow Equality 를 어떻게 사용하는가?
간단하게 설명하자면 combinReducers 함수는 분할한 여러개의 리듀서 함수가 들어있는 객체로 createStore 에 전달하도록 도와주는 함수이다.
결국 리듀서 함수들은 상태값을 반환하게 되고, store 의 가장 상위에 state 객체가 있고 그 아래 다시 reducer 들에서 분리된 상태 객체들이 존재하게 된다.
아래의 코드를 보면 좀더 이해하는데 도움이 될것이다. (Redux 공식문서 예시코드)
// ...modules/index.js
import { combineReducers } from 'redux'
import todos from './todos'
import counter from './counter'
export default combineReducers({
todos,
counter
})
// App.js
import { createStore } from 'redux'
import reducer from './modules/index'
const store = createStore(reducer)
console.log(store.getState()) //
// getState() 로 얻는 객체는 항상 store 전체 state 객체이다. (.... return state)
// {
// counter: 0,
// todos: []
// }
store.dispatch({
type: 'ADD_TODO',
text: 'Use Redux'
})
console.log(store.getState())
// {
// counter: 0,
// todos: [ 'Use Redux' ]
// }
Redux Store 는 state 객체를 key 로 여러 Slice 로 분할 하고, 각각의 Data Slice 를 관리하기 위해 별도의 리듀서 함수를 사용하는 구조로 되어 있다.
combineReducers 는 reducer 들의 key-value 쌍의 집합인 Hash Table 로 정의된 인수를 사용하여 이러한 구조 작업을 더 쉽게 만들어 준다. Key 는 State Slice 의 이름이 되고, Value 는 다음 상태에 작용할 리듀서 함수이다.
combineReducers({ todos: myTodosReducer, counter: myCounterReducer })
그래서 combineReducers 는 각각의 key-value 쌍을 반복 수행한다.
- 각 Key 가 참조 하는 현재 State Slice 에 대한 참조 생성
- 정의된 Reducer 를 호출하고 Slice 를 전달
- Reducer 가 반환하는 변경 가능성이 있는 State Slice 에 대한 참조 생성 ( 새로운 상태 객체 )
반복 수행을 통해, 각 Reducer 에서 반환된 State Slice 로 새로운 State 객체를 생성한다.
combineReducers 함수는 이 새로운 State 객체와 현재 State 객체의 변경 사항 여부를 확인하는 작업에서 Shallow Equality 를 사용한다.
반복의 각 단계 에서 combineReducers 는 현재 State Slice 와 리듀서가 반환한 새로운 State Slice 에 대해 Shallow Equality 를 수행하고, 리듀서가 새 상태객체를 반환했다면 비교검사는 hasChanged 플래그를 true 로 설정한다.
반복이 완료 되고, hasChanged 플래그를 확인해서 true 라면 새로운 상태 객체를, false 라면 현재 상태 객체가 반환된다.
다시 말해 Reducer가 모두 동일한 상태객체를 반환 했다면, combineReducers 는 새로운 상태객체를 반환하지 않고 기존의 상태객체를 반환하게 된다.
❓ React-Redux 에서는 Shallow Equality 를 어떻게 사용하는가?
먼저, React-Redux 는 connect API 에 Shallow Equality 가 사용된다.
React-Redux 는 래핑된 컴포넌트가 리렌더링을 해야하는지 여부를 결정할때 Shallow Equality 를 사용한다.
래핑된 컴포넌트가 Pure 하다고 가정해보자. 컴포넌트는 동일한 props 및 state 가 주어지면, 동일한 결과를 생성해야한다.
그런 경우에 root 상태 객체 또는 반환된 값인 mapStateToProps 가 변경되었는지 여부만 확인하면 된다. 그렇지 않은 경우, 래핑된 구성요소를 다시 렌더링할 필요가 없다.
mapStateToProps 는 root 상태 객체에 대한 참조와 함수에서 반환된 props 객체의 각 value 에 대한 참조를 유지해 변경사항을 감지한다.
mapStateToProps 는 다음 root 상태 객체 및 전달된 상태 객체에 대한 참조에 대해 Shallow Equality 를 실행하고, props 객체의 값과 함수를 다시 실행하여 반환된 값에 대한 각 참조에 대해 Shallow Equality 를 실행한다.
React-Redux v7.1 에서 Hooks API 가 추가되고서, 공식문서 에서는 Hooks API 로 컴포넌트 접근을 권장한다.
따라서 connect 함수대신 useSelector() hook 을 사용하길 권장하는데, 이 useSelector 는 기본적으로 Shallow Equality 가 아닌 strict reference equality 를 사용한다. 이 내용은 다음 포스트에서 다루도록 하겠다. 여기에는 React-Redux Hooks API 에 존재하는 문제점이 달려있다.
(작성중)
참고 문헌 :
Immutable Data | Redux
Table of Contents
redux.js.org
'Front-End > Redux' 카테고리의 다른 글
Redux 의 불변성에 대해 - (1) (0) | 2022.03.24 |
---|