프론트엔드에서 모의 서버 만들기

김석진·2023년 5월 27일
65
post-thumbnail
post-custom-banner

MSW란?

MSW는 Mock Service Worker에 줄임말로써 Service Worker를 사용하여 네트워크 요청을 가로채서 요청에 대한 모킹을 해줄 수 있는 라이브러리이다

사용 이유

여러 이유가 있겠지만 백엔드와 프론트엔드에 개발 속도 차이 떄문에 사용하게 되었다. 프론트엔드는 API가 나오지 않으면 데이터 처리를 못한다 즉 백엔드 개발이 되어야 프론트엔드는 개발을 진행할수있다 하지만 프로젝트를 진행 할 때 API가 나오기 까지의 대기시간이 있었고 이 대기 시간을 줄이기위해 MSW를 사용하였다

MSW 동작 방식

여러 이유가 있겠지만 백엔드와 프론트엔드에 개발 속도 차이 때문에 사용하게 되었다. 프론트엔드는 API가 나오지 않으면 데이터 처리를 못한다 즉 백엔드 개발이 되어야 프론트엔드는 개발을 진행할 수 있다 하지만 프로젝트를 진행할 때 API가 나오기까지의 대기시간이 있었고 이 대기 시간을 줄이기 위해 MSW를 사용하였다

서비스 워커는 브라우저에서만 사용 가능하기 때문에 노드 환경에서는 node-request-interceptor로 처리하고 네이티브에서는 http, https, XMLHttpRequest로 모듈을 확장하여 리퀘스트를 처리한다

설치 및 기본 세팅

우선 MSW 라이브러리를 설치해보자

yarn add msw --dev

브라우저에서 MSW를 사용하기 위해서는 서비스 워커에 등록하는 과정이 필요하다
그러므로 커맨드를 통해 브라우저에 서비스 워커에 등록할 것이다

npx msw init public/ --save

public 폴더에 mockServiceWorker가 생겼다면 성공적으로 생성된 것이다

브라우저 환경

mocks/browser.ts

import { setupWorker } from "msw";
import { handlers } from "./handlers";

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

노드 환경

mocks/server.ts

import { setupServer } from "msw/node";
import { handlers } from "./handlers";

export const server = setupServer(...handlers);

MSW 실행하기

mocks/index.ts

const initMockAPI = async (): Promise<void> => {
  if (typeof window === "undefined") {
    const { server } = await import("@/mocks/server");
    server.listen();
  } else {
    const { worker } = await import("@/mocks/browser");
    worker.start();
  }
};

export default initMockAPI;

src/app/page.tsx

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

env를 통해 development 환경이면 MSW를 실행 주도록 설정해 준다

console에 Mocking enabled가 찍혀있다면 MSW가 성공적으로 실행된 것이다

handler 작성하기

import { rest } from "msw";

export const MOCK_API_BASE_URL = "http://localhost:3000";

const MainNoticeListData = [
  {
    id: 1,
    title: "테스트입니다",
  },
  {
    id: 2,
    title: "테스트입니다",
  },
  {
    id: 3,
    title: "테스트입니다",
  },
];

export const handlers = [
  rest.get(`${MOCK_API_BASE_URL}/main/notice/list`, (req, res, ctx) => {
    return res(ctx.status(200), ctx.json(MainNoticeListData));
  })
];

get method 작성하였다 http://localhost:3000/test를 get method로 성공적으로 연결이 되었다면 TestData 더미 데이터를 넘겨주어야 한다

axios와 react query 사용하여 연결해보기

const mainNoticeList = async () => {
  const { data } = await axios.get(`${MOCK_API_BASE_URL}/main/notice/list`);
  return data;
};

export const useMainNoticeListQuery = () => {
  const { data } = useQuery<MainNoticeListType[]>([KEY.MAIN_NOTICE_LIST], () =>
    mainNoticeList()
  );
  return { data: data || [] };
};

성공적으로 연결이 되었다면 console에 아래와 같이 뜰 것이다

구현 화면

MSW를 효율적으로 사용하려면?

MSW를 효율적으로 사용하려면 백엔드와의 소통이 정말 중요한 것 같다 결론적으로 아직 나오지 않은 API를 미리 연결해 보는 작업이기 때문에 나중에 API가 만들어졌을 때 URL만 바꾸면 바로 연결할 수 있도록 해야 한다 그러기 위해서는 백엔드와 데이터를 어떤 식으로 어떻게 보내줄 건지 미리 소통이 되어야 한다

참고한 자료

https://blog.mathpresso.com/msw%EB%A1%9C-api-%EB%AA%A8%ED%82%B9%ED%95%98%EA%B8%B0-2d8a803c3d5c
https://tech.kakao.com/2021/09/29/mocking-fe/
https://velog.io/@khy226/msw%EB%A1%9C-%EB%AA%A8%EC%9D%98-%EC%84%9C%EB%B2%84-%EB%A7%8C%EB%93%A4%EA%B8%B0

profile
해탈의 경지에 이르자
post-custom-banner

6개의 댓글

comment-user-thumbnail
2023년 5월 27일

좋은글이네요~ 잘보고갑니당

1개의 답글
comment-user-thumbnail
2023년 6월 1일

wow! 프론트엔드에서 서버를 구현하다니!

답글 달기
comment-user-thumbnail
2023년 6월 1일

이런게 있는 줄 처음 알았네요 ㄷㄷ 좋은 거 배워가네요

답글 달기
comment-user-thumbnail
2023년 6월 2일

김석진.

답글 달기
comment-user-thumbnail
2023년 6월 6일

하트가 무려 47개 ㅎㄷㄷ 하네요 석가모니 개발자님

답글 달기