7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

弥生Advent Calendar 2022

Day 18

AWS CDKでAppSyncを構築してみた

Last updated at Posted at 2022-12-17

この記事は弥生 Advent Calendar 2022の18日目の記事です。

こんちには、2022年7月に入社したバックエンドエンジニアの永野です。

弥生にはエンジニアリンググループという取り組みがあり、
そこで検証したAWS CDKでAppSyncを構築する方法について、ご紹介しようと思います。

なお、今回はAWS CDKとAppSync、またGraphQLについての説明は割愛させていただきます。
すでに詳しい記事が世に沢山あることと、そもそも私自身が実は上記に触るのが初めてで、知るより慣れろということで、手を動かすことをメインに取り組みを進めてきたためです。

エンジニアリンググループとは

技術情報やノウハウの蓄積/共有を行い、エンジニアを育成するためのバーチャルグループです。
毎週水曜日に2~3時間ほど活動を行っています。

活動内容はグループごとに決めています。私が参加しているグループでは、直近はAWSのスキルアップを目的に、各自がハンズオンの実施やサービスの調査・検証などを行い、その結果の共有や意見交換を行っております。

ちなみに、この活動のために限らずですが、弥生では申請すればAWSの勉強用環境を利用することができるので、AWS利用コストを気にせず自己学習を進めることができます。

今回実装するもの

AppSyncで下記2つのコマンドを持つGraphQL APIを実装します。

1. addBookFromIsbnミューテーション

リクエストで送ったISBNコードでGoogleBooksAPIから書籍情報を取得して、それをDynamoDBに登録する操作を行うコマンドです。
データソースとしてLambdaを使用して、LambdaHandlerの中で必要な処理を行います

2. allBooksクエリ

DynamoDBに登録されている全書籍データを取得するコマンドです。
データソースとしてDynamoDBを使用して、AppSyncから直接データを取得して呼び出し元に返します。

AppSyncDemo.png

事前準備

AWS CDK の使用を開始する 入門ガイドに記載のとおり、CDKを使用するためにAWS CLIとNode.JSのインストールが事前に必要です。
今回はWindowsマシーンで開発を行うので、Windowsで使用できるパッケージマネージャのWingetでインストールしていきます。

Node.JSのインストール

winget install -e --id OpenJS.NodeJS.LTS

AWS CLIのインストール

winget install -e --id Amazon.AWSCLI

認証情報は、名前付きプロファイルを利用して保存しておきます。
また、今回はAWS SSOで認証するので、aws sso configureコマンドを実行し、プロンプトに対話的に表示される設問に対して入力していきます。(参考)

aws configure sso --profile enggrp 

設定後はログインしている状態となりますが、時間が経ってから利用する場合は、
aws sso loginコマンドでログインをしておいてください。

aws sso login --profile enggrp

CDKプロジェクトの作成

さて、事前準備が終わったところで、さっそくCDKを利用するためのプロジェクトを作成していきます。

まずは、今回プロジェクトを作成するフォルダの中で、cdk initコマンドを使用してプロジェクトを作成します。

npx cdk@latest init app --language typescript

実行するとフォルダの中にCDKのプロジェクトが作成されます。
自動作成されたフォルダとファイルに、いくつか手動で追加して今回使用する全てのファイルとなります。
(手動追加と記載しているものは、後述の中で作成していくものです)

📦eng-grp-cdk-appsync
 ┣ 📂bin
 ┃ ┗ 📜eng-grp-cdk-appsync.ts
 ┣ 📂graphql                          # 手動追加
 ┃ ┗ 📜schema.graphql                 # 手動追加
 ┣ 📂lambda                           # 手動追加
 ┃ ┣ 📜appsync-resolver.ts            # 手動追加
 ┃ ┗ 📜graphql.ts                     # 手動追加(コードジェネレータで生成する)
 ┣ 📂lib
 ┃ ┗ 📜eng-grp-cdk-appsync-stack.ts
 ┣ 📂node_modules
 ┣ 📂test
 ┃ ┗ 📜eng-grp-cdk-appsync.test.ts
 ┣ 📜.gitignore
 ┣ 📜.npmignore
 ┣ 📜cdk.json
 ┣ 📜codegen.ts                       # 手動追加
 ┣ 📜jest.config.js
 ┣ 📜package-lock.json
 ┣ 📜package.json
 ┣ 📜README.md
 ┗ 📜tsconfig.json

