[ASAC 웹풀스택] 비동기 Action 및 사이드 이펙트를 위한 라이브러리 Redux-Thunk, Redux-Saga 그리고 Toolkit
본문 바로가기

컴퓨터공부/ASAC 웹풀스택

[ASAC 웹풀스택] 비동기 Action 및 사이드 이펙트를 위한 라이브러리 Redux-Thunk, Redux-Saga 그리고 Toolkit

by Life & study 2023. 8. 27.
반응형

비동기 Action 및 사이드 이펙트를 위한 라이브러리 Redux-Thunk, Redux-Saga 그리고 Toolkit

 

참고사이트 : 용어집 | Redux

 

용어집 | Redux

이 문서는 Redux의 핵심 용어들을 그 타입 시그니처와 함께 모아둔 용어집입니다. 타입은 Flow notation에 따라 문서화되어 있습니다.

ko.redux.js.org

 

React

React – 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리 (reactjs.org)

 

React – 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

Redux
Redux - 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너. | Redux

 

Redux - 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너. | Redux

자바스크립트 앱을 위한 예측 가능한 상태 컨테이너.

ko.redux.js.org


Next.js

Next.js by Vercel - The React Framework (nextjs.org)

 

Next.js by Vercel - The React Framework

Next.js Boilerplate A Next.js app and a Serverless Function API. Image Gallery Starter An image gallery built on Next.js and Cloudinary. Next.js Commerce An all-in-one starter kit for high-performance e-commerce sites.

nextjs.org

 

 

[ASAC 웹풀스택] Redux 란 무엇인가?  , Store, Action, Reducer의 의미와 특징

Redux 자체에는 비동기 작업을 처리하는 기능이 없습니다. 

이를 위해 Redux-Thunk와 Redux-Saga와 같은 미들웨어가 필요하며, 각각은 다음과 같은 특징을 가지고 있습니다.

 

 

Redux는 자바스크립트 상태 관리 라이브러리입니다. 애플리케이션의 상태를 중앙화하고, "액션"이라는 이벤트를 통해 상태를 예측 가능한 방식으로 업데이트할 수 있게 해줍니다. Redux를 사용하면 애플리케이션의 일관성, 환경 호환성, 테스트 용이성 등을 향상시킬 수 있습니다

 

Store, Action, Reducer의 의미와 특징

 

 

[ASAC 웹풀스택] fetchthen 은 무엇인가?

 

fetch

 

fetch('/api/data') // '/api/data' URL로부터 리소스를 가져옴
  .then(response => response.json()) // 응답을 JSON 형식으로 파싱
  .then(data => console.log(data)) // 파싱된 데이터 로깅
  .catch(error => console.error('Error:', error)); // 오류 처리

 

then 메서드

 

는 Promise의 성공 결과 값을 처리합니다. 즉, 비동기 작업이 성공적으로 완료되면 그 결과 값을 가지고 무언가를 하고 싶을 때 then 메서드 안에 콜백 함수를 넣어 사용합니다.

javascript
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('성공!');
  }, 1000);
});


promise.then(value => console.log(value)); // '성공!' 출력


위 코드에서 setTimeout으로 인해 비동기적으로 동작하는 부분이 있습니다. 이 부분이 성공적으로 수행된 후에 어떤 작업을 수행하고 싶다면, 해당 작업은 then 메서드 내부에 위치해야 합니다.

 

 

 

[ASAC 웹풀스택]  Then then 메서드는 Promise의 성공 결과 값을 처리합니다.

 

 

Then then 메서드는 Promise의 성공 결과 값을 처리합니다.

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('성공!');
  }, 1000);
});

promise.then(value => console.log(value)); // '성공!' 출력

 

 

 

[ASAC 웹풀스택] Redux-Thunk Redux-Thunk 란 무엇인가? createStore,  applyMiddleware

 

Redux-Thunk Redux-Thunk

는 함수를 디스패치할 수 있게 해주는 Redux 미들웨어입니다. 이 함수 내부에서 비동기 작업을 처리한 후, 그 결과에 따라 다시 액션을 디스패치할 수 있습니다

 

 

createStore:

 이 함수는 Redux 애플리케이션의 스토어를 생성하는 데 사용됩니다. 스토어는 애플리케이션의 상태를 보유하고 관리하는 객체입니다. createStore 함수는 리듀서(reducer)라고 하는 특별한 함수를 인자로 받아 스토어를 생성합니다.

 


applyMiddleware: 

이 함수는 Redux 미들웨어를 스토어에 적용할 때 사용됩니다. 미들웨어는 액션이 디스패치되고 나서, 해당 액션이 리듀서에 의해 처리되기 전에 실행되는 커스텀 로직을 정의할 수 있게 해줍니다.

 

 

createStore with Middleware applyMiddleware

 함수를 사용하여 스토어 생성 시 logger 미들웨어를 적용하였습니다.

 이렇게 하면 모든 액션이 디스패치될 때마다 logger 미들웨어가 실행됩니다.

 


Dispatch Actions 

마지막으로, increment()와 decrement()라는 액션 크리에이터 함수를 호출하여 반환된 액션 객체를 디스패치하였습니다.

 


결과적으로, 각각의 액션이 디스패치될 때마다 'dispatching' 메시지와 함께 해당 액션 객체가 출력되고, 그 후 'next state' 메시지와 함께 업데이트된 상태가 출력됩니다.

즉, 이 코드의 목적은 Redux 스토어에서 발생하는 모든 변화를 추적하기 위한 것입니다. 이렇게 하면 어플리케이션의 상태 변화 과정을 보다 명확하게 이해할 수 있습니다.

 

 

작업진행순서,

action creator -> action -> dispatch -> Redux Thunk

 

