프로젝트가 더 복잡해질수록 Redux를 올바르게 사용하기도 복잡해집니다.
이번 게시글에서는 Redux를 조금 더 쉽게 관리하는 방법을 알아보도록 하겠습니다.
// 리덕스 로직을 저장
// 0. redux import
import { createStore } from "redux";
const initialState = { counter: 0, showCounter: true };
// 2. Reducer 함수 생성 후 Action에 대한 작업 설정 - State의 초깃값 설정 필수
// (Reducer 함수는 항상 객체를 새로운 반환하고 반환된 객체는 store에 저장)
const countReducer = (state = initialState, action) => {
if (action.type === "INCREMENT") {
return { counter: state.counter + 1, showCounter: state.showCounter };
}
if (action.type === "INCREASE") {
return {
counter: state.counter + action.amount,
showCounter: state.showCounter,
};
}
if (action.type === "DECREMENT") {
return { counter: state.counter - 1, showCounter: state.showCounter };
}
if (action.type === "TOGGLE") {
return { counter: state.counter, showCounter: !state.showCounter };
}
return state;
};
// 1. store(중앙 데이터 저장소) 생성
// 3. store과 Reducer 함수 연결
const store = createStore(countReducer);
// 4. React에서 Redux store에 접근할 수 있도록 설정
export default store;
State 관리하기
프로젝트의 규모가 커질수록 store에서 관리하는 State 객체도 점점 커질 것입니다.
Reducer 함수 관리하기
프로젝트의 규모가 커질수록 Reducer 함수는 점점 길어질 것입니다.
이는 결국 하나의 거대한 React-Context를 사용할 때 생기는 단점이 그대로 발생할 수 도 있습니다.
하지만 Redux의 경우에는 해결방법이 존재합니다.
식별자 관리하기
현재 위의 예시 코드는 4개의 Action을 식별하여 그에 해당하는 작업만 정의되어 있습니다.
하지만 프로젝트의 규모가 커지고 협업하는 인원이 늘어나게 되면 식별자는 보다 많아질 것이고 이로 인해 식별자가 잘못 건드려 틀어지는 경우가 발생할 수 있습니다.
방법은 간단합니다.
상수에 고정되는 문자열을 담고 export 해주고 dispatch 하는 컴포넌트에서 하드코딩으로 Action을 전달하는 것이 아니라 export 된 상수로 Action을 전달하도록 해줍니다.
하지만 Redux toolkit을 사용하면 보다 쉽게 위의 문제를 해결할 수 있습니다.
Redux toolkit 사용하기
Redux toolkit 사용법
npm i @reduxjs/toolkit
우선 Redux toolkit을 설치해줍니다.
Redux toolkit 설치가 끝나면 Redux를 삭제해주어야 합니다.(이미 Redux toolkit에 포함되어있기 때문입니다.)
이렇게 설치된 Redux toolkit은 Redux store를 관리하는 파일에서 사용하게 됩니다.
(이유는 Redux toolkit은 Redux의 몇 가지 특징을 단순화한 것이기 때문입니다.)
Redux store를 관리하는 파일 createSlice를 import 해줍니다.
createSlice는 보다 강력하게 Redux의 몇 가지 특징을 한 번에 단순화시킬 수 있습니다.
import한 createSlice를 호출하여 아래의 작업을 진행해줍니다.
우선 각 기능에 맞는 slice를 미리 만들어 놓아야 합니다.
(예를 들어 카운터 State와 사용자 인증 State가 있다면 2개의 slice를 생생해줍니다.)
이렇게 추가해준 reducers 안의 메서드는 기존에 Reducer 함수에서 식별자 별로 작업 설정한 부분에 사용됩니다.
또한 메서드들은 자동으로 최신의 State를 받게 되며 나중에 Redux에 의해 호출됩니다.
앞서 작성한 게시글을 보시면 위와 같은 접근으로 State을 변형하면 안 된다고 했지만 createSlice를 사용하면 기존의 State를 변형할 수 없습니다.
왜냐하면 Redux toolkit은 내부적으로 immer라는 다른 패키지를 사용하는데 이런 코드를 감지하고 자동으로 원래 있는 State를 복제하여 새로운 State 객체를 생성하고 모든 State를 변경할 수 없게 유지하고 위에 작성한 코드를 오버 라이딩하게 됩니다.
즉 Redux toolkit을 사용하면 위와 같이 State의 변형을 일으키는 실행문을 작성해도 내부적으로 감지하여 기존에 State에 오버 라이딩을 시켜 변형을 일으키지 않게 해 줍니다.
다른 메서드들도 위와 같은 방식으로 작업해줍니다.
(기존 Reducer 함수에서 식별자 별로 작업 설정하는 것과 유사합니다. 차이는 State의 변형을 일으키게 작업 설정을 하여도 내부적으로 오버 라이딩해준다는 것뿐입니다.)
다음으로 생성한 silce를 store에 연결해주어야 합니다.
기존 Reducer 함수를 인수로 전달하던 곳에 slice 객체의 reducer를 전달해줍니다.
하지만 이렇게 되면 만약 프로젝트 규모가 커졌을 때 store(저장소)는 하나만 생성할 수 있기 때문에 여러 개의 slice 중 하나의 slice만 접근할 수 있다는 문제가 발생하게 됩니다.
때문에 configureStore를 추가로 import 해줍니다.
configureStore는 createStore처럼 store(저장소)를 생성하지만 차이점은 여러 개의 reducer를 하나의 reducer로 쉽게 합칠 수 있습니다.
configureStore에는 객체를 전달하며 해당 객체는 configureStore가 요구하는 설정을 담당하게 됩니다.
다음으로 dispatch(Action 전달)가 가능하도록 설정해주어야 합니다.
생성한 slice 뒤에 actions 메서드를 사용하면 앞서 생성한 reducers 객체의 키에 접근이 가능해집니다.
이렇게 slice에 있는 reducers 객체의 키에 접근하게 되면 reducers 객체에 접근할 이유가 사라집니다.
(reducers 객체에 접근하여 객체 안에 있는 각각의 메서드에 접근해야 하는데 위의 과정으로 각각의 메서드에 접근을 했기 때문입니다.)
actions 메서드는 Action 생성자라고 할 수 있으며 Action에 대한 식별자를 자동으로 생성해주기 때문에 더 이상 신경 쓸 필요가 없어지게 됩니다.
이렇게 export 작업까지 해주고 나면 컴포넌트에서 Redux로 Action을 전달할 때 더 이상 Action 식별자에 대한 오타 걱정을 하지 않아도 됩니다.
컴포넌트에서 dispatch를 위와 같이 진행해줍니다.
(store에서 export 한 actions 메서드를 사용했습니다.)
store 관리 js
import { createSlice, configureStore } from "@reduxjs/toolkit";
const initialState = { counter: 0, showCounter: true };
const counterSlice = createSlice({
name: "counter",
initialState,
reducers: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
},
increase(state, action) {
state.counter = state.counter + action.payload;
},
toggleCounter(state) {
state.showCounter = !state.showCounter;
},
},
});
const store = configureStore({
reducer: counterSlice.reducer,
});
export const counterActions = counterSlice.actions;
export default store;
정리
Redux toolkit을 사용하여 store을 생성하고 관리하는 순서는 아래와 같습니다.
1. configureStore를 사용하여 store를 생성해줍니다. configureStore을 사용하면 여러 개의 reducer를 하나로 병합하여 store에 연결할 수 있게 됩니다.
2. createSlice를 사용하여 slice를 생성해줍니다. slice 기존의 Reducer 함수의 역할을 하며 해당 slice는 객체를 받아 생성됩니다.
해당 객체에 설정은 name, initialSlice, reducers 설정이 필수입니다.
3. slice의 reducers에 있는 객체 안에 있는 메서드에 접근하기 위해 actions 메서드를 사용하는데 actions 메서드는 식별자를 자동으로 생성해주는 기능도 합니다. actions 메서드를 export 해줍니다.
4. 컴포넌트에서 actions를 import 하여 dispatch 작업을 진행합니다.
'React > 상태관리하기' 카테고리의 다른 글
MobX 톺아보기 0 - 컨셉, 원칙 (0) | 2023.02.13 |
---|---|
Redux 톺아보기 2 - (비동기 로직) (0) | 2023.02.11 |
Redux 톺아보기 1 - (redux-toolkit) (0) | 2023.02.10 |
Redux 톺아보기 0 - ( 핵심 컨셉, 적절한 사용, 개념 및 용어 ) (0) | 2023.02.10 |
Redux React에 적용하기 (0) | 2022.11.08 |