React & React Native/라이브러리 활용

[RN] React Native Redux 이해하고 설정하기 : RTK(Redux Toolkit)

adjh54 2023. 6. 21. 20:33
반응형
해당 글에서는 React-native 개발 환경에서 상태관리를 위해 RTK(Redux ToolKit)에 대해 이해하고 환경설정 하는 방법에 대해서 공유합니다.


 

1) Redux ToolKit(RTK)


💡 Redux ToolKit 

- Redux의 사용을 간편하게 하고, 코드의 복잡성을 줄이며, 일반적인 Redux 작업을 더 쉽게 하기 위해 만들어진 라이브러리입니다.
- 이는 Redux 애플리케이션을 구축하는 데 필요한 다양한 도구와 유틸리티를 제공합니다. 

[ 더 알아보기 ]

💡Redux

- React.js 애플리케이션에서 사용되는 상태 관리 라이브러리입니다. Redux는 애플리케이션에서 발생하는 모든 데이터를 중앙에 저장하고 관리합니다. 이를 통해 애플리케이션의 상태를 예측 가능하고 디버깅이 용이하게 만들어줍니다.

 

 

1. Redux와 Redux Toolkit의 차이


💡 Redux와 Redux Toolkit의 차이

- 공식 사이트 내용을 확인해 보면 Redux의 세 가지 문제를 해결하기 위해 만들어져 있습니다.


- "Redux 스토어 구성이 너무 복잡합니다."
- "Redux가 유용한 작업을 수행하려면 많은 패키지를 추가해야 합니다."
- "Redux에는 너무 많은 상용구 코드가 필요합니다"

- Redux를 사용하면서 세 가지 요인으로 인해 Redux 사용에 대한 불편함을 가지고 이를 해결하기 위해서 Redux Toolkit을 사용합니다.

 

분류 Redux Redux ToolKit
코드량 많은 코드 양 적은 코드 양
Immutable 추가 Immutable 업데이트 미지원 Immutable 업데이트 지원
createSlice 함수 추가 상태, 액션, 리듀서를 각각 개별적으로 작성 createSlice 함수로 상태, 액션, 리듀서를 한 번에 생성
configureStore 함수 추가 스토어 생성 코드를 따로 작성 configureStore 함수로 스토어 생성 코드 자동 생성
기본적인 미들웨어 포함 기본 미들웨어 미포함 몇 가지 기본 미들웨어 포함

 

 

Getting Started | Redux Toolkit

 

redux-toolkit.js.org

 

 

 

2. Redux ToolKit(RTK) 주요 용어


용어 설명
Store - 애플리케이션 ‘상태를 담고 있는 객체’를 의미합니다.
- 상태를 변경하는 유일한 방법은 액션(Action)을 발생시킵니다.
Action - ‘상태의 변경’을 알리는 객체를 의미합니다.
- type 프로퍼티를 가지고 있으며, 이 값을 통해 어떤 상태 변경을 하고자 하는지 구분
Reducer - ’Action에 따라 상태를 업데이트’하는 함수를 의미합니다.
Combine Reducer - ‘Reducer 함수를 여러 개로 분리해서 관리’할 수 있도록 도와주는 함수를 의미합니다.
Dispatch - ‘Action을 발생시키는 함수’를 의미합니다.
Middleware - ‘Action’과 ‘Reducer’ 사이에서 추가적인 작업을 수행할 수 있는 코드를 의미합니다.

 

 

Redux Toolkit | Redux Toolkit

The official, opinionated, batteries-included toolset for efficient Redux development

redux-toolkit.js.org

 

 

 

3. Redux Toolkit(RTK) 주요 메서드


메서드 설명
configureStore() Redux Store를 구성하는 메서드로, reducer 및 middleware를 설정하고 store를 반환합니다.
createReducer() 일반적인 reducer 함수를 작성하는 데 사용할 수 있는 유틸리티입니다.
createAction() 일반적인 액션 생성 함수를 작성하는 데 사용할 수 있는 유틸리티입니다.
createSlice() Redux Toolkit에서 reducer를 작성하는 유틸리티 메서드입니다. 초기 상태 및 reducer 함수를 정의하고, 액션 생성 함수를 자동으로 생성합니다.
createAsyncThunk() 비동기 작업을 수행하는 Action Creator를 생성하는 유틸리티 메서드입니다.
createEntityAdapter() 비정규화된 엔티티 데이터를 쉽게 관리할 수 있는 메서드입니다.
createSelector() Reselect 라이브러리와 함께 사용하여 성능 최적화된 셀렉터를 생성할 수 있습니다.
useSelector() Redux store에서 state를 가져오는 Hook입니다. 이 Hook은 컴포넌트 내에서 Redux store의 state를 불러와 사용할 수 있습니다.
useDispatch() Redux store에서 action을 dispatch하는 Hook입니다. 이 Hook을 이용하면 컴포넌트에서 Redux store의 state를 변경할 수 있습니다.

 

 

