기억의 실마리
2022. 12. 26. 23:11

Redux-Toolkit

기존 리덕의 경우 reducer를 구현할 때마다 type 이름을 명확하게 적어야 하며

switch문이나 if/else를 사용해야하는 boilerpate코드가 많다.

간단하게 상태관리를 하겠다고 만든 리덕스이지만 많은 개발자들이 오히려 복잡한 코드를

짜야한 다는 것에 불만을 품었고 그 의견을 반영하여 redux팀 자체에서

redux-toolkit이 redux를 대체할 라이브러리라고 소개했고 실제로 더 간단하게

상태관리를 할 수 있는 라이브러리로 출시되었다.

 

상태관리 라이브러리의 원리

< 기존의 상태관리 방식의 시각화 >

React에서 State의 특성상 계속해서 props를 통해서 병렬적으로

상태를 관리할 수 밖에 없는 구조이다.

이렇게되면 로직처리중 의도치않은 버그가 발생할 수도 있고

아주 비효율적인 처리방식이라고 볼 수 있다.

 

 

< Redux의 상태관리 방식의 시각화 >

Redux는 Reducer와 Store를 통해서 상태변경과정을 간소화하고 직렬적으로

필요한 상태만 변경할 수 있게 만들어주기 때문에 효율적이고 간편하며

버그의 빈도를 낮추는 역할을 하게된다.

 

 

Redux 기본용어

Store

스토어는 컴포넌트의 상태를 관리하는 저장소다. 하나의 프로젝트 내에는 반드시 하나만 존재해야 한다.

Action

스토어의 상태를 변경하기 위해서는, 액션을 생성해야한다. 액션은 객체이며, 반드시 type을 가져야 한며 액션 객체는 액션생성함수에 의해서 만들어지고 type내부에 payload를 생성하고 state를 저장한다.

Reducer

리듀서는 현재 상태와 액션 객체를 받아 새로운 상태를 리턴하는 함수다.

Dispatch

디스패치는 스토어의 내장 함수 중 하나이며, 액션 객체를 넘겨줘 상태를 업데이트 시켜주는 역할을 한다.

Subscribe

스토어의 내장 함수 중 하나로, 리듀서가 호출될 때 서브스크라이브된 함수 및 객체를 호출한다.

 

 

 

Redux는 어떻게 상태를 변경할까?

 

1. UI가 처음 렌더링 될 때 UI는 스토어를 통해서 상태로 접근하여 초기에 설정해둔 값(initialState)으로 상태를 렌더링한다.

 

2. UI에서 상태가 변경되면 디스패치를 실행하여 action을 일으키고 type내부의 payload를 만든 후 전달받은 값을 가지고 스토어로가서 변경된 State를 저장한다.

 

4. 해당 UI는 Subscribe되었기 때문에 State가 변경된 것을 감지하고 변경된 상태를 렌더링한다.

 

 

사용예시

Redux-Toolkit Install

npm install @reduxjs/toolkit
//리액트 환경인 경우 react-redux 설치가 필요하다.

 

user.js   < reducer > 

import { createSlice } from '@reduxjs/toolkit';

export const userSlice = createSlice({
    name: "user",
    initialState: { value: {name: "", age: 0, email: ""}},
    reducers: {
        login: (state, action) => {
            state.value = action.payload
        },
    },
});

export const { login } = userSlice.reducer;

export default userSlice.reducer;

createSlice는 기존에 createReducer와 createAction 이 하던 일을 같이 해준다. 쉽게 말해 actions를 위한 js파일을 따로 만들 필요가 없다. 리듀서를 만들면 스토어에 저장을 해주어야한다.

 

 

store.js

import { configureStore } from '@reduxjs/toolkit'
import userReducer from './user'

export default configureStore({
    reducer:{
        user: userReducer
    }
})

redux-toolkit에서는 자동적으로 name + Reducer로 지정되어서 name: nameReducer가 된다.

 

 

index.js

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

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

Provider를 통해서 store를 전역으로 사용할 수 있도록 만든다.

 

 

Profile.js

import React from 'react'
import { useSelector } from 'react-redux'

function Profile() {
    const user = useSelector((state) => state.user.value);
    return (
        <div>
            <h1>Profile Page</h1>
            <p> Name : {user.name} </p>
            <p> Age : {user.age} </p>
            <p> Email : {user.email} </p>
        </div>
    );
}

