본문 바로가기

React

React + MSW(Mock Service Worker)로 백엔드 API 없이 개발하기

서비스 개발 단계에 있어서 보통 프론트엔드 작업은 후순위일 것이다. 기획을 하고 디자인과 백엔드 API가 나오면서 비로소 프론트에서의 본격적인 개발이 시작된다. 하지만 언제까지나 API 개발만을 기다릴 순 없기에 프론트엔드 개발자가 실제 백엔드 API가 아직 준비되지 않은 상황에서도 MSW를 사용하여 목(mock) 데이터를 생성함으로써, 프론트엔드 개발을 선행적으로 시작할 수 있는 방법에 대해 알아볼 것이다.

 

본 글은 React + TypeScript + MSW 2.0 이후의 버전에 기반하여 작성했습니다.

https://mswjs.io/docs/migrations/1.x-to-2.x/


1. MSW(Mock Service Worker) 란?

Mock Service Worker (MSW)는 웹 애플리케이션 개발 시 API 요청을 모의(mock)하여 프론트엔드 개발과 테스트를 용이하게 하는 도구이다. 실제 백엔드 서버가 준비되지 않았거나, 백엔드와 독립적으로 프론트엔드 개발을 진행하고자 할 때 유용하게 사용된다. MSW는 Service Worker API를 활용하여 네트워크 요청을 가로챈 후, 미리 정의된 응답을 반환함으로써 실제 서버와의 상호작용 없이도 애플리케이션을 테스트할 수 있게 한다.

 

 

MSW의 특징

공식 홈페이지에 나와있는 MSW의 특징 3가지는 다음과 같다.

https://mswjs.io/docs

 

 

  1. Agnostic (환경 무관성): MSW는 환경, 프레임워크, 그리고 도구에 완전히 무관하도록 설계되었습니다. 별도의 추가 설정, 어댑터 또는 플러그인 없이도 모든 브라우저나 Node.js 프로세스에서 사용할 수 있습니다. 네이티브 window.fetch()든, Axios, React Query, Apollo와 같은 서드파티 라이브러리든 모든 요청 클라이언트와 호환됩니다.
  2. Seamless (원활함): MSW는 Service Worker API를 사용하여 네트워크 수준에서 실제 프로덕션 요청을 가로챕니다. fetch를 패치하거나 애플리케이션의 무결성에 간섭하는 대신, MSW는 플랫폼에 의존하여 표준 브라우저 API를 활용함으로써 혁신적인 요청 가로채기 로직을 구현합니다.
  3. Reusable (재사용 가능성): API 모킹을 독립적인 계층으로 취급함으로써, MSW는 전체 스택에 걸쳐 통합될 수 있으며, 필요에 따라 네트워크 동작을 재사용하고 커스터마이즈할 수 있습니다. 예를 들어, 개발, 통합 및 엔드 투 엔드 테스트 중에 동일한 API 모킹을 사용하고, 이후 Storybook이나 라이브 데모에서도 동일한 모킹을 사용할 수 있습니다. MSW를 사용하면 이러한 모든 것이 가능합니다.

 

2. MSW 설치

# npm 사용 시
npm install msw --save-dev

#pnpm 사용 시
pnpm add msw --save-dev

# yarn 사용 시
yarn add msw --dev

 

 

3. 서비스 워커(Service Worker) 파일 생성

다음 명령어를 통해 서비스 워커 파일(mockServiceWorker.js)을 public 디렉토리에 생성한다.

npx msw init public/ --save

서비스 워커란 사용자와 웹 애플케이션간의 네트워크 요청을 가로채고 처리할 수 있는 기능을 제공한다.

 

4. 핸들러 정의

핸들러는 네트워크 요청을 가로채고 응답 방식을 정의하는 파일이다. 루트 폴더 하위에 mocks라는 디렉토리를 생성한 후 handlers.ts 파일을 생성하였다. 최상단에 1.x 버전에서 2.0으로 마이그레이션되는 부분의 링크를 달아놓았지만, 혹시나 하고 말하자면 2.0에서는 MSW에서 가져오는 rest 인스턴스가 http 인스턴스로 바뀌었다.

