【個人開発】ティアリストを作成するアプリを作ってみた話


## はじめに

最近、YouTubeで動画を見ていると、ゲームやカードなどを『ティア』というランク形式で分類する動画をよく見かけます。この形式は情報を簡潔に伝えられるため、とても便利だと感じました。そこで、自分でも簡単にティアリストを作成できるアプリを作ってみることにしました。

### 開発したアプリ

本題に入る前に、まずは開発したアプリをご紹介します。このアプリは現在、App Storeで公開中です。気に入っていただけたら、レビューしていただけると幸いです。

[App Storeのリンク](https://apps.apple.com/jp/app/%E3%83%86%E3%82%A3%E3%82%A2%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC/id6667102590)

[<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/d392f010-1043-f48b-b2b4-e19e6ec6370e.png">](https://apps.apple.com/jp/app/%E3%83%86%E3%82%A3%E3%82%A2%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC/id6667102590)

![AppStoreスクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/a4142c5d-4d1b-1ab7-0893-4e0d5e3aaff7.png)

## 要件定義

### 機能要件

#### 必須機能

ティアリストを作成するアプリに必要な機能は、以下の通りです。

- **ティアリスト作成**
  ティアリストを新規に作成する機能
- **ティアリスト修正**
  作成済みのティアリストを修正する機能
- **ティアリスト管理**
  作成したティアリストを一覧で確認・管理する機能

### システム要件

#### フロントエンド要件

フロントエンドの要件として、「**スムーズな操作性**」を重視しました。

「**スムーズな操作性**」を実現するため、以下の点を考慮しました。

- ティアアイテムを **[簡単に追加](#ティアアイテムの文字での設定)** できる

- ティアアイテムの **[スムーズな移動](#ティアアイテムの移動)** を行える

#### バックエンド要件

基本的に個人開発では、バックエンドは主に**管理のしやすさ**を重視してサービスを選定しています。Firebaseなどの **BaaS** を利用することで、サーバーの運用や保守の手間を省くことができます。また、プライバシーポリシーや利用規約のページは Notionの **Web 公開機能** を活用することで、無料かつ簡単に公開できます。

## 基本設計／機能設計

### 開発環境

iPhoneアプリの開発には **Xcode** を使用し、ドキュメントの一元管理には **Notion** を利用しました。画面レイアウトの作成にはAIデザインツールの **Uizard** を活用しています。

以前書いた個人開発の記事でも紹介しましたが、Uizardは非常に便利なツールなので、興味があればぜひ試してみてください。

**前回の記事はこちら：**

https://qiita.com/sakes9/items/6f98dbed5b206e39e99d

#### iPhoneアプリ開発環境

| 役割 | ツール／サービス |
| --- | --- |
| 統合開発環境 | Xcode |

#### 開発支援（Dev）

| 役割 | ツール／サービス |
| --- | --- |
| タスク管理 | Notion |
| バージョン管理 | GitHub |
| ドキュメント管理 | Notion |
| 製図 | draw.io |
| 画面レイアウト | Uizard |

### 機能一覧

#### ティアリストの作成

アプリのメイン機能であるティアリスト作成では、「タイトル」「詳細」「サムネイル」を設定できます。
これらの情報は一覧画面に表示され、リストの概要や説明を視覚的に確認できます。

<img width="200" alt="ティアリストの作成_01" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/e6ac5951-3a20-59cc-a578-d3ad40c19649.gif">

ティアアイテムには、「アイテム名」と「アイテム画像（任意）」を設定できます。アイテム画像は必須ではないため、画像が用意できていなくてもアイテム名だけで追加でき、後から画像を設定することも可能です。

<img width="200" alt="ティアリストの作成_02" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/8634e162-80fe-e671-9ce4-35ea6902a705.gif">

ティアランクの追加・削除は画面下部のボタンで行います。

<img width="200" alt="ティアリストの作成_03" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/5f9c346d-3c68-2a49-f81d-5028daf0cea7.gif">

#### ティアリストの管理

作成したティアリストを一覧で確認する画面です。この画面からティアリストの削除や並び替えも行えます。

<img width="200" alt="ティアリストの管理" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/dff8ad36-72e8-9bf3-a3ef-4b2be9bc0342.gif">

#### ティアリストのダウンロード

作成したティアリストを画像として保存する機能です。画像として保存することで、様々な用途に活用できます。

<img width="200" alt="ティアリストの画像保存" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/204b0b97-2e2e-a9c7-06e7-f5509d7ae03d.gif">

## システム方式

### システム構成図

システム全体の構成図は以下の通りです。

![iPhoneアプリ構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/c42f75b0-63bc-1257-88b6-0ccde982d766.png)

### フロントエンド

iPhoneアプリの開発には **SwiftUI** を使用しています。SwiftUIは、UIの構築が簡単で、コードの記述量が少なくて済むため、開発効率が向上します。また、SwiftUIは **Combine** というフレームワークと組み合わせることで、状態管理が容易になります。

| カテゴリ | ツール／ライブラリ／フレームワーク |
| --- | --- |
| 言語 | Swift |
| フレームワーク | SwiftUI |
| 状態管理 | Combine |
| ルーティング | NavigationStack |
| コードフォーマッター | SwiftFormat |
| 静的解析ツール | SwiftLint |
| リソース管理 | SwiftGen |
| 単体テスト | XCTest |

### バックエンド

バックエンドには**Firebase**を採用しました。今回は認証機能やリモートデータベースは使用していませんが、将来的に利用する可能性があるため、拡張性を考慮してFirebaseを選びました。

データベースには **SwiftData** を使用しました。SwiftDataはCoreDataの後継フレームワークで、SQLを書くことなくデータを簡単に永続化できます。SwiftDataの仕様として内部ではSQLiteが使われています。

さらに、SwiftDataはCloudKitを利用してiCloudにデータを保存することもできるため、ローカルだけでなくクラウドでのデータ管理にも適しています。

#### データベース

| カテゴリ | ツール／ライブラリ／フレームワーク |
| --- | --- |
| データベース | SwiftData |
| クラウドストレージ | CloudKit |

#### アプリケーション開発プラットフォーム

| カテゴリ | サービス | 備考 |
| --- | --- | --- |
| 設定管理 | Firebase Remote Config | 強制アップデート、メンテナンスモード に使用 |

#### Webサービス

お問い合わせフォームや利用規約、プライバシーポリシーのページは、レンタルサーバーを借りたり、S3などの静的ファイルホスティングを使用することも考えましたが、管理の手間を避けるために **Notion** を使用しました。Notionは無料でWeb公開ができるので、コストを抑えることができます。

| カテゴリ | サービス | 備考 |
| --- | --- | --- |
| お問い合わせフォーム | Noway Form | Notionと連携したフォーム作成サービス |
| 利用規約 | Notion | NotionのWeb公開 |
| プライバシーポリシー | Notion | NotionのWeb公開 |

#### アプリ配信サービス

| カテゴリ | サービス |
| --- | --- |
| 商用 | App Store |
| 検証| TestFlight |

#### アプリ内課金

| カテゴリ | サービス |
| --- | --- |
| アプリ内課金 | StoreKit |

## 画面設計

### 画面レイアウト&画面遷移図

前回の個人開発の記事でも紹介しましたが、画面レイアウトの作成にはAIデザインツールの**Uizard**を活用しています。Uizardは画面デザインを自動生成してくれるため、デザインのスピードが大幅に向上します。

[<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/e94ee2cc-10df-b57f-fae4-3af6af813733.jpeg">](https://uizard.io/)

## データベース設計

### ER図

Draw.ioは製図に非常に適しているツールですが、Notionで管理する場合はアップロードの手間がかかってしまうため、ER図などのシンプルな図は **Mermaid** で作成しました。

- **TierEntity**
  ティアリストを管理するテーブル
- **TierItemEntity**
  ティアリスト内のアイテムを管理するテーブル

```mermaid
erDiagram
    TierEntity {
      UUID id PK
      Data thumbnail "Optional"
      String title
      String detail "Optional"
      Int order
      Date createdAt
      Date updatedAt "Optional"
    }

    TierItemEntity {
      UUID id PK
      UUID tierId FK
      String tierRankId
      String name
      Data image "Optional"
      Int order
      Date createdAt
      Date updatedAt "Optional"
   }

    TierEntity ||--|{ TierItemEntity : "「ティア」は1つ以上の「ティアアイテム」を持つ"
```

## 製造

### AIツールの活用

最近も相変わらずAIツールに頼りがちで、今回も **ChatGPT** と **Copilot for Xcode** を使って多くのコードを生成しました。AIに頼りすぎてロジカルな思考力が低下しているのではと心配になることもありますが、AIツールの活用で開発効率が向上し、設計や品質向上により多くの時間を割けるため、今後も積極的に利用していきたいと考えています。ただし、AIツールで生成されたコードはそのまま使用せず、必ず確認して理解することが重要だと日々感じています。

### 設計手法

基本的な設計にはドメイン駆動設計（DDD）を採用しています。時間があれば、DDDの活用方法についても記事にまとめたいと考えています。

### アーキテクチャ

アーキテクチャには**MVVM**を採用しています。UIKitではRxSwiftを使うことが多いですが、SwiftUIでは@Stateや@Bindingなどの状態管理と**Combine**を用いてMVVMを実現しています。

以前の記事で、Combineの後継である**Observation**を使用したいと書いていましたが、そのことをすっかり忘れていました。リファクタリングの際にはObservationを試してみたいと考えています。
[Observation | Apple Developer Documentation](https://developer.apple.com/documentation/observation)

### UI/UXの設計

#### ティアアイテムの文字での設定

ティアリストを作成する際に、**画像の用意** が一番のネックになると考えました。画像を用意するのは手間がかかるため、画像がなくてもティアリストを作成できるように、ティアアイテムの **文字での設定** を採用しました。

<img width="200" alt="ティアアイテムの文字での設定" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/e6803505-4b2b-f506-9863-e5bf15786530.gif">

<img width="200" alt="ティアリスト内のアイテムの文字表示" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/200a1aa4-f99e-fb24-38d7-4d8c45fceb8c.gif">

#### ティアアイテムの移動

当初は **ドラッグ＆ドロップ** での移動を検討していましたが、ティアアイテムが増えると操作がしづらくなることや、ドラッグ操作に長押しアクションが必要になることから操作性が悪くなると考えました。そこで、 **タップ式** での移動を採用しました。タップ式での移動は直感的で、スムーズに操作できるため、ユーザーにとって使いやすいと考えました。

<img width="200" alt="スムーズな操作性" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/cbbb2fa3-2363-fe1c-6ded-13062e280577.gif">

## 開発工数

Gitのコミットログから算出した開発工数は以下の通りです。

![Gitコミットログ_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/ca203818-2e5e-61ad-46e2-23e63b64ba83.png)

![Gitコミットログ_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087076/3f1a52a6-3c90-9e4a-bb41-d001b7749587.png)

| 日付 | 内容 |
| --- | --- |
| 2024年8月17日 | 初回コミット |
| 2024年8月27日 | App Storeに公開申請 |
| 2024年8月29日 | App Storeに公開 |

この結果、開発期間は10日間でした。開発時間は50時間ほどだと思います。
前に開発したアプリのロジックを流用したため、その分開発期間が短縮できたと思います。

## 今後

基本的な機能は実装できたと思うので、今後は不具合の修正やユーザーからのフィードバックがあれば、機能の追加や改善を進めていきたいと考えています。

## おわりに

今回は **ティアリスト作成アプリ** の開発についてのお話でした。自分が使いたいアプリを開発するのはとても楽しいものがあります。個人開発では、自分の好みや使い勝手を重視してアプリを作れるので、息抜きにでも日常生活で使いたいアプリを作ってみるのもありかと思います。

最後までお読みいただき、ありがとうございました。アプリは [App Store](https://apps.apple.com/jp/app/%E3%83%86%E3%82%A3%E3%82%A2%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC/id6667102590) で公開中ですので、興味がありましたらぜひダウンロードしていただけると幸いです。