[Redux] 공식문서 보면서 따라하는 Redux-toolkit 초기 세팅

hongduhyeon·2022년 5월 24일
7
post-thumbnail
오랜만에 블로그... 살짝 설레는걸...

되게 오랜만에 돌아왔다. 사실 그동안 공부했던 React-native, Typescript를 적고 싶었지만 양도 적었고 뭔가 확실하게 한게 없는 공허한 느낌이다.

노력했는데 속상하다.

거두절미하고 요즘 시장에서 무조건x100 필요한 Redux toolkit에 대해 알아보자.

일단 공식문서에 들어가서 redux를 설치해준다.

한글이 없는 리덕스 공식문서 ^_^...

뭔가 이걸해야지 ! 라는게 아직 없어서 튜토리얼을 차근차근 따라해봤다.

이게 뭐람... 한국어 지원이 안된다.
악으로 깡으로 버텨보자.

💡 1. Package 설치하기

당연히 시작을 하려면 package를 설치 해야한다.

npm install @reduxjs/toolkit react-redux
yarn add @reduxjs/toolkit react-redux

성공적으로 설치를 마쳤다면 package.json에서 잘 설치가 되었는지 확인해보자.

아주 성공적으로 설치가 되었다.

여기서 의문이 드는 점은 정말 네이티브하고 날 것 그 자체인 redux와 좀 더 편하게 사용할 수 있게 만들어 놓은 redux-toolkit이 있는데 난 자꾸 그 둘 사이에서 괴리감을 느낀다.

redux-toolkit을 알려면 redux도 알아야하고 react-redux를 알아야하는거 아닌가? 어디서부터 시작해야하지... 뭘 해야하지.. 뭐가 더 중요하지....

다 집어치우고 일단 코드부터 치는게 중요하다 생각한다.

💡 2. Store 생성하기

먼저 스토어 생성은 configureStore함수를 실행하여 할 수 있다. 이 안에서 리듀서(reducer)들을 바인딩해주면 된다.

// store.js
import { configureStore } from "@reduxjs/toolkit"

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

이렇게 하면 store 생성은 완료가 된다. reducer:{ }안에 들어갈 내용은 우리가 생성하게 될 redux state slice(상태의 일부분)이다.

configureStore는 뭔가요 !

configureStore가 reducer를 감싸고 있다.
그렇다. 저기서 모든 state를 관리한다는 뜻이다.
reducer가 비어있는데 저기에 이제 상태관리할 것들을 저장할 예정이다.

끝 ? 어림도 없지.

💡 3. Provider로 App 감싸주기

// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import store from "./app/store";


const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

Prodiver가 App을 감싸주고 있다. store를 전역에서 사용하기 위해 store를 파라미터로 받고 있는 모습을 볼 수 있는데, 저게 App.js 전역에서 store를 사용할 수 있게 하기 위한 용도라고 생각하면 된다. 자세하게 들어가기엔... 아직 모르는게 너무 많다....
(마음 아픈 지식의 한계...)

💡 4. reducer 만들기

드디어 reducer를 만들건데 reducer란 무엇인가 ?
store가 식당이라고 가정한다고 하면 reducer는 접시라고 생각하면 된다.
음식이 나왔는데 접시가 있어야하지 않겠는가 ! 맨손으로 받아먹기엔 너무 뜨겁다.

// counterSlice.jsx
import { createSlice } from "@reduxjs/toolkit";

export 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;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;

export default counterSlice.reducer;

내가 보기 어려운 건 못참기 때문에 조금 풀어서 적어보겠다.

name

먼저 name은 이 reducer를 직접 사용할 이름을 정의 해준다고 생각하면 쉽다.

initialState

아마 reduce를 공부하거나 찾아보는 사람들은 무조건 react를 해봤을 것이고 hooks중에 useState를 사용해봤을 것이다. useState의 개념 중 초기 값을 지정하는 것과 동일하다고 생각하면 좀 쉽게 이해할 수 있다.

reducers

reducers는 음... 왜 s가 붙었는가 ? 복수형이다.
여러가지 함수를 작성할 수 있고 상태가 변하면 어떻게 실행될 지 정하는 부분이다. 내가 하려는 건 버튼을 눌렀을 때 숫자가 올라가고 내려가고 특정값을 입력했을 때 그만큼 올라가는 기능을 구현하기 위해 3가지 함수를 넣었다.

