๐Ÿ“ฑ Cross Platform/React Native

[React Native] Redux-Toolkit์ด๋ž€? (feat. ๊ธฐ์กด Redux์™€ ๋น„๊ต)

Fomagran ๐Ÿ’ป 2022. 8. 6. 00:49
728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š”. Foma ์ž…๋‹ˆ๋‹ค!

 

์ €๋ฒˆ ๊ธ€์—์„œ Redux๊ฐ€ ๋ฌด์—‡์ด๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ๋‹ค๋ค˜์—ˆ๋Š”๋ฐ์š”.

 

(์•„์ง ์•ˆ ๋ณด์‹  ๋ถ„๋“ค์€ ์—ฌ๊ธฐ ์—์„œ ๋ณด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค!)

 

Redux์— ๋Œ€ํ•ด ์ฐพ์•„๋ณด๋‹ˆ Redux๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ํšจ์œจ์ ์ธ Redux-Toolkit์ด ์žˆ๋”๋ผ๊ตฌ์š”.

 

๊ทธ๋ž˜์„œ ์˜ค๋Š˜์€ Redux-Toolkit์ด ๋ฌด์—‡์ด๊ณ  ์™œ ๋” ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ํšจ์œจ์ ์ธ์ง€์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


Redux-Toolkit์ด๋ž€?

 

Redux-Toolkit์€ Redux๋ฅผ ๋งŒ๋“  ๊ณณ์—์„œ ๊ณต์‹์ ์œผ๋กœ ํšจ์œจ์ ์ธ Redux ๊ฐœ๋ฐœ์„ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ํˆดํ‚ท์ž…๋‹ˆ๋‹ค.

 

Redux ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ณ , Redux ๋ณด๋‹ค ํ›จ์”ฌ ํšจ์œจ์ ์ด๋ฏ€๋กœ ์‚ฌ์šฉ์„ ๊ณต์‹์ ์œผ๋กœ ๊ฐ•๋ ฅํžˆ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ค ๋ฉด์—์„œ ๋” ํšจ์œจ์ ์ด๋ผ๋Š” ๊ฒƒ ์ผ๊นŒ์š”?

 

๊ธฐ์กด์˜ Redux์—์„  ์•„๋ž˜์™€ ๊ฐ™์€ 3๊ฐ€์ง€ ๋ฌธ์ œ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

  • Redux ์Šคํ† ์–ด ๊ตฌ์„ฑ์ด ๋„ˆ๋ฌด ๋ณต์žกํ•˜๋‹ค.
  • Redux์—์„œ ์œ ์šฉํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋งŽ์€ ํŒจํ‚ค์ง€๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
  • Redux์—๋Š” ๋„ˆ๋ฌด ๋งŽ์€ ์ƒ์šฉ๊ตฌ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

์œ„ ๋ฌธ์ œ์ ์„ Redux-Toolkit์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ฃ .

 

Redux๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด Redux-Toolkit์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, ๋ชจ๋“  Redux์•ฑ์—” Redux-Toolkit์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.

 

์ƒˆ๋กœ์šด Redux ์‚ฌ์šฉ์ž์ด๋“  ๊ธฐ์กด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹จ์ˆœํ™”ํ•˜๋ ค๋Š” ์ˆ™๋ จ๋œ ์‚ฌ์šฉ์ž์ด๋“  Redux-Toolkit์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋” ๊ฐœ์„ ๋˜๊ณ  ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ์‰ฌ์›Œ ์ง„๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.


Redux-Toolkit์ด ์ œ๊ณตํ•˜๋Š” ๊ฒƒ

 

configureStore

 

๊ฐ„๋‹จํ•˜๊ฒŒ Store๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค,

 

createReducer

 

switch๋ฌธ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ ๋Œ€์‹  ๊ฐ„๋‹จํ•˜๊ฒŒ Reducer๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

 

createAction

 

Reducer์— ์ž‘์„ฑํ•œ ๊ฒƒ๋“ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ Action๋“ค์„ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

 

createSlice

 

reducer์˜ ์ด๋ฆ„, ์ดˆ๊ธฐ์ƒํƒœ, reducers ๋“ฑ์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

 

createAsyncThunk

 

