React.js - redux tool kit
https://lshjju.tistory.com/152
React.js - redux toolkit- 리덕스툴킷
Redux Toolkit(리덕스 툴킷)이란 무엇인가요?Redux Toolkit은 Redux(리덕스)를 더 쉽고 효율적으로 사용하기 위해 만들어진 **공식적으로 권장하는 '도구 모음'**입니다. Redux 자체는 강력하지만, 설정하고
lshjju.tistory.com
https://lshjju.tistory.com/162
reducer와 reducers의 차이
React에서 reducer (단수)와 reducers (복수)의 차이에 대해 알기 쉽게 설명해 드릴게요. 특히 Redux Toolkit의 createSlice를 사용할 때 이 두 단어가 자주 나와 헷갈리실 수 있는데, 아주 간단해요!마치 **요리
lshjju.tistory.com
https://lshjju.tistory.com/160
reducer / redux / redux-toolkit
reducer / redux / redux-toolkit 관계와 차이 React에서 reducer, Redux, 그리고 Redux Toolkit은 상태 관리와 관련해서 서로 깊은 관계를 가지고 있어요. 이걸 마치 요리에 비유해서 알기 쉽게 설명해 드릴게요.
lshjju.tistory.com
Final build
https://stackblitz.com/edit/vitejs-vite-ufskmlaq?file=src%2FApp.jsx
egoing - redux tool kit - StackBlitz
Next generation frontend tooling. It's fast!
stackblitz.com
New project building
https://lshjju.tistory.com/104
StackBlitz web editor - 스택블리츠 웹 에디터
스택블리츠로 새 프로젝트 생성하기 https://stackblitz.com/ 로그인 방법 선택 대쉬보드에서 new project + 버튼 - 탭 모달 - frontend 탭 - 탭react javascript - 탭 바이트 리액트가 생성됩니다.프로젝트 생성 완
lshjju.tistory.com
카운트 데이터바인딩 합니다.
function Counter() {
return (
<div>
<button>+</button> 0
</div>
);
}
펑션 앱 위에 펑션 카운터 추가 합니다.
export default function App() {
return (
<div>
<Counter></Counter>
</div>
);
}
펑션 카운터 렌더링 합니다.
https://lshjju.tistory.com/150
React.js - redux - 리액트 리덕스
Redux(리덕스)란 무엇인가요? Redux는 React(뿐만 아니라 다른 JavaScript 라이브러리/프레임워크)에서 **애플리케이션의 상태(State)를 효율적으로 관리하기 위한 예측 가능한 상태 컨테이너(Predictable Stat
lshjju.tistory.com
redux
react-redux
인스톨 합니다.
import { createStore } from "redux";
스토어를 생성하기 위해 크리에이트스토어 레거시 임포트 합니다.
import { createStore } from 'redux';
// Redux의 핵심 함수인 createStore를 가져와 상태 저장소(스토어)를 생성합니다.
const store = createStore(reducer, initialState);
스토어 스코프는 글로벌이어야 합니다.
그러므로 임포트 아래에 스토어를 초기화 합니다.
파라미터로 리듀서와 이니셜스테이트를 사용합니다.
이렇게 만든 리덕스스토어는 프로바이더로 컴포넌트에 공급될 것입니다.
const store = createStore(reducer, initialState);
// 위에서 정의한 리듀서와 초기 상태를 사용하여 Redux 스토어를 생성합니다.
const initialState = { value: 0 };
스토어는 이니셜스테이트가 필요합니다.
스토어 변수 위에 이니셜스테이트를 오브젝타입으로 초기화 합니다.
const initialState = { value: 0 };
// Redux 스토어의 초기 상태를 정의합니다. 'value'는 0으로 시작합니다.
function reducer(state, action) {
return state;
}
스토어는 리듀서도 필숩니다.
임포트 아래에 펑션리듀서를 추가합니다.
이 펑션은 현재상태와 액션을 파라미터로 받아 연산한 결과를 리턴 합니다.
/**
* Redux 리듀서 함수입니다.
* 현재 상태(state)와 발생한 액션(action)을 인자로 받아 새로운 상태를 반환합니다.
* 이 함수는 아직 상태를 변경하는 로직이 구현되어 있지 않으며, 현재 상태를 그대로 반환합니다.
* @param {object} state - 현재 애플리케이션의 상태
* @param {object} action - 발생한 액션 객체
* @returns {object} - 새로운 상태
*/
function reducer(state, action) {
return state;
}
import { Provider } from "react-redux";
컴포넌트와 리덕스스토어를 연결하는 프로바이더 임포트 합니다.
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
펑션앱 디브를 프로바이더로 래핑해서 스토어를 공급 합니다.
import { Provider, useSelector } from "react-redux";
스토어 상태를 조회할 수 있는 유즈셀렉터를 임포트 합니다.
import { Provider, useSelector } from 'react-redux';
// React 애플리케이션에 Redux 스토어를 연결하는 Provider와, 스토어의 상태를 컴포넌트에서 조회할 수 있는 useSelector Hook을 가져옵니다.
const count = useSelector((state) => state.value);
펑션카운터 리턴 위에 유즈셀렉터로 카운트를 초기화 합니다.
이제 펑션카운터와 스토어가 연결되었습니다.
파라미터에 스테이트를 리턴하는 펑션도 살짝 껴줍니다.
즉 이 컴포넌트에서 스토어 밸류를 가져 와서 조회할 수 있습니다.
// useSelector Hook을 사용하여 Redux 스토어의 'value' 상태를 가져옵니다.
// 이 값은 'count' 변수에 할당되어 컴포넌트 내에서 사용됩니다.
const count = useSelector((state) => state.value);
<div>
<button>+</button> {count}
</div>
펑션카운터에 카운트를 데이터 바인딩 합니다.
test
카운터가 표시 되는지 체크 합니다.

Completion
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createStore } from 'redux';
import { Provider, useSelector } from 'react-redux';
function reducer(state, action) {
return state;
}
const initialState = { value: 0 };
const store = createStore(reducer, initialState);
function Counter() {
const count = useSelector((state) => state.value);
return (
<div>
<button>+</button> {count}
</div>
);
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}
버튼을 탭해서 데이터를 증가 시킵니다.
import { Provider, useSelector, useDispatch } from "react-redux";
액션을 보내기 위한 유즈디스패치를 임포트 합니다.
import { Provider, useSelector, useDispatch } from "react-redux";
// useDispatch: Redux store로 액션(action)을 보낼 수 있게 하는 Hook입니다.
const dispatch = useDispatch();
펑션카운터 카운트변수 위에 디스패치를 유즈디스패치로 초기화 합니다.
지금부터 유즈디스패치를 사용할 수 있습니다.
// useDispatch Hook을 사용하여 Redux store로 액션을 보낼 수 있는 dispatch 함수를 가져옵니다.
const dispatch = useDispatch();
<div>
<button
onClick={() => {
dispatch({ type: "up", step: 2 });
}}
>
+
</button>{" "}
{count}
</div>
펑션카운터 리턴 내부 버튼에 이벤트를 겁니다.
액션을 리듀서로 디스패치 합니다.
그러면 펑션리듀서는 상태를 업테이트 합니다.
왜냐하면 그렇게 약속되어 있기 때문입니다.
액션 보낼 때 오브젝 타입으로 스텝도 같이 보냅니다.
<div>
<button
// 버튼 클릭 시 익명 함수가 실행됩니다.
// 이 함수 내에서 dispatch를 호출하여 Redux store로 액션을 보냅니다.
// 액션 객체는 type: "up"과 step: 2를 포함하고 있으며, 이는 리듀서가 상태를 업데이트하는 데 사용됩니다.
onClick={() => {
dispatch({ type: "up", step: 2 });
}}
>
+ {/* 버튼에 표시될 텍스트입니다. */}
</button>{" "}
{count} {/* 현재 Redux store에서 가져온 count 값을 화면에 표시합니다. */}
</div>
function reducer(state, action) {
if (action.type === "up") {
return { ...state, value: state.value + action.step };
}
return state;
}
펑션리듀서에서 타입 액션을 받기 위해 이프문을 추가하고 결과를 리턴합니다.
기존 스테이트를 유지하면서 복제합니다.
오른쪽 연산을 처리합니다.
연산 결과를 왼쪽에 업데이트 합니다.
그 외 액션인 경우 원래 상태 그대로 리턴합니다.
/**
* Redux 리듀서 함수입니다.
* 현재 상태(state)와 발생한 액션(action)을 인자로 받아, 액션의 타입에 따라 새로운 상태를 반환합니다.
* Redux에서 상태 변경은 반드시 이 리듀서 함수를 통해서만 이루어집니다.
*
* @param {object} state - 현재 애플리케이션의 상태 객체 (초기값은 initialState입니다).
* @param {object} action - 상태 변경을 지시하는 객체 (예: { type: "up", step: 2 }).
* @returns {object} - 변경된 새로운 상태 객체입니다.
*/
function reducer(state, action) {
// 액션의 타입이 "up"인 경우, 상태의 value를 액션의 step만큼 증가시킵니다.
// ...state를 사용하여 기존 상태를 불변적으로 유지하면서 필요한 속성만 업데이트합니다.
if (action.type === "up") {
return { ...state, value: state.value + action.step };
}
// 그 외의 액션 타입에 대해서는 현재 상태를 변경하지 않고 그대로 반환합니다.
return state;
}
test
카운터를 탭했을 때 숫자가 2씩 증가하는지 체크 합니다.

