카테고리 없음

MSW(Mock Service Worker)로 API 개발 지연에 대응해보기

Dev.JH 2025. 1. 16. 20:57

MSW 도입 배경

사실 프론트엔드 개발자에게 가장 이상적인 개발 과정은 MVP 모델 수립 이후 백엔드 개발이 완성되어 있는 상태에서 프론트엔드 개발을 하는 것이다. 그러나 지금까지 겪어 왔던 프로젝트들은 이러한 이상과는 거리가 있었다. 바로 아래의 그림처럼 말이다.

 

 

설상가상으로 이전 독서 토론 플랫폼 지성인 프로젝트를 진행하면서 백엔드 개발자 분들이 바쁜 시기가 있어 예정된 시기에 API를 제공 받지 못하였다. 백엔드 개발에 의존적인 프론트엔드 개발의 특성 상, 프론트엔드 개발 일정도 덩달아 길어지게 되었고, 우리 팀은 MSW를 적용해 백엔드 개발에 의존적이지 않은 개발 환경을 구축하기로 하였다.


MSW에 대해 알아보기

MSW(Mock Service Worker)는 프론트엔드 개발에서 API를 모킹하기 위한 라이브러리다. 주로 네트워크 요청을 가로채고 가짜 데이터를 반환하여, 백엔드 준비가 완료되지 않은 상태에서도 프론트엔드 개발 및 테스트를 진행할 수 있도록 도와준다.

MSW가 이런 기능을 제공할 수 있는 이유는 Service Worker가 HTTP 요청을 가로채주는 기능을 제공하기 때문이다.

Service Worker

서비스 워커는 웹 응용 프로그램, 브라우저, 그리고 (사용 가능한 경우) 네트워크 사이의 프록시 서버 역할을 합니다. 서비스 워커의 개발 의도는 여러가지가 있지만, 그 중에서도 효과적인 오프라인 경험을 생성하고, 네트워크 요청을 가로채서 네트워크 사용 가능 여부에 따라 적절한 행동을 취하고, 서버의 자산을 업데이트할 수 있습니다.
또한 푸시 알림과 백그라운드 동기화 API로의 접근도 제공합니다. 
출처: MDN - Service Worker API

MSW를 적용하여서 클라이언트에서 요청을 보냈을 때는 위 사진과 같은 프로세스를 거치게 된다.


1. 브라우저가 Service Worker에 요청을 보냄
2. Service Worker가 해당 요청을 가로채서 복사함
3. 서버에 요청을 보내지 않고, MSW 라이브러리의 핸들러와 매칭시킴
4. MSW가 등록된 핸들러에서 모의 응답 (mocked response)를 Service Worker에게 전달함
5. 마지막으로, Service Worker가 모의 응답을 브라우저에게 전달함


MSW 적용해보기

이제 본격적으로 MSW를 적용해보자! 우리 프로젝트 특성상 이미지를 사용할 일이 많아서 가짜 데이터를 생성해주는 faker-js도 같이 사용할 예정이다. 만약 faker-js가 필요 없다면 해당 부분은 건너뛰어도 된다.

1. MSW 설치

$ npm install msw

2. Faker.js 설치

$ npm i -D @faker-js/faker

 

패키지 설치가 완료되면 public 폴더에 mockServiceWorker.js 파일이 생성된 것을 확인할 수 있다.

2-1. Faker image domain 추가

지성인 프로젝트의 경우 Next.js를 사용하고 있기에 next.config.js파일의 domains 배열 안에 "loremflickr.com" domain을 추가해줘야 에러가 발생하지 않는다. 위와 같이 추가해주도록 하자.

module.exports = {
  images: {
    domains: ["k.kakaocdn.net"],
    domains: ["k.kakaocdn.net", "loremflickr.com"],  // loremflickr.com 추가
  },
  webpack: (config) => {
    config.module.rules.push({
    ....

3. http.ts 파일 작성

이제 http 파일을 작성해야 하는데, origin은 여러분의 localhost

import { createMiddleware } from "@mswjs/http-middleware";
import express from "express";
import cors from "cors";
import { handlers } from "./handlers";

const app = express();
const port = 9090;

app.use(
  cors({
    origin: "http://localhost:3000",
    optionsSuccessStatus: 200,
    credentials: true,
  }),
);
app.use(express.json());
app.use(createMiddleware(...handlers));
app.listen(port, () => console.log(`Mock server is running on port: ${port}`));

4. handler 생성

src/mocks 폴더 아래에 임의의 응답을 보내주는 handler.ts 파일을 만들어주자.

기본적으로 handlers는  여러개 생성함으로 보통 배열 형태로 관리된다. 아래의 예제는 handler.ts 파일 내의 코드로, 내가 /api/my/star 주소로 http 요청을 보냈을 때, 내가 세팅해둔 응답값을 임의로 보내주는 코드이다.

import { http, HttpResponse, StrictResponse } from "msw";
import { faker } from "@faker-js/faker";

export const handlers = [
  http.get("/api/my/star", ({ request }) => {
    // const url = new URL(request.url);
    // const cursor = parseInt(url.searchParams.get("cursor") as string) || 0;
    return HttpResponse.json([
      {
        postId: 1,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 2,
        title: "정의란 무엇이에요?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 3,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 4,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 5,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 6,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 7,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 8,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
      {
        postId: 9,
        title: "정의란 무엇인가?",
        image: faker.image.urlLoremFlickr(),
        starRate: "★★★★★",
      },
    ]);
  }),
];

 

 

image 키에는 faker-js의 도움을 받아 임의의 이미지를 받아와 return 할 수 있도록 세팅해주었다.

만약 image까지 가짜데이터로 만들어주고 싶으면 faker 모듈을 가져와서 faker.image.urlLoremFlicker() 를 이용해 이미지를 가져오자. (대부분 고양이 이미지가 온다.)

가져온 데이터로 렌더링 해주기

이제 실제 API가 없음에도 불구하고 HTTP 요청이 성공하여 응답 값을 가져온 것처럼 동작시킬 수 있다!

우리는 이제 API 명세를 보면서 프론트엔드 개발을 계속해서 진행하다가, 실제 API가 완성되면 적용한 MSW를 걷어내고 연결만 해주면 된다.

백엔드 개발에 종속적인 프론트엔드 개발의 특성을 어느정도 메워준 고마운 MSW이다.