Redux에 대해 알아보자🙏

c_yj·2022년 7월 6일
0

Redux

목록 보기
2/2
post-thumbnail

😁 Redux란 ?

Redux란 Javascript 상태관리 라이브러리다.

✔️ 스토어 (Store)

Store(스토어)는 상태가 관리되는 오직 하나의 공간이다.
리덕스에서는 한 애플리케이션당 하나의 스토어를 만들게 됩니다. 스토어 안에는, 현재의 앱 상태와, 리듀서가 들어가있고, 추가적으로 몇가지 내장 함수들이 있습니다.

✔️ 리듀서 (Reducer)

리듀서는 변화를 일으키는 함수입니다. 리듀서는 두가지의 파라미터를 받아옵니다.

function reducer(state, action) {
  // 상태 업데이트 로직
  return alteredState;
}

리듀서는, 현재의 상태와, 전달 받은 액션을 참고하여 새로운 상태를 만들어서 반환합니다. 이 리듀서는 useReducer 를 사용할때 작성하는 리듀서와 똑같은 형태를 가지고 있습니다.

✔️ 액션 (Action)

Action(액션)은 앱에서 스토어에 운반할 데이터를 말한다.
상태에 어떠한 변화가 필요하게 될 땐, 우리는 액션이란 것을 발생시킵니다. 이는, 하나의 객체로 표현되는데요, 액션 객체는 다음과 같은 형식으로 이뤄져있습니다.

{
  type: "TOGGLE_VALUE"
}

액션 객체는 type 필드를 필수적으로 가지고 있어야하고 그 외의 값들은 개발자 마음대로 넣어줄 수 있습니다.

✔️ 액션 생성함수 (Action Creator)

액션 생성함수는, 액션을 만드는 함수입니다. 단순히 파라미터를 받아와서 액션 객체 형태로 만들어주죠.

export function addTodo(data) {
  return {
    type: "ADD_TODO",
    data
  };
}

// 화살표 함수로도 만들 수 있습니다.
export const changeInput = text => ({ 
  type: "CHANGE_INPUT",
  text
});

이러한 액션 생성함수를 만들어서 사용하는 이유는 나중에 컴포넌트에서 더욱 쉽게 액션을 발생시키기 위함입니다. 그래서 보통 함수 앞에 export 키워드를 붙여서 다른 파일에서 불러와서 사용합니다.

✔️ 디스패치 (dispatch)

디스패치는 스토어의 내장함수 중 하나입니다. 디스패치는 액션을 발생 시키는 것 이라고 이해하시면 됩니다. dispatch 라는 함수에는 액션을 파라미터로 전달합니다.. dispatch(action) 이런식으로 말이죠.
그렇게 호출을 하면, 스토어는 리듀서 함수를 실행시켜서 해당 액션을 처리하는 로직이 있다면 액션을 참고하여 새로운 상태를 만들어줍니다.

✔️ 구독 (subscribe)

구독 또한 스토어의 내장함수 중 하나입니다. subscribe 함수는, 함수 형태의 값을 파라미터로 받아옵니다. subscribe 함수에 특정 함수를 전달해주면, 액션이 디스패치 되었을 때 마다 전달해준 함수가 호출됩니다.
리액트에서 리덕스를 사용하게 될 때 보통 이 함수를 직접 사용하는 일은 별로 없습니다. 그 대신에 react-redux 라는 라이브러리에서 제공하는 connect 함수 또는 useSelector Hook 을 사용하여 리덕스 스토어의 상태에 구독합니다.

✔️ 리덕스의 3가지 규칙

1. 하나의 애플리케이션 안에는 하나의 스토어가 있습니다.

하나의 애플리케이션에선 단 한개의 스토어를 만들어서 사용합니다.

2. 상태는 읽기전용 입니다.

기존의 상태는 건들이지 않고 새로운 상태를 생성하여 업데이트 해주는 방식으로 해주면, 나중에 개발자 도구를 통해서 뒤로 돌릴 수도 있고 다시 앞으로 돌릴 수도 있습니다.
리덕스에서 불변성을 유지해야 하는 이유

  • 내부적으로 데이터가 변경 되는 것을 감지하기 위하여 shallow equality 검사를 하기 때문입니다 객체의 변화를 감지 할 때 객체의 깊숙한 안쪽까지 비교를 하는 것이 아니라 겉핥기 식으로 비교를 하여 좋은 성능을 유지할 수 있는 것이죠.

3. 변화를 일으키는 함수, 리듀서는 순수한 함수여야 합니다.

순수한 함수란?

  • 리듀서 함수는 이전 상태와, 액션 객체를 파라미터로 받습니다.
  • 이전의 상태는 절대로 건들이지 않고, 변화를 일으킨 새로운 상태 객체를 만들어서 반환합니다.
  • 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과값을 반환해야만 합니다.

😀 실습하기

store 폴더를 생성하고 index.js 파일을 만들어서 store, action, reducer를 적어보자

import {legacy_createStore as createStore} from 'redux';
// createStore를 사용하면 밑줄이 그어지는데 @reduxjs/toolkit 사용을 권장사용을 유도하기 위해 그러는 것 같다고 한다 legacy_createStore as createStore 를 사용하면 임시로 밑줄을 지울 순 있다.


// reducer 만들기
// state 기본 값 설정하기
// action 으로 상태 변화 주기
const reducerFn = (state={counter : 0},action) => {
    if(action.type === "INC"){
        return {counter : state.counter+1};
    }
    if(action.type === "DEC"){
        return {counter : state.counter-1};
    }
    if(action.type === 'ADD'){
        return {counter : state.counter + action.payload}
    }
    return state;
}

// 스토어에 리듀서 넣기
const store = createStore(reducerFn);
export default store;

index.js 파일에 Provider, store 적용

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


const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  // Provider에 store를 넣어줘야 함.
  <Provider store={store}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Provider>
);

App.js

  • useSelector = 리덕스의 state를 조회할 수 있다.
  • useDispatch = 생성한 action을 useDispatch를 통해 발생시킬 수 있다
  • payload = action의 type에 따라 필요한 state값을 담고 있다.
import { useSelector, useDispatch } from 'react-redux';
import './App.css';

function App() {
  const counter = useSelector((state) => state.counter)
  const dispatch = useDispatch();
  const increment = () => { 
      dispatch({type: 'INC'})
  }
  const decrement = () => {
     dispatch({type: 'DEC'})
  }
  const addBy = () => {
    dispatch({type : 'ADD', payload: 10})
  }
  return (
    <div className="App">
      <h1>Count</h1>
      <h2>{counter}</h2>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={addBy}>Add by 10</button>
    </div>
  );
}

export default App;

출처

profile
FrontEnd Developer

0개의 댓글