Completion
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
function reducer(state, action) {
if (action.type === 'up') {
return { ...state, value: state.value + action.step };
}
return state;
}
const initialState = { value: 0 };
const store = createStore(reducer, initialState);
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state) => state.value);
return (
<div>
<button
onClick={() => {
dispatch({ type: 'up', step: 2 });
}}
>
+
</button>{' '}
{count}
</div>
);
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}
리덕스툴킷을 설치하는 두 가지 방법
https://lshjju.tistory.com/152
React.js - redux toolkit- 리덕스툴킷
Redux Toolkit(리덕스 툴킷)이란 무엇인가요?Redux Toolkit은 Redux(리덕스)를 더 쉽고 효율적으로 사용하기 위해 만들어진 **공식적으로 권장하는 '도구 모음'**입니다. Redux 자체는 강력하지만, 설정하고
lshjju.tistory.com
리덕스를 리덕스툴킷으로 업그레이드 합니다.
크리에이트슬라이스로 스토어를 관리 합니다.
npm install @reduxjs/toolkit
@reduxjs/toolkit 을 설치합니다.
import { createSlice } from "@reduxjs/toolkit";
리듀서/액션타입 관리 도구 크리에잇슬라이스 임포트 합니다.
import { createSlice } from "@reduxjs/toolkit";
// createSlice: Redux 리듀서와 액션 타입을 한 번에 정의할 수 있도록 도와주는 유틸리티 함수입니다.
const counterSlice = createSlice({
name: "counter",
initialState: { value: 0 },
reducers: {
up: (state, action) => {
state.value = state.value + action.step;
},
},
});
임포트 아래에 기존의 리듀서를 대신 할 슬라이스를 세팅합니다.
슬라이스 이름 세팅 합니다.
이것은 액션타입의 접두사로 사용합니다.
슬라이스 초기값 세팅 합니다.
리듀서스 세팅합니다.
업 액션이 디스패치 되면 콜 할 펑션을 세팅 합니다.
... 로 원본데이터 복제할 필요 없습니다.
리덕스툴킷에 이 일을 대신 해 주는 내장 기능이 있습니다.
연산해서 데이터를 갱신 합니다.
/**
* createSlice를 사용하여 Redux 상태 슬라이스(slice)를 정의합니다.
* 이 함수는 액션 타입, 액션 생성자, 그리고 리듀서 로직을 한데 모아 관리할 수 있게 해줍니다.
*/
const counterSlice = createSlice({
name: "counter", // 이 슬라이스의 이름입니다. 액션 타입의 접두사로 사용됩니다 (예: "counter/up").
initialState: { value: 0 }, // 이 슬라이스의 초기 상태입니다. 'value'는 0으로 시작합니다.
reducers: {
// 리듀서 함수들을 정의합니다. 여기서 각 함수는 특정 액션에 대한 상태 변경 로직을 포함합니다.
// Redux Toolkit에서는 Immer 라이브러리가 내장되어 있어, 상태를 직접 '변경'하는 것처럼 코드를 작성해도 불변성을 유지합니다.
up: (state, action) => {
// 'up' 액션이 디스패치될 때 실행되는 리듀서 로직입니다.
// `action.step` 값만큼 `state.value`를 증가시킵니다.
state.value = state.value + action.step;
},
},
});
import { createSlice, configureStore } from "@reduxjs/toolkit";
스토어를 효율적으로 세팅하기 위해 컨피규어스토어를 임포트 합니다.
import { createSlice, configureStore } from "@reduxjs/toolkit";
// configureStore: Redux 스토어 설정을 간소화하고, 기본적으로 Redux DevTools 확장 프로그램 통합 및 일부 미들웨어를 포함하여 스토어를 생성해주는 함수입니다.
/*
function reducer(state, action) {
if (action.type === "up") {
return { ...state, value: state.value + action.step };
}
return state;
}
const initialState = { value: 0 };
const store = createStore(reducer, initialState);
*/
리듀서를 슬라이스로 업그레이드 할 것입니다.
그러므로 리듀서/이니셜스테이트/스토어를 주석처리 합니다.
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
리덕스를 리덕스툴킷으로 업그레이드 합니다.
컨피규어 스토어는 리덕스 스토어 콘트롤 타워 입니다.
카운터슬라이스 아래에 스토어를 세팅 합니다.
카운터슬라이스를 카운터에 세팅해서 관리 합니다.
이제부터 이 스토어를 원하는 곳에 공급할 수 있습니다.
이 스토어에 담긴 특정 데이터를 사용하려면 유즈셀렉터로 지정하여 사용할 수 있습니다.
/**
* configureStore를 사용하여 Redux 스토어를 설정하고 생성합니다.
* Redux Toolkit을 사용하면 스토어 설정을 훨씬 간편하게 할 수 있습니다.
*/
const store = configureStore({
reducer: {
// 여러 슬라이스의 리듀서들을 결합하여 루트 리듀서를 만듭니다.
// 'counter'라는 이름 아래에 counterSlice의 리듀서를 할당합니다.
counter: counterSlice.reducer,
},
});
const count = useSelector((state) => {
return state.counter.value;
});
펑션카운터 내부에서 카운터 슬라이스가 연산한 스테이트 밸류를 데이터로 사용해야 합니다.
유즈셀렉터로 그것을 가져옵니다.
그 데이터로 카운트를 초기화 합니다.
현재 유저는 이벤트를 발생시키지 않았습니다.
즉, 디스패치가 실행되지 않았습니다.
그러므로 카운트 데이터는 이니셜스테이트 밸류인 0이 찍힐 것입니다.
// useSelector Hook을 사용하여 Redux 스토어의 상태에서 필요한 데이터를 선택합니다.
// configureStore에서 'counter'라는 이름으로 리듀서를 할당했으므로,
// 상태에 접근할 때 `state.counter.value`와 같이 경로를 지정해야 합니다.
const count = useSelector((state) => {
return state.counter.value;
});
test
0이 데이터 바인딩 되는지 체크 합니다.

