React!

리덕스툴킷(Redux Toolkit)

개발따라김양 2022. 8. 1. 12:57

1. 리덕스(Redux)의 문제점

1) store configuration의 복잡성

리덕스 스토어를 설정하는 게 너무 복잡합니다.

 

2) 리덕스를 사용하기 위한 다른 라이브러들의 추가 설치 

  • react와 바인딩하기 위한 react-redux
  • 불변성을 유지하기위한 immutable/immer
  •  비동기 통신을 위한 redux-thunk/redux-saga/redux-pender
  •  액션 생성을 위한 redux-actions

3) 많은 양의 보일러 플레이트를 파일마다 반복 작성해야 함

리덕스 액션과 리듀서들을 도메인마다 분리를 하고, 또 리액트 각 컴포넌트마다 바인딩을 하면,

엄청나게 많은 수의 파일에서 리덕스 코드를 사용하게 됩니다.

그런데 그 많은 파일에서 많은 양의 보일러 플레이트 코드를 반복해서 사용해줘야 해서

코드가 지저분해지고 관리포인트가 많다는 단점이 있습니다.

2.  리덕스 툴킷 (Redux Toolkit)

  • 리덕스 로직을 작성하기 위해 리덕스에서 공식적으로 추천하는 방법입니다.
  • 리덕스 툴킷은 리덕스 앱을 만들기에 필수적으로 여기는 패키지와 함수들을 포함합니다.
  • 리덕스 툴킷은 저장소 준비, 리듀서 생산과 불변 수정 로직 작성, 상태 "조각" 전부를 한번에 작성 등
    일반적인 작업들을 단순화해주는 유틸리티를 포함하고 있습니다

1) 개선점

  • store configuation 
     configureStore 함수는 리덕스 라이브러리의 createStore 함수를 추상화한 것입니다.
    기존의 번거러운 리덕스 설정을 간편하게 할 수 있도록 해주고 디폴트로 redux-thunk, DevTools를 제공해줍니다.
import { configureStore } from '@reduxjs/toolkit'

import rootReducer from './reducers'

const store = configureStore({ reducer: rootReducer })
  • createSlice
    createSlice 함수는 선언한 slice의 name에 따라 액션 생성자, 액션 타입, 리듀서를 자동으로 생성해줍니다.
    따라서 별도로 createAction 이나 createReducer을 사용하지 않아도 됩니다.
import { configureStore, createSlice } from '@reduxjs/toolkit'

let user = createSlice({  ///createSlice 선언
    name: 'user',	     ///이름 
    initialState : {name : 'crystal', age : 30 }, //초기값설정
    reducers: {						//state 바꾸는 함수 reducers 선언
        changeName(state){ 
            state.name = 'new-crystal'
            state.age +=1
        }
    }
})

export default configureStore({
  reducer: { 
    user : user.reducer
  }
})
  • 정리
  • 리덕스는 데이터를 단방향으로 흐르게 하여 결과를 예측 가능하게 하고 디버깅을 쉽게 만듭니다.
  • RTK는 기존 리덕스의 문제를 개선하고, 리덕스 로직을 작성하는 표준을 제안한다.
    • 스토어 구성은 configureStore를 사용하자.
    • 리덕스 로직을 작성할 때는 덕-패턴(ducks pattern) 형태로 작성을 돕는 createSlice를 사용하자.
    • 비동기 로직은 createAsyncThunk를 사용해서 작성하자.
      • 타입 스크립트를 지원하는 빌더 콜백(builder callback) 표기법을 사용하자.
      • 프로미스 생명 주기를 따르는 액션 타입으로 비동기 로직을 관리해 보자.
    • 데이터 패칭과 캐싱은 RTK Query를 사용해 보자.

 

1) 설치

yarn add @reduxjs/toolkit

 

2)React Redux 앱 만들기

React와 Redux로 새 앱을 만들기 위해 추천하는 방법은 Create React App를 위한 공식 Redux+JS 템플릿을 사용하는 것입니다. 이를 통해 Redux Toolkit와 React Redux가 React 컴포넌트와 통합되는 이점을 누릴 수 있습니다.

npx create-react-app my-app --template redux

3) Redux 코어

Redux 코어 라이브러리는 NPM에서 패키지로 받아 모듈 번들러나 Node 앱에서 사용 가능합니다.

yarn add redux

4) 기본 예제

import { createStore } from 'redux'

/**
 * 이것이 (state, action) => state 형태의 순수 함수인 리듀서입니다.
 * 리듀서는 액션이 어떻게 상태를 다음 상태로 변경하는지 서술합니다.
 *
 * 상태의 모양은 자유롭습니다: 기본형(primitive)일수도, 배열일수도, 객체일수도,
 * 심지어 Immutable.js 자료구조일수도 있습니다.  
 * 오직 중요한 점은 상태 객체를 변경해서는 안되며,
 * 상태가 바뀐다면 새로운 객체를 반환해야 한다는 것입니다.
 *

function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

// 앱의 상태를 보관하는 Redux 저장소를 만듭니다.
// API로는 { subscribe, dispatch, getState }가 있습니다.
let store = createStore(counter)

// subscribe()를 이용해 상태 변화에 따라 UI가 변경되게 할 수 있습니다.
// 보통은 subscribe()를 직접 사용하기보다는 뷰 바인딩 라이브러리(예를 들어 React Redux)를 사용합니다.
// 하지만 현재 상태를 localStorage에 영속적으로 저장할 때도 편리합니다.

store.subscribe(() => console.log(store.getState())))

// 내부 상태를 변경하는 유일한 방법은 액션을 보내는 것뿐입니다.
// 액션은 직렬화할수도, 로깅할수도, 저장할수도 있으며 나중에 재실행할수도 있습니다.
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1