// src/mocks/handlers.js

import { http, HttpResponse } from 'msw';
import { MatchingUserCard } from '../entities/my-page/model/matching-user-card.interface';

// 더미 데이터 생성
const dummyUsers: MatchingUserCard[] = Array.from({ length: 30 }, (_, i) => ({
  profileImage: '/svg/default-profile-icon.svg',
  nickname: `유저 ${i + 1}`,
  matchCount: Math.floor(Math.random() * 10) + 1,
  location: `지역 ${i + 1}`,
  hashtags: [
    '#소규모형',
    '#귀차니즘형',
    '#기능성피트니스위주',
    '#헬스헬스무조건벌크업',
  ],
}));

// API 핸들러
export const handlers = [
  http.get('/api/matching-users', () => {
    // 무작위 유저 한 명을 선택
    const randomUser =
      dummyUsers[Math.floor(Math.random() * dummyUsers.length)];

    // 랜덤 유저 한 명 반환
    return HttpResponse.json([randomUser]);
  }),
];

우선 나는 유저 정보에 대한 더미 데이터가 필요 했기에 30개의 더미 유저 데이터를 dummyUsers를 통해 생성하였다. 그후 handlers 함수를 정의하여 matching-users라는 엔드포인트를 임의로 만들어서 요청하였다. 그 후 리턴값으로 dummyUsers 함수를 통해 만든 목 데이터를 랜덤으로 반환 받는다. 

 

본인은 우선 get 요청을 통해 유저의 정보들만 받아오기에 위와 같이 작성한 것이고 필요에 따라 post, put, delete 등의 로직을 작성하면 된다. 물론 더미데이터도 포함이다.

 

5. 개발 환경 구성

5-1 브라우저 환경 설정

 

개발 환경에서 MSW를 사용하기 위해서 mocks 디렉토리 안에 browser.ts 파일을 생성해주도록 하자.

// src/mocks/browser.js
import { setupWorker } from 'msw/browser';
import { handlers } from './handlers';

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

 

5-2 MSW 활성화 하기

//src / main.tsx

import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import { worker } from './mocks/browser.ts';

if (process.env.NODE_ENV === 'development') {
  worker.start().then(() => {
    createRoot(document.getElementById('root')!).render(
      <div>
        <GlobalStyles />
        <App />
      </div>
    );
  });
} else {
  // 프로덕션에서 워커 없이 실행
  createRoot(document.getElementById('root')!).render(
    <div>
      <App />
    </div>
  );
}

애플리케이션 진입점 파일에 위와 같이 설정하였다. 위의 코드는 개발 환경에서만 MSW를 활성화하고 프로덕션 환경에서는 활성화하지 않는다.

 

6. MSW 실행

개발 서버를 실행해서 MSW가 잘 동작하는지 확인해보자

[MSW] Mocking enabled.

관리자도구를 열었을 때 콘솔창에 위와 같이 출력이 된다면 MSW가 정상적으로 활성화 된 상태이다.
또는 아래와 같이 관리자도구에서 애플리케이션 탭에서 확인할 수 있다.

 

목 데이터 값 확인하기

이제 데이터를 사용할 컴포넌트에서 목 데이터를 받아와서 값이 들어오는지 확인을 하면 된다.

  fetch('/api/matching-users')
    .then((res) => res.json())
    .then((data) => console.log(data));

간단한 fetch 함수를 통해 콘솔에 데이터를 출력하면

아까 handler.ts에 만들어 놓은 더미 데이터가 잘 들어오는 것을 확인할 수 있다.


 

이상으로 MSW를 세팅하고 사용하는 방법에 대해서 알아보았다.
백엔드 API가 나오기전에 프론트에서 목 데이터를 통해 선 작업을 시작하여 조금 더 효율적이고 빠른 개발이 가능해졌다.