0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KiroのSpecモードでiOSのマップアプリを作成してみた

Posted at

はじめに

こんにちは、某SI会社2Gのかとうです。
今回は、KiroのSpecモードを使ったモバイルアプリ作成を行います。

前回は、KiroのVibeモードを使って、簡単なリズムゲームを作成しました。
(前回の記事 ↓ )

引き続き、「IT 初心者が、AIエージェントを使ってどこまでのものを作れるのか?
という視点で、検証していきたいと思います。

よろしくお願いします。

今回の検証

Kiro / Specモードとは

今回の検証では、Kiroの「Specモード」を使用しました。

Kiroの最大の特徴である「Specモード」とは、
実装だけでなく、要件定義の工程からAIが行ってくれる開発モードです。

人間の「こんなものが作りたい!」に対して、すぐにコードを出すのではなく、
「こういうものを作りますよ。いいですか?」と確認してから、実装をはじめてくれるイメージですね。
公式ドキュメント ↓

そちらのモードを使って、モバイルアプリを作成しました。

どんなアプリを作るのか?

今回作るのは、ランダムなウォーキングルートを作成してくれるアプリです。

例えば……

「ウォーキングしたいけど、毎日同じ道を歩くのはつまらない!」
「カフェや公園に寄り道したい!」
「でも、自分でルートを考えるのはめんどくさい!」

そんな時に使えるアプリを目指しました。

使用言語はSwiftで、Mapkitという地図表示専用のフレームワークを使います。

SwiftのMapkitを選んだ理由は、私がちょっとだけ触ったことのある分野だからです。
少しは、中身が分かる方がいいかなと思ったので……。

とはいえ、今回も難しい作業は、全てKiroにお任せします😌

検証スタート!

要件定義書の作成

まず、Specモードを選択して、最初のプロンプトを投げました。
作りたいアプリのイメージがはっきりあるので、かなり細かく指示してみます。

↓ 最初のプロンプト

「モバイルアプリを作成してください。
・iOS向けのアプリ。SwiftUIのMapkitを使用する。
・ランダムなウォーキングルートを作って、地図上に表示してほしい。
・ルートだけでなく、ウォーキング中に通ることのできるお店や施設の情報を、「中継スポット」として地図上に表示してほしい。
・中継スポットの数や、ウォーキングルートの総距離を指定できる。
・中継スポットの種類も指定できる。
  例:カフェを含める、駅を含める、など、、、
・ユーザーの現在地を取得し、現在地を起点にしてルートを作成してほしい。
・中継スポットをタップしたとき、その施設の情報を表示してほしい。」

スクリーンショット 2025-11-20 15.56.10.png

最初のプロンプトを投げると、要件定義書を作成してくれました!
英語で出力されたので、日本語に直してもらいました。

# 要件定義書

## イントロダクション

このシステムは、ユーザーの現在地を起点として、指定された条件に基づいてランダムなウォーキングルートを生成し、地図上に表示するiOSアプリケーションです。ルート上には中継スポット(カフェ、駅などの施設)が含まれ、ユーザーはこれらのスポット情報を確認できます。

## 用語集

- **Walking Route App**: ランダムなウォーキングルートを生成・表示するiOSアプリケーション
- **User**: アプリケーションを使用する人
- **Walking Route**: ユーザーの現在地を起点とした歩行経路
- **Waypoint Spot**: ウォーキングルート上に配置される中継スポット(施設や店舗)
- **Route Parameters**: ルート生成の条件(総距離、中継スポット数、スポットの種類)
- **Current Location**: ユーザーの現在の地理的位置
- **Spot Information**: 中継スポットの詳細情報(名称、種類、住所など)
- **Map View**: 地図を表示するインターフェース
- **Location Service**: デバイスの位置情報サービス

## 要件

### 要件 1

**ユーザーストーリー:** ユーザーとして、自分の現在地を起点としたウォーキングルートを自動生成してほしい。そうすることで、新しい散歩コースを発見できる。

#### 受入基準

1. WHEN Userが Walking Route Appを起動したとき, THE Walking Route App SHALL Location Serviceへのアクセス許可を要求する
2. WHEN Location Serviceが許可を付与したとき, THE Walking Route App SHALL 50メートル以内の精度でCurrent Locationを取得する
3. THE Walking Route App SHALL Current LocationをWalking Route生成の起点として使用する
4. WHEN Current Locationが利用できないとき, THE Walking Route App SHALL Userにエラーメッセージを表示する
5. THE Walking Route App SHALL Userがルート上にいる間、10秒ごとにCurrent Locationを更新する

### 要件 2

**ユーザーストーリー:** ユーザーとして、ウォーキングルートの総距離と中継スポットの数を指定したい。そうすることで、自分の体力や時間に合わせたルートを作成できる。

#### 受入基準

