솔미는 성장중

백엔드와 협업할 때 API를 못 받았다면? MSW mocking서버를 이용해보자! (feat. React & TypeScript) 본문

프로젝트

백엔드와 협업할 때 API를 못 받았다면? MSW mocking서버를 이용해보자! (feat. React & TypeScript)

solming 2023. 11. 30. 12:21
728x90

문제 상황

백엔드와 야놀자 기업 과제 프로젝트를 진행하게 되었다.

 

2주라는 짧은 프로젝트였기에 모든 과정이 빠르게 진행되어야 했다. \(〇_o)/

초반 ERD작업, API설계, 디자인 시안 제작, 기획 등 빠르게 진행되었다!


모든 것이 착착 진행되나 싶었으나 문제가 생겼다..

퍼블리싱을 다 끝냈는데도 불구하고 API를 만드는 작업은 아주 초반 단계였던 것이다.

그렇다고 손놓고 있을 수는 없겠다라는 생각에 붕 뜬 시간에 무엇을 할 수 있을지 알아보았다.

 

✨  그러다가 알게 된 MSW ! ✨

 

MSW 작동방식

1. 라이브러리를 설치하면 브라우저에 Service Worker을 등록한다. 
2. Service Worker는  브라우저에서 이루어지는 실제 네트워크 요청들을 가로채 복사해서 실제 서버가 아닌 클라이언트 사이드에 있는 MSW 라이브러리로 보낸다.

3. 그러면 등록된 핸들러를 통해 모의 응답(Mocked response)을 제공받을 수 있다. 제공받은 모의 응답은 브라우저에게 그대로 전달한다.

Mock Service Worker 다이어그램    https://mswjs.io/docs/#request-flow-diagram

 

 

출처

 

MSW(Mock Service Worker)로 더욱 생산적인 FE 개발하기

MSW(Mock Service Worker)는 Service Worker를 이용해 서버를 향한 실제 네트워크 요청을 가로채서(intercept) 모의 응답 (Mocked response)를 보내주는 API Mocking 라이브러리이다.

velog.io

 

터미널에서 설치

npm i -D msw
npx msw init public/ --save

 

 

public 폴더내에 생성된다.

 

 

/src/mocks 폴더 생성

해당 폴더내에 browsers.ts와 handlers.ts 파일 생성

// browsers.ts
import { setupWorker } from "msw/browser";
import { handlers } from "./handlers";

export const worker = setupWorker(...handlers);

 

// handlers.ts

import { http, HttpResponse } from "msw";
// 더미 데이터 불러오기
import accommodationDetail from "../../public/data/accommodationDetail.json";

// get 핸들러
const getHotelResolver = () => {
  return HttpResponse.json(accommodationDetail);
};
// post 핸들러
const postHotelResolver = async ({ request }: any) => {
  const newPost = await request.json();
  console.log("newPost", newPost);

  return HttpResponse.json(newPost, { status: 201 });
};

export const handlers = [
  //
  http.get("/accommodation", getHotelResolver),
  http.post("/accommodation", postHotelResolver),
];

 

msw가 업데이트되고, rest대신 http를 사용한다고 한다. (이거 공식문서도 찾기 어렵고, 구글링해도 안나와서 엄청 고생했다...) 

 

 

// main.tsx

import React from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import router from "./routes/router.tsx";
import { QueryClient, QueryClientProvider } from "react-query";
import { worker } from "./mocks/browsers.ts";
import { RecoilRoot } from "recoil";

const queryClient = new QueryClient(); //react-Query

if (process.env.NODE_ENV === "development") {
  worker.start();
}

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
      <QueryClientProvider client={queryClient}>
        <RouterProvider router={router} />
      </QueryClientProvider>
  </React.StrictMode>
);

 

React-query & axios를 사용할 거라 리액트 쿼리도 불러와 import 해주었다.

이제 세팅은 끝! 실제로 사용해보자.

 

get 사용 예제

  const fetchListData = async () => {
    try {
      const res = await axios.get(
        "../../../../public/data/accommodationDetail.json" //더미 데이터 경로
      );
      return res.data.data;
    } catch (error) {
      console.log("에러발생!!!!!!!!!", error);
      throw new Error("Failed to fetch data");
    }
  };

  const { data, error, isError, isLoading, refetch }: any = useQuery({
    queryKey: ["postDetail"],
    queryFn: fetchListData,
    staleTime: 500000,
  });
  if (isLoading) {
    return <div>로딩중..!!!!!</div>;
  }
  if (isError) {
    return <div>여기는 에러 페이지!!!!! {error.message}</div>;
  }

 

 

post 사용 예제

const postBasket: any = () => {
    try {
      const response = axios.post("../../../../public/data/accommodationDetail.json", {
        roomId: roomId,
        startDate: startDate,
        endDate: endDate,
        headCount: filterData.amount,
        orderPrice: totalPrice, //넣어줄 데이터
      });
      return response;
    } catch (error) {
      console.log("에러에러에러", error);
    }
  };

  const mutation = useMutation({
    mutationFn: postBasket,
    onSuccess: data => {
      console.log("데이터 전송 성공", data);
      showToast();
    },
    onError: error => {
      console.log("전송 실패했습니다!!", error);
    },
  });
  
   const onClickBasket = () => {
    mutation.mutate();
  };
  
  
// JSX element
<button
    className="room__buttons-container__basket"
    onClick={onClickBasket}
>

 

 

어떤 데이터를 어떤 이름으로 주고 받을지 API명세서를 잘 작성해두었다면 나중에 url부분만 수정하면 다른 코드는 그대로 쓸 수 있다!


시간을 단축하는 데에 아주 큰 도움이 되었다 :D 모킹 서버 짱!

 

728x90