MSW(Moking Service Worker)는 서비스워커를 사용하여 네트워크 호출을 가로채는 API 모킹(mocking) 라이브러리 입니다.
간단하게 말하면 백엔드 API인척 하면서 프론트앤드의 요청에 가짜 데이터를 응답해주는 녀석입니다.
보통의 프로젝트를 생각하면 FE는 BE가 완성되야 진행된다고 생각하는데
현실은 그렇지 않습니다.
적은시간에 좋은결과를 도출해야하기때문에 같이 개발을 해야하는데 API가 없으면 테스트가 힘들었다는걸 개발을 해본사람이라면 알고 있다.
근데 가짜데이터를 받고 에러에 대한 테스트를 진행한다면?
백엔드와 속도를 맞추면서 마지막단계로 CI 만 진행하면 된다.
먼저, 브라우저에 Service Worker(웹 표준 기술)를 설치합니다
설치이후로부터 브라우저에서 실제로 이루어지는 요청을 Service Worker가 가로채게 됩니다.
Service Worker에서는 해당하는 실제 요청을 복사해서 MSW에게 해당 요청과 일치하는 모의 응답을 제공받고 이를 브라우저에게 그대로 전달하게 됩니다.
이러한 과정을 통해서, 실제 서버 존재 여부와 상관없이 실제 요청으로 이어지지 않고 예상할 수 있는 요청에 대해 Mocking이 가능해집니다.
이렇게 Mocking이 가능해지면 API가 준비되지 않았어도 다음과 같은 개발 방식을 선택할 수 있습니다.
기획자가 요구 사항을 전달하면, 프론트엔드 개발자와 백엔드 개발자가 API 스펙을 합의하고 백엔드 개발자는 프론트엔드 개발자에게 API의 스펙을 제공합니다. 그 이후, 프론트엔드 개발자는 MSW를 통해 네트워크 레벨에서의 Mocking을 진행한 후, 애플리케이션을 개발하게 됩니다.
API 없이도 프론트엔드 개발자는 높은 완성도를 갖고 있는 수준에서 기획자와 미리 프론트엔드 애플리케이션을 확인하며 피드백을 주고받고, 그 사이 백엔드 개발자는 API 개발을 진행합니다. 이후 백엔드 개발자가 API를 제공하면, 프론트엔드 개발자는 별다른 작업 없이 MSW를 스위치 오프만 하면 Production으로 배포할 수 있는 형태의 개발 과정을 통해 개발을 진행할 수 있습니다.
MSW는 디버깅이 필요한 상황에서도 좋은 시너지를 만들어 낼 수 있습니다.
예를 들어, 특정 API 응답을 기준으로 에러가 발생해 디버깅이 필요한 상황이라면, 기존 서비스 로직을 전혀 건드리지 않고 오로지 MSW에서 Mocking을 만들어 내서 쉽게 디버깅할 수 있습니다.
더 나아가, 이러한 장점은 기획자 등의 다른 누군가에게 각 화면을 공유하고 피드백을 받아야 하는 상황이 발생했을 때에도, 추가적으로 MSW에서 해당 상황을 만들어낼 수 있도록 작업을 해 둔다면 별다른 서비스 로직의 수정 없이도 MSW를 통해 제공이 가능해집니다.
얼마나 간단하게 MSW를 적용할 수 있는지도 중요할 것 같습니다. 간단하게 한번 살펴보겠습니다. 설치하게 될 프로젝트는 Create-React-App 기반으로 구성되어 있다고 전제합니다.
$ npm i -D msw
mock을 사용하기위한 라이브러리 설치
npx msw init public/ --save
public/ 폴더 안에 서비스 워커 코드를 생성한다는 의미이다.
서비스워커가 설치되야 mocking 이 가능하다
이제 본격적으로 만들어보자
API 신호를 가로채는 핸들러는 express 코드와 유사하다.
// /src/mocks/handler.js
import { rest } from "msw";
const todos = ["먹기", "자기", "놀기"];
export const handlers = [
// 할일 목록
rest.get("http://localhost:8000/auth/signin", (req, res, ctx) => {
return res(ctx.status(200), ctx.json(todos));
}),
// 할일 추가
rest.post("/todos", (req, res, ctx) => {
todos.push(req.body);
return res(ctx.status(201));
})
];
req : 요청
res : 응답
ctx : JSON,STATUS 와 같은 라이브러리를 사용할 수 있음
// /src/mocks/worker.js
import { setupWorker } from "msw";
import { handlers } from "./hander";
export const worker = setupWorker(...handlers);
핸들러를 서비스워커에 설정해준다.
// /src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { worker } from "./mocks/worker";
if (process.env.NODE_ENV === "development") {
worker.start();
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
설정해준 서비스워커를 코드가 돌아갈때 같이 실행시켜줘여한다.
react가 시작하는 시점인 index.js 맨 상단에 위치해두고, 개발환경에서만 작동하도록 설정해줬다.
이제 실행을 해보자
웹 콘솔에 아래 와 같이 뜨면 성공적으로 실행된 것이다.
이제 우리가 만든 가짜응답이 오는지 확인해보자
// App.js
const fetchHandler = async() =>{
const response = await fetch("/todos");
const movies = await response.json();
console.log(movies);
}
useEffect( ()=>{
fetchHandler()
},[])
코드를 실행하면 아래와 같이 가짜 api 값이 넘어온다.
const fetchHandler = async() =>{
const response = await axios.get("/todos");
console.log(response.data);
}
axios도 문제없이 작동한다.
MSW를 사용하려면 FE도 어느정도 서버에 대한 지식은 알고 있어야하고
HTTP에대한 지식이 필요하다는것을 느꼈다.
https://tech.kakao.com/2021/09/29/mocking-fe/
https://www.daleseo.com/mock-service-worker/