プロジェクトの作成が終わったら、最後にAWSアカウントのブートストラップを行います。

npx cdk bootstrap --profile enggrp

追加パッケージのインストール

今回の実装や作業で使用するnpmパッケージを追加していきます。

aws-cdk/aws-appsync-alpha

今回AppSyncを構築するにあたって、L2コンストラクトを使用したいです。
CDKはV2から、安定版(stable)のAPIはaws-cdk-libパッケージに全リソースのものが含まれています。
一方で、実験的な(experimental)APIは、aws-cdk-libには含まれず、別のパッケージで提供されます。(参考)
AppSyncのL2コンストラクトはまだ、experimentalなものしかないので、そちらを追加でインストールします。

npm install @aws-cdk/aws-appsync-alpha

このように末尾に-alphaと付いているものが、experimental apiになります。

esbuild

NodejsFunctionコンストラクトが、TypeScriptで実装したLambdaHandlerをトンランスコンパイルやバンドルをするために使用します。

今回、LambdaについてもTypeScriptを使用して実装します。
CDKのNodejsFunctionコンストラクトを使うとTypeScriptで実装したコードに対して、自動でトランスコンパイルやバンドルをしたLambda関数を作成してくれるのです。楽ちんです。

そのコンパイル作業をDockerコンテナ内で実行させることもできるのですが、今回はローカルにesbuildをインストールして使用して行います。
esbuildがインストールされている場合、自動でこちらを使用します。

npm install -D esbuild

types/aws-lambda

TypescriptでLambda関数ハンドラーを扱うための型定義をインストールします。

npm install -D @types/aws-lambda

aws-sdk dynamodb関連パッケージ

今回作成するLambda関数の中でDynamoDBを扱うため、
DynamoDB操作のクライアントとユーティリティをインストールします

npm install @aws-sdk/client-dynamodb @aws-sdk/util-dynamodb

axios

HTTPクライアントとしてaxiosをインストールします。
Lambda関数内で、GoogleBookAPIとのやり取りをするために使用します。

npm install axios

コードジェネレータ

GraphQLスキーマからTypeScriptの型定義のコードを作成するために使用するパッケージをインストールします。

npm install -D @graphql-codegen/cli @graphql-codegen/typescript

GraphQLスキーマの定義

まず、今回AppSyncを使って作成するGraphQL APIのスキーマ定義を外部ファイルとして作成しておきます。
CDKでリソースを作成する際に、こちらのファイルを読み込んでAppSyncのスキーマ定義を実装します。
また、Lambdaを作成する際に、スキーマ定義からTypeScriptの型定義を生成するためにもこのファイルを使用します。

# graphql/schema.graphql

scalar AWSDate

type Book {
  id: ID!
  title: String!
  subtitle: String
  isbn: String
  authors: [String]
  publishedDate:AWSDate
  thumbnailLink: String
}

type Mutation {
  addBookFromIsbn(isbn: String!): Book
}

type Query {
  allBooks: [Book]
}

AWSDateはAppSyncでデフォルトで使用できる日付型のスカラー定義です。
スキーマ定義上で型として使用する分には、いちいちスカラー定義を再度しなくても使用できるのですが、今回は後述で出てくるコードジェネレータに認識させるために定義をしています。
AppSyncで使用できるスカラー型はこちらに記載があります。

LambdaHandlerの実装

次にLambda関数としてデプロイするLambdaHandlerを実装してしまいます。
今回のLambdaは、受け取ったISBNをもとに、Google Books APIに問い合わせをして書籍情報を取得してDynamoDBに登録する処理を行います。

GraphQLスキーマからTypeScriptの型定義を作成

まず、コードジェネレータというツールを使って、GraphQLスキーマからTypeScriptの型定義のコードを作成します。

設定ファイルの作成

コードジェネレータの挙動を決める設定ファイルをプロジェクトルートに作成します。
作成したソースは下記になります。

codegen.ts
import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  overwrite: true,
  schema: "./graphql/schema.graphql", 
  generates: {
    "./lambda/graphql.ts": { 
      plugins: ["typescript"], 
    },
  },
  config: {
    skipTypename: true,
    useTypeImports: true,
    scalars: {
      AWSDate: "Date", 
    },
  },
};