Completion
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
import { configureStore, createSlice } from '@reduxjs/toolkit';
const couterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
up: (state, action) => {
state.value = state.value + action.step;
},
},
});
const store = configureStore({
reducer: {
counter: couterSlice.reducer,
},
});
/*
function reducer(state, action) {
if (action.type === 'up') {
return { ...state, value: state.value + action.step };
}
return state;
}
const initialState = { value: 0 };
const store = createStore(reducer, initialState);
*/
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state) => {
return state.counter.value;
});
return (
<div>
<button
onClick={() => {
dispatch({ type: 'up', step: 2 });
}}
>
+
</button>{' '}
{count}
</div>
);
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}
데이터를 증가 시킵니다.
name: "counterSlice",
스토어 counter와 카운터슬라이스 네임이 같습니다.
헷갈리지 않도록 카운터슬라이스 네임을 - counter에서 couterSlice로 변경합니다.
onClick={() => {
dispatch({ type: "counterSlice/up", step: 2 });
}}
펑션카운터 온클릭메소드 디스패치 타입 up을 counterSlice/up으로 변경합니다.
counterSlice는 카운터슬라이스 변수 내부에 있는 네임입니다.
유저가 탭하면 타입과 스텝을 스토어로 디스패치 합니다.
그리고 슬라이스가 리턴한 밸류가 새로운 스테이트가 됩니다.
이제부터 플러스 유아이를 탭하면 값이 증가합니다.
// 버튼 클릭 시 호출되는 이벤트 핸들러입니다.
// dispatch 함수를 사용하여 'counterSlice/up' 타입의 액션과 'step' 값(2)을 포함하는 액션 객체를 스토어로 보냅니다.
// 이 액션은 counterSlice 내의 'up' 리듀서에 의해 처리됩니다.
// Redux Toolkit에서는 `counterSlice.actions.up(2)`와 같이 액션 생성자를 사용하는 것이 권장되는 방식입니다.
onClick={() => {
dispatch({ type: "counterSlice/up", step: 2 });
}}
test
플러스 탭 체크 합니다.