createAction์„ ๋น„๋™๊ธฐ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

 

createSelector

 

Store์—์„œ ์ƒํƒœ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ €์žฅํ•˜๋„๋ก ๋ ์›๋‹ˆ๋‹ค.


๊ธฐ์กด Redux์™€ ๋น„๊ต

 

์œ„์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง„ ๋ชปํ–ˆ์ง€๋งŒ ๊ธฐ์กด Redux์™€ Redux-Toolkit์„ ์ด์šฉํ•˜์—ฌ Counter์•ฑ๊ณผ Todo์•ฑ์„ ๋งŒ๋“ค์–ด ๋ณด์•˜๋Š”๋ฐ์š”.

 

๊ฐ„๋‹จํ•œ ์•ฑ์„ ๋งŒ๋“œ๋Š” ๋ฐ๋„ Redux-Toolkit์ด ๊ฐ„ํŽธํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋Š๋‚„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

1. Store

 

๊ธฐ์กด Redux๋Š” store๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

 

Reducer๋ฅผ ์ƒ์„ฑํ•˜๊ณ  combineReducers๋กœ ์—ฌ๋Ÿฌ Reducer๋ฅผ ํ•ฉ์ณ์ค€ ๋’ค rootReducer๋ฅผ ๋งŒ๋“ค๊ณ  RootState ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด ์ค˜์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

export const rootReducer = combineReducers({
  counter: counterReducer,
  todoList: todoReducer,
});

export interface RootState {
  counter: Counter;
  todoList: TodoState;
}

 

๊ทธ ๋‹ค์Œ createStore๋กœ ๋งŒ๋“ค์–ด ์ค˜์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

const store = createStore(rootReducer);

 

Redux-Toolkit์„ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

 

configureStore๋กœ ์—ฌ๋Ÿฌ reducer๋ฅผ ๋‹ด์•„ ๋งŒ๋“ค์–ด ์ฃผ๊ณ ,

 

const store = configureStore({
  reducer: {
    counter: counterSlice.reducer,
    todoList: todoSlice.reducer,
  },
});

 

State ๋˜ํ•œ store.getState๋ฅผ ํ†ตํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

export type RootState = ReturnType<typeof store.getState>;

 

2. Action

 

๊ธฐ์กด Redux๋Š” ๋ฐœ์ƒํ•  Action๊ณผ ActionType ๋“ฑ์„ ์ง์ ‘ ๋งŒ๋“ค์–ด ์ค˜์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

export enum TodoActionType {
  tapAdd,
  tapDelete,
  tapUpdate,
  modalOpen,
  modalClose,
}

export type TodoPayload = {
  todo: Todo;
  selectedIndex: number;
};

export type TodoAction = {
  type: TodoActionType;
  payload: TodoPayload;
};

 

Redux-Toolkit์—์„  createSlice์—์„œ ๋งŒ๋“  ๊ฒƒ์„ ๋ฐ”ํƒ•์œผ๋กœ action์„ ์ถ”์ถœํ•ด ๋‚ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

 

3. Reducer

 

๊ธฐ์กด Redux๋Š” ์ง์ ‘ Reducer๋ฅผ ๋งŒ๋“ค์–ด initialState ๋“ฑ๊ณผ switch๋ฌธ์œผ๋กœ action์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‚˜๋ˆ ์ค˜์•ผ ํ–ˆ๊ณ  ๊ธฐ์กด state์— ๋ฐ”๋€์ ๋“ค์„ ์ ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

const todoReducer = (
  state: TodoState = initialState,
  action: TodoAction,
): TodoState => {
  let newTodos = state.todos;
  switch (action.type) {
    case TodoActionType.tapAdd:
      newTodos.push(action.payload.todo);
      return {
        ...state,
        todos: newTodos,
        isModalVisible: false,
      };
    case TodoActionType.tapDelete:
      newTodos.splice(action.payload.selectedIndex, 1);
      return {
        ...state,
        todos: newTodos,
      };
    case TodoActionType.tapUpdate:
      newTodos[action.payload.selectedIndex] = action.payload.todo;
      return {
        ...state,
        todos: newTodos,
        selectedIndex: action.payload.selectedIndex,
        isModalVisible: false,
      };
    case TodoActionType.modalClose:
      return {
        ...state,
        isModalVisible: false,
        selectedIndex: -1,
      };
    case TodoActionType.modalOpen:
      return {
        ...state,
        isModalVisible: true,
        selectedIndex: action.payload.selectedIndex,
      };
    default:
      return state;
  }
};

 

