지난 CORE 프로젝트와 NVP 프로젝트를 통해 Redux를 차례대로 구현해보았다.
React에서 가장 많이 쓰고 있는 상태 관리 라이브러리인데, 사람들은 왜 이 Redux가 좋다고 하는 것일까?
이에 대한 궁금증을 해결하고, 정확한 개념을 쌓기 위해 이 글을 쓰고자 한다.
JavaScript 상태관리 라이브러리
이며, 본질은 Node.js 모듈이다.
Store, Action, Reducer로 구성되어 있으며 지켜야 할 3가지 규칙이 있다.
그렇다면 Store, Action, Reducer는 각각 어떤 특징을 가지고 있을까?
상태가 관리되는 단 하나의 공간이다.
컴포넌트와는 별개로 store라는 공간이 존재하기 때문에, 앱에서 필요한 상태를 모두 이곳에 담는다.
따라서 컴포넌트에서는 상태 정보가 필요할 때, store에 접근하는 것이 필수적이다.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
const store = createStore(/*root reducer*/);
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>
document.getElementById('root')
);
앱에서 store에 운반할 데이터를 말한다.
action은 자바스크립트 객체 형식으로 되어있어야 하며 type필드
는 필수적이다.
{
type : "LOGIN",
payload : {
id : "seohee",
password : "12345"
}
}
액션을 만드는 함수이며, 단순히 파라미터를 받아와서 액션 객체 형태로 변경해준다.
이는 컴포넌트에서 더욱 쉽게 액션을 발생시키기 위함이지만, 리덕스를 사용할 때 액션 생성함수를 사용하는 것이 필수적이지는 않다. 액션을 발생 시킬 때마다 직접 액션 객체를 작성하는 것도 가능하다.
export function login(data){
return{
type : "LOGIN",
data
}
}
//화살표 함수도 가능하다.
export const changeId = id => ({
type : "CHANGE_ID",
id
});
Action에서 보낸 데이터 처리 방식을 보고 Store의 상태를 관리해준다.
즉, 변화를 일으키는 함수이다.
Action이 일어나면, 바로 Store에서 상태를 변경하는 것이 아니라 Reducer를 거쳐서 전달된다.
리듀서는 두 가지의 파라미터로 state와 action을 갖는다.
const initState = {
id :'',
password:''
}
function reducer(state= initState, action){
//상태 업데이트
switch(action.type){
case 'LOGIN':
return {
...state,
id : action.data.id,
password : action.data.password
};
default:
return state;
}
return state;
}
여기서 Action을 전달받기 위해 dispatch( ) 메소드를 사용해야한다.
Store의 내장함수 중 하나이며, 액션을 발생시키는 것이다.
dispatch(action)
의 형태로 사용된다.
구도 또한 Store의 내장함수 중 하나이며, 함수 형태의 값을 파라미터로 받아온다.
즉, subscribe 함수에 특정 함수를 전달해주면, 액션이 dispatch 될 때마다 전달된 함수가 호출된다
react-redux 라이브러리에서 제공하는 connect()
또는 useSelector
Hook을 사용하여 구독한다.
import { connect } from 'react-redux';
const mapStateToProps = (state, ownProps) => {
return {
id : state.id,
password : state.password
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
return{
login : (data) => {
dispatch(login(data));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Login);
정리하면 Redux의 흐름은 다음과 같다.
- Action 객체가 dispatch( )메소드에 전달된다
- dispatch(액션)를 통해 Reducer를 호출한다.
- Reducer는 새로운 store를 생성한다.
이러한 이유는 React에서의 데이터는 단방향 흐름
을 갖고 있기 때문이다.
지금까지 살펴본 것에 의하면, Redux는 단순히 React를 도와주는 역할에 불과하다.
하지만, 앞서 말한 3가지 규칙을 지킨 Redux는 상당한 강점을 갖게 된다.
- 사용자가 어떤 액션을 했고, 어떤 데이터가 변경되었는지 쉽게 알 수 있다.
더불어 개발자는 일어난 모든 액션의 기록을 확인할 수 있기에, 오류가 발생했을 때 이전 상태로 쉽게 돌아가 테스트를 해볼 수 있다.- 많은 사용자들이 동시에 다양한 작업을 하는 경우에 유리해진다.
- 모든 데이터를 storage에 저장할 수 있다.
즉, 사용자가 브라우저를 종류하고 다시 들어와도 동일한 시점에서부터 실행할 수 있다는 것이다.
그러나, 규칙에 의해 발생하는 단점도 있다.
- 사소한 기능이라도 Redux로 구현하려면, 몇 개의 파일을 필수적으로 만들어야한다.
따라서 최소한의 코드로 기능을 구현한다는 말은 적용할 수 없다.
장단점을 동시에 가지고 있는 Redux는 대체 언제 사용해야 할까??
📚 학습할 때, 참고한 자료 📚