DEV Community

Cover image for Git으로 OpenAPI 스펙 버전 관리하는 방법
Rihpig
Rihpig

Posted on • Originally published at apidog.com

Git으로 OpenAPI 스펙 버전 관리하는 방법

OpenAPI 스펙은 API 계약입니다. 스펙이 변경되면 클라이언트가 오작동하거나, 목업이 실제 API와 달라지거나, 더 이상 존재하지 않는 API에 대한 테스트가 계속 통과할 수 있습니다. 따라서 OpenAPI 스펙도 코드처럼 Git에 저장하고, 브랜치로 변경하고, PR에서 검토하고, CI에서 검증해야 합니다.

오늘 Apidog를 사용해 보세요

이 글에서는 Git을 사용해 OpenAPI 스펙을 버전 관리하는 실무 흐름을 정리합니다. 스펙 파일 위치, 브랜치 전략, PR 검토 기준, CI 유효성 검사, Apidog에서 변경 사항을 커밋하고 푸시하는 방법까지 다룹니다.

OpenAPI 스펙을 버전 관리해야 하는 이유

위키나 공유 드라이브에 있는 스펙은 변경 이력을 추적하기 어렵습니다. 누가 POST /orders 요청 바디를 바꿨는지, 왜 필드가 필수로 바뀌었는지 확인하기 힘듭니다.

openapi.yaml을 Git으로 관리하면 다음을 얻을 수 있습니다.

  • 히스토리: 모든 변경 사항이 작성자, 시간, 커밋 메시지와 함께 기록됩니다.
  • 책임 추적: git blame openapi.yaml로 특정 필드가 언제, 누구에 의해 추가됐는지 확인할 수 있습니다.
  • 롤백: 잘못된 계약 변경이 병합되면 해당 커밋을 되돌릴 수 있습니다.
  • 검토: 스펙 변경이 PR을 거치므로 배포 전에 다른 개발자가 계약 변경을 확인할 수 있습니다.

이것이 Git-native API 워크플로우의 기본입니다. 스펙은 소스 코드이고, 소스 코드는 Git에 있어야 합니다.

저장소에서 스펙 파일 위치 정하기

가장 중요한 원칙은 단순하고 예측 가능하게 유지하는 것입니다. 대부분의 팀은 저장소 루트 또는 api/ 디렉터리에 단일 openapi.yaml 파일을 둡니다.

my-service/
├── api/
│   └── openapi.yaml
├── src/
└── README.md
Enter fullscreen mode Exit fullscreen mode

여러 메이저 버전을 병렬로 유지해야 한다면 버전별 파일을 분리합니다.

api/
├── api-v1.yaml
└── api-v2.yaml
Enter fullscreen mode Exit fullscreen mode

이 방식은 파괴적 변경을 격리하는 데 유용합니다.

  • api-v1.yaml: 기존 클라이언트를 위해 안정적으로 유지
  • api-v2.yaml: 새로운 계약 변경 반영
  • 각 파일의 변경 이유가 명확해져 diff가 작아짐
  • PR 검토가 쉬워짐

이처럼 스펙을 코드처럼 다루는 것이 API spec as code의 핵심입니다.

팀에서는 다음 규칙을 문서화해 두는 것이 좋습니다.

API 스펙 위치: api/openapi.yaml
메이저 버전 분리 시: api/api-v{version}.yaml
main 브랜치의 스펙만 배포 기준으로 사용
Enter fullscreen mode Exit fullscreen mode

가장 피해야 할 상황은 여러 파일이 동시에 “진짜 스펙”이라고 주장하는 것입니다.

스펙 변경을 위한 브랜칭 전략

OpenAPI 스펙에 별도의 복잡한 브랜칭 모델은 필요하지 않습니다. 애플리케이션 코드와 같은 흐름을 사용하면 됩니다.

  1. main에서 브랜치를 생성합니다.
  2. 스펙을 수정합니다.
  3. 유효성 검사를 실행합니다.
  4. PR을 생성합니다.
  5. 리뷰와 CI를 통과하면 병합합니다.

예시:

git checkout main
git pull
git checkout -b api/add-refunds
Enter fullscreen mode Exit fullscreen mode

