Redux는 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너입니다.
공식 홈페이지 에서는 redux에 대해 다음과 같이 정의하고 있다.
react 혹은 다른 뷰 라이브러리에서도 사용 가능한 상태 관리 라이브러리인데 요 상태 에 대해 알아보기 위해 우선 react의 state와 props를 먼저 이야기 하려 한다.
props는 property의 줄임말으로 부모 컴포넌트 안에 자식 컴포넌트가 들어갔을 때 컴포넌트 단에 무언가를 주고받기 위해 사용하는게 prop이다. 즉, 자식 컴포넌트에 정보를 내려다주는 것을 props라고 말한다. prop는 위에서 아래로만(부모에서 자식으로만) 보낼 수 있다. 또한, 부모 컴포넌트에서 자식 컴포넌트로 prop을 줬을 때 해당 value는 변화가 불가하다.(불변성을 지님) 값을 바꾸고 싶으면 자식 컴포넌트 단에서 값을 바꿀 수는 없고 부모 컴포넌트에서 value 값을 바꾼 뒤 다시 내려주어야한다.
<ChatMessages messages={messages} currentMember={member}>
컴포넌트 안에서 데이터를 교환하거나 전달하기 위해 필요하다. props는 부모 컴포넌트에서 자식 컴포넌트로 내려주어야 값이 변할 수 있지만 state는 그냥 컴포넌트 안에서도 state를 변하게 할 수 있다. 다만, state의 value가 변하게 되면 렌더링이 다시 된다.
state = {
message: "",
attachFile: undefined,
openMenu: false,
};
그래서 Redux는 state를 관리하기 위해 사용한다. 이해를 돕기 위해 예시를 들어보자.
최상위 컴포넌트에서 comment에 대한 부분을 다 관리한다고 가정해보자. 모든 comment의 state는 최상위 컴포넌트에서 관리되고 있다. 그런데 자식 컴포넌트와 자식의 자식 컴포넌트에서도 comment 관리에 대한 기능이 들어가있다. 이럴 때 자식 컴포넌트나 자식의 자식 컴포넌트에서 무언가 comment에 관련된 작업을 했을 때 최상위 컴포넌트에 알려주어야 하는데 redux가 없다면 하나하나 타고 올라간 다음 다시 정보를 타고 다시 하나하나 다시 내려주어야한다.
comment를 최상위 컴포넌트에 두는게 아니라 redux store에 저장해두면 굳이 타고 올라가거나 타고 내려가지 않아도 직접 각 컴포넌트에서 store에 접근해서 데이터를 보내거나 받을 수 있으므로 훨씬 편하게 상태 관리가 가능하다.
React Component에서 시작을 해서 Dispatch를 해서 ACTION -> REDUCER -> STORE 순으로 간 뒤 Subscribe를 거쳐 다시 React Component로 돌아온다. Redux는 철저하게 한반향으로만 흐르는 Flow를 가진다.
Action은 무엇이 일어났는지 설명하는 객체를 말한다.
{type: "LIKE_ARTICLE" articleId: 42}
{type: "FETCH_USER-SUCCESS", response: {id: 3, name: "Mary"}}
{type: "ADD_TODO", text: "Read the Redux docs."}
원래 state가 action을 거치면서 값이 변한 것을 설명해주는 부분이다. 이전 state와 action object를 받은 후에 next state를 return 해준다.
(previousState, action) => nextState;
reducer는 pure function이기에 reducer내부에서 하지 말아야 할 것들
이라고 하는데 위의 내용은 이후에 redux를 조금 더 공부하면서 살펴보려.. 한다.. 이미 이것만으로도 너무 어려워..
redux의 메인 부분이다. 어플리케이션의 state를 감싸주는 역할을 한다. store 안에는 여러가지 많은 메서드들이 있는데 메서드들을 이용해서 state 관리가 가능하다.
redux 세팅을 위해 dependency들을 다운받아주자.
필요한 dependency들은 다음과 같다.
npm install redux react-redux redux-promise redux-thunk --save
client 디렉토리에서 해당 명령어를 실행해주자.
간단하게 설명하자면 redux를 잘 쓸 수 있게 도와 주기 때문이에요! 라고 말할 수 있다. 즉, redux store에서는 원래 객체만 받지만 promise와 functions을 받을 수 있도록 해준다.
redux는 redux store 안에 모든 state를 관리하는데 store에 state를 변경하고 싶으면 dispatch를 이용해서 action으로 변경시킬 수 있다. 여기서 action은 객체의 형식이어야 한다.
하지만 store에서는 언제나 객체의 형식으로만 된 action 을 받지만은 않는다. 어떨 때는 promise형식으로 된 걸 받을 때도 있고, 어떤 때는 functions 형식으로 된 것을 받을 때도 있다.
redux store는 오직 객체의 형식으로만 받는다고 했는데 promise나 function 형식으로 오면 당연히 react store가 받지 못하므로 에러가 난다. 이때 해당 미들웨어들을 사용해서 해결을 해준다. redux-thunk는 dispatch에게 function을 받는 방법을 알려주고 redux-promise는 dispatch에게 promise을 받는 방법을 알려준다.
import { Provider } from "react-redux";
import { applyMiddleware, createStore } from "redux";
import promiseMiddleware from "redux-promise";
import ReduxThunk from "redux-thunk";
import Reducer from "./_reducers";
const createStoreWithMiddleware = applyMiddleware(promiseMiddleware, ReduxThunk)(createStore);
ReactDOM.render(
<Provider
store={createStoreWithMiddleware(
Reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)}
>
<App />
</Provider>,
document.getElementById("root")
);
Provider 태그로 감싸주면 redux와 프로젝트의 어플리케이션과 연결이 된다. provider안에는 store를 넣어주어야한다. 원래 createStore를 해서 그냥 store만 생성하는데 그냥 store는 객체 밖에 못받기 때문에 promise와 function도 받을 수 있게 middleware와 함께 만들어준다. reducer와 extension tool을 이용하기 위해서 extension 관련 코드도 넣어준다!
기본 예제는 여기서 확인 가능하다.
미들웨어와 관련해서는 여기에 잘 정리되어있다!
import { combineReducers } from "redux";
// import user from "./user_reducer";
// import comment from "./comment_reducer";
const rootReducer = combineReducers({
// user, comment
});
export default rootReducer;
combineReducers는 여러가지 reducer들이 하나로 합해주는 기능을 한다.
reducer가 하는 일은 state가 변하는지 것을 보여준 다음 변한 마지막 값을 return 해준다. state는 user state가 있을 수도 있고 comment state가 있을 수도 있고 여러가지 state가 있을 수 있다. 여러가지 reducer가 요것들을 나누어져있는데 합해준다.
요것도 아주 유용하므로 받아준다!
따라하며 배우는 노드, 리액트 시리즈 - 기본 강의 를 공부하며 작성한 글입니다.