[MSW] Mock Service Worker

hyo·2023년 1월 27일
0
post-thumbnail

MSW(Mock Service Worker)

시작하며!

전에 프로젝트를 할때 팀원이 MSW를 쓰자하여 따라해보긴 했었다.
MSW를 써보니 express로 Mock 서버를 만드는것보다 간단하고 편리했다.
그래서 이번 사이드프로젝트를 하며 MSW를 써보기로 하였다.

MSW란?

MSW는 서비스 워커(Service Worker)를 사용하여 네트워크 호출을 가로채는 API 모킹(mocking) 라이브러리이다.
즉, 브라우저에서 마치 백엔드 API인 척하여 프론트엔드의 요청에 가짜 데이터를 응답해주는 녀석이다.

MSW를 쓰게된 이유!

백엔드 API 개발과 프론트엔드 개발이 동시에 진행돼야하는데, 백엔드 API 구현이 완료전까지 프론트엔드에서 데이터요청을 Mock 데이터를 활용하여 MSW로 가짜 응답을 받아가며 테스트를 해보기 위함이다!
그리고 무엇보다 써보고 싶었다.

MSW 적용해보기

브라우저 Request flow diagram

1. 브라우저에서 요청을 보내면
2. 서비스워커가 받아
3. 요청을 클론하여
4. MSW로 보내고
5. 모킹한값(응답)을 다시 서비스워커로 보내고
6. 서비스워커는 전달 받은 응답을 브라우저로 보내준다.

서비스워커는 브라우저 환경이 아닌곳에서는 동작하지 않음!
노드에서는 노드서버 방식을 사용한다.

설치 및 세팅

npm install msw --save-dev

msw를 먼저 설치 해준 뒤 ->

public 폴더에 mockServiceWorker 파일을 생성해주는 명령어까지 실행!

npx msw init public/ --save

  • mockServiceWorker 파일을 생성해야만 작동한다.
    위 명령어를 실행하면 /public/mockServiceWorker.js 란 파일이 생기고 이 파일이 대신 서비스 워커에 mock 서버를 등록 시켜준다.
    --save 플래그를 붙이면 package.json 에 디렉토리가 등록되고 msw 를 업데이트 할 때 자동으로 해당 코드가 업데이트 된다 함

이번프로젝트는 Next.js + typescript를 적용시킨 프로젝트이다.

app.tsx

//worker를 실행 시켜주는 코드 추가

if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') {
  import('../mocks');
}

.env

  • NEXT_PUBLIC_API_MOCKING 라는 환경변수를 사용하게 되는데 이 환경변수에 따라 mock 서버를 사용 할지를 결정하기 때문에 .env 파일같은 환경변수 파일에 해당 환경변수를 추가해 준다.
    따라서 필요한 환경에서만 사용할 수 있게 됨
NEXT_PUBLIC_API_MOCKING=enabled

mocks

mocks 폴더 아래에 파일들을 세팅한다.

  1. handlers.ts
  2. index.ts
  3. server.ts
  4. browser.ts

mocks/browser.ts

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

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

mocks/handlers.ts

아래 handlers.ts에는 내가 현재 사용중인 api 모킹 코드를 써보았다.

import {rest} from 'msw';

interface UserInfo {
  email?: string;
  password?: string;
  nickname?: string;
}
  
export const handlers = [
  rest.get<UserInfo>('/api/members', (req, res, ctx) => {
    const searchParam = new URLSearchParams(req.url.searchParams);
    const email = searchParam.get('email');
    const existEmail = MockUsers.find((el) => {
      return email === el.email;
    });
    if (email && existEmail) {
      return res(
        ctx.delay(),
        ctx.status(400),
        ctx.json('중복된 이메일 입니다.'),
      );
    } else if (email && !existEmail) {
      return res(
        ctx.delay(),
        ctx.status(200),
        ctx.json('사용가능한 이메일 입니다.'),
      );
    } else {
      return res(ctx.delay(), ctx.status(200), ctx.json('아무것도 안씀!'));
    }
  }),
]

mocks/index.ts

  • 서버에서 부르는지 웹 브라우저에서 부르는지 확인하여 임포트 함
    강제로 module 로 만들기 위해 비어있는 export {} 를 사용함
if (typeof window === 'undefined') {
  const { server } = require('./server');
  server.listen();
} else {
  const { worker } = require('./browser');
  worker.start();
}
export {};

mocks/server.ts

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

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

이렇게 설치 & 세팅해두고 handlers.ts에 쓰고 싶은 모킹 코드를 써가며 활용하면 끝!

profile
개발 재밌다

0개의 댓글