Completion
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counterSlice',
initialState: { value: 0 },
reducers: {
up: (state, action) => {
state.value = state.value + action.step;
},
},
});
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
/*
function reducer(state, action) {
if (action.type === 'up') {
return { ...state, value: state.value + action.step };
}
return state;
}
const initialState = { value: 0 };
const store = createStore(reducer, initialState);
*/
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state) => {
return state.counter.value;
});
return (
<div>
<button
onClick={() => {
dispatch({ type: 'counterSlice/up', step: 2 });
}}
>
+
</button>{' '}
{count}
</div>
);
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}
디스패치를 액션스 오브젝으로 업그레이드 합니다.
onClick={() => {
dispatch(counterSlice.actions.up(2));
}}
펑션카운터 디스패치를 액션스코드로 변경 합니다.
리덕스툴킷은 리듀서 펑션을 참고해서 자동으로 액션을 생성하는 액선크리에이터를 생성해 줍니다.
즉, 크리에잇슬라이스는 리듀서펑션 액션을 액션스 오브젝에 자동 생성해 줍니다.
{ type: "counterSlice/up", payload: 2 } 이것이 액션스 오브젝에 세팅 합니다.
이것은 리덕스 툴킷이 권장하는 코드입니다.
// `dispatch(counterSlice.actions.up(2))`는 Redux Toolkit에서 권장하는 액션 디스패치 방식입니다.
// `createSlice`는 자동으로 리듀서 함수에 해당하는 액션 생성자들을 `.actions` 객체 안에 생성합니다.
// `counterSlice.actions.up(2)`는 `{ type: "counterSlice/up", payload: 2 }`와 같은 액션 객체를 생성하여 반환하고,
// 이를 `dispatch` 함수가 스토어로 보냅니다. 이는 수동으로 액션 타입을 지정하는 것보다 오류 발생 가능성을 줄여줍니다.
onClick={() => {
// dispatch({ type: "counterSlice/up", step: 2 }); // 이전 방식 (주석 처리됨)
dispatch(counterSlice.actions.up(2)); // Redux Toolkit 권장 방식: 액션 생성자 사용
}}
reducers: {
up: (state, action) => {
state.value = state.value + action.payload;
},
}
카운터슬라이스에서 업으로 디스패치 받았습니다.
페이로드는 액션크리에이터 실행 시 데이터를 받는 프로퍼티 입니다.
즉, 페이로드 데이터 만큼 데이터를 증가시킵니다.
그래서 툴킷은 액션을 직접 코딩하지 않고 자동으로 만들어 주는 이점을 제공 합니다.
reducers: {
// 리듀서 함수들을 정의합니다. 각 함수는 특정 액션에 대한 상태 변경 로직을 포함합니다.
// Redux Toolkit에서는 Immer 라이브러리가 내장되어 있어, 상태를 직접 '변경'하는 것처럼 코드를 작성해도 불변성을 유지합니다.
up: (state, action) => {
// 'up' 액션이 디스패치될 때 실행되는 리듀서 로직입니다.
// `action.payload`는 Redux Toolkit에서 권장하는 표준 방식으로, 액션과 함께 전달되는 주요 데이터를 포함합니다.
// 여기서는 payload의 값만큼 `state.value`를 증가시킵니다.
state.value = state.value + action.payload;
},
},
test
잘 작동하는지 체크합니다.

