ホーム > LINE特集 > 第3章: 予約システム
第3章LINEミニアプリ特集
レストランのオーナーがタブレットで予約を確認している様子

第3章 — 実例1

LINEミニアプリ×サーバーレスで
予約システムを作る

美容室・飲食店向け。「月間500件の予約を月数十円で回す」技術構成を、設計から実装まで解説します。

なぜLINE上で予約するのか

飲食店や美容室の予約といえば、電話か対面が主流でした。しかし、「電話がつながりにくい」「営業時間外に予約したい」「予約確認の電話を取りたくない」といった課題は、店舗側・顧客側の双方に存在します。

一方、最近はホットペッパーグルメRettyといった外部予約サイトも普及しましたが、これらには月額1〜3万円のランニングコストが発生し、顧客データもプラットフォーム側に蓄積されます。自社の顧客との接点を「借りた土地」に置くリスクは、長期的に見ると小さくありません。

LINEミニアプリ上の自社予約システムなら、顧客データも予約履歴も自社管理。コストは月数十円。ユーザーにとってはLINEのトーク画面から「予約する」ボタンを押すだけで、外部アプリを一切開く必要がありません。

💡 ポイント: ホットペッパーの月額プラン最低ランク(約13,000円/月)と比較して、LINEミニアプリ予約の月間コストは500円以下。年間で約15万円のコスト削減になります。

システム全体像

構成はシンプルです。フロントエンドはLINEミニアプリ(LIFF)で、バックエンドはAWSのサーバーレスコンポーネントで構成します。サーバー管理は不要、トラフィックに応じて自動スケール、使った分だけ課金されます。

👤 LINEミニアプリ(LIFF) 🔗 API Gateway ⚡ Lambda 🗄️ DynamoDB
LINEミニアプリの予約画面
LINEのトーク画面で予約確認

認証設計: LINEユーザーの身元を保証する

予約システムで最も重要なのは「誰が予約したか」を正確に把握することです。LIFFアプリではliff.getIDToken()で取得できるIDトークンをバックエンドに送信し、LINEの公式検証エンドポイントで本人確認を行います。

// フロントエンド(LIFFアプリ)側のコード const idToken = liff.getIDToken(); const res = await fetch('/api/reservation', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idToken, date, time, partySize }) }); // Lambda側での検証(概略) const payload = await verifyLineToken(idToken); const userId = payload.sub; // LINE userId(一意・不変)

ポイントは、フロントから送られるuserIdをそのまま信頼しないことです。必ずサーバー側でIDトークンを検証し、LINE公式のuserIdを取得してから予約を紐づけます。

DynamoDB設計

予約システムのアクセスパターンを洗い出すと、以下の4つが主要です。

操作条件頻度
空き枠一覧取得日付指定高(ユーザーが毎回実行)
予約作成日付+時間+ユーザーID
自分の予約一覧ユーザーID
予約キャンセル予約ID+本人確認

DynamoDBのキー設計例は以下の通りです。パーティションキーに日付、ソートキーに時間帯とユーザーIDを組み合わせることで、すべての操作が単一のテーブルで完結します。

PK: RES#2026-09-15 SK: SLOT#14:00#U1234567890 PK: RES#2026-09-15 SK: SLOT#15:00#U0987654321 PK: USER#U1234567890 SK: RES#2026-09-15#14:00 属性: status (confirmed/cancelled), partySize, createdAt

同時予約の競合対策

最も気をつけたいのはダブルブッキングです。2人の顧客が同時に同じ時間枠を予約した場合、DynamoDBの条件付き書き込み(ConditionExpression)で対策します。

// 予約作成の条件付き書き込み PutItem({ TableName: 'Reservations', Item: newReservation, ConditionExpression: 'attribute_not_exists(PK)', // → すでに同じPK+SKが存在する場合、ConditionalCheckFailedException が返る })

