LoginSignup
2
1

GraphQLについて少し調べた

Last updated at Posted at 2022-03-15

GraphQL用語

Schema

  • APIのこと。
  • クライアントがサーバーにクエリを送信した時に、返却値として期待されるオブジェクトの型定義。
    • type キーワードによってGraphQLオブジェクトの型を定義する(その集合がSchema)。
    • 以下の例において、 id, text, done, user, createTodo などを field(フィールド) と呼ぶ。
# graph/schema.graphqls
type Todo {
  id: ID!
  text: String!
  done: Boolean!
  user: User!
}

type User {
  id: ID!
  name: String!
}

type Query {
  todos: [Todo!]!
}

input NewTodo {
  text: String!
  userId: String!
}

type Mutation {
  createTodo(input: NewTodo!): Todo!
}

Resolver

  • フィールド(CreateTodo, etc)の実装。
  • クライアントが要求したフィールドの値を返却するための関数。
    • フィールドをresolve(解決する)ので resolver
// graph/schema.resolvers.go
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
	todo := &model.Todo{
		Text:   input.Text,
		ID:     fmt.Sprintf("T%d", rand.Int()),
		User:   &model.User{ID: input.UserID, Name: "user " + input.UserID},
		UserID: input.UserID,
	}
	r.todos = append(r.todos, todo)
	return todo, nil
}



func (r *todoResolver) User(ctx context.Context, obj *model.Todo) (*model.User, error) {
	return &model.User{ID: obj.UserID, Name: "user " + obj.UserID}, nil
}

Query

  • データの取得を行う言語。
  • HTTP GETに相当。
  • サーバーの schema で定義された「オブジェクトの型 type 」に、クライアントから取得可能な field が定義されている。
query findTodos {
  todos {
    text
    done
    user {
      name
    }
  }
}

queryのレスポンス

{
  "data": {
    "todos": [
      {
        "text": "todo",
        "done": false,
        "user": {
          "name": "user 1"
        }
      }
    ]
  }
}

Mutation

  • データの作成・更新・削除を行う言語。
  • HTTP POST/PUT/DELETEに相当。
mutation createTodo {
  createTodo(input: { text: "todo", userId: "1" }) {
    user {
      id
    }
    text
    done
  }
}

mutationのレスポンス

{
  "data": {
    "createTodo": {
      "user": {
        "id": "1"
      },
      "text": "todo",
      "done": false
    }
  }
}

Data source(ApolloServerを利用した場合)

  • ApolloServerが、DBやREST APIなどから取得したデータをカプセル化し、キャッシュやエラー処理を行えるようにするためのクラス。
    • 接続先毎に作成する。
    • resolver から利用される。
    • Data sourceの例
      • RailsのREST APIのHTTPクライアント
      • ElasticSearchクライアント
      • DynamoDBクライアント

GraphQLとRESTの比較

REST GraphQL
参照 リクエスト(GET) クエリ(query)
作成・更新・削除 リクエスト(POST/PUT/DELETE) クエリ(mutation)
Pub/Sub なし
(WebSocketを使う場合が多い)
クエリ(subscription)
サーバの記述 ルーティングとコントローラ スキーマ(schema・type) / リゾルバ(resolver)

(エンドポイントは1つになるためルーティングの定義は最初の一回を除いて不要(なはず))

REST API運用の課題

  • サーバーサイドでユースケース毎にAPIが増える。
  • クライアントサイドでドメインロジックを作ったり、状態を持つ必要性が出る。

GraphQLのメリット

  • クライアントサイドとサーバーサイドのコミュニケーションコストの削減。
    • グラフ構造でリレーションを表現できるので、サーバーサイドはユースケース毎のAPIを作る必要がなくなり、クライアントサイドでそのまま表示できるようなクエリを作れば良い。(?)
    • クライアントサイドは利用可能な全ての状態がわかり、必要なデータを選択できる。
  • GraphQLクライアント(Appolo、Relayなど)を利用すると、グラフ構造をキャッシュしてくれる。これにより、
    • クライアントサイドは状態を持つ必要がなくなる。

GraphQLのデメリット

よくある誤解

Q. DB構造をクライアントにそのまま公開してしまうのでは?
A. Hasuraを使った場合、DB構造からGraphQLスキーマを自動生成するが、これはRESTでも同様。

参照

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1