Redux-Toolkit์„ ์‚ฌ์šฉํ•˜๋ฉด createSlice๋กœ ๊ฐ Action์— ๋”ฐ๋ฅธ reducer๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

export const todoSlice = createSlice({
  name: 'todoList',
  initialState,
  reducers: {
    add: (state, action: PayloadAction<TodoPayload>) => {
      let newTodos = state.todos;
      newTodos.push(action.payload.todo!);
      state.todos = newTodos;
      state.isModalVisible = false;
    },
    delete: (state, action: PayloadAction<TodoPayload>) => {
      let newTodos = state.todos;
      newTodos.splice(action.payload.selectedIndex!, 1);
      state.todos = newTodos;
    },
    edit: (state, action: PayloadAction<TodoPayload>) => {
      state.todos[action.payload.selectedIndex!] = action.payload.todo!;
      state.isModalVisible = false;
    },
    modalOpen: (state, action: PayloadAction<TodoPayload>) => {
      state.isModalVisible = true;
      state.selectedIndex = action.payload.selectedIndex!;
    },
    modalClose: state => {
      state.isModalVisible = false;
      state.selectedIndex = -1;
    },
  },
});

 

4. Dispatch

 

๊ธฐ์กด Redux๋Š” ์•ก์…˜์„ Reducer์— ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด act๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ 

 

  const act = (type: TodoActionType, selectedIndex: number) => {
    const payload: TodoPayload = {
      todo: todoState.todos[selectedIndex],
      selectedIndex: selectedIndex,
    };
    const action: TodoAction = {
      type: type,
      payload: payload,
    };
    dispatch(action);
  };

 

์•ก์…˜ํƒ€์ž…์„ ์ž…๋ ฅํ•ด ์ค˜์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

act(TodoActionType.modalOpen, -1)

 

Redux-Toolkit์„ ์ด์šฉํ•˜๋ฉด Slice์—์„œ actions๋ฅผ ์ถ”์ถœํ•ด ๋‚ธ ๋’ค,

 

  const actions = todoSlice.actions;

 

์•„๋ž˜์™€ ๊ฐ™์ด ์•ก์…˜์˜ ์ข…๋ฅ˜๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋์Šต๋‹ˆ๋‹ค.

 

  const payload: TodoPayload = {todo: null, selectedIndex: -1};
  dispatch(actions.modalOpen(payload)

Source Code

 

์•„๋ž˜๋กœ Repository๋กœ ์ด๋™ํ•˜์…”์„œ Redux์™€ Redux-Toolkit์˜ Counter์•ฑ๊ณผ Todo์•ฑ์„ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

GitHub - fomagran/ReduxTSPractice

Contribute to fomagran/ReduxTSPractice development by creating an account on GitHub.

github.com


๋Š๋‚€ ์ 

 

์•„์ง ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๋‹ค๋ค„๋ณธ ๊ฑด ์•„๋‹ˆ์ง€๋งŒ ์‹ค์ œ๋กœ ํŽธ๋ฆฌํ•˜๊ณ  ์ฝ”๋“œ ์–‘์ด ์ค„์–ด๋“œ๋Š” ๊ฒƒ์„ ๋Š๋ผ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

Redux์—์„œ ์•„์ฃผ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์‚ฌ์šฉ์„ ์ถ”์ฒœํ•˜๋‹ˆ ์•ˆ ์“ธ ์ด์œ ๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ์•ž์œผ๋กœ๋Š” Redux๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Redux-Toolkit์„ ์ด์šฉํ•ด ๊ฐœ๋ฐœํ•ด์•ผ๊ฒ ๋‹ค.


Reference

 

 

Redux Toolkit: Overview | Redux

Redux Toolkit is the recommended way to write Redux logic

redux.js.org

 

728x90
๋ฐ˜์‘ํ˜•