---
title: "Spring for GraphQLとは？Spring Boot 4.1での実装手順とトレース設定【2026年版】"
url: "https://www.issoh.co.jp/tech/details/4575/"
published: 2024-12-19
updated: 2026-10-20
categories: ["Java"]
publisher: "株式会社一創"
---

# Spring for GraphQLとは？Spring Boot 4.1での実装手順とトレース設定【2026年版】

Spring for GraphQLは、graphql-javaの実行エンジンをSpringの`@Controller`モデルから扱えるようにしたGraphQLサーバー実装です。Spring Boot 4.1では`spring-boot-starter-graphql`とトランスポート用のstarterを組み合わせるだけでエンドポイントが立ち上がり、Micrometerの計装も同梱されています（発行条件は後述します）。本記事では、2026年8月18日時点のMaven Centralと公式ドキュメントで確認した版・設定プロパティをもとに、依存追加からトレース出力までを通しで整理します。Spring Boot 3系から移行するときに名前が変わったプロパティ、そして配布そのものが止まった依存も併せて示します。

## まとめ

- Spring Boot 4.1.0が管理するSpring for GraphQLは2.0.4、Spring Boot 3.5.16は1.4.6です。starterを使うなら版指定は不要です。
- 依存は`spring-boot-starter-graphql`だけでは足りません。GraphQLはトランスポート非依存のため、HTTPで公開するなら`spring-boot-starter-web`を併せて入れます。
- スキーマは`src/main/resources/graphql/`配下に`.graphqls`または`.gqls`で置けば自動で読み込まれます。
- GraphiQLは既定で無効ですが、スキーマを外部から読み取れるintrospectionは既定で有効です。この2つは別設定なので混同しないでください。
- 可観測性はGraphQL専用のObservationとして`graphql.request`、`graphql.datafetcher`、`graphql.dataloader`の3種が用意されています。汎用のHTTPトレースでは見えないフィールド単位の遅延がここで取れます。
- 2024年頃の記事にある`opentelemetry-exporter-jaeger`は使えません。OpenTelemetry Java 1.35.0で削除済みで、JaegerへはOTLPで送ります。

以降で、対応バージョンの確認から実装手順、Observationの中身、Spring Boot 4系での送信設定までを順に見ていきます。

## Spring for GraphQLの役割と対応バージョン

### graphql-javaをSpringのコントローラモデルで包む位置づけ

GraphQLのクエリ解析とスキーマ実行そのものを担うのはgraphql-javaです。Spring for GraphQLはその上位に位置し、`AnnotatedControllerConfigurer`が`@SchemaMapping`系のアノテーションが付いたメソッドを走査して、graphql-javaの`DataFetcher`として登録します。開発者はSpring MVCのコントローラを書く感覚でリゾルバを実装でき、HTTP・WebSocket・RSocketの各トランスポートはフレームワーク側が用意します。

単体の成果物名は`org.springframework.graphql:spring-graphql`で、Maven Centralでの最新公開版は2.0.4です。ただしSpring Bootから使う場合、この版を自分で指定する必要はありません。GraphQLそのものの設計思想やREST APIとの違いは[GraphQLとは？REST APIとの違い・メリット・デメリットをわかりやすく解説](/tech/details/2924/)で扱っています。

### Spring Boot 4.1と3.5で実際に入る依存の版

starterを使うと、Spring Bootのバージョン管理（BOM）が下表の版を解決します。可観測性まわりの版も連動して決まるため、「どのSpring Bootを使うか」がそのまま「どのMicrometer Tracingを使うか」になります。

| Spring Boot | spring-graphql | micrometer-tracing | opentelemetry-bom |
| ----------- | -------------- | ------------------ | ----------------- |
| 4.1.0       | 2.0.4          | 1.7.0              | 1.62.0            |
| 3.5.16      | 1.4.6          | 1.5.12             | 1.49.0            |

数値は`spring-boot-dependencies`の各POMに記載された管理版です。Spring Boot 4系そのものの変更点は[Spring Boot 4とは？最新バージョン4.1の変更点・新機能とSpring Boot 3との違いを解説【2026年最新】](/tech/details/10124/)にまとめています。

## 最小構成でGraphQLエンドポイントを公開する手順

### トランスポート用starterを含む依存の追加

GraphQLはトランスポート非依存の仕様のため、`spring-boot-starter-graphql`だけでは通信経路が決まらず、APIを外部に公開できません。公式も同starterを「最低限」と位置づけたうえで、公開手段に応じた追加starterを求めています。選択肢はHTTP向けの`spring-boot-starter-web`、Servletアプリ向けWebSocketの`spring-boot-starter-websocket`、HTTPとWebSocketの両方を扱う`spring-boot-starter-webflux`、TCPとWebSocket向けの`spring-boot-starter-rsocket`です。一般的なHTTP APIなら次の2つになります。

