모킹 어떻게 하시나요? (feat.MSW)

Ko Myungsoo
식스샵 기술 블로그
13 min readJun 1, 2022
MSW — Seamless API Mocking Library

안녕하세요. 이번 블로그 포스팅은 식스샵에서 프론트엔드 개발자가 사용하고 있는 MSW(Mock Service Worker) API Mocking Library를 소개하려고 합니다.

MSW를 소개하기에 앞서, 프론트엔드 개발자의 고충과 MSW를 도입한 배경부터 전달하려고 합니다.

😰 프론트엔드 개발자의 고충

API와 관련된 개발을 진행하게 될 경우 프론트엔드 개발자는 백엔드 개발자의 API 개발이 완료될 때까지 UI 관련된 부분을 제외하고는 진행이 불가능합니다.
오랜 기다림 끝에 API 연동을 하는데, API에 문제가 있는 경우 프론트엔드 개발자는 백엔드 개발자에게 API 수정 요청을 하고, 백엔드 개발자는 API를 수정을 합니다.
백엔드 개발자가 API 수정을 완료하면, 수정된 API를 같이 맞춰보는 시간을 가져야합니다.
수정된 API가 또 문제가 있는 경우 이 과정을 계속 반복해야 합니다.

개발 기간은 한정되어 있고 개발 완료의 기준은 프론트엔드 개발자의 작업이 완료되는 시점입니다.

개발이 완료된 이후에도 테스트, 디버깅, 리팩토링 등 완성도를 높이기 위해 해야 할 일들이 있습니다.

백엔드 API 작업이 길어질수록 프론트엔드의 작업 가능한 시간은 줄어들게 됩니다. 😰
기획자와 PM은 프론트엔드 개발자만 바라보고 있겠죠… 생각만 해도 부담스럽습니다. 😭

🔥 MSW 도입 배경

  • 개발과정의 이상과 현실

위의 이미지를 보고 많은 프론트엔드 개발자분들이 공감하실 것으로 생각합니다. 순차적으로 개발이 진행되면 좋겠지만, 대부분이 병렬로 진행하게 될 것입니다.

프론트엔드 개발자는 API가 완성되기 전까지 UI 작업 및 Mock 데이터를 이용하여 작업을 할 것입니다.

일반적으로 사용되는 모킹 방식에는 2가지가 있습니다.

  1. 화면에 필요한 데이터와 상태들을 직접 로직에 모킹하는 방식
  2. 모킹 서버를 구축하는 방식
  • postman
  • json-server

1번 방식의 경우 빠르게 화면을 개발할 수 있다는 장점이 있지만 http 메소드와 응답에 따른 대응이 어려운 단점이 있죠.

그렇다면 2번은 어떨까요? 모킹 서버를 구축하는 경우 1번의 단점들은 해결할 수 있지만 모킹 데이터가 늘어날수록 복잡도가 높아지고 공수가 많이 들어간다는 단점이 있습니다.

이 단점을 모두 해결한 라이브러리가 있는데요.
바로 MSW(Mock Service Worker) 입니다.

MSW는 API가 개발되지 않은 상황에서, 프론트엔드가 가상 데이터를 불러올 수 있도록 가상 API를 제공해주는 라이브러리입니다.

API를 제공해주기 때문에 추후 API 개발이 완료된 후 로직을 수정해야 하는 일이나 응답 상태에 따른 처리를 위한 걱정을 하지 않아도 되죠.

식스샵 스토어프론트팀의 프론트엔드 기술 스택은 TypeScript + Next.js + GraphQL 을 사용하고 있는데요. 마침, MSW가 TypeScript 및 GraphQL도 지원하고 있어 긍정적으로 다가왔습니다.

MSW를 도입하여 궁극적으로 추구하는 목적은
“API가 완성되기 전에 프론트엔드 개발 완성도를 높이자” 입니다.

MSW를 이해하기 위해서는 Service Worker에 대해 알아야 하는데요.
Service Worker에 대해 먼저 알아보겠습니다!

🤔 Service Worker 란?

Service Worker API는 웹 어플리케이션, 브라우저 및 네트워크 사이에 있는 프록시 서버 역할을 합니다.

웹 어플리케이션의 메인 스레드와 분리된 별도의 백그라운드 스레드에서 실행시킬 수 있는 기술 중 하나입니다.

요약하면 UI Blocking 없이 브라우저가 백그라운드에서 실행하는 스크립트입니다.

Application + Service Worker + MSW Process

Service Worker의 개념 및 사용 예시, 제한사항에 대해서 알아보겠습니다.

Service Worker 개념

  1. 웹사이트와 별개로 동작합니다.

Service Worker는 웹사이트와 별개로 동작하며, 웹사이트의 Life Cycle을 따르지 않습니다. 웹페이지가 닫히더라도 자동으로 비활성화되지 않습니다.
단, DOM이나 window 요소에 접근할 수 없습니다.

2. 웹사이트의 요청을 가로챌 수 있습니다.

