OpenAPI Diff
OpenAPI diff는 API 명세의 두 버전 — 기존 계약과 새 계약 — 을 비교해 실제로 무엇이 바뀌었는지 보고합니다: 제거된 엔드포인트, 필수가 된 매개변수, 타입이 바뀐 필드, 사라진 열거값. 아래에 두 명세를 불러오거나 붙여 넣으면 이 페이지는 모든 변경을 파괴적 또는 비파괴적으로 분류합니다. 공급업체 업그레이드나 자신의 릴리스가 운영 환경에 닿기 전에 판단할 수 있습니다. 두 파일 모두 이 페이지, 여러분의 기기에서 파싱됩니다 — 아무것도 업로드되지 않습니다. 명세에는 남의 서버에 올리고 싶지 않은 내부 엔드포인트가 적혀 있는 경우가 많으므로 중요한 점입니다. 용어가 낯설다면, 짝을 이루는 글 파괴적 API 변경 설명에서 여기서 쓰는 모든 용어를 정의합니다.
마지막 업데이트:
이전 명세 (클라이언트가 오늘 사용하는 계약)
이 패널의 아무 곳에나 파일을 놓거나, 파일을 선택하거나, 텍스트를 붙여 넣으세요. 파싱은 로컬에서 이뤄지며, 어떤 것도 이 기기를 떠나지 않습니다.
새 명세 (후보 계약)
이 패널의 아무 곳에나 파일을 놓거나, 파일을 선택하거나, 텍스트를 붙여 넣으세요. 파싱은 로컬에서 이뤄지며, 어떤 것도 이 기기를 떠나지 않습니다.
비교 결과
요약이 클립보드에 복사됐습니다.
이 비교 도구가 검사하는 것 — 그리고 "파괴적"의 진짜 의미
변경이 파괴적인 경우는, 이전 명세에 맞게 올바르게 작성된 클라이언트가 자신의 코드를 한 줄도 바꾸지 않고 새 명세에서 실패할 수 있을 때입니다. 이 페이지의 모든 판정은 이 정의를 따릅니다. 경로나 작업을 제거하는 것은 파괴적입니다. 기존 호출이 갈 곳이 없어지기 때문입니다. 응답 상태 — 특히 2xx — 를 제거하는 것은 파괴적입니다. 클라이언트의 오류 처리가 기존 상태 집합을 전제로 작성됐기 때문입니다. 필수 매개변수나 필수 요청 속성을 추가하는 것은 파괴적입니다. 어제까지 유효하던 요청이 갑자기 거부되기 때문입니다. 필드의 타입이나 형식을 바꾸는 것은 파괴적입니다. 파서, 검증기, 생성된 SDK가 모두 선언된 타입을 전제로 하기 때문입니다. 열거값을 제거하는 것은 파괴적입니다. 클라이언트가 그 값을 여전히 보낼 수도 있고, 더 이상 해석할 수 없는 데이터를 저장하고 있을 수도 있기 때문입니다. 그 외의 모든 것 — 새 엔드포인트, 선택적 매개변수, 새 응답 필드, 새 열거값, 새 상태 코드 — 은 비파괴적으로 보고됩니다. 기존 클라이언트는 계속 동작합니다. 새 기능을 아직 쓰지 못하더라도 말입니다.
비교는 텍스트가 아니라 구조로 이뤄집니다. 두 문서는 비교 전에 같은 모델로 정규화됩니다. 각 경로와 작업, 이름과 위치로 색인된 매개변수, 요청 본문과 각 응답은 스키마 서명으로 축소됩니다. 이는 타입, 형식, 속성 이름, 필수 목록, 열거값으로 재귀적으로 구축되는 결정적 요약이며, 로컬 $ref 참조는 해석됩니다. 그래서 키 순서를 바꾸거나 공백을 다시 포맷하거나 모든 설명을 다시 써도 diff는 비어 있습니다. 그런 것들은 계약을 바꾸지 않기 때문입니다. 그리고 참조되는 스키마 세 단계 깊이 묻힌 변경도 찾아냅니다. 서명은 참조의 이름을 비교하는 것이 아니라 참조를 펼치기 때문입니다.
생태계가 두 형식을 모두 게시하므로 입력 형식은 두 가지를 받습니다. 먼저 JSON으로 시도하고, 실패하면 YAML로 파싱합니다. 손으로 쓴 OpenAPI 문서 대부분이 YAML을 사용합니다. Swagger 2.0 문서도 동작하며, in: body 매개변수와 응답별 스키마를 포함합니다. 의도적으로 실시간 가져오기도, 업로드도 없습니다. HAR 캡처와 똑같이 문서를 붙여 넣거나 파일을 놓으세요. 비교는 키를 누를 때마다가 아니라 버튼을 누를 때 실행되므로, 붙여 넣은 두 개의 큰 명세도 반응성을 유지합니다.
결과를 장식이 아니라 릴리스 게이트로 사용하세요. 리뷰에서 파괴적 목록이 곧 안건입니다. 각 항목에는 수정, 버전 올림, 사용 중단 기간, 또는 "파괴는 의도됐으며 공지됐다"는 서면 결정 중 하나가 필요합니다. 비파괴적 목록은 변경 로그의 초안입니다. diff를 JSON으로 내보내면 그 결정을 릴리스 옆에 보관할 수 있고, 복사 가능한 요약은 풀 리퀘스트에 바로 들어갑니다. 페이로드가 조용히 바뀌면 모든 구독자가 한 번에 깨지는 webhook 계약 변경에 적용할 것과 같은 규율입니다.
정직한 한계를 분명히 말합니다. 이 비교 도구는 선언된 계약을 비교합니다. 명세가 선언하지 않은 동작은 볼 수 없습니다. 타입은 그대로인데 의미가 바뀐 필드, 새 비즈니스 규칙, 더 엄격한 속도 제한, 클라이언트가 (현명하지 못하게) 파싱하던 오류 메시지 같은 것들입니다. 로컬 참조를 따라가며 제한된 깊이까지 스키마를 비교하므로, 병적으로 깊게 중첩되거나 서로 재귀하는 스키마는 무한히 펼쳐지지 않고 요약됩니다. 그리고 파괴적 변경이 0건인 diff는 업그레이드가 안전하다는 약속이 아닙니다. 문서화된 계약이 유지됐다는 증거이며, 바로 그것이 배포 전에 가질 가치가 있는 증거입니다.
이 페이지가 판정에 사용하는 분류표
| 경로 또는 작업 제거 | 파괴적. 더 이상 존재하지 않는 엔드포인트에 대한 호출은 곧바로 실패합니다. 기존 클라이언트가 그대로 동작하게 할 호환 방법은 없습니다. |
| 응답 상태 제거 | 파괴적. 클라이언트의 재시도, 오류 처리, 모니터링 로직은 선언된 상태 집합을 전제로 작성됩니다. 2xx를 잃는 것이 가장 심각한 형태입니다. |
| 매개변수가 필수가 됨 / 필수 필드 추가 | 파괴적. 이전 명세에서 유효하던 요청이 새 명세에 거부되므로, 기존 클라이언트는 모두 엔드포인트를 호출할 수 있게 되기 전에 바뀌어야 합니다. |
| 타입 또는 형식 변경 | 파괴적. 파서, 검증기, 생성된 SDK는 선언된 타입으로 구축됩니다. integer에서 string으로(또는 int32에서 int64로) 바뀌면, 와이어 값이 비슷해 보여도 엄격한 클라이언트가 깨집니다. |
| 속성 제거 (요청 또는 응답) | 파괴적. 클라이언트가 보내는 요청 속성은 무시되거나 거부되고, 클라이언트가 읽는 응답 속성은 그 코드 안에서 null이 되거나 사라집니다. |
| 열거값 제거 | 파괴적. 클라이언트가 제거된 값을 여전히 보낼 수도 있고, 그 값을 쓰는 저장된 데이터를 갖고 있을 수도 있습니다. 추가된 열거값은 비파괴적이며 따로 보고됩니다. |
| 추가 | 비파괴적. 새 경로, 작업, 선택적 매개변수, 선택적 요청 속성, 응답 속성, 응답 상태, 열거값은 이전에 유효하던 상호작용을 절대 무효화하지 않습니다. |
자주 묻는 질문
제 명세 파일이 어딘가에 업로드되나요?
아니요. 두 문서 모두 이 페이지, 여러분의 기기에서 파싱되고 비교됩니다. 비교는 네트워크 요청을 만들지 않으며 아무것도 저장되지 않습니다. 이는 의도적인 규칙입니다. 명세는 내부 및 문서화되지 않은 엔드포인트까지 포함한 여러분 API의 지도이며, 비교하려면 업로드하라고 요구하는 도구는 바로 비공개로 지켜야 할 그 지도를 수집하는 셈이기 때문입니다.
어떤 형식을 받나요?
OpenAPI 3.x와 Swagger 2.0이며, JSON 또는 YAML입니다. 텍스트는 먼저 JSON으로 시도되고 실패하면 YAML로 파싱됩니다. 문서가 명세로 인식되려면 paths 객체가 있어야 합니다. 그 외의 것은 조용히 빈 diff를 내는 대신 "명세가 아님"으로 보고됩니다.
여기서 무엇이 파괴적 변경에 해당하나요?
올바르게 작성된 기존 클라이언트를 실패하게 만들 수 있는 모든 것입니다: 경로, 작업, 응답 상태의 제거; 필수로 바뀐 매개변수나 요청 속성; 타입이나 형식의 변경; 요청 또는 응답 속성의 제거; 열거값의 제거. 선택적인 것을 추가하는 것은 비파괴적입니다. 설명, 제목, 포맷의 변경은 완전히 무시됩니다 — 계약 변경이 아니기 때문입니다.
참조되는 스키마는 어떻게 처리되나요?
#/components/schemas/Pet 같은 로컬 참조(또는 Swagger 2.0의 #/definitions/Pet)는 서명을 만들 때 해석되므로, 공유 스키마 내부의 변경은 그것을 사용하는 모든 작업에 보고됩니다. 해석은 깊이가 제한되고 순환에 안전하므로, 재귀 스키마가 비교를 멈추게 할 수 없습니다.
결과를 보관하거나 공유할 수 있나요?
네. 다운로드 버튼은 전체 diff를 JSON으로 내보냅니다 — 요약 카운트와 함께 심각도, 종류, 경로, 메서드, 구조화된 세부 정보를 가진 모든 변경을 포함합니다. 복사 버튼은 풀 리퀘스트나 릴리스 노트용 일반 텍스트 요약을 만듭니다. 둘 다 방금 실행한 비교에서 로컬로 생성됩니다.