(1) ํดํท ์ค์นํ๊ธฐ
CRA๋ฅผ ํตํด ์๋ก์ด ํ๋ก์ ํธํ ์์ฑํ๊ณ yarn
์ ํตํด ์๋ ํจํค์ง๋ฅผ ์ค์นํ๋ค.
yarn add react-redux @reduxjs/toolkit
(2) count ํ๋ก๊ทธ๋จ ์ฝ๋ ๋น๊ต
์๋ ๋ณด์ด๋ ์ฝ๋๋ ์ผ๋ฐ ๋ฆฌ๋์ค์ counter ํ๋ก๊ทธ๋จ ๋ชจ๋. Action Value, Action Creator๋ฅผ ๋ณ๋๋ก ์์ฑํด์ค์ผ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฆฌ๋์์์ ๊ฐ์ ์ด๋ป๊ฒ ๋ณํ์ํฌ ์ง ๋ง๋ค์ด์คฌ์ด์ผ ํ์๋ค.
// ์ผ๋ฐ ๋ฆฌ๋์ค ์์ ์ฝ๋
// Action Value
const ADD_NUMBER = "ADD_NUMBER";
const MINUS_NUMBER = "MINUS_NUMBER";
// Action Creator
export const addNumber = (payload) => {
return {
type: ADD_NUMBER,
payload,
};
};
export const minusNumber = (payload) => {
return {
type: MINUS_NUMBER,
payload,
};
};
// Initial State
const initialState = {
number: 0,
};
// Reducer
const counter = (state = initialState, action) => {
switch (action.type) {
case ADD_NUMBER:
return {
number: state.number + action.payload,
};
// [ํด์ฆ ๋ต]
case MINUS_NUMBER:
return {
number: state.number - action.payload,
};
default:
return state;
}
};
// export default reducer
export default counter;
์๋ ์ฝ๋๊ฐ ๋ฆฌ๋์ค ํดํท์ ์ฌ์ฉํด์ ๋ง๋ counter ํ๋ก๊ทธ๋จ ๋ชจ๋์ด๋ค. ์ผ๋ฐ ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ์ ๋ ๋ณด๋ค ํ์คํ ์ฝ๋์ ์์ด ์ค์๋ค.
ํ๋ฒ ์์ธํ ์ดํด๋ณด๋ฉด ํฐ ์ฐจ์ด์ ์ Action Value์ Action Creator๋ฅผ ์ด์ ์ง์ ์์ฑํด์ฃผ์ง ์๊ณ , Action Value, Action Creator, Reducer๊ฐ ํ๋๋ก ํฉ์ณ์ก๋ค๋ ์ .
์ด์ ์ฐ๋ฆฌ๋ Slice
๋ผ๋ API๋ฅผ ์ฌ์ฉํ๋ค. ์ด ์ฌ๋ผ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด, ์ 3๊ฐ๋ฅผ ๊ฐ๊ฐ ๋ง๋ค์ด์ค ํ์ ์์ด ํ๋ฒ์ 3๊ฐ๊ฐ ๋ชจ๋ ๋ง๋ค์ด์ง๋ค. ์๋ ์ฝ๋๋ฅผ ์์ฑํด๋ณด์.
// src/redux/modules/counterSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
number: 0,
};
const counterSlice = createSlice({
name: "counter",
initialState,
reducers: {
addNumber: (state, action) => {
state.number = state.number + action.payload;
},
minusNumber: (state, action) => {
state.number = state.number - action.payload;
},
},
});
// ์ก์
ํฌ๋ฆฌ์์ดํฐ๋ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๊ธฐ ์ํด export ํ๊ณ
export const { addNumber, minusNumber } = counterSlice.actions;
// reducer ๋ configStore์ ๋ฑ๋กํ๊ธฐ ์ํด export default ํ๋ค.
export default counterSlice.reducer;
์ฌ๋ผ์ด์ค๋ง ์์ธํ ์ดํด๋ณด์. ์ฌ๋ผ์ด์ค๋ createSlice ๋ผ๋ API๋ฅผ ํตํด ๋ง๋ค ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ธ์๋ก ์ค์ ์ ๋ณด๋ฅผ ๊ฐ์ฒด๋ก ๋ฐ๋๋ฐ, ๊ทธ ์์ ์ฐ๋ฆฌ๊ฐ ํ์๋ก ์์ฑํด์ค์ผ ํ๋ ๊ฐ์ name
, initialState
, reducers
๊ฐ ์๋ค.
//createSlice API ๋ผ๋
const counterSlice = createSlice({
name: '', // ์ด ๋ชจ๋์ ์ด๋ฆ
initialState : {}, // ์ด ๋ชจ๋์ ์ด๊ธฐ์ํ ๊ฐ
reducers : {}, // ์ด ๋ชจ๋์ Reducer ๋ก์ง
})
์ ๊ธฐํ ๊ฒ์ ์์ counterSlice ๋ฆฌ๋์ ๊ฐ์ฒด ์์์ ๋ง๋ค์ด์ฃผ๋ ํจ์๊ฐ ๋ฆฌ๋์์ ๋ก์ง์ด ๋๋ฉด์๋ ๋์์ Action Creator๊ฐ ๋๋ค๋ ์ . ๊ทธ๋ฆฌ๊ณ Action Value ๊น์ง ํจ์์ ์ด๋ฆ์ ๋ฐ์ ์๋์ผ๋ก ๋ง๋ค์ด์ง๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ Reducer๋ง ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค.
// counterSlice.js์ Slice ๊ตฌ์กฐ
const counterSlice = createSlice({
name: "counter",
initialState,
reducers: {
// ๋ฆฌ๋์ ์์์ ๋ง๋ ํจ์ ์์ฒด๊ฐ ๋ฆฌ๋์์ ๋ก์ง์ด์, ์ก์
ํฌ๋ฆฌ์์ดํฐ๊ฐ ๋๋ค.
addNumber: (state, action) => {
state.number = state.number + action.payload;
},
minusNumber: (state, action) => {
state.number = state.number - action.payload;
},
},
});
๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๊ฐ ์ผ๋ฐ ๋ฆฌ๋์ค์์ export๋ฅผ ํตํด์ ๊ฐ๊ฐ์ Action Creator๋ฅผ ๋ด๋ณด๋ด์ฃผ์๋ ๊ฒ์ ์๋ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๊ฐ์ด ๋ด๋ณด๋ผ ์ ์๋ค. ๊ทธ๋์ ๋ฆฌ๋์์ ๋ก์ง์ ์ถ๊ฐํ ๋๋ง๋ค ํจ์๋ฅผ ์ถ๊ฐํด์ ๋ด๋ณด๋ด์ฃผ๋ฉด ๋๋ค.
// ์ก์
ํฌ๋ฆฌ์์ดํฐ๋ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๊ธฐ ์ํด export ํ๊ณ
export const { addNumber, minusNumber } = counterSlice.actions;
// reducer ๋ configStore์ ๋ฑ๋กํ๊ธฐ ์ํด export default ํ๋ค.
export default counterSlice.reducer;
(3) configStore ๋น๊ต
์ผ๋ฐ ๋ฆฌ๋์ค
// ์ผ๋ฐ ๋ฆฌ๋์ค combineReducers ์์ ์ฝ๋
import { createStore } from "redux";
import { combineReducers } from "redux";
import counter from "../modules/counter";
const rootReducer = combineReducers({
counter,
});
const store = createStore(rootReducer);
export default store;
configStore
์์๋ ์๋์ ๊ฐ์ด ์์ฑํ๋ฉด ๋๋ฉฐ, ํฌ๊ฒ ๋ฌ๋ผ์ง๋ ์ ์ ์๋ค. todos ๋ชจ๋ ์ฝ๋๋ฅผ ์๋์ ์๋ค. ๋ชจ๋์ ์ถ๊ฐํด์ ์๋ ์ฝ๋์ฒ๋ผ ์ฌ๋ฌ๊ฐ์ ๋ชจ๋์ store์ ๋ฑ๋กํด๋ณด์.// src/redux/modules/config/configStore.js
import { configureStore } from "@reduxjs/toolkit";
/**
* import ํด์จ ๊ฒ์ slice.reducer
*/
import counter from "../modules/counterSlice";
import todos from "../modules/todosSlice";
/**
* ๋ชจ๋(Slice)์ด ์ฌ๋ฌ๊ฐ์ธ ๊ฒฝ์ฐ
* ์ถ๊ฐํ ๋๋ง๋ค reducer ์์ ๊ฐ ๋ชจ๋์ slice.reducer๋ฅผ ์ถ๊ฐํด์ค์ผ ๋ค.
*
* ์๋ ์์๋ ํ๋์ ํ๋ก์ ํธ ์์์ counter ๊ธฐ๋ฅ๊ณผ todos ๊ธฐ๋ฅ์ด ๋ชจ๋ ์๊ณ ,
* ์ด๊ฒ์ ๊ฐ๊ฐ ๋ชจ๋๋ก ๊ตฌํํ ๋ค์์ ์๋ ์ฝ๋๋ก 2๊ฐ์ ๋ชจ๋์ ์คํ ์ด์ ์ฐ๊ฒฐํด์ค ๊ฒ.
*/
const store = configureStore({
reducer: { counter: counter, todos: todos },
});
export default store;
configureStore
์ todosSlice๋ฅผ ์ถ๊ฐํ๋ค. (์๋ ์ฝ๋๋ ๋จ์ํ ๋น์ด์๋ todosSlice.)// src/redux/modules/todosSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
todos: [],
};
const todosSlice = createSlice({
name: "todos",
initialState,
reducers: {},
});
export const {} = todosSlice.actions;
export default todosSlice.reducer;
๊ทธ๋ฆฌ๊ณ ์ด๋ ๊ฒ ์์ฑํ store๋ฅผ export default ํด์ ์ต์์์ index.js Provider์ ์ฃผ์ ํด์ฃผ๋ ๊ฒ์ ์ ํ ๋ฐ๋๊ฒ ์๋ค.
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./redux/config/configStore";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
App.jsx
์์๋ ํดํท์ ์ฌ์ฉํด์ ๋ง๋ ๋ชจ๋์ ์กฐํํ ์ ์๋ค. ๋ฐฉ์์ ์ผ๋ฐ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ์ ๋์ ๋์ผ. ์๋ ์ฝ๋๋ฅผ ์์ฑํ์ฌ, ๋ฆฌ๋์ค ๋ชจ๋๋ค์ด ์ ์ฐ๊ฒฐ๋์๋์ง ํ์ธํด๋ณด์.
// src/App.js
import React from "react";
import { useSelector } from "react-redux";
const App = () => {
// Store์ ์๋ todos ๋ชจ๋ state ์กฐํํ๊ธฐ
const todos = useSelector((state) => state.todos);
// Store์ ์๋ counter ๋ชจ๋ state ์กฐํํ๊ธฐ
const counter = useSelector((state) => state.counter);
return <div>App</div>;
};
export default App;
์ฐ๋ฆฌ๊ฐ ์์์ ์์ฑํ ํ์ผ๋ค์ ๊ตฌ์กฐ ์ด๋ฏธ์ง๋ค. modules์์ ์๋ ํ์ผ์ ์ด๋ฆ์ ์์๋ก ํ๋ฉด ๋๋ค. counter.js
, todos.js
๋ก, ํน์ counterSlice.js
, todosSlice.js
๋ก ํด๋ ๋๋ค. ์ ํ์ฌํญ. ์๋ ํ์ผ ๊ตฌ์กฐ์ ๋์ผํ์ง ํ์ธํด๋ณด์.
(1) devtools ์๊ฐ
๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด, ๋ฆฌ๋์ค devtools๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
๋ค๋ฅธ ํจํค์ง์์๋ ์ฐพ์๋ณผ ์ ์๋ ๊ต์ฅํ ๊ฐ๋ ฅํ ๊ฐ๋ฐํด. ํ์ฌ ํ๋ก์ ํธ์ state ์ํ๋ผ๋๊ฐ, ์ด๋ค ์ก์ ์ด ์ผ์ด๋ฌ์ ๋ ๊ทธ ์ก์ ์ด ๋ฌด์์ด๊ณ , ๊ทธ๊ฒ์ผ๋ก ์ธํด state๊ฐ ์ด๋ป๊ฒ ๋ณ๊ฒฝ๋์๋์ง ๋ฑ ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ฐํ ๋ ์์ฃผ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
์ด devtools ๋๋ฌธ์ ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ๋ค๊ณ ๋งํ๋ ๊ฒ๋ ๊ณผ์ธ์ด ์๋๋ค. ์ฐ๋ฆฌ๋ ํ๋ฒ ์ฌ์ฉํด๋ณด์.
๊ตฌ๊ธ ์น์คํ ์ด์์ ํ๋ฌ๊ทธ์ธ์ ์ค์นํด์ผ ํ๋ค.
(2) ์ฌ์ฉํ๋ ๋ฒ
์น ์คํ ์ด์์ devtools๋ฅผ ์ค์นํ๊ณ ๋ง์ฝ ๋ฆฌ์กํธ ํ๋ก์ ํธ์์ ๋ฆฌ๋์ค๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉด ์ด๋ ๊ฒ ํ๋ฌ๊ทธ์ธ์ ๋ น์์ผ๋ก ๋ถ์ด ์ผ์ง๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐ๋ฐ์๋๊ตฌ ํญ์์ Redux ๋ผ๋ ๋ฉ๋ด๋ฅผ ๋ณผ ์ ์๋ค.
์ด์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ Counter ํ๋ก๊ทธ๋จ์ ๋ฆฌ๋์ค devools ๋ฅผ ๋์๋๊ณ ํ๋ฒ ์๋์์ผ ๋ณด์.
๋ํ๊ธฐ
๋ฒํผ์ ๋๋ฅด๋ฉด addNumber
๋ผ๋ ์ก์
์ด dispatch ๋๋ค. ๊ทธ๊ฒ์ devtools์์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด๊ณ , ๊ทธ๊ฒ์ผ๋ก ์ธํด state ๊ฐ์ด ์ด๋ป๊ฒ ๋ณํ๋์ง๋ฅผ ์ ๋ถ ๋ณด์ฌ์ค๋ค.
ํ๋ก์ ํธ๊ฐ ์ ์ ๋ณต์กํด์ง์๋ก ๋ก๊ทธ๋ฅผ ํ์ธํ๋ ๊ฒ์ด ์ฝ์ง ์์๋ฐ, ์ด ํด์ ์ด์ฉํด์ ์ ๋ง ์ฝ๊ฒ ๋๋ฒ๊น ์ ํ ์ ์๋ค. devtools๋ฅผ ์ ํ์ฉํด๋ณด์.
๐ก **ํดํท์ด ์๋ ์ผ๋ฐ ๋ฆฌ๋์ค์์ devtools๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ๋ค๋ฉด, ๋ณ๋ ์ค์ ์ด ํ์ํ๋ค. ํดํท์ devtools์ด ๋ด์ฅ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ์ฝ๋ ์ค์ ์์ด ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ.** ## 4. Flux ํจํด๋งํ๋ก ๋ณด๋ Flux
Flux์ redux์ ๊ด๊ณ