export default config;

 
少しピックアップして見てみます。

スキーマ情報の取得先パスを指定

  schema: "./graphql/schema.graphql", 

今回は、スキーマ情報の取得元として、前の手順で作成したGraphQLのスキーマ定義を記載しているファイルを指定します。

本来は、AppSyncを先に作成して公開したエンドポイントを取得元に指定して、各種サーバやクライアント側で使用する型定義を生成するのが正しそうですが、今回はLambdaも同時にデプロイする都合上、ローカルのファイルに定義しているスキーマ情報から型を生成します。

生成されるファイルパスと生成に使用するプラグインの指定

  generates: {
    "./lambda/graphql.ts": { 
      plugins: ["typescript"], 
    },
  },      

generatesには、生成されるファイルのパスをキーに、使用するプラグインの情報などを記載していきます。
つまり、複数のプラグインを使って別々のファイルを同時に生成することも可能です。
プラグインについては、今回Lambdaの中ではスキーマに基づく型定義しか使用しないので、@graphql-codegen/typescript のみを使用します。

オプション設定を指定

  config: {
    skipTypename: true,
    useTypeImports: true,
    scalars: {
      AWSDate: "Date", 
    },
  },    

生成にかかわるオプション設定を指定していきます。

ポイントになるのはscalarsで、これは定義したスカラーをTypeScript上のどの型に変換するかを指定します。
今回はコードジェネレータがデフォルトで認識できない、AWSDateをDate型に変換するように指示しています。他の型はデフォルトで変換される型が決まっているので特に指定不要です。

ソースコードの生成を実行

設定ファイルが準備できたら、下記コマンドを使用して、コードを生成を実行します。

npx graphql-codegen --config codegen.ts 

実行の結果lambda/graphql.tsが生成されます。この中にTypeScriptで使用できる型定義が含まれているので、LambdaHandlerのソースコードにインポートして使用します。

Lamdba Handlerの実装

次にLambda Handlerとして使用するソースコードを作成します。
Lambda Handlerのソースは、今回はCDKのプロジェクト内に作成して、後々スタックのコードから相対パスで指定します。

作成したソースは下記になります。

lambda/appsync-resolver.ts
import { AppSyncResolverHandler } from "aws-lambda";
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall } from "@aws-sdk/util-dynamodb";
import axios from "axios";
import { randomUUID } from "crypto";
import { Book, MutationAddBookFromIsbnArgs } from "./graphql";

const httpClient = axios.create({
  baseURL: "https://www.googleapis.com/books",
});
const dbClient = new DynamoDBClient({});

export const handler: AppSyncResolverHandler<
  MutationAddBookFromIsbnArgs,
  Book
> = async (event, context) => {
  try {
    const response = await httpClient.get<GoogleApiResponseData>(
      "/v1/volumes",
      {
        params: {
          q: `isbn:${event.arguments.isbn}`,
        },
      }
    );
    const responseData = response.data.items[0];
    if (!responseData) {
      throw new Error("GoogleBookApiからデータが取得できません");
    }
    // DynamoDbに登録
    let data: Book = {
      id: randomUUID(),
      title: responseData.volumeInfo?.title,
      subtitle: responseData.volumeInfo?.subtitle ?? "",
      isbn: event.arguments.isbn,
      authors: responseData.volumeInfo?.authors ?? [],
      publishedDate: responseData.volumeInfo?.publishedDate ?? null,
      thumbnailLink: responseData.volumeInfo?.imageLinks?.thumbnail ?? "",
    };
    await dbClient.send(
      new PutItemCommand({
        TableName: "books",
        Item: marshall(data),
      })
    );
    return data;
  } catch (err) {
    console.error(err);
    throw new Error(`データ登録に失敗しました。`);
  }
};
interface GoogleApiResponseData {
  items: BookItem[];
  kind: string;
  totalItems: number;
}

interface BookItem {
  id: string;
  volumeInfo: {
    title: string;
    subtitle?: string;
    authors?: string[];
    publishedDate?: Date;
    imageLinks?: {
      thumbnail?: string;
    };
  };
}