```
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-graphql")
    implementation("org.springframework.boot:spring-boot-starter-web")
}
```

### スキーマファイルの配置先と読み込み範囲

スキーマは`spring.graphql.schema.locations`が指す場所から読み込まれ、既定値は`classpath:graphql/**/`です。`src/main/resources/graphql/`配下に拡張子`.graphqls`または`.gqls`のファイルを置けば設定なしで認識されます。拡張子そのものは`spring.graphql.schema.file-extensions`で変更できます。

```
type Query {
    bookById(id: ID): Book
}

type Book {
    id: ID
    name: String
    author: Author
}

type Author {
    id: ID
    firstName: String
    lastName: String
}
```

注意が必要なのは複数モジュール構成です。既定の`classpath:`プレフィックスのままだと読み込み範囲が広がらないため、アプリケーションの全モジュールと依存関係からスキーマを集めたい場合は、ディレクトリを変えるのではなく`spring.graphql.schema.locations`を`classpath*:graphql/**/`とアスタリスク付きのプレフィックスに変更します。

### @QueryMappingによるリゾルバ実装

スキーマのQuery型のフィールドは`@QueryMapping`、任意の型のフィールドは`@SchemaMapping`で実装します。引数は`@Argument`でバインドします。

```
@Controller
public class BookController {

    @QueryMapping
    public Book bookById(@Argument Long id) {
        // ...
    }

    @SchemaMapping
    public Author author(Book book) {
        // ...
    }
}
```

メソッド名がそのままフィールド名、引数に取った親オブジェクトの単純クラス名がそのまま型名の既定値になります。上の`author`メソッドは型「Book」のフィールド「author」に対応します。書き込み系は`@MutationMapping`、購読は`@SubscriptionMapping`を使い、この2つと`@QueryMapping`の3つが`@SchemaMapping`のメタアノテーションとして、typeNameをQuery・Mutation・Subscriptionに固定したものです。`@BatchMapping`はこれらとは別系統で、親オブジェクトのリストを受け取って関連データをまとめて読み込むためのものです。例えば書籍のリストに対して著者を一括取得する用途に使います。

### GraphiQLの有効化と疎通確認

GraphQLのHTTPエンドポイントは`spring.graphql.http.path`の既定値どおり`/graphql`に公開されます。ブラウザで試すためのGraphiQL UIは同梱されていますが、**`spring.graphql.graphiql.enabled`の既定値はfalse**で、明示的に有効化しないと表示されません。

```
spring.graphql.graphiql.enabled=true
spring.graphql.schema.printer.enabled=true
```

有効にすると`spring.graphql.graphiql.path`の既定値`/graphiql`でUIが開きます。`schema.printer.enabled`も既定falseで、有効にするとHTTPパスの末尾に`/schema`を足したURLで解決済みスキーマを確認できます。スキーマが読み込まれているかを切り分けたいときに役立ちます。

## Spring BootでGraphQLを採用する判断基準

### エンドポイント増加が止まらない場合に効く条件

GraphQLは「クライアントが必要なフィールドだけを1リクエストで取れる」ことに価値があります。採用が効くのは、画面ごとに必要なフィールドの組み合わせが大きく異なり、REST側でエンドポイントが増え続けている場合です。モバイルとWebで必要な項目が違う、画面改修のたびにBFFを直している、といった状況が典型です。

### 単一クライアントで見送るべき条件

逆に、**単一クライアントしか存在せず、レスポンス形状が安定しているシステムにGraphQLを載せるべきではありません**。取得フィールドが可変になることで、キャッシュ設計・認可のフィールド単位の制御・クエリ深度の制限といった、RESTでは不要だった論点が一式増えます。フィールド単位のリゾルバがそれぞれデータソースを叩くため、N+1問題も自前で潰す必要があります。エンドポイント数が問題になっていないなら、RESTのままの方が総コストは低くなります。判断軸をより細かく比べたい場合は[REST APIとGraphQLの違いと使い分け｜選定基準と運用コスト](/tech/details/3591/)を参照してください。

## GraphQL固有の可観測性を担う3種類のObservation

### graphql.requestが記録するオペレーション種別と成否

Spring for GraphQLにはMicrometer Observationの計装が直接組み込まれており、`GraphQlObservationInstrumentation`を登録するとリクエスト単位のObservationが`graphql.request`という名前で作られます。Spring Bootのstarterを使っている場合はこのインストルメンテーションが自動で構成されます。ただし**アプリケーションに`ObservationRegistry`が構成されていなければObservationは発行されません**。