브랜치 이름은 변경 의도를 바로 알 수 있게 작성합니다.

브랜치 유형 패턴 예시
새 엔드포인트 api/add-<resource> api/add-refunds
필드 변경 api/change-<resource>-<field> api/change-order-status
파괴적 변경 api/breaking-<description> api/breaking-v2-auth
수정 / 정리 api/fix-<description> api/fix-pagination-schema

api/ 접두사는 “이 PR은 API 계약을 변경한다”는 신호입니다. 리뷰어와 CI가 스펙 변경 PR을 쉽게 식별할 수 있습니다.

파괴적 변경이라면 breaking- 접두사를 사용하세요. 예를 들어 다음과 같은 변경은 파괴적 변경일 수 있습니다.

  • 기존 응답 필드 제거
  • 필드 타입 변경
  • 요청 필드를 필수로 변경
  • enum 값 제거
  • 기존 엔드포인트 삭제
  • 인증 방식 변경

브랜치는 짧게 유지하세요. 오래 열린 스펙 브랜치는 다른 변경과 충돌할 가능성이 큽니다. 하나의 PR에는 하나의 논리적 계약 변경만 포함하는 것이 좋습니다.

풀 리퀘스트에서 스펙 변경 검토하기

스펙 PR은 단순한 문서 변경이 아니라 API 계약 변경입니다. 코드 리뷰와 같은 수준으로 검토해야 합니다.

먼저 YAML을 diff 친화적으로 작성하세요.

paths:
  /orders/{orderId}:
    get:
      summary: Get an order
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Order found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
Enter fullscreen mode Exit fullscreen mode

좋은 diff를 만들기 위한 규칙:

  • 들여쓰기를 일관되게 유지합니다.
  • 한 줄에 하나의 속성만 둡니다.
  • 불필요한 재정렬을 피합니다.
  • 자동 포맷 도구를 팀 단위로 통일합니다.
  • 큰 스키마 변경은 작은 PR로 나눕니다.

리뷰어는 다음 항목을 확인해야 합니다.

1. 파괴적 변경 여부

다음 변경은 기존 클라이언트를 깨뜨릴 수 있습니다.

# 기존
schema:
  type: object
  properties:
    status:
      type: string
Enter fullscreen mode Exit fullscreen mode
# 변경 후: enum 제한 추가
schema:
  type: object
  properties:
    status:
      type: string
      enum: [paid, canceled]
Enter fullscreen mode Exit fullscreen mode

기존 클라이언트가 다른 status 값을 사용하고 있었다면 문제가 될 수 있습니다.

확인할 항목:

  • 필수 요청 필드가 추가됐는가?
  • 응답 필드가 제거됐는가?
  • 필드 이름이 변경됐는가?
  • 타입이 변경됐는가?
  • enum 값이 제거됐는가?
  • 상태 코드가 변경됐는가?

2. 하위 호환성

일반적으로 다음 변경은 안전한 편입니다.

  • 새로운 선택적 필드 추가
  • 새로운 엔드포인트 추가
  • 새로운 응답 예시 추가
  • 설명 또는 문서 보강

반대로 기존 요청/응답 구조를 바꾸는 변경은 주의해야 합니다.

3. 명명 규칙과 일관성

새 엔드포인트가 기존 API 스타일과 맞는지 확인합니다.

좋음: /orders/{orderId}/refunds
나쁨: /OrderRefund/create
Enter fullscreen mode Exit fullscreen mode

검토 기준:

  • 리소스 이름이 복수형인가?
  • path parameter 이름이 일관적인가?
  • snake_case, camelCase 규칙이 섞이지 않았는가?
  • 기존 에러 응답 형식과 같은가?

4. 완전성

새 작업에는 최소한 다음이 포함되어야 합니다.

  • summary
  • 요청 스키마
  • 성공 응답 스키마
  • 에러 응답
  • 현실적인 예시

예시:

responses:
  "201":
    description: Refund created
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/Refund"
  "400":
    description: Invalid refund request
  "401":
    description: Unauthorized
Enter fullscreen mode Exit fullscreen mode

5. 예시 데이터

예시는 문서, 목업, 테스트에서 모두 중요합니다. 실제 사용 가능한 값으로 작성하세요.

