Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
AWS CDKを利用して、 Next.js/Stripeで構築したフルスタックSaaSアプリを...
Search
Hidetaka Okamoto (Stripe)
April 09, 2022
Programming
1.7k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AWS CDKを利用して、 Next.js/Stripeで構築したフルスタックSaaSアプリをデプロイ・管理する/cdk-conf-jp-2022
AWS CDK Conference Japan
https://jawsug.connpass.com/event/240422/
Hidetaka Okamoto (Stripe)
April 09, 2022
More Decks by Hidetaka Okamoto (Stripe)
See All by Hidetaka Okamoto (Stripe)
Stripeではじめる Revenue Operations / jp_stripes_okinawa_8
stripehideokamoto
0
330
収益を高めるための Stripeダッシュボード活用術 / jp_stripes_online_7
stripehideokamoto
0
420
No-code SaaS and Full Site Editing / wcasia2023
stripehideokamoto
0
280
コア機能開発に集中するための Stripe Checkout活用法 / jp_stripes_deep_dive_202301
stripehideokamoto
0
560
State of Checkout 2022から見た オンライン決済フローの最適化/jp-stripes-miyzaki-202301
stripehideokamoto
0
250
サブスクリプション決済入門 Stripeでの実装方法と、要件定義時のポイント/okta-stripe-202301
stripehideokamoto
0
220
ノーコード・ローコードツールで サブスク運用を効率化する方法 / JP_Stripes_Osaka_202301
stripehideokamoto
0
170
ビジネスユーザを巻込む Stripeダッシュボード活用法 / jp_stripes_deepdive-202212
stripehideokamoto
0
370
AWSでローコードにはじめる サブスクリプション運用の効率化/aws-startup-tech-meetup-fukuoka-2
stripehideokamoto
0
200
Other Decks in Programming
See All in Programming
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
460
the container ship “Apple Silicon”@WWDC26 Recap -Japan-\(region).swift
shingangan
0
120
2年かけて Deno に DOMMatrix を実装した話 / How I implemented DOMMatrix in Deno over two years
petamoriken
0
210
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
18k
自動化したのに回らないテスト運用の壁ーAI時代の品質責任と生産性
mfunaki
0
130
Apache Hive: そしてCloud Native Lakehouseへ
okumin
1
220
AIが無かった頃の素敵な出会いの話
codmoninc
1
400
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
770
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
180
Foundation Models frameworkで画像分析
ryodeveloper
1
610
属人化した知識を、 AIが辿れる地図にする
pkshadeck
PRO
1
160
楽しそうなつよつよエンジニアと目が死んでる僕/A brilliant engineer having a blast, and dead-eyed me.
3l4l5
2
100
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
sira's awesome portfolio website redesign presentation
elsirapls
0
320
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
The SEO identity crisis: Don't let AI make you average
varn
0
530
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Building Applications with DynamoDB
mza
96
7.2k
From π to Pie charts
rasagy
0
260
A Modern Web Designer's Workflow
chriscoyier
698
190k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
440
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
380
Transcript
AWS CDKを利用して、 Next.js/Stripeで構築したフルスタック SaaSアプリをデプロイ・管理する AWS CDK Conference Japan 2022 Hidetaka
Okamoto(@hide__dev) 2022/04/09
岡本 秀高 ( @hide__dev ) • Stripe Developer Advocate (ex-developer
in Digitalcube) • JavaScript / TypeScript developer • AWS / Next.js / WordPress / etc… • WordCamp Kyoto 2017 / JP_Stripes Connect 2019 / AWS Samurai 2017 / etc… • 🐈(猫フラご容赦) 2 ジャムジャム!!Jamstack_5 #cdkconf
3 https://stripe.com/jp
4 決済だけでなく決済周辺の機能もご利用可能 AWS CDK Conference Japan 2022 Payments Checkout Radar
Billing Connect Terminal Issuing Payouts Capital Corporate Card Treasury オンライン決済 構築済み決済 UI 不正使用とリスクの管理 サブスクリプションの管理 プラットフォーム向けの決済 Climate Sigma Atlas 収益の一部で CO2 除去に貢献 カスタムレポート Identity 決済最適化 ビジネスモデル ビジネス運営 送金・資金移動 融資・法人カード発行 オンライン請求書 Invoicing BaaS 支出管理 ビジネスの資金調達 海外への入金 カード作成 Tax 消費税と VAT の自動計算 オンライン本人確認 スタートアップの企業設立 対面支払い (日本未展開)
Low Code / No Codeで、決済リンクが作れる 5 AWS CDK Conference Japan
2022 #cdkconf const session = await stripe.checkout.sessions.create({ mode: "payment", success_url: `${req.headers.origin}`, cancel_url: `${req.headers.origin}`, line_items:[{ price: req.body.price_id, quantity: 1 }] }) return session.url
Stripeをより便利に使うには、サーバー側の処理が必要 • 請求やサブスクのデータは、 サーバー側で作成・処理する • クライアント側だけでもできないことはない *Stripe-js SDKのCheckoutやPayment Linksを利用 •
が、機能面の制限がでる ◦ クーポン入力 ◦ 消費税の自動計算 ◦ 動的な料金プラン ◦ etc… • フロントエンドのアプリと、 サーバー側の処理の両方を 用意しておきたい 6 AWS CDK Conference Japan 2022 #cdkconf
Next.js: ExpressライクなAPIとReactアプリをまとめて管理 • React向けのフレームワーク • フロントエンドと バックエンド(REST API)を まとめて管理できる •
SSRや静的化、ISRに対応 画像の最適化も • ウェブアプリから メディア・通販など、 幅広い用途で採用が増加中 7 AWS CDK Conference Japan 2022 #cdkconf https://nextjs.org/
Reactでフロントエンドを実装(一部Next.js独自実装有) 8 AWS CDK Conference Japan 2022 import type {
GetStaticProps, NextPage } from 'next'; import Head from 'next/head'; import Image from 'next/image'; import styles from '../styles/Home.module.css'; export const getServerSideProps: GetServerSideProps = async () => { return { props: {} }; }; export const getStaticProps: GetStaticProps = async () => { return { props: {} }; }; const Home: NextPage = (props) => { return ( <div className={styles.container}> <Head> <title>Create Next App</title> </Head> </div> ); };
APIはExpressライクな書き方で実装 9 AWS CDK Conference Japan 2022 import { NextApiRequest,
NextApiResponse } from 'next'; import Stripe from 'stripe'; export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, { apiVersion: '2020-08-27' }); export default async function handler(req: NextApiRequest, res: NextApiResponse<{ url: string | null; }>) { const session = await stripe.checkout.sessions.create({ mode: 'payment', line_items: [{ price: 'price_xxxxx', quantity: 1, } ], success_url: 'http://localhost:3000/success', cancel_url: 'http://localhost:3000/cancel', }); res.status(200).json({ url: session.url, }); }
Next.jsで実装したアプリのデプロイ先(一例) • Vercel: Next.jsの提供元で、Next.jsに最適化されているホスティング • NetlifyやAmazon S3: 静的にサイトをビルドする( APIやサーバー側機能を使わない)場合に使える •
AWS Amplify: AWSで、GUIからアプリの設定やアプリのパイプラインを管理したい。 • Lambda@edgeなど: serverless-nextjsを使って、AWSで構成をコード管理したい。 • AWS App Runner: Node.jsのアプリとして、コンテナの文脈で管理したい。 10 AWS CDK Conference Japan 2022
Amplifyか、それ以外のAWSサービスか • AWSで手軽に開始するなら AWS Amplify • GUIで直感的に設定が可能 ワークフローなども管理可 • Amplify
Studioを使えば、 Figmaとの連携も可能 • 連携するAWSサービスが 増えると、IAM系で少し手間 • コードで管理したいか、 GUIでなるべく管理したいか 11 AWS CDK Conference Japan 2022 #cdkconf
Serverless Next.js pluginを利用する • AWSでNext.jsを Serverlessに使う場合に利用 • Next.jsを動かすための、 AWSリソースを作成・管理 •
CloudFront / Lambda@edge S3 / SQSなどをデプロイする • Serverless Componentまたは AWS CDKから利用可能 • CDK v2にも対応済み 12 AWS CDK Conference Japan 2022 #cdkconf https://github.com/serverless-nextjs/serverless-next.js
NextJSLambdaEdgeコンストラクタを設定するだけ 13 AWS CDK Conference Japan 2022 import * as
cdk from "aws-cdk-lib"; import { NextJSLambdaEdge } from "@sls-next/cdk-construct"; import { Construct } from "constructs"; export class ServerlessNextjsCdkExampleStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const app = new NextJSLambdaEdge(this, "NextJsApp", { serverlessBuildOutDir: "./build" }); new cdk.CfnOutput(this, 'Domain', { value: app.distribution.domainName, description: 'CloudFrontDomain' }) } }
serverless-nextjsでデプロイするリソース • CloudFront: CDN • S3: 静的ファイルのホスト • Lambda@Edge ◦
APIの処理実行 ◦ アプリのSSR系処理 ◦ 画像処理系 ◦ ISR処理系 • SQS: ISR処理系 • そのほか: IAM / CWL / etc 14 AWS CDK Conference Japan 2022 #cdkconf https://github.com/serverless-nextjs/serverless-next.js# architecture
serverless-nextjsを使う上での注意点 • Lambda@edgeの仕様・制限に影響を受ける ◦ Nodeのランタイムバージョン ◦ 実行時間 ◦ 環境変数 •
Lambdaのログが複数リージョンの CWLに散らばるので、Sentryなどの併用が安全 • Next.js / Vercelのアップデート後、サポートまで時間差があるケースも 15 AWS CDK Conference Japan 2022
AWS CDK + Next.js (+ Stripe) Topics: • Next.jsプロジェクトに、serverless-nextjs +
AWS CDKを追加する • Secrets Managerを利用して、安全にAPIキーを利用する • CloudFrontのキャッシュ設定をカスタマイズする • 独自ドメイン設定のために、 ACMを設定する 16 AWS CDK Conference Japan 2022
AWS CDK + Next.js (+ Stripe) Topics: • Next.jsプロジェクトに、serverless-nextjs +
AWS CDKを追加する • Secrets Managerを利用して、安全にAPIキーを利用する • CloudFrontのキャッシュ設定をカスタマイズする • 独自ドメイン設定のために、 ACMを設定する 17 AWS CDK Conference Japan 2022
Next.jsをセットアップ後、CDKを追加する • CDKの方が、 後から手動追加しやすい • Next.jsとCDKを 別ディレクトリ化はちょっと大変 (monorepoなら・・・?) • リソース区別のため、
CDKディレクトリを用意 • CDKのリソースを消せば、 Vercelなどへの引っ越しも容易 • cdk initした後、ファイルだけ 持ってくるやり方でも可能 18 AWS CDK Conference Japan 2022 https://github.com/serverless-nextjs/serverless-next.js # Next.jsのセットアップ $ npx create-next-app --typescript ✔ What is your project named? … cdk-demo # AWS CDKのリソースを手動追加(最小限) $ yarn add aws-cdk-lib constructs source-map-support $ yarn add -D aws-cdk ts-node $ touch tsconfig.cdk.json cdk.json # Serverless Next.jsを追加する $ yarn add @sls-next/cdk-construct # CDK用のファイルを追加 $ mkdir -p cdk/bin $ touch cdk/bin/aws-cdk.ts $ touch cdk/stack.ts
CDKとNext.jsでtsconfig.jsonを分ける(tsconfig.cdk.json) 19 AWS CDK Conference Japan 2022 { "compilerOptions": {
"target": "ES2018", "module": "commonjs", // ここでNext.js/CDKがコンフリクトする "lib": [ "es2018" ], … "typeRoots": [ "@types", "./node_modules/@types" ] }, "include": [ "next-env.d.ts", "cdk" ], "exclude": [ "pages", "public", "styles", "node_modules", ".next", "cdk.out"] }
CDK.jsonを用意する(cdk initした結果を使っても可) 20 AWS CDK Conference Japan 2022 { "app":
"npx ts-node --project tsconfig.cdk.json --prefer-ts-exts cdk/bin/aws-cdk.ts", "context": { "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, "@aws-cdk/core:stackRelativeExports": true, "@aws-cdk/aws-lambda:recognizeVersionProps": true, … }
CDKでリソースを定義(cdk/stack.ts) 21 AWS CDK Conference Japan 2022 import * as
cdk from "aws-cdk-lib"; import { NextJSLambdaEdge } from "@sls-next/cdk-construct"; import { Construct } from "constructs"; export class ServerlessNextjsCdkExampleStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const app = new NextJSLambdaEdge(this, "NextJsApp", { serverlessBuildOutDir: "./build" }); new cdk.CfnOutput(this, 'Domain', { value: app.distribution.domainName, description: 'CloudFrontDomain' }) } }
CDKでNext.jsのビルドを指示(cdk/bin/aws-cdk.ts) 22 AWS CDK Conference Japan 2022 #!/usr/bin/env node import
'source-map-support/register'; import { App } from 'aws-cdk-lib'; import { Builder } from "@sls-next/lambda-at-edge"; import { AwsCdkStack } from '../stack'; const builder = new Builder(".", "./build", { args: ["build"] }); builder.build() .then(() => { const app = new App(); new AwsCdkStack(app, 'ServerlessNextjsCdkExampleStack', { }); }) .catch((e) => { console.log(e); process.exit(1); });
nextコマンドでローカル実行、cdkコマンドでデプロイ 23 AWS CDK Conference Japan 2022 # Next.jsアプリをローカル実行 $
yarn dev $ npx next dev # Next.jsアプリとCDKのビルド -> CFN出力 $ npx cdk synth # Next.jsアプリのビルド -> AWSへデプロイ $ npx cdk deploy
AWS CDK + Next.js (+ Stripe) Topics: • Next.jsプロジェクトに、serverless-nextjs +
AWS CDKを追加する • Secrets Managerを利用して、安全にAPIキーを利用する • CloudFrontのキャッシュ設定をカスタマイズする • 独自ドメイン設定のために、 ACMを設定する 24 AWS CDK Conference Japan 2022
Serverless Next.jsでのAPIキー管理 • Stripeには、フロント用の公開可能キー とシークレットAPIキーの2つがある ◦ シークレットAPIキーは、顧客情報などにもアクセスできる ので、門外不出 ◦ 公開可能キーは、ソースから取得されても問題のない
「公開して良い」キー ◦ 「カスタマイズ可能なシークレット APIキー相当」として、「制限付きキー」もある • 最低でもシークレットAPIキーは、AWSを利用して安全に管理する必要がある • Lambda@Edgeなので、環境変数で埋め込む方法はそもそも使えない 25 AWS CDK Conference Japan 2022
安全なAPIキー管理のため、Secrets Managerをつかう • APIキーなどを安全に 管理するためのサービス • API呼び出しへの課金なので、 呼び出し回数には注意 • コストが厳しい場合、
Systems Managerで代替も • キーのローテーションなど、 安全性をとるならこちら 26 AWS CDK Conference Japan 2022 #cdkconf
Secrets Managerへのアクセス権を設定 27 AWS CDK Conference Japan 2022 import {
PolicyStatement } from 'aws-cdk-lib/aws-iam' // 中略 const app = new NextJSLambdaEdge(this, "NextJsApp", { serverlessBuildOutDir: "./build" }); const secretManagerPolicyStatement = new PolicyStatement({ resources: ['Secret ManagerのSecret ARN'], actions: ['secretManager:GetSecretValue'] }) app.defaultNextLambda.addToRolePolicy(secretManagerPolicyStatement); if (app.nextApiLambda) app.nextApiLambda.addToRolePolicy(secretManagerPolicyStatement);
Lambda内で取得・利用する 28 AWS CDK Conference Japan 2022 import { SecretsManager
} from 'aws-sdk'; import Stripe from 'stripe'; const secretsmanager = new SecretsManager(); const secrets = await secretsmanager.getSecretValue({ SecretId: 'secret-id' }).promise() const secretsJSON = JSON.parse(secrets.SecretString) const stripe = new Stripe(secretsJSON.STRIPE_SECRET_API_KEY)
AWS CDK + Next.js (+ Stripe) Topics: • Next.jsプロジェクトに、serverless-nextjs +
AWS CDKを追加する • Secrets Managerを利用して、安全にAPIキーを利用する • CloudFrontのキャッシュ設定をカスタマイズする • 独自ドメイン設定のために、 ACMを設定する 29 AWS CDK Conference Japan 2022
Serverless Next.js Constructの戻り値から上書きする • LambdaやCloudFrontの設定は 上書き可能 • TypeScriptなどの型付き言語は、 定義を追いかけて調査しやすい •
「一部だけ変更」は難しそう • cdk synthでCFNスタックを 出力し、初期値を調査する方式 • Amplifyより手間だけど、 触れる範囲と柔軟性は上 30 AWS CDK Conference Japan 2022 https://github.com/serverless-nextjs/serverless-next.js import { Stack, StackProps, CfnOutput, Duration } from 'aws-cdk-lib'; import { NextJSLambdaEdge } from "@sls-next/cdk-construct"; import { CachePolicy, CacheQueryStringBehavior, CacheHeaderBehavior } from 'aws-cdk-lib/aws-cloudfront'; // 中略 const app = new NextJSLambdaEdge(this, "App", { serverlessBuildOutDir: "./build"}); app.nextLambdaCachePolicy = new CachePolicy(this, "NextLambdaCache", { queryStringBehavior: CacheQueryStringBehavior.all(), headerBehavior: CacheHeaderBehavior.allowList("Authorization", "Origin"), cookieBehavior: { behavior: 'all' }, defaultTtl: Duration.seconds(0), maxTtl: Duration.days(365), minTtl: Duration.seconds(0),
AWS CDK + Next.js (+ Stripe) Topics: • Next.jsプロジェクトに、serverless-nextjs +
AWS CDKを追加する • Secrets Managerを利用して、安全にAPIキーを利用する • CloudFrontのキャッシュ設定をカスタマイズする • 独自ドメイン設定のために、ACMを設定する 31 AWS CDK Conference Japan 2022
Serverless Next.js Constructの引数から設定 • 「よくある設定」は、 Constructの引数から指定可能 • ドメイン・ログ・Cookie キャッシュ設定など・・・ •
「どう解釈されるか」は、 cdk synthなどで出力を読もう 32 AWS CDK Conference Japan 2022 https://github.com/serverless-nextjs/serverless-next.js const app = new NextJSLambdaEdge(this, "NextJsApp", { serverlessBuildOutDir: "./build", domain: { domainNames: ['example.com'], certificate: Certificate.fromCertificateArn( this, "ACM", 'ACM Resource ARN' ) }, withLogging: false, whiteListedHeaders: ["Authorization", "Origin"] });
まとめ • AWS CDKを使うと、Next.jsアプリをAWSと連携させやすくなる • ただしLambda@edgeを利用する前提の構成になる点に注意 • GUIベースの管理や手軽さを求めるなら Amplify、AWS使わないならVercel •
利用開始も終了も手軽にできる serverless-nextjsで、 Next.jsを利用したアプリ・サイト開発で AWSリソースをフル活用しよう 33 AWS CDK Conference Japan 2022