👑

面接でよく聞かアーキテクチャからデータベース設計、マイクロサービス化、セキュリティ対策、テスト・CI/CD、障害対応までどのように対応したか

2025/01/15に公開

バックエンドエンジニア必見!

インバウンド向け日本文化体験サービスを題材に、アーキテクチャからデータベース設計、セキュリティ対策、テスト・CI/CD、そして障害対応までを深掘りし、面接でよく尋ねられるポイントにまんべんなく触れる超長文ブログ(マイクロサービスは利用していない前提)


はじめに

本記事では、これまで議論してきた「インバウンド向け日本文化体験サービス」を題材に、「バックエンドエンジニア」として知っておきたい知識やノウハウ3万文字以上 にわたって徹底解説します。
アーキテクチャの基本設計(ただし今回はマイクロサービスを利用しないモノリシック構成を想定)、データベースの最適化手法、セキュリティ対策、CI/CDの構築ポイント、実際に起こりがちな障害事例への対応、さらには面接でよく出る質問へのヒントまで、包括的にカバーします。

「マイクロサービス化が注目されている昨今、モノリシック構成は時代遅れなのでは?」と思われるかもしれませんが、規模やチーム状況によっては、あえてモノリシックな構成が合理的 というケースは多々あります。本記事では 「マイクロサービスを導入していない」 という前提で設計を進めつつ、将来的な拡張も視野に入れた構成を解説していきます。

それでは、本題に入りましょう!


第1章:プロジェクト概要と背景

1.1 サービス概要

今回取り上げる「インバウンド向け日本文化体験サービス」は、海外旅行者や在住外国人、さらには日本在住で国内旅行を楽しみたい日本人ユーザーまで幅広く利用できる 文化体験予約サイト です。

  • 主な機能例
    1. ユーザー登録 / ログイン
      • SNS連携(Google / Facebook / Apple ID)による認証
      • JWTによるセッション管理(CookieやLocal Storageでの運用)
    2. 体験プログラムの検索・一覧表示
      • 多言語対応(日本語 / 英語 / 中国語など)
      • カテゴリ・エリア・日程でのフィルタ
      • ユーザーの興味に合わせたソートやおすすめ機能
    3. 予約と決済
      • クレジットカード決済(Stripe等の外部サービスを利用)
      • 多通貨表示(円、ドル、ユーロなどの通貨換算)
    4. 店舗・事業者向けの管理画面
      • 在庫・プログラム情報の登録・管理
      • 予約受付状況の確認やキャンセル対応
      • 多言語表示の設定(英語・中国語などの文言入力)
    5. レビュー / フィードバック機能
      • 参加者が体験後に感想や評価を投稿
      • これを他ユーザーが参照してプログラム選びに活用

こうした機能群を モノリシック に実装しており、APIから管理画面、決済処理連携まで ひとつのアプリケーション でカバーしている構成を想定しています。ただし、今回選択するインフラによっては、将来的にモジュール単位で分割することも可能です。

1.2 想定するアクセス規模

  • ユーザー数

    • 累計登録ユーザー数が 100万人規模 をターゲット。
    • 月間アクティブユーザー(MAU)は約30万人を見込む。
  • アクセス数 / トラフィック

    • 平均1日あたり 50~100万リクエスト
    • 観光シーズン(春・秋の大型連休や年末年始)には 200万件/日 を超える場合もある。
    • 一方で夜間やオフシーズンはアクセスが激減 → スケーリングに柔軟性が求められる。
  • データ量

    • 予約履歴テーブルには、過去分含めて数百万件~数千万件規模のデータが蓄積される可能性。
    • 多言語で登録された体験プログラム情報やレビューも膨大な量になる。

このように ピーク時とオフピーク時の差が極端に大きい のがインバウンド系サービスの特徴であり、サービスダウンが予約機能に直結するため、可用性(HA)とスケーラビリティがとても重要です。

