본문 바로가기
  • 삽질하는 자의 블로그
메인-프로젝트/Next.js - 심리검사와 강아지 프로젝트

4. Redux-toolkit을 사용해 "비동기함수(fetch)" 를 이용한 DB 의 값 받아와서 넣기 + Thunk 생성자 + action.ts

by 이게뭐당가 2023. 1. 29.

클라이언트는 서버(api) 에게 요청을 하고, 서버(api) 는 DB의 값을 받아 응답한다.

 

좋다. 클라이언트는 그 값을 받을 수 있다.

 

문제는 매번, 필요할때마다, 모든 페이지에서 서버에게 요청해 그 값을 받아올 것인가?

 

아니면 받아놓고, 열심히 props 전달을 통해 그 값을 앱 전역에 퍼뜨릴 것인가?

 

둘다 정답은 아닐 것이다. 그것이 내가 전에 했던 크나큰 실수이자, 엄청나게 느려진 반응속도를 낳게한 주범이었다.

 

이번에는 서버로부터 응답받은 그 값을 Redux-toolkit 의 store 에 넣고, 앱 전역에서 사용할 것이다.

 

React 를 사용하면서 Redux-toolkit 의 action 생성자를 통해 비동기함수를 다루어보았다.

 

정확히는 비동기함수를 사용가능하게 하는 action 을 통해 FireBase 의 데이터를 클라이언트의 store 로 바로 받아왔다.

 

이번에도 별다를 것은 없다. 다만 요청하는 곳이 내가 만든 api 일 뿐이다.

 

기존의 React 와 Firebase(가짜 서버)를 이용했던 경우

 

action 생성자를 만들어 클라이언트에서 Firebase 로 직접 요청했다.

 

이번에는 api 로 요청을 보내고 api 가 DB의 값을 응답할것이다.

 

저번시간까지 api 를 만들었다. 이번에는 Redux-toolkit 을 다룰것이다.

 

 

1. Redux-toolkit 의 설치

https://redux-toolkit.js.org/introduction/getting-started

 

Getting Started | Redux Toolkit

 

redux-toolkit.js.org

npm install @reduxjs/toolkit

 

 

2. slice 를 만든다.

 

<store / sample-slice.ts>

    import { createSlice, PayloadAction } from "@reduxjs/toolkit";

    export interface SampleType {
      _id: string;
      message: string;
    }

    const initialState: { sample: SampleType[] } = { sample: [] };

    const sampleSlice = createSlice({
      name: "sample",
      initialState,
      reducers: {
        showSample(state) {
          console.log(state.sample);
        },
        getSample(state, action: PayloadAction<SampleType[]>) {
          state.sample = action.payload;
        },
      },
    });

    export const sampleAction = sampleSlice.actions;

    export default sampleSlice.reducer;

 

 

3. index store 를 만든다.

 

< store / index.ts >

    import { configureStore } from "@reduxjs/toolkit";
    import sampleSlice from "./sample-slice";

    export const store = configureStore({ reducer: { sample: sampleSlice } });

    export type RootState = ReturnType<typeof store.getState>;
    export type AppDispatch = typeof store.dispatch;

 

 

4. Provider 를 통해 전역에 공급한다.

 

< pages / _app.tsx >

    import type { AppProps } from "next/app";
    import { SessionProvider } from "next-auth/react";
    import "../styles/globals.scss";
    import { Provider } from "react-redux";		// Provider
    import { store } from "@/store";			// store

    export default function App({ Component, pageProps }: AppProps) {
        return (
            <SessionProvider session={pageProps.session}>
              <Provider store={store}>
                <Component {...pageProps} />
              </Provider>
            </SessionProvider>
        );
    }

 

 

5. redux-toolkit 에서 비동기함수를 처리할 action 을 만든다.

 

< store / sample-action.ts >

    import { Dispatch } from "@reduxjs/toolkit";	// dispatch 타입
    import { sampleAction } from "./sample-slice";	// store 에 저장해야하므로 저장하는 action 가져오고
    import { useDispatch } from "react-redux";		// 사전정의 dispatch 를 사용할것이니 미리 불러오고
    import type { AppDispatch } from "./index";		// 미리 index 에서 정의한 dispatch 타입을 가져온다.

    export const sendRequest = () => {			// 비동기함수 처리할 "일반함수" 생성(Hook 이 아니다)
      return async (dispatch: Dispatch) => {		// 반환은 dispatch 하는 함수의 결과물
        
        const getData = async () => {			// 해당 함수를 정의한다.
          const response = await fetch("/api/getSample");	// 해당 함수는 서버에 요쳥하고
          const responseData = await response.json();

          return responseData;				// 그 값을 반환하는 함수로
        };

        const sampleData = await getData();		// 그 값을 sampleData 에 저장하고

        dispatch(sampleAction.getSample(sampleData));	// dispatch 하여 store 에 저장하는 것이 최종
      };
    };

    export const useAppDispatch: () => AppDispatch = useDispatch;

 

 

6. 클라이언트에서 사용한다.

 

< pages / index.tsx >

    import Head from "next/head";
    import Link from "next/link";
    import { useSelector } from "react-redux";
    import { RootState } from "@/store";
    import { useEffect } from "react";
    import { useAppDispatch, sendRequest } from "@/store/sample-action";	// useAppDispatch 를 사용한다

    export default function Home() {
      const sample = useSelector((state: RootState) => state.sample);
      const dispatch = useAppDispatch();

      useEffect(() => {
        dispatch(sendRequest());	// dispatch 안에는 action 에서 정의한 일반함수가 들어간다.
      }, []);

      console.log(sample);

      return (

 

 

이로써 DB 의 값을 가져오는 api 를 통해,

해당 api 로 값을 요청하고 응답받아와 store 에 저장하는 기본 시스템이 완성되었다.

댓글