프리온보딩 사전과제로 오픈 소스 최소 구현을 받았다. 그래서 구현해보며 느꼈던 점을 회고하며 기록한 게시글이다.
📦redux
┣ 📂js
┃ ┣ 📜createStore.js
┃ ┗ 📜main.js
┣ 📜index.html
┗ 📜readme.md
Redux의 createStore
파일을 최소 구현해보았다.
최소 구현이기에 에러 처리는 생략했다.
여기서 핵심 파일은 js/createStore.js
이다.
export default function createStore(counter) {
let currentState = counter();
let listeners = [];
function getState() {
return currentState;
}
function subscribe(listener) {
listeners.push(listener);
}
function dispatch(action) {
currentState = counter(currentState, action.type);
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i];
if (typeof listener === "function") listener();
}
return action;
}
const store = {
getState,
dispatch,
subscribe,
};
return store;
}
나는 함수형으로 작성하고 메서드로 사용할 수 있도록 구현했다.
getState()
는 현재 값을 가져온다.
let currentState = counter();
counter를 호출하여 현재 값을 반환받는데 이게 가능한 이유는 counter 함수에 있다.
function counter(state = 0, action) {
if (action === INCREMENT) return state + 1;
if (action === DECREMENT) return state - 1;
return state;
}
counter 함수의 기본값은 0이다. action 값이 없다면 마지막 코드인 return state
를 통해 현재 값을 반환한다. 따라서 getState를 호출했을 때 나오는 값은 현재 누적된 값이다.
function dispatch(action) {
currentState = counter(currentState, action.type);
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i];
if (typeof listener === "function") listener();
}
return action;
}
dispatch는 액션 값을 인자로 받는다. action 값은 counter 함수 내부에 if문으로 작성한 INCREMENT
,DECREMENT
값이다.
dispatch를 호출 할 때,
store.dispatch({type:INCREMENT})
으로 사용하면 된다.
값이 변경되었는지 감지하는 메서드이다. 나는 subscribe 함수가 dispatch와 연관되어 있다고 생각한다. 따라서 둘은 밀접한 관계가 있다.
store.subscribe(() => (value.innerText = store.getState()));
위와 같이 값이 변경되었다면 변경된 현재 값을 innerText에 넣어서 화면에 페인트하도록 코드를 작성했다. 이렇게 작성된 코드는 subscribe 함수에 인자로 넘어가게 된다.
let listeners = [];
...
function subscribe(listener) {
listeners.push(listener);
}
빈 배열을 선언하고 배열에 listener를 저장한다. 아까 작성했던 함수가 들어가는 것인데, 함수가 아니어도 괜찮다. subscribe은 저장만 하고 함수가 종료된다. 이후는 dispatch를 통해 실행되는데 아래를 보자.
function dispatch(action) {
currentState = counter(currentState, action.type);
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i];
if (typeof listener === "function") listener();
}
return action;
}
다시 dispatch 함수이다.
for 구문을 통해 배열을 순환하고 배열 안에 모든 요소를 순환하고 나면 종료된다. 내부에 선언된 지역변수는 현재 순환하고 있는 요소이고, 해당 요소가 함수라면 해당 함수는 즉시 실행된다.
따라서, 이벤트 리스너를 통해 플러스를 누르면, 디스패치를 통해
store.subscribe(() => (value.innerText = store.getState()));
해당 함수가 실행되는 것이다.
이 부분이 제일 어렵고 이해가 잘 가지 않았다. 지금 블로그를 작성하며 정리하니 조금은 이해가 되고 있다. 코드가 제일 어려운 점은 서로 얽히고 협력하는 부분이라고 느낀다. 그렇기에 매력적인 것이겠지.
이렇게 선택과제로 주셨던 redux
의 createStore
최소 구현하기가 끝이났다.
오픈 소스를 까보는 건 개발자로 전향한 뒤 처음이다. 하지 않았던 건 오픈 소스는 막연하게 어려울 것이라 생각했기 때문이다. 물론, 그건 지금도 변함없지만 적어도 두려움은 어느 정도 사라졌다. 어차피 까봐야 한다면...미리 매를 맞는 게.
적어도 강사님께서 덜 어렵고 이해가 쉬운 것으로 추천해주셔서 용기를 내보았던 거 같다. 과제도 해보는 김에...
그렇다고 이것 저것 까보면서 다니지는 않겠지만 내가 사용하는 라이브러리 정도는 까보며 공부하는 것도 괜찮을 것 같다.