はじめに

こんにちは。
今年の夏ごろにAWSからAIを搭載したIDEであるKiroがリリースされました(プレスリリース)。
AWSから提供されていることもありAWSとの連携は強いのですが、最大の特徴としては単なるAIによるコード補完や生成にとどまらず、仕様駆動開発 (Spec-Driven Development)を核としているところにあります。

開発のアイデアを日本語などの自然言語でAIに与えることで、AIが要件定義、システム設計、実装タスク等を作成してくれます。それを基にコードを含む成果物を生成することで、短時間で開発のアイデアを動くモノとしてアウトプットすることが可能になります。

実際に下記のようなWebページをKiroを用いて開発しました。

インストール

公式ページからダウンロードが行えます。リリース当初はウェイトリストがあったのですが、現在はウェイトリストは終了しているとのことです。無料でも多少のクレジットが使用できるため、早速インストールしてみました!
インストールが完了して起動すると、VSCodeに似た画面が現れます。 VSCodeがベースになっているため、プラグインなどはKiroにも一部流用することもできます。

使ってみた

仕様の作成

早速つかって開発してみます。新規チャットを開き、Specを選択した状態で開発アイデアを投げてみます。

自分はカメラを使った風景などの撮影が趣味なので、撮った写真を簡単に公開できるWebページがあると便利かなと思っていることから、写真を簡単に公開できるページを作成してみたいと思います。

下図のように、AIから要件定義のための質問を投げてもらい、それに答える形で仕様を定義していきます。
ここではコンテキストファイルとして要件定義のサンプルと出力先は指定しています。サンプルには要件定義書に記載してほしい項目(ビジネス仮説、概要、ユーザーストーリー、要件と受け入れ基準)を記載しています。

AIからの質問は下記の通りでした。

回答を基に要件定義書が作成されます。作成された要件に対して修正したい部分があれば追加で指摘することで要件定義がブラッシュアップされます。

要件定義について承認すると、システムのアーキテクチャ、コンポーネント設計、データモデルなどを含む詳細な設計書が作成されます。特に指定はしていないのですが、フロントエンドのコンポーネント一覧、REST API、データベーススキーマ、セキュリティ対策、テスト戦略まで設計してくれます!ここで実装に向けた技術選定も行われます。

設計書の作成が完了するとタスクリストが作成されます。実装に向けて段階的に構築できるよう手順が記載されています。次のフェーズでこの生成されたタスクリストを基にコーディングしたいと思います。

実装

実装では上記で作成したタスクリストに従ってコーディングしてもらいます。開発環境の用意から実装、テストまですべてAIが対応してくれます。下図のようにコマンドの実行中にエラーが発生した場合でも、原因の特定から修正まで自動的に実施してくれます。便利です。

テストも実行され、タスクリストの内容が全て実行完了したようです。

ローカルホストで起動できるらしいので、実際にアクセスしてみたいと思います!(画像には)既に写真が追加済みですが、意図通り動作していることが確認できます。

ちなみに、SwaggerによるAPIドキュメントも作成されていました!至れり尽くせりで感動しました。

所感

1時間程度でWebページの作成までできました。 私自身はAIとチャットしていただけですが、AIとの対話によって要件定義から設計書、成果物まで作成されました。
一番驚いたのが、Pythonで使用する外部パッケージのpipインストールを含む環境構築や、コード実行時のエラーが発生したときの挙動です。エラーが発生した場合、自動的に出力内容やコードを精査し原因の対処を実施していました。仕様が固まった後は、私はコーヒーを飲みながらAIが開発している様子を眺めているだけでした。

このように、プロダクトに対するアイデアを爆速で動くモノに仕上げることができるため、初期プロトタイピングの加速や市場適合性の早期確認ができるようになるメリットがあるのではと思います。また、実際に動くモノを提供できるため、ドキュメントによる説明よりもプロダクトに対する認識ズレを最小限にすることも期待できそうです。

生成された要件定義
# 要件定義(requirements.md)

## ビジネス仮説
写真愛好家は、作例を閲覧する際に撮影機材や設定情報を同時に確認することで、自身の撮影技術向上に役立てたいと考えている。また、自身が撮影した写真を体系的に公開することで、オンラインポートフォリオとして活用し、自分の撮影スキルや作品を効果的にアピールできる。シンプルで直感的なインターフェースを提供することで、非エンジニアのユーザーでも容易に写真作例を閲覧・管理でき、プロフェッショナルな印象を与えるWebページが求められている。

