개발일기

React - Redux를 통한 상태관리 본문

Javascript/React.js

React - Redux를 통한 상태관리

Flashback 2022. 3. 22. 17:21
728x90
반응형

 

1. 리액트의 상태관리(props)

리액트에서 컴포넌트간의 상태관리를 위해 각 컴포넌트들의 상태값을 props로 넘겨 주고받는 방법으로 상태관리를 하였다.

프로젝트의 규모가 소규모라 나뉘어진 컴포넌트와 기능들이 적은 경우 props로 간단하게 상태관리를 할 수 있다. 하지만, 이와는 반대로 프로젝트의 규모가 커지는 경우 원하는 컴포넌트로 상태값들을 전달하려 할 때, 4~5 개의 컴포넌트들을 지나쳐 값을 전달하는 경우가 종종 발생한다. 불필요한 컴포넌트들을 거쳐 값을 전달하여 관리하려면, 값을 전달할 때 마다, 불필요한 작업을 반복적으로 해야하고, 실수를 통해 에러가 발생할 수도 있다는 단점을 가지고 있다.

 

  • 각 컴포넌트 간에 value={value} 형식으로 값을 주고받는다.
  • 컴포넌트가 적은 소규모 프로젝트에서는 유용하게 쓰인다.
  • 컴포넌트가 많은 경우는 props를 사용한 상태관리라 복잡해진다.

 

props를 통한 복잡한 상태관리를 보다는 리덕스를 사용할 경우, store라는 공간에 상태값들을 저장한 후, 해당 상태값이 필요한 컴포넌트에서 값을 빼어내어 사용할 수 있다는 편리한 장점을 가지고 있다.

 

2. redux, react-redux, redux-thunk 설치

npm install redux
yarn add redux

npm install react-redux
yarn add react-redux

npm install redux-thunk
yarn add redux-thunk

 

리액트에서 리덕스를 사용하려면 redux와 react-redux를 설치해야 한다. 또한 액션 생성 함수를 작성할 수 있도록 하기 위해 추가적으로 redux-thunk를 설치해야 한다.

 

3. index.js 초기 설정

리액트의 index.js를 구성할 때, 다음과 같은 핵심 부분이 있다. HTML파일에서 id값이 root인 html태그에 App.js의 내용을 덧붙히는 것을 의미한다. 리덕스를 사용하기 위해서는 ReactDOM.render 부분에서 App.js를 다음과 같은 Provider태그로 감싸주면 된다.

// index.js

import { Provider } from 'react-redux';
import { createStore } from 'redux';
import App from './App'; // App.js의 내용이 렌더링된다.

ReactDOM.render(
  <Provider store={ store }>
    <App />
  </Provider>,
  document.getElementById("root")
);

또한  리덕스의 createStore객체를 사용하여 리액트 앱에서 사용할 리덕스 스토어를 생성해줘야 한다. 리덕스 스토어는 각 앱에 한 개씩만 생성하는 것을 권장한다. 물론, 여러개의 리덕스 스토어를 생성할 수 있지만, 여러개의 스토어를 사용하면 리덕스 개발도구를 사용할 수 없고 오히려 상태관리를 할 때 더욱 복잡해질 수 있다. 리덕스의 장점을 유지하고자 상태 관리 스토어는 한 개만 사용하도록 권장된다.

 

4. 리듀서 생성

index.js에서 Provider를 감싼 후, 리덕스 스토어를 생성해 주기 위해 reducer들을 생성해줘야 한다. 리듀서를 사용할 때는, modules라는 폴더를 하나 만든 후, 해당 폴더 안에 기능별로 파일을 생성하여 사용한다.

// modules/fruit.js -  fruit이라는 기능을 가진 리듀서

// 액션
const SET_FRUIT_LIST = "fruit/SET_FRUIT_LIST";

// 액션 생성 함수
export const setFruitList = fruistList => ({ type : SET_FRUIT_LIST, fruitList });

// 초기값
const initialState = {
  name: false,
  price: false,
};

// 리덕스 스토어값 변경
export default function fruit(state = initialState, action) {
  switch(action.type) {
    case SET_FRUIT_LIST :
      return {
        ...state,
        name: action.fruitList,
      };
    default:
      return state;
  }
}

 

  • 액션 타입 정의 : 액션의 종류를 분류할 수 있도록 모듈명/액션이름 으로 액션을 정의한다.
  • 액션 생성 함수 : 정의된 액션 타입을 바탕으로 실행할 액션함수를 생성한다.
  • 초기상태 : 해당 모듈의 리덕스 스토어의 초기값을 나타낸다.
  • 리덕스 스토어 값 변경 : 액션 타입이 일치하는 case에 따라 스토어의 값이 변하게 된다. 

 

액션을 생성할 때는, 해당 모듈의 이름을 앞 부분에 써준 후, 뒷 부분에는 해당 액션 이름을 넣어준다는 약속된 규칙을 가지고 있다.

