티스토리 뷰

🚀 Redux(리덕스)란?

Redux(리덕스)란 자바스크립트 상태관리 라이브러리입니다. 

 

❓ 상태관리 도구가 필요한 이유

우리가 리액트에서 자식 컴포넌트에게 데이터를 전달하기 위해 props를 사용했었습니다. 그런데 자식 컴포넌트들 간의 다이렉트 데이터 전달은 불가능했었는데요. 자식 컴포넌트 간의 데이터를 주고 받을 때는 상태를 관리하는 부모 컴포넌트를 통해서 주고 받았었습니다.

그런데 자식이 많아진다면, 그리고 자식의 자식의 자식 컴포넌트들이 많아진다면 상태 관리가 매우 복잡해질 것입니다. 상태를 관리하는 상위 컴포넌트에서 계속 내려 받아야 하는 문제를 Props drilling 이슈라고 하기도 합니다.

component G에서 데이터가 필요한 건데 이 데이터를 전달 받기 위해서는 A에서 B로 B에서 C로, ... 이런식으로 중간 컴포넌트들은 해당 데이터가 필요 없음에도 전달을 위해 가지고 있어야 하는 불편함이 생기게 됩니다.

따라서 이러한 상태 관리의 복잡성을 해결해주는 라이브러리가 등장하게 되었습니다.

 

상태 관리 도구들은 다음과 같은 문제들을 해결해 줍니다.

  • 전역 상태 저장소 제공
  • Props drilling 이슈 해결

 

상태 관리 도구의 종류에는 React Context, Redux, MobX 등이 있습니다.

 

🚀 Redux의 기본 개념 : 세 가지 원칙

1. Single source of truth

  • 동일한 데이터는 항상 같은 곳에서 가지고 온다.
  • 즉, 스토어라는 하나뿐인 데이터 공간이 있다는 의미이다.

 

2. State is read-only

  • 리액트에서는 setState 메소드를 활용해야만 상태 변경이 가능하다.
  • 리덕스에서도 액션이라는 객체와 dispatch라는 메소드를 통해서만 상태를 변경할 수 있다.

 

3. Changes are made with pure functions

  • 변경은 순수함수로만 가능하다.
  • reducer와 연관되는 개념이다.
  • Store(스토어) - Action(액션) - Reducer(리듀서)

🚀 Store, Action, Reducer의 의미와 특징

 

🧺 Store (스토어) - 어디서든 사용할 데이터를 담은 저장소

Store는 상태가 관리되는 오직 하나의 공간입니다. 컴포넌트와는 별개로 스토어라는 공간이 있어서 그 스토어 안에 앱에서 필요한 상태를 담습니다. 컴포넌트에서 상태 정보가 필요할 때 스토어에 접근합니다.

 

📜 Action (액션) - state를 업데이트할 때 필요한 정보들을 담는다

Action은 앱에서 스토어에 운반할 데이터를 말합니다. Action은 객체 형식으로 되어있습니다.

 

🤖 Reducer (리듀서) - state와 action을 받으면 action의 type별로 로직을 처리한다

Action을 Store에 바로 전달하는 것이 아니라 Action을 Reducer에게 전달하면 그 주문을 보고 Store의 상태를 업데이트하는 것입니다. Action을 Reducer에 전달하기 위해서는 dispatch라는 메소드를 사용해야 합니다.

 

🚀 이제 진짜 Redux를 써보자

라이브러리 설치

$ npm i redux react-redux 
$ npm i -D redux-devtools-extension redux-logger

총 4개의 라이브러리를 설치한 것이 되는데요.

redux, react-redux는 리덕스를 사용하기 위한 라이브러리입니다.

redux-devtools-extension은 크롬 확장 프로그램에서 redux dev tools를 통해 설치할 수 있고, redux의 데이터 흐름을 알아보기 쉽게 하기 위해 사용합니다.

