Post

Redux의 동작원리 및 문제점

Redux란?

애플리케이션의 state를 관리하기 위한 오픈소스 JavaScript 라이브러리




필요성

웹 서비스가 발전하게 되면서 이제는 하나의 Page단위가 아니라 Page안에 여러 컴포넌트들이 하나의 화면에서 구성이 될 수 있도록 발전을 하게 된다.

- 웹 서비스의 발전과 개발 패턴에 대한 내용이 궁금하다면 프론트엔드 아키텍쳐 게시글을 통해 확인할 수 있습니다.


화면을 구성하는 component간에 데이터를 주고받기 위해서는 아래의 조건이 따른다.

  • Component간의 데이터를 주고받기 위한 조건

    • 자식 컴포넌트들 간의 다이렉트 데이터 전달은 불가능하다.
    • 자식 컴포넌트들 간의 데이터를 주고 받을 때는 상태를 관리하는 부모 컴포넌트르 통해서 주고 받는다.

image

  • 위의 그림처럼 자식 컴포넌트에서 state가 변경 된다면 state가 사용되는 컴포넌트는 부모 컴포넌트에서부터 props로 전달받아야한다.

  • 100번째 자식에게 props를 전달하기 위해선 그 사이의 모든 컴포넌트들의 props에 데이터를 하향적으로 전달해주어야 한다.

    => Props drilling이슈 발생



💡 해결: 다른 컴포넌트에서도 사용되는 state를 전역으로 관리하면 하위로 내려줄 필요가 없다.

image

  • redux 상태관리 라이브러리를 통해 필요한 state를 모든 컴포넌트에서 접근이 가능하게 되었다.

  • Props drilling 이슈 해결




동작 원리

image

  • Store

    • Store(스토어)는 상태가 관리되는 오직 하나의 공간이다.

    • 컴포넌트에서 상태 정보가 필요할 때 useSeletor로 스토어에 접근해 state를 사용=> state.data


  • Action

    • Store에 운반할 데이터로, 자바스크립트 객체 형태이다. Action을 Reducer에 전달한다.


  • Reducers

    • Action을 전달받아 Store의 상태를 업데이트한다.

    • Action을 Reducer에 전달하기 위해서는 dispatch() 메소드를 사용한다.

    • 기존의 state를 받지만 그걸 직접 변경하는게 아니라 새로운 state 객체를 만들어 기존 state를 대체함




사용 방법

Redux 공식 문서

1. 설치

1
 $ npm install redux

2. 적용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const { createStore } = require("redux");

// 초기 state
const initialState = {
  compA: "a",
  compB: 12,
  compC: null
};

// action 생성
const changeCompA = (data) => {
  return {
    // action
    type: "CHANGE_COMP_A",
    data
  };
};

// reducer 함수
const reducer = (prevState, action) => {
  switch (action.type) {
    case "CHANGE_COMP_A":
      return {
        ...prevState,
        compA: action.data
      };
    default:
      return prevState;
  }
};

// store 생성
const store = createStore(reducer, initialState);

// action reducer에 전달
store.dispatch(changeCompA((data = "b"))); // compA를 b로 변경




Redux에서의 비동기(Middleware)

Redux의 action은 객체고 동기적인 일 밖에 수행하지 못한다.

로그인, 게시글 작성등 서버를 거치는 비동기 작업을 위해서 middleware를 사용해야한다.

middleware란?

dispatch와 reducer 사이에 위치하여 어떤 역할을 수행하며 비동기 처리를 할 수 있다.

image


대표적인 redux middleware인 thunk에 대해 살펴보자.


thunk 구현해보기

1. middleware 정의

1
2
3
4
5
6
const thunkMiddleware = (store) => (dispatch) => (action) => {
  if (typeof action === "function") {
    return action(store.dispatch, store.getState);
  }
  return dispatch(action);
};
  • redux-thunk middleware에서, 전달받을 action이 함수인 경우는 비동기, 객체인 경우 동기로 dispatch

2. store에 middleware 등록

1
2
const store = createStore(reducer, initialState, enhancer);
const enhancer = applyMiddleware(thunkMiddleware);

3. 예시) setTimeout으로 로그인 요청 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const logIn = () => {
  return (dispatch, getState) => {
    dispatch(logInRequest(data));
    setTimeout(() => {
      dispatch(
        logInSuccess({
          userId: 1,
          nickname: "hajeong"
        })
      );
    }, 2000);
  };
};

const logInRequest = (data) => {
  return {
    type: "LOG_IN_REQUEST",
    data
  };
};

const logInSuccess = (data) => {
  return {
    type: "LOG_IN_SUCCESS",
    data
  };
};

store.dispatch(logIn());
  • dispath로 실행된 action이 함수이므로 비동기로 실행

  • logInRequest 실행하고 2초뒤에 loginSuccess 실행




redux에서 비동기 상태 관리 라이브러리로

  • Redux의 불편한 점

    • Redux로 비동기 데이터를 관리하는 일에는 여전히 불필요하게 느껴지는 반복되는 Boilerplate 코드가 필요

    • Redux를 사용하여 비동기 데이터를 관리하기 위해서는 상태를 세분화하여 관리하는 경우도 있다.
      ex) LOADING | SUCCESS | ERROR 등


이러한 redux의 불편함으로 비동기 상태 관리 라이브러리를 탐색

image

가장 많이 사용하는 swr과 react-query를 비교해보기로 결정!

swr과 react-query비교 내용은 프론트엔드 아키텍쳐 게시글을 통해 확인할 수 있습니다.




📑 참고 자료

Redux(리덕스)란? (상태 관리 라이브러리)

React.js - redux middleware(리덕스 미들웨어, redux-thunk, redux-saga)

카카오페이 프론트엔드 개발자들이 React Query를 선택한 이유

React에서 Redux가 왜 필요할까?

npm trends

This post is licensed under CC BY 4.0 by the author.