Getting Started | Redux Toolkit

 

redux-toolkit.js.org

 

 

 

 

3) Redux Toolkit Middleware


💡 Redux Toolkit Middleware

- Redux의 Action과 Reducer 사이에서 추가적인 작업을 수행할 수 있는 코드를 의미합니다. 미들웨어는 주로 비동기 작업, 로깅, 오류 처리등을 수행하는 데 사용됩니다.

 

💡 [참고] Redux Tookit 종류
종류 설명
redux-thunk 비동기 작업을 처리하기 위한 함수를 반환하는 미들웨어
redux-saga 제너레이터 함수를 사용하여 비동기 작업을 처리하는 미들웨어
redux-observable RxJS를 사용하여 비동기 작업을 처리하는 미들웨어
redux-promise-middleware Promise를 사용하여 비동기 작업을 처리하는 미들웨어
redux-logger 액션을 콘솔에 출력해주는 미들웨어
redux-flipper React Native 앱의 Redux 스토어를 모니터링하고, 디버깅하는 데 사용되는 디버깅 도구
redux-immutableCheck 불변성을 체크하는 미들웨어
redux-serializableCheck 액션 객체가 직렬화 가능한지 체크하는 미들웨어
middleware1 사용자가 만든 미들웨어
middleware2 사용자가 만든 미들웨어

 

 

4) Redux Tookit(RTK) 구성하기


 

1. 라이브러리를 설치합니다


# 1.redux를 구성하기 위한 라이브러리(npm)
$ npm i react-redux @reduxjs/toolkit 

# or

# 1.redux를 구성하기 위한 라이브러리(yarn)
$ yarn add react-redux @reduxjs/toolkit 


# 2. redux의 값을 유지하기 위한 라이브러리(npm)
$ npm i @react-native-async-storage/async-storage redux-persist && npm i -save--dev @types/redux-persist

# or

# 2. redux의 값을 유지하기 위한 라이브러리(yarn) 
$ yarn add @react-native-async-storage/async-storage && yarn add --dev @types/redux-persist


# 3. redux를 디버깅 하기 위한 라이브러리(npm)
$ npm i redux-logger && npm i --save-dev redux-logger

# or

# 3. redux를 디버깅 하기 위한 라이브러리(yarn)
$ yarn add redux-logger && yarn add --dev redux-logger

 

 

react-redux

Official React bindings for Redux. Latest version: 8.1.1, last published: 10 hours ago. Start using react-redux in your project by running `npm i react-redux`. There are 15960 other projects in the npm registry using react-redux.

www.npmjs.com

 

 

@reduxjs/toolkit

The official, opinionated, batteries-included toolset for efficient Redux development. Latest version: 1.9.5, last published: 2 months ago. Start using @reduxjs/toolkit in your project by running `npm i @reduxjs/toolkit`. There are 2701 other projects in t

www.npmjs.com

 

 

 

2. 프로젝트 디렉터리 구성


 

 

3. Slice 구성 및 설정 과정 -1


💡Slice 

- Redux Toolkit에서 상태 관리를 단순화하고 구조화하기 위해 도입된 개념입니다.
- Slice는 액션과 리듀서를 한 곳에 모아 두고, 상태의 특정 부분을 관리할 수 있게 해 줍니다.
- 일반적으로 Redux Toolkit의 createSlice 함수를 사용하여 생성됩니다.


💡Slice 구성 및 설정 과정 -1

- reducer를 작성하는 유틸리티 메서드입니다. 초기 상태 및 reducer 함수를 정의하고, 액션 생성 함수를 자동으로 생성합니다.


1. TemplateUserSlice에서 관리하는 상태값(State)을 정의합니다.

2. TemplateUserSlice에서 관리하는 Reducer 메서드를 관리합니다.

3. Reducer 메서드를 정의하여 외부에서 Redux의 상태를 변경할 수 있도록 구성합니다.
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { TemplateType } from "types/template/TemplateType";

/**
 * UserSlice의 관리하는 상태값(State)을 정의합니다.
 */
const initialState = {
    name: '',
    nickName: '',
    email: '',
    accessToken: '',
};

/**
 * TemplateUserSlice에서 관리하는 Reducer 메서드를 관리합니다.
 */