内容については、今回のメインから外れるので割愛しますが、
ポイントとしては、コードジェネレータを使用して生成した型を使うことで、handlerの引数と戻り値の型定義を、スキーマで定義した addBookFromIsbn Mutationの型定義と一致させられることです。

export const handler: AppSyncResolverHandler<MutationAddBookFromIsbnArgs, Book> 

handerとしてexportする関数をAppSyncResolverHandler型で定義して、1つ目の型引数にMutationの引数の型を、2つ目に戻り値の型を指定しています。

スタックの実装

いよいよスタックのソースコードに対して、作成するリソースの定義を追加していきます。
作成したソースは下記になります。

lib/eng-grp-cdk-appsync-stack.ts
import {
  Duration,
  Expiration,
  RemovalPolicy,
  Stack,
  StackProps,
} from "aws-cdk-lib";
import {
  AuthorizationType,
  FieldLogLevel,
  GraphqlApi,
  MappingTemplate,
} from "@aws-cdk/aws-appsync-alpha";
import { Construct } from "constructs/lib";
import { AttributeType, Table } from "aws-cdk-lib/aws-dynamodb";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import { RetentionDays } from "aws-cdk-lib/aws-logs";
import { SchemaFile } from "@aws-cdk/aws-appsync-alpha/lib/schema";

export class EngGrpCdkAppsyncStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // DynamoDB
    const table = new Table(this, "DynamoDbTable", {
      tableName: "books",
      partitionKey: {
        name: "id",
        type: AttributeType.STRING,
      },
      removalPolicy: RemovalPolicy.DESTROY,
    });

    // Lambdaを定義
    const lambdaHandler = new NodejsFunction(this, "LambdaHandler", {
      entry: "lambda/appsync-resolver.ts",
      logRetention: RetentionDays.ONE_DAY,
    });
    // dynamoDbのread/write権限を付与
    table.grantReadWriteData(lambdaHandler);

    // AppSyncリソースを定義
    const api = new GraphqlApi(this, "GraphqlApi", {
      name: "eng_group_cdk_demo",
      schema: SchemaFile.fromAsset("./graphql/schema.graphql"), // プロジェクトルートからの相対パス
      authorizationConfig: {
        defaultAuthorization: {
          authorizationType: AuthorizationType.API_KEY,
          apiKeyConfig: {
            expires: Expiration.after(Duration.days(365)),
          },
        },
      },
      logConfig: {
        fieldLogLevel: FieldLogLevel.ALL,
        retention: RetentionDays.ONE_DAY,
      },
    });

    // Query「allBooks」とDynamoDBを関連付けるデータソースを作成
    const dataSource1 = api.addDynamoDbDataSource("DataSource1", table);
    // リゾルバを定義
    dataSource1.createResolver("Resolver1", {
      typeName: "Query",
      fieldName: "allBooks",
      requestMappingTemplate: MappingTemplate.dynamoDbScanTable(),
      responseMappingTemplate: MappingTemplate.dynamoDbResultList(),
    });

    // Mutation「addBookFromIsbn」とLambdaを関連付けるデータソースを作成
    const dataSource2 = api.addLambdaDataSource("DataSource2", lambdaHandler);
    // リゾルバを定義
    dataSource2.createResolver("Resolver2", {
      typeName: "Mutation",
      fieldName: "addBookFromIsbn",
    });
  }
}

 
分解して見ていきます。

DynamoDBの定義を追加

book という名前のテーブルを定義します。

const table = new Table(this, "DynamoDbTable", {
  tableName: "books",
  partitionKey: {
    name: "id",
    type: AttributeType.STRING,
  },
  removalPolicy: RemovalPolicy.DESTROY,
});

Lambda関数の定義を追加

前述したとおり、
NodejsFunctionコンストラクトを使用することで、TypeScriptで実装したLambdaHandlerのソースコードをトンランスコンパイルやバンドルした上でLambda関数としてデプロイしてくれます。

entryには、前述のステップで作成したLambda Handlerのソースコード(lambda/appsync-resolver.ts)のパスをプロジェクトルートからの相対パスで記載します。

const lambdaHandler = new NodejsFunction(this, "LambdaHandler", {
  entry: "lambda/appsync-resolver.ts",
  logRetention: RetentionDays.ONE_DAY,
});

DynamoDbテーブルのRead/Write権限をLambdaのロールに付与

