[React] Redux

mj·2021년 6월 28일
0

Redux란?

Redux는 애플리케이션 상태를 관리하기위한 오픈 소스 JavaScript 라이브러리이다.
Context API처럼 전역으로 상태(state)를 관리하는 것을 수월하게 해준다.

충분히 Context API로도 전역 상태를 관리할 수 있지만, Redux는 saga라는 미들웨어도 지원하고 전역 상태 관리 외에도 로컬스토리지 상태저장, 버그리포트 첨부 기능 등의 기능들을 사용할 수 있다.

액션(Action)

상태에 어떠한 변화가 필요하면 액션이라는 것이 발생한다. 액션은 하나의 객체로 표현되고 type필드를 꼭 가지고 있어야 한다.

{
	type: 'action',
      	data: {
         id: 1,
         text: 'action text'
        }
}

액션은 함수로 생성할 수 있다.

funciton addAction(data){
  return {
	type:  'action',
    	data
  }
}

const actionfunc1 = data => ({ type: 'action', data });

리듀서(Reducer)

reducer 변형하는 것이라는 의미를 담고 있습니다. 액션을 발생시키면 리듀서가 현재 상태와 전달받은 액션 객체를 파라미터로 받아서 새로운 상태로 만들어 반환합니다.

const initState = { number: 1 };
function reducer(state = initState, action){
  switch(action.type){
    case PLUS :
      return { number: state.number + 1 };
     default :
      return state;
  }
}

스토어(store)

프로젝트에 리덕스를 적용하기 위해 스토어를 사용합니다.

A store holds the whole state tree of your application. The only way to change the state inside it is to dispatch an action on it.

리덕스 공식홈페이지에서 스토어는 애플리케이션 전체의 상태 트리를 보유하고 있다고 나옵니다. 내부 상태를 변경하기 위해서는 dispatch를 통해 액션을 전달해야 한다고 말하고 있습니다.

디스패치(dispatch)

스토어의 내장함수이며, 디스패치는 액션을 발생시킵니다. 디스패치가 호출되면 스토어는 리듀서 함수를 통해서 새로운 상태를 만들어줍니다.

store.dispatch(actionfunc1(data));

구독(subscribe)

스토어의 내장함수이며, 액션이 디스패치 되었을 때마다 호출되어 현재 상태의 트리를 읽을 수 있습니다.

const listener = () => { console.log('상태가 업데이트되었어요.';) }
const unsubscribe = store.subscire(listener);
unsubscribe();

리덕스 규칙

  • 1. 단일스토어: 하나의 애플리케이션 안에는 하나의 스토어를 사용한다. 여러 개의 스토어를 사용하면 상태관리가 매우 복잡해진다.
  • 2. 읽기 전용 상태: 리덕스의 상태는 읽기 전용이다. 데이터 변경을 얕은 비교를 통해서 검사하기 때문에 불변성을 지켜주어야 하기 때문이다.
  • 3. 순수한 함수: 리듀서는 순수한 함수여야 한다. 파라미터외에는 의존하지 않고, 일관성있게 새로운 상태 객체를 만들어서 반환해야 한다.

리덕스 적용

리덕스는 actions, constants, reducers 세 개의 기능이 필요한데 이것을 ducks 패턴으로 모듈화하여 사용한다.
만든 리듀서들은 한 곳에 모아 rootReducer로 제공한다. 그리고 react-redux 라이브러리 안에 있는 Provider 컴포넌트를 사용하여 store을 prop으로 전달할 수 있다.
모든 기능들을 Container별로 나누어 react-redux 라이브러리의 connect를 함수로 연동한다.

redux-actions 라이브러리

액션 생성 함수를 짧고 직관적이게 작성하게 도와주는 라이브러리이다. 리듀서를 작성할 때에도 switch/case문이 아닌 handleActions라는 함수를 통해 각 함수마다 업데이트 함수를 설정하는 형식으로 작성할 수 있다.
파라미터의 첫 번째에는 액션의 업데이트 함수를 넣고, 두 번째에는 초기 상태를 넣어준다.

import { createAction } from 'redux-actions';

const ACTION = 'module/ACTION';
const action = createAction(action);

const initState = { number: 0 };

const reducer = handleActions(
  {
  	[ACTION]: (state, action) => ({ number: state.number + 1 })
  },
  initState
)

미들웨어(middle ware)

미들웨어는 액션을 디스패치했을 때 리듀서에서 이를 처리하기전 지정된 작업을 실행해줍니다. 액션과 리듀서의 중간자입니다. flux구조를 보면
액션 -> 미들웨어 -> 리듀서 -> 스토어 -> 뷰 라고 할 수 있습니다.
미들웨어는 전달받은 액션을 기반으로 다른 종류의 액션을 추가로 디스패치하거나 취소할 수도 있는 다재다능한 기능입니다.
redux-logger라는 오픈소스 미들웨어를 스토어에 적용하려면
yarn add redux-logger로 프로젝트에 다운받습니다.

(...)
import { createLogger } from 'redux-logger';
const logger = createLogger();
const store = createStore(rootReducer, applyMiddleware(logger));

redux-saga

saga는 비동기 작업을 관리를 수월하게 할 수 있도록 도와주는 라이브러리입니다. redux-thunk는 함수 형태의 액션을 디스패치하여 미들웨어에서 해당 함수에 스토어의 dispatch와 getState를 파라미터로 넣어서 사용하는 원리입니다. saga는 thunk와 유사하지만
1. 기존 요청을 취소 처리해야 할 때(불필요한 중복 요청 방지)
2. 특정 액션이 발생했을 때 다른 액션을 발생시키거나, API요청 등 리덕스와 관계없는 코드를 실행할 때
3. 웹 소켓을 사용할 때
4. API요청 실패 시 재요청해야 할 때
위와 같은 상황에서는 saga를 사용하는 것이 좋습니다.

0개의 댓글