redux-logger는 redux를 통해 바뀔 이전 state, dispatch 실행으로 인해 바뀐 state가 콘솔에 찍혀 디버깅을 쉽게 해주는 라이브러리입니다.

 

1. rootReducer 파일을 생성

reducer는 state를 업데이트하는 로직입니다.

우리가 state를 여러 개 작성해서 사용하는 것처럼 reducer로 여러 개가 존재할 수 있습니다.

따라서 이 여러 개의 reducer들을 하나로 합칠 rootReducer가 필요합니다.

 

📄 reducer/index.js 파일

import {combineReducers} from 'redux';

export const rootReducer = combineReducers({}); // 객체 안에 생성한 reducer들을 넣어주면 됨

 

2. 세부 reducer를 정의해서 rootReducer에 넣어주자

const initialState = [
  {
    id: 1,
    name: '홍길동',
  },
];

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_USER':
      return [action.payload, ...state];
    default:
      console.log('지정된 타입이 없습니다');
      return state;
  }
};

export default reducer;

 

📄 reducer/index.js 파일

import {combineReducers} from 'redux';
import user from './user';

export const rootReducer = combineReducers({user});

 

3. 비어있는 store를 생성하고 rootReducer를 넣어주자

📄 store/store.js 파일

import {applyMiddleware, createStore} from 'redux';
import {rootReducer} from '../reducer';
import {composeWithDevTools} from 'redux-devtools-extension';
import logger from 'redux-logger';

const reduxConfig = () => {
  const store = createStore(
    rootReducer,
    process.env.NODE_ENV === 'development' &&
      composeWithDevTools(applyMiddleware(logger))
  );
  return store;
}
export default reduxConfig;

composeWithDevTools는 DevTools를 사용하겠다는 의미이고,

applyMiddleware(logger)는 미들웨어를 적용시켜주는 역할을 의미합니다.

즉, 미들웨어랑 devtools를 같이 쓰겠다는 의미가 됩니다.

 

그리고 이때 devtools는 개발 모드일 때만 실행되도록 코드를 작성해주었습니다.

 

4. Provider(덮개)를 생성하고 app.js에서 덮고 store 속성에 만들어놓은 store를 넣어주자

📄 app.js 파일

import {Provider} from 'react-redux';

import reduxConfig from './store/store';

function App() {
  const store = reduxConfig(); // 리턴값이 store이므로 실행해서 등록
  
  return (
    <Provider store={store}>
      // ...
    </Provider>
  )
}

 

5. store에 담겨있는 reducer를 사용 - useSelector

store에 담겨있는 reducer를 사용하기 위해서는 컴포넌트에서 useSelector를 사용하면 됩니다.

useSelector를 사용하면 reducer에서 state=initialState를 가지고 오게 됩니다.

const userList = useSelector((state) => state.user);

위 코드에서 state는 rootReducer 정도의 의미가 되며, 우리가 rootReducer에서 객체 안에 reducer들을 담았었죠?

그래서 state.user 이런식으로 가져왔던 것입니다.

위와 같이 코드를 작성하게 되면 userList에는 reducer에 state=initialState로 작성했었던 state가 담아지게 됩니다.

 

6. rootRducer에게 action 객체를 보내자 - useDispatch

useDispatch를 사용하면 rootReducer에 action 객체를 보낼 수 있습니다.

import {useDispatch} from 'react-redux';

const dispatch = useDispatch();

// ...

dispatch({
  type: 'ADD_USER',
  payload: {
    id: Math.floor(Math.random() * 100000),
    name: name.current.value,
  },
});

 

 

🚀 Redux DevTools를 사용해보자

크롬 웹 스토어에서 Redux DevTools를 추가해줍니다.

그러면 다음과 같이 DevTools에 Redux라는 항목이 추가되는데요.

이는 우리가 reduxConfig를 작성할 때 미들웨어로 작성해주었던 내용 때문에 확인이 가능한 것인데요.

사용하게 되면 위와 같이 효율적으로 state를 관리하고 확인이 가능해 집니다.

728x90
LIST
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함