Service Worker는 연결된 웹사이트를 제어 및 탐색할 수 있으며, 리소스 요청을 가로채서 수정할 수 있습니다.

3. 웹사이트와 네트워크의 중간다리 역할을 할 수 있습니다.

웹사이트와 브라우저 및 네트워크 사이에서 프록시 서버 역할을 할 수 있습니다. 프록시 서버란, 클라이언트와 서버 사이에서 데이터를 전달해 주는 서버입니다.

4. 리소스를 캐싱할 수 있습니다.

리소스를 캐싱할 수 있기 때문에 불필요한 API 요청을 줄일 수 있습니다.

Service Worker 사용 예시

  • 백그라운드 데이터 동기화가 가능하기에 메시지 전송 중 컴퓨터가 오프라인이 되어도, 다시 온라인 상태가 되면 작업 마무리가 가능합니다.
  • API 요청을 가로채 모의 응답을 전송할 수 있습니다.
  • 인터넷 연결이 끊겨도 캐시가 존재하는 한, 브라우저에 정보를 보여줄 수 있습니다.
  • 브라우저 창이 닫혀도 동작하기에, 푸시 알람을 구현할 수 있습니다.

Service Worker 제한사항

  • 대부분의 모던 브라우저에서 지원하고 있으나, IE와 같은 일부 브라우저에서는 지원하지 않습니다.
  • localhost가 아닌 환경이라면 HTTPS 보안 프로토콜 환경이 필요합니다.

🧐 MSW는 무엇인가?

MSW는 Mock Service Worker의 약자로 API Mocking Library입니다.

MSW는 다음과 같은 특징을 가지고 있습니다.

  • BrowserNode 환경에서 동일한 Request Handler 공유
  • Service Worker API를 사용하여 네트워크상에서 실제 요청을 가로채서 Mock 데이터를 제공
  • REST APIGraphQL 지원
  • TypeScript 지원

MSW 공식 문서에는 아래와 같이 소개하고 있습니다.

API mocking of the next generation

Mock by intercepting requests on the network level. Seamlessly reuse the same mock definition for testing, development, and debugging.

🤝 MSW를 활용한 개발 방식

MSW가 도입되기 전

  1. 기획자가 요구 사항을 전달합니다. (그림 1)
  2. 프론트엔드 개발자와 백엔드 개발자가 API 스펙을 합의합니다. (그림 2)
  3. 백엔드 개발자는 합의된 API 스펙에 맞게 개발을 진행합니다. (그림 3)
  4. API 개발이 완료되면 프론트엔드 개발자에게 API를 전달합니다. (그림 4)
  5. 프론트엔드 개발자는 전달받은 API로 개발을 진행합니다. (그림 5)

MSW가 도입된 후

  1. 기획자가 요구 사항을 전달합니다. (그림 1)
  2. 프론트엔드 개발자와 백엔드 개발자가 API 스펙을 합의합니다. (그림 2)
  3. (그림 3)
    3–1. 백엔드 개발자는 합의된 API 스펙에 맞게 개발을 진행합니다.
    3–2. 프론트엔드 개발자는 목업 데이터를 기반으로 개발을 진행합니다.
  4. API 개발이 완료되면 프론트엔드 개발자에게 API를 전달합니다. (그림 4)
  5. 프론트엔드 개발자는 기획자와 피드백을 주고 받고 개발 사항을 확인합니다. (그림 5)

🔨 기본 설정 및 구현 예시

프로젝트에 적용한 코드를 보면서 이해도를 높여 보겠습니다.

  1. MSW 설치

개발 환경에서만 MSW를 사용하기 때문에 devDependency로 패키지를 설치합니다.

Install msw package

2. mocks 정의

mocks 폴더에는 다음과 같은 파일이 있습니다.

  • index.ts: MSW 실행 파일
  • handlers.ts: API Mocking을 지정하는 파일들의 모음
  • browser.ts: Browser에서 실행하기 위한 worker 구성
  • server.ts: Node에서 실행하기 위한 server 구성

mocks 폴더 및 index, handlers 파일을 생성합니다.

  • index.ts
개발 환경에 따라 구분해서 실행합니다.
  • handlers.ts
기능별로 분리된 handlers를 통합하는 파일
  • API 선택

어플리케이션에서 사용하는 API가 REST API 방식인지, GraphQL API 방식인지에 따라 구현하는 방법이 다른데요.

식스샵 스토어프론트 팀에서는 GraphQL을 사용하기 때문에 MSW의 graphql를 import 하여 Mocking 관련 코드를 작성했습니다.

Response resolver에는 파라미터로 request, response, context가 있습니다.

  • request: 캡처된 요청에 대한 정보
  • response: 모의 응답을 생성하는 함수
  • context: 현재 request handler에 특정한 context 유틸리티

기능별 요청을 보냈을 때 응답 값을 JSON으로 작성해서 context.data로 넘겨주면 됩니다.
context.status()로 status code도 지정할 수 있어 에러 케이스도 테스트할 수 있습니다!