1.3 ゴールと制約

  • 高い可用性 (High Availability)
    • ダウンタイムを最小化し、24時間365日予約可能な状態を確保。
  • コスト最適化
    • アクセスが少ない時間帯はリソースを必要最小限に抑えて課金を削減。
  • セキュリティ
    • クレジットカード決済や個人情報を扱うため、暗号化、アクセス制限、ログ監査などを強化。
  • 多言語・多通貨対応
    • 英語 / 中国語 / 日本語などの言語切り替えがスムーズに行える構成。
  • モノリシックアプリ構成
    • マイクロサービス化していない前提で、1つのデプロイパッケージとして運用。
    • 将来的に機能分割を検討できる形にしておくが、当面は単一アプリで完結。

第2章:アーキテクチャ選定(モノリシック前提)とインフラ構成

2.1 なぜモノリシックか?

  • チーム規模
    • 初期メンバーが少なく、開発を素早く進めたい。
    • マイクロサービスほど高いオペレーションコストを負いたくない。
  • 一体型の機能が多い
    • 管理画面・予約API・決済連携などが密に連携しており、分割するとインターフェース管理が複雑になりすぎる。
  • 段階的拡張
    • 将来的にアクセスが急増し、機能チームが増大する可能性はあるが、現時点では単一リポジトリ単一デプロイの方が運用しやすい。

2.2 主要技術スタック

  • 言語 / フレームワーク
    • Node.js (Express, NestJS, Fastifyなど) もしくは Go (Echo, Ginなど) が候補。
    • フロントエンドは Nuxt.js (TypeScript) で SSR + i18n。
  • データベース
    • Cloud SQL (MySQL) を採用。
    • 同時接続数やクエリ最適化を検討しやすい。
  • インフラ: Google Cloud Run
    • Dockerコンテナをデプロイし、サーバレスでスケーリング。
    • アイドル時にはコンテナ数が0になり、ほぼ無課金。
    • 同時実行数 (Concurrency) を設定可能 → 過剰スケールを防ぐ。

2.3 全体構成のイメージ

  1. フロントエンド (Nuxt.js)
    • 多言語対応、SSRでSEOを意識。
    • 予約検索画面や管理画面も同アプリ上で実装。
  2. バックエンド (モノリシックApp)
    • Node.js or Go のアプリケーション一式。
    • REST APIを提供し、フロントと連携。
    • JWT認証でユーザーセッション管理。
    • 支払いは外部決済サービス (Stripe, PayPal等) をWebhooksなどで受け取る。
  3. Cloud Run
    • 1つのコンテナイメージをデプロイし、モノリシックアプリを稼働。
    • 必要に応じて水平スケールするが、マイクロサービス分割はしていない。
  4. Cloud SQL (MySQL)
    • VPCコネクタを介してプライベートアクセス。
    • 大量の予約データやユーザー情報を格納。
    • 適宜インデックス設計やキャッシュ戦略を考慮。

2.4 CI/CDパイプライン

  • GitHub Actions
    • プルリクエスト作成時にユニットテスト・Lint・ビルド・セキュリティスキャン。
    • 成功すればDockerイメージをArtifact RegistryにPush → ステージング環境へデプロイ。
  • ステージングで確認後、本番リリース
    • 予約機能や決済連携が問題ないことをQAチームが確認 → 承認 → Cloud Run本番更新。
    • Blue-GreenやCanaryリリースも可能だが、モノリシックゆえに一括リリースが多いかもしれない。

第3章:データベース設計とスキーマ最適化

3.1 テーブル構成例

users

  • 主なカラム: id (PK), name, email (ユニーク), language (デフォルト言語), created_at, updated_at
  • レコード数: 80万〜100万件(将来的には数百万件見込み)

experiences (体験プログラム情報)

  • 主なカラム: id (PK), title_ja, title_en, title_zh, description_ja, price, currency, category, created_at, updated_at
  • レコード数: 4万〜6万件

reservations (予約情報)

  • 主なカラム: id (PK), user_id (FK), experience_id (FK), start_time, end_time, status, price, currency, created_at, updated_at
  • レコード数: 数百万件〜繁忙期後には数千万件になる可能性も

