React/NodeBird(ZeroCho)

saga 설치 & generator 이해하기

느리지만 꾸준하게 2021. 10. 28. 22:48

 

이전에 진행했던 thunk를 지우고 saga를 설치해주자.

npm rm redux-thunk

npm i redux-saga

 

그리고 createMiddleware를 import 해서 변수에 넣고 아래와 같이 넣어준다.

// reducers 폴더안에 configureStore.js파일 코드 일부분

import createSagaMiddleware from "redux-saga";


const configureStore = () => {
  const sagaMiddleware = createSagaMiddleware();
  const middlewares = [sagaMiddleware, loggerMiddleware];

 

sagamiddleware는 살짝 기능이 조금 더 있다. 아래 코드를 보자. rootsaga는 우리가 직접 작성을 해야한다. sagas라는 폴더안에다가 작성을 하자.

import rootSaga from "../sagas";

const configureStore = () => {
  const sagaMiddleware = createSagaMiddleware();
  const middlewares = [sagaMiddleware, loggerMiddleware];
  const enhancer =
    process.env.NODE_ENV === "production"
      ? compose(applyMiddleware(...middlewares))
      : composeWithDevTools(applyMiddleware(...middlewares));
  const store = createStore(reducer, enhancer);
  
  // 이부분 보자
  store.sagaTask = sagaMiddleware.run(rootSaga)
  return store;
};

function뒤에 *이 붙어있는데 뭘까 그냥 generator 문법자체가 이렇게 생겼다고 알자. saga도 활용방식은 대단히 다양하지만

대부분의 사람들은 자기만의 패턴을 하나 만들어서 그러한 패턴대로 계속해서 코딩을 하기 때문에 한번 팍 세워놓은 패턴에서 벗어날 일이 많이 없다.

 

generator부터 간단히 보자. generator도 함수인데 여기를 한번 보자. 특별한 역할을 하는 함수인데 gen라고 해서 function 뒤에 * 붙이고 시작한다. gen는 또 그냥 실행되는 것이 아니라 gen().next()라고 해야 실행이 된다.(값을 안넣고 시작했기에 undefined가 나오게 된다.)

이제 값을 할당하고 진행해보자. 그냥 generator(generator변수에다가 gen을 할당)고 쳐주면 suspended라고 나오고 next라고 하면 1을 yield하고 멈추게 된다. 계속해서 next를 하게되면 값을 계속 실행해주고 멈추게 된다.

아하 제너레이터는 yield가 있는 곳에서 멈추는구나!라고 알수가 있다. 즉, 중단점이 있는 함수!!

원래 자바스크립트 함수의 특성이 쭉 실행되는 것인데 함수를 실행했다는 것은 함수 제일 위에서 함수 제일 아래까지 전부다 실행되는데 generator는 안에 yield를 넣어주면 그 부분에서 멈춰버린다. yield 뒤에다가 숫자 4를 붙이면 그 값이 value: 형식으로 return이 될 수도 있다. 이러한 성질을 활용한게 saga이다. 즉 generator 자체는 막 엄청 치가떨리는 문법은 아니다...(function*, yield보면 그렇다..)

 

그냥 gen를 호출을 한번 해주고( const generator = gen() ) 계속해서 next next 해주고 done이 true가 될 때까지 해주면 함수를 중단해준다.

함수를 실행했는데 실행하다가 그냥 중간에 멈추고 싶으면 어떻게 해야할까? 일반함수로는 불가능하지만 generator을 쓰고 yield를 중간중간에 중단하고 싶은 점마다 많이 넣어놓으면 next 계속 호출하다가 중간에 멈추고 싶을 때 next를 더이상 호출 안하면 멈춰버릴 것이다. 그런식으로 함수를 중간에 멈출수가 있다.

 

그리고 saga에서는

절대 멈추지 않는 generator가 있는데 아래를 보자. while true는 무한인 금기시 코드는 무한 반복걸려서 프로그램이 멈춰버린다.

하지만 saga에서는 다르게 작동한다. yield가 중단점이니까 이 반복문이 무한 반복 되는 것이 아니라 매번 중단된다.

const gen = function*() {
    while (true) {
        yield '무한';
    }
}
// undefined

아래를 보면 함수를 실행했는데 무한 반복이 안되는 것을 볼 수 있다. 이것으로 무한의 개념을 표현할 수 있다.

const gen = function*() {
    while (true) {
        yield '무한';
    }
}
// undefined

const g = gen();
// undefined

g.next()
// {value: '무한', done: false}

 

다시 한번 보자. 이번에는 무한대신 i로

let i = 0;
const gen = function*() {
    while (true) {
        yield i++;
    }
}
// undefined
const g = gen();
// undefined

g.next()
// {value: 0, done: false}

g.next()
// {value: 1, done: false}

g.next()
// {value: 2, done: false}

g.next()
// {value: 3, done: false}

g.next()
// {value: 4, done: false}

g.next()
// {value: 5, done: false}

g.next()
// {value: 6, done: false}

g.next()
// {value: 7, done: false}

g.next()
// {value: 8, done: false}

g.next()
// {value: 9, done: false}

이 특성을 활용해서 eventListener같은 역할을 할 수도 있다.

무한 반복문 돌려놓고 g.next()를 호출할 때 그 안에 코드가 실행이 되는데 이것이 eventListener와 비슷하다.

eventListener은 click을 할 때 yield를 호출하는 것 그것처럼 g.next가 특정 event때 next를 하게되고 그때 yield i++ 이부분을 실행하게 하면 이게 eventListener와 똑같다고 볼 수 있다.

즉 click을 했을 때 g.next()를 호출하고 그러면 yield i++가 실행이 되는데 그게 바로 eventListener이다.

generator로 표현한 eventListener 이러한 성질을 saga가 활용한 것이다.

 

 

 

 

 

 

 

 

 

<출처 조현영: [리뉴얼] React로 NodeBird SNS 만들기>

https://www.inflearn.com/course/%EB%85%B8%EB%93%9C%EB%B2%84%EB%93%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%A6%AC%EB%89%B4%EC%96%BC/dashboard

 

[리뉴얼] React로 NodeBird SNS 만들기 - 인프런 | 강의

리액트 & 넥스트 & 리덕스 & 리덕스사가 & 익스프레스 스택으로 트위터와 유사한 SNS 서비스를 만들어봅니다. 끝으로 검색엔진 최적화 후 AWS에 배포합니다., 새로 만나는 제로초의 리액트 노드버

www.inflearn.com

 

'React > NodeBird(ZeroCho)' 카테고리의 다른 글

take 시리즈, throttle 알아보기  (0) 2021.10.29
saga 이펙트 알아보기  (0) 2021.10.29
redux-thunk 이해하기  (0) 2021.10.28
정규표현식 맛보기  (0) 2021.10.28
리덕스의 원리와 불변성  (0) 2021.10.26