아래는 GraphQL+MSW를 사용하여 상품 목록에 대한 handler를 정의한 예제입니다.

상품 관련 API Mocking handler 정의

3. 개발 환경 통합

Browser와 Node 환경에서 동일한 request handler를 공유할 수 있습니다.
Service Worker는 Node에서 실행할 수 없으므로 환경에 따라 통합 프로세스가 다릅니다.

  • Browser에서 실행하기

Browser에서 MSW를 사용하기 위해서는 Service Worker를 등록하는 과정이 필요합니다.

Service Worker를 제공하기 위해 MSW는 전용 CLI를 제공합니다.

Service Worker 스크립트는 http 요청을 가로채서 모의 서버에서 동작하도록 해줍니다.

아래 명령어를 통해 public 폴더에 Service Worker 스크립트를 생성합니다.

public 폴더에 mockServiceWorker.js 파일 생성
  • worker 구성하기

mocks 폴더 안에 browser.ts 파일을 생성합니다.

MSW의 setupWorker를 이용하여 Service Worker를 초기화할 수 있습니다.

초기화 과정을 거치면 클라이언트의 요청을 서버가 아닌 Service Worker로 보내고 Mock API에 정의한 JSON 값을 response 값으로 받아올 수 있습니다.

API Mocking을 정의한 handlers.ts로 Service Worker를 초기화해야 합니다.

  • Node에서 실행하기

Node에서 Mock Service Worker의 가장 일반적인 사용법 중 하나는 통합 테스트를 위해 request handler를 활용하는 것입니다.

  • Server 구성하기

mocks 폴더 안에 server.ts 파일을 생성합니다.

handler.ts에서 정의한 request handler로 Server 인스턴스를 생성합니다.

  • MSW 실행하기

개발 환경에서만 MSW가 실행되도록 _app.tsx 파일에 설정합니다.

MSW를 이용하여 API를 호출하는 경우 (from service worker) 표시
Bypass for network 옵션을 체크하면 Service Worker 동작을 멈추고 실제 서버로 요청
MSW API Mocking의 Mock 데이터를 활용한 결과물

🕹 API Mocking & 실제 API 스위칭

MSW를 활용하여 개발 효율을 높이던 와중에 문제가 하나 발생했습니다.

같이 일하는 동료 개발자분이 실제 API를 연동하는 시점에 API Mocking에서 실 서버로 연동을 변경하는 방법에 대해서 문의하였습니다.

“실제 API로 요청하도록 변경하려면 어떻게 해야 하나요? handlers 코드들을 주석처리 해야 하나요?”
“실제 API를 연동한 handler는 Mocking을 Off하고 그 외 handler는 Mocking을 유지하도록 분기가 가능한가요?”

아쉽게도, MSW에서 해당 기능을 공식적으로 지원하지 않습니다.
MSW GitHub Issues에 우리와 비슷한 문제를 겪고 있는 내용이 있어 API Mocking과 실제 API를 스위칭할 수 있는 작업을 추가로 진행하였습니다.

  • localStorage를 이용하여 MSW On & Off 관리

startMSW.ts 파일을 생성하고 아래와 같이 작성합니다.

window 객체에 worker 제어하는 함수 추가

기존 index.ts 파일을 아래와 같이 변경합니다.

Browser console 창에서 MSW On & Off를 스위칭할 수 있습니다.
스위치 On & Off가 localStorage에서 관리되어 Browser를 다시 접속해도 이전 설정이 유지됩니다!

  • Mocking On & Off Hidden 버튼

코드 수정 없이 API Mocking & 실제 API를 스위칭하는 것이 가능해졌습니다.
하지만, console로 수동 제어하는 부분이 불편하게 느껴졌습니다.

동료 개발자분이 “Hidden 버튼으로 제어하는 것은 어떠세요?” 라고 좋은 아이디어를 주셨습니다. 👍

개발 환경에서만 더블 클릭했을 때, Mocking On & Off 하는 히든 버튼을 생성했습니다.

👣 마치며

MSW를 실제로 도입해보니, API가 완성되기까지 기다려야 하는 부담을 줄일 수 있었고 처음에는 프론트엔드 개발자를 위해서 MSW를 도입하였지만 결국 백엔드 개발자분들도 개발 부담이 줄어들었습니다!
백엔드 & 프론트 개발이 병렬로 자주 진행되는 경우 MSW를 도입하는 것을 강력히 추천합니다!

이상으로 MSW 포스팅을 마치겠습니다. 🙇‍♂️
긴 글 읽어주셔서 감사합니다 🙂

식스샵은 올인원 이커머스 플랫폼을 만들고 있는 팀입니다.

B2B | E-Commerce | SaaS 시장에 대해 함께 고민하고, 빠른 실험과 검증을 통한 사업의 성장을 경험하고 싶은 분을 모시고 있습니다.

채용 중인 포지션은 이곳에서 확인하실 수 있습니다 🙂

--

--