Redux thunk에서 dispatch 된 액션이 함수인지 아닌지 판단한다.
Redux Thunk -> 함수인가? -> 아니요.(Plain Object) -> dispatch -> Reducer

Redux Thunk -> 함수인가? -> 예 -> 함수실행 -> dispatch -> 함수인가? -> 아니요(Plain Object) -> Reducer

 

 

[ASAC 웹풀스택] middleware란 무엇인가?

 

미들웨어는 dispatch 함수를 결합해서 새 dispatch 함수를 반환하는 고차함수이다.
이들은 비동기 action을 acion으로 전환한다. action을 로깅하거나, 라우팅과 같은 부수효과를 일으키거나,
비동기 API 호출을 일련의 동기 action으로 바꾸는데 유용하다.

 

 

 

 

[ASAC 웹풀스택] Redux-Thunk와 Redux-Saga 코드

 

Redux는 JavaScript 애플리케이션에서 상태를 관리하는 데 사용되는 오픈 소스 JavaScript 라이브러리입니다. 

그러나 Redux 자체에는 비동기 작업을 처리하는 기능이 없습니다. 이를 위해 Redux-Thunk와 Redux-Saga와 같은 미들웨어가 필요하며, 각각은 다음과 같은 특징을 가지고 있습니다.

Redux-Thunk Redux-Thunk는 함수를 디스패치할 수 있게 해주는 Redux 미들웨어입니다. 이 함수 내부에서 비동기 작업을 처리한 후, 그 결과에 따라 다시 액션을 디스패치할 수 있습니다.

 

Redux-Thunk Redux-Thunk는 간단한 비동기 작업에 적합합니다.

 

 


투표관련앱을 만든다면?

 


Redux-Thunk

 

// Action Types
const VOTE = 'VOTE';
const VOTE_SUCCESS = 'VOTE_SUCCESS';
const VOTE_ERROR = 'VOTE_ERROR';

// Action Creators
function vote() {
  return {
    type: VOTE,
  };
}

function voteSuccess(data) {
  return {
    type: VOTE_SUCCESS,
    payload: data,
  };
}

function voteError(error) {
  return {
    type: VOTE_ERROR,
    error,
  };
}

// Thunk Function
function submitVote(candidate) {
  // Thunk 함수는 dispatch와 getState를 인자로 가집니다.
  return (dispatch, getState) => { 
    dispatch(vote());

    // 비동기 작업을 수행합니다.
    fetch('/api/vote', { 
      method: 'POST',
      body: JSON.stringify({ candidate }),
    })
      .then(response => response.json())
      .then(data => dispatch(voteSuccess(data)))
      .catch(error => dispatch(voteError(error)));
  };
}

 

이 코드에서의 작업 흐름은 다음과 같습니다:

사용자 인터랙션: 사용자가 투표 버튼을 클릭하거나, 특정 후보를 선택하는 등의 인터랙션이 발생합니다.
액션 생성 및 디스패치: submitVote(candidate) 함수가 호출되며, 이 함수는 Thunk 함수입니다. 이 Thunk 함수는 내부에서 vote() 액션 크리에이터를 호출하여 반환된 액션 객체 { type: VOTE }를 디스패치합니다.
비동기 작업 시작: 그 다음으로, fetch API를 사용하여 서버에 비동기 요청을 보냅니다. 요청은 '/api/vote' 엔드포인트로 POST 메소드와 함께 선택된 후보 정보를 담아 보냅니다.
비동기 작업 응답 처리: 서버로부터 응답이 오면, 그 결과는 Promise 형태로 반환됩니다. 이 Promise는 then 메소드를 사용해 처리할 수 있습니다.
성공적인 응답: 서버로부터 받은 데이터를 파라미터로 하여 voteSuccess(data) 액션 크리에이터 함수가 호출됩니다. 그리고 반환된 액션 객체 { type: VOTE_SUCCESS, payload: data }가 디스패치됩니다.
오류 발생: 오류가 발생하면 catch 문으로 들어갑니다. 여기서 voteError(error) 액션 크리에이터 함수가 호출되며 반환된 액션 객체 { type: VOTE_ERROR, error } 가 디스패치됩니다.
상태 업데이트: 위에서 디스패치된 액션이 리듀서에 도착하면 리듀서는 해당 타입의 액션을 처리하여 새로운 상태를 생성하고 스토어에 저장합니다.
UI 갱신: 스토어의 상태 변경을 구독하고 있는 컴포넌트들이 새롭게 렌더링되어 화면상의 변경 사항을 반영합니다.
위 과정은 Redux와 Redux-Thunk 미들웨어를 함께 사용하는 경우의 일반적인 데이터 흐름입니다.

 


 

 

Redux-Saga Redux-Saga

는 좀 더 복잡한 비동기 로직을 처리하기에 적합합니다. 예를 들어, 특정 이벤트가 발생하면 여러 종류의 데이터 패칭 요청을 동시에 처리해야 할 때 유용합니다.

 

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

// Action Types
const FETCH_EVENTS = "FETCH_EVENTS";
const FETCH_EVENTS_SUCCESS = "FETCH_EVENTS_SUCCESS";
const FETCH_EVENTS_FAILURE = "FETCH_EVENTS_FAILURE";

// Saga (Generator Function)
function* fetchEventsSaga() {

   try{
     const response = yield call(fetch,'/api/events');
     const data = yield call([response,'json']);
     
     yield put({type : FETCH_EVENTS_SUCCESS , payload : data});
   
   } catch(e){
     yield put({type : FETCH_EVENTS_FAILURE , error : e.message});
   
   }
}

export default function* rootSaga() {
   yield takeEvery(FETCH_EVENTS , fetchEventsSaga);
}

 

 

 

 

반응형

댓글