상세 컨텐츠

본문 제목

57일차 TIL(Redux(RTK) / 후발대 강의)

TILs

by API284 2023. 8. 6. 23:48

본문

Redux는

 

JavaScript 애플리케이션에서 (전역 / 부분전역) 상태를 관리하는 오픈 소스 라이브러리

주로 React와 함께 사용되며, Angular, Vue 등 다른 프론트엔드 라이브러리와도 연동하여 상태 관리를 용이

 

상태 관리의 복잡성 해소

애플리케이션의 상태는 컴포넌트 **계층 구조를 통해 전달

(props!**되는데, 애플리케이션이 커지고 복잡해질수록 상태의 흐름을 파악하기 어려워지는데

Redux는 이러한 상태 관리의 복잡성을 해소하고,

애플리케이션 전역에서 상태를 통합적으로 관리함으로써 간결하고 예측 가능한 상태 관리를 제공

 

예측이 가능하다?

어느 컴포넌트에서든지 접근(useSelector) / 제어(useDispatch)가 쉽고 용이하게 되어있으므로,

전역상태가 어떨지 특정 이벤트에서 고려하기 쉽다

어느 컴포넌트에서 오류가 발생했는지도 바로 알 수 있음.

 

데이터 흐름의 일관성 유지 Redux는 상태 변경을 예측 가능한 "액션(Action)"객체로 관리. 이를 통해 어떤 액션이 어떤 상태를 변경하는지 추적하기 쉬워지며, 애플리케이션의 데이터 흐름이 일관성을 유지.

 

 

 

Redux의 주요 개념들은 무엇인가요? (예: Store, Action, Reducer)

 

Store

  1. Store는 애플리케이션의 상태를 담고 있는 객체. 모든 상태는 단일한 Store에 저장되며 Redux의 createStore 함수를 사용하여 Store를 생성할 수 있다.

Action

  1. 액션(Action)은 상태 변화를 발생시키기 위해 스토어(Store)에 보내는 객체. 액션은 어떤 일이 일어났는지 기술하는 'type' 필드와 해당 액션과 관련된 추가적인 정보를 포함할 수 있는 다른 필드**(payload)**로 구성. 액션은 일종의 메시지로 생각할 수 있으며, 상태 변화를 일으키는 유일한 방법.

 

Reducer

  1. 상태(state)를 변화시키는 함수. 리듀서는 액션(Action)이 발생했을 때, 현재 상태와 해당 액션을 기반으로 새로운 상태를 계산하고 반환. Redux에서는 리듀서를 이용하여 앱의 상태 변화를 관리하며, 이러한 상태 변화를 예측 가능하고 투명하게 만들어준다.
  2. 리듀서는 순수 함수(pure function)로 작성되어야 한다. 순수 함수란 같은 입력에 대해 항상 같은 출력을 반환하고, 부작용(side effect)이 없는 함수를 의미. 이를 통해 Redux는 액션과 상태의 흐름을 추적하고, 디버깅, 테스트 등을 쉽게 할 수 있게 됨.
  3. 리듀서의 형태는 보통 **state**와 action 두 개의 매개변수를 받아 새로운 상태를 반환하는 형태.

Toolkit(Feat. Flux Pattern)

 

리덕스를 사용하기 위해 작성했던 ducks 패턴의 요소들이 전체적인 코드의 양을 늘린다는 개발자들의 불만이 발생하기 시작했고, 리덕스 팀에서는 이것을 수용하여 코드는 더 적게, 그리고 리덕스를 더 편하게 쓰기 위한 기능들을 흡수해서 만든 것이 리덕스툴킷

줄여서 RTK 라고도 합니다.

 

전혀 새로운 것이 아니며,

리덕스의 전체 코드의 양을 줄이기 위해 새로운 API가 추가되었고 우리가 일일히 손으로 만들어 줘야 했던

ducks 패턴의 요소들이 어느정도 자동화 되었다.

  • 컴포넌트에서 useSelector를 통해서 사용하는 것은 모두 똑같으며, 바뀐 부분은 그저 모듈 파일 뿐. 

 

일반 리덕스와 코드 비교

 

/// 일반 REDUX


// Action Value
const ADD_NUMBER = "ADD_NUMBER";
const MINUS_NUMBER = "MINUS_NUMBER";

// Action Creator
export const addNumber = (payload) => {
  return {
    type: ADD_NUMBER,
    payload,
  };
};

export const minusNumber = (payload) => {
  return {
    type: MINUS_NUMBER,
    payload,
  };
};

// Initial State
const initialState = {
  number: 0,
};

// Reducer
const counter = (state = initialState, action) => {
  switch (action.type) {
    case ADD_NUMBER:
      return {
        number: state.number + action.payload,
      };
    // [퀴즈 답]
    case MINUS_NUMBER:
      return {
        number: state.number - action.payload,
      };
    default:
      return state;
  }
};

// export default reducer
export default counter;

 

 

 

 

/// RTK

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

const initialState = {
  number: 0,
};

const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    addNumber: (state, action) => {
      state.number = state.number + action.payload;
    },

    minusNumber: (state, action) => {
      state.number = state.number - action.payload;
    },
  },
});

// 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;
// reducer 는 configStore에 등록하기 위해 export default 합니다.
export default counterSlice.reducer;

 

 

한 눈으로 보기에도 코드가 굉장히 짧아졌고 이해하기에도 쉬워졌다.

 

슬라이스는 createSlice 라는 API를 통해 만들 수 있다. 그리고 그 인자로 설정정보를 객체로 받는데, 그 안에 우리가 필수로 작성해줘야 하는 값은 name, initialState, reducers가 있다

 

//createSlice API 뼈대

const counterSlice = createSlice({
name: '', // 이 모듈의 이름
initialState : {}, // 이 모듈의 초기상태 값
reducers : {}, // 이 모듈의 Reducer 로직
})

 

counterSlice 리듀서 객체 안에서 만들어주는 함수가 리듀서의 로직이 되면서도 동시에 Action Creator가 된다

 그리고 Action Value 까지 함수의 이름을 따서 자동으로 만들어지며, 그래서 우리는 Reducer만 만들어주면 됨

 

 

// 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;
// reducer 는 configStore에 등록하기 위해 export default 한다.
export default counterSlice.reducer;

관련글 더보기