Redux 소개
Redux란?전역상태 라이브러리
1. 리덕스가 필요한 이유

- useState의 불편함
- props를 통해 부모 컴퍼넌트->자식 컴퍼넌트로 값을 보내줘야 했음 (prop drilling 유발)
- 자식 컴포넌트에서 부모 컴포넌트로 값을 보낼 수 없음
- useContext를 사용하는 것과 유사하게 전체영역에서 특정 경로(위치)에 있는 store라는 개념에서부터 데이터를 공유받음
- 그렇기 때문에, 리덕스를 사용하면 전역상태를 사용할 수 있어
- Global State(Redux)와 Local State(useState)
- Local State: useState를 이용해 생성한 state
- Global State: 컴포넌트에서 생성되지 않음, 중앙화 된 곳에서 state들이 생성됨 => 컴포넌트가 어디에 위치하고 있든 상관없이 state를 불러와 사용할 수 있음
2. 리덕스?
: “중앙 state 관리소”를 사용할 수 있게 도와주는 패키지(라이브러리)
3. 리덕스의 흐름

- View에서 사용자 action 발생 (ex. click)
- Dispatch를 통해 action 전달
- Reducer가 액션을 처리하기 전 Middleware가 실행됨
- Reducer가 실행
- Store에 새로운 값을 저장
- Store의 상태 변경을 감지한 UI가 업데이트
4. 주요 개념 복습
- 액션 객체: 반드시 type이라는 키를 포함하며, 리듀서로 보낼 명령을 나타냄
- 디스패치(dispatch): 액션 객체를 리듀서로 전달하는 함수입니다. useDispatch() 훅을 사용해 호출
- 리듀서: 전달받은 액션 객체에 따라 조건이 일치했을 때 새로운 상태를 생성하는 함수
- 액션 객체의 type은 대문자로 작성: JavaScript에서 상수는 대문자로 작성
5. 리덕스 설치 및 설정
- 패키지 설치: Redux와 React-Redux를 설치합니다.
-
yarn add redux react-redux - 폴더 구조 생성: src/redux/config와 src/redux/modules 폴더를 생성합니다.
- configStore.js: 중앙 상태 관리소인 Store를 설정하는 파일입니다.
- modules 폴더에는 상태 관리 로직을 작성한 모듈 파일들이 위치합니다.
- Store 설정 (src/redux/config/configStore.js):
-
import { createStore } from "redux"; import { combineReducers } from "redux"; import counter from "../modules/counter"; // 1. rootReducer 만듬 const rootReducer = combineReducers({ counter: counter, // 뒤의 counter를 생략하여 counter만 작성해도 됨 }); // 모듈 안에 들어갈 값들이 combineReducers의 인풋(객체)으로 들어감 // 2. store를 조합 const store = createStore(rootReducer); // 3. 만든 store 내보내기 export default store; - Provider 설정 (src/main.jsx):
-
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App.jsx"; import "./index.css"; import { Provider } from "react-redux"; import store from "./redux/config/configStore.js"; ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> );
6. 첫 번째 모듈 작성 (Counter)
- 모듈 생성 (src/redux/modules/counter.js)
- Store와 모듈 연결: 이미 configStore.js에서 설정을 완료
// 초기값 설정: 객체를 가지고 key로 number =0을 가짐
const initialState = {
number: 0,
};
const PLUS_ONE = "PLUS_ONE";
export const plusOne = () => {
return {
type: PLUS_ONE
}
}
// reduce 함수 생성: 인자를 2개 받음 (리덕스 사용방법)
const counter = (state = initialState, action) => {
// action은 type을 가진 객체
switch (action.type) {
case "PLUS_ONE": // action.type이 PLUS ONE인 경우
return {
number: state.number + 1, // 기존의 초기값 number: 0이 아니라, 새로운 객체 number: 1을 반환
};
case "MINUS_ONE":
return {
number: state.number - 1,
};
default:
return state; // default로 state를 그대로 반환
}
};
export default counter;
7. 스토어와 모듈 연결 확인
- 스토어 조회: useSelector 훅을 사용하여 스토어에서 상태를 조회할 수 있음
import React from "react";
import { useDispatch, useSelector } from "react-redux";
const App = () => {
const conterReducer = useSelector((state) => {
return state.counter;
});
console.log("state", conterReducer);
const dispatch = useDispatch(); // dispatch가 액션 객체를 redux에 보내는 역할
return (
<div>
{conterReducer.number}
<br />
<button
// 마우스를 클릭했을 때 dispatch를 실행
onClick={() => {
dispatch(
// dispatch를 통해 아래 부분이 counter.js의 counter의 인자 action으로 가게 됨
{
// 스토어에 변경이 생기려면 action 객체를 보내야 함
// 객체에는 key-value pair로 type과 type의 이름이 들어가야 함
type: "PLUS_ONE",
}
);
}}
>
+1
</button>
<button
onClick={() => {
dispatch({
type: "MINUS_ONE",
});
}}
>
-1
</button>
</div>
);
};
export default App;
8. Redux로 Counter 기능 구현하기: +1, -1 기능
(1) +1 기능 구현하기
1.액션 객체 생성
: 액션 객체는 반드시 type 키를 포함해야 합니다. 예를 들어, 숫자에 1을 더하는 액션 객체는 아래와 같이 정의됩니다:
{ type: "PLUS_ONE" }
2. 디스패치로 액션 보내기
디스패치는 리덕스의 useDispatch 훅을 사용해 액션 객체를 리듀서로 보냅니다. App.js에서 버튼 클릭 시 디스패치를 호출합니다:
import React from "react";
import { useDispatch } from "react-redux";
const App = () => {
const dispatch = useDispatch();
return (
<div>
<button
onClick={() => {
dispatch({ type: "PLUS_ONE" });
}}
>
+ 1
</button>
</div>
);
};
export default App;
3. 리듀서 로직 추가
리듀서는 액션의 type에 따라 상태를 변경합니다. counter.js에서 PLUS_ONE에 대한 로직을 추가합니다:
// 초기 상태값
const initialState = {
number: 0,
};
// 리듀서
const counter = (state = initialState, action) => {
switch (action.type) {
case "PLUS_ONE":
return {
number: state.number + 1,
};
default:
return state;
}
};
export default counter;
(2) -1 기능 구현하기
1. 빼기 버튼 추가
App.js에 -1 버튼을 추가합니다:
<button
onClick={() => {
dispatch({ type: "MINUS_ONE" });
}}
>
- 1
</button>
2. 리듀서 로직 확장
리듀서에 MINUS_ONE에 대한 로직을 추가합니다:
const counter = (state = initialState, action) => {
switch (action.type) {
case "PLUS_ONE":
return {
number: state.number + 1,
};
case "MINUS_ONE":
return {
number: state.number - 1,
};
default:
return state;
}
};
(3) 변경된 상태 확인하기
리덕스의 상태를 확인하기 위해 useSelector를 사용하여 상태를 가져옵니다. 이 값을 화면에 출력합니다:
import { useSelector } from "react-redux";
const number = useSelector((state) => state.counter.number);
return (
<div>
{number}
<button onClick={() => dispatch({ type: "PLUS_ONE" })}>+ 1</button>
<button onClick={() => dispatch({ type: "MINUS_ONE" })}>- 1</button>
</div>
);
(4) 마무리
이제 +1, -1 버튼을 클릭할 때마다 화면에 표시된 숫자가 증가하고 감소하는 것을 확인할 수 있습니다. 리덕스를 통해 상태를 관리하면서, 각 컴포넌트가 리덕스 상태를 반영하여 리렌더링되는 과정을 이해할 수 있었습니다.
'⚛️ React 공부 > 기초 문법' 카테고리의 다른 글
| React JS 심화: 인증과 인가(쿠키, 세션, 토큰, JWT) (0) | 2024.09.06 |
|---|---|
| ReactJS 숙련: Hooks (Memorization, CustomHook) (0) | 2024.08.20 |
| ReactJS 숙련: Hooks (useState, useEffect, useRef, useContext) (0) | 2024.08.19 |
| ReactJS 숙련: CSS-in-JS와 Styled-Components (0) | 2024.08.16 |
| ReactJS 입문: React 소개와 프로젝트 생성 (0) | 2024.08.13 |