# Echo の OpenAPI / Swagger：コードファースト(swag) と契約ファースト(oapi-codegen) の使い分けと本番運用

> Go Echo（v5）で OpenAPI / Swagger ドキュメントを運用するガイド。コードファースト（swag アノテーション）と契約ファースト（oapi-codegen でスキーマから型・サーバー生成）の使い分け、Swagger UI の配信、CI でのドキュメント整合性検証、そして Echo v5 でのツール対応状況（oapi-codegen 安定版はv4対応・v5は実験的）まで、忖度なく実コードで解説します。

- 公開日: 2026-06-28
- 著者: 友田 陽大
- タグ: Go, Echo, OpenAPI, 型安全, アーキテクチャ設計, ドキュメント
- URL: https://tomodahinata.com/blog/go-echo-openapi-swagger-swag-oapi-codegen-documentation-guide
- カテゴリ: Go・Echo 本番運用
- 総合ガイド: https://tomodahinata.com/blog/go-echo-framework-production-guide

## 要点

- API ドキュメントは手書きで腐らせない。コードファースト(swag)かスキーマファースト(oapi-codegen)で、コード／仕様／ドキュメントを1つの真実源に束ねる
- swag は Go のコメント注釈から OpenAPI を生成。導入が軽く、既存コードに後付けしやすい。注釈解析は v5 でも機能する
- oapi-codegen は OpenAPI 仕様から Go の型・サーバーを生成。契約が真実源になり多言語クライアントとも整合。長期保守は契約ファーストが強い
- 正直な注意：oapi-codegen 安定版(v2)は Echo v4 対応で、v5 対応は実験版(V3)段階。Swagger UI 配信ミドルウェアも v4 想定が多い。v5 では型生成＋手動マウント or 実験版で対応する
- 生成物はコミットし CI で再生成差分が出たら落とす。これで仕様・生成物・実装が Git の一点で必ず一致する

---

「API ドキュメントが実装とズレている」——これは API を提供するすべてのチームの慢性疾患です。手書きの Markdown は必ず腐り、フロントエンドやクライアント企業は古いドキュメントを信じて実装し、障害になります。解決策は精神論ではなく、**コード・仕様・ドキュメントを1つの真実源（Single Source of Truth）に束ねる**自動化です。

この記事は、[Go Echo 本番運用ガイド](/blog/go-echo-framework-production-guide)の API ドキュメント編です。Echo v5 で OpenAPI を運用する2つのアプローチ——**コードファースト（swag）**と**契約ファースト（oapi-codegen）**——を使い分け、本番での整合性担保まで設計します。そして、**Echo v5 が新しいがゆえのツール対応状況**も忖度なくお伝えします。

