Swagger와 Postman 간의 드리프트는 프로세스 실패가 아닙니다. 동일한 API 계약을 openapi.yaml과 Postman 컬렉션이라는 두 곳에 저장하고, 두 아티팩트를 자동으로 동기화하는 메커니즘이 없을 때 자연스럽게 발생합니다. OpenAPI 스펙을 작성하고, Swagger UI로 문서화한 뒤, 테스트를 위해 Postman 컬렉션을 내보냅니다. 일주일 후 누군가 YAML은 수정하지 않고 컬렉션의 엔드포인트만 변경하면, 문서와 테스트는 서로 다른 API를 설명하게 됩니다. 스펙에서 테스트를 생성하는 단계별 방법은 OpenAPI 테스트 생성에 대한 기존 방법 가이드를 참조하십시오.
💡 Apidog를 사용하는 팀은 OpenAPI 파일을 문서, 모의(mock), 테스트를 동시에 구동하는 단일 아티팩트로 취급합니다. 구조적인 해결책은 더 엄격한 검토 프로세스가 아니라, 애초에 드리프트를 유발할 수 있는 두 번째 아티팩트를 제거하는 것입니다.
두 파일이 항상 동기화되지 않는 이유
일반적인 API 리포지토리에는 다음 두 가지가 함께 존재합니다.
openapi.yaml- Postman 컬렉션
두 파일은 같은 API 계약을 설명하지만, 별도로 저장되고, 다른 사람이 편집하며, 다른 시점에 업데이트됩니다. 문제는 어떤 도구도 두 파일 간의 일관성을 강제하지 않는다는 점입니다.
예를 들어 백엔드 팀이 다음 엔드포인트를 출시한다고 가정해 봅시다.
POST /payments/refund
Content-Type: application/json
요청 본문에는 새 필수 필드인 reason이 포함됩니다.
{
"transaction_id": "txn_8x9Ka21",
"reason": "requested_by_customer"
}
QA 또는 백엔드 개발자는 테스트를 위해 Postman 컬렉션에 이 요청을 추가합니다. 하지만 openapi.yaml 업데이트는 스프린트 백로그에 남습니다.
3일 후 프런트엔드 개발자는 Swagger 문서를 보고 reason 없이 API를 호출합니다.
{
"transaction_id": "txn_8x9Ka21"
}
결과는 문서만으로는 설명할 수 없는 400 Bad Request입니다.
근본 원인은 태만이 아닙니다. 두 아티팩트 사이에 바인딩이 없기 때문입니다. Swagger UI는 YAML만 알고, Postman은 컬렉션만 압니다.
| 아티팩트 | 업데이트 담당자 | 업데이트 트리거 | 유효성 검사 |
|---|---|---|---|
openapi.yaml |
API 설계자 / 기술 리드 | 예정된 문서 스프린트 | 선택적 린터, 예: Spectral |
| Postman 컬렉션 | QA / 백엔드 개발자 | 테스트 실행 필요 시 | 수동 검토 또는 없음 |
| Swagger UI 보기 | YAML에서 자동 렌더링 | YAML 푸시 시에만 | YAML을 반영하지만, 실제 구현은 반영하지 않음 |
단일 Spectral 린터를 YAML에 실행해도 스키마 오류만 잡을 수 있습니다. YAML과 Postman 컬렉션이 서로 다른 요청을 보내고 있는지는 확인하지 못합니다.
세 개의 복사본 문제
Stoplight 같은 별도 문서화 플랫폼까지 사용하면 계약 복사본은 세 개가 됩니다.
- Git에 커밋된
openapi.yaml - 워크스페이스로 내보내고 공유한 Postman 컬렉션
- Stoplight, Swagger UI, 위키 등에 렌더링된 문서
각 복사본은 독립적으로 드리프트될 수 있습니다.
OpenAPI Specification은 동기화 프로토콜이 아니라 설명 형식입니다. YAML에 원하는 API를 기술할 수는 있지만, Postman 컬렉션이 다른 방식으로 동작하는 것을 막지는 못합니다.
즉, 계약이 세 곳에 존재하면 다음도 세 개가 됩니다.
- 실패 지점
- 수동 동기화 루프
- 리뷰해야 할 변경 경로
서비스 수와 팀 규모가 커질수록 유지보수 비용은 선형이 아니라 비선형으로 증가합니다.
드리프트가 테스트를 조용히 망가뜨리는 방법
Swagger와 Postman 드리프트의 위험한 점은 테스트가 틀렸는데도 계속 통과할 수 있다는 것입니다.
예를 들어 OpenAPI 스펙은 v2로 변경되었습니다.
# openapi.yaml - 업데이트된 스펙 (v2)
paths:
/payments/refund:
post:
summary: Initiate a refund
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- transaction_id
- reason # v2에서 추가된 새로운 필수 필드
properties:
transaction_id:
type: string
example: "txn_8x9Ka21"
reason:
type: string
enum: [duplicate, fraudulent, requested_by_customer]
example: "requested_by_customer"
responses:
'200':
description: Refund initiated
content:
application/json:
schema:
type: object
properties:
refund_id:
type: string
status:
type: string
하지만 Postman 컬렉션은 여전히 v1 요청을 보냅니다.
{
"transaction_id": "txn_8x9Ka21"
}
백엔드가 마이그레이션 기간 동안 reason에 기본값을 넣어주면 Postman 테스트는 계속 녹색으로 통과합니다. 그러나 실제 스펙은 reason을 필수로 요구합니다.
이 상태에서는 다음 문제가 발생합니다.
- 테스트는 통과함
- Swagger 문서는 최신 스펙을 표시함
- Postman 컬렉션은 오래된 요청을 보냄
- 프런트엔드 통합은 스테이징에서 실패함
OpenAPI 유효성 검사 도구를 YAML에 실행하면 스펙 내부의 스키마 불일치는 잡을 수 있습니다. 하지만 스펙과 Postman 컬렉션이 실제로 보내는 요청 간의 차이는 잡지 못합니다.
OpenAPI 기반 테스트의 실제 의미
OpenAPI 기반 테스트는 스펙을 신뢰할 수 있는 소스로 둔다는 뜻입니다.
핵심은 테스트를 스펙과 병렬로 작성하지 않는 것입니다. 테스트는 스펙에서 파생되어야 합니다.
올바른 흐름은 다음과 같습니다.
-
openapi.yaml을 Git에 정식 계약으로 저장합니다. - 도구가 해당 파일을 읽습니다.
- 문서, 모의(mock), 테스트 케이스를 같은 파일에서 생성합니다.
- PR에서 스펙이 변경되면 파생 출력물도 함께 변경됩니다.
- 동기화해야 할 별도 컬렉션을 만들지 않습니다.
이는 “Swagger를 Postman으로 가져오기”와 다릅니다.
가져오기는 일회성 복사입니다.
openapi.yaml
└── import
└── Postman collection
가져오는 순간에는 동일해 보이지만, 이후 두 아티팩트는 다시 독립적으로 변경됩니다. 다음 스펙 변경 시 다시 가져오거나 컬렉션을 수동으로 수정해야 합니다. 즉, 드리프트를 해결한 것이 아니라 드리프트 타이머를 0으로 되돌린 것뿐입니다.
진짜 스펙 우선 실행은 다음 구조에 가깝습니다.
openapi.yaml
├── interactive docs
├── mock server
└── test suite
스펙 우선 API 개발 모델은 더 넓은 워크플로우 철학을 설명합니다. 이 글은 문서와 테스트 간 드리프트 문제에 집중합니다.
단일 스펙 위에 있는 실행 계층으로서의 Apidog
Apidog의 모델은 Git을 진실의 원천으로 두고, Apidog를 그 위의 실행 계층으로 사용하는 방식입니다.
기본 흐름은 다음과 같습니다.
Git repository
└── openapi.yaml
├── Apidog interactive docs
├── Apidog mock server
└── Apidog test suite
openapi.yaml을 커밋하면 Apidog는 해당 파일을 읽고 다음 출력물을 생성합니다.
- 대화형 문서
- 모의 서버
- 테스트 스위트
Apidog의 스펙 우선 모드(현재 베타 중)는 이러한 워크플로우를 위해 설계되었습니다. OpenAPI 파일을 지정하면 별도 컬렉션을 유지하지 않고도 문서, 모의, 테스트를 같은 소스에서 파생합니다.
실제 효과는 간단합니다.
- 드리프트될 Postman 컬렉션이 없습니다.
- 업데이트할 파일은 하나입니다.
- 문서, 모의, 테스트가 같은 계약을 읽습니다.
OpenAPI 스펙 동기화 워크플로우는 GitHub에 스펙을 커밋하고 Apidog를 정렬 상태로 유지하는 방법을 다룹니다.
Postman 중심 워크플로우에서 전환하는 팀은 POC에서 다음 항목을 확인하는 것이 좋습니다.
- 기존 스키마 복잡도를 Apidog 테스트가 어떻게 처리하는지
- 데이터 기반 테스트 시나리오를 표현할 수 있는지
- 보고서 가시성 및 권한 모델이 조직의 액세스 정책과 맞는지
- 기존 CI 흐름에 어떻게 연결할지
API 모의(mocking)도 중요합니다. 모의가 테스트와 같은 스펙에서 파생되면 프런트엔드 개발자가 받는 응답과 테스트가 검증하는 응답이 일치합니다. 자세한 사용 시나리오는 API 모의 사용 사례를 참조하십시오.
마이그레이션 경로의 모습
Swagger + Postman 설정에서 전환할 때 한 번에 모든 것을 대체할 필요는 없습니다. 안전한 순서는 다음과 같습니다.
1. 현재 스펙과 컬렉션을 비교합니다
먼저 openapi.yaml과 Postman 컬렉션을 비교합니다.
확인할 항목은 다음과 같습니다.
- 스펙에는 있지만 컬렉션에는 없는 엔드포인트
- 컬렉션에는 있지만 스펙에는 없는 엔드포인트
- 요청 본문 스키마 차이
- 필수 필드 차이
- 응답 코드 차이
- 인증 방식 차이
예를 들어 다음과 같은 체크리스트를 사용할 수 있습니다.
[ ] 모든 path가 양쪽에 존재하는가?
[ ] method가 동일한가?
[ ] required 필드가 동일한가?
[ ] enum 값이 동일한가?
[ ] response status code가 동일한가?
[ ] auth header가 동일한가?
2. 스펙을 실제 API 기준으로 정리합니다
openapi.yaml은 처음 설계한 API가 아니라 현재 운영 중인 API를 설명해야 합니다.
오래된 스펙을 기준으로 테스트를 생성하면 오래된 테스트만 자동화됩니다. 먼저 현실과 스펙을 맞춰야 합니다.
3. 스펙을 Apidog로 가져옵니다
정리한 OpenAPI 파일을 Apidog로 가져옵니다. 이후 Apidog가 스펙 구조에서 초기 테스트 스위트를 생성하도록 합니다.
4. 한 스프린트 동안 병렬 실행합니다
기존 Postman 컬렉션과 Apidog 기반 테스트를 한 스프린트 정도 병렬로 실행합니다.
비교할 항목은 다음과 같습니다.
- 실패 케이스 차이
- 누락된 테스트 케이스
- 테스트 데이터 구성 방식
- CI 실행 시간
- 리포트 가시성
5. Postman 컬렉션을 보관합니다
검증이 끝나면 Postman 컬렉션을 계약 테스트의 소스로 사용하지 않습니다. 필요하다면 읽기 전용으로 보관합니다.
이후 구조는 다음과 같이 단순해집니다.
Git openapi.yaml = source of truth
Apidog = execution layer
1단계가 보통 가장 어렵습니다. 그동안 두 아티팩트가 얼마나 멀어졌는지 드러나기 때문입니다. 드리프트가 6개월 이상 누적된 팀은 20~40%의 엔드포인트 커버리지 격차를 발견하는 경우도 있습니다.
스펙에서 초기 테스트 컬렉션을 생성하는 상세 절차는 OpenAPI 스펙에서 테스트 컬렉션 생성 가이드에서 다룹니다.
비교: 이중 유지보수 vs. 스펙 기반
| 측면 | Swagger + Postman, 이중 유지보수 | OpenAPI 기반, 스펙이 소스 |
|---|---|---|
| 드리프트 위험 | 높음. 두 아티팩트가 독립적으로 업데이트됨 | 낮음. 하나의 아티팩트에서 출력물 파생 |
| 테스트 커버리지 정확성 | 수동 동기화 규율에 의존 | 스펙 변경 사항을 자동으로 추적 |
| 신규 개발자 온보딩 | 두 도구와 두 데이터 모델을 이해해야 함 | 하나의 스펙을 중심으로 이해 |
| CI/CD 통합 | 컬렉션을 별도로 내보내고 버전 관리해야 함 | Git의 스펙을 직접 읽음 |
| 모의 일관성 | 모의를 별도로 유지하거나 가져와야 함 | 모의가 테스트와 같은 스펙에서 파생됨 |
| 스키마 변경 비용 | 스펙 업데이트 + 컬렉션 업데이트 + 모의 업데이트 | 스펙 한 번 업데이트 |
이 비교는 Postman 자체의 실패를 의미하지 않습니다. Postman은 컬렉션 기반 테스트에 강하고 생태계도 큽니다.
문제는 컬렉션을 파생 아티팩트가 아니라 병렬 계약으로 취급하는 워크플로우입니다.
구현 체크리스트
Swagger + Postman 드리프트를 줄이려면 다음 순서로 진행하십시오.
1. openapi.yaml을 정식 계약으로 선언
2. Postman 컬렉션을 계약 소스로 사용하지 않도록 결정
3. 현재 컬렉션과 스펙 차이 감사
4. 스펙을 실제 API 동작에 맞게 수정
5. 문서, mock, test를 같은 스펙에서 생성
6. CI에서 스펙 기반 테스트 실행
7. 컬렉션은 탐색적 테스트 용도로만 제한
PR 리뷰에서는 다음 항목을 확인하는 것이 좋습니다.
[ ] API 구현 변경과 openapi.yaml 변경이 같은 PR에 포함되어 있는가?
[ ] required 필드 변경이 테스트에 반영되는가?
[ ] response schema 변경이 문서에 반영되는가?
[ ] mock 응답이 같은 스펙에서 파생되는가?
[ ] 별도 Postman 컬렉션 수정이 필요한 구조인가?
마지막 항목의 답이 “예”라면 아직 이중 유지보수 구조가 남아 있는 것입니다.
자주 묻는 질문
Swagger를 Postman으로 가져오는 것이 드리프트를 해결하지 못하는 이유는 무엇입니까?
가져오기는 특정 시점의 복사본을 생성합니다. 가져온 후에는 openapi.yaml과 Postman 컬렉션이 독립적으로 변경됩니다.
다음 스펙 변경은 컬렉션에 자동으로 전파되지 않습니다. 결국 매번 다시 가져오거나 컬렉션을 수동으로 수정해야 하며, 이는 이중 유지보수 문제로 돌아가는 것입니다.
스펙 우선 모델을 채택하면서도 탐색적 테스트를 위해 Postman을 계속 사용할 수 있습니까?
네. 스펙 우선 방식은 애드혹 테스트를 금지하지 않습니다.
실무적으로는 다음처럼 역할을 나누면 됩니다.
- 자동화된 회귀 테스트: 스펙 기반 러너
- 계약 검증: OpenAPI 스펙
- 일회성 탐색적 호출: Postman 사용 가능
핵심은 탐색적 컬렉션을 계약 검증의 진실의 원천으로 커밋하지 않는 것입니다.
내 스펙이 실제 API 구현과 달라졌는지 어떻게 알 수 있습니까?
가장 신뢰할 수 있는 방법은 계약 테스트 계층을 두는 것입니다. API 서버는 테스트 시점에 들어오는 요청과 나가는 응답을 OpenAPI 스펙에 대해 검증할 수 있습니다.
Spectral 같은 도구는 스펙 내부 일관성을 린트합니다. 하지만 실제 구현과 스펙의 차이를 잡으려면 런타임 유효성 검사가 필요합니다.
이는 Swagger-Postman 드리프트와는 별개의 문제입니다. 하지만 두 문제가 동시에 존재하면 디버깅 비용이 더 커집니다.
Apidog가 Postman을 완전히 대체합니까?
팀의 워크플로우에 따라 다릅니다.
Apidog는 단일 워크스페이스에서 설계, 모의(mocking), 테스트, 문서를 처리합니다. Postman의 주요 용도가 계약 테스트와 회귀 스위트라면 Apidog가 해당 영역을 다룰 수 있습니다.
반대로 팀이 CI에서 Postman 컬렉션 러너를 사용하거나 광범위한 컬렉션 스크립트를 이미 보유하고 있다면, 스펙 우선 설계 워크플로우와 함께 Postman을 사용한 테스트를 유지하는 것도 선택지입니다.
가장 안전한 접근은 한 스프린트 동안 두 방식을 비교 평가하는 것입니다.
내 openapi.yaml이 이미 오래되었다면 어떻게 해야 합니까?
먼저 스펙을 현실에 맞춰야 합니다. 지름길은 없습니다.
순서는 다음과 같습니다.
- 실제 API 동작을 확인합니다.
- 기존 Postman 컬렉션과 비교합니다.
-
openapi.yaml을 현재 API 기준으로 수정합니다. - 수정된 스펙을 정식 소스로 선언합니다.
- 이후 문서, 모의, 테스트를 해당 스펙에서 파생합니다.
오래된 스펙을 자동화하면 오래된 계약만 더 빠르게 실행할 뿐입니다.
결론
Swagger 문서와 Postman 컬렉션이 드리프트되는 이유는 두 개의 별도 아티팩트가 서로 바인딩되지 않았기 때문입니다. 이는 팀 규율 문제가 아니라 이중 유지보수 워크플로우의 구조적 특성입니다.
해결책은 두 번째 계약 아티팩트를 제거하는 것입니다.
하나의 OpenAPI 파일
├── 문서
├── mock
└── 테스트
Git에 하나의 OpenAPI 파일을 두고, 문서와 모의(mock), 테스트를 그 파일에서 파생하십시오. 그러면 Swagger 문서와 Postman 컬렉션을 수동으로 맞추는 작업이 사라집니다.
Apidog를 다운로드하고 기존 OpenAPI 스펙을 가져오세요. 하나의 파일이 문서, 모의, 테스트를 같은 소스에서 구동하는 방식을 직접 확인할 수 있습니다. 스펙 우선 모드(현재 베타 중)를 평가 중이라면 Apidog 스펙 우선 모드 페이지에서 현재 기능 범위와 접근 세부 정보를 확인하십시오.

Top comments (0)