Scala(Play) & AngularでGraphQLアプリケーション実装

Dongjin Kim
nextbeat-engineering
11 min readMar 7, 2022

こんにちは!

ネクストビートエンジニアのキムです。
保育施設向けの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の全体の仕組みを比較したものです。

Rest APIと比較

ScalaでGraphQLサーバー側の作成

ScalaでGraphQLのサーバーサイドを実装するためのライブラリは2種類存在しています。

今回はSangriaというGraphQLライブラリを使用してScalaのGraphQLのアプリケーションを作成しました。

SangriaライブラリにはAkka HttpとPlay Framework用のサンプルコードが用意されていて、参考にしながら環境構築することができます。

Play FrameworkにSangriaライブラリを利用するために必要な設定は下記となります。

Play Frameworkでsangriaを利用するためのライブラリ

Controller

Controllerについては1個のPOSTメソッドの/graphqlというEndpointから全ての処理を行います。

エンドポイントは一つ

クライアントから送信されるデータは大きく3つの項目で構成されます。

  • query
    GraphQLを実行するためのクエリ
  • operationName
    GraphQLのオペレーションタイプ(QueryかMutationか)
  • variables
    引数として使う項目

リクエストで送信されたJSONデータより、上記のquery、operationName、variablesを取得します。

Controller処理

executeQueryには実際の処理を行います。
QueryParserにはQueryが正しく書かれているかをチェックします。それからSyntaxエラーが発生する場合は、エラーを返すように制御されています。

Queryに問題がない場合、Schema、Operation、Variablesを指定してGraph QLクエリを実行します。この段階ではmiddlewareというプロパティーで、HTTPヘッダーなどをクエリを実行する前にチェックすることができます。

Schema

Schema構造

GraphQLのSchemaはQueryとMutationに分かれいてその下にFieldというクエリ処理の詳細を書きます。ここから指定したSchemaが上記のControllerに設定され、リクエストのGqlが有効かを検証し、有効の場合は実際処理するResolverというビジネスロジックを呼び出します。Schemaはそのビジネスロジックを指定するまでの役割を持っています。

Queryの明細を作成します。各Fieldのプロパティーは例よりもっと多いですが、機能するために必要なものとして下記4つがあります。

  • name
    Fieldの名前の指定
  • fieldType
    Queryを実行することで戻されるデータの型を指定
  • arguments
    Queryに引数が必要な場合、その引数を指定
  • resolve
    実際に実行される処理を記述
Queryの明細作成

Mutationの場合もQueryと一緒で、Fieldの名前や引数、実際の処理を記述します。

Mutationの明細作成

Resolver

Resolverにはビジネスロジックを作成します。
例のコードはRepositoryの結果をそのまま返すように実装されていますが、場合によっては複雑なビジネスロジックを作成することができます。

GraphQL PlayGround

作成したSchemaはGraphQLから提供しているPlayGroundというIDEツールから確認することができます。

直接QueryやMutationを実行することもでき、右側には実装したQueryとMutationの明細が確認できます。

AngularでGraphQLクライアント側の作成

AngularからGraphQLクライアントを実現するためのライブラリはApolloが唯一の選択肢でしたので、こちらを使ってAngularでGraphQLを実装しました。

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)

参考

We are Hiring!

株式会社ネクストビートでは

「人口減少社会において必要とされるインターネット事業を創造し、ニッポンを元気にする。」
を理念に掲げ一緒に働く仲間を募集しております。

バックエンドにはPlay Framework(言語はScala)、フロントエンドの開発には主にAngularを用いています。フルスタックに開発したい!という方のご応募をお待ちしております。

--

--