🖥️Frontend/React

[React] Redux & RTK

뉴발자 2023. 11. 17.
728x90

 

 

 

 

 

 

 

 

 

 

 

 

 

 

그림 1-1. Redux

 

 

상태 관리 라이브러리

처음 리액트를 접하고 리덕스 강의를 보고 문법이 어렵다고 느껴졌다.

 

그래서 리덕스 대신 상태 관리 라이브러리인 zustand를 사용해서 상태를 관리했다.

 

확실히 zustand의 문법이 더 쉬웠고, 더욱 편리하게 상태를 관리할 수 있었다.

 

하지만 리덕스의 사용법을 모르고 넘어가면 안될 것 같아서 간단하게 학습을 진행하기로 했다.

 

 

리덕스

리덕스는 상태 관리 라이브러리이다.

 

리덕스 자체로도 사용 가능하지만 리액트와 함께 사용하면 더욱 편리하게 상태를 관리할 수 있게 된다.

 

리덕스는 단일 스토어에서 상태를 관리한다.

 

그래서 동일한 데이터는 항상 하나의 스토어에서만 관리하게 된다.

 

 

Store

리덕스를 사용하려면 먼저 스토어를 생성해줘야 한다.

 

스토어의 상태에 접근할 수 있게 하기 위해 Reducer를 생성해주고 스토어를 생성해주면 된다.

 

Reducer를 생성할 때는 상태를 관리할 state와 전달 받을 action을 매개변수로 가진다.

 

스토어를 사용하기 위해서는 최상위 컴포넌트에서 react-redux의 Provider로 감싸줘야한다.

 

그리고 필수 값으로 생성한 store가 들어가야만 한다.

// store.js

const reducer = (state, action) => {
  ...
};

export let store = Redux.createStore(reducer);


// App.jsx
import { Provider } from "react-redux";
import store from "./store";

const App = () => {
  <Provider store={store}>
  	...
  </Provider>
};

 

 

Action

리액트에서 set 함수로 상태를 변경하듯 리덕스에서는 action이란 객체로 상태를 변경할 수 있다.

 

action은 JavaScript 객체 형식으로 구성돼있다.

 

type은 필수로 들어가야하고, 원하는 값을 넣어서 dispatch로 전송하면 된다.

// App.jsx

const App = () => {
  const onClickHandler = () => {
    store.dispatch({ type: "CLICK_EVENT", data: {} });
  };
  
  return (
    <Provider>
      <div>
        <button onClick={onClickHandler}>클릭</button>
      </div>
    </Provider>
  );
};

 

 

Reducer

Action을 스토어로 바로 전달할 수는 없다.

 

Action을 리듀서로 전달하면 리듀서가 스토어에 접근해서 상태를 업데이트 한다.

 

전달받은 action의 type값에 해당하는 로직을 실행하고 상태를 변화시킨다.

// store.js

const reducer = (state, action) => {
  if( action.type === "CLICK_EVENT" ) {
    ...
  }
};
728x90

 

 

리덕스를 왜 쓰는가?

그렇다면 이렇게 복잡한 구조로 리덕스를 왜 쓰는지에 대한 의문이 생길것이다.

 

부모 컴포넌트의 데이터를 넘겨줄 때 props로 자식 컴포넌트로 값을 넘겨주면 된다.

 

한 두 개의 자식 컴포넌트만 존재한다면 데이터를 넘겨주는 것은 쉽게 가능할 것이다.

 

하지만 프로젝트 규모가 커지고 전달해야하는 depth가 깊어지게 된다면 무분별하게 props를 사용해야 한다.

그림 1-2. props로 자식 컴포넌트에 데이터를 넘겨준다

 

리덕스를 사용하면 중앙에서 상태를 관리하기 때문에 필요한 컴포넌트에서 state값을 직접 접근할 수 있게 된다.

 

 

@reduxjs/toolkit

위 방법이 기존에 사용하던 Redux의 상태 관리 방식이다.

 

하지만 Redux를 더욱 편리하게 사용하기 위해서 Redux에서 제공하는 새로운 라이브러리가 있다.

 

바로 @reduxjs/tookit (RTK) 이다.

 

공식 사이트에서도 RTK의 사용을 권장하고 있고, redux 라이브러리의 createStore를 import하면 RTK를 사용하라는 문구가 나온다.

그림 1-3. createStore

 

Redux 라이브러리가 아닌 RTK를 사용하여 상태 관리 하는 방법을 간단한 예제 코드로 알아보겠다.

 

 

configureStore

Redux 라이브러리에서 스토어를 생성하기 위해 createStore 함수를 사용했다.

 

RTK에서는 configureStore 함수를 사용해서 스토어를 생성한다.

공식문서

