😵‍💫

個人開発SaaS: 技術負債を生まないための初期実装Tips

に公開

はじめに

現在、ブログと学習ログ管理機能を組み合わせたWebサービス「ログツー」を個人開発しています。
https://zenn.dev/ymsy/articles/31d8d7bf73f680

この記事では、その開発過程で 「これは早めに実装しておいて本当に助かった!」と感じた機能と、逆に 「もっと初期段階で考慮しておくべきだった…」と反省している機能 について、その理由とともにまとめます。

個人でSaaS開発を進めている方、これから始めようとしている方の参考になれば幸いです。
(※ 本記事の内容は、開発を進める中で得られた学びに基づき、随時更新していく可能性があります。)

早めに実装してよかった機能

後々の改修コストや運用負荷を考えると、以下の機能は初期段階で実装しておいて正解だったと感じています。

ダークモード対応

理由: 実装が後になるほど、影響範囲(対応が必要なコンポーネント数)が広がり、修正コストが増大するため。

CSS変数などを活用し、初期のコンポーネント設計段階からダークモード/ライトモードの切り替えを意識しておくと、後々の負担が格段に減ります。UIライブラリ(shadcn/uiなど)によっては比較的容易に導入できる場合もありますが、カスタムコンポーネントが増えるほど対応は大変になります。導入を検討している場合は、早めに対応しておきましょう。

アクセス制御機能(管理画面)

理由: サービス運用中の予期せぬ事態や、段階的な機能リリースに柔軟に対応するため。

管理者向けの画面で、サービスの挙動を一時的に変更できる機能を実装しました。これにより、緊急メンテナンスや特定機能の不具合時に、ユーザー影響を最小限に抑えることができます。

  • メンテナンスモード:

    • 目的: 緊急の不具合修正、DBマイグレーション、インフラ作業など、サービス全体を一時停止したい場合。
    • 機能: 管理者以外のアクセスを遮断し、指定したメッセージ(例:「〇時までメンテナンス中です」)を表示するログインページ等へリダイレクト。
    • 効果: リリース前の最終調整期間など、安心して作業を進めることができました。
  • アカウント作成受付停止:

    • 目的: メール送信サービス(例: Resend)の障害時や、スパムアカウント対策など、新規登録を一時的に止めたい場合。
  • 外部認証(hCaptcha等)の一時停止:

    • 目的: 外部認証サービスの障害時に、ログインや特定操作ができなくなるのを回避する場合。
  • 課金機能の有効/無効切り替え:

    • 目的: Stripe等を導入する際、開発・テスト中は機能を無効化し、準備が整い次第、安全に有効化するため。
    • 効果: 段階的な機能リリースが容易になり、実装中の機能をユーザーから隠蔽できます。

メディアストレージの最適化

理由: ストレージコストの抑制と、データ管理の複雑化を防ぐため。

ユーザーが画像をアップロードする機能がある場合、ストレージ(S3など)の容量とコストは無視できません。リリース後に無駄なファイルが溜まると、整理や移行が非常に困難になります。

  • 画像圧縮:

    • 目的: ストレージ容量と転送量を削減。
    • 実装例: アップロード時にサーバーサイドで自動的に圧縮処理を実行。
  • 関連コンテンツ削除時のメディア自動削除:

    • 目的: 不要になったメディアファイルを自動で削除し、ストレージの肥大化を防ぐ。
    • 実装例: 記事削除のトランザクション内で、紐づくS3オブジェクトも削除する処理を組み込む。
  • ユーザーによるメディア管理機能:

    • 目的: ユーザー自身が不要なファイルを削除できるようにし、ストレージ容量制限の運用をしやすくする。
    • 実装例: 記事編集画面等で、紐づくメディアファイル一覧を表示し、個別に削除できるUIを提供。ユーザは記事毎の容量制限や使用状況を把握可能。

通報機能(CGM向け)

理由: CGM (Consumer Generated Media) としての法的・倫理的責任への対応、健全なコミュニティ維持のため。

ユーザー投稿コンテンツに不適切なものが含まれる可能性はゼロではありません。迅速かつ適切に対応できる体制は必須です。

  • スナップショット保存:

    • 目的: 通報時点でのコンテンツ内容を証拠として保全するため(通報後に編集・削除される可能性がある)。
    • 実装例: 通報時に記事本文や関連情報を別テーブルやJSONデータとして記録。
  • 対応履歴管理:

    • 目的: 複数人で対応する場合の責任の明確化、対応状況の追跡。
    • 実装例: 通報データに対応した管理者ID、対応日時、対応内容などを記録。

[反省] 早めに実装すべきだった機能

タイムゾーン対応

理由: 後からの修正は、日時を扱う全ての箇所(DBスキーマ、API、フロントエンド表示)に影響し、修正漏れのリスクも高く、非常にコストがかかるため。

開発初期段階で「ターゲットは国内ユーザーだから日本時間(JST)固定でいいや」と安易に考えてしまいました。しかし、海外在住の日本人ユーザーや、将来的なグローバル展開の可能性を考えると、これは明らかな設計ミスでした。

データベースにはUTCで日時を保存し、ユーザーごとに設定されたタイムゾーンに基づいて表示時に変換する、といった基本的な対応を、初期のデータモデリング段階から組み込むべきでした。既存データの移行や関連箇所の洗い出し・修正を考えると、気が重いです…。

おわりに

個人開発ではリソースが限られるため、どこまで初期に作り込むかは悩ましい問題です。素早く価値を届けるMVP(Minimum Viable Product)の考え方と、将来を見据えたこれらの基盤整備との間で、どこまで初期投資すべきかバランスを取るのは、個人開発における難しい判断点です。しかし、今回挙げたような機能、特に アクセス制御、ストレージ最適化、タイムゾーン対応 などは、後回しにすると技術的負債となり、将来の開発速度や運用コストに大きく影響する可能性があります。

この記事が、皆さんの個人開発における機能実装の優先順位付けや、設計の初期段階での考慮事項として、少しでも参考になれば嬉しいです。

私も今回の反省を活かし、今後の開発を進めていきたいと思います。

P.S. catnose大先生の「Webサービス公開前のチェックリスト」は必見です。まだの人は是非どうぞ。
https://zenn.dev/catnose99/articles/547cbf57e5ad28

Discussion