1. THE Walking Route App SHALL 1キロメートルから20キロメートルの間で総距離を指定するインターフェースをUserに提供する
2. THE Walking Route App SHALL 1から10の間でWaypoint Spotsの数を指定するインターフェースをUserに提供する
3. WHEN UserがRoute Parametersを送信したとき, THE Walking Route App SHALL 指定されたWaypoint Spotsの数を含めるのに総距離が十分であることを検証する
4. IF 指定されたWaypoint Spotsの数に対して総距離が不十分な場合, THEN THE Walking Route App SHALL Userに警告メッセージを表示する
5. THE Walking Route App SHALL 現在のセッションのためにRoute Parametersを保存する

### 要件 3

**ユーザーストーリー:** ユーザーとして、中継スポットの種類(カフェ、駅など)を指定したい。そうすることで、自分の興味に合った場所を訪れることができる。

#### 受入基準

1. THE Walking Route App SHALL カフェ、レストラン、公園、駅、コンビニエンスストアを含むWaypoint Spot typesの選択可能なオプションを提供する
2. THE Walking Route App SHALL Userが複数のWaypoint Spot typesを同時に選択することを許可する
3. WHEN Userが少なくとも1つのWaypoint Spot typeを選択したとき, THE Walking Route App SHALL ルート生成を有効にする
4. THE Walking Route App SHALL 生成されたWalking Routeに選択されたWaypoint Spot typesのみを含める
5. WHEN Waypoint Spot typeが選択されていないとき, THE Walking Route App SHALL ルート生成ボタンを無効にする

### 要件 4

**ユーザーストーリー:** ユーザーとして、生成されたウォーキングルートと中継スポットを地図上で確認したい。そうすることで、どこを歩くのか視覚的に理解できる。

#### 受入基準

1. THE Walking Route App SHALL MapKitを使用してWalking RouteをMap View上に連続した線として表示する
2. THE Walking Route App SHALL 各Waypoint SpotをMap View上に個別のマーカーとして表示する
3. THE Walking Route App SHALL 異なる色またはアイコンを使用してWaypoint Spotマーカーをタイプ別に区別する
4. THE Walking Route App SHALL Current LocationをMap View上に青い点として表示する
5. WHEN Walking Routeが生成されたとき, THE Walking Route App SHALL ルート全体を表示するためにMap Viewのズームレベルを調整する

### 要件 5

**ユーザーストーリー:** ユーザーとして、中継スポットをタップしてその施設の詳細情報を見たい。そうすることで、訪れる価値があるか判断できる。

#### 受入基準

1. WHEN UserがWaypoint Spotマーカーをタップしたとき, THE Walking Route App SHALL 詳細ビューでSpot Informationを表示する
2. THE Walking Route App SHALL Spot Informationに名称、カテゴリ、住所、Current Locationからの距離を含める
3. THE Walking Route App SHALL 2秒以内にMapKitローカル検索からSpot Informationを取得する
4. WHEN Spot Informationが利用できないとき, THE Walking Route App SHALL 限定的なデータを示すメッセージとともに基本情報を表示する
5. THE Walking Route App SHALL Userが詳細ビューを閉じてMap Viewに戻ることを許可する

### 要件 6

**ユーザーストーリー:** ユーザーとして、指定した条件に基づいてランダムなルートが生成されることを期待する。そうすることで、毎回異なる散歩体験ができる。

#### 受入基準

1. WHEN UserがRoute Parametersでルート生成を要求したとき, THE Walking Route App SHALL 10パーセントの許容範囲内で指定された総距離を満たすWalking Routeを生成する
2. THE Walking Route App SHALL Route Parametersで指定された数のWaypoint Spotsを正確に含める
3. THE Walking Route App SHALL 200メートルから2キロメートルの間隔でWalking Route沿いにWaypoint Spotsを配置する
4. THE Walking Route App SHALL 100メートル以内でCurrent Locationに戻る円形ルートを作成する
5. WHEN Userが同じRoute Parametersで新しいルートを生成したとき, THE Walking Route App SHALL 異なるWalking Routeを生成する

### 要件 7

**ユーザーストーリー:** ユーザーとして、アプリが位置情報サービスを適切に扱い、エラー時には明確なフィードバックを受け取りたい。そうすることで、問題を解決できる。

#### 受入基準

1. WHEN Location Serviceの許可が拒否されたとき, THE Walking Route App SHALL 位置情報アクセスが必要な理由を説明するメッセージを表示する
2. THE Walking Route App SHALL Userが位置情報許可を付与するためにシステム設定を開くボタンを提供する
3. WHEN ネットワーク接続が利用できないとき, THE Walking Route App SHALL 接続の問題を示すエラーメッセージを表示する
4. THE Walking Route App SHALL 以前に読み込まれたエリアのオフライン表示のためにMap Viewタイルをキャッシュする
5. WHEN ルート生成が失敗したとき, THE Walking Route App SHALL 推奨されるアクションを含むエラーメッセージをUserに表示する