Completion
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counterSlice',
initialState: { value: 0 },
reducers: {
up: (state, action) => {
state.value = state.value + action.payload;
},
},
});
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
/*
function reducer(state, action) {
if (action.type === 'up') {
return { ...state, value: state.value + action.step };
}
return state;
}
const initialState = { value: 0 };
const store = createStore(reducer, initialState);
*/
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state) => {
return state.counter.value;
});
return (
<div>
<button
onClick={() => {
dispatch(counterSlice.actions.up(2));
}}
>
+
</button>{' '}
{count}
</div>
);
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}
Comment ver
import { useState } from 'react'; // React에서 상태 관리를 위한 useState Hook을 가져옵니다. (현재 코드에서는 직접 사용되지 않습니다.)
import reactLogo from './assets/react.svg'; // React 로고 SVG 파일을 가져옵니다. (현재 코드에서는 사용되지 않습니다.)
import viteLogo from '/vite.svg'; // Vite 로고 SVG 파일을 가져옵니다. (현재 코드에서는 사용되지 않습니다.)
import './App.css'; // 이 컴포넌트에 적용될 CSS 스타일 파일을 가져옵니다. (스타일 관련 파일입니다.)
import { createStore } from 'redux'; // Redux의 핵심 함수인 createStore를 가져옵니다. (현재 코드에서는 Redux Toolkit의 configureStore로 대체되어 사용되지 않습니다.)
import { Provider, useSelector, useDispatch } from 'react-redux'; // React 애플리케이션에 Redux 스토어를 연결하는 react-redux 라이브러리에서 다음을 가져옵니다.
// Provider: Redux 스토어를 React 컴포넌트 트리에 제공하여 모든 하위 컴포넌트가 스토어에 접근할 수 있도록 합니다.
// useSelector: Redux 스토어의 상태에서 필요한 데이터를 선택하여 가져올 수 있게 하는 Hook입니다.
// useDispatch: Redux 스토어로 액션(Action)을 디스패치(Dispatch)할 수 있게 하는 Hook입니다.
import { configureStore, createSlice } from '@reduxjs/toolkit'; // Redux Toolkit에서 다음을 가져옵니다.
// configureStore: Redux 스토어 설정을 간소화하고, 개발 도구 및 미들웨어 통합을 용이하게 하는 함수입니다.
// createSlice: 리듀서, 액션 타입, 액션 생성자 등을 간결하게 정의하고 관리할 수 있도록 돕는 유틸리티 함수입니다.
/**
* Redux Toolkit의 `createSlice`를 사용하여 'counterSlice'라는 이름의 상태 슬라이스를 정의합니다.
* 이 함수는 특정 기능(여기서는 카운터)에 대한 상태, 액션, 리듀서를 한 곳에 모아 관리하며 Redux 개발을 간소화합니다.
*/
const counterSlice = createSlice({
name: 'counterSlice', // 이 슬라이스의 이름입니다. 생성되는 액션 타입의 접두사로 사용됩니다 (예: "counterSlice/up").
initialState: { value: 0 }, // 이 슬라이스의 초기 상태를 정의합니다. 'value'는 0으로 시작합니다.
reducers: {
// 리듀서 함수들을 정의합니다. 각 함수는 특정 액션에 대한 상태 변경 로직을 포함합니다.
// Redux Toolkit은 Immer 라이브러리를 내장하고 있어, 상태를 직접 '수정'하는 것처럼 코드를 작성해도 내부적으로 불변성을 유지합니다.
up: (state, action) => {
// 'up' 액션이 디스패치될 때 실행되는 리듀서 로직입니다.
// `action.payload`는 Redux Toolkit에서 액션과 함께 전달되는 주요 데이터를 담는 표준 속성입니다.
// 여기서는 `payload`의 값만큼 `state.value`를 증가시킵니다.
state.value = state.value + action.payload;
},
},
});
/**
* Redux Toolkit의 `configureStore`를 사용하여 애플리케이션의 메인 Redux 스토어를 설정하고 생성합니다.
* 이 함수는 Redux 스토어의 복잡한 설정을 자동화하여 개발 편의성을 높입니다.
*/
const store = configureStore({
reducer: {
// 애플리케이션의 모든 리듀서들을 통합하여 루트 리듀서를 구성합니다.
// 'counter'라는 키 아래에 `counterSlice`에서 생성된 리듀서를 할당합니다.
// 이렇게 함으로써 `state.counter`를 통해 해당 슬라이스의 상태에 접근할 수 있게 됩니다.
counter: counterSlice.reducer,
},
});
/**
* 카운터 값을 표시하고 증가시키는 기능을 가진 React 컴포넌트입니다.
*/
function Counter() {
// `useDispatch` Hook을 사용하여 Redux 스토어로 액션을 보내는 `dispatch` 함수를 가져옵니다.
const dispatch = useDispatch();
// `useSelector` Hook을 사용하여 Redux 스토어의 현재 상태에서 'counter' 슬라이스의 'value' 값을 선택하여 가져옵니다.
// 이 값은 `count` 변수에 할당되어 컴포넌트 렌더링에 사용되며, 상태가 변경될 때 컴포넌트가 자동으로 리렌더링됩니다.
const count = useSelector((state) => {
return state.counter.value;
});
return (
<div>
<button
// 버튼 클릭 시 호출되는 이벤트 핸들러입니다.
// `dispatch(counterSlice.actions.up(2))`는 Redux Toolkit에서 권장하는 액션 디스패치 방식입니다.
// `createSlice`는 리듀서 함수에 해당하는 액션 생성자들을 `.actions` 객체 안에 자동으로 생성합니다.
// `counterSlice.actions.up(2)`를 호출하면 `{ type: "counterSlice/up", payload: 2 }`와 같은 액션 객체가 생성되어 반환되며,
// 이 액션 객체를 `dispatch` 함수가 스토어로 보냅니다. 이는 수동으로 액션 타입을 지정하는 것보다 타입 안정성과 코드 가독성을 높여줍니다.
onClick={() => {
dispatch(counterSlice.actions.up(2));
}}
>
+ {/* 버튼에 표시될 텍스트입니다. */}
</button>{' '}
{count} {/* 현재 Redux 스토어에서 가져온 count 값을 화면에 표시합니다. */}
</div>
);
}
/**
* 애플리케이션의 최상위 컴포넌트입니다.
* Redux 스토어를 전체 React 컴포넌트 트리에 연결합니다.
*/
export default function App() {
return (
// `Provider` 컴포넌트를 사용하여 생성된 Redux 스토어(`store`)를 하위 컴포넌트들에게 제공합니다.
// `Provider` 내부에 렌더링되는 모든 컴포넌트는 `react-redux`의 Hook(`useSelector`, `useDispatch`)을 통해
// 스토어 상태에 접근하고 액션을 디스패치할 수 있게 됩니다.
<Provider store={store}>
<div>
<Counter></Counter> {/* Counter 컴포넌트를 렌더링합니다. */}
</div>
</Provider>
);
}
코드를 분리 합니다.
import { createSlice } from "@reduxjs/toolkit";
const counterSlice = createSlice({
name: "counterSlice",
initialState: { value: 0 },
reducers: {
up: (state, action) => {
state.value = state.value + action.payload;
},
},
});
export default counterSlice;
export const { up } = counterSlice.actions;
counterSlice.jsx
카운터슬라이스를 파일로 분리 합니다.
리덕스툴킷 임포트 합니다.
앱에서 카운터슬라이스를 컷하고 페이스트 합니다.
카운터슬라이스 익스포트 합니다.
App.js 코드를 간결하게 하기 위해 counterSlice.actions를 up 에 담아서 익스포트 합니다.
import { configureStore } from "@reduxjs/toolkit";
import counterSlice from "./counterSlice";
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
export default store;
stoer.jsx
스토어를 파일로 분리 합니다.
리덕스툴킷 임포트 합니다.
카운터슬라이스 임포트 합니다.
앱에서 스토어를 컷하고 페이스트 합니다.
스토어 익스포트 합니다.
import store from "./store";
import { up } from "./counterSlice";
App.jsx
스토어와 카운트슬라이스 임포트 합니다.
<button
onClick={() => {
dispatch(up(2));
}}
>
+
</button>{" "}
App.jsx
디스패치 코드 체지방을 줄입니다.
test
코드를 분리하고 잘 작동하는지 체크 합니다.

Completion
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
import { configureStore, createSlice } from '@reduxjs/toolkit';
import store from './store';
import { up } from './counterSlice';
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state) => {
return state.counter.value;
});
return (
<div>
<button
onClick={() => {
dispatch(up(2));
}}
>
+
</button>{' '}
{count}
</div>
);
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}

'생활코딩! React 리액트 프로그래밍' 카테고리의 다른 글
| egoing - React redux - stackblitz ver (0) | 2025.09.06 |
|---|---|
| egoing - useReducer - stackblitz ver (0) | 2025.09.06 |
| egoing - Context API - stackblitz ver (0) | 2025.09.06 |
| egoing - styled component - stackblitz ver (0) | 2025.09.05 |
| egoing - React Router DOM - stackblitz ver (0) | 2025.09.05 |