example:
  id: "refund_123"
  orderId: "order_456"
  amount: 2500
  currency: "KRW"
  reason: "Damaged item"
Enter fullscreen mode Exit fullscreen mode

파괴적 변경 감지는 사람이 직접 눈으로 확인하는 것보다 도구에 맡기는 것이 안전합니다. CI에서 PR의 스펙과 main의 스펙을 비교해 호환되지 않는 변경이 있으면 빌드를 실패시키세요.

Apidog에서 커밋 및 푸시하기

원시 YAML을 직접 편집할 수도 있지만, 시각적 편집기를 사용하면 실시간 유효성 검사와 구조화된 편집이 가능해 실수를 줄일 수 있습니다.

Apidog의 Spec-First 모드는 양방향 Git 동기화를 제공합니다. UI에서 스펙을 편집하고, 변경 사항을 커밋한 뒤 저장소로 푸시할 수 있습니다. 반대로 팀원이 Git에 푸시한 변경 사항도 다시 가져올 수 있습니다.

기본 흐름은 다음과 같습니다.

  1. Git 저장소를 Apidog에 연결합니다.
  2. Apidog가 사용할 OpenAPI 파일을 지정합니다.
  3. 시각적 편집기에서 엔드포인트, 스키마, 예시를 수정합니다.
  4. 변경 사항을 확인합니다.
  5. 브랜치에 커밋하고 푸시합니다.
  6. GitHub, GitLab 등에서 PR을 생성합니다.

Apidog Spec-First mode

Apidog는 YAML을 일관된 형식으로 직렬화하므로 불필요한 재정렬이나 포맷 변경을 줄일 수 있습니다. diff가 작아지면 리뷰도 쉬워집니다.

설정 방법은 Apidog Spec-First 모드 문서를 참고하세요. GitHub 저장소와 동기화하는 흐름은 GitHub에 OpenAPI 스펙 동기화하기에서 확인할 수 있습니다.

CI 유효성 검사 훅 추가하기

유효하지 않은 OpenAPI 스펙이 main에 병합되면 안 됩니다. PR마다 스펙을 검사하도록 CI를 설정하세요.

가장 간단한 GitHub Actions 예시는 다음과 같습니다.

name: Validate OpenAPI

