- 소개
- 시작하기
- 철학
- 비교
- 제한 사항
- 디버깅 실행 매뉴얼
- FAQ
- Basics
- Concepts
- Network behavior
- Integrations
- API
- CLI
- Best practices
- Recipes
- Cookies
- Query parameters
- Response patching
- Polling
- Streaming
- Network errors
- File uploads
- Responding with binary
- Custom worker script location
- Global response delay
- GraphQL query batching
- Higher-order resolver
- Keeping mocks in sync
- Merging Service Workers
- Mock GraphQL schema
- Using CDN
- Using custom "homepage" property
- Using local HTTPS
비교
Mock Service Worker와 유사한 도구들과의 비교.
작업에 적합한 도구를 선택하는 것은 매우 중요합니다. 아래에서 Mock Service Worker와 다른 오픈소스 API 모킹 라이브러리 간의 포괄적이고 공정한 비교를 제공하기 위해 최선을 다했습니다.
이 페이지의 목적은 어떤 기술이 더 나은지 또는 더 나쁜지를 논하는 것이 아닙니다. 여기에 나열된 모든 라이브러리는 각자의 존재 이유가 있으며, 이를 평가하는 것은 주관적일 뿐만 아니라 특정 라이브러리를 사용해야 하는 사람들에게도 실례가 될 수 있습니다.
비교 기준
좋은 비교는 명확하게 정의된 기준에서 시작합니다. MSW와 대안들을 비교할 때 사용한 기준은 다음과 같습니다 (개발자 관점에서 작성):
- 지원하는 API 타입. 어떤 종류의 API를 모킹할 수 있는가?
- 환경. 어떤 환경에서 사용할 수 있는가?
- 구현 방식. 요청 가로채기를 어떻게 구현했는가?
- 통합. 프로젝트에 통합하는 데 얼마나 많은 노력이 필요한가?
- 정의 방식. 모의 응답을 어떻게 정의하는가?
Nock
Nock은 Node.js용 HTTP 서버 모킹 및 기대값 설정 라이브러리입니다.
Nock은 Node.js에서 API 모킹과 어설션을 결합하는 데 탁월한 라이브러리입니다. Mock Service Worker는 내장된 어설션 기능을 제공하지 않지만, 브라우저와 Node.js에서 동일한 모킹을 원활하게 재사용할 수 있으며, 퍼스트클래스 GraphQL 지원과 표준 기반의 요청/응답 처리를 제공합니다.
API 지원
API 타입 | Nock | Mock Service Worker |
---|---|---|
REST API | ✅ | ✅ |
GraphQL API | ❌ | ✅ |
WebSocket API | ❌ | ✅ |
지원 환경
환경 | Nock | Mock Service Worker |
---|---|---|
Node.js | ✅ | ✅ |
브라우저 | ❌ | ✅ |
통합
Nock | Mock Service Worker |
---|---|
코드 변경 없이 사용 가능 | 코드 변경 없이 사용 가능 |
특정 요청 클라이언트(예: axios )를 가로채기 위해 추가 어댑터 필요 | 추가 설정 없이 모든 요청 클라이언트와 함께 작동 |
Definition
Nock
Nock는 _메서드 체이닝_을 사용해 요청을 가로채고 모의 응답을 선언합니다:
nock('https://api.example.com')
.get('/user')
.reply(200, { id: 1, name: 'John' })
Mock Service Worker
import { bypass } from 'msw'
http.post('/fruits', async ({ request }) => {
const response = await fetch(bypass(request))
const json = await response.json()
json.push({ name: 'Mock Service Worker' })
return HttpResponse.json(json, response)
})
MSW에서
route.continue()
대신 사용할 수 있는 방법은 응답 리졸버에서 아무것도 반환하지 않는 것입니다. 하지만 우리는 요청을 메서드(POST
)와 경로(/fruits
)로 좁힐 수 있기 때문에, 이 요청 핸들러는 다른 요청에 대해 신경 쓸 필요가 없습니다.
MSW는 커스텀 bypass()
함수를 사용하여 주어진 Request
인스턴스를 감싸서, 다른 요청 핸들러의 영향을 받지 않도록 합니다.
JSON Server
JSON Server는 JSON 파일을 기반으로 실제 HTTP 서버를 생성할 수 있게 해줍니다.
JSON Server는 추상적인 응답 정의 형식을 사용하는 실제 HTTP 서버입니다. 이는 여러분이 실행하고 유지해야 하는 서버를 의미합니다. Mock Service Worker는 어떤 서버도 생성하지 않기 때문에 초기화 비용이 없습니다. 또한 Mock Service Worker는 TypeScript와 같은 언어를 사용하여 실제 백엔드 구현에서 모의 데이터를 생성함으로써 더 안전한 모의 정의를 가능하게 합니다.
API 지원 현황
API 타입 | JSON 서버 | Mock Service Worker |
---|---|---|
REST API | ✅ | ✅ |
GraphQL API | ❌ | ✅ |
WebSocket API | ❌ | ✅ |
지원 환경
환경 | JSON 서버 | Mock Service Worker |
---|---|---|
Node.js | ✅ | ✅ |
브라우저 | ✅1 | ✅ |
1—JSON 서버는 실제로 브라우저에서 실행되지 않습니다. 독립형 서버이기 때문에 시스템 어디에서나 요청할 수 있습니다.
Integration_Q5V2MVyb6wRowkRHzFGxNm
JSON 서버 | Mock Service Worker |
---|---|
모의 서버에서 리소스를 요청하도록 코드를 변경해야 함. | 코드 변경 없이 사용 가능. |
추가 설정 없이 모든 요청 클라이언트와 함께 작동. | 추가 설정 없이 모든 요청 클라이언트와 함께 작동. |
Definition_BvcXBvPNQxC7pcCCjhE5dC
JSON Server
JSON Server는 리소스 중심의 라우트 형식을 사용하여 요청 경로를 암묵적으로 생성하고 모의 응답을 설명합니다.
{
"posts": [
{ "id": 1, "title": "json-server" },
{ "id": 2, "title": "mock-service-worker" }
]
}
이렇게 하면 설명된 리소스를 기반으로
GET /posts
및DELETE /posts/:index
와 같은 서버 측 라우트가 자동으로 생성됩니다. 이러한 라우트의 특성은 정적이며, 더 복잡한 네트워크 동작을 구현하려면 추가적인 추상화가 필요합니다.
Mock Service Worker_Y3Kvu9fneg2pjcFkHN7D6C
MSW는 서버 사이드 라우팅을 모델로 한 인터셉션 API를 제공하며, Fetch API 명세에 따라 요청과 응답을 처리합니다. 이때 일반적으로 자바스크립트에서 사용하는 동일한 클래스를 사용합니다:
http.get('/posts', () => {
return HttpResponse.json([
{ id: 1, title: 'json-server' },
{ id: 2, title: 'mock-service-worker' },
])
})
MSW를 사용할 때는
http.get('/posts')
나http.delete('/posts/:index')
와 같은 서버 사이드 작업을 명시적으로 정의해야 합니다. MSW는 명시성을 우선시하며, 프로그래밍 방식의 요청 해결을 활용하여 더 복잡한 네트워크 동작을 가능하게 합니다.
Mirage
Mirage는 백엔드 서비스에 의존하지 않고도 완전히 동작하는 자바스크립트 애플리케이션을 구축하고 테스트하며 공유할 수 있게 해주는 API 모킹 라이브러리입니다.
Mirage는 더 복잡한 서버 동작을 에뮬레이트하기 위해 데이터 모델링을 중심으로 설계되었습니다. 반면 Mock Service Worker는 내장된 데이터 모델링 기능을 제공하지 않으며, 대신
@mswjs/data
라는 별도의 패키지로 이를 제공합니다. 이렇게 하면 필요할 때 모델링 기능을 추가할 수 있습니다.
API 지원_V5YUdQJWC56bHj2KqGrwg7
API 타입 | Mirage | Mock Service Worker |
---|---|---|
REST API | ✅ | ✅ |
GraphQL API | ❌ | ✅ |
WebSocket API | ❌ | ✅ |
지원 환경
환경 | Mirage | Mock Service Worker |
---|---|---|
Node.js | ❌ | ✅ |
브라우저 | ✅ | ✅ |
구현
환경 | Mirage | Mock Service Worker |
---|---|---|
브라우저 | fetch 와 XMLHttpRequest 를 몽키 패칭(monkey-patch)하여 사용 (pretender 사용). | 서비스 워커를 사용하여 브라우저 수준에서 요청을 가로챔. |
Integration_E9uewouvTYCzqDUiMGKES3
Mirage | Mock Service Worker |
---|---|
코드 변경 없이 사용 가능. | 코드 변경 없이 사용 가능. |
추가 설정 없이 모든 요청 클라이언트와 호환. | 추가 설정 없이 모든 요청 클라이언트와 호환. |
Definition_bXzPPNjU5qn2WssRUTV55N
Mirage
Mirage는 서버와 유사한 라우트와 모의 응답을 정의하기 위해 라우트 핸들러 형식을 사용합니다.
createServer({
routes() {
this.get('/movies', () => {
return ['Interstellar', 'Inception', 'Dunkirk']
})
},
})
Mirage는 더 복잡한 데이터 관계를 모델링할 수 있도록 메모리 내 데이터베이스를 제공합니다.
createServer({
models: {
movie: Model.extend({
castMembers: hasMany(),
}),
castMember: Model.extend({
movie: belongsTo(),
}),
},
routes() {
// 데이터를 응답하는 라우트 핸들러
},
})
Mock Service Worker_YrsqJPpuZwaEAyuKY6VoFT
MSW는 서버 측 라우팅을 모델로 한 인터셉션 API를 제공하며, Fetch API 명세에 따라 요청과 응답을 처리합니다. 이때 일반적으로 자바스크립트에서 사용하는 동일한 클래스를 활용합니다:
http.get('/movies', () => {
return HttpResponse.json(['Interstellar', 'Inception', 'Dunkirk'])
})
MSW는 기본적으로 데이터 모델링 기능을 제공하지 않지만, @mswjs/data
와 같은 생태계 패키지를 활용해 데이터 중심의 API 모킹 방식을 선택할 수 있습니다.
import { factory, primaryKey, oneOf, manyOf } from '@mswjs/data'
// 데이터 모델링
const db = factory({
movie: {
id: primaryKey(randomUuid),
title: String,
castMembers: manyOf('castMember'),
},
castMember: {
id: primaryKey(randomUuid),
name: String,
movie: oneOf('movie'),
},
})
// 모델을 기반으로 요청 핸들러 생성
// - GET /movies
// - GET /movies/:id
// - POST /movies
// - ...
db.toHandlers('rest')
// GraphQL 쿼리도 포함!
// - query ListMovies
// - query GetMovie
// - mutation AddMovie
// - ...
db.toHandlers('graphql')
Cypress - cy.intercept()
Cypress는 cy.intercept()
API를 통해 API 모킹 기능을 제공하는 엔드투엔드 테스트 프레임워크입니다.
API 지원 비교표
API 타입 | cy.intercept() | Mock Service Worker |
---|---|---|
REST API | ✅ | ✅ |
GraphQL API | ❌1 | ✅ |
WebSocket API | ❌ | ✅ |
1—커스텀 별칭을 통해 GraphQL 요청을 처리할 수 있지만, 여전히 많은 추가 설정이 필요합니다. Cypress는 GraphQL을 퍼스트클래스로 지원하기보다는 HTTP 처리(웹에서 GraphQL이 주로 HTTP를 통해 구현되기 때문)를 통해 GraphQL API 모킹을 구현합니다.
지원 환경_GfVivJ7fwqc2JZYt8h4rAq
API 타입 | cy.intercept() | Mock Service Worker |
---|---|---|
Node.js | ❌1 | ✅ |
브라우저 | ✅ | ✅ |
1—Cypress는 브라우저 테스트 프레임워크이므로, 통합 테스트나 백엔드 애플리케이션과 같은 Node.js 프로세스에서는
cy.intercept()
모킹을 사용할 수 없습니다.
Implementation_DX6taHN8c66gTPp9GQwhcV
환경 | cy.intercept() | Mock Service Worker |
---|---|---|
브라우저 | Cypress 런타임의 일부로 생성된 커스텀 서버를 통해 나가는 요청을 라우팅하기 위해 브라우저 전체 HTTP 프록시를 사용합니다. | 브라우저 수준에서 요청을 가로채기 위해 Service Worker를 사용합니다. |
Integration_LoWuFoKKqfcHGy2Udas7JY
cy.intercept() | Mock Service Worker |
---|---|
코드 변경 없이 사용 가능. Cypress에 기본 내장되어 있음. | 코드 변경 없이 사용 가능. |
추가 설정 없이 모든 요청 클라이언트와 함께 작동. | 추가 설정 없이 모든 요청 클라이언트와 함께 작동. |
Definition_myeZmXhCwWja7NqREQWtpi
cy.intercept()
Cypress는 커스텀 매처 시그니처와 라우트 핸들러 함수를 사용하여 요청을 가로채고 처리합니다. 더 세부적인 요청 제어를 위해 req.reply()
, req.continue()
, req.redirect()
와 같은 커스텀 메서드를 활용합니다.
cy.intercept('POST', '/users', {
statusCode: 201,
body: req.body,
delay: 100,
})
Mock Service Worker_432rVbdnpKhfve7xiEPNvQ
MSW는 서버 측 라우팅을 모델로 하여 인터셉션 API를 설계했으며, Fetch API 명세에 따라 요청과 응답을 처리합니다. 이때 일반적으로 자바스크립트에서 사용하는 동일한 클래스를 사용합니다:
import { http, delay } from 'msw'
http.post('/users', async ({ request }) => {
// 일반적으로 하듯이 요청 본문을 읽습니다.
const user = await request.json()
// 응답 리졸버 실행 흐름을 제어합니다.
// 아래의 "delay" Promise와 같이 Promise를 사용합니다.
await delay(100)
// 일반적으로 하듯이 응답을 구성합니다.
return HttpResponse.json(user, { status: 201 })
})
MSW는 passthrough()
와 bypass()
API를 통해 요청에 대한 더 세밀한 제어를 제공하며, 이는 내부적으로 여전히 의미론적인 HTTP 응답을 생성합니다.
Playwright - page.route()
Playwright는 page.route()
API를 통해 브라우저 테스트 도구로서 API 모킹 기능을 제공합니다.
API 지원_Sns6x7e5vTJULjVgfWhzoF
API 타입 | page.route() | Mock Service Worker |
---|---|---|
REST API | ✅ | ✅ |
GraphQL API | ❌1 | ✅ |
WebSocket API | ✅ | ✅ |
1—GraphQL 요청은 HTTP 요청이므로
page.route()
로 처리할 수 있지만, Playwright는 GraphQL API 모킹을 위한 퍼스트클래스 지원을 제공하지 않습니다.
지원 환경_kAARhUPZAPuwEUJa6YRPpZ
API 타입 | page.route() | Mock Service Worker |
---|---|---|
Node.js | ❌1 | ✅ |
브라우저 | ✅ | ✅ |
1—Playwright를 사용하면 테스트를 Node.js로 작성하지만,
Playwright 자체(및page.route()
)는 생성된 브라우저의 트래픽에만 영향을 미치며,
Node.js 프로세스에는 영향을 주지 않습니다.
Implementation_8eFvKUf8ChratpwVwH4FYa
환경 | page.route() | Mock Service Worker |
---|---|---|
브라우저 | Chrome DevTools Protocol를 사용하여 브라우저 수준에서 요청을 가로챕니다. | Service Worker를 사용하여 브라우저 수준에서 요청을 가로챕니다. |
Integration_HSH8WWwZs2X5PNveHPakYw
page.route() | Mock Service Worker |
---|---|
코드 변경 없이 사용 가능. Playwright에서 기본 제공. | 코드 변경 없이 사용 가능. |
추가 설정 없이 모든 요청 클라이언트와 호환. | 추가 설정 없이 모든 요청 클라이언트와 호환. |
Definition_KmtWoenDAJizzqcheP7BQy
page.route()
Playwright의 page.route()
함수는 route.fulfill()
및 route.continue()
와 같은 커스텀 메서드를 사용하여 요청을 더 세밀하게 제어할 수 있게 해줍니다.
page.route('/fruits', async (route) => {
const request = route.request()
if (request.method === 'POST') {
const response = await route.fetch()
const json = await response.json()
json.push({ name: 'Playwright' })
return route.fulfill({ response, json })
}
route.continue()
})