마지막 incrementByAmount에 action이 보일텐데 다른 기능들은 state만 갖고 어떠한 액션을 취했는데 incrementByAmount는 조금 다르게 action과 payload를 받는다.

그리고 이제 지금 작성한 3가지의 기능을 사용하려면 export로 사용할 수 있게 작성해주는데
counterSlice안에 actions라는 이름으로 자동으로 만들어지게 되어지는 것이다.

그리고 한번더 export default counterSlice.reducer;로 만들어진 기능들을 리턴해준다.

💡 5. store에서 정의 해주기

위에서 저렇게 아무리 만들어봤자 store에서 작성해주지 않으면 말짱 도루묵이다.

//store.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";

export default configureStore({
  reducer: {
    counter: counterReducer,
  },
});

우선 import로 불러오고 key값에 그 counter라고 정의를 해준다. 여기서 counter라고 정의 된 이름이 실제로 컴포넌트에서 쓰일 이름이기 때문에 확실히 인지하자 !!!!
value값에 counterReducer라고 써주면 import로 가져온 counterSlice를 정의할 수 있다.

💡 6. reducer 사용하기

import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { increment, decrement, incrementByAmount } from "./counterSlice";

export default function Counter() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <div>
        <button onClick={() => dispatch(increment())}>increment</button>
        <span>{count}</span>
        <button onClick={() => dispatch(decrement())}>decrement</button>
        <button onClick={() => dispatch(incrementByAmount(5))}>
          incrementByAmount
        </button>
      </div>
    </div>
  );
}

원래는 useState로 관리했었지만 useSelector로 관리해보자.

useSelector

redux의 state를 조회할 수 있다. 바로 위 store에서 정의 해주기 섹션에서 key값에 정의한 counter가

  const count = useSelector((state) => state.counter.value);

이 부분에서 쓰이는게 보인다. 말 그대로 useSelector는 내가 설정해둔 redux에 state를 조회할 수 있는 편리한 기능을 담고 있다.

useDispatch

액션을 발생 시켜준다. 아까 우리가 counterSlice 안에 넣어줬던 increase, decrease, incrementByAmount를 import를 통해 가져오고 ()를 붙혀 실행이 될 수 있도록 작성해준다.

4. reducer 만들기에서 state와 action을 둘 다 받아왔을때 왜 action이 있고 왜 payload가 있는지 몰랐지만 dispatch를 통해 함수를 작성하고 거기에 파라미터로 넘겨주는 값을 payload라고 생각하면 편하다. 결국 payload로 넘겨주는 값을 받아와서 실행을 시켜준다고 생각하면 된다.

💡 7. 다른 루트에서도 작동하는지 확인

똑같은 코드를 다른 경로에 똑같이 만들어줬다.
(test를 위한 네이밍... 불편해..)

app.js에서 물론 불러와주는거 잊지말고 !!

import "./App.css";
import TestMocking from "./components/TestMocking";
import Counter from "./features/counter/Counter";
import Counter2 from "./components/Counter2";

function App() {
  return (
    <div className="App">
      <TestMocking /> // 이건 무시하셔도 됩니다 :)
      <Counter /> // 요거랑
      <br />
      <br />
      <Counter2 /> // 요거
    </div>
  );
}

export default App;

성공 !

후기 & 결론
redux를 구글링 해보면 되게 많은 사람들의 지식이 쏟아져 나온다. 물론 내 입맛에 맞추는건 정말 과분한 욕심이지만 그래도 일단 공식문서를 찾아보는게 제일 좋은 것 같다. 지금 취준의 입장에서 어떻게든 이악물고 redux를 써야한다는 중압감도 있지만 이렇게 조금 사용해봤는데 상태관리가 편해서 블로그 쓰고 있는 내가 신기했다. 오.... 앞으로 좀 더 디테일한 내용을 블로깅 해보자 !
(현재시간 05월 25일 새벽 3:03)

profile
마음이 시키는 프론트엔드

2개의 댓글

comment-user-thumbnail
2022년 5월 24일

역시.. 실망시키지 않으시네요.. 감사합니다

1개의 답글