필사 모드: API 계약 테스트 & API 도구 2026 딥다이브: Pact, Bruno, Hoppscotch, MSW, Karate DSL, Schemathesis 완전 비교
한국어2026년 API 도구 풍경: 왜 다시 계약 테스트인가
2026년 마이크로서비스 팀이 마주한 가장 큰 변화는 두 가지다. 첫째, 2023년 Postman의 SaaS 전면 전환 이후 오프라인/오픈소스 대안인 Bruno와 Hoppscotch가 엔터프라이즈 채택을 가속화했다. 둘째, OpenAPI 3.1과 AsyncAPI 3.0이 안정화되면서 "스키마 우선(schema-first)" 워크플로가 다시 주류가 되었고, Pact 같은 CDC(Consumer-Driven Contracts) 도구가 폴리글랏 환경의 표준 안전망으로 자리잡았다. 이 글은 11가지 도구를 실전 코드와 함께 비교한다.
계약 테스트가 해결하는 진짜 문제
기존 통합 테스트는 두 서비스를 동시에 띄워야 했다. 서비스 수가 50개를 넘어가면 CI는 1시간이 넘고, 한 팀의 배포가 다른 팀을 막는다. 계약 테스트는 "소비자가 기대하는 응답"과 "공급자가 실제 제공하는 응답"을 각자 독립적으로 검증한다. 두 검증이 같은 계약 파일을 통해 만나면 통합은 안전하다. 이것이 ThoughtWorks Tech Radar가 2018년부터 일관되게 Pact를 "Adopt" 단계로 유지하는 이유다.
Pact: CDC의 표준이 된 이유
Pact는 Realestate.com.au에서 시작해 2013년 오픈소스화된 가장 성숙한 CDC 프레임워크다. JS, Java, .NET, Go, Python, Rust, PHP, Swift, Kotlin 클라이언트가 있고 Pact Broker로 계약을 중앙 관리한다. 2026년 현재 Pact 명세 v4는 메시징(Kafka, RabbitMQ)과 GraphQL을 1급 시민으로 다룬다.
// consumer-pact.test.js — Jest + @pact-foundation/pact v15
const { like, integer, decimal, iso8601DateTime } = MatchersV3
const provider = new PactV4({
consumer: 'web-checkout',
provider: 'order-service',
dir: path.resolve(process.cwd(), 'pacts'),
logLevel: 'warn',
})
describe('Order API contract', () => {
it('returns order details', async () => {
await provider
.addInteraction()
.given('order 42 exists')
.uponReceiving('a request for order 42')
.withRequest('GET', '/orders/42', (b) => b.headers({ Accept: 'application/json' }))
.willRespondWith(200, (b) =>
b.jsonBody({
id: integer(42),
total: decimal(199.99),
createdAt: iso8601DateTime('2026-05-01T10:00:00Z'),
items: like([{ sku: 'ABC-1', qty: integer(2) }]),
})
)
.executeTest(async (mockServer) => {
const client = new OrderClient(mockServer.url)
const order = await client.fetch(42)
expect(order.total).toBe(199.99)
})
})
})
소비자 테스트가 통과하면 `pacts/web-checkout-order-service.json` 파일이 생성되고, Pact Broker로 publish된다. 공급자는 `pact-provider-verifier`로 그 계약을 자신의 실제 코드에 대해 재검증한다.
Pact Broker와 can-i-deploy
Pact Broker는 단순한 파일 저장소가 아니다. 핵심은 `can-i-deploy` 명령이다. 어떤 버전의 소비자/공급자가 어떤 환경에 함께 배포 가능한지 매트릭스를 계산해준다. PactFlow는 SaaS형이고, Pact Broker OSS는 self-host용이다. Toss(토스)는 자체 Pact Broker를 운영하며 50개 이상의 마이크로서비스 간 계약을 관리한다고 2024년 SLASH 컨퍼런스에서 공유한 바 있다.
MSW: 브라우저와 Node를 한 번에 모킹
MSW(Mock Service Worker)는 Service Worker API와 Node `http` 인터셉터를 활용해 네트워크 레이어에서 직접 모킹한다. 즉 애플리케이션 코드 한 줄도 바꾸지 않고 진짜 `fetch`/`XHR` 호출을 가로챈다. 2026년 v2부터 OpenAPI 스펙에서 핸들러를 자동 생성하는 `@mswjs/source` 도구가 GA되었다.
// src/mocks/handlers.js — MSW v2
export const handlers = [
http.get('https://api.example.com/orders/:id', async ({ params }) => {
await delay(100)
if (params.id === '404') {
return new HttpResponse(null, { status: 404 })
}
return HttpResponse.json({
id: Number(params.id),
total: 199.99,
items: [{ sku: 'ABC-1', qty: 2 }],
})
}),
http.post('https://api.example.com/orders', async ({ request }) => {
const body = await request.json()
return HttpResponse.json({ id: 99, ...body }, { status: 201 })
}),
]
MSW vs Pact: 보완 관계
흔한 오해는 "MSW로 모킹하면 Pact가 필요 없다"는 것이다. 둘은 보완 관계다. MSW는 소비자 개발/UI 테스트용 임시 모킹이고, Pact는 소비자-공급자 간 계약을 영구적으로 저장하고 양쪽이 동의했는지 검증한다. 이상적인 조합은 MSW 핸들러를 Pact 상호작용에서 자동 생성하는 것이고, Mercari 엔지니어링 블로그가 이 패턴을 2024년에 공유했다.
Bruno: 오프라인 우선의 Postman 대안
Bruno는 2023년 등장해 2025년 v2부터 엔터프라이즈 기능을 갖춘 오픈소스 API 클라이언트다. 가장 큰 차별점은 "컬렉션이 Git에 들어가는 파일"이라는 점이다. JSON이 아닌 Bru 문법을 사용해 diff가 깔끔하고, 클라우드 동기화 없이 팀 협업이 가능하다.
users/get-by-id.bru — Bruno collection file
meta {
name: Get user by id
type: http
seq: 1
}
get {
url: {{baseUrl}}/users/{{userId}}
body: none
auth: bearer
}
auth:bearer {
token: {{accessToken}}
}
vars:pre-request {
userId: 42
}
assert {
res.status: eq 200
res.body.id: eq 42
res.body.email: matches /.+@.+\..+/
}
tests {
test("user has expected role", function() {
expect(res.getBody().role).to.equal("admin")
})
}
Hoppscotch: 브라우저 기반 오픈소스 API 워크벤치
Hoppscotch(전 Postwoman)는 PWA로 동작하는 풀 스택 API 클라이언트다. REST, GraphQL, WebSocket, SSE, MQTT, Socket.IO를 단일 UI에서 다룬다. 2024년부터 Hoppscotch Cloud와 self-hosted 엔터프라이즈 에디션이 분리되었고, EU GDPR 이슈에 민감한 팀이 self-host를 선호한다. SmartHR(스마트HR)이 GraphQL 스키마 탐색에 Hoppscotch를 사내 표준으로 채택한 사례가 공개되어 있다.
Karate DSL: BDD 스타일의 한 줄 API 테스트
Karate는 Intuit가 만든 자바 기반 API 테스트 프레임워크지만, 사용자는 자바 코드를 한 줄도 쓰지 않는다. Gherkin 문법으로 REST, GraphQL, 성능 테스트(Karate Gatling), UI 테스트(Karate UI)까지 가능하다. 2026년 v1.5는 Native Image(GraalVM)를 공식 지원해 CI 부팅 시간을 80% 줄였다.
Feature: Order API contract
Background:
* url 'https://api.example.com'
* header Accept = 'application/json'
Scenario: get order returns expected schema
Given path 'orders', 42
When method get
Then status 200
And match response ==
"""
{
id: 42,
total: '#number',
createdAt: '#regex .+T.+Z',
items: '#[] #object'
}
"""
Scenario: create order
Given path 'orders'
And request { sku: 'ABC-1', qty: 2 }
When method post
Then status 201
And match response.id == '#number'
Schemathesis: OpenAPI에서 자동 생성되는 속성 기반 테스트
Schemathesis는 Hypothesis 위에 만들어진 Python 도구다. OpenAPI/Swagger 또는 GraphQL 스키마를 입력으로 받아 자동으로 수천 개의 엣지 케이스를 생성한다. "유효한 입력에 5xx가 나면 안 된다", "응답이 스키마와 일치해야 한다" 같은 불변식을 검증한다.
Schemathesis CLI 기본 사용
pip install schemathesis
schemathesis run \
--checks all \
--workers 8 \
--hypothesis-deadline 1000 \
--report \
https://api.example.com/openapi.json
CI에서 특정 엔드포인트만 빠르게
schemathesis run \
--include-path-regex '^/orders' \
--max-examples 50 \
--base-url https://staging.example.com \
./openapi.yaml
Schemathesis는 GitLab, Spotify, Bose 등이 도입했다고 공개적으로 밝혔다. 한국에서는 카카오 엔터프라이즈가 2024년 사내 API 게이트웨이 회귀 테스트에 도입했다.
Dredd: 마크다운/OpenAPI에서 직접 돌리는 테스트
Dredd는 Apiary가 만든 가장 오래된 OpenAPI 테스트 도구 중 하나다. API Blueprint 또는 OpenAPI 2.0/3.0 문서를 읽어 각 예제(example)를 실제로 호출하고 응답을 검증한다. 단순하지만 "문서가 거짓말하지 않는다"를 보장하는 데는 강력하다. 2026년 현재 활발한 개발은 줄었지만 안정적이라는 평가다.
Prism: Stoplight의 OpenAPI 목 서버
Prism은 OpenAPI 3.x 문서를 HTTP 목 서버로 즉시 변환한다. 백엔드가 준비되기 전에 프론트엔드가 진짜 같은 응답을 받을 수 있다. `prism mock openapi.yaml`만으로 schema에 정의된 examples와 dynamic 모드를 모두 지원한다. Schemathesis + Prism 조합은 백엔드 없이 OpenAPI 스펙 자체를 회귀 테스트하는 강력한 패턴이다.
RestAssured: Java 진영의 사실상 표준
RestAssured는 자바/그루비 기반 통합 테스트 라이브러리다. JUnit5/TestNG와 자연스럽게 통합되며, Spring Boot Test, WireMock, TestContainers와 결합해 마이크로서비스 통합 시나리오를 한 파일에 담는다. Karate가 BDD라면 RestAssured는 코드 우선이다.
Postman과 Insomnia: SaaS 시대의 현재
Postman은 2024년 v11부터 Postman AI를 추가하며 SaaS 의존도를 더 높였다. Insomnia(Kong 소유)는 2024년 사용자 약관 변경 논란 후 Insomnium이라는 포크가 등장했다. 두 도구 모두 강력하지만, 컬렉션이 클라우드에 묶이고 정책상 self-host 옵션이 제한적이라 금융/공공 분야에서 Bruno/Hoppscotch로의 이탈이 가속됐다.
OpenAPI 3.1: 무엇이 달라졌나
OpenAPI 3.1은 JSON Schema 2020-12과 100% 정렬되었다. 가장 큰 변화는 `nullable` 키워드가 사라지고 `type: ["string", "null"]` 같은 정식 JSON Schema 표현을 쓴다는 점이다. 또 `webhooks` 객체가 추가되어 인바운드 콜백 API도 1급으로 문서화한다.
openapi: 3.1.0
info:
title: Order Service
version: 2.0.0
paths:
/orders/{id}:
get:
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
webhooks:
orderShipped:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ShippedEvent'
responses:
'200':
description: Webhook received
components:
schemas:
Order:
type: object
required: [id, total]
properties:
id:
type: integer
total:
type: number
cancelReason:
type: ['string', 'null']
AsyncAPI 3.0: 이벤트 드리븐 API의 OpenAPI
AsyncAPI 3.0은 2023년 12월 GA되었고, OpenAPI와 동일한 철학을 Kafka, RabbitMQ, MQTT, WebSocket, AMQP에 적용한다. 3.0의 핵심 변화는 채널과 작업(operation)의 분리다. 동일 채널을 send/receive 양방향으로 더 명확하게 문서화할 수 있다. Microcks와 EventCatalog가 AsyncAPI 기반 모의 브로커와 카탈로그를 제공한다.
GraphQL 스키마 테스트
GraphQL은 SDL 자체가 계약이라 OpenAPI보다 계약 테스트가 자연스럽다. 그러나 "응답이 스키마와 일치"하는 것과 "쿼리가 BFF의 비즈니스 요구를 충족"하는 것은 다르다. Apollo GraphOS의 schema-check, GraphQL Inspector, 그리고 Pact의 GraphQL 플러그인이 세 가지 다른 층위에서 답을 제공한다.
CDC vs 통합 테스트 vs 스키마 검증
세 가지를 자주 혼동한다. 스키마 검증(Dredd/Schemathesis/Prism)은 "스펙 자체가 일관되고 응답이 스펙과 맞는지". 계약 테스트(Pact)는 "실제 소비자가 의존하는 부분을 공급자가 깨뜨리지 않는지". 통합 테스트는 "두 서비스를 진짜로 띄워 종단 시나리오 통과하는지". CDC는 통합 테스트의 99%를 대체할 수 있지만 0%는 항상 필요하다.
CI 통합 패턴: Pact + GitHub Actions
name: api-contract
on: [push, pull_request]
jobs:
consumer-contract:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run test:pact
- name: Publish pacts
if: github.ref == 'refs/heads/main'
env:
PACT_BROKER_BASE_URL: https://broker.example.com
PACT_BROKER_TOKEN: $PACT_TOKEN
run: npx pact-broker publish ./pacts --consumer-app-version=$GITHUB_SHA --branch=main
- name: Can I deploy
run: npx pact-broker can-i-deploy --pacticipant web-checkout --version $GITHUB_SHA --to-environment production
도구 선택 매트릭스
| 도구 | 카테고리 | 오픈소스 | REST | GraphQL | 메시징 | 강점 |
|------|---------|---------|------|---------|--------|------|
| Pact | CDC | Yes | Yes | Yes | Yes | 양방향 계약, Broker |
| MSW | 모킹 | Yes | Yes | Yes | No | 브라우저+Node 통합 |
| Bruno | 클라이언트 | Yes | Yes | Yes | WS | Git 친화 |
| Hoppscotch | 클라이언트 | Yes | Yes | Yes | WS/MQTT/SSE | PWA, 다중 프로토콜 |
| Karate | E2E | Yes | Yes | Yes | Kafka | BDD DSL |
| Schemathesis | 퍼징 | Yes | Yes | Yes | No | 속성 기반 자동 생성 |
| Dredd | 스펙 검증 | Yes | Yes | No | No | 단순함 |
| Prism | 목 서버 | Yes | Yes | No | No | OpenAPI에서 즉시 |
| RestAssured | 코드 테스트 | Yes | Yes | Yes | No | JUnit 통합 |
| Postman | SaaS 클라이언트 | No | Yes | Yes | WS/gRPC | 거대 생태계 |
| Insomnia | SaaS 클라이언트 | 일부 | Yes | Yes | gRPC | 깔끔한 UI |
한국/일본 사례: 토스, 카카오, 메르카리, Cybozu
토스는 50+ 마이크로서비스 환경에서 Pact + Pact Broker를 표준화했고, 자체 Slack 봇으로 `can-i-deploy` 결과를 자동 알림한다(2024 SLASH 발표). 카카오 엔터프라이즈는 카카오워크 API 회귀에 Schemathesis를 도입했다. 메르카리는 메시지 큐 기반 CDC를 위해 Pact Message + Karate Kafka를 조합했다. Cybozu는 kintone 공개 API 문서를 OpenAPI 3.1로 전면 마이그레이션하면서 Prism 목 서버를 외부 개발자용으로 호스팅한다.
안티패턴: 무엇을 하지 말아야 하나
첫째, Pact를 통합 테스트처럼 쓰지 말 것. Pact는 양쪽 서비스를 동시에 띄우면 안 된다. 둘째, OpenAPI 스펙이 코드에서 멀어진 채 손으로 관리되면 계약 테스트가 거짓말이 된다. tRPC, Zod, openapi-fetch 같은 타입 우선 도구로 코드와 스펙을 동기화하라. 셋째, Schemathesis로 production을 두드리지 말 것. 항상 staging이나 격리된 환경에서.
폴리글랏 환경의 표준 스택 제안
2026년 현실적인 표준 조합: 프론트엔드 개발/UI 테스트는 MSW, 소비자-공급자 계약은 Pact + Pact Broker, OpenAPI 스펙은 Schemathesis로 회귀 테스트, 백엔드가 없을 때는 Prism으로 모킹, 팀의 일상적인 API 탐색은 Bruno(Git 친화) 또는 Hoppscotch(PWA). E2E는 Karate 또는 RestAssured. Postman은 외부 파트너 데모용으로만.
마이그레이션 체크리스트
Postman → Bruno로 옮길 때: Bruno CLI의 `import postman-collection` 명령으로 컬렉션 변환. 환경 변수는 `bru` 파일의 `vars` 블록으로 옮겨진다. WireMock → MSW: WireMock 스텁 매핑을 MSW 핸들러로 1:1 매핑하는 자동 변환기는 아직 없으니 수동. Dredd → Schemathesis: Dredd의 단순 예제 검증을 넘어 속성 기반으로 확장하려면 `--checks all` 옵션부터 시작. OpenAPI 3.0 → 3.1: `nullable: true`를 `type: ["string","null"]`로 치환. `openapi-format` 도구가 변환을 자동화한다.
결론: 계약을 코드처럼 다루기
API 계약 테스트의 본질은 "스펙이 코드와 동시에 변하고, 동시에 검증된다"는 점이다. 2026년 도구 풍경은 충분히 성숙했다. 빠진 것은 도구가 아니라 팀의 합의다. 소비자가 무엇을 기대하는지, 공급자가 무엇을 보장하는지, 그 사이를 누가 기록할지. Pact든 Schemathesis든 도구는 그 합의를 영구 기록할 뿐이다.
References
- Pact 공식 문서: https://docs.pact.io/
- Pact Broker: https://github.com/pact-foundation/pact_broker
- MSW 공식: https://mswjs.io/
- Bruno 공식: https://www.usebruno.com/
- Hoppscotch 공식: https://hoppscotch.io/
- Karate DSL: https://github.com/karatelabs/karate
- Schemathesis 문서: https://schemathesis.readthedocs.io/
- Dredd 공식: https://dredd.org/
- Stoplight Prism: https://stoplight.io/open-source/prism
- OpenAPI Initiative: https://www.openapis.org/
- OpenAPI 3.1 명세: https://spec.openapis.org/oas/v3.1.0
- AsyncAPI 공식: https://www.asyncapi.com/
- RestAssured: https://rest-assured.io/
- ThoughtWorks Tech Radar: https://www.thoughtworks.com/radar/techniques/consumer-driven-contract-testing
- Microcks: https://microcks.io/
- Postman: https://www.postman.com/
현재 단락 (1/226)
2026년 마이크로서비스 팀이 마주한 가장 큰 변화는 두 가지다. 첫째, 2023년 Postman의 SaaS 전면 전환 이후 오프라인/오픈소스 대안인 Bruno와 Hoppscotc...