## 概要
本アプリケーションは、20代~40代の写真愛好家をターゲットとした写真作例公開Webページです。撮影した写真とともに、使用機材(カメラ、レンズ)や撮影設定(シャッタースピード、絞り、ISO感度、焦点距離)を表示し、ジャンル別・機材別のフィルタリング機能を提供します。写真家が自身の作品を体系的に公開し、オンラインポートフォリオとして活用できることを目的としています。PCとスマートフォンの両方に対応したレスポンシブデザインを採用し、管理画面から写真の追加・編集が可能です。

## 用語集

- **システム**: 写真作例公開Webページシステム
- **閲覧者**: Webページを訪問して写真を閲覧するユーザー
- **管理者**: 管理画面から写真の追加・編集を行うユーザー
- **撮影情報**: カメラ、レンズ、シャッタースピード、絞り、ISO感度、焦点距離を含む撮影時の設定データ
- **ジャンル**: 風景、ポートレート、スナップなど、写真のカテゴリー分類
- **フィルタリング**: ジャンルまたは機材による写真の絞り込み表示機能
- **一覧表示**: 複数の写真をサムネイル形式で表示する画面
- **拡大表示**: 個別の写真を大きく表示する画面
- **管理画面**: 管理者が写真の追加・編集を行うための専用インターフェース

## ユーザーストーリー
### 閲覧者の利用シーン
田中さん(32歳、写真愛好家)は、自分の撮影技術を向上させるために、他の写真家の作例を参考にしたいと考えています。特に、どのような機材と設定で撮影されたかを知ることで、自分の撮影に活かしたいと思っています。PCやスマートフォンから気軽にアクセスし、ジャンルや使用機材でフィルタリングして、興味のある写真を効率的に閲覧できることを望んでいます。

### 管理者(写真家)の利用シーン
佐藤さん(写真家)は、自分の撮影した写真を定期的にWebページで公開し、オンラインポートフォリオとして活用したいと考えています。クライアントや写真愛好家に自分の作品と撮影スキルをアピールするため、プロフェッショナルな印象を与えるWebページが必要です。エンジニアではないため、複雑な操作なしに管理画面から写真をアップロードし、ジャンルや撮影情報を入力できることを望んでいます。また、自分の作品を体系的に整理し、訪問者が興味のある作品を見つけやすくすることで、ポートフォリオとしての価値を高めたいと考えています。

## 要件

### 要件1: 写真一覧表示機能
**ユーザストーリー**: 閲覧者として、公開されている写真の一覧をサムネイル形式で閲覧したい。そうすることで、興味のある写真を素早く見つけることができる。

#### 受け入れ基準
1. WHEN 閲覧者がトップページにアクセスしたとき、THE システム SHALL 公開されているすべての写真をサムネイル形式で一覧表示する
2. WHEN 閲覧者がPCからアクセスしたとき、THE システム SHALL PC画面に最適化されたレイアウトで写真一覧を表示する
3. WHEN 閲覧者がスマートフォンからアクセスしたとき、THE システム SHALL スマートフォン画面に最適化されたレイアウトで写真一覧を表示する
4. WHEN 写真一覧が表示されているとき、THE システム SHALL 各写真のサムネイルとともにジャンル名を表示する

### 要件2: 写真拡大表示機能
**ユーザストーリー**: 閲覧者として、一覧から写真をクリックして拡大表示し、詳細な撮影情報を確認したい。そうすることで、撮影技術の参考にできる。

#### 受け入れ基準
1. WHEN 閲覧者が一覧表示で写真のサムネイルをクリックしたとき、THE システム SHALL その写真を拡大表示する
2. WHEN 写真が拡大表示されているとき、THE システム SHALL カメラ名、レンズ名、シャッタースピード、絞り、ISO感度、焦点距離を表示する
3. WHEN 写真が拡大表示されているとき、THE システム SHALL 前の写真に遷移するボタンを表示する
4. WHEN 写真が拡大表示されているとき、THE システム SHALL 次の写真に遷移するボタンを表示する
5. WHEN 閲覧者が拡大表示で前の写真ボタンをクリックしたとき、THE システム SHALL 前の写真を拡大表示する
6. WHEN 閲覧者が拡大表示で次の写真ボタンをクリックしたとき、THE システム SHALL 次の写真を拡大表示する