今回Lambda関数からDynamoDBへの操作が必要なため、
作成した bookテーブルの読み取り/書き込み権限をLamdba関数のロールに付与します。
ここまで特にロールの定義は出てきていませんが、Lambda関数の定義時にロールの指定を省略した場合は自動で作成されています。

table.grantReadWriteData(lambdaHandler);

AppSync GraphQL APIの定義を追加

GraphQL APIには、スキーマの定義を持たせる必要があります。
今回は前述のステップで作成した定義ファイル(graphql/schema.graphql)を読み込んで設定するようにしています。

また、今回APIの認証方式としては、APIキー方式を使用しています。
他にもAWS Cognitoと連携して認証を行うことなども可能です。

const api = new GraphqlApi(this, "GraphqlApi", {
  name: "eng_group_cdk_demo",
  schema: SchemaFile.fromAsset("./graphql/schema.graphql"), 
  authorizationConfig: {
    defaultAuthorization: {
      authorizationType: AuthorizationType.API_KEY,
      apiKeyConfig: {
        expires: Expiration.after(Duration.days(365)),
      },
    },
  },
  logConfig: {
    fieldLogLevel: FieldLogLevel.ALL,
    retention: RetentionDays.ONE_DAY,
  },
});

allBooksクエリとDynamoDBを関連付けるリゾルバを作成

スキーマで定義したallBooksクエリとデータソースとして指定するDynamoDBのbookテーブルを解決するためのリゾルバを定義します。

リゾルバでは、VTL言語を使用してマッピングテンプレート という、GraphQL リクエスト及びレスポンスとバックエンドのデータを変換する方法の定義を記載しないといけないのですが、AppSyncのL2コンストラクタは、単純なものであれば記述なしでマッピングテンプレートを生成することも可能です。楽ちんです。

const dataSource1 = api.addDynamoDbDataSource("DataSource1", table);
dataSource1.createResolver("Resolver1", {
  typeName: "Query",
  fieldName: "allBooks",
  requestMappingTemplate: MappingTemplate.dynamoDbScanTable(),
  responseMappingTemplate: MappingTemplate.dynamoDbResultList(),
});

addBookFromIsbnミューテーションとDynamoDBを関連付けるリゾルバを作成

スキーマで定義したaddBookFromIsbnミューテーションとデータソースとして指定するLambda関数を解決するためのリゾルバを定義します。

データソースにLambda関数を使用する場合は、Direct Lambda Resolvers を使用することで、マッピングテンプレート定義を省略できるので、テンプレートの指定は不要です。

const dataSource2 = api.addLambdaDataSource("DataSource2", lambdaHandler);
dataSource2.createResolver("Resolver2", {
  typeName: "Mutation",
  fieldName: "addBookFromIsbn",
});

リソースの作成を実行

ここまでで必要なソースコードは揃ったので、cdk deployコマンドを使用して実際にAWS上にリソースを作成します。

npx cdk deploy --profile enggrp

コマンドを実行するとプロンプト上に作成されるリソースの変更差分と、
Do you wish to deploy these changes (y/n)? のメッセージが表示されます。
問題なければ、yを入力してエンターを押下します。

特にエラーが発生しなければ、これで定義したリソースがAWS上に構築されます。

ローカル端末からリクエストを送信

最後に動作確認として、ローカル端末からリクエストを送ってみます。
リクエストの送信にはPowershell CoreのInvoke-RestMethodコマンドレットを使用します。

まず、作成したGraphQLAPIのエンドポイントURIとAPIキーをAWS CLIを使用して確認します。

# API IDとUrlを確認
aws appsync list-graphql-apis --query "graphqlApis[?name=='eng_group_cdk_demo'].{apiId:apiId,uri:uris.GRAPHQL}"  --profile enggrp
# API IDを使用してAPI KEYを確認
aws appsync list-api-keys --api-id ${取得したAPI ID} --profile enggrp      

確認したURIとAPIキーを埋め込みつつ、下記スクリプトをPowershellで実行します

$uri = "${確認したAPI URL} "
$headers = @{
    "X-API-KEY" = "${確認したAPI KEY} "
}
$contentType = "application/json"

$allBooksQuery = @{"query" = @"
query {
    allBooks {
      id
      title
      subtitle
      isbn
      authors
      publishedDate
      thumbnailLink
    }
}
"@
} | ConvertTo-Json

