React!
리덕스툴킷(Redux Toolkit)
개발따라김양
2022. 8. 1. 12:57
1. 리덕스(Redux)의 문제점
1) store configuration의 복잡성
리덕스 스토어를 설정하는 게 너무 복잡합니다.
2) 리덕스를 사용하기 위한 다른 라이브러들의 추가 설치
- react와 바인딩하기 위한 react-redux
- 불변성을 유지하기위한 immutable/immer
- 비동기 통신을 위한 redux-thunk/redux-saga/redux-pender
- 액션 생성을 위한 redux-actions
3) 많은 양의 보일러 플레이트를 파일마다 반복 작성해야 함
리덕스 액션과 리듀서들을 도메인마다 분리를 하고, 또 리액트 각 컴포넌트마다 바인딩을 하면,
엄청나게 많은 수의 파일에서 리덕스 코드를 사용하게 됩니다.
그런데 그 많은 파일에서 많은 양의 보일러 플레이트 코드를 반복해서 사용해줘야 해서
코드가 지저분해지고 관리포인트가 많다는 단점이 있습니다.
2. 리덕스 툴킷 (Redux Toolkit)
- 리덕스 로직을 작성하기 위해 리덕스에서 공식적으로 추천하는 방법입니다.
- 리덕스 툴킷은 리덕스 앱을 만들기에 필수적으로 여기는 패키지와 함수들을 포함합니다.
- 리덕스 툴킷은 저장소 준비, 리듀서 생산과 불변 수정 로직 작성, 상태 "조각" 전부를 한번에 작성 등
일반적인 작업들을 단순화해주는 유틸리티를 포함하고 있습니다
1) 개선점
- store configuation
configureStore 함수는 리덕스 라이브러리의 createStore 함수를 추상화한 것입니다.
기존의 번거러운 리덕스 설정을 간편하게 할 수 있도록 해주고 디폴트로 redux-thunk, DevTools를 제공해줍니다.
import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './reducers'
const store = configureStore({ reducer: rootReducer })
- createSlice
createSlice 함수는 선언한 slice의 name에 따라 액션 생성자, 액션 타입, 리듀서를 자동으로 생성해줍니다.
따라서 별도로 createAction 이나 createReducer을 사용하지 않아도 됩니다.
import { configureStore, createSlice } from '@reduxjs/toolkit'
let user = createSlice({ ///createSlice 선언
name: 'user', ///이름
initialState : {name : 'crystal', age : 30 }, //초기값설정
reducers: { //state 바꾸는 함수 reducers 선언
changeName(state){
state.name = 'new-crystal'
state.age +=1
}
}
})
export default configureStore({
reducer: {
user : user.reducer
}
})
- 정리
- 리덕스는 데이터를 단방향으로 흐르게 하여 결과를 예측 가능하게 하고 디버깅을 쉽게 만듭니다.
- RTK는 기존 리덕스의 문제를 개선하고, 리덕스 로직을 작성하는 표준을 제안한다.
- 스토어 구성은 configureStore를 사용하자.
- 리덕스 로직을 작성할 때는 덕-패턴(ducks pattern) 형태로 작성을 돕는 createSlice를 사용하자.
- 비동기 로직은 createAsyncThunk를 사용해서 작성하자.
- 타입 스크립트를 지원하는 빌더 콜백(builder callback) 표기법을 사용하자.
- 프로미스 생명 주기를 따르는 액션 타입으로 비동기 로직을 관리해 보자.
- 데이터 패칭과 캐싱은 RTK Query를 사용해 보자.
1) 설치
yarn add @reduxjs/toolkit
2)React Redux 앱 만들기
React와 Redux로 새 앱을 만들기 위해 추천하는 방법은 Create React App를 위한 공식 Redux+JS 템플릿을 사용하는 것입니다. 이를 통해 Redux Toolkit와 React Redux가 React 컴포넌트와 통합되는 이점을 누릴 수 있습니다.
npx create-react-app my-app --template redux
3) Redux 코어
Redux 코어 라이브러리는 NPM에서 패키지로 받아 모듈 번들러나 Node 앱에서 사용 가능합니다.
yarn add redux
4) 기본 예제
import { createStore } from 'redux'
/**
* 이것이 (state, action) => state 형태의 순수 함수인 리듀서입니다.
* 리듀서는 액션이 어떻게 상태를 다음 상태로 변경하는지 서술합니다.
*
* 상태의 모양은 자유롭습니다: 기본형(primitive)일수도, 배열일수도, 객체일수도,
* 심지어 Immutable.js 자료구조일수도 있습니다.
* 오직 중요한 점은 상태 객체를 변경해서는 안되며,
* 상태가 바뀐다면 새로운 객체를 반환해야 한다는 것입니다.
*
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
// 앱의 상태를 보관하는 Redux 저장소를 만듭니다.
// API로는 { subscribe, dispatch, getState }가 있습니다.
let store = createStore(counter)
// subscribe()를 이용해 상태 변화에 따라 UI가 변경되게 할 수 있습니다.
// 보통은 subscribe()를 직접 사용하기보다는 뷰 바인딩 라이브러리(예를 들어 React Redux)를 사용합니다.
// 하지만 현재 상태를 localStorage에 영속적으로 저장할 때도 편리합니다.
store.subscribe(() => console.log(store.getState())))
// 내부 상태를 변경하는 유일한 방법은 액션을 보내는 것뿐입니다.
// 액션은 직렬화할수도, 로깅할수도, 저장할수도 있으며 나중에 재실행할수도 있습니다.
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1