### 要件3: ジャンル別フィルタリング機能
**ユーザストーリー**: 閲覧者として、特定のジャンルの写真だけを表示したい。そうすることで、興味のあるジャンルの作例を効率的に閲覧できる。

#### 受け入れ基準
1. WHEN 写真一覧が表示されているとき、THE システム SHALL ジャンル選択用のフィルターUIを表示する
2. WHEN 閲覧者がジャンルフィルターで特定のジャンルを選択したとき、THE システム SHALL 選択されたジャンルの写真のみを一覧表示する
3. WHEN ジャンルフィルターが適用されているとき、THE システム SHALL フィルター解除ボタンを表示する
4. WHEN 閲覧者がフィルター解除ボタンをクリックしたとき、THE システム SHALL すべての写真を一覧表示する

### 要件4: 機材別フィルタリング機能
**ユーザストーリー**: 閲覧者として、特定のカメラまたはレンズで撮影された写真だけを表示したい。そうすることで、自分が所有している機材や購入を検討している機材の作例を確認できる。

#### 受け入れ基準
1. WHEN 写真一覧が表示されているとき、THE システム SHALL カメラ選択用のフィルターUIを表示する
2. WHEN 写真一覧が表示されているとき、THE システム SHALL レンズ選択用のフィルターUIを表示する
3. WHEN 閲覧者がカメラフィルターで特定のカメラを選択したとき、THE システム SHALL 選択されたカメラで撮影された写真のみを一覧表示する
4. WHEN 閲覧者がレンズフィルターで特定のレンズを選択したとき、THE システム SHALL 選択されたレンズで撮影された写真のみを一覧表示する
5. WHEN 複数のフィルターが適用されているとき、THE システム SHALL すべての条件を満たす写真のみを一覧表示する

### 要件5: 写真追加機能
**ユーザストーリー**: 管理者として、管理画面から新しい写真を追加したい。そうすることで、エンジニアの支援なしに写真作例を公開できる。また、撮影情報を手動で入力する手間を省くため、EXIF情報から自動的に取得したい。

#### 受け入れ基準
1. WHEN 管理者が管理画面にアクセスしたとき、THE システム SHALL 写真追加フォームを表示する
2. WHEN 管理者が写真ファイルを選択したとき、THE システム SHALL 選択された画像のプレビューを表示する
3. WHEN 管理者が写真ファイルを選択したとき、THE システム SHALL 写真のEXIF情報からカメラ名、レンズ名、シャッタースピード、絞り、ISO感度、焦点距離を抽出する
4. WHEN EXIF情報が正常に抽出されたとき、THE システム SHALL 抽出された撮影情報を各入力フィールドに自動入力する
5. WHEN EXIF情報が存在しないまたは抽出できなかったとき、THE システム SHALL 入力フィールドを空白のまま表示する
6. WHEN 管理者が写真追加フォームを表示しているとき、THE システム SHALL ジャンル選択フィールドを表示する
7. WHEN 管理者が写真追加フォームを表示しているとき、THE システム SHALL カメラ名、レンズ名、シャッタースピード、絞り、ISO感度、焦点距離の入力フィールドを表示する
8. WHEN EXIF情報から自動入力された撮影情報が表示されているとき、THE システム SHALL 管理者が手動で編集できるようにする
9. WHEN 管理者がすべての必須項目を入力して送信ボタンをクリックしたとき、THE システム SHALL 写真と撮影情報を保存する
10. WHEN 写真が正常に保存されたとき、THE システム SHALL 成功メッセージを表示する

### 要件6: 写真編集機能
**ユーザストーリー**: 管理者として、既に公開している写真の情報を編集したい。そうすることで、誤った情報を修正できる。

#### 受け入れ基準
1. WHEN 管理者が管理画面で写真一覧を表示しているとき、THE システム SHALL 各写真に編集ボタンを表示する
2. WHEN 管理者が編集ボタンをクリックしたとき、THE システム SHALL その写真の編集フォームを表示する
3. WHEN 編集フォームが表示されているとき、THE システム SHALL 現在の撮影情報が入力された状態で表示する
4. WHEN 管理者が編集内容を変更して保存ボタンをクリックしたとき、THE システム SHALL 更新された情報を保存する
5. WHEN 写真情報が正常に更新されたとき、THE システム SHALL 成功メッセージを表示する