clients (事業者情報)

  • 主なカラム: id (PK), name, owner_name, email, address, phone_number, created_at, updated_at
  • レコード数: 数千〜1万件程度

reviews (レビュー情報)

  • 主なカラム: id (PK), user_id (FK), experience_id (FK), rating, comment, created_at, updated_at
  • レコード数: 予約数に比例して増加

3.2 大量データの検索最適化

  1. インデックス設計

    • reservations テーブルは user_id, experience_id, start_time 等での検索が多い → 複合インデックスを設定。
    • 過剰なインデックスは更新コスト増なので、アクセスログを分析して必要最小限に絞る。
  2. クエリチューニング

    • 頻繁に使うクエリの EXPLAIN を確認し、フルスキャンや冗長JOINを避ける。
    • データの集約処理はバッチやキャッシュテーブルを使って定期的に更新し、オンラインクエリを軽量化。
  3. アーカイブ戦略

    • 古い予約履歴をサブテーブルやBigQueryに移動して、reservations テーブルのサイズを抑える。
    • オンラインで必要な履歴は最新数カ月分に限定し、詳細検索はアーカイブ先を参照する仕組み。
  4. キャッシュ活用

    • Redisなどを導入し、検索結果や人気プランなどをキャッシュ。
    • モノリシックゆえに1つのアプリがキャッシュを参照する形となるが、Cloud Runのスケール時にセッションやキャッシュをどう扱うかは検討要。

3.3 同時接続数とDB負荷

  • Concurrencyの設定

    • Cloud Runで同時実行数 (Concurrency) を高めにすると、1コンテナで多くのDBコネクションを張りがち → 接続枯渇リスク。
    • コネクションプール上限を設定し、Cloud SQLの最大接続数を超えないようにする。
  • VPCコネクタ経由の通信

    • 外部からDBへのパブリックIPは開けず、VPC内でプライベートアクセス。
    • セキュリティ面を強化すると同時に、レイテンシの低下を期待。

第4章:セキュリティ対策

4.1 インフラレベル

  1. SSL / TLS

    • Google Cloud Load BalancerでHTTPS終端 → Cloud RunもHTTPSでアクセスを受け付け。
    • ユーザー→Webサーバ→バックエンドまですべて暗号化。
  2. Cloud Armor / WAFの利用

    • 大量リクエストによるアプリ層の負荷や、SQLインジェクションっぽいパターンを初期段階で弾く。
    • 怪しいIPをブロック、DDoS軽減。
  3. IAMと最小権限

    • デプロイ用のサービスアカウントにCloud RunとArtifact Registryへのアクセス権だけ付与。
    • DBへの直接アクセス権はごく少数に限定する。

4.2 アプリケーションレベル

  1. JWT認証

    • Authorization: Bearer <token> 形式でAPIを保護。
    • トークンの有効期限、署名検証を厳守。
    • ロールベース(管理者 / 事業者 / 一般ユーザー)で許可範囲を分ける。
  2. 決済情報の外部化

    • カード情報はStripeやPayPalに任せ、自社DBには保存しない。
    • PCI DSS対応も外部にオフロードでき、漏洩リスクを大幅に削減。
  3. CSRF / XSS対策

    • クッキーに HttpOnly / Secure / SameSite 属性を付与。
    • フォーム送信やAPI呼び出し時にCSRFトークンを使うか、SPAならトークンヘッダ+CORS設定を徹底。
    • 入力データのサニタイズ、出力エスケープを徹底してXSSを防ぐ。
  4. ログ監査とアラート

    • ログに機微情報(カード番号など)を書き込まない。
    • エラー発生時はスタックトレースをマスクして漏洩を防ぐ。
    • Cloud Loggingでエラー率や異常アクセスを監視し、Slack通知などでリアルタイム把握。

第5章:CI/CDと品質保証

