Redux
리덕스(Redux)는 어플리케이션 상태관리를 위해 만들어진 JS 라이브러리이며, 특히 리액트와 함께 사용된다.
전역 상태관리 라이브러리이며 단방향 데이터 흐름의 리액트를 사용할 때에 불편한 점들을 해소해준다.
예를 들면 조부모 컴포넌트에서 손자 컴포넌트로 값을 보내고자 할때 반드시 부모 컴포넌트를 거쳐야만 하기 때문에 부모 컴포넌트에서 그 값이 필요 없어도 불필요하게 거쳐야한다.
그렇기 때문에 중앙에서 상태관리 해주는 것이 필요하다.
리덕스의 주요 기능
1. 중앙화된 상태 관리
어플리케이션의 모든 상태를 하나의 중앙 저장소(Store)에서 관리하며, 상태를 한 곳에서 관리하므로 데이터 흐름을 추적하기 쉽다.
2. 예측 가능한 상태 변경
상태는 리듀서(Reducer)라는 순수 함수에 의해 변경되며, 리듀서는 이전 상태와 액션을 입력받아 새로운 상태를 반환한다.
3. 단방향 데이터 흐름
데이터는 단방향으로만 흐르며, 어플리케이션의 디버깅과 유지보수를 간소화 한다.
* 리덕스의 단방향 데이터 흐름이란?
- state는 특정 시점의 앱 상태를 설명한다.
- UI는 해당 상태를 기반으로 렌더링된다.
- 어떤 이벤트가 발생하면 발생한 일에 따라 state가 업데이트 된다.
- 새로운 상태에 따라 UI가 다시 렌더링된다.
과정
- UI가 작업(이벤트)를 전달한다.
- store는 reducer를 실행하고, 발생한 상황(action type)에 따라 상태가 업데이트된다.
- store는 상태가 변경되었음을 UI에게 알린다.
설치 및 사용법 (feat.Redux Toolkit)
1. Redux Toolkit 설치
리덕스는 초기 설정과 사용법이 복잡하다는 평을 받았지만, Redux Toolkit이 도입되면서 설정이 간소화 되었다.
npm install @reduxjs/toolkit react-redux
2. Store 생성
configureStore는 스토어 설정을 단순화하며 Redux DevTools와의 통합을 기본적으로 지원한다.
// src/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './features/counter/counterSlice';
const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export default store;
3. Slice 생성
slice는 리듀서와 액션을 한 곳에서 정의할 수 있는 Redux Toolkit의 주요 기능며, 상태(state), 리듀서(reducer) 그리고 액션(action)을 간편하게 하나의 객체로 묶어 관리한다.
// src/features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// **키워드 설명**
// - `increment`: 상태의 값을 1 증가시키는 액션입니다.
// - `decrement`: 상태의 값을 1 감소시키는 액션입니다.
// - `incrementByAmount`: 전달된 값을 받아 상태에 더하는 액션입니다.
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
4. Provider로 감싸기
Reat 어플리케이션에서 Redux를 사용하려면 Provider로 컴포넌트를 감싸야 스토어를 컴포넌트에서 사용할 수 있다.
// src/App.jsx
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './features/counter/Counter';
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
export default App;
5. useSelector와 useDispatch 사용
useSelector는 스토어의 상태를 읽는 데 사용되며, useDispatch는 액션을 디스패치하는 데 사용된다.
// src/features/counter/Counter.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './counterSlice';
function Counter() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<h1>{count}</h1>
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(decrement())}>-</button>
<button onClick={() => dispatch(incrementByAmount(5))}>+5</button>
</div>
);
}
export default Counter;
6. 간단한 카운트 모듈 예제
디렉토리 구조
src/
├── features/
│ └── counter/
│ ├── counterSlice.js // Slice 정의
│ ├── Counter.jsx // counter 컴포넌트 정의
├── store.js // 스토어 설정
└── App.jsx // 메인 애플리케이션
1. Slice 생성
// src/features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
2. 스토어 설정
// src/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './features/counter/counterSlice';
const store = configureStore({
reducer: { counter: counterReducer },
});
export default store;
3. 컴포넌트 작성
// src/features/counter/Counter.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './counterSlice';
function Counter() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
}
export default Counter;
4. App.jsx 작성
// src/App.jsx
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './features/counter/Counter';
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
export default App;
💡 Redux Tip
1. Redux Tookit 적극 활용
createSlice, configureStore를 사용하면 설정이 단순화된다.
2. 비동기 작업 관리
Redux Toolkit의 createAsyncThunk를 사용하면 비동기 로직을 간단히 처리할 수 있다.
3. Redux DevTools
configureStore는 기본적을 Redux DevTools와 통합되어 상태와 액션을 실시간으로 추적할 수 있다.
4. 폴더 구조 관리
Feature 기반 폴더 구조를 사용하여 파일을 정리하면 유지보수가 편리하다.
'항해99 플러스 > React 스터디' 카테고리의 다른 글
[React 스터디] React Router Dom (0) | 2025.03.04 |
---|---|
[React 스터디] React-Query(Tanstack-Query) (0) | 2025.02.25 |
[React 스터디] 2주차 숙련 단계 (0) | 2025.02.17 |
[React 스터디] 2주차 입문 단계 (1) | 2025.02.16 |
[React 스터디] 1주차 입문 단계 (1) | 2025.02.05 |