$addBookFromIsbn = @{"query" = @"
mutation {
    addBookFromIsbn(isbn:"@isbn") {
      id
      title
      subtitle
      isbn
      authors
      publishedDate
      thumbnailLink
    }
  }
"@
} | ConvertTo-Json 

# 2つのISBNコードで書籍登録Mutationを実行
Invoke-RestMethod -Method Post -Uri $uri -ContentType $contentType -Headers $headers -Body ($addBookFromIsbn -replace "@isbn","9784822262969")  > $null
Invoke-RestMethod -Method Post -Uri $uri -ContentType $contentType -Headers $headers -Body ($addBookFromIsbn -replace "@isbn","9784295010654")  > $null

# 全書籍取得Queryを実行して結果を表示
(Invoke-RestMethod -Method Post -Uri $uri -ContentType $contentType -Headers $headers -Body $allBooksQuery) | ConvertTo-Json -Depth 10

実行して、allBooksクエリが下記結果を返したことを確認できました。

allBooksクエリの結果
{
  "data": {
    "allBooks": [
      {
        "id": "751494de-0769-454a-a4dc-466c479d7bd5",
        "title": "Amazon Web Services基礎からのネットワーク&サーバー構築",
        "subtitle": "さわって学ぶクラウドインフラ",
        "isbn": "9784822262969",
        "authors": [
          "玉川憲",
          "片山暁雄",
          "今井雄太"
        ],
        "publishedDate": "2014-07-22",
        "thumbnailLink": "http://books.google.com/books/content?id=zMzgoAEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
      },
      {
        "id": "0aac1d4a-f622-4b60-a75c-c9b1e151562d",
        "title": "改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書[SAA-C02]対応",
        "subtitle": "",
        "isbn": "9784295010654",
        "authors": [
          "鳥谷部 昭寛",
          "宮口 光平",
          "菖蒲 淳司"
        ],
        "publishedDate": "2021-01-08",
        "thumbnailLink": "http://books.google.com/books/content?id=a7USEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
      }
    ]
  }
}
  また、DynamoDBにデータが登録されているかをAWS CLIで確認します
aws dynamodb scan --table-name "books" --profile enggrp

こちらもDBにデータが投入されていることを確認できました。

aws dynamodb scanの結果
{
    "Items": [
        {
            "thumbnailLink": {
                "S": "http://books.google.com/books/content?id=zMzgoAEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
            },
            "isbn": {
                "S": "9784822262969"
            },
            "subtitle": {
                "S": "さわって学ぶクラウドインフラ"
            },
            "id": {
                "S": "751494de-0769-454a-a4dc-466c479d7bd5"
            },
            "publishedDate": {
                "S": "2014-07-22"
            },
            "title": {
                "S": "Amazon Web Services基礎からのネットワーク&サーバー構築"
            },
            "authors": {
                "L": [
                    {
                        "S": "玉川憲"
                    },
                    {
                        "S": "片山暁雄"
                    },
                    {
                        "S": "今井雄太"
                    }
                ]
            }
        },
        {
            "thumbnailLink": {
                "S": "http://books.google.com/books/content?id=a7USEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
            },
            "isbn": {
                "S": "9784295010654"
            },
            "subtitle": {
                "S": ""
            },
            "id": {
                "S": "0aac1d4a-f622-4b60-a75c-c9b1e151562d"
            },
            "publishedDate": {
                "S": "2021-01-08"
            },
            "title": {
                "S": "改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト - アソシエイト教科書[SAA-C02]対応"
            },
            "authors": {
                "L": [
                    {
                        "S": "鳥谷部 昭寛"
                    },
                    {
                        "S": "宮口 光平"
                    },
                    {
                        "S": "菖蒲 淳司"
                    }
                ]
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 2,
    "ConsumedCapacity": null
}

あとがき

AppSyncを構築する方法を調べるとよく出てくるのはAmplify CLIですが、
L2コンストラクトを使用すれば、CDKでもかなり簡単に実装できることがわかりました。
これだけ簡単に実装できれば、APIとしてGraphQLを選択する敷居は大分下がるのではないでしょうか。
これから実際のアプリに組み込んだりして使いこなしていこうと思います。

7
2
1

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
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?