Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
AWSでサーバレスな書籍管理アプリを作る
Search
Ryosuke Uchiyama
May 09, 2025
Technology
75
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AWSでサーバレスな書籍管理アプリを作る
Ryosuke Uchiyama
May 09, 2025
More Decks by Ryosuke Uchiyama
See All by Ryosuke Uchiyama
PythonでSlack通知botを作る
step63r
0
24
ChatGPT実践
step63r
1
410
IoT実践! 行先予定表を電子ペーパーで作る
step63r
0
54
React x Socket.ioで人狼サーバを作る 第一章 フロントエンド実装
step63r
0
36
深層強化学習で東方AI 第一章 DQNの基本
step63r
0
430
Build 2021 プレイバック
step63r
0
45
WPFで実践アプリ開発! 第四章 機能の実装 Part 2
step63r
0
63
WPFで実践アプリ開発! 第三章 機能の実装 Part 1
step63r
0
140
WPFで実践アプリ開発! 第二章 UI
step63r
0
190
Other Decks in Technology
See All in Technology
契約で守るコンパウンドプロダクトのデザインシステム
yug1224
1
180
シンプルな設定ファイルで実現する AWS IAM Identity Center の ユーザー管理Terraformフレームワークを公開しました / Simplifying AWS IAM Identity Center User Management: An Open-Source Terraform Framework
yamaguchitk333
0
220
PHPカンファレンス関西の招待状 / Invitation to PHP Conference Kansai
ykanoh
0
230
古い指輪から広がった JAVA コミュニティ とのつながり
yamad
0
140
Code for Security プロジェクト紹介 2026年10月
yu23ki14
0
120
Claude Code on Bedrock で統制をかける小ネタ集/claude-code-bedrock-governance-tips
emiki
1
410
Kiro Crewで「みのるん式」仕事術やってみた
minorun365
PRO
3
1k
How to teach your AI Agent with Agent skills
linedevth
0
110
AIにシークレットを見せない、WSL2で安全な開発環境
yazm
0
340
アカウント統制の健康診断
kenichinakamura
1
140
DBについての基礎説明(MySQL編) - コロプラ 2026年度 新卒研修
colopl
0
160
「Learning Outcome」を書きたくない私が、Learning Outcomeと折り合いをつけるまで
mhlyc
0
130
Featured
See All Featured
The SEO Collaboration Effect
kristinabergwall1
1
600
Designing for Timeless Needs
cassininazir
1
530
Un-Boring Meetings
codingconduct
0
460
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
710
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
420
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
300
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
500
Statistics for Hackers
jakevdp
799
230k
Amusing Abliteration
ianozsvald
1
350
Transcript
AWSでサーバレスな 書籍管理アプリを作る Ryosuke UCHIYAMA
はじめに © 2025 minato project. 2
実現したかったこと • 持っている書籍をデータベース管理にする • カメラで読み取るなどできるだけ簡易な方法で登録できる • 読み取った書籍が所有済みであるかをチェックする • 登録した書籍の情報を閲覧、編集できる •
書籍の貸出・返却管理を行う(将来的実装) © 2025 minato project. 3
つくったもの © 2025 minato project. 4 https://sbms.minatoproject.com/
ソースコード © 2025 minato project. 5 step63r/sam-ayano https://github.com/step63r/sam-ayano
システム構成図 © 2025 minato project. 6
システムイメージ © 2025 minato project. 7
Demo © 2025 minato project. 8
実装ハイライト © 2025 minato project. 9
アカウント作成、ログイン機能 © 2025 minato project. 10 AWS Amplify UI Componentsを活用し簡易的な実装とした
root.render( <> <CssBaseline /> <Authenticator.Provider> <LoadingProvider> <App /> </LoadingProvider> </Authenticator.Provider> </> ) index.tsx 32 33 34 35 36 37 38 39 40 41 const Settings: React.FC = () => { const navigate = useNavigate(); const { user, signOut } = useAuthenticator((context) => [context.user]); const [disabled, setDisabled] = useState(false); ... }; Settings.tsx 17 18 19 20 ... 59
キャリアメール対応 © 2025 minato project. 11 Amazon SES設定とDKIMのDNS登録に加え、DMARC準拠の設定が必要だった
なぜキャリアメールへのメールが届かないのか? © 2025 minato project. 12 結論 キャリアが送信ドメイン認証を行っていたから 送信ドメイン認証とは なりすましメールや迷惑メールへの対策として、送信元のIPアドレスとDNSサーバに公開された送信用メールサーバのIPアドレ
スが一致しているかを確認すること。送信元のIPアドレスの確認には、メールヘッダーに含まれるFromフィールドが利用され ている。キャリアにメールを送信するにはDMARCに準拠する必要がある。 DMARCとは SPFやDKIMの認証が失敗した場合の対 応策を定めたもの。送信側は受信側の 認証失敗時の推奨アクションをDNSに 「DMARCポリシー」として宣言してお き、受信側は認証失敗時にこのDMARC ポリシーを参照して、受信メールをど う扱うか判断する。 SPFとは IPアドレスを利用して受信したメール の送信元が詐称されていないかを確認 する。メール送信時に利用するサーバ のIPアドレスを送信側のDNSに「SPF レコード」として事前に登録。受信側 はメール受信時に送信側のSPFレコー ドと照合し、なりすましかどうかを判 断する。 DKIMとは 電子署名を利用してメール送信元が詐 称されていないかを確認する。送信側 がメールに電子署名を付与し、受信側 はそれをメール受信時に検証すること で、なりすましやメールの改ざんを検 知する。
SPFの仕組み © 2025 minato project. 13
DKIMの仕組み © 2025 minato project. 14
DMARCの仕組み © 2025 minato project. 15
バーコード読取 © 2025 minato project. 16 書籍JANコードを読み捨ててISBNだけ取るようにした const handleScan =
useCallback(async (results: IDetectedBarcode[]) => { setIsLoadingOverlay(true); if (results.length > 0) { for (const item of results) { if (item.rawValue.startsWith("978") || item.rawValue.startsWith("979")) { ... } } } setIsLoadingOverlay(false); }, [getBooksAsync, checkExists, navigate, setIsLoadingOverlay, searchOpenBdAsync]); ReadBarcode.tsx 113 114 115 116 117 118 ... 145 146 147 148 149 150
書籍情報の取得、登録 © 2025 minato project. 17 openBDのAPIで書籍情報を取得するようにした try { await
axios.get(url) .then(r => { console.log("response", r); if (r.data.length === 1) { response = createResponse(200, r.data[0]); } else { response = createResponse(500, { message: "検索結果が1件ではありませんでした。" }); } }); } catch (error) { console.log("error", error); response = createResponse(500, error); } search-openbd/app.mjs 32 33 34 35 36 37 38 39 40 41 42 43 44 45
書籍情報の検索、一覧取得 © 2025 minato project. 18 キーワード入力のイベント抑止 (debounce) とフィルタ対応 const
[debouncedKeyword] = useDebounce(keyword, 500); ... const result = await getBooksAsync({ pageSize: PAGE_SIZE, lastEvaluatedKey: undefined, keyword: debouncedKeyword, sortKeyId: sortKeyId, desc: isDesc, }); Books.tsx 89 ... 174 175 176 177 178 179 180 // 取得件数がpageSizeに到達するまでQueryし続ける while (currentLength < pageSize) { ... } ... // 取得結果がpageSizeより多い場合はスライスする if (items.length > pageSize) { items = items.slice(0, pageSize); currentLastEvaluatedKey.username = userName; currentLastEvaluatedKey.seqno = items[items.length - 1].seqno; } get-books/app.mjs 84 85 ... 103 ... 105 106 107 108 109 110
APIGWにCognito認証を追加する © 2025 minato project. 19 OPTIONSに認証設定を入れてはいけない(戒め) Resources: ... ApiGateway:
Type: AWS::Serverless::Api Properties: ... Auth: DefaultAuthorizer: CognitoAuthorizer AddDefaultAuthorizerToCorsPreflight: false Authorizers: CognitoAuthorizer: UserPoolArn: arn:aws:cognito-idp:... template.yaml 22 ... 72 73 74 ... 87 88 89 90 91 92 const session = await fetchAuthSession(); const token = session?.tokens?.idToken.toString(); const options = { 'headers': { 'Content-Type': 'application/json', 'Authorization': token, }, }; TypeScript
残課題 • 異常系の強化 • openBDにデータがない場合に他サービスへの問い合わせ • サブスクリプション対応 • バーコード読み取りのライブラリ、他に良いのないか •
UI改善 © 2025 minato project. 20
参考資料 • QR コードスキャンライブラリ @yudiel/react-qr-scanner で IScannerComponents を設定してスキャン時の UI をカスタマイズしてみた
| DevelopersIO • Authenticator | Amplify UI for React • 【React開発】処理待機中に画面全体を覆うオシャレなローディング画面を表示させる方法! #個人開発 - Qiita • Amazon Cognito からキャリアのアドレスにメールを送信するためにやったこと #AWS - Qiita • 送信ドメイン認証(SPF / DKIM / DMARC)の仕組みと、なりすましメール対策への活用法を徹底解説 – エン タープライズIT [COLUMNS] • API GatewayのOPTIONSメソッド(CORS)でAPIキーを不要にする(AWS SAM) | DevelopersIO © 2025 minato project. 21