はじめに
モダンなWeb開発では、GraphQL, SQL, ORMといった言葉をよく目にします。
それぞれが「どんなものか」は知っていても、「これらがどう連携して動いているの?」と聞かれると意外とスッキリ説明できない、という方も多いのではないでしょうか。少なくとも私はできませんでした。
この記事ではその複雑に見える関係性を「レストランでの注文」に例えながら、自分の復讐も兼ねて誰にでも分かるように解説していきます。
全体像のイメージ
まず、3つの技術がアプリケーション全体の中で、どの位置で活躍しているのかを図で見てみましょう。

このように、それぞれが担当する層(レイヤー)が異なります。有名どころでいうとServerにはRuby on Rails、DatabaseにはMySQLなどがあります。
- GraphQL: クライアントとサーバーの間の対話を担当します。
- SQL: サーバーとデータベースの間の対話を担当します。
- ORM: サーバー内部で、GraphQLの要求をSQLの命令に翻訳します。
では、この関係性をレストランの例え話で見ていきましょう。
レストランの注文に例えると…
この3つの関係性は、レストランの運営にそっくりです。
- お客さん = あなた(フロントエンドのクライアント)
- ウェイター = GraphQLサーバー(API)
- シェフ = データベース (MySQL, PostgreSQLなど)
あなた(お客さん)は、メニューを見ながら、ウェイターに自分の言葉で注文をします。
あなた: 「ステーキのランチセットをください焼き加減はミディアム、ライスは大盛りで。あと、サラダも欲しいな。全部同じタイミングで持ってきて欲しいです。」
この、お客さんとウェイターの間の、柔軟で複雑な会話が GraphQL です。お客さんは、厨房の事情(レシピや調理手順)を一切知る必要はありません。
ウェイターは、あなたの複雑な注文を正確に理解します。そして、厨房の中にいる専門の料理人たちに、的確で単純な指示伝票を渡します。
ウェイター:
- (焼き場担当へ) → 「ステーキ1枚、ミディアムレアで」
- (盛り付け担当へ) → 「大ライス一皿」
- (サラダ担当へ) → 「サイドサラダを一つ」
この、ウェイターが厨房で使う、専門的で、 unambiguous(一意に決まる、一通りにしか解釈できない)な指示言語が SQL です。
厨房の料理人たち(データベース)は、その指示書(SQL)に従って、黙々と手順通りに料理を作り、ウェイターに渡します。
最後にウェイターは各所から上がってきた料理を、あなたが最初に注文した通りにトレンチに乗せてあなたのテーブルに同時に届けます。
この物語におけるウェイターの「翻訳能力」、つまり、お客さんの自由な言葉(GraphQL)を、厨房の専門言語(SQL)に正確に変換し、出てきた料理を再びお客さんの望む形に整える能力こそが、ORM (Object-Relational Mapper) の役割なのです。
Railsでの具体的なコードの流れ
この流れを、Ruby on RailsでGraphQL APIを構築する際の、実際のコードで見てみます。
全体の流れとしてはこんな感じです
Client → GraphQL Query → Rails Server (Controller) → GraphQL Schema/Resolver → ActiveRecord(ORM) → SQL Query → Database → ActiveRecord (ORM)→GraphQL Resolver →GraphQL Engine→Rails Server (Controller)→ JSON Response → Client
1. クライアントからのGraphQLリクエスト(お客さんの注文)
フロントエンドは、以下のようなGraphQLクエリをRailsサーバーに送信します。
query {
user(id: "1") {
id
name
# ユーザーに関連する投稿も同時に要求
posts {
title
}
}
}
2. GraphQLサーバーとリゾルバー(ウェイターの仕事)
Railsサーバーは、このリクエストを受け取ると、graphql-ruby
gemが対応するリゾルバーを呼び出します。リゾルバーには、データを取得するための具体的なロジックが書かれています。
# app/graphql/types/query_type.rb
class Types::QueryType < Types::BaseObject
field :user, Types::UserType, null: true do
argument :id, ID, required: true
end
# userクエリのリゾルバー(具体的な処理)
def user(id:)
# ここでORMであるActiveRecordが使われる
User.find(id)
end
end
3. ORMによって生成されるSQL(厨房への指示書)
ウェイター(GraphQLサーバー)が、User.find(id)
というRubyのコードを、厨房(データベース)の言葉であるSQLに翻訳します。
-- User.find(id) から生成されるSQL
SELECT "users".* FROM "users" WHERE "users"."id" = 1;
-- user.posts を取得するために、さらにもう一つのSQLが生成される
SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = 1;
開発者はSQLを直接書く必要がありません。ORMであるActiveRecord
が、最適なSQLを自動で生成してくれます。
4. フロントエンドへのJSONレスポンス(提供される料理)
データベースから返ってきた結果を、GraphQLサーバーが最初に要求された形に整形し、JSONとしてフロントエンドに返します。
{
"data": {
"user": {
"id": "1",
"name": "田中 太郎",
"posts": [
{ "title": "最初の投稿" },
{ "title": "2番目の投稿" }
]
}
}
}
まとめ
- GraphQLは、クライアントとサーバー間の柔軟なコミュニケーションを実現する「APIの言語」です。
- SQLは、その裏側にあるサーバーとデータベース間の厳密なデータ操作を実現する「データベースの言語」です。
- ORMは、その中間に立ち、開発者がSQLを意識することなく、使い慣れたプログラミング言語でデータベースを操作できるようにする「翻訳家」です。
これらは競合する技術ではなく、それぞれが担当する層で協力し合う、モダンなWeb開発における強力なパートナーなのです。