redux toolkit 없이 전역 상태 관리 하는 방법을 알아봅니다. 현재는 toolkit 사용을 권장하고 있어, 오늘날에 사용되는 코드는 아닙니다.
redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레거시)
목차
1. redux란?
- react에서 사용되는 전역 상태 관리 라이브러리
- 기존의 하향식 전달에서 벗어나 어디서든 상태를 참조, 변경을 가능하게끔 함
2. redux의 구성
- state
- redux에서 관리하는 상태 정보
- action
- 상태를 변경하는 요청
- 어떠한 상태 변경을 하겠다를 타입에 명시
- ex) 이름을 변경시키겠다, 나이를 변경시키겠다
- reducer
- 이전 state와 action을 받아 새로운 상태를 반환하는 함수
- 액션에 담긴 타입에 맞춰 로직 실행
- 상태를 변경시키는 로직이 담겨 있음
- store
- state, action, reducer 모두를 관리하는 중앙 저장소
- action을 reducer로 전달하여 상태 변경을 적용
- dispatch
- action을 store로 전달하는 메서드

3. 장점
- 쉬운 디버깅
- redux devtools를 사용하면 디버깅이 쉬움
- 높은 점유율
- redux는 다른 상태 관리 라이브러리와 비교해 점유율이 높음
- 따라서 관련 자료들을 쉽게 찾을 수 있음
- middleware 지원
- middleware는 reducer가 action을 처리하기 전에 추가적인 로직을 가능하게 해줌
- 비동기 작업, 인증 등 추가적인 작업을 처리가능
4. 단점
- boilerplate (작성해야 하는 코드가 많음)
- redux를 사용하기 위해 기본적으로 작성해야 하는 코드가 많은 편
- redux-toolkit 등의 라이브러리를 통해 코드를 줄일 수 있지만, 그럼에도 다른 상태 관리 라이브러리로 보다는 코드가 긴편
- 비동기 작업 복잡
- 비동기 작업을 처리하기 위해 Redux Thunk, Redux Saga 등 middleware를 사용할 수 있지만, 이 역시 다른 상태 관리 라이브러리 보다 사용법이 다소 복잡한 편
5. 구현
- reducer 설치
npm i redux react-redux redux-devtools-extension
- reducer를 작성
- 초기 상태 값을 작성
- reducer 내부에 각 액션에 따라 어떠한 로직을 실행할 지 작성
- action을 작성, payload는 action의 parameter를 의미
- 생성한 reducer와 action을 export
// store/reducers/infoReducer.js
// 기본 상태 값을 설정
const initialState = {
name: "홍길동",
age: 20,
};
// reducer를 작성
// 각 액션에 따라 어떠한 로직을 실행할 지 작성
const infoReducer = (state = initialState, action) => {
switch (action.type) {
case "CHANGENAME":
return { ...state, name: action.payload };
case "CHANGEAGE":
return { ...state, age: action.payload };
default:
return state;
}
};
// 액션 작성
// changeName 액션 작성
// payload는 action에 담긴 parameter를 의미
const changeName = (value) => ({
type: "CHANGENAME",
payload: value,
});
// changeAge 액션 작성
const changeAge = (value) => ({
type: "CHANGEAGE",
payload: value,
});
// 생성한 reducer와 action export
export { infoReducer, changeName, changeAge };
- rootReducer 작성
- combineReducers를 통해 생성한 reducer를 모두 묶어줌
- comibineReducers에서 reducer에 지정한 키를 통해 상태를 불러 올 수 있음 (useSelector 부분 참고)
// store/reducers/rootReducer.js
import { combineReducers } from "redux";
import { infoReducer } from "./infoReducer";
// 생성한 리듀서를 하나로 묶어 줌
const rootReducer = combineReducers({
// state에서 해당 상태를 불러올 때 state.info를 통해 접근할 수 있음
info: infoReducer,
});
export default rootReducer;
- store 작성
- createStore은 현재 사용을 권장하지 않음. 현재 코드에서는 redux toolkit을 사용하지 않기에 사용
- store에 rootReducer 추가
- composeWithDevTools()를 적용하여 redux 개발자 도구 사용 가능
import { createStore } from "redux";
import rootReducer from "./reducers/rootReducer";
import { composeWithDevTools } from "redux-devtools-extension";
// store를 생성
// createStore은 현재 권장되지 않는 방법, 앞으로는 toolkit의 configureStore를 사용합시다.
// store에는 rootReducer를 넣어줌
// composeWithDevTools를 넣어 redux 스토어의 변화를 확인할 수 있음
const store = createStore(rootReducer, composeWithDevTools());
export default store;
- redux를 사용하고자 하는 컴포넌트 최상단에 store 적용
// main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store/store";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
{/* redux를 이용하고자 하는 컴포넌트 최상단에 store를 적용 */}
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
- redux 사용하기
- useSelector로 store 상태 불러오기
- useDispatch로 dispatch 사용하기
- dispatch를 통해 action을 store로 전달하기
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { changeAge, changeName } from "./store/reducers/infoReducer";
function App() {
// useSelector를 통해 store의 상태를 불러올 수 있음
// rootReducer의 할당한 키를 통해 불러올 수 있음
const info = useSelector((state) => state.info);
// useDispatch에 action을 이용하면 상태 변화 로직을 실행할 수 있음
const dispatch = useDispatch();
const [name, setName] = useState("홍길동");
const [age, setAge] = useState(20);
const handleInputName = (e) => {
setName(e.target.value);
};
const handleInputAge = (e) => {
setAge(e.target.value);
};
const submitName = () => {
// action을 dispatch를 통해 store로 전달
// changeName에 해당하는 상태 변화 로직 실행
dispatch(changeName(name));
};
const submitAge = () => {
// action을 dispatch를 통해 store로 전달
// changeAge에 해당하는 상태 변화 로직 실행
dispatch(changeAge(age));
};
return (
<div className="App" style={{ display: "flex", flexDirection: "column" }}>
<div>{`현재 이름은 ${info.name} 입니다.`}</div>
<div>{`현재 나이는 ${info.age}세 입니다.`}</div>
<div>
<label>
이름
<input onChange={handleInputName} />
</label>
<button onClick={submitName}>이름 변경</button>
</div>
<div>
<label>
나이
<input type="number" onChange={handleInputAge} />
</label>
<button onClick={submitAge}>나이 변경</button>
</div>
</div>
);
}
export default App;
- devtools 사용
- chrome extension 에서 redux devtools 설치
- 현재 state와 실행 되었던 action 확인
6. 구현된 코드로 보기
'react > 상태관리' 카테고리의 다른 글
redux toolkit으로 전역 상태 관리하기 (1) | 2023.10.09 |
---|---|
mobx 사용하기 (0) | 2023.10.06 |