Black Belt Online Seminarで学んだAWS AppSyncをベースにまとめる

AWS AppSyncの利用の検討に伴い、[【AWS Black Belt Online Seminar】AWS AppSync](https://www.youtube.com/watch?v=89NGPaxZlW0&t=2116s)を見てどんなことができるか記載した。

## AWS AppSyncとは
GraphQLのマネージドサービスですぐにGraphQLを開始できる。

## AWS AppSyncの特徴

* GraphQLのマネージドサービス
* アカウントのDataSourceに接続
* データ同期、リアルタイム、オフライン機能を保持していること
* GraphQLファサード（複雑な内部処理を意識させることなく利用者にシンプルなインタフェースを提供するパターン）であること
* 競合の検出と解決
* セキュリティとしてAPI Key, IAM, Cognito, OIDCが利用可能


## 開発者の課題解決
* リアルタイムコラボレーション
* 同期を考慮したオフラインプログラミング
* 必要なデータのみの取得
* 複数のデータソースへのアクセス
* セキュリティを利用したアクセス制御


## ユースケース
AWS AppSyncでは3つの大きなユースケースがある。
* リアルタイム
  * 最新の情報をウォッチするダッシュボード
  * ほぼリアルタイムでデータを更新 
* コラボレーション
  * 複数ユーザが共同編集を行うアプリケーション
  * ドキュメント、画像、テキストメッセージ等、様々なコンテンツタイプを自動更新
* ソーシャルメディア
  * ソーシャルメディアやチャット
  * 複数ユーザ間でのメッセージング管理をサポート
  * オフライン時でもアプリケーションを操作でき、再接続時に自動Sync
 

## AWS AppSyncのコンセプト
* **AWS App Sync Client**：認証、オフラインロジックなどを含んだClient
* **Resolver**：リクエスト/ レスポンスの処理を記述する関数
* **Data Source**：DynamoDB/ Lambda/ Aurora Serverless（RDS）/ Elasticsearch/ HTTP Endpoint.（DynamoDBを利用する人が多い）
* Identity：GraphQL Proxyへのリクエスト認証
* GraphQL Proxy：リクエストのマッピング、コンフリクトのハンドリング、アクセスコントロール
* Operation：Query/ Mutation/ SubscriptionなどGraphQLのオペレーション

## 迅速なプロトタイピング
AppSyncの試行ステップ
`Schema定義` → `DataSourceとの接続` → `クライアントの設定`となる。

### Schema定義
* スキーマはサーバの機能を記述し、クエリが有効か透過を判断するために使われる。
* GraphQL APIは1つのGraphQL Schemaで定義され、SDL（Schema Definition Language）によって記述される
* Schemaの書き方
```proto
type Query {
  # スカラー型、オブジェクト型、列挙型を利用可能 
  # リストが角かっこで表現
  getTodos:[Todo]
}
typeTodo {
  # Not Nullは感嘆符で表現
  id:ID!
  name:String
  description:String
  status:TodoStatus
}
enum TodoStatus{
  done
  pending
}
```


### Datasourceとの接続
DatasourceとAppSyncを繋ぐResolverについて

#### Resolver マッピングテンプレート　について
* マッピングテンプレートは、GraphQLリクエストをデータソースの命令に変換する方法とデータソースからの応答をGraphQLレスポンスに変換する方法を定義する。
* Resolverマッピングテンプレートは、`VTL（Velocity Template Language）`によって記述される。

#### Resolver マッピングテンプレートで実施する例
* アクセスコントロール 
* 新規アイテムのデフォルト値
* 入力のバリデーション、フォーマット
* データの変換と整形
* リスト、マップの加工
* ユーザーIDに基づいたレスポンスのフィルタリング/ 変更
* 複雑な権限チェック

#### 2種類のマッピングテンプレート
マッピングテンプレートにはRequest用とResponce用の2種類が存在する。

##### Requestテンプレート（Request -> DataSource命令）
例:
```
{
  "version" : "2017-02-28",
  "operation" : "GetItem",
  "key" : {
    "id" : {"S" : "${context.atguments.id}"}
  }
}
```
##### Responceテンプレート（DataSource応答 -> GraphQL Responce）
デフォルトで返す場合：
```
$ utils.toJson($context.result)
```
データを統合する場合：
```
{
  "id" : ${context.data.id},
  "title" : "${context.data.theTitle}",
  "content" : "${context.data.body1} ${context.data.body2}"
}
```

#### マッピングテンプレート記述方法
* AppSync上のエディタで直接記述
* No-code GraphQL API Builderを利用
* 記述したSchemaからリゾルバマッピングを直接ジェネレート
* 既存のDynamoDBをデータソースとして指定した場合、そのテーブル定義からマッピングテンプレートをジェネレート

### クライアントの設定
#### GraphQL Endpointへの接続情報
APIキーを利用した例
```
export default {
    "graphqlEndpoint": "https*//**.appsync-api.**.amazon.com/graphql",
    "region": "us-east-1",
    "authenticationType": "API_KEY",
    "apiKey": "***"
}
```

#### クライアントの諸々の設定例
クライアントの設定例
```
const client = new AWSAppSyncClient({
url: awsconfig.ENDPOINT,
region: AWS.config.region,
auth: { type: AUTH_TYPE.AWS_IAM, credentials: Auth.currendCredentials() }
})
const WithProvider = () => (
    <ApolloProvider client={client}>
        <Rehydrated>
            <AppWithData /> 自動でオフライン利用が可能に
        </Rehydrated>
    </ApolloProvider>
);
```
※ AWS Amplifyから流し込むことも可能。その際にはオフライン利用できるテンプレートも作成される。

#### クライアント認証例
APIキーを利用して認証するテンプレート構成例
```
// API Key
const client = new AWSAppSyncClient({
    url: awsconfig.ENDPOINT,
    region: awsconfig.REGION,
    auth: {type: AUTH_TYPE.API_KEY, apiKey: awsconfig.apiKey}
});
```

IAM認証の例
```
// IAM認証
auth: { type: AUTH_TYPE.AWS_IAM,
    credentials: Auth.currentCredentials()
}
```

Cognito認証の例
```
auth: { type: AUTH_TYPE.AMAZON_COGNITO_USER_POOLS,
    jwtToken: Auth.currentSession().accessToken.jwtToken
} 
```

## API Gatewayとどっちが良い（動画にはない）
API Gatewayは1つのAPIで複数のエンドポイントを提供できる一方で、
AppSyncはGraphQLコードを受け付ける1つのエンドポイントしか提供しない。

結論GraphQLのときは AppSync、RestのときはAPI Gatewayが良い。
ただし、GraphQLを使うかRestを使うかはユースケースによる。


## 料金

||価格|
| -- | -- |
| クエリとデータ変更操作 | $4.00 / 100万件 |
| リアルタイム更新 | $2.00 / 100万件|
| リアルタイム更新 接続時間（分） | $0.08 / 100万分 |

## 参考
* [AppSync VS APIGateway 両者の違いをスタートアップCTOが本気で考えてみた！](https://www.ragate.co.jp/blog/articles/245)