Scala(Play) & AngularでGraphQLアプリケーション実装
こんにちは!
ネクストビートエンジニアのキムです。
保育施設向けのICTシステム「保育士バンク!コネクト」の開発を担当しています。
今回は以前から興味を持っていたGraphQLについて、Scala(Play)とAngularで実装してみましたので、そちらについて紹介します。
GraphQLとは?
GraphQLはFacebookが作ったGraph Query Languageで、アプリケーションレイヤークエリ言語です。
クライアント側では必要なデータの構造を指定することができ、サーバーはその内容と同一の構造でデータを返します。
GraphQLの構造
GraphQLはQueryとMutation、そしてSubscriptionという3種類のオペレーションタイプが存在します。
- Query
Queryはデータ参照(R)を担当します。 - Mutation
Mutationはデータ作成、修正、削除(CUD)を担当します。 - Subscription
Pub・Subモデルでリアルタイムアプリケーションを構築するためのオペレーションタイプですが、Query、Mutationと仕組みが違い、今回は除外します。
REST APIとの比較
REST APIとの大きな差異はREST APIの場合、URL、Methodなどを組み合わせるため色々なEndpointが存在しますが、GraphQLは1個のURLのみ存在し、そのURLにgqlというクエリをクライアント側で要請する仕組みになっています。
その仕組みで、既存のREST APIの問題である、必要ではないデータを取得する問題(Over-Fetching)、必要なデータが取得できない(Under-Fetching)問題を回避できます。
- Over-Fetching
REST APIではデータモデルが決まっているので、実際フロント側には使っていない項目まで取得してしまう問題がありますが、GraphQLは必要な項目だけをリクエストすることができます。
- Under-Fetching
たとえば、User情報とPost情報が必要な画面の場合、REST APIだとAPIを2回呼び出す必要がありますが、GraphQLではgqlでまとめて実行することで1回のAPIリクエストで全てのデータを取得することができます。
下記の図はREST APIとGraphQLの全体の仕組みを比較したものです。
ScalaでGraphQLサーバー側の作成
ScalaでGraphQLのサーバーサイドを実装するためのライブラリは2種類存在しています。
今回はSangriaというGraphQLライブラリを使用してScalaのGraphQLのアプリケーションを作成しました。
SangriaライブラリにはAkka HttpとPlay Framework用のサンプルコードが用意されていて、参考にしながら環境構築することができます。
Play FrameworkにSangriaライブラリを利用するために必要な設定は下記となります。
Controller
Controllerについては1個のPOSTメソッドの/graphqlというEndpointから全ての処理を行います。
クライアントから送信されるデータは大きく3つの項目で構成されます。
- query
GraphQLを実行するためのクエリ - operationName
GraphQLのオペレーションタイプ(QueryかMutationか) - variables
引数として使う項目
リクエストで送信されたJSONデータより、上記のquery、operationName、variablesを取得します。
executeQueryには実際の処理を行います。
QueryParserにはQueryが正しく書かれているかをチェックします。それからSyntaxエラーが発生する場合は、エラーを返すように制御されています。
Queryに問題がない場合、Schema、Operation、Variablesを指定してGraph QLクエリを実行します。この段階ではmiddlewareというプロパティーで、HTTPヘッダーなどをクエリを実行する前にチェックすることができます。
Schema
GraphQLのSchemaはQueryとMutationに分かれいてその下にFieldというクエリ処理の詳細を書きます。ここから指定したSchemaが上記のControllerに設定され、リクエストのGqlが有効かを検証し、有効の場合は実際処理するResolverというビジネスロジックを呼び出します。Schemaはそのビジネスロジックを指定するまでの役割を持っています。
Queryの明細を作成します。各Fieldのプロパティーは例よりもっと多いですが、機能するために必要なものとして下記4つがあります。
- name
Fieldの名前の指定 - fieldType
Queryを実行することで戻されるデータの型を指定 - arguments
Queryに引数が必要な場合、その引数を指定 - resolve
実際に実行される処理を記述
Mutationの場合もQueryと一緒で、Fieldの名前や引数、実際の処理を記述します。
Resolver
Resolverにはビジネスロジックを作成します。
例のコードはRepositoryの結果をそのまま返すように実装されていますが、場合によっては複雑なビジネスロジックを作成することができます。
GraphQL PlayGround
作成したSchemaはGraphQLから提供しているPlayGroundというIDEツールから確認することができます。
直接QueryやMutationを実行することもでき、右側には実装したQueryとMutationの明細が確認できます。
AngularでGraphQLクライアント側の作成
AngularからGraphQLクライアントを実現するためのライブラリはApolloが唯一の選択肢でしたので、こちらを使ってAngularでGraphQLを実装しました。
- Apollo Angular
https://apollo-angular.com/docs/ - Apollo Angularのインストール
yarn add @apollo/client apollo-angular graphql
Module
GraphQLを使用するための基本的な設定をモジュールで作成します。作ったモジュールはapp.module.tsファイルにimportします。
gql作成
GraphQLサーバーに要請するQueryとMutationを作成します。
Apollo Angular中には、gqlというモジュールが存在し、QueryとかMutationを作成しgqlで囲むことで、gqlのことを示します。
- Query
- Mutation
上記の例はtsファイルに変数として定義した方法ですが、.graphqlファイルを作成し、そのファイルからgqlを作成し管理することもできます。
.graphqlファイルで管理するメリットとしては、IDEからGraphQLの拡張機能とかを使ってgqlの有効性を確認することができるどころです。
Service
実際サービスに定義したgqlを使用してサーバー送信ロジックを作成します。Apollo AngularはQueryの場合watchQueryというメソッドを使ってgqlでサーバーからデータを取得します。
Mutationの場合、mutationというメソッドがApolloモジュールの中に存在し、そのメソッドの使用してサーバーに作成、更新、削除をリクエストすることができます。
Component
作成したサービスをコンポーネントで呼び出して画面に取得したデータを反映、入力したデータを作成、削除処理などを行います。
GraphQL通信の確認
終わりに
今回はScalaのPlay FrameworkとAngularでGraphQLアプリケーションを簡単に紹介しましたが、興味がある方は、以下の実装コードを参考にして頂ければと思います。
次回はGraphQLのSubscriptionを使って、リアルタイムチャットアプリケーションを実装してみてまた紹介して行こうと思います。
最後まで読んでいただきありがとうございました!
今回実装したコード
使用したライブラリ
サーバーサイド
- Scala(2.13.7)
- Play Framework(2.8.0)
- Slick(3.3.2)
- Sangria(2.0.1)
フロントエンド
- Angular(13.1.0)
- apollo-angular(3.0.0)
- @apollo/client(3.5.8)
参考
- GraphQL — https://graphql.org/
- Scala Sangria — https://sangria-graphql.github.io/
- Apollo Angular — https://apollo-angular.com/
We are Hiring!
「人口減少社会において必要とされるインターネット事業を創造し、ニッポンを元気にする。」
を理念に掲げ一緒に働く仲間を募集しております。
バックエンドにはPlay Framework(言語はScala)、フロントエンドの開発には主にAngularを用いています。フルスタックに開発したい!という方のご応募をお待ちしております。