export default Profile

 

Login.js

import React from 'react';
import { useDispatch } from 'react-redux';
import { login } from '../redux/user';

function Login() {
  const dispatch = useDispatch()
  return (
    <div>
      <button onClick={() => {
        dispatch(login({name: "내 이름", age: 20, email: "email@gmail.com"}))
      }}>Login</button>
    </div>
  );
}

export default Login

 

  • useSelector()로 스토어에서 현재 상태 값을 가져온다.
  • useDispatch()를 통해 변경되는 값을 스토어로 전달한다.

'Frontend > Redux' 카테고리의 다른 글

[ Redux ] 상태관리 라이브러리  (0) 2022.11.19
2022. 11. 19. 11:23

# 리덕스를 왜 쓰는가?

1. 리덕는 상태관리라이브러리이다. 즉 state를 관리한다는 것인데
state = '상태' 이며, 이 '상태'라는 것은 useState를 생각하면 쉽게 이해가능하다.
데이터를 변경시켜 주고 이를 setState를 통해 rerender시켜주는 것

이라고 이해하면 된다. 그리고 이 state들을 store에 넣어서

전역으로 관리하기 위함이다.

 

store = [State의 집합체] 이다.

 

 

2. 객체의 변화(데이터의 변화)를 감지하여 간단하게 비교(shallow equality 검사)하여

객체의 깊은 변화가 아닌 겉핥기식의 변화를 비교하기 때문에 좋은 성능을

유지할 수 있는 것이 가장 큰 장점이다.

props를 연속적으로 전달받는 방식을 대신하기 위함도 크다.





# shallow equality 검사와 불변성

리덕스에서 가장 큰 이점으로 앞서 겉핥기식의 변화를 언급했었다.

이는 불변성에 의한 검사가 이뤄지면 복잡한 변경을 감지하는 것보다

더 간단하고 빠르게 구현할 수 있기 때문에 비용 역시 줄어들게된다.

 

불변성이란?

절대 변경되지않는 데이터를 말한다.

 

불변성이 성능을 높여주는 가장 큰 이유는

[ 불변성데이터의 추론 ]  <<  [ 임의로 변경가능한 데이터의 추론 ]

 

이러하기 때문에 프로그래밍 및 디버깅이 간단하게 구현가능하다.

 

# 사용예시

 

< HTML 영역 >

<button id="add">Add</button>
<span>0</span>
<button id="minus">Minus</button>

 

< JAVA SCRIPT 영역 >

import { legacy_createStore } from "redux";

const add = document.getElementById("add");
const minus = document.getElementById("minus");
const number = document.querySelector("span");

const countModifier = (count = 0, action)=> {
/* countModifier는 리듀서이며 순수함수이고, 스토어데이터를 modify시킨다.
디폴트 = 0 이며 action은 전달받을 인자 or 파라미터(매개변수)다. */

    console.log(count, action);
    if (action.type === "ADD") {
        return count + 1;
    } else if (action.type === "MINUS") {
        return count - 1;
    } else {
        return count;
    }
    
};

const countStore = legacy_createStore(countModifier);
//store를 사용할 변수에 legacy_createStore를 할당시키고 리듀서를 매개변수로 넣는다.

const onChange = ()=> {
    number.innerText = countStore.getState();
};
// 스토어에 getState를 사용해서 변경된 데이터를 re-render시킨다.

countStore.subscribe(onChange);
/* subscribe는 스토어 내부 변화를 감지한다(리스너).
변화가 감지되면 매개변수에있는 함수를 실행시킨다. */

const handleAdd = ()=>{
    countStore.dispatch({ type: "ADD" })
};
 //dispatch = 스토어의 데이터를 변형시킨다.

const handleMinus = ()=>{
    countStore.dispatch({ type: "MINUS" })
};

add.addEventListener("click", (handleAdd));
minus.addEventListener("click", (handleMinus));

 간단한 예시를 위해 버튼을 클릭하면 가운데 숫자에서 마이너스, 플러스 되도록 구현했다.

'Frontend > Redux' 카테고리의 다른 글

[ Redux-Toolkit ] 더 간단해진 상태관리 라이브러리  (0) 2022.12.26