우아한 테크 러닝 3기 세미나 내용 정리 part.4🙌🙌
middleware 알아보기
미들웨어
// index.js 구조
import {createStore} from "./redux"
function reducer(state= {counter : 0}, aaction) {
switch(action.type ) {
case "increment" :
return {
...state,
counter : state.counter +1 ,
}
defualt:
return {...state}
}
}
// store에 reducer함수를 넣어준다.
const store = createStore(reducer)
// 스토어의 변경사항을 구독(subscribe) 하면 변경사항을 꺼내가서 고쳐줌
store.subscribe(() => {
console.log(store.getState());
})
store.dispatch( {
type : "increment"})
middleware는 동기적으로 작동 되게 되어있음(비동기 액션을 동기처럼 보이게 하는거라고 볼 수 있다.)
reducer는 순수함수 여야 한다(외부와 아무런 dependency없이 작동하게끔 해야 함)
순수하지 않은 작업 == 결과가 항상 일치하지 않은 작업 (ex. 비동기 API 호출)
function api (url) {
return {};} // 이건 동기적
function api (url,cb) {
setTimeout(()=>{cb()},2000}
function reducer(state= {counter : 0}, aaction) {
switch(action.type ) {
case "increment" :
return {
...state,
counter : state.counter +1 ,
}
defualt:
return {...state}
}
}
//case 문 안에서 스토어의 상태 업데이트는 불가능하다
const store = createStore()
그럼 비동기 처리는 어떻게 해주어야 할까?💁
middleware에서 처리하는 것
const myMiddleware = store => dispatch => action {
dispatch(action};
//지연호출에 대한 개념을 알기 위해서
//리덕스 공식문서를 더 참고해볼것!👆🆗
function your middleware(Store) {}
return function (dispatch) {
return funtion(Action) {
dispatch(action)
}}
//클로져라는 background가 있어서 실행이 가능한 것
function ourMiddleware(store,dispatch,action) {
dispatch(action); //
}
인자 두개를 함수 두개로 쪼개는 것을 '커링'이라고 부른다
둘다 실행 함수는 같지만 다른점은 인자의 갯수 차이이다.
myMiddleware를 실행하면
console.log("lob=> "inc");
mymiddleware(store)(store.dispatch)({type : "increment"})
ourmiddleware(store,store.dispatch, {type : "increment"})
함수로 감싸는 기법(dispatch와 log를 묶는 기법)
function dissspatchAndLog(store, action) {
console.log("dispatching" , action)
store.dispatch(Action);
console.log("next state", store.getState())}```
// 디스패치 몽키패칭 실행중인 런타임에서 바꾸어 주는 기법
let next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log("dispatching", action)
let result = next(action)
console.log("next state", store.getState());
return result;
};
이런 구조가 좋게 느껴지지 않는 이유는 하드코딩 이기 때문인데, 맥락으로 풀어보면 함수가 함수를 부르는 이 구조가 핵심이다.
function patchStoreToAddLogging(store) {
const next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
const add1 = function(a,b) {
return a+b
const add2 = function (a) {
return function (b) {
return a+b}}
add1(0,20)
add2(10)(20)
const addTen = add2(10)
addTen(20);
addTen(120);
사용자에게 인자와 인자 사이에 개입할 여지를 주는 것 (몽키패칭 숨기기)
미들웨어는 실제로는 첫번째 미들웨어는 사실상 두번째 미들웨어 데이터가 순차적으로 흘러간다.
그래서 next
라고 하는건 다음 미들웨어 실행해 라는 의미이다
function logger(store) {
return function wrapDispatchToAddLogging(next) {
return function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
}
최종적으로 쓰는 것은
middlewares = Array.from(middlewares).reverse();
//순서를 역전시켜서 원하는 순서를 보장
let lastDispath = store.dispatch
const mymd = store => next => acttion => {
next(action};}
middlewares.forEach(middleware => {lastDispach = middleware(store)(lastDispatch)});
//store and next is called and caugth in closer