2026.8.13

コーディングエージェントでiPhoneアプリ開発に挑戦③

技術

SCROLL DOWN SCROLL DOWN SCROLL DOWN

こんにちは!代表取締役 兼 AIサービス開発室の鈴木生雄です。

前回の記事では、Shoelogの機能を一通り紹介しました。今回からいよいよ技術の話に入っていきます。まずは全体像として「システム構成」を、そしてiPhoneアプリの内部を3つの層に分けた「アーキテクチャ」を紹介します。

冒頭で申し上げておきますと、私はShoelogの開発においてコードを1行も書いていません。それでも、システムの全体構成とアプリ内部のアーキテクチャだけは、自分で理解して意思決定するように努めました。ここを人任せ(AI任せ)にしてしまうと、開発の途中で方向修正が必要になったときに、何をどう指示すればよいか分からなくなってしまうからです。逆に言えば、この2つさえ押さえておけば、細部の実装はコーディングエージェントに委ねられる、というのが今回の開発を通じた実感です。

全体構成:スタンドアローンにしなかった理由

Shoelogは、利用者が操作するiPhoneアプリを中心として、バックエンドサービスであるSupabaseと、AppleおよびSentryが提供する各種サービスを組み合わせて構成しています。

趣味の記録アプリであれば、データを端末の中だけに保存する「スタンドアローン構成」でも十分に成立します。実際、その方が開発はずっとシンプルです。それでもバックエンドと連携する構成にした理由は、データをクラウド側に保持することによって、機種変更時のデータ継続性と、データ消失防止の効果が得られるからです。

考えてみてください。何年分も積み重ねた着用記録やお手入れ記録が、iPhoneの故障や買い替えで消えてしまったら……。革靴愛好家としては耐えられません(笑)。記録を蓄積して振り返ることが価値のアプリだからこそ、データを失わない仕組みは最初から必須要件だったのです。

図中の各サービスの役割は次のとおりです。

  • Supabase:認証、データベース、写真の保存、サーバー側処理を担うバックエンドサービス。詳しくは次回に紹介します
  • Apple:Sign in with Appleによる認証と、App Storeの仕組みを利用したアプリ内課金
  • Sentry:アプリの障害を検知し、原因を調査するためのオブザーバビリティ基盤

AppleとSentryについても、それぞれ回を改めて詳しく紹介する予定です。

フロントエンド:SwiftUIという選択

続いて、利用者が操作するiPhoneアプリの中身の話です。Shoelogの画面はすべてSwiftUIで構築しています。

SwiftUIは、画面に表示する内容をプログラミング言語Swiftのコードによって宣言的に記述するためのUIフレームワークです。Web開発をご存じの方なら、ReactやVueのようなリアクティブ・宣言的UIのiOSネイティブ版と捉えていただいて差し支えありません。

SwiftUIを使うことによって、画面部品の状態を個別に変更するのではなく、アプリが保持するデータの状態に応じて、表示内容を自動的に更新できます。

これがShoelogとどう相性がよいかと言いますと、Shoelogは「同一のデータを複数の画面に反映する」場面が多いアプリなのです。たとえば、利用者が着用記録を1件追加すると、カレンダー画面にも、靴ごとの着用回数にも、統計画面にも、その変更が反映される必要があります。SwiftUIであれば、データを更新すれば関係する画面が自動的に追従してくれるので、「この画面の更新を忘れていた」というたぐいの不具合が起きにくいわけです。

アーキテクチャ:3つの層に分ける

Shoelogでは、アプリ内部を主にPresentation層、Domain層、Infrastructure層の3つの領域に分離しています。

なぜ分けるのかと言いますと、すべてを一つの画面クラスに記述すると、プログラムが複雑になり、機能の追加や修正が難しくなるからです。それぞれの層の役割は次のとおりです。

Presentation層

利用者に画面を表示し、タップや文字入力などの操作を受け付ける役割を持つ層です。SwiftUIのViewと、画面の状態や処理の進行を管理するViewModelがこの層に該当します。Viewは画面表示を担当し、ViewModelは表示データ、入力内容、エラーメッセージなどの状態を管理します。

Domain層

Shoelog固有の業務ルールを扱う層です。革靴、着用記録、お手入れ記録などのデータモデルに加え、「着用記録を登録する」「靴ごとの統計を集計する」「お手入れの必要性を判定する」といった処理をUseCaseとして定義しています。これにより、画面の表示方法やバックエンドとの通信方法から、アプリ本来の処理を分離しています。

Infrastructure層

Supabase、アプリ内課金を実現するフレームワークであるStoreKit2、共有シートなど、外部の仕組みとの接続を担当する層です。たとえば、革靴の情報をSupabaseのデータベースに保存する処理や、写真をSupabase Storageにアップロードする処理は、この層に実装しています。

なぜコードを書かないのに層を分けるのか

「コードを書かないなら、アーキテクチャなんてどうでもいいのでは?」と思われるかもしれません。しかし実際には逆で、コーディングエージェントに開発を任せるからこそ、層の分離が効いてきます。

というのも、層が分かれていると、エージェントへの指示が具体的になるのです。「お手入れの判定ロジックを変えたい」ならDomain層、「写真の保存先を変えたい」ならInfrastructure層、というように、変更の影響範囲を人間側が把握したうえで指示を出せます。また、エージェントが生成したコードをレビューする際にも、「この処理がこの層にあるのはおかしい」という観点でチェックできるので、コードの詳細を追わなくても構造の乱れに気づけます。

アーキテクチャは、人間とエージェントの共通言語である。今回の開発を通じて、私はそう感じています。

次回予告

次回は、今回の構成図に登場したバックエンドサービス「Supabase」を深掘りします。認証・データベース・ストレージ・サーバーレス関数を一手に引き受けてくれるBaaSの実力と、データベースの行単位でアクセスを制御するRow Level Securityの話をする予定です。お楽しみに!