### 要件7: 写真削除機能
**ユーザストーリー**: 管理者として、公開している写真を削除したい。そうすることで、不要になった写真を管理できる。

#### 受け入れ基準
1. WHEN 管理者が管理画面で写真一覧を表示しているとき、THE システム SHALL 各写真に削除ボタンを表示する
2. WHEN 管理者が削除ボタンをクリックしたとき、THE システム SHALL 削除確認ダイアログを表示する
3. WHEN 管理者が削除確認ダイアログで確認ボタンをクリックしたとき、THE システム SHALL その写真を削除する
4. WHEN 写真が正常に削除されたとき、THE システム SHALL 成功メッセージを表示する

## KPI設計

### 主要指標
- 月間ページビュー数: 写真作例ページの閲覧回数
- 写真拡大表示率: 一覧表示から拡大表示への遷移率
- フィルタリング使用率: フィルター機能を使用した閲覧セッションの割合

### 副次指標
- デバイス別アクセス比率: PC vs スマートフォンのアクセス割合
- 平均セッション時間: 1回の訪問あたりの平均滞在時間
- 写真追加頻度: 管理者による月間写真追加数

## 技術要件

### 優先順位付き機能一覧

**Week 1: 必須機能**
- 写真一覧表示機能(レスポンシブ対応)
- 写真拡大表示機能(撮影情報表示含む)
- 基本的な管理画面(写真追加機能)

**Week 2: 重要機能**
- ジャンル別フィルタリング機能
- 機材別フィルタリング機能
- 拡大表示での写真遷移機能

**Week 3: 追加機能**
- 写真編集機能
- 写真削除機能
- 管理画面のUI改善

**Week 4: 拡張機能**
- 写真ダウンロード機能
- パフォーマンス最適化
- アクセシビリティ対応強化

## 受け入れ条件

### 写真閲覧機能
- PCとスマートフォンの両方で正常に表示されること
- 一覧表示から拡大表示への遷移がスムーズに動作すること
- すべての撮影情報が正確に表示されること

### フィルタリング機能
- ジャンル、カメラ、レンズの各フィルターが正常に動作すること
- 複数フィルターの組み合わせが正しく機能すること
- フィルター解除が正常に動作すること

### 管理機能
- 非エンジニアの管理者が直感的に操作できること
- 写真の追加・編集・削除がエラーなく実行できること
- 入力エラー時に適切なエラーメッセージが表示されること

生成された設計書

※一部修正しています。

# 設計書(design.md)

## 概要
本設計書は、写真作例公開Webページシステムの技術的な実装方針を定義します。フロントエンドとバックエンドを分離したアーキテクチャを採用し、レスポンシブデザイン、EXIF情報の自動抽出、効率的なフィルタリング機能を実現します。

## アーキテクチャ

### システム構成
本システムは以下の3層アーキテクチャで構成されます:

1. **プレゼンテーション層(フロントエンド)**
   - HTML/CSS/JavaScriptによるSPA(Single Page Application)
   - レスポンシブデザインフレームワーク(Bootstrap または Tailwind CSS)
   - 閲覧者向けページと管理者向けページ

2. **アプリケーション層(バックエンド)**
   - RESTful API
   - Node.js + Express または Python + Flask/FastAPI
   - EXIF情報抽出ライブラリ(exif-js または Pillow)
   - 認証・認可機能(管理画面用)

3. **データ層**
   - リレーショナルデータベース(SQLite または PostgreSQL)
   - 画像ファイルストレージ(ローカルファイルシステム または クラウドストレージ)

### 技術スタック

**フロントエンド**
- HTML5, CSS3, JavaScript (ES6+)
- CSSフレームワーク: Tailwind CSS または Bootstrap
- 画像表示: Lightbox系ライブラリ(例: PhotoSwipe, GLightbox)

**バックエンド**
- Python 3.9+
- FastAPI(Webフレームワーク)
- SQLAlchemy(ORM)
- Pillow(EXIF抽出)
- python-jose(JWT認証)
- passlib(パスワードハッシュ化)