| KeyValue               | カーディナリティ | 内容                                           |
| ---------------------- | -------- | -------------------------------------------- |
| graphql.operation.type | 低        | query/mutation/subscription（解析失敗時 operation） |
| graphql.outcome        | 低        | SUCCESS / REQUEST\_ERROR / INTERNAL\_ERROR   |
| graphql.operation.name | 高        | クライアント指定のオペレーション名                            |
| graphql.execution.id   | 高        | graphql-java の ExecutionId                   |

ここで実務上重要なのは`graphql.outcome`の3値の切り分けです。GraphQLはHTTP 200を返しつつレスポンス本体にエラーを含められるため、HTTPステータスだけを見ている監視では失敗を取りこぼします。エラーを含むレスポンスは`ErrorType.INTERNAL_ERROR`が含まれるかどうかで`INTERNAL_ERROR`と`REQUEST_ERROR`に分かれるので、アラートはサーバー起因の`INTERNAL_ERROR`に絞ると、クライアント側の不正クエリによるノイズを避けられます。レスポンスに載ったエラーはObservation Eventとしても記録され、トレース上ではスパンのアノテーションとして扱われるのが一般的です。

### graphql.datafetcherとgraphql.dataloaderで追うフィールド単位の遅延

フィールド解決の計測は`graphql.datafetcher`という名前で作られます。ここには重要な条件があり、**Javaオブジェクトのプロパティを読むだけの「自明な」フェッチは計測対象外**です。計測されるのはデータソースへのアクセスを伴う非自明なフェッチだけなので、スパンが大量に増える心配はありません。付与されるのは`graphql.field.name`、フィールドのパスを示す`graphql.field.path`（例：`/bookById`）、`graphql.outcome`、エラー時のクラス名を示す`graphql.error.type`です。ただしここでの`graphql.outcome`はSUCCESSとERRORの2値で、リクエスト単位の3値とは値域が違います。

3つ目の`graphql.dataloader`は、**`@BatchMapping`のコントローラメソッドと、手動登録した`DataLoader`インスタンスの呼び出しだけ**を観測します。`graphql.loader.name`と、読み込んだ要素数を示す`graphql.loader.size`が付きます。この発行条件がそのままN+1の診断手順になります。まず、`graphql.datafetcher`のスパンは出ているのに`graphql.dataloader`が1件も出ていなければ、その経路は`@BatchMapping`も`DataLoader`も通っておらず、フィールドごとの個別解決のままです。バッチ化の入り口に立てていない状態なので、まずここを疑います。次に`graphql.dataloader`が出ている場合は`graphql.loader.size`を親の件数と突き合わせ、想定より小さい値に分割されていればバッチ境界が細かすぎると判断できます。いずれもHTTPスパンだけを見ていても分からない情報です。Observationの出力先設定そのものは[Spring Boot OpenTelemetry導入｜2つのstarterの違いとMaven設定](/tech/details/4692/)で詳しく扱っています。

## Spring Boot 4系のトレース出力設定と廃止済み依存

### ZipkinとOTLPで異なるstarterと設定プロパティ

Spring Boot 4.0以降は代表的な2つの組み合わせに専用starterが用意されています。どちらを選ぶかで、追加する依存も設定プロパティの接頭辞も変わります。

| 組み合わせ                | starter                           | 設定プロパティ                                         |
| -------------------- | --------------------------------- | ----------------------------------------------- |
| OpenTelemetry + OTLP | spring-boot-starter-opentelemetry | management.opentelemetry.tracing.export.otlp.\* |
| Brave + Zipkin       | spring-boot-starter-zipkin        | management.tracing.export.zipkin.\*             |

サンプリング率は`management.tracing.sampling.probability`で調整します。**既定値は0.1で、全リクエストの10%しか送信されません**。開発中にトレースが見当たらない原因の多くはこれです。OpenTelemetryを使う場合はサンプラー自体も`management.opentelemetry.tracing.sampler`で選べます。実務で明示指定する場面はほぼ検証時に限られ、そこで使うのは全件収集の`always-on`です。既定は親スパンの判定を引き継ぐ`parent-based-trace-id-ratio`で、残る`always-off`、`trace-id-ratio`、`parent-based-always-on`、`parent-based-always-off`は、親子関係と比率のどちらを優先するかを細かく制御したい場合の選択肢です。

```
management.tracing.sampling.probability=1.0
management.tracing.export.zipkin.endpoint=http://localhost:9411/api/v2/spans
```

### 2024年以前の記事に残る廃止済み依存の見分け方

Spring BootとOpenTelemetryはこの2年で構成が入れ替わっており、当時の手順をそのまま貼ると依存解決の段階で失敗します。扱いが変わったのは次の依存とプロパティです。