const TemplateUserSlice = createSlice({
    name: 'templateUser',
    initialState,
    reducers: {
        // 모든 사용자 정보를 상태에 저장합니다.
        setUser(state, action) {
            state.name = action.payload.name;
            state.nickName = action.payload.nickName;
            state.email = action.payload.email;
            state.accessToken = action.payload.accessToken;
        },

        // 사용자 이름을 상태에 저장합니다.
        setName(state, action) {
            state.name = action.payload;
        },

        // 닉네임을 상태에 저장합니다.
        setNickName(state, action) {
            state.nickName = action.payload;
        },

        // 사용자 이메일을 상태에 저장합니다.
        setEmail(state, action) {
            state.email = action.payload;
        },

        // 접근 토큰을 상태에 저장합니다.
        setAccessToken(state, action) {
            state.accessToken = action.payload;
        },

    },
});

/**
 * Reducer 메서드를 정의하여 외부에서 Redux의 상태를 변경할 수 있도록 구성합니다.
 */
export const { setUser, setName, setNickName, setEmail, setAccessToken } = TemplateUserSlice.actions

export default TemplateUserSlice.reducer

 

 

 

4. Slice 구성 및 설정 과정-2


💡 Slice 구성 및 설정 과정 -2

- 동일하게 reducer를 작성하는 유틸리티 메서드입니다. 초기 상태 및 reducer 함수를 정의하고, 액션 생성 함수를 자동으로 생성합니다.


1. TemplateSlice에서 관리하는 상태값(State)을 정의합니다.

2. TemplateSlice에서 관리하는 Reducer 메서드를 관리합니다.

3. Reducer 메서드를 정의하여 외부에서 Redux의 상태를 변경할 수 있도록 구성합니다.
import { createSlice, PayloadAction } from "@reduxjs/toolkit";


/**
 * TemplateSlice에서 관리하는 상태값(State)을 정의합니다.
 */
const initialState = {
    tempId: '',
    tempName: '',
    tempMenu: '',
};
/**
 * TemplateSlice에서 관리하는 Reducer 메서드를 관리합니다.
 */
const TemplateSlice = createSlice({
    name: 'template',
    initialState,
    reducers: {

        // 모든 사용자 정보를 상태에 저장합니다.
        setTemplate(state, action) {
            state.tempId = action.payload.tempId;
            state.tempName = action.payload.tempName;
            state.tempMenu = action.payload.tempMenu;
        },

        setTempId(state, action) {
            state.tempId = action.payload;
        },

        setTempName(state, action) {
            state.tempName = action.payload;
        },

        setTempMenu(state, action) {
            state.tempMenu = action.payload;
        },

    },
});

/**
 * Reducer 메서드를 정의하여 외부에서 Redux의 상태를 변경할 수 있도록 구성합니다.
 */
export const { setTemplate, setTempId, setTempName, setTempMenu } = TemplateSlice.actions

export default TemplateSlice.reducer

 

 

 

5. RootReducer 구성 및 설정


💡 RootReducer 

- Redux에서 사용하는 하나의 최상위 리듀서(Reducer)입니다. 애플리케이션의 상태를 관리하기 위해 여러 개의 리듀서를 하나로 결합하여 사용하는데, 이 결합된 리듀서(combineReducers)를 Root Reducer라고 합니다.
- 각 리듀서는 상태의 특정 부분을 담당하며, Root Reducer는 이들을 하나로 합쳐 전체 상태 트리를 관리합니다.


💡 RootReducer 구성 및 설정

- 사용 목적에 따라서 Slice 단위로 분리하여서 Root Reducer를 구성합니다.
import { combineReducers } from "@reduxjs/toolkit";
import templateSlice from "./slice/TemplateSlice";
import templateUserSlice from "./slice/TemplateUserSlice";

/**
 * 사용 목적에 따라서 Slice 단위로 분리하여서 Root Reducer를 구성합니다.
 */
const RootReducer = combineReducers({
    templateUser: templateUserSlice,
    template: templateSlice
});

export type RootState = ReturnType<typeof RootReducer>;

export default RootReducer;

 

 

 

6. Redux Store 구성 및 설정


💡 Redux Store

- 애플리케이션의 상태를 보관하는 중앙 저장소입니다. Redux는 단일 상태 트리 구조를 가지고 있기 때문에, 애플리케이션의 모든 상태는 하나의 store 객체 안에 저장됩니다. 
- 이 store는 애플리케이션의 상태를 읽고, 변경하고, 구독할 수 있는 여러 기능을 제공합니다.


💡 Redux Store 구성 및 설정


1. Redux-Persist 설정 값을 구성합니다

- redux의 값이 유지되는 redux-persist를 통해서 각각의 설정을 구성합니다.
- storage 속성을 통해서 React-native의 내부저장소인 react-native-async-store 내에 이를 저장하여 값을 유지합니다.


2. 애플리케이션의 '상태'를 관리하기 위한 Store 구성합니다.

- 구성한 redux-persist에서 설정한 값과 Root Reducer에서 지정한 값을 기반으로 reducer를 지정하고 미들웨어를 지정합니다.