**データベース**
- SQLite(プロトタイプ・本番環境共通)
- 完全無料、設定不要、ファイルベース

## コンポーネントと機能

### フロントエンド コンポーネント

#### 1. 閲覧者向けページ

**PhotoGalleryPage(写真一覧ページ)**
- 責務: 写真のサムネイル一覧表示、フィルタリングUI提供
- 主要機能:
  - グリッドレイアウトでサムネイル表示
  - ジャンル、カメラ、レンズのフィルターUI
  - レスポンシブ対応(PC: 4列、タブレット: 3列、スマホ: 2列)
- API連携: GET /api/photos(クエリパラメータでフィルタリング)

**PhotoDetailModal(写真拡大表示モーダル)**
- 責務: 写真の拡大表示と撮影情報表示
- 主要機能:
  - 画像の拡大表示
  - 撮影情報(カメラ、レンズ、設定値)の表示
  - 前/次の写真への遷移ボタン
  - モーダルクローズ機能
- API連携: GET /api/photos/:id

**FilterPanel(フィルターパネル)**
- 責務: フィルタリング条件の選択UI
- 主要機能:
  - ジャンルドロップダウン
  - カメラドロップダウン
  - レンズドロップダウン
  - フィルター解除ボタン
- API連携: GET /api/filters(利用可能なフィルター選択肢取得)

#### 2. 管理者向けページ

**AdminLoginPage(管理者ログインページ)**
- 責務: 管理者認証
- 主要機能:
  - ユーザー名/パスワード入力フォーム
  - ログイン処理
- API連携: POST /api/auth/login

**AdminDashboard(管理ダッシュボード)**
- 責務: 写真管理の統合画面
- 主要機能:
  - 写真一覧表示(管理用)
  - 写真追加ボタン
  - 各写真の編集/削除ボタン
- API連携: GET /api/admin/photos

**PhotoUploadForm(写真アップロードフォーム)**
- 責務: 新規写真の追加
- 主要機能:
  - ファイル選択(ドラッグ&ドロップ対応)
  - 画像プレビュー
  - EXIF情報の自動抽出と表示
  - 撮影情報入力フィールド(編集可能)
  - ジャンル選択
  - 送信ボタン
- API連携: POST /api/admin/photos

**PhotoEditForm(写真編集フォーム)**
- 責務: 既存写真の情報編集
- 主要機能:
  - 現在の撮影情報表示
  - 撮影情報編集フィールド
  - ジャンル変更
  - 保存ボタン
- API連携: PUT /api/admin/photos/:id

### バックエンド コンポーネント

#### 1. APIエンドポイント

**公開API(認証不要)**