> **この記事のルール**：Echo の API は **公式ドキュメント（v5・2026年6月時点）** に基づきます。**重要**：Echo v5 はリリース直後（2026年6月）のため、`oapi-codegen`・Swagger UI 配信ミドルウェア等の**サードパーティ対応が追随中**です。本記事は[その現実](#4-正直な現状echo-v5-とツールの対応状況)を明記した上で、v5 で**今動く**書き方を示します。導入前に各ツールの最新対応を必ず確認してください。

---

## 0. 2つのアプローチ：どちらの「真実源」を選ぶか

| 観点 | **コードファースト（swag）** | **契約ファースト（oapi-codegen）** |
| --- | --- | --- |
| 真実源 | **Go のコード（注釈）** | **OpenAPI 仕様（YAML/JSON）** |
| 流れ | コード → 注釈 → 仕様生成 | 仕様 → 型・サーバー生成 → 実装 |
| 導入の軽さ | **軽い（後付け可）** | やや重い（最初に仕様を書く） |
| 型安全 | 注釈と実装は別物（ズレ得る） | **仕様＝型。実装が契約に従う** |
| 多言語クライアント | 生成した仕様から各言語へ | **仕様が中心なので相性◎** |
| 向く場面 | 既存 API に文書を後付け | 新規・複数チーム・契約駆動 |

> **判断の目安**：**既存の Echo API に手早くドキュメントを付けたい**なら **swag**。**新規で、フロントや外部クライアントと契約を先に固めたい**なら **oapi-codegen（契約ファースト）**。フロントエンド（Next.js 等）まで含めた**エンドツーエンドの型安全**を狙うなら、契約ファーストが本命です（[Next.js × Go × OpenAPI の実践](/blog/nextjs-go-openapi-end-to-end-type-safety)）。

---

## 1. コードファースト：swag で注釈から OpenAPI を生成

`swag` は、ハンドラの**コメント注釈**を解析して OpenAPI 仕様（`swagger.json` / `swagger.yaml`）を生成します。注釈解析は Go コードのコメントを読むだけなので、**フレームワークのバージョンに依存しません**（v5 でも機能します）。

```go
// CreateUser godoc
// @Summary      ユーザーを作成
// @Description  メールとパスワードで新規ユーザーを登録する
// @Tags         users
// @Accept       json
// @Produce      json
// @Param        request body CreateUserDTO true "作成するユーザー"
// @Success      201 {object} UserResponse
// @Failure      400 {object} ErrorResponse
// @Failure      422 {object} ErrorResponse
// @Router       /api/v1/users [post]
func (h *UserHandler) Create(c *echo.Context) error {
	// ... 実装
}
```

生成はコマンド一発。CI に組み込めます。

```bash
# 注釈から docs/swagger.json / swagger.yaml を生成
swag init -g cmd/server/main.go -o ./docs
```

注釈で書いた DTO は[バインディング＆バリデーション](/blog/go-echo-request-binding-validation-error-handling-guide)の構造体と同じものを参照できます。**注意点**は、注釈と実装が**別物**である以上、`@Param` の型を変えても実装が追随しない（ズレ得る）こと。これを CI で検出する方法は[第5章](#5-ci整合性を機械で担保する)で扱います。

---

## 2. Swagger UI の配信：v5 では「静的配信」が最も確実

生成した仕様は、**Swagger UI** でブラウザから閲覧できるようにします。`echo-swagger` のような専用ミドルウェアもありますが、それらは**Echo のバージョンに依存**します（v5 直後の現時点では v4 想定のものが多い）。**バージョンに左右されない確実な方法**は、仕様 JSON と Swagger UI を**普通の静的ルートで配信**することです。

```go
// 生成した OpenAPI 仕様を普通のルートで配る（バージョン非依存）
e.GET("/openapi.json", func(c *echo.Context) error {
	return c.File("docs/swagger.json")
})

// Swagger UI / Redoc / Scalar 等の静的アセットを配信し、上の /openapi.json を指す
e.Static("/docs", "third_party/swagger-ui") // index.html が /openapi.json を読む
```

この方式なら、Swagger UI でも Redoc でも Scalar でも、**好きなビューアを Echo のバージョンと無関係に**載せられます。ドキュメント配信は**認証の内側**に置くか、公開範囲を絞るのが本番の作法です（社内 API の仕様を無防備に公開しない）。

---

## 3. 契約ファースト：oapi-codegen で仕様から型を生成

契約ファーストでは、**先に OpenAPI 仕様を書き**、そこから Go の型（とサーバーの土台）を生成します。**仕様が唯一の真実源**になり、実装は契約に従うことを強制されます。

```yaml
# openapi.yaml（真実源）
paths:
  /users:
    post:
      operationId: createUser
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CreateUserRequest' }
      responses:
        '201':
          content:
            application/json:
              schema: { $ref: '#/components/schemas/User' }
components:
  schemas:
    CreateUserRequest:
      type: object
      required: [name, email]
      properties:
        name:  { type: string, minLength: 2, maxLength: 50 }
        email: { type: string, format: email }
```

ここから**型**を生成すれば、リクエスト/レスポンスの構造体を**手書きしなくて済み**、仕様変更が型エラーとして実装に伝わります。

```bash
# 仕様から Go の型を生成（型だけなら最も移植性が高い）
oapi-codegen -generate types -package api -o api/types.gen.go openapi.yaml
```

生成した型を、Echo ハンドラの[Bind/Validate](/blog/go-echo-request-binding-validation-error-handling-guide)に使います。「仕様で `minLength:2` を変えたら、生成型と検証も追従する」——これが契約ファーストの型安全です。

---

## 4. 正直な現状：Echo v5 とツールの対応状況

ここを濁す技術記事が多いので、**忖度なく**書きます。Echo v5 は 2026年6月にリリースされたばかりで、**ハンドラ署名が `func(c *echo.Context) error` に変わった**ため、コード生成ツールやミドルウェアの**追随が進行中**です。

| ツール | Echo v5 対応状況（2026年6月時点） | 推奨アクション |
| --- | --- | --- |
| **swag（注釈解析）** | コメント解析なので**機能する** | そのまま使える |
| **swag の UI 配信（echo-swagger）** | v4 想定が中心 | [静的配信](#2-swagger-ui-の配信v5-では静的配信が最も確実)で代替 |
| **oapi-codegen（型生成）** | `-generate types` は**仕様→型なので使える** | 型生成は活用可 |
| **oapi-codegen（Echo サーバー生成）** | **安定版(v2)は Echo v4 想定**。v5 対応は**実験版(V3)**段階（Go 1.25 要） | 型生成＋手動マウント、または実験版を慎重に評価 |

**現実的な戦略**（v5・2026年6月時点）：

1. **契約ファースト + 型生成のみ**：`oapi-codegen -generate types` で**型だけ**生成し、ルーティングとハンドラの結線は**自分で書く**（Echo v5 の `e.POST(...)` に手で繋ぐ）。生成サーバーの v5 対応を待たずに、契約の恩恵（型安全）を今すぐ得られます。**これが最も堅実。**
2. **コードファースト（swag）**：注釈は v5 で機能。UI は静的配信。後付け文書化に最適。
3. **生成サーバーが必要**：安定版が v5 対応するまで待つ、もしくは実験版を**本番外で評価**する。

> この「**新しいフレームワークは本体が先行し、周辺ツールが後追いする**」のは、あらゆる技術移行で起きる普遍的な現象です。だからこそ、**ツールに依存しすぎない（型生成は使うがサーバー生成には縛られない）**設計が、移行期のリスクを下げます。これは ETC（変更容易性）の実践でもあります。

---

## 5. CI：整合性を機械で担保する

OpenAPI 運用の価値は、**ドキュメントが実装と必ず一致している**ことで初めて生まれます。これは規律ではなく **CI** で機械的に強制します。

```yaml
# .github/workflows/ci.yml（抜粋）
- name: Regenerate & verify OpenAPI is in sync
  run: |
    swag init -g cmd/server/main.go -o ./docs   # コードファーストなら再生成
    # oapi-codegen の場合：oapi-codegen ... -o api/types.gen.go openapi.yaml
    git diff --exit-code docs/ api/             # 差分が出たら CI を落とす
```

**生成物をリポジトリにコミットし、CI で「再生成して差分が出たら失敗」**にします。これで、**仕様・生成物・実装が Git の一点で必ず整合**します。誰かが注釈や仕様を更新し忘れた瞬間に CI が落ちるので、ドキュメントが腐りません。さらに、OpenAPI 仕様の**破壊的変更検知**（`oasdiff` 等）を CI に足せば、後方互換を壊す変更を PR で止められます。

この「整合性を人の注意ではなく CI で担保する」思想は、[AI駆動開発の品質ゲート](/blog/ai-driven-development-quality-gates-ci-type-safety-test-security)や[エンドツーエンド型安全](/blog/nextjs-go-openapi-end-to-end-type-safety)（生成物をコミットして再生成差分で落とす）と完全に同じです。

---

## まとめ：Echo の OpenAPI を本番運用する7原則

1. **ドキュメントは手書きで腐らせない**。コード or 仕様を真実源に自動生成する。
2. **後付けは swag（コードファースト）**、**新規・契約駆動は oapi-codegen（契約ファースト）**。
3. **Swagger UI は静的配信が最も確実**（バージョン非依存）。
4. **正直な v5 現状**：swag 注釈と oapi-codegen の**型生成は使える**。**Echo サーバー生成は安定版が v4 想定**、v5 は実験版段階。
5. **移行期は型生成＋手動マウント**でツール依存を下げる（ETC）。
6. **生成物はコミットし、CI で再生成差分が出たら落とす**（整合性の機械担保）。
7. **破壊的変更検知**を CI に入れ、契約の後方互換を守る。

API ドキュメントは「書くもの」ではなく「**実装から外れない仕組みを作るもの**」です。Echo v5 のような新しい基盤では、ツールの対応状況を見極めて**型安全の恩恵だけ先取りする**現実解が効きます。全体像は[Go Echo 本番運用ガイド](/blog/go-echo-framework-production-guide)、可観測性は[OpenTelemetry 連携](/blog/go-echo-opentelemetry-distributed-tracing-metrics-observability-guide)へ。