on: [pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Lint spec
        run: npx @redocly/cli lint api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

이 단계는 다음 문제를 잡는 데 도움이 됩니다.

  • 잘못된 OpenAPI 구조
  • 누락된 필수 속성
  • 잘못된 $ref
  • 일관되지 않은 스타일
  • 파싱 불가능한 YAML

스펙 변경이 많아지면 검사 단계를 확장하세요.

name: Validate OpenAPI

on: [pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Lint OpenAPI spec
        run: npx @redocly/cli lint api/openapi.yaml

      - name: Validate OpenAPI syntax
        run: npx @redocly/cli bundle api/openapi.yaml --output /tmp/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

파괴적 변경 감지도 추가할 수 있습니다. 예를 들어 PR 브랜치의 스펙과 main의 스펙을 비교하는 도구를 실행해 breaking change가 있으면 실패 처리합니다.

검사 항목은 단계적으로 늘리는 것이 좋습니다.

  1. OpenAPI lint
  2. YAML 파싱 검증
  3. $ref 검증
  4. breaking change 감지
  5. 문서 생성 또는 목업 생성 검증

CI 검사는 몇 초 안에 실행되며, 사람이 리뷰에서 놓치기 쉬운 오류를 안정적으로 잡아냅니다.

모범 사례

OpenAPI 스펙 버전 관리를 안정적으로 유지하려면 다음 규칙을 적용하세요.

1. info.version을 업데이트하세요

스펙 변경이 있으면 info.version을 함께 관리합니다.

info:
  title: Orders API
  version: 1.2.0
Enter fullscreen mode Exit fullscreen mode

일반적인 기준:

  • 파괴적 변경: 메이저 버전 증가
  • 하위 호환 추가: 마이너 버전 증가
  • 문서 또는 예시 수정: 패치 버전 증가

2. 변경 로그를 유지하세요

스펙 옆에 CHANGELOG.md를 두면 API 소비자가 변경 사항을 빠르게 파악할 수 있습니다.

api/
├── openapi.yaml
└── CHANGELOG.md
Enter fullscreen mode Exit fullscreen mode

예시:

# Changelog

## 1.2.0
- Added `GET /refunds`
- Added optional `refundReason` field to refund response

## 1.1.1
- Fixed pagination schema description
Enter fullscreen mode Exit fullscreen mode

3. PR당 하나의 논리적 변경만 포함하세요

좋은 PR:

api/add-refunds
Enter fullscreen mode Exit fullscreen mode

나쁜 PR:

api/update-everything
Enter fullscreen mode Exit fullscreen mode

큰 PR은 파괴적 변경을 숨깁니다. 작은 PR은 리뷰와 롤백이 쉽습니다.

4. 커밋 메시지를 구체적으로 작성하세요

좋은 예:

Add refundReason to refund request schema
Enter fullscreen mode Exit fullscreen mode

나쁜 예:

Update spec
Enter fullscreen mode Exit fullscreen mode

커밋 메시지만 봐도 계약 변경 내용을 이해할 수 있어야 합니다.

5. main에서 직접 수정하지 마세요

오타 수정이라도 브랜치와 PR을 거치세요. 그래야 리뷰, CI, 히스토리가 유지됩니다.

git checkout -b api/fix-refund-description
Enter fullscreen mode Exit fullscreen mode

6. 자동 포맷을 통일하세요

팀원마다 다른 포맷터를 사용하면 의미 없는 diff가 늘어납니다. 하나의 도구와 규칙을 정하세요.

- 들여쓰기: 2 spaces
- YAML key 순서: 도구 기본값 사용
- 자동 정렬 여부: 팀 규칙으로 고정
Enter fullscreen mode Exit fullscreen mode

자주 묻는 질문

OpenAPI 스펙에서 파괴적 변경 사항을 어떻게 감지하나요?

CI에서 PR 브랜치의 스펙을 main 브랜치의 스펙과 비교하는 diff 도구를 실행하세요. oasdiff와 같은 도구는 변경 사항을 파괴적 변경, 비파괴적 변경, 미분류 변경으로 구분할 수 있습니다.

이 방식은 다음과 같은 변경을 잡는 데 유용합니다.

  • 제거된 응답 필드
  • 새로 추가된 필수 요청 파라미터
  • 변경된 필드 타입
  • 제거된 enum 값
  • 삭제된 엔드포인트

수동 리뷰는 이런 변경을 놓칠 수 있으므로 자동 검사를 함께 사용해야 합니다.

하나의 OpenAPI 파일을 유지해야 하나요, 아니면 여러 개로 분할해야 하나요?

처음에는 단일 openapi.yaml로 시작하는 것이 좋습니다. 가장 읽기 쉽고, 리뷰하기 쉽고, 버전 관리도 단순합니다.

다음 상황이 되면 분할을 고려하세요.

  • 여러 메이저 버전을 동시에 유지해야 함
  • 파일이 너무 커져 리뷰가 어려움
  • 공통 스키마를 여러 API에서 재사용해야 함

분할 예시:

api/
├── api-v1.yaml
├── api-v2.yaml
└── schemas/
    ├── order.yaml
    └── refund.yaml
Enter fullscreen mode Exit fullscreen mode

하지만 너무 일찍 분할하지 마세요. 읽기 쉬운 하나의 파일이 파편화된 여러 파일보다 낫습니다.

YAML을 수동으로 작성하지 않고도 스펙을 버전 관리할 수 있나요?

네. Apidog의 Spec-First 모드를 사용하면 시각적 편집기에서 OpenAPI 스펙을 수정하고 Git과 양방향으로 동기화할 수 있습니다.

이 방식의 장점은 다음과 같습니다.

  • YAML을 직접 많이 작성하지 않아도 됨
  • 실시간 유효성 검사 가능
  • Git 히스토리 유지
  • PR 기반 리뷰 유지
  • 일관된 YAML 출력으로 diff가 깔끔해짐

즉, 시각적 편집기의 생산성과 Git 기반 워크플로우를 함께 사용할 수 있습니다.

Top comments (0)