리액트 없이 쓰는 리덕스
리덕스는 리액트에 종속되는 그런 라이브러리가 아닙니다. 물론 리액트에서 쓰기위해 만든거니 궁합은 매우 잘맞죠! 한번, 평범한 HTML 와 JavaScript 환경에서 리덕스를 사용해가면서, 리덕스의 기본 개념을 배워봅시다.
우선, JSBin(https://jsbin.com/) 을 열으세요.
우리는 간단한 카운터를 구현해보겠습니다. HTML 섹션엔 다음과 같이 입력해보세요.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>그냥 평범한 리덕스</title>
</head>
<body>
<h1 id="number">0</h1>
<button id="increment">+</button>
<button id="decrement">-</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.js"></script>
</body>
</html>
그럼 이러한 결과가 만들어집니다.
자, 이제 자바스크립트를 작성 할 것입니다! 주석을 아주~ 상세하게 적어놓았으니, 주석도 함께 읽어가면서 자바스크립트를 작성해보세요.
// 편의를 위하여 각 DOM 엘리먼트에 대한 레퍼런스를 만들어줍니다.
const elNumber = document.getElementById('number');
const btnIncrement = document.getElementById('increment');
const btnDecrement = document.getElementById('decrement');
// 액션 타입을 정의해줍니다.
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// 액션 객체를 만들어주는 액션 생성 함수
const increment = (diff) => ({ type: INCREMENT, diff: diff });
const decrement = () => ({ type: DECREMENT });
// 초기값을 설정합니다. 상태의 형태는 개발자 마음대로 입니다.
const initialState = {
number: 0
};
/*
이것은 리듀서 함수입니다.
state 와 action 을 파라미터로 받아옵니다.
그리고 그에 따라 다음 상태를 정의 한 다음에 반환해줍니다.
*/
// 여기에 state = initialState 는, 파라미터의 기본값을 지정해줍니다.
const counter = (state = initialState, action) => {
console.log(action);
switch(action.type) {
case INCREMENT:
return {
number: state.number + action.diff
};
case DECREMENT:
return {
number: state.number - 1
};
default:
return state;
}
}
// 스토어를 만들 땐 createStore 에 리듀서 함수를 넣어서 호출합니다.
const { createStore } = Redux;
const store = createStore(counter);
// 상태가 변경 될 때 마다 호출시킬 listener 함수입니다
const render = () => {
elNumber.innerText = store.getState().number;
console.log('내가 실행됨');
}
// 스토어에 구독을하고, 뭔가 변화가 있다면, render 함수를 실행합니다.
store.subscribe(render);
// 초기렌더링을 위하여 직접 실행시켜줍니다.
render();
// 버튼에 이벤트를 달아줍니다.
// 스토어에 변화를 일으키라고 할 때에는 dispatch 함수에 액션 객체를 넣어서 호출합니다.
btnIncrement.addEventListener('click', () => {
store.dispatch(increment(25));
})
btnDecrement.addEventListener('click', () => {
store.dispatch(decrement());
})
이제 버튼들을 눌러보시면 숫자가 변경 될 것입니다. 지금까지 한 작업들을 정리해봅시다.
- 액션타입을 만들어주었습니다.
- 그리고 각 액션타입들을 위한 액션 생성 함수를 만들었습니다. 액션 함수를 만드는 이유는 그때 그때 액션을 만들 때마다 직접
{ 이러한 객체 }
형식으로 객체를 일일히 생성하는 것이 번거롭기 때문에 이를 함수화 한 것입니다. 나중에는 특히, 액션에 다양한 파라미터가 필요해 질 때 유용합니다. - 변화를 일으켜주는 함수, 리듀서를 정의해주었습니다. 이 함수에서는 각 액션타입마다, 액션이 들어오면 어떠한 변화를 일으킬지 정의합니다. 지금의 경우에는 상태 객체에 number 라는 값이 들어져있습니다. 변화를 일으킬 때에는 불변성을 유지시켜주어야 합니다.
- 스토어를 만들었습니다. 스토어를 만들 땐 createStore 를 사용하며 만듭니다. createStore 에는 리듀서가 들어갑니다. (스토어의 초기상태, 그리고 미들웨어도 넣을 수 있습니다.)
- 스토어에 변화가 생길 때 마다 실행시킬 리스너 함수 render 를 만들어주고,
store.subscribe
를 통하여 등록해주었습니다. - 각 버튼의 클릭이벤트에,
store.dispatch
를 사용하여 액션을 넣어주었습니다.
리덕스의 작동 흐름에 대하여 조금 감이 잡히셨나요? 그럼 이제 리액트에서 리덕스를 사용해봅시다!