GLoves Blog
AWS CDKで構築するAWS AppSync

AWS CDKで構築するAWS AppSync

タグ
投稿日
2023-07-22

AWS CDKの設定

AWS CDKのインストール

$ curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
$ sudo installer -pkg AWSCLIV2.pkg -target /
$ npm install -g aws-cdk
$ cdk --version

AWS ConsoleでIAMユーザーを作成

ユーザー名を「cdk-sample-user」として登録。

※ユーザー名は任意。


ここではフル権限を付与しますが、権限管理の変更は必要に応じて別途対応をお願いします。

タグつけについても必要に応じて別途対応をお願いします。


aws configureの設定

IAMユーザー作成時に生成したアクセスキーとシークレットキーを元に設定。

PROFILE名・リージョンは任意ですが、ここでは ap-northeast-1を設定

$ export AWS_PROFILE=appsync-backend-app # => 任意の環境変数名を設定
$ aws configure

バックエンドのプロジェクト作成

CDKコマンドで初期設定

$ mkdir 任意のフォルダ名
$ cd 任意のフォルダ名
$ cdk init app --language typescript

CDKセットアップとデプロイ

CDKを使用する前に、cdk bootstrap コマンドを実行してAWS環境をセットアップすることで、CDKを利用してアプリケーションをデプロイする準備が整います。

コマンドは作成したバックエンドのプロジェクトのルートディレクトリで実行する。

$ cdk bootstrap
$ cdk deploy
$ aws cloudformation list-stacks # => 作成されたスタック一覧

デプロイが完了すると、AWS Console上の CloudFormation > スタックにデプロイしたスタック名が表示されます。


GraphQLの設定

スキーマ設定とTypeScriptの型定義

ここでは簡単なTODOアプリを想定してスキーマを設定しています。

/graphql/schema.graphql
scalar AWSTimestamp

type Todo {
  id: ID!
  title: String!
  completed: Boolean!
  createdAt: AWSTimestamp!
}

type Query {
  getTodos: [Todo!]!
}

$ npm i graphql @graphql-codegen/cli @graphql-codegen/typescript

GraphQL Code Generator の設定ファイルを作成

/codegen.yml
overwrite: true
schema:
  - graphql/schema.graphql
generates:
  ./graphql/generated/generated-types.ts:
    plugins:
      - typescript

codegenのスクリプトをpackage.jsonに追加。

/package.json
"scripts": {
  "build": "tsc",
  "watch": "tsc -w",
  "test": "jest",
  "cdk": "cdk",
  "codegen": "graphql-codegen"
},

スキーマの型を生成

$ npm run codegen

/graphql/generated/generated-types.tsファイルが生成されます。


Lambda関数の実装

$ npm i aws-sdk # => AWS CDK v2
$ npm i -D @types/aws-lambda
$ npm install @aws-cdk/aws-appsync

/lib/プロジェクト名-stack.ts
import * as cdk from "aws-cdk-lib";
import * as lambdaNodeJs from "aws-cdk-lib/aws-lambda-nodejs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as appsync from "aws-cdk-lib/aws-appsync";
import { Construct } from "constructs";
import * as path from "path";

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

    // DynamoDB
    const todoTable = new dynamodb.Table(this, "TodoTable", {
      billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      partitionKey: {
        name: "id",
        type: dynamodb.AttributeType.STRING,
      },
    });

    // AppSync
    const todoApi = new appsync.GraphqlApi(this, "TodoGraphqlApi", {
      name: "todo-graphql-api",
      schema: appsync.SchemaFile.fromAsset(
        path.join(__dirname, "../graphql/schema.graphql")
      ),
      authorizationConfig: {
        defaultAuthorization: {
          authorizationType: appsync.AuthorizationType.API_KEY,
          apiKeyConfig: {
            expires: cdk.Expiration.after(cdk.Duration.days(365)),
          },
        },
      },
    });

    // Lambda
    const getTodosLambda = new lambdaNodeJs.NodejsFunction(
      this,
      "getTodosHandler",
      {
        entry: path.join(__dirname, "../lambda/getTodos.ts"),
        handler: "handler",
        environment: {
          TODO_TABLE: todoTable.tableName,
        },
        // runtimeの指定がないとAppSync側でエラーが出力される。
        runtime: lambda.Runtime.NODEJS_18_X,
      }
    );
    todoTable.grantReadData(getTodosLambda);

    // DataSource
    const getTodosDataSource = todoApi.addLambdaDataSource(
      "getTodosDataSource",
      getTodosLambda
    );

    // Resolver
    new appsync.Resolver(this, "QueryGetTodosResolver", {
      api: todoApi,
      dataSource: getTodosDataSource,
      typeName: "Query",
      fieldName: "getTodos",
    });

    // CfnOutput
    new cdk.CfnOutput(this, "GraphQlApiUrl", {
      value: todoApi.graphqlUrl,
    });

    new cdk.CfnOutput(this, "GraphQlApiKey", {
      value: todoApi.apiKey || "",
    });
  }
}

コマンド実行前にローカル環境上にDockerを設定し、起動させてください。

$ cdk diff
$ cdk deploy

デプロイが完了したら、AWS consoleのAppSyncのクエリページでクエリ実行が可能になります。

※データはAWS console上から追加できます。

AWS AppSyncのイメージ

参考リンク

https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html