ざっと読んでみましたが、大きな問題はなさそうなので、設計書の作成に進んでもらいます。

設計書の作成

以下が出力された設計書です。
長いので、途中まで載せます。

# 設計書

## 概要

このアプリケーションは、SwiftUIとMapKitを使用して構築されるiOS向けのランダムウォーキングルート生成アプリです。ユーザーの現在地を起点として、指定された条件(総距離、中継スポット数、スポットの種類)に基づいてランダムなウォーキングルートを生成し、地図上に表示します。

## アーキテクチャ

### アーキテクチャパターン

MVVM(Model-View-ViewModel)パターンを採用します。これにより、ビジネスロジックとUIを分離し、テスタビリティと保守性を向上させます。


┌─────────────────────────────────────────────────────────┐
│                         View Layer                       │
│  (SwiftUI Views - MapView, RouteConfigView, etc.)      │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│                    ViewModel Layer                       │
│  (RouteViewModel, LocationViewModel, SpotViewModel)     │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│                      Model Layer                         │
│  (Route, WaypointSpot, RouteParameters, Location)      │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│                     Service Layer                        │
│  (LocationService, RouteGenerationService,              │
│   MapKitSearchService)                                  │
└─────────────────────────────────────────────────────────┘


### 主要コンポーネント

1. **View Layer**: SwiftUIビュー
2. **ViewModel Layer**: ビジネスロジックとUI状態管理
3. **Model Layer**: データモデル
4. **Service Layer**: 外部サービスとの連携(位置情報、MapKit検索、ルート生成)

## コンポーネントとインターフェース

### 1. Models

#### Location
```swift
struct Location: Identifiable, Codable {
    let id: UUID
    let coordinate: CLLocationCoordinate2D
    let timestamp: Date
}


#### WaypointSpot
```swift
struct WaypointSpot: Identifiable {
    let id: UUID
    let name: String
    let category: SpotCategory
    let coordinate: CLLocationCoordinate2D
    let address: String?
    let distanceFromStart: Double
}

enum SpotCategory: String, CaseIterable {
    case cafe = "カフェ"
    case restaurant = "レストラン"
    case park = "公園"
    case station = "駅"
    case convenienceStore = "コンビニ"
    
    var mapKitCategory: MKPointOfInterestCategory {
        // MapKitカテゴリへのマッピング
    }
}


#### RouteParameters
```swift
struct RouteParameters {
    var totalDistance: Double // キロメートル単位(1-20)
    var waypointCount: Int // 1-10
    var selectedCategories: Set<SpotCategory>
    
    func isValid() -> Bool {
        // バリデーションロジック
    }
}


#### WalkingRoute
```swift
struct WalkingRoute: Identifiable {
    let id: UUID
    let startLocation: CLLocationCoordinate2D
    let waypoints: [WaypointSpot]
    let pathCoordinates: [CLLocationCoordinate2D]
    let totalDistance: Double
    let createdAt: Date
}
・・・

実際のクラスやプロトコルの定義が羅列されており、
具体的なロジックやアルゴリズムは、コメントアウトで「ここに実装するよ〜」とメモしている感じでした。

正直ちょっと難しい……ですが、頑張って目を通したところ、
ルート生成アルゴリズム」なるものが少し気になりました。

 // ルート生成アルゴリズム
        // 1. 起点から指定距離内でランダムな方向を選択
        // 2. 選択されたカテゴリの施設を検索
        // 3. 適切な間隔で中継スポットを配置
        // 4. 起点に戻る円形ルートを作成

そんなにシンプルでいいのかな?

とは思ったのですが、まあメモ段階だろうし……と一旦スルーして、このまま進めてもらうことにしました。
(後々分かったのですが、本当はここで確認するべきでした。)

タスクリストの作成

次に、タスクリストの作成をお願いしました。
すると、こんなことを言われました。

スクリーンショット 2025-11-20 16.42.59.png

Kiro「現在のタスクリストでは、一部のタスク(ユニットテスト、UIテストなど)をオプション扱いにして、コア機能の実装に集中できるようにしています。どちらを希望されますか?」

何ぞや……と思いましたが、
要するに、「テスト工程を飛ばして実装だけ行うこともできるよ」ということらしい。

早く完成形が見たいので、テストをオプションタスクにしてもらいます。

スクリーンショット 2025-11-20 17.06.49.png

タスクの実行

タスクを実行する方法は、2通りあります。

①タスクリストの「Start task」ボタンを押す
②チャットで「実行してください」とお願いする。

どちらでも実行できます。
が、実行する時は、どちらか一方に統一した方がいいかもしれません。