\```
GET /api/photos
- 説明: 写真一覧取得(フィルタリング対応)
- クエリパラメータ:
  - genre: ジャンルでフィルタリング
  - camera: カメラでフィルタリング
  - lens: レンズでフィルタリング
- レスポンス: 写真オブジェクトの配列

GET /api/photos/:id
- 説明: 特定の写真の詳細情報取得
- レスポンス: 写真オブジェクト

GET /api/filters
- 説明: 利用可能なフィルター選択肢取得
- レスポンス: { genres: [], cameras: [], lenses: [] }
\```

**管理API(認証必要)**

\```
POST /api/auth/login
- 説明: 管理者ログイン
- リクエストボディ: { username, password }
- レスポンス: { token, user }

GET /api/admin/photos
- 説明: 管理用写真一覧取得
- レスポンス: 写真オブジェクトの配列

POST /api/admin/photos
- 説明: 新規写真追加
- リクエストボディ: FormData(画像ファイル + 撮影情報)
- レスポンス: 作成された写真オブジェクト

PUT /api/admin/photos/:id
- 説明: 写真情報更新
- リクエストボディ: 更新する撮影情報
- レスポンス: 更新された写真オブジェクト

DELETE /api/admin/photos/:id
- 説明: 写真削除
- レスポンス: { success: true }
\```

#### 2. サービス層

**PhotoService**
- 責務: 写真関連のビジネスロジック
- 主要メソッド:
  - `getAllPhotos(filters)`: フィルタリング条件に基づいて写真を取得
  - `getPhotoById(id)`: IDで写真を取得
  - `createPhoto(photoData, file)`: 新規写真作成
  - `updatePhoto(id, photoData)`: 写真情報更新
  - `deletePhoto(id)`: 写真削除
  - `getAvailableFilters()`: 利用可能なフィルター選択肢取得

**ExifService**
- 責務: EXIF情報の抽出
- 主要メソッド:
  - `extractExifData(imageFile)`: 画像ファイルからEXIF情報を抽出
  - `parseExifToPhotoData(exifData)`: EXIF情報を撮影情報オブジェクトに変換
- 抽出する情報:
  - カメラ名: Make + Model
  - レンズ名: LensModel
  - シャッタースピード: ExposureTime
  - 絞り: FNumber
  - ISO感度: ISOSpeedRatings
  - 焦点距離: FocalLength

**AuthService**
- 責務: 認証・認可
- 主要メソッド:
  - `login(username, password)`: ログイン処理、JWTトークン発行
  - `verifyToken(token)`: トークン検証
  - `hashPassword(password)`: パスワードハッシュ化

**FileService**
- 責務: ファイル管理
- 主要メソッド:
  - `saveImage(file)`: 画像ファイルを保存
  - `deleteImage(filename)`: 画像ファイルを削除
  - `generateThumbnail(file)`: サムネイル生成(オプション)

## データモデル

### Photoテーブル

\```sql
CREATE TABLE photos (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  filename VARCHAR(255) NOT NULL,
  genre VARCHAR(50) NOT NULL,
  camera VARCHAR(100),
  lens VARCHAR(100),
  shutter_speed VARCHAR(50),
  aperture VARCHAR(50),
  iso VARCHAR(50),
  focal_length VARCHAR(50),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
\```

**フィールド説明**
- `id`: 写真の一意識別子
- `filename`: 保存された画像ファイル名
- `genre`: ジャンル(風景、ポートレート、スナップなど)
- `camera`: カメラ名
- `lens`: レンズ名
- `shutter_speed`: シャッタースピード(例: "1/250")
- `aperture`: 絞り値(例: "f/2.8")
- `iso`: ISO感度(例: "ISO 400")
- `focal_length`: 焦点距離(例: "50mm")
- `created_at`: 作成日時
- `updated_at`: 更新日時

### Userテーブル(管理者用)

\```sql
CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username VARCHAR(50) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
\```

**フィールド説明**
- `id`: ユーザーの一意識別子
- `username`: ログイン用ユーザー名
- `password_hash`: ハッシュ化されたパスワード
- `created_at`: 作成日時

## インターフェース設計

### APIレスポンス形式

**写真オブジェクト**
\```json
{
  "id": 1,
  "filename": "photo_001.jpg",
  "imageUrl": "/uploads/photo_001.jpg",
  "genre": "風景",
  "camera": "Fuga EOS R5",
  "lens": "Fuga 24-70mm F2.8 L IS USM",
  "shutterSpeed": "1/250",
  "aperture": "f/5.6",
  "iso": "ISO 400",
  "focalLength": "50mm",
  "createdAt": "2025-11-10T10:00:00Z",
  "updatedAt": "2025-11-10T10:00:00Z"
}
\```

**フィルター選択肢オブジェクト**
\```json
{
  "genres": ["風景", "ポートレート", "スナップ"],
  "cameras": ["Fuga EOS R5", "Hoge Z9"],
  "lenses": ["Fuga 24-70mm F2.8 L IS USM", "Hoge Z 24-70mm f/2.8 S"]
}
\```

**エラーレスポンス**
\```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "ジャンルは必須項目です",
    "details": {}
  }
}
\```

## エラーハンドリング

### フロントエンド

**ネットワークエラー**
- API通信失敗時にユーザーフレンドリーなエラーメッセージを表示
- リトライボタンを提供

**バリデーションエラー**
- フォーム送信前にクライアント側でバリデーション
- エラーメッセージを各入力フィールドの近くに表示

**画像読み込みエラー**
- 画像が読み込めない場合、プレースホルダー画像を表示

### バックエンド

**HTTPステータスコード**
- 200: 成功
- 201: 作成成功
- 400: バリデーションエラー
- 401: 認証エラー
- 403: 権限エラー
- 404: リソースが見つからない
- 500: サーバーエラー

**エラーログ**
- すべてのエラーをログファイルに記録
- 重要なエラーは管理者に通知(オプション)

## セキュリティ設計

### 認証・認可
- 管理APIへのアクセスはJWTトークンによる認証が必要
- トークンの有効期限: 24時間
- パスワードはbcryptでハッシュ化して保存

### ファイルアップロード
- 許可する画像形式: JPEG, PNG
- 最大ファイルサイズ: 10MB
- ファイル名のサニタイズ(特殊文字除去)
- アップロードされたファイルの拡張子検証

### XSS対策
- ユーザー入力のエスケープ処理
- Content Security Policy (CSP) ヘッダーの設定

### CSRF対策
- 管理画面のフォームにCSRFトークンを含める
- SameSite Cookie属性の設定

## パフォーマンス最適化

### 画像最適化
- サムネイル画像の自動生成(一覧表示用)
- 画像の遅延読み込み(Lazy Loading)
- 適切な画像フォーマット(WebP対応)

### データベース最適化
- 頻繁に検索されるカラム(genre, camera, lens)にインデックス作成
- ページネーション実装(将来的に写真数が増えた場合)

### キャッシング
- 静的アセット(CSS, JS, 画像)のブラウザキャッシュ
- APIレスポンスのキャッシュ(フィルター選択肢など)

## テスト戦略

### フロントエンドテスト
- **ユニットテスト**: 個別コンポーネントのロジックテスト
- **統合テスト**: コンポーネント間の連携テスト
- **E2Eテスト**: ユーザーシナリオに基づいた動作テスト
  - 写真一覧表示と拡大表示の遷移
  - フィルタリング機能
  - 管理画面での写真追加・編集・削除

### バックエンドテスト
- **ユニットテスト**: 各サービスクラスのメソッドテスト
- **統合テスト**: APIエンドポイントのテスト
- **EXIF抽出テスト**: 様々な画像ファイルでのEXIF情報抽出テスト

### テストデータ
- 異なるカメラ・レンズで撮影された画像サンプル
- EXIF情報が存在しない画像
- 異なるジャンルの画像

## デプロイメント

### 開発環境
- ローカル開発サーバー
- SQLiteデータベース
- ローカルファイルシステムでの画像保存

### 本番環境候補
- **ホスティング**: Vercel, Netlify(フロントエンド)+ Heroku, Railway(バックエンド)
- **データベース**: PostgreSQL(Heroku Postgres, Supabase)
- **画像ストレージ**: AWS S3, Cloudinary(オプション)

### CI/CD
- GitHubリポジトリへのプッシュで自動テスト実行
- mainブランチへのマージで自動デプロイ

## 将来の拡張機能

### Week 4以降の機能
- **写真ダウンロード機能**: 拡大表示時にダウンロードボタンを追加
- **ページネーション**: 写真数が増えた際の一覧表示最適化
- **検索機能**: キーワードによる写真検索
- **お気に入り機能**: 閲覧者が気に入った写真を保存(要会員登録)
- **コメント機能**: 写真へのコメント投稿(要会員登録)
- **SNSシェア**: Twitter, Facebookへの共有ボタン
- **アクセス解析**: Google Analyticsとの統合

## 設計上の決定事項と根拠

### SPA vs MPA
**決定**: SPA(Single Page Application)を採用
**根拠**: 
- 写真の拡大表示やフィルタリングなど、動的なUI操作が多い
- ページ遷移なしでスムーズなユーザー体験を提供
- APIとフロントエンドの分離により、将来的なモバイルアプリ開発も容易

### データベース選択
**決定**: SQLiteを使用(プロトタイプ・本番環境共通)
**根拠**:
- 完全無料で追加コストなし
- 設定不要で即座に開発開始可能
- 初期段階の写真数(5枚程度)には十分な性能
- ファイルベースでバックアップが容易
- 将来的にPostgreSQLやDynamoDBへの移行も可能

### EXIF抽出のタイミング
**決定**: バックエンドでアップロード時にPillowを使用して抽出
**根拠**:
- より確実なEXIF情報の抽出
- セキュリティ面で有利(ファイル検証も同時に実施)
- Pythonエコシステムとの統合が容易

### 認証方式
**決定**: JWT(JSON Web Token)を使用
**根拠**:
- ステートレスな認証により、スケーラビリティが向上
- フロントエンドとバックエンドの分離に適している
- トークンの有効期限管理が容易