ReactJS

ReactJS - Redux-Saga

PHM 2022. 7. 15. 10:28

리덕스의 사이클

- 비동기적인 것들은 어떻게 해결할 것인가?

    → Middleware

 

Middleware

1. Redux-thunk

    ㆍ추적이 힘들고, 테스트가 어렵다

    ㆍ패턴을 직접 만들어야하고 , 직접 지켜야한다

    ㆍAction creator의 반환이 Action object가 아니다.

 

2. Redux-saga

    ㆍ관리하기 쉽고, 테스트가 쉽다

    ㆍ적당한 패턴으로 서비스로직을 쉽게 만들 수 있다

    ㆍAction creator의 반환은 Action object


Redux-saga

Concept

1. side effect ( 부수 효과 )

- 비동기 요청, 브라우저 캐시, 로컬 스토리지

- (자바스크립트) 코드가 외부 세계에 영향을 주거나 받는 것

2. Generator

- Runner는 generator를 받을 수도 있고, generator를 직접 호출할 수 있다

EX1

import { put, takeEvery, delay } from 'redux-saga/effects'

export default function* rootSaga() {
    yield takeEvery('INCREMENT_ASYNC', incrementAsync )
}

export function* incrementAsync() {
    yield delay(1000)
    yield put({ type: 'INCREMNET' })
}

- INCREMNET_ASYNC 액션이 발생하면

- incrementAsync 함수 실행 ( 1초를 기다리고 INCREMENT 액션 Dispatch )

 

- Effect는 미드웨어에 의해 수행되는 명령을 담고 있는 평범한 자바스크립트 객체라고 생각

- Saga는 Effect를 yield하고, Middleware는 Effect를 처리한다.

EX2

function* fetchSaga() {
    const result = yield call(api.fetchA, arg1, arg2)
    
    console.log(result)
}

- call은 async-await의 await같은 역할을 한다.

 

Effect를 yield하면, Middleware에서 처리가 끝날때까지 기다려야 할까? ㄴㄴ

- Blocking 작업이 끝날 때까지 기다려주지만, Non-blocking은 작업이 끝날 때까지 기다려주지는 않는다.

 

- fork : 다른 saga를 전달( 다른 공간에서 실행될것 )


Orchestration

( 주로 자동화 개념? )

1. " takeLastest " Effect

- 어떤 작업의 요청이 들어왔을 때 앞선 요청이 끝나지 않았다면 전부다 취소

-  마지막에 들어온 작업만 완료를 시키겠다.

 

2. 파일업로드 시 Progress 

- channel 사용

( → 웹소켓 공부이후에 볼 것... )

 


redux-saga의 헬퍼함수

1. delay

- 설정된 시간 이후에 resolve를 하는 Promise 객체를 리턴

2. put

- 특정 액션을 dispatch 한다 ( ex: put({type: 'INCREMENT'}) )

3. call

- 주어진 함수를 실행한다 ( ex: call( delay, 1000 ) )

- 미들웨어가 Promise의 resolve를 기다리게 하기 때문에 동기함수 ( 주로 api 호출 )에 사용

4. take

- 들어오는 특정 액션을 처리한다. 한번 실행되고 이벤트가 삭제

5. takeEvery

- 모든 리퀘스트에 대해 take를 실행

function* watchFetchData() {
    yield takeEvery('FETCH_REQUESTED', fetchData)
}

- 만약 fetchData task가 시작되었을때 이미 이전 task가 실행중이라면, 이전 task는 자동으로 취소

6. fork

- 백그라운드에서 task가 실행

- 나중에 다시 볼 것! ( 두번째 참고자료 )

7. cancel

- fork된 task를 취소 시킨다 ( ex: yield cancel(task) )

- 제너레이터를 finally 구간으로 가게한다. 이때 취소한 task하위에 다른 task가 포함되어 있다면 모두 취소

8. all

- 이 함수를 사용해서 제너레이터 함수를 배열의 형태로 넣어주면, 제너레이터 함수들이 병행적으로 동시에 실행되고, 전부 resolve 될 때까지 기다린다.( Promise.all 과 비슷하다 )

 

 

 

 

참조 :

1. https://www.youtube.com/watch?v=UxpREAHZ7Ck

2. https://leego.tistory.com/entry/Redux-saga%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90#-%EF%B-%-F%E-%--%A-%--callback%--%ED%--%A-%EC%--%--%EB%A-%BC%--action%--payload%EB%A-%-C%--%EB%--%--%EA%B-%B-%--%EC%--%--%--%EC%-E%--%EB%-B%A--

3.  https://react.vlpt.us/redux-middleware/10-redux-saga.html

 

 

추가 공부 자료 :

1.https://blog.nerdfactory.ai/2021/01/02/setting-redux-saga.html

2. https://github.com/velopert/ts-react-redux-tutorial

3. https://github.com/piotrwitek/typesafe-actions#1-basic-actions

4. https://redux-saga.js.org/docs/introduction/GettingStarted/