본문 바로가기

React

[React] Redux 개념 이해

[해당 포스트는 개인적으로 공부를 하고 차후에 참고용으로 하고자 작성한 것입니다.
따라서 잘못된 부분이나 부족한 부분이 있을 수 있기에 참고하시기 바랍니다.]

 

- Redux?

Redux는 state를 효율적으로 관리해주는 React의 Library로, 각 Component별 state를 분리시켜 효율적으로 작업 및 관리할 수 있다. 이전 Project까진 Main Component에 state를 생성하여 자식 Component와 연결한 후, Component별로 전달하고 전달하여 사용하였다. 그러나 Redux를 사용하면 연결된 Component사이에서 옮길필요없이 state를 전달 할 수 있다.

 

아래는 Redux를 사용하지 않고 state를 이용하는 그림이다.

 

 

위의 방식은 처음 사용했던 state를 통해 처리하는 방식이다.

부모 Component로 부터 연결된 자식 Component만 상태를 공유하고 변경할 수 있다. 하지만 서로 연결되지 않은 Component끼리는 상태를 바로 연결하여 이용할 수 없다.

 

다음은 Redux를 이용하여 state를 공유하는 방법이다.

 

 

Redux에선 "store" 라는 공간이 존재한다. Store는 서로 등록된 Component끼리 상태를 저장하는 장소이다. 이후 Component는 dispatch를 통해 state를 변경할 수 있다.

 

단순히 작은 프로젝트를 수행할 땐 Redux를 사용하지 않고 Main Component에서 state를 공유하여 사용해도 문제는 없다. 다만 프로젝트 규모가 커지면, state가 필요한 자식 Component까지 전달되게 하기 위해, 사용하지 않는 Component까지 거쳐가야하기 때문에 비효율적으며 작업이 귀찮아 진다.

 

- (Action, Action Creator), Reducer, Store, Dispatch

 

1. Action

State에 어떤 변화가 필요할 땐, Action을 발생시킨다. 선언은 하나의 객체로 표현되며, default로 type을 선언해줘야 한다. 추가적으로 변화시킬 값을 인자를 통해 추가할 수 있다.

 

// 방법 1
{
	type: "TODO_ANYTHING"
}

// 방법 2
{
	type: "TODO_ANYTHING",
	data: any_data
}

 

1-2. Action Creator

1. 은 Action을 어떻게 선언하는지에 대해 작성하였다. 이번엔 이를 이용할 수 있는 함수가 필요한데, 그것이 바로 Action Creator이다. 함수를 생성하여 Action을 return하면 된다.

 

// 방법 1
function todoAnything {
	return {
    	type: "TODOANYTHING"
    };
}

// 방법 2
const todoAnything = any_data => ({
	type: "TODOANYTHING",
	data: any_data
});

 

2. Reducer

Reducer는 state 변화를 일으키는 함수로, 공유하여 사용할 state와 action을 인자로 사용한다.

초기 state는 Reducer에서 생성해야하며, 이후 변경된 state는 덮어씌어서 사용된다.

또한 각 action별로 다르게 동작시키기 위해 switch ~ case 문을 이용한다. Action에서 지정했던 Type별로 분기하여 처리가 된다.

 

initState = {}

const reducer = (state = initState, action ) => {
    switch (action.type) {
        case "TODOANYTHING1":
            //To do something to state
            return changed state;
        case "TODOANYTHING2":
            //To do something to state
            return changed state;
        default:
            return state;
    }
}

 

Reducer에 대한 중요한 특징이 있는데 바로 순수함수여야 한다.

Reducer는 다음과 같은 성질을 가져야 한다.

 

- Reducer 함수는 이전 state와, action 객체를 파라미터로 받아야 한다.

- Reducer는 이전의 state는 변경하지 않고 변화를 일으킨 새로운 state 객체를 덮어씌우고 반환해야 한다.

- 똑같은 파라미터로 호출된 Reducer 함수는 언제나 똑같은 결과값을 반환해야 한다.

 

new Date()나 Axios나, Math.random 같이 실행 할 때마다 결과값이 다르게 나타는 비순수함수 같은 방식을 Reducer안에서 사용하면 안 된다. 이러한 처리는 Reducer 함수의 바깥에서 처리해줘야 한다.

 

Axios같이 네트워크 요청을 처리를 할 땐, Middle Ware를 이용하여 처리해야 한다.

3. Store

Application의 상태와 Reducer 등 모든 정보는 Store에 저장된다. Store는 React Application 당 한 개의 Store를 가지게 된다. Store는 주로 index.js에서 만들어 진다.

 

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './reducers';

const store = createStore(reducer);

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

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

 

redux Module을 통해 createStore를 호출하여 store를 생성할 수 있으며 인자는 reducer를 담는다. 이후 react-redux Module을 통해 Provider를 Main Component를 감싸고, store를 지정해서 사용한다.

 

4. Dispatch

Dispatch는 Store의 내장함수 중 하나로, Action Creator(Action)를 발생 시킨다. dispatch 함수에 action을 인자로사요 사용한다. 이후, Store는 Reducer 함수를 실행시켜 해당 Action을 처리하는 로직이 있다면 Action을 참고하여 새로운 state를 만든다.

 

let mapDispatchToProps = (dispatch) => {
    return {
        todoAnything: (value) => dispatch(todoAnything(value))
    };
}

 

참고 사이트
https://velog.io/@velopert/Redux-1-소개-및-개념정리-zxjlta8ywt (Velopert 님)