configureStore는 한 번의 호출로 Redux 스토어를 설정하며, 
리듀서를 결합하고 thunk 미들웨어를 추가하고, 
Redux DevTools 통합을 하는 등의 작업을 수행합니다. 
또한, 이름이 있는 옵션 매개변수를 사용하기 때문에 createStore보다 구성이 쉽습니다.

 

// store.js

import { configureStore } from "@reduxjs/toolkit";

const store = configureStore({
  reducer: {
    ...
  }
});

export default store;

 

위의 reducer 부분에 스토어에서 사용할 Slice를 넣어주면 된다.

 

 

createSlice

Slice란 기존  Redux에서 사용하던 Reducer이다.

 

createSlice로 생성할 때 Slice의 이름인 name초기값을 설정할 initialState, 사용할 함수인 reducers를 작성하면 된다.

 

reducers 안의 함수의 매개변수로 state와 action을 설정할 수 있다.

 

Slice를 생성하고 Store의 reducer에 등록하면 상태를 관리할 수 있게 된다.

// countSlice.js
export const countSlice = createSlice({
  name: "count",
  initialState: {
    value: 1,
  },
  reducers: {
    increment: state => {
      state.value += 1;
    },
    decrement: state => {
      state.value -= 1;
    },
  }
});

export const { increment, decrement } = countSlice.actions;

export default countSlice.reducer;


// store.js
import countReducer from "../slice/countSlice";

const store = configureStore({
  reducer: {
    count: countReducer,
  }
});

export default store;

 

 

useSelector, useDispatch

스토어 및 슬라이스를 생성한 후 react-redux의 useSelector와 useDispatch를 사용해서 state의 상태를 관리할 수 있다.

 

아래는 버튼을 누르면 counter의 state 값이 증가 또는 감소 하는 간단한 예제 코드이다.

// App.jsx

import { store } from "./store";
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement } from "../slices/countSlice";

const App = () => {
  return (
    <Provider store={store}>
      <div class="borderLayout">
        <h1>Root</h1>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
          <Left1 />
          <Right1 />
        </div>
      </div>
    </Provider>
  );
};

const Left1 = () => {
  return (
    <div class="borderLayout">
      <h1>Left1</h1>
      <Left2 />
    </div>
  )
};

const Left2 = () => {
  return (
    <div class="borderLayout">
      <h1>Left2</h1>
      <Left3 />
    </div>
  )
};

const Left3 = () => {
  // useSelector로 state의 값을 가져온다.
  const count = useSelector((state) => state.count.value);

  return (
    <div class="borderLayout">
      <h1>Left3 : {count}</h1>
    </div>
  )
};

const Right1 = () => {
  return (
    <div class="borderLayout">
      <h1>Right1</h1>
      <Right2 />
    </div>
  )
};

const Right2 = () => {
  return (
    <div class="borderLayout">
      <h1>Right2</h1>
      <Right3 />
    </div>
  )
};

const Right3 = () => {
  // useDispath를 선언하고 Slice의 reducers에 정의된 함수를 호출한다.
  const dispatch = useDispatch();

  return (
    <div class="borderLayout">
      <h1>Right3</h1>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
    </div>
  )
};

export default App;

 

위 코드를 실행하면 아래와 같은 화면이 나온다.

 

Right3의 +, - 버튼을 클릭하면 Left3의 상태 값이 변경되게 된다.

 

그림 1-4. 상태 관리 구현 화면

 

 

참고 사이트

https://ko.redux.js.org/introduction/why-rtk-is-redux-today

 

Redux Toolkit이 오늘날 Redux를 사용하는 방법인 이유 | Redux

소개 > RTK가 현재의 Redux인 이유: RTK가 어떻게 Redux 코어를 대체하는지에 대한 상세 내용

ko.redux.js.org

 

https://hanamon.kr/redux%EB%9E%80-%EB%A6%AC%EB%8D%95%EC%8A%A4-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC/

 

Redux(리덕스)란? (상태 관리 라이브러리) - 하나몬

Redux(리덕스)란? 무엇인지 부터 간단한 실습까지 (상태 관리 라이브러리 리덕스 알아보기) ⚡️ Redux(리덕스)란? Redux(리덕스)란 JavaScript(자바스트립트) 상태관리 라이브러리이다. Redux(리덕스)의

hanamon.kr

 

https://www.youtube.com/watch?v=yjuwpf7VH74

 

 

 

 

 

 

 

 

 

 

728x90

'🖥️Frontend > React' 카테고리의 다른 글

[React] RTK & TypeScript  (1) 2023.11.20
[React] zustand  (0) 2023.11.18
[React] xlsx & file-saver & csv  (0) 2023.09.14
[React] React 배포 시 CORS 이슈  (0) 2023.09.13
[React] Inflearn 처음 만난 리엑트(React) - Context  (0) 2023.02.24

댓글