3. 외부에서 사용할 수 있도록 Persistor를 구성합니다.
import { configureStore } from "@reduxjs/toolkit";
import RootReducer, { RootState } from "./RootReducer";
import { persistStore, persistReducer, PersistConfig } from 'redux-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';
import logger from 'redux-logger'

/**
 * 1. Redux-Persist에 설정 값을 구성합니다.
 */
const persistConfig: PersistConfig<RootState> = {
    key: 'root',                // 저장되는 값에 대한 식별자로 반드시 입력해주세요.
    storage: AsyncStorage,      // Redux가 저장되는 Storage로 AsyncStorage를 이용합니다.
    blacklist: [],              // 선택적으로 저장하지 않을 리듀서를 지정할 수 있습니다.
};

/**
 * 2. 애플리케이션의 '상태'를 관리하기 위한 Store 구성합니다.
 */
export const Store = configureStore({
    // Redux-Persist 설정값과 구성한 RootReducer를 통해 Reducer를 구성합니다.
    reducer: persistReducer(persistConfig, RootReducer)!,

    // 미들 웨어로 logger를 사용합니다.
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
    // middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false }),
});

/**
 * 3. 외부에서 사용할 수 있도록 persistor를 구성합니다.
 */
export const Persistor = persistStore(Store);

export type AppDispatch = typeof Store.dispatch

 

 

Quick Start | Redux Toolkit

 

redux-toolkit.js.org

 

 

 

7. Provider 구성 및 설정


💡 Provider

- Redux 스토어를 React 애플리케이션의 모든 컴포넌트에 주입하는 역할을 수행합니다.


💡 PersistGate

- Redux 스토어의 상태를 로컬 스토리지나 세션 스토리지에 저장하고(React Native 내에서는 AsyncStore와 같은 공간에 저장) 재로딩 시 복원하는 역할을 수행합니다.


💡 Provider 구성 및 설정


- App 페이지 최상위에 Provider로 스토어와 PersistGate를 등록합니다.
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { Persistor, Store } from "modules/redux/Stroe";


const App = () => {
	return (
        // Redux-Store
        <Provider store={Store}>
            {/* Redux-Persist */}
            <PersistGate persistor={Persistor}>
                <NavigationContainer>
                    {/* Stack Navigation Element */}
                    <StackNavigator />
                </NavigationContainer>
            </PersistGate>
        </Provider>
	)
}
export default App;

 

 

Quick Start | Redux Toolkit

 

redux-toolkit.js.org

 

 

 

4) 구성 결과 확인하기


1. 상태 갱신하기


💡 상태 갱신하기

- useDispatch()를 통해서 Redux 저장소를 확인하여서 정보를 세팅합니다.
import { useDispatch, useSelector } from "react-redux";
import { setEmail } from "modules/redux/slice/TemplateUserSlice";

const TemplateReduxScreen = ({ route, navigation, appState }: CommonType.CommonProps) => {
	const dispatch = useDispatch()
	
	/**
	 * Redux 공간에 사용자 정보를 세팅합니다.
	 */
	const setUserInfo = () => {
	    const result = dispatch(setEmail("hohoho"))
	    console.log("result :: ", result)
	}
}

 

 

2. 현재 상태 불러오기


💡 현재 상태 불러오기

- useSelector() 함수를 통해서 Redux 저장소를 확인하여서 현재 상태를 불러옵니다.
import { RootState } from "modules/redux/RootReducer";
import { useDispatch, useSelector } from "react-redux";

const TemplateReduxScreen = ({ route, navigation, appState }: CommonType.CommonProps) => {
    const dispatch = useDispatch()

    // Redux 저장소에서 데이터를 조회해옵니다.
    const userInfo = useSelector((state: RootState) => state.templateUser);

    /**
     * Redux 상태에 사용자 정보를 가져옵니다.
     */
    const selectUserInfo = () => {
        console.log("userInfo :: ", userInfo);
    }
}

 

 

 

 

99) 참고


1. Redux를 변경하였는데 초기값이 변경되지 않습니다.


💡 Redux를 변경하였는데 초기값이 변경되지 않습니다.

- Redux는 기본적으로 디바이스의 메모리에 저장이 됩니다.
- Redux의 구조가 변경된 경우, 메모리 데이터를 지워주는 것이 적절합니다.
- Redux는 상태 관리를 위해 메모리에 데이터를 저장하므로 구조 변경 시 이전 데이터가 남아있을 수 있습니다. 따라서 변경된 Redux 구조에 맞게 메모리 데이터를 지워주는 것이 좋습니다.

 

💡 앱 정보 선택 - 저장공간 탭 선택

 

 

💡 '데이터 삭제' 버튼을 선택하여 데이터를 삭제한 후에 수행합니다.

 

 

 

 

오늘도 감사합니다. 😀

 

 

 

반응형