0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GraphQLスキーマから作ったモックサーバーをSSTでデプロイする

Last updated at Posted at 2025-06-05

:sunny: はじめに

GraphQL API の開発初期に、モックサーバーがあるとクライアント側の開発が楽になります。Apollo Server はモック機能 を提供してくれていますが、デプロイするには少々手間がかかり、もっと簡単に作れないかと思っていました。
そこで最近 SST というサーバーを爆速で構築するフレームワークを知り、GraphQLモックサーバーをいい感じに作れそうだったので紹介します。

SSTの詳しい説明は https://sst.dev/ を参照ください。
一言で言うとワンコマンドでサーバーをデプロイできてしまうフレームワークです。最大の特徴は Live 機能で、ローカルの変更を即座に AWS Lambda へ反映し動作確認ができます。AWS Lambda にデプロイするコードはローカルで動作確認しにくいことがあるので、これが大変魅力的でした。

:dart: 構成

  • SST を用いて AWS 上に GraphQL モックサーバーをデプロイする

  • Apollo Server を AWS Lambda にホスティングする

  • GraphQL スキーマファイル(schema.graphql)に基づいたレスポンスを Apollo Server の Mock 機能で自動生成する

:pick: 使用技術

  • SST 3.17.2

  • Apollo Server v4

  • TypeScript

:hand_splayed: 手順

SST の立ち上げ

まずは プロジェクトを構築するところから始めましょう。

mkdir graphql-lambda && cd graphql-lambda
npm init -y

SST を初期化します。Template は js、Where do you want to deploy your app? You can change this later: と聞かれるので、AWSを選択します。

npx sst@latest init


   ███████╗███████╗████████╗
   ██╔════╝██╔════╝╚══██╔══╝
   ███████╗███████╗   ██║   
   ╚════██║╚════██║   ██║   
   ███████║███████║   ██║   
   ╚══════╝╚══════╝   ╚═╝   

>  JS project detected. This will...
   - use the JS template
   - create an sst.config.ts

✓  Template: js

✓  Using: aws

✓  Done 🎉

ここで SSTの設定を記述する sst.config.ts が作られます。async run() が空なので記述します。

/// <reference path="./.sst/platform/config.d.ts" />

export default $config({
  app(input) {
    return {
      name: "aws-express",
      removal: input?.stage === "production" ? "retain" : "remove",
      protect: ["production"].includes(input?.stage),
      home: "aws",
    };
  },
-  async run() {},
+   async run() {
+   new sst.aws.Function("GraphQLMock", {
+     url: true,
+     handler: "src/index.graphqlHandler",
+    });
+  },
+ }
});

SST は Terraform のように、作成するAWSリソースをコードで記述します。ここでは Function を使い、これにより後のコマンドで AWS Lambda のリソースが作られます。

次に handler を記述します。
Apollo には、Lambda にデプロイする専用のhandlerが提供されているのでこれを使いましょう。

ドキュメントに従い、必要なパッケージをインストールして、index.ts を作成します。

npm install @apollo/server graphql @as-integrations/aws-lambda

npm install -D typescript

mkdir src && touch src/index.ts

とりあえず動くことを確認したいので、スキーマはあとで読み込むとして、今はハードコーディングします。

index.ts
import { ApolloServer } from '@apollo/server';
import {
  startServerAndCreateLambdaHandler,
  handlers,
} from '@as-integrations/aws-lambda';

// TODO: あとでスキーマファイルから読み込む
const typeDefs = `#graphql
  type Query {
    hello: String
  }
`;

