アーキテクチャの概要
このプロジェクトは、コアなQ&Aフォーラムを模倣したモノリシックなMVCフルスタック・アプリケーションであり、Java Spring Boot 3上にネイティブに構築されています。
- バックエンドとセキュリティ: Spring Bootがビジネスロジック、データの永続化、およびセキュリティをオーケストレーションします。分離されたSPAの代わりに、レスポンシブなUIコンポーネントのためのBootstrap 5と組み合わせた、Thymeleafによるサーバーサイド・レンダリング (SSR) を使用しています。この実用的な決定により、アプリケーションが純粋なモノリシックMVCパターンに統合され、セッション管理が簡素化され、CORSの複雑さが回避されました。
- データ層: Spring Data JPA/Hibernateを介してPostgreSQLデータベースと対話します。リレーショナル・モデルは高度に構造化されており、ユーザーのマッピングを質問、回答、および投票メカニズムに厳密に制限しています。
- アセット・ストレージ: メディアのアップロード(質問に添付されるスクリーンショットなど)は、Java SDKを使用して外部のCloudinaryにオフロードされ、ローカルサーバーやデータベースにバイナリ・データの肥大化が完全に生じないようにしています。
解決されたエンジニアリング課題
投票の完全性の確保
賛成票/反対票の単純な整数カウンターは、スパムや同じユーザーによる複数回の投票の影響を受けやすくなります。これに対抗するため、AnswerとUserの間の正確なリレーショナル・マッピングを追跡する専用のジャンクション・テーブル(AnswerUpvoteEntityおよびAnswerDownvoteEntity)を設計しました。toggleUpvoteロジックは、認証されたユーザーによる既存の投票がないかデータベースをチェックし、見つかった場合は削除し、見つからなかった場合は登録します。これにより、競合状態に強い完璧なトグル効果が生み出されます。
孤立したクラウド・メディアの管理
Cloudinaryなどの外部に画像を保存すると、ユーザーが質問を削除したり、新しい画像で更新したりした際に、古い画像が孤立してクラウド・ストレージの肥大化を招く可能性があります。QuestionServiceImplは、PostgreSQLでimageUrlとimagePublicIdの両方を明示的に追跡します。質問が更新または削除された場合、サービスはimagePublicIdを使用して明示的なAPI呼び出しを行い、リモート・アセットを安全に破棄し、クラウド環境を非常にクリーンに保ちます。
実用的な開発環境(メールのシミュレーション)
SMTP設定のボトルネックにより、ローカル開発中に(アクティベーション・トークンを使用した)アカウント・アクティベーション・フローを実装することは困難です。EmailServiceImplは、実際のアクティベーションURLを構築してメールをフォーマットするように設計されていますが、ローカル環境ではJavaMailSenderを明示的にバイパスし、代わりにアクティベーション・リンクをターミナル・コンソールに直接出力します。これにより、外部との摩擦なしに完全な認証フローを構築することができました。
成果
コードベースは、Javaエンタープライズ・アーキテクチャに対する実用的なアプローチを強調しています。サーバーサイド・レンダリング(SSR)を活用し、この特定のユースケースでは分離されたRESTful APIを放棄することで、システムは、厳格なエンタープライズグレードのSpring Securityと堅牢なリレーショナル整合性を維持しながら、納品までの時間を大幅に短縮しました。