条件付き書き込みが失敗した場合、その時間枠は既に埋まっていると判断し、ユーザーに別の時間帯を選んでもらうUIを表示します。データベースレベルで排他制御が行われるため、アプリケーション側のロック機構は不要です。

Lambda実装のポイント

Lambda関数は2つ作ります。1つはAPI Gatewayからの予約操作(GET/POST/DELETE)を受け付けるハンドラ、もう1つは予約後のLINE通知を担当するハンドラです。

予約作成フロー

  1. ユーザーがミニアプリで日付・人数を選んで「予約する」をタップ
  2. LIFF IDトークンをヘッダに含めてPOSTリクエスト
  3. LambdaがIDトークンを検証、userIdを取得
  4. 条件付き書き込みでDynamoDBに予約レコードを作成
  5. 成功したらユーザーのLINEトークに確認メッセージを送信
  6. 失敗したら409 Conflictを返し、フロントが別の枠を提案
LINEトークに届く予約確認通知

CORSとAPI Gateway設定の注意点

LIFFアプリからのリクエストはLINEドメインからのクロスオリジンリクエストになるため、API GatewayにCORS設定が必要です。HeadersにAccess-Control-Allow-Originを設定し、OPTIONSメソッドのプリフライトリクエストにも200を返すよう忘れずに行います。また、API Gatewayにはスロットリング(レート制限)を設定して、悪意あるリクエストから守ります。

コスト試算: 月間500予約でいくら?

リソース仕様月間コスト
LINE公式アカウント無料プラン¥0
API Gateway月間1,000リクエスト(500予約 × 2)¥0(無料枠内)
Lambda月間1,000回実行、平均200ms¥0(無料枠内)
DynamoDBオンデマンド、月間5,000リクエスト¥10〜50
S3 + CloudFrontミニアプリの静的ファイル配信¥0〜100
合計¥10〜150/月

ホットペッパーグルメの最低プラン(約13,000円/月)と比較すると、年間約15万円の差。予約数が増えても数百円程度にしかならないため、店舗規模を問わず導入しやすい構成です。

導入前後の比較

比較項目電話予約LINEミニアプリ予約
受付時間営業時間のみ24時間365日
スタッフの対応電話1件約3〜5分自動(不要)
予約確認の手間手動で確認・記録LINE通知で自動送信
キャンセル率高い(忘れるため)低い(リマインド通知で削減)
顧客データ手書きノート or なし全件DynamoDBに蓄積
月間コスト人件費(時間給×受付時間)¥0〜150

📊 実績データの参考: 予約リマインド通知を入れた飲食店では、平均キャンセル率が 12% → 4% に低下(Holiday Otter社の調査)。LINE通知によるリマインドの効果は大きく、来店率の向上にも直結します。

よくある質問

Q. LINEのミニアプリは外部からもアクセスできますか?

いいえ。LINEミニアプリはLINEアプリ内ブラウザ(LIFF)でしか開けません。ただし、S3+CloudFrontで同じWebアプリを別URLでも公開すれば、ブラウザからもアクセス可能にできます。「LINE内」と「通常のブラウザ」の両方で動く構成は容易です。

Q. 予約の取り消し・変更はどうやりますか?

ミニアプリ内の「予約一覧」画面から変更・キャンセルが可能です。変更はDynamoDBの条件付き書き換え、キャンセルはstatusを「cancelled」に更新するだけ。ユーザー側にもLINEメッセージでキャンセル通知が届きます。

Q. リマインド通知はいつ届きますか?

Lambda + EventBridge(CloudWatch Events)で予約日前日に自動送信を設定できます。前日18:00に「明日14:00から2名のご予約です」というLINEメッセージが自動で送られます。

他の章も読む

LINEミニアプリ予約システムの導入をご検討中の方へ

貴社の業態・規模に合わせた最適な構成をご提案いたします。
まずはお気軽にご相談ください。

無料相談を予約する →