- `io.opentelemetry:opentelemetry-exporter-jaeger`はOpenTelemetry Java 1.35.0（2024年2月9日）で削除されました。Maven Centralでの最終公開版は1.34.1です。JaegerはOTLPを直接受け取れるため、現在はOTLPエクスポータを使います。
- Zipkinへの送信先プロパティは、Spring Boot 3系の`management.zipkin.tracing.endpoint`からSpring Boot 4系では`management.tracing.export.zipkin.endpoint`に変わりました。既定値はどちらも`http://localhost:9411/api/v2/spans`です。
- OpenTelemetryはZipkinサポートを非推奨としており、Spring Boot側の自動設定も**4.2で削除予定**と公式ドキュメントに明記されています。OpenTelemetryとZipkinを組み合わせている構成は、Braveへ切り替えるかOTLP経由に寄せる前提で計画してください。

見分け方は単純で、手元の依存をMaven Centralの`maven-metadata.xml`で引き、最新公開版が数年前で止まっていれば配布終了と判断できます。OpenTelemetry本体の構成要素については[OpenTelemetry（OTel）とは｜3つのシグナル・OTLP・Collector・Prometheusとの違いを解説](/tech/details/3625/)で整理しています。

## よくある質問

### Spring Boot 3系のままでもSpring for GraphQLの可観測性は使えますか？

使えます。Spring Boot 3.5.16が管理するSpring for GraphQLは1.4.6で、Micrometer Tracingは1.5.12です。`graphql.request`や`graphql.datafetcher`といったObservationの計装はSpring for GraphQL側に組み込まれているため、3系でも利用できます。違いが出るのはトレース出力側です。Spring Boot 4.0で導入された`spring-boot-starter-zipkin`や`spring-boot-starter-opentelemetry`は3系に存在せず、公式が案内するOpenTelemetryとZipkinの組み合わせは`spring-boot-starter-actuator`、`micrometer-tracing-bridge-otel`、`opentelemetry-exporter-zipkin`を個別に追加する形です。プロパティも`management.zipkin.tracing.*`のままです。

### GraphiQLを無効にすればスキーマは外部から見えなくなりますか？

なりません。ここは取り違えやすい部分です。スキーマの型定義を外部から読み取れるのはintrospectionという機能で、これはGraphiQLの有効・無効とは独立して**既定で有効**です。GraphiQL自体はそれを利用するツールにすぎません。型定義を公開したくない場合は`spring.graphql.schema.introspection.enabled`をfalseに設定します。GraphiQLを既定のfalseのままにしていても、introspectionを閉じていなければスキーマは読み取れる、と理解してください。

### Observationが1件も記録されないときは何を確認すればよいですか？

まず`ObservationRegistry`が構成されているかを見てください。これが無いとObservationは発行されません。次にサンプリング率で、`management.tracing.sampling.probability`の既定値0.1のままだと10%しか送信されないため、検証時は1.0にします。それでも特定のフィールドだけ出ない場合は計測対象の条件を疑ってください。`graphql.datafetcher`は非自明なフェッチだけが対象で、Javaオブジェクトのプロパティを返すだけのフィールドにはスパンが作られません。

### トレースをJaegerで確認したい場合はどの依存を入れますか？

`spring-boot-starter-opentelemetry`を追加し、`management.opentelemetry.tracing.export.otlp.endpoint`にJaegerのOTLP受信エンドポイントを指定します。JaegerはOTLPをネイティブに受け取れるため、専用のエクスポータは不要です。旧来の`opentelemetry-exporter-jaeger`はOpenTelemetry Java 1.35.0で削除済みで、依存に書いても解決できません。

### 既存のREST APIと同じアプリケーションにGraphQLを追加できますか？

追加できます。GraphQLをHTTPで公開する際に使う`spring-boot-starter-web`はSpring MVCの実装そのものなので、同じアプリケーション内で`@RestController`によるRESTエンドポイントと、`spring.graphql.http.path`（既定`/graphql`）のGraphQLエンドポイントが併存します。既存のREST APIを止めずに、必要な画面から順にGraphQLへ寄せる段階移行が取れるということです。RESTを一度に置き換える必要はありません。

## 関連記事

- [Spring Boot OpenTelemetry導入｜2つのstarterの違いとMaven設定](/tech/details/4692/)
- [Spring Boot 4とは？最新バージョン4.1の変更点・新機能とSpring Boot 3との違いを解説【2026年最新】](/tech/details/10124/)
- [REST APIとGraphQLの違いと使い分け｜選定基準と運用コスト](/tech/details/3591/)
- [GraphQLとは？REST APIとの違い・メリット・デメリットをわかりやすく解説](/tech/details/2924/)
- [OpenTelemetry（OTel）とは｜3つのシグナル・OTLP・Collector・Prometheusとの違いを解説](/tech/details/3625/)

---

出典: [Spring for GraphQLとは？Spring Boot 4.1での実装手順とトレース設定【2026年版】](<https://www.issoh.co.jp/tech/details/4575/>)（株式会社一創）