위에 코드를 작성한 파일의 이름이 fruit.js이고 액션 이름이 SET_FRUIT_LIST이기에 "fruit/SET_FRUIT_LIST"로 액션을 생성하였다.

 

액션 생성 함수는 리덕스 스토어에 저장할 값을 가져오는 역할을 한다. 나중에 알아볼 dispatch를 통해 이 액션 함수와 값을 호출한 후, 액션 타입에 따라 리덕스 스토어에 값이 어떻게 들어갈지 판별하게 되는 과정을 거쳐 스토어의 값을 변경한다.

 

초기값은 리덕스 스토어가 생성될 때, 어떠한 형태로 스토어를 형성할지 결정하는 부분이다. 위와 같이 초기상태를 결정한 경우, name과 price에 false라는 초기값이 들어간 상태로 fruit모듈의 리덕스 스토어가 생성된다.

 

export default function fruit 부분은 이 부분에 있는 switch 조건문의 조건을 통해 실행할 액션을 결정하게 된다. 해당 액션명의 타입에따라 조건을 걸러지게 되고, 일치하는 case문에 따라 가지고 있는 액션값을 통해 리덕스 스토어의 상태값이 변경된다.

 

이와 같이 기능에 따라 파일을 나누어 리듀서들을 생성한다. 기능별로 나뉘어진 리듀서들을 리덕스 라이브러리의 combineReducer라는 객체를 통해 하나의 리듀서로 통합한 후, 리덕스 스토어를 생성하여 리덕스 스토어 설정을 마무리할 수 있다.

 

5. 리듀서 통합

// modules/index.js - 리듀서들을 통합할 때, index.js에서 리듀서들을 합쳐준다.

import fruit from './fruit';
import { combineReducers } from 'redux';

const rootReducer = combineReducers({ fruit });
// 이 부분에 여러 개의 리듀서들을 콤마로 구분하여 넣어주면 된다.
// 리듀서들이 fruit, food, plant 총 3개가 있는 경우
// const rootReducer = combineReducers({ fruit, food, plant }); 가 된다.

export default rootReducer

redux의 combineReducers 객체를 사용하여 리듀서들을 하나로 묶어 준다.

 

리듀서를 묶어준 후, ReactDOM.render가 있는 index.js로 이동하여 리덕스 스토어를 생성하여 Provider객체에 props로 넣어주면 리덕스 스토어가 생성된다.

 

6. index.js 마무리 설정

// index.js

import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './modules'; // modules/index.js
import App from './App'; // App.js의 내용이 렌더링된다.
import ReduxThunk from 'redux-thunk';

const store = createStore( rootReducer, applyMiddleware(ReduxThunk) );

ReactDOM.render(
  <Provider store={ store }>
    <App />
  </Provider>,
  document.getElementById("root")
);

rootReducer를 import한 후, redux의 createStore객체 파라미터에 rootReducer 추가하여 리덕스 스토어를 생성한다. 그 후, Provider에 props로 리덕스 스토어 변수를 추가해주면 리덕스 스토어가 생성된다.

 

createStore에 두 번째 파라미터리액트 개발자 도구와, 로그를 찍어주는 미들웨어들을 적용할 수 있다. 개발자 도구와 로그 미들웨어를 추가하면 액션이 발생할 때 마다, 콘솔 창에 해당 액션에 관한 콘솔 로그가 찍히게 되고, 리액트 개발자 도구에서 액션이 발생할 때 마다, 리덕스 스토어의 상태가 어떻게 변경되었고, 현재의 상태는 어떠한지 알 수 있어 원활하게 개발을 진행할 수 있다.


-- 액션을 호출하여 리덕스 스토어의 상태값을 변경하는 방법 --

https://phsun102.tistory.com/84

 

React - useDispatch를 사용한 액션 실행

redux의 액션 생성함수를 실행하여 리덕스 스토어에 변경된 상태값을 저장하기 위해서는 useDispatch라는 리액트 훅을 사용하여 액션을 실행시켜야 한다. 1. useDispatch 사용을 위한 react-redux 설치 npm in

phsun102.tistory.com

 

-- 리덕스 스토어의 상태값을 반환하는 방법 --

https://phsun102.tistory.com/85

 

React - useSelector를 활용한 리덕스 상태값 반환

useSelector는 리액트의 리덕스 스토어 관련 Hook중 하나이다. 이 Hook은 스토어의 상태값을 반환해주는 역할을 한다. useSelector를 사용한 함수에서 리덕스 스토어의 상태값이 바뀐 경우( 버튼 클릭 등

phsun102.tistory.com

 

dispatch를 통해 액션을 호출하여 스토어의 상태를 변경하고, 개발자 도구와 미들웨어를 통해 로그를 찍어볼 수 있는 추가 설정은 다음 포스팅에서 다뤄보고자 한다.

728x90
반응형
Comments