const resolvers = {
  Query: {
    hello: () => 'world',
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

// NOTE: sst.config.ts の handler に記述した名前と一致させる
export const graphqlHandler = startServerAndCreateLambdaHandler(
  server,
  handlers.createAPIGatewayProxyEventV2RequestHandler()
);

AWS 認証情報の設定

AWSリソースを作成するので、AWSアカウントの認証情報が必要です。

いくつか設定の方法はありますが、今回はprofileを読み込む方法をとってみます。他の方法は以下を参照ください。

IAM を作成し、アクセスキーIDとシークレットアクセスキーを ~/.aws/credentials に保存します。IAM はAdministratorAccess があるものにします(本当は最低限がいいですが)。この辺りのやり方は調べたら出てくると思いますのでこの記事では割愛します。

[default]
aws_access_key_id = <DEFAULT_ACCESS_KEY_ID>
aws_secret_access_key = <DEFAULT_SECRET_ACCESS_KEY>

[miyamasaru]
aws_access_key_id = <MY_ACCESS_KEY_ID>
aws_secret_access_key = <MY_SECRET_ACCESS_KEY>

profileを sst.config.ts に追加します。profile名は ~/.aws/credentials に設定したものと一致させます。

export default $config({
  app(input) {
    return {
      name: "aws-express",
      removal: input?.stage === "production" ? "retain" : "remove",
      protect: ["production"].includes(input?.stage),
      home: "aws",
+     providers: {
+       aws: {
+         profile: "miyamasaru"
+       }
+     }
    };
  },

これで準備完了です! sst dev を実行します。

sst dev

SSTのドキュメントでは npx sst dev が実行されていますが、Deployが終わらずうまく実行できなかったので、sstのCLI をインストールして sst dev で実行したら安定しました。

2025年6月現在、似たようなissueが上がっているようです。
https://github.com/sst/sst/issues/5655

ターミナルに専用のウィンドウが出て、Complete が出れば成功です!

スクリーンショット 2025-06-05 19.37.17.png

Permallink の URL はアクセスするとエラーとなりますが、そちらではなく、その下の Lambda の URL にブラウザからアクセスしましょう。Apollo Server の Sandbox が確認できるはずです。

もちろん GraphQLのリクエストもできます。 /graphql をつけるのを忘れないようにしましょう。

$ curl -X POST https://ulut4yniqrmfbyd5ykjpydwvpe0rdaky.lambda-url.ap-northeast-1.on.aws/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "query ExampleQuery { hello }"}'
{"data":{"hello":"world"}}                

index.ts の 「world」 の部分を書き換えて再度リクエストすると、リアルタイムで変更されるかと思います。すごいですね。

AWS Lambda へのデプロイ

sst dev はあくまで開発用に Lambda を立ち上げるコマンドなので、Curl + C で停止すると Lambda もアクセスできなくなってしまいます。

そこで、deploy コマンドで実際にデプロイをします。--stage でのデプロイ先の環境を指定することもできます。

sst deploy --stage production

ここで生成されるURLを共有することでみんながモックを使用できるようになります。

GraphQL スキーマファイルの読み込み

では、後回しにしていた .graphql ファイルからモックを作成してみましょう。ルートに schema.graphql を作成します。

schema.graphql
type User {
    id: ID!
    name: String!
    email: String!
    age: Int!
    posts: [Post!]!
}

type Post {
    id: ID!
    body: String!
    createdBy: User!
    comments: [Comment]!
}

type Comment {
    id: ID!
    body: String!
    createdBy: User!
}

type Query {
  # 全ての投稿を取得
  posts: [Post]!
}

ファイルを Lambda に渡すには、copyFiles を追加します。sst.config.ts を以下のように変更します。

  async run() {
    new sst.aws.Function("GraphQLMock", {
      url: true,
      handler: "src/index.graphqlHandler",
+     copyFiles: [{ from: "schema.graphql" }]
    });
  },

そして index.ts でファイルを読ませます。

index.tsx
import { ApolloServer } from '@apollo/server';
import {
  startServerAndCreateLambdaHandler,
  handlers,
} from '@as-integrations/aws-lambda';
import { readFileSync } from 'fs';

// 修正
const typeDefs = readFileSync(
  'schema.graphql',
  'utf-8'
);

// hello()はなくなりエラーになるので消す
const resolvers = {
  Query: {
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers
});

export const graphqlHandler = startServerAndCreateLambdaHandler(
  server,
  handlers.createAPIGatewayProxyEventV2RequestHandler()
);

Apollo の Mock を導入する

今のままだと型エラーでレスポンスが取得できません。Apollo の Mock を導入して値が返ってくるようにしましょう。

まず必要なライブラリをインストールします。

npm install --save-dev @graphql-tools/mock @graphql-tools/schema

mocks を定義して ApolloServer に渡します。
mocks に型と値の対応を記述することで、その型であれば自動的にその値を返すようにすることができます。

index.ts
import { addMocksToSchema } from '@graphql-tools/mock';
import { makeExecutableSchema } from '@graphql-tools/schema';

...

// 追加
const mocks = {
  Int: () => 6,
  String: () => 'Hello',
};

// mocksを渡すように修正
const server = new ApolloServer({
  schema: addMocksToSchema({
    schema: makeExecutableSchema({ typeDefs, resolvers }),
    mocks,
  }),
});

...

sst dev でサーバーを立ち上げ、リクエストすると値が帰ってくるはずです。デプロイしたい場合は sst deploy を実行しましょう!

query ExampleQuery {
  posts {
    id
    created_by {
      id
      age
      email
    }
  }
}

{
  "data": {
    "posts": [
      {
        "id": "f8e888f6-f6f3-44e5-9c4d-c990c0aa591c",
        "createdBy": {
          "id": "5b08d7a8-c579-4ac6-ae9f-06219e615fbc",
          "email": "Hello",
          "age": 6
        }
      },
      {
        "id": "5cf0a6dc-3df8-44a8-8759-361ad31e25bb",
        "createdBy": {
          "id": "97c0463b-2fd2-4469-8e63-64d8c39034cc",
          "email": "Hello",
          "age": 6
        }
      }
    ]
  }
}

感想

SST を使えば1日足らずで Lambda の環境を構築できるのは便利です。ローカルでのデバッグがしやすいのも良かったです。
(Serverless Framework だと、GraphQL の Query を文字列としてbodyに渡すのが面倒そう?)

:sparkles: Next

今のままでは最低限なので、さらに改善して実運用で使えるようにしましょう。以下の記事は次回以降書きます。

  • Mock の改善(ランダムな値、配列の個数制御、カスタムスカラーへの対応 etc)
  • https通信とBasic認証を導入
0
0
0

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?