gqlgenでGraphQLサーバーを立ててみる

gqlgenとは

gqlgenとはGraphQLのSchemaベースでGraphQLサーバーの開発を進めるためのライブラリです。最近ではでmercariがmercari tech conf 2018のサーバーのプログラムをGraphQLで書いていて、「お」と目を見張りました。今回はそんな gqlgen の導入部分を記載していきたいと思います

なおGraphQL自体についてはこの記事では割愛します。
GraphQLについて知りたい方は公式のページがあるのでこちらをご覧いただければと

本題に入る前に

導入部分を書く前にこの記事を書いた時点でのgqlgenの情報を載せておきます。
この記事を書く時点での最新のtree
この記事を書く時点での公式のドキュメント

本題

最新のドキュメントはここから確認できます。本記事でもこちらを参考にしながら話を進めます。が、多少割愛してまずはGraphQLとして機能するサーバーを立ち上げることを目標にします。Getting Startedをまず見ていきましょう。

まずライブラリのインストールです。 dep等のパッケージマネージャーを使っている人は適宜変えてください。

$ go get -u github.com/99designs/gqlgen github.com/vektah/gorunpkg

さて、インストールが終わったら gqlgen init を実行してしまいましょう。あらかじめ用意しておいてGitリポジトリを使っている前提で git statusでどんなファイルができたか確認します。

$ gqlgen init
Exec "go run ./server/server.go" to start GraphQL server
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        generated.go
        gqlgen.yml
        models_gen.go
        resolver.go
        schema.graphql
        server/

gqlgen initの実行により下記のファイルたちが作られました。 それぞれの役割を簡単に記述していきます。

  • schema.graphql
    • GraphQLのスキーマを書く
    • 書かれたスキーマgqlgen generate を経て各 .go ファイルに Golangのコードとして内容が記載される
  • generated.go
    • gqlgen generateでこのファイルの中にGraphQLの処理に必要な処理が吐かれる
    • schema.graphqlで記載したスキーマ情報やそれに沿ったResolverTypeの情報
  • gqlgen.yml
    • gqlgen generateの際にプロダクションによってカスタマイズしたい場合に記載する設定ファイル
    • 何が設定できるかはここを参照
  • models_gen.go
    • gqlgen generateの際にGraphQLのType等を Golangstruct が書かれる
    • schema.graphqlに記載されたものからコードが作られる
    • Resolver 以外のものがここに吐き出されると思ってもらえたらいいかも。 Type,Input,Scalar,Enum and so on...
  • resolver.go
    • gqlgen generateの際にGraphQLのQueryMutationの処理を書くためのResolverが用意される。
    • Resolverは各Query(or Mutation)を処理するためのメソッドを持っている。それを処理する役割と捉えてもらえると。他のフレームワークやライブラリでもこの用途でResolverという名前で出てくる。
    • Type が 1つ以上のfieldを持つ場合もここに吐き出される。
  • server/server.go
    • go run ./server/server.go でサーバーを試せるようになっている

さて、これで実はデモを試す最低限の準備はできてしまいました。
gqlgen init の時点でExampleに必要なSchemaやそれに沿ったGolangのコードが生成されています。
Todoという例でドキュメントには書かれています。今の状態でこれと同じものができています。便利。

ではローカルホストにサーバーを立ち上げ、 http:localhost:8080 にアクセスします。

$ go run ./server/server.go

下記のようなページが立ち上がれば成功です。

これはGraphQL PlaygroundCDNを利用して立ち上げています。GraphQL PlaygroundGraphQL IDEという立ち位置みたいですね。このツールでQueryをインタラクティブに確認することができます。
というわけで下記のQueryを書いて動作を確認してみます。

query {
  todos {
    id
  }
}

結果がjsonで帰ってきたのが右側の画面を見て確認できると思います。
しかし、実行してみると何やらエラーが出ています。エラーが起きずに正しくデータが取得できている場合はdataの項目にtodosの結果が返ってきて、errorsの方はフィールド自体が存在しないはずです。

なぜエラーが返ってきたのかなのですが、gqlgenではQueryを処理する役割のResolverのコードが生成された時点ではpanicを呼ぶコードが埋め込まれています。当たり前のことなのですが、GraphQLのインタフェースを通った後の内部の処理はその都度書く必要が出てきます。gqlgenではコード生成されたタイミングで下記のようなテンプレなコードが埋め込まれています。これは resolver.go を見て確認することができます。

func (r *queryResolver) Todos(ctx context.Context) ([]Todo, error) {
    panic("not implemented")
}

では、ここに[]Todo 型の値を返すようにコードを下記のように変更してあげましょう。

func (r *queryResolver) Todos(ctx context.Context) ([]Todo, error) {
    return []Todo{Todo{ID: "1"}, Todo{ID: "2"}, Todo{ID: "3"}}, nil
}

雑ですが、配列で3つの要素を返してあげています。
$ go run ./server/server.go を再度実行してみて動作を確認してみましょう。先ほど遠同じQueryを投げてみます。 下記のように表示されていれば成功です。

終わりに

これで gqlgen を導入して GraphQLサーバーを立ち上げるところまでできました。次回は実際にschema.grpahqlを編集してgqlgen generateでコード生成をするといったことも書けたらと思っています。

GitHubにここまでの内容を公開しています。
https://github.com/bannzai/gqlgen-demo

branchは introduction/gqlgen となっています
https://github.com/bannzai/gqlgen-demo/tree/introduction/gqlgen

この記事がいいと思ったら、GitHubのスターください

おしまい \(^o^)/