본문 바로가기
Next.js

React에서 Redux, Reducer, 그리고 Redux-Saga를 활용한 상태 관리(Redux-DevTools)

by code2772 2024. 7. 28.

[ 목차 ]

    728x90
    반응형

    리액트 애플리케이션을 개발하다 보면 상태 관리가 복잡해지는 경우가 많습니다. 이런 상황에서 상태 관리를 보다 체계적으로 관리하기 위해 Redux를 사용할 수 있습니다. 또한, 비동기 작업을 효율적으로 처리하기 위해 Redux-Saga를 활용할 수 있습니다. 이번 글에서는 리덕스(Redux), 리듀서(Reducer), 사가(Saga)에 대해 자세히 알아보겠습니다.

     

     

    1. Redux란?

    Redux는 애플리케이션의 상태를 중앙에서 관리하는 라이브러리입니다. Redux는 상태를 예측 가능하게 관리하며, 다양한 컴포넌트 간에 데이터를 쉽게 공유할 수 있도록 돕습니다.

    Redux의 주요 개념은 다음과 같습니다:

    • 스토어(Store): 애플리케이션의 상태를 담고 있는 객체입니다.
    • 액션(Action): 상태에 변화를 일으키는 객체입니다. 액션은 타입(type)과 페이로드(payload)를 가집니다.
    • 리듀서(Reducer): 현재 상태와 액션을 받아 새로운 상태를 반환하는 순수 함수입니다.
    • 디스패치(Dispatch): 액션을 스토어에 전달하는 함수입니다.
    dispatch는 Redux에서 액션을 발생시키는 함수입니다. 액션은 상태 변경을 위한 지시사항이라고 볼 수 있습니다. 위 코드에서는 직접적으로 보이지 않지만, 컴포넌트에서 다음과 같이 사용될 것입니다:

     

    dispatch(fetchCallbacksRequest({ page: 1, size: 20 }));

     

    2. 리듀서(Reducer)란?

    리듀서는 Redux에서 상태 변화를 처리하는 순수 함수입니다. 현재 상태와 액션을 받아서 새로운 상태를 반환합니다.

    아래는 createSlice를 사용한 리듀서 예제입니다:

     

    // 콜백 상태를 위한 인터페이스 정의
    interface CallbackState {
      isCallbackLoading: boolean;  // 콜백 데이터 로딩 중 여부
      isCallbackSuccess: boolean;  // 콜백 데이터 로드 성공 여부
      isCallbackError: boolean;    // 콜백 데이터 로드 실패 여부
      isDeletingCallback: boolean; // 콜백 삭제 중 여부
                    /*
                    생략
                    */
      };
    }
    
    // 초기 상태 정의
    const initialState: CallbackState = {
      // ... (초기값 설정)
    };
    
    // 콜백 관련 리듀서 정의
    const callbackSlice = createSlice({
      name: "callback",
      initialState,
      reducers: {
        // 콜백 데이터 요청 액션
        fetchCallbacksRequest: (state, action: PayloadAction<{ page: number, size: number }>) => {
          state.isCallbackLoading = true;
          // ... (상태 업데이트)
        },
        // 콜백 데이터 요청 성공 액션
        fetchCallbacksSuccess: (state, action: PayloadAction<any>) => {
          state.isCallbackLoading = false;
          state.callbackData = action.payload;
          // ... (상태 업데이트)
        },
        // 콜백 데이터 요청 실패 액션
        fetchCallbacksError: (state, action: PayloadAction<string>) => {
          state.isCallbackLoading = false;
          state.error = action.payload;
          // ... (상태 업데이트)
        },
        // 콜백 상태 초기화 액션
        resetCallbackState: (state) => {
          // ... (상태 초기화)
        },
        // 콜백 삭제 요청 액션
        deleteCallbackRequest: (state, action: PayloadAction<any[]>) => {
          state.isDeletingCallback = true;
          // ... (상태 업데이트)
        },
        // 콜백 삭제 성공 액션
        deleteCallbackSuccess: (state) => {
          state.isDeletingCallback = false;
          // ... (상태 업데이트)
        },
        // 콜백 삭제 실패 액션
        deleteCallbackError: (state, action: PayloadAction<string>) => {
          state.isDeletingCallback = false;
          state.deleteCallbackError = action.payload;
        },
      },
    });
    
    // 액션 생성자 내보내기
    export const { 
      fetchCallbacksRequest, 
      fetchCallbacksSuccess, 
      fetchCallbacksError,
      resetCallbackState,
      deleteCallbackError,
      deleteCallbackRequest,
      deleteCallbackSuccess
    } = callbackSlice.actions;

     

    위 코드에서 callbackSlice는 상태와 액션을 정의하고, 리듀서 함수를 자동으로 생성합니다. 각 액션에 대응하는 상태 변화를 관리합니다.


    3. Redux-Saga란?

    Redux-Saga는 Redux 애플리케이션에서 비동기 작업을 처리하기 위한 미들웨어입니다. Redux-Saga는 제너레이터 함수를 사용하여 비동기 작업을 효율적으로 관리할 수 있게 해줍니다.

    Saga의 주요 개념은 다음과 같습니다:

    • 사가(Saga): 제너레이터 함수로 작성된 비동기 작업 처리 함수입니다.
    • 이펙트(Effect): 사가 내부에서 발생하는 비동기 작업입니다. 예를 들어 call, put 등이 있습니다.
    • takeEvery: 특정 액션 타입에 대해 모든 액션을 처리합니다.
    • takeLatest: 특정 액션 타입에 대해 마지막 액션만 처리합니다.

    아래는 Redux-Saga의 예제입니다:

     

    import { call, put, takeLatest } from 'redux-saga/effects';
    import { 
      fetchCallbacksRequest, 
      fetchCallbacksSuccess, 
      fetchCallbacksError, 
      deleteCallbackError, 
      deleteCallbackRequest, 
      deleteCallbackSuccess 
    } from '../reducers/callback';
    import api from './axiosInstance';
    
    // 콜백 데이터를 가져오는 API 호출 함수
    const fetchCallbacksAPI = (page: number, size: number) => {
      return api.get(`/user/callback?page=${page}&size=${size}`);
    }
    
    // fetchCallbacksRequest 액션에 대응하는 사가 함수
    function* handleFetchCallbacks(action: ReturnType<typeof fetchCallbacksRequest>) {
      try {
        const { page, size } = action.payload;
        console.log('Fetching callbacks...', { page, size });
        const result = yield call(fetchCallbacksAPI, page, size); // API 호출
        console.log('API response:', result);
        yield put(fetchCallbacksSuccess(result.data)); // 성공 액션 디스패치
      } catch (error) {
        console.error('Error fetching callbacks:', error);
        yield put(fetchCallbacksError(error.response?.data?.message || 'An error occurred while fetching callbacks')); // 실패 액션 디스패치
      }
    }
    
    // 콜백 데이터를 삭제하는 API 호출 함수
    const deleteCallbacksAPI = (callbackIds: any[]) => {
      return api.post('/user/callback/delete', callbackIds);
    }
    
    // deleteCallbackRequest 액션에 대응하는 사가 함수
    function* handleDeleteCallbacks(action: ReturnType<typeof deleteCallbackRequest>) {
      try {
        yield call(deleteCallbacksAPI, action.payload); // API 호출
        yield put(deleteCallbackSuccess()); // 성공 액션 디스패치
        // 삭제 후 목록 새로고침
        yield put(fetchCallbacksRequest({ page: 0, size: 20 }));
      } catch (error) {
        yield put(deleteCallbackError(error.response?.data?.message || 'An error occurred while deleting callbacks')); // 실패 액션 디스패치
      }
    }
    
    // 루트 사가
    export default function* callbackSaga() {
      yield takeLatest(fetchCallbacksRequest.type, handleFetchCallbacks); // 최신 fetchCallbacksRequest 액션만 처리
      yield takeLatest(deleteCallbackRequest.type, handleDeleteCallbacks); // 최신 deleteCallbackRequest 액션만 처리
    }

     

    위 코드에서 handleFetchCallbacks와 handleDeleteCallbacks 사가는 비동기 작업(API 호출)을 처리합니다. takeLatest를 사용하여 최신 액션만 처리하도록 설정했습니다.


    4. Redux와 Saga의 통합

    리덕스와 사가를 통합하여 사용하려면 redux-saga 미들웨어를 설정해야 합니다. 기본적인 설정 과정은 다음과 같습니다:

     

    import { configureStore } from '@reduxjs/toolkit';
    import createSagaMiddleware from 'redux-saga';
    import callbackReducer from './reducers/callback';
    import callbackSaga from './sagas/callback';
    
    // 사가 미들웨어 생성
    const sagaMiddleware = createSagaMiddleware();
    
    // 스토어 설정
    const store = configureStore({
      reducer: {
        callback: callbackReducer, // 콜백 리듀서 등록
      },
      middleware: [sagaMiddleware], // 사가 미들웨어 적용
    });
    
    // 사가 실행
    sagaMiddleware.run(callbackSaga);
    
    export default store;

     

    위 코드에서 configureStore를 사용하여 스토어를 설정하고, createSagaMiddleware로 사가 미들웨어를 생성하여 스토어에 적용합니다. 그런 다음 sagaMiddleware.run을 호출하여 루트 사가를 실행합니다.


    이렇게 Redux와 Redux-Saga를 사용하여 React 애플리케이션에서 상태 관리와 비동기 작업을 효율적으로 처리할 수 있습니다. 이를 통해 코드의 가독성과 유지보수성을 높이고, 애플리케이션의 상태를 보다 체계적으로 관리할 수 있습니다.

     

    Redux DevTools

     Redux 애플리케이션의 상태를 모니터링하고 디버깅하기 위한 도구입니다. Redux는 애플리케이션 상태를 예측 가능하게 관리하기 위한 상태 관리 라이브러리이며, Redux DevTools는 이를 더 효과적으로 사용하고 디버깅하는 데 도움을 줍니다

     

     

    상태를 한번에 확인이 가능하며 

     

     

    어떤 것들을 작성했는지도 한번에 알 수 있는 편리한 도구이다.

    반응형