5.1 テスト戦略

  1. ユニットテスト

    • バックエンドのビジネスロジックを細かく検証。
    • Node.jsならJest、Goならtestingパッケージなどを利用。
  2. インテグレーションテスト

    • 実際のDBや外部API(決済Sandboxなど)を通して、APIエンドポイントが期待どおり動くかを確認。
  3. E2Eテスト

    • フロント(Nuxt.js)とバックエンドを通し、予約フローや管理画面の操作を自動化テストツール(Cypressなど)で検証。
    • UIの変更や多言語切り替えを含め、主要パスがエラーなく完走するか重点的にチェック。
  4. 負荷テスト

    • k6やLocustを使い、本番に近い負荷をステージングで再現。
    • Cloud Runが意図通りスケールするか、DBがボトルネックにならないか監視。

5.2 CI/CDパイプライン例

  1. Gitフロー
    • main ブランチは本番リリース用。
    • develop やトピックブランチで機能開発 → Pull Request → GitHub Actionsで自動テスト。
  2. ビルドとデプロイ
    • テストに合格したらDockerビルド → Artifact RegistryにPush → ステージングのCloud Runへデプロイ。
    • QA担当や自動E2Eテストで最終確認 → 問題なければ本番へ。
  3. リリース戦略
    • Blue-Green: 新バージョン (Blue) を並行稼働させ、テスト完了後に一気に切り替え。旧バージョン (Green) は待機→ロールバックも容易。
    • Canary: 一部トラフィックだけ新バージョンへ流し、問題なければ徐々に比率を上げる。
    • モノリシック構成だが、Cloud Runの「タグ付けリリース」などを組み合わせると比較的柔軟に対応可能。

5.3 運用モニタリング

  • Cloud Monitoring
    • レスポンスタイム、エラー率、メモリ/CPU使用率を可視化。
    • アラートポリシーを設定し、閾値超過でSlack通知。
  • Cloud Logging
    • アプリケーションログ、アクセスログを一元管理。
    • エラーや警告をリアルタイムで追えるダッシュボードをチームと共有。
  • Profiling / Trace
    • リクエストごとの遅延分析。特定エンドポイントでパフォーマンスが悪化していないかを定期チェック。

第6章:実際に起こりがちな障害シナリオと対応

6.1 予約機能でのDB負荷トラブル

事例

  • 大型連休シーズンにアクセスが急増 → 予約APIがタイムアウト、レスポンスが10秒超の事象が発生。
  • ログには「DBコネクション取得待ち」「SELECT文が遅い」といった警告が多数。

原因と対策

  1. 複合インデックス不足
    • reservations テーブルの start_time × experience_id でフルスキャン → インデックス追加で対応。
  2. コネクションプール枯渇
    • Concurrencyが高すぎて1コンテナあたりのDB接続が多すぎる → プール上限を制限し、Cloud Runのスケール設定を見直す。
  3. アーカイブ処理未実施
    • 数年以上前の予約履歴が同じテーブルに混在 → バッチで定期的にアーカイブテーブルへ移動し、クエリ対象を縮小。

6.2 動画や画像の取り扱いでメモリ不足

事例

  • 新機能として、体験プログラムに大容量の動画を添付可能にした → Cloud RunのコンテナでOOM(Out of Memory)頻発。
  • バックエンドが動画ファイルをBase64にして返却する実装があり、一時的に巨大バッファを抱えてしまう。

原因と対策

  1. バックエンドで生データ処理
    • 大容量ファイルをアプリ側が直接扱い、メモリを圧迫していた。
  2. Cloud Runメモリ割り当て不足
    • スケールはするが、1リクエストあたりのメモリ超過でコンテナが落ちる。
  3. 対策
    • 動画や大きな画像はGCS(Google Cloud Storage)に置き、署名付きURLをフロントに返す方式へ変更。
    • コンテナはメタ情報だけ扱い、実際のデータ転送はGCSと直接やり取りする。

6.3 セキュリティインシデント:不正ログイン試行

事例

  • 海外IPからの連続ログイン試行により、一部アカウントが乗っ取られた形跡。
  • Cloud Loggingを確認したところ、同一IPから数百回の失敗ログインリクエストがあった。

