MSW(Mock Service Worker) 2.0

ยทDev
#TIL

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๋ฐฑ์—”๋“œ API๊ฐ€ ๊ฐœ๋ฐœ๋˜๊ธฐ ์ „ ๋ชฉ์—… API๋ฅผ ์ง์ ‘ ๊ฐœ๋ฐœํ•ด UI๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค. ์ฒซ ํšŒ์‚ฌ์—์„œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์ฒ˜์Œ ์‚ฌ์šฉํ•ด ๋ดค๋‹ค. ์ตœ๊ทผ 2.0 ๋ฒ„์ „์ด ์ƒˆ๋กญ๊ฒŒ ๋‚˜์™”๋‹ค๊ณ  ํ•˜๋‹ˆ ์„ค์ • ๋ฐฉ๋ฒ•์„ ๊ธ€๋กœ ๋‚จ๊ฒจ๋ณธ๋‹ค.

MSW(Mock Service Worker)๋ž€?

Getting started

โฌ‡๏ธ Install

> npm install msw --save-dev
> yarn add -D msw

โœ… MSW ์ƒ์„ฑ

> npx msw init public/ --save 

โš’๏ธ Setup

msw๋Š” ์„œ๋น„์Šค ์›Œ์ปค๋ผ๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง€์›ํ•˜๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์„œ๋น„์Šค ์›Œ์ปค๋Š” ๋ธŒ๋ผ์šฐ์ € ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ ํ•ด๋‹น ํŽ˜์ด์ง€์™€๋Š” ๋ณ„๊ฐœ๋กœ ์ž‘๋™ํ•˜๋ฏ€๋กœ DOM ์ œ์–ด๋‚˜ ์‚ฌ์šฉ์ž ์ธํ„ฐ๋ ‰์…˜์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ธฐ๋Šฅ๋งŒ ์ œ๊ณตํ•œ๋‹ค.

์„œ๋น„์Šค ์›Œ์ปค ์„ค์ •์ธ brower.ts ์™€ ๋ชจํ‚น API ํ•จ์ˆ˜์ธ handler.ts ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

๐Ÿ“ ./mock/brower.ts

import { setupWorker } from 'msw/browser'
import { handlers } from './handlers'
 
export const worker = setupWorker(...handlers)

๐Ÿ“ ./mocks/handler.ts

import { http, HttpResponse } from 'msw'
 
export const handlers = [
  http.get('/api/user', ()=>{
		return HttpResponse.json({ status: 200, name: 'kkusaeng' })
  })
]

๐Ÿ“ main.tsx

import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'react-router'
import router from '@/router'
import '@/styles/index.css'
 
const enableMockingg = async () => {
  if (import.meta.env.MODE === 'production') return
 
  const { worker } = await import('../mocks/browser')
  return worker.start()
}
 
enableMockingg().then(() => {
	ReactDOM.createRoot(document.getElementById('macjjuni') as HTMLElement).render(
	  // <React.StrictMode>
	  <RouterProvider router={router} />,
	  // </React.StrictMode>
	)
}

์—”ํŠธ๋ฆฌ ํฌ์ธํŠธ์—์„œ ๊ฐœ๋ฐœ ๋ชจ๋“œ์—์„œ๋งŒ ์›Œ์ปค๋ฅผ ์‹คํ–‰์‹œํ‚จ ํ›„ ๋ฆฌ์•กํŠธ DOM ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ๋ฉด ๋œ๋‹ค. ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ฝ˜์†” ์ฐฝ์—์„œ Mocking enabled ๋ฉ”์„ธ์ง€๊ฐ€ ๋ณด์ธ๋‹ค๋ฉด ์ œ๋Œ€๋กœ ์ž‘๋™๋œ ๊ฒƒ์ด๊ณ  ๋‹ค์Œ์œผ๋กœ ํ…Œ์ŠคํŠธ๋กœ ๋งŒ๋“  ๋ชจํ‚น API๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด ๋ณด์ž ๐Ÿƒ๐Ÿปโ€โ™‚๏ธ

[MSW] Mocking eanbled.

๐Ÿƒ๐Ÿปโ€โ™‚๏ธ ๋ชจํ‚น API ํ˜ธ์ถœ ํ…Œ์ŠคํŠธ

๐Ÿ“ App.tsx

import { Outlet } from 'react-router'
import { useEffect } from 'react'
 
export default function App() {
 
  const getUser = async () => {
    const response = await fetch('/api/user')
    const data = await response.json()
    console.log(data)
  }
 
  useEffect(() => {
    getUser()
  }, [])
  return <Outlet />
}

getUser() ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์„œ ์‹คํ–‰ํ•ด๋ณด๊ณ  ์ฝ˜์†”์ฐฝ์— ์ž˜ ๋‚˜์˜ค๋‚˜ ํ™•์ธํ•ด๋ณด์ž.

ํ…Œ์ŠคํŠธ๋กœ ๋งŒ๋“ค์–ด ๋ณธ ๋ชฉํ‚น API๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ์—๋„ ์ž‘์„ฑํ•œ ๋Œ€๋กœ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ชฉํ‚น API ์„ค์ •์€ ๋์ด๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ ๋ฐฑ์—”๋“œ API ๊ฐœ๋ฐœ์ด ๋˜๊ธฐ ์ „ ์ž„์˜๋กœ ๋ชจํ‚น API๋ฅผ ๋งŒ๋“ค์–ด UI๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ณ  API ํ˜ธ์ถœ์— ์‹คํŒจ์™€ ์„ฑ๊ณต ๋‘ ๊ฐ€์ง€ ์ผ€์ด์Šค์— ๋Œ€ํ•ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณธ๋‹ค๋ฉด ์™„๋ฒฝํ•œ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ด์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค.

Reference

Getting started

[React] MSW(Mock Service Worker) 2.0์„ ์•„์‹œ๋‚˜์š”?