(というのも、以前、タスク3 まではチャットからタスクを実行し、
タスク4 からボタンでの実行に切り替えてみたところ、タスクを二重で実行してしまった?のか、作成中のファイルが壊れてしまったことがあるので……)

今回は、チャットで実行しました。
「次のタスクに進んで!」とチャット上でお願いすると、サクサク実装を進めてくれます。

あっという間に、タスク15 まで完了しました!

アプリ完成!

完成したアプリを、Xcodeで開いてみます。

いくつかエラーが出ていましたが、
エラーメッセージと、エラーが出た箇所をKiroに投げると、すぐに修正してくれました。

4回ほどのやり取りで全てのエラーがなくなり、アプリをビルドすることができました!

スクリーンショット 2025-11-20 17.33.24.png

メイン画面、それっぽいですね!
ちゃんと、ユーザーの現在地を取得できています。

「ルートを生成」ボタンを押すと…

スクリーンショット 2025-11-20 17.33.52.png

それっぽい!!

総距離をスライドバーで設定できるのは、気がきいてます ✨
なんとなく、プルダウンや数値入力をイメージしていましたが、
個人的にはバーの方が、直感的に操作できて嬉しいかもです。

前回の検証ではUIに苦労しましたが、今回はむしろ、UIがとてもいい感じでした!

さっそくルートを生成してもらいましょう。
距離とスポットを選び、ドキドキしながら「ルート生成」ボタンを押すと……

スクリーンショット 2025-11-20 17.42.34.png

いや、歩けるか!!!

シンプルに、スポットを直線で繋いだルートが出力されてしまいました!
建物も道路も、全て突っ切っていかねばならない……。

やはり、「ルート生成アルゴリズム」がまずかったようです。
あのとき、ちゃんと聞くべきでした……。

あと、スポットのマークを押すと表示される「施設情報」が
「ルートを生成」ボタンと被ってしまう部分も、要修正でした。

スクリーンショット 2025-11-20 17.49.35.png

でも逆に、それ以外は、ほぼ完璧なUIだったかなと思います。

存在しない施設を出しているのではないか……?と少し疑いましたが、
GoogleMapで確認したところ、ちゃんと実在の施設を出してくれていました。

修正

ルート生成ロジックの修正をKiroに依頼すると、すぐに修正してくれました。

スクリーンショット 2025-11-26 9.51.44.png

↓ ビルドすると…

スクリーンショット 2025-11-26 9.54.27.png

ちゃんと直ってます ✨
要件定義で見落としてしまっても、後から修正できるようです。

「施設情報」と「ルートを生成」ボタンの重なりも、
チャットで一言お願いするだけで直してくれました!

スクリーンショット 2025-11-26 10.11.41.png

これで、主要な問題は解決されました。
なかなか、良いアプリが完成したのではないでしょうか。

まとめ

今回は、KiroのSpecモードを使って、モバイルアプリの作成を行いました。

良かった点

1. クオリティ

完成したアプリですが、想像以上のクオリティだったなと思います!

前回のリズムゲームではUIの調整に苦労しましたが、今回はむしろUIが素敵でした。
(ゲームと違って厳密に位置を決める必要がないのも、一つの要因かもしれませんが……)

ほぼイメージ通りのアプリが出力されて満足です。

特に、ウォーキングルートの距離をスライドバーで調整するというのは思いつかなかったので、Kiroのナイス提案でした。

2. 手間 & スピード

また、今回の検証、要件定義〜実装完了まで4時間かかっていません。
それも、ほとんどKiroの実装を待っている時間で、手を動かした時間は2時間あるかどうか…
それくらい、あっという間に完成しました。

作業自体も、「Kiroに指示を出す」以外のことはほとんどしていません。
設計書を読むのと、エラーメッセージのコピペが、一番大変だったくらいです 😌 笑

「楽してサクッと作れた」という印象で、あっという間にアプリが完成しました。

課題点

本検証では、Specモードの利点を活かしきれなかった気がします。

修正箇所が少なかったので、実装が完了した後でも直してもらえましたが、
もしも、もっと複雑なアプリでたくさん問題が発生していたら
修正によって他の箇所に影響が出て、エラーまみれ……という、怖い事態になりそうでした。

次回検証では、要件定義・設計段階でもっと突っ込んでみたいと思います。

(ただ、簡単な修正であれば、実装後でも十分直せました。
要件定義が100%完璧じゃなくても大丈夫なのは、ありがたいところです。)

また、コードを見てみると、一度も使われてないメソッドが定義されている部分がありました。
AIコーディング全般に言える注意点かと思いますが、完成したコードは鵜呑みにせず、チェックが必要だと思いました。

次回の検証

次回は、要件定義・設計の部分で、もっとKiroと対話したいと思います!

今回の記事はここまでです。
お読みいただき、ありがとうございました!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?