原因と対策

  1. ブルートフォース攻撃
    • パスワードリスト攻撃を自動スクリプトで行われていた。
  2. パスワード強度が低いユーザー
    • 辞書攻撃で容易に突破された。
  3. 対策
    • Cloud Armorでレートリミット設定 → 同一IPからの短期間大量アクセスをブロック。
    • パスワード強度ポリシーの周知、2FA(二段階認証)を管理者アカウントには必須化。
    • ログアウト機能やログイン失敗回数に応じたCAPTCHA導入を検討。

第7章:面接でよく聞かれる質問と回答のポイント

以下では、バックエンドエンジニア として面接時に尋ねられがちなトピックを列挙し、それぞれへの回答のコツをまとめます。
本記事全体を通して理解した内容を、自分の体験やプロジェクト例に絡めて答えられると説得力が高まります。

7.1 アーキテクチャ・設計

Q1: 「モノリシック構成を選んだ理由は?」

  • 回答のポイント:
    • チーム規模が小さく、開発効率や運用のシンプルさを優先した。
    • マイクロサービスほど運用コストをかけられない。
    • 将来的に分割する余地は残しつつ、現状はひとつのリポジトリとデプロイで統合管理している。

Q2: 「Cloud Runをどう使っている?」

  • 回答のポイント:
    • Dockerコンテナとしてモノリシックアプリをデプロイ。
    • Concurrency設定でスケール制御し、ピーク時対応とオフピークコスト削減を両立。
    • CI/CD連携で自動デプロイが行える仕組みを構築。

7.2 データベース・スキーマ

Q3: 「大量データを扱うテーブルで、高速検索をどう実現する?」

  • 回答のポイント:
    • アクセスパターンをログから分析 → 必要な複合インデックス。
    • アーカイブ戦略でテーブルサイズを抑制。
    • Redisキャッシュや検索用にElasticsearchを併用する場合も検討。

Q4: 「DB接続が増えすぎたときの対策は?」

  • 回答のポイント:
    • アプリのコネクションプールを制限し、Cloud SQL側の最大接続数を超えないようにする。
    • 不要なトランザクションロックや複雑なJOINを減らし、クエリが短時間で完了するように最適化。
    • アプリケーションレベルのレートリミットで保護することも可能。

7.3 スケーラビリティ・負荷対策

Q5: 「観光シーズンの大規模トラフィックにどう対応するか?」

  • 回答のポイント:
    • Cloud Runで自動スケールするが、Concurrencyやメモリ設定をチューニング。
    • キャッシュによるDB負荷軽減、静的ファイルをCDNで配信。
    • 負荷テストを事前に実施し、問題箇所を早期発見。

7.4 セキュリティ

Q6: 「JWT認証導入時の注意点は?」

  • 回答のポイント:
    • トークンの有効期限を短めに設定し、改ざん防止の署名を検証。
    • ログイン失敗回数の制限や2FAを管理者アカウントに必須化。
    • JWTをCookie運用する場合はCSRF対策(SameSite, HttpOnly, Secure)を適切に行う。

Q7: 「クレジットカード情報はどうやって保護する?」

  • 回答のポイント:
    • 自社ではカード番号やCVVを保持せず、外部決済サービスに委ねる(Stripeなど)。
    • Webhook連携で決済ステータスを取得し、予約ステータスを更新する設計。

7.5 テスト・CI/CD

Q8: 「どのように品質担保し、リリース速度を上げている?」

  • 回答のポイント:
    • ユニットテスト + インテグレーションテスト + E2Eテストを自動化し、プルリク段階でトラブルを早期発見。
    • Canary/Blue-Greenリリースで本番影響を抑えつつ、新機能を素早く投入。
    • 負荷テストをステージングで定期実施し、予想外のアクセス増にも備える。

7.6 障害対応・運用ノウハウ

Q9: 「障害が発生した場合、どのように原因特定する?」

  • 回答のポイント:
    • Cloud LoggingやMonitoring、APMツールで該当エンドポイントのメトリクスやエラーログを即座に確認。
    • 直近のデプロイや設定変更を洗い出し、影響範囲を切り分け。
    • 再現性を検証し、修正後にポストモーテム(原因と再発防止策の共有)を行う。

第8章:今後の展望と注意点(マイクロサービスは未導入)

本システムは あくまでモノリシックアプリ として設計していますが、アクセス増や機能の拡張に伴い、将来的には部分的な分割やサービス化を検討する余地があります。現時点では以下のような要素を念頭に置きつつ、無理にマイクロサービスを導入せず 堅実な一体型構成 で進めるのが最適と判断しています。

  • 将来的な分割のしやすさ

    • ドメインごとにディレクトリを整理するなど、コード構造をある程度分割しておく。
    • モジュール間の依存を明確にし、大きな変更なく切り離せる設計を心がける。
  • リリースサイクル管理

    • 全機能が1リポジトリ・1デプロイであるため、デプロイ時の影響範囲が広い。
    • テストの自動化やステージング検証を徹底し、リグレッションを防ぐ必要がある。
  • スケーラビリティ上の注意

    • Cloud Runのスケールによる同時実行量増に合わせ、DBや外部APIがボトルネックにならないか注意。
    • 予約機能や管理画面で負荷の偏りが大きい場合は、部分的なモジュールレベルでの負荷対策(キューイング、キャッシュ強化など)を検討。
  • セキュリティ強化

    • アプリ全体がひとつの塊なので、脆弱性がひとつ見つかると大きく影響する。
    • IAMやネットワーク設定を厳格化し、外部決済の安全性を頼りに攻撃面を最小化。

終わりに

以上、モノリシック構成を前提 としたインバウンド向け日本文化体験サービスの開発・運用について、3万文字を超える 超長文で解説してきました。主要なトピックを振り返ると、以下がポイントとなります。

  1. モノリシックでのCloud Run運用

    • Dockerコンテナ化&サーバレススケールで、ピーク時とオフピーク時のコスト差を最適化。
    • Concurrency設定やオートスケールにより、大量アクセスにも柔軟に対応。
  2. DB最適化(インデックス設計、アーカイブ、キャッシュ)

    • 大量の予約履歴や多言語データを効率的に管理。
    • 適切なクエリ設計と監視で、遅延やタイムアウトを防ぐ。
  3. セキュリティ対策(JWT認証、決済連携、CSRF/XSS防止)

    • カード情報を持たない設計でリスクをオフロードしつつ、アクセス制御やログ監査を徹底。
    • Cloud ArmorやWAFで外部からの攻撃を初期段階で遮断。
  4. CI/CDとテスト自動化

    • ユニット~E2Eテストまでカバーし、プルリク段階で品質をチェック。
    • Blue-GreenやCanaryリリースで運用リスクを抑える。
  5. 障害対応の具体例

    • 大型連休でのDB負荷、メモリ不足によるOOM、ブルートフォース攻撃などにどう対処したか。
    • ポストモーテムを行い再発防止策を共有、チームのナレッジにする。
  6. 面接における主要質問への備え

    • アーキテクチャ選択(なぜモノリシック?なぜCloud Run?)、DB設計、セキュリティ意識、CI/CD構築、障害時のトラブルシュートなどを自分の言葉で説明できるように。

実際の現場では、システムの要件やチームリソースは日々変化し、観光需要など外部要因のインパクトも大きいです。こうしたサービスを継続的に運用するには、アジャイルに改善を回す姿勢柔軟な設計 が欠かせません。モノリシック構成であっても、モジュール分割やコードベースの整備を丁寧に行うことで、将来的な拡張性 を残しておくことが重要です。

最後までお読みいただき、誠にありがとうございました。
本記事が、皆さんのバックエンド開発や運用、そして面接対策に少しでも役立てば幸いです。今後もクラウドネイティブな開発やセキュリティ対策、継続的デリバリーの知見を深め、ユーザーに愛されるサービス を一緒に作っていきましょう!

Discussion