はじめに
こんにちは。HelloweenHead's Depotです。
こちらのブログはexeを作って終わりじゃなかった — Tauri製GUIアプリをMicrosoft Storeに出すまでの振り返り -上の続きです。お時間ございましたら、上編の方から読んでいただけると幸いです。
GitHub URL: TypeNap
奇行:イラついた挙句AI Agentを怒鳴りつける
さて、ここまでの開発はすべて個人で進めてきた。
チーム開発ではまた事情が違うのだろうが、少なくとも個人開発では、プロジェクト全体のLOCが増えるほど、一つの機能追加や一つのバグ修正のために参照しなければならないファイルも着実に増えていく。
私の場合、それを強く感じ始めたのは、プロジェクト全体が2500LOCを超えたあたりだった。
この頃から、AI AgentとしてAntigravityやCodexへ頼る比重もかなり増えていった。
別に、コードが書けなくなったわけではない。
何をやるべきかも、ある程度は分かっている。
ただ、それを自分一人でファイルを開いて、追って、書き換えて、また別のファイルへ移って……とポチポチやることを次第に莫迦莫迦しさを感じるようになった。
人間が300LOC程度のファイルを一つ読み解くにも、それなりに時間がかかる。普通の人がそれを10分?あるいは20分?かは分からない。
私なら、場合によっては1時間くらい平気で持っていかれるかもしれない。
でもAIなら、そのファイルを一瞬で読み込める。
だったら読ませる。
読ませたなら、いっそそのまま編集まで任せてしまう。
そんな使い方が増え、いつの間にか私は、テキストエディタのタブをほとんど自分で触らなくなっていた。
そして、当然のように問題が起きた。
ある日、原因の分からないバグが発生した。
私はいつものようにAI Agentへ修正を一任した。しかし、何度試しても一向に直らない。
仕方なく重い腰を上げ、自分で原因を追うことにした。
そこで久しぶりに、しばらくまともに開いていなかったファイルを読んだ。
すると、妙なことに気づいた。
私が以前書いたはずのコードが、随分と違う形になっている。
さらに読み進めると、私の想定と微妙に食い違う仕様になっている箇所が、いくつも見つかった。
ここで、ようやく原因が見えてきた。
私の中では、
私の想定 → プロンプトとして言語化 → AIが実装
という流れで正しく伝わっているつもりだった。
しかし実際には、その途中で細かな認識のズレが発生していた。
AIは、私が言葉にした範囲では正しく動いている。
ただし、私の頭の中にしか存在しない前提や、言語化しなかった細かな仕様までは当然知らない。
その結果、コードには少しずつ「私の想定とは違うが、単体では一応動く処理」が混ざっていった。
1つ1つは些細な違いである。
単体テストをすれば問題なく動くものも多い。
しかし、それが10個、20個と積み重なると話は変わる。
それぞれの小さなズレが糸のように絡み合い、やがて、
「なんでこんな動きするんだ?」
という意味不明のバグとして表面化する。
私はそれを理解した瞬間、顔を真っ赤にした。
そしてAIに物理的に怒鳴りつけた。
それだけでは飽き足らず、画面右下の小さな入力欄へ思いつく限りの罵倒を打ち込み、謝らせた。
……が。
今になって考えれば、悪いのは私である。
AIが書いたコードを、私はあまりにも無邪気に信用しすぎていた。
そして何より、
生成されたコードをレビューする責任まで、AIへ丸投げしていた。
ここが一番の問題だった。
それから、AI Agentの使い方について自分なりのルールを決めた。
目的と手段が明確で、変更範囲も小さいもの――目安として100行程度まで――はAIに任せる。
一方で、それ以上の中規模な変更では、先に自分で関数の形やデータ構造、責務の分担などを決めてからAIへ渡す。
もちろん、実装後のレビューも自分で行う。
要するに、
「何を作るか」までAIに決めさせるのではなく、「決めたものを作らせる」
という形へ変えた。
個人開発では、使える時間も労力も限られている。
その中である程度の規模の製品を作ろうとするなら、AI Agentはかなり強力な道具になる。
私自身、もはや完全に排除して開発する気はない。というか無理だ。
ただし、便利だからといって設計判断やレビューまで手放せば、そのツケはどこかで必ず返ってくる。
地味で、あまり面白くもない結論だが、
運用方針を自分なりに持つことが肝要
結局のところ、今の私が知る中では、これが一番効率の良いやり方だと思っている。
気付けばアプリになっていた
さて、ひと悶着はあったものの、AI Agentを適切に使えば、開発速度そのものはかなり向上させることができる。
そんなこんなで、この頃までに私は以下のような機能を実装していた。
- ファイルのバックアップシステム
- 好きな画像をアプリ背景として設定できるカスタマイズ機能
- フロントエンドUIのさらなるブラッシュアップ
-
i18nextを用いた日本語 / 英語対応 -
batteryクレートを利用した、バッテリー残量低下時の自動保存 - ショートカットキーの拡充
- アプリ初回起動時の簡易チュートリアル
- その他諸々……
そして最終的に、プロジェクト全体の規模は約12,000LOCになっていた。
(さらなる自慢)
ここまで来ると、さすがに最初の「メモ帳」と呼ぶには無理がある。
最低限、小説執筆アプリとしての輪郭は見えてきた。
そこで次に悩んだのが、
このまま機能を追加し続けるのか。
それとも、
一度どこかへ正式に出してみるのか。
という問題だった。
少し迷った末、私は後者を選んだ。
別に、突然完璧主義を捨てたわけではない。
理由はもう少し現実的である。
実際に就職活動を始めてみたところ、
インターンへ応募するも全落ち。
(実話・マジ)
いい加減、自分のポートフォリオを一度きちんと整理し、形のある成果物として残した方が良いのではないか。
そんな、最初の12月とよく似た焦りが再びやってきた。
こうして私は、
「アプリを作る」から「アプリをリリースする」
という、次の段階へ進むことになった。
リリースって何すりゃええの?
さて。
実際にアプリをリリースしようとしてみると、分からないことだらけだった。
PC向けのデスクトップアプリなら、やっぱりAppleのApp StoreやMicrosoft Storeだろうか。
そう思って調べてみると、まずApple側で軽く項垂れることになる。
Apple Developer Programでは、アプリを配信するために年額99米ドルのメンバーシップ費用が必要になる。
詳しくは、私が実際に読んで項垂れた某林檎のサイトを参照してほしい。
学生個人開発者にとって、毎年99ドルはなかなかに重い。
ではMicrosoft Storeはどうなのか。
こちらは少し事情が違った。
現在のMicrosoft Storeでは、新しいオンボーディングフローを使うことで、個人・会社ともに開発者アカウントを無料で作成できる。
個人開発者については2025年に無料化され、会社アカウントについても2026年5月に登録料が撤廃された。
つまり、少なくとも「Storeへ登録する」という入り口だけなら、0円である。
貧乏学生としては実にありがたい。
Microsoft Storeの開発者アカウントには、大きく分けて「個人」と「会社」の2種類がある。
ここで私は一瞬、
「会社アカウントとか取ったらかっこよくね?」
という誇大な野心を抱いた。
しかし調べてみると、当然ながら会社アカウントは、単に名前だけ会社っぽくすればいいわけではない。
会社アカウントでは事業者としての確認が必要になり、D-U-N-S番号や公式な事業登録書類などを使って、実在する事業者であることを確認する仕組みになっている。
D-U-N-S番号とは、企業や組織を識別するための番号である。
もちろん、個人が何らかの事業体を作り、その情報を整えて申請すること自体は不可能ではない。飽くまでも、「割に合わないくらいの苦労をしてもいいのなら。」という条件付きで。
結局、今回は素直に個人開発者アカウントを選ぶことにした。
こちらは比較的すんなり通った。
さて。
アカウントを作った。
これで、いざリリース!!!
……とはならない。
当然ながら、現在のTauriプロジェクトを、Microsoft Storeが受け付けられる配布形式へ変換する必要がある。
Microsoft StoreでWin32アプリを配布する方法として、私が調べた範囲では大きく2つのルートがあった。
一つは、EXE / MSIインストーラをそのまま提出する方法。
もう一つは、MSIXとしてパッケージ化して提出する方法。
最終的に私は後者を選んだ。
だが、ここでもまた二転三転することになる。
MSIX → EXE → MSIX
最初にChatGPTから、
「MSIXで出せばいいよ」
と教えられた。
なるほどMSIXね。
そう思ってTauri公式ドキュメントを改めて読む。
すると、
あれ? Tauriの標準bundleで出てくるの、NSISのEXEとかMSIじゃん。MSIXどこ??
となった。
そこで今度は、
じゃあEXEでMicrosoft Storeへ出せばよくね?
と方針転換する。
ところがEXE / MSIをそのままStoreへ提出する場合、別の壁が現れる。
Microsoft StoreへWin32のEXE / MSIを提出する際には、インストーラをHTTPS経由で直接ダウンロードできるURLとして用意する必要がある。
しかも、そのURLに置いたファイルは提出後に勝手に差し替えてはいけない。
さらに、インストーラはオフラインインストール可能である必要があり、サイレントインストールにも対応している必要がある。
そして、もう一つ大きな壁がある。
コードサイニングである。
署名という壁
EXE / MSI形式で提出する場合、インストーラとその内部の実行ファイルには、信頼された認証局につながるコードサイニング証明書によるデジタル署名が必要になる。
ざっくり言えば、
「このファイルは確かにこの開発者が作ったもので、途中で改ざんもされていませんよ」
という証明をファイルへ付与する仕組みである。
自己署名では駄目で、Microsoft Storeの要件を満たすには、信頼されたCAの証明書が必要になる。
そして、この証明書を自前で用意するとなると、多くの場合お金がかかる。
ここで私は再び思う。
絶対に金は払いたくない!
そこで再びMSIXについて調べた。
するとMSIX形式でMicrosoft Storeへ提出した場合は、事情が違う。
Store側が、認定後にパッケージへ署名してくれる。
つまり、Store配布だけを目的にするなら、自分でCA発行のコードサイニング証明書を購入して用意する必要がない。
さらにMSIXはStore側の配信基盤に載せることもできる。
私にとってはかなり都合が良かった。
そうして最終的には、
Tauriでアプリをビルド
↓
生成されたWindows実行ファイルを用意
↓
Microsoftのwinapp CLIを使ってMSIX化
↓
Microsoft Storeへ提出
という流れに落ち着いた。
winapp CLIはMicrosoftが提供しているWindowsアプリ開発向けCLIで、MSIXパッケージの生成やmanifest、証明書、アセット周りの処理などを扱える。
RustやTauri向けの利用も想定されているため、最終的にはこれを利用してStore提出用のMSIXを作成した。
結果として、
MSIXにしよう
↓
Tauri標準ではMSIXじゃない
↓
じゃあEXEで出そう
↓
署名と配布URLが必要
↓
やっぱりMSIXにしよう
という、美しい一周を経験することになった。
人生、だいたい最初の場所へ戻ってくる。
そしてMicrosoft Storeへ
そして8月30日。
必要な情報をまとめ、TypeNapをMicrosoft Storeへ提出した。
日曜日だった。
審査結果が返ってくるまで、かなり落ち着かなかった。
何度Partner Centerを見ても、
「認定中」
の文字が居座っている。
何かやらかしただろうか。
manifestが間違っていたか。
MSIXの作り方が悪かったか。
スクリーンショットが駄目だったか。
そもそも初回申請で一発通過なんてするものなのか。
そんなことを考えながら待つこと約2日。
9月1日の昼頃、ステータスが変わった。
認定完了。
正直、死ぬほどビビっていた。
却下される可能性も普通に考えていたので、無事通った画面を見たときはかなり嬉しかった。
最初は、
「何かGUIアプリ作りたい。かっこいいから」
という理由で始めたプロジェクトだった。
それが、
PythonとFletを触り、
Reactに苦しみ、
Rustに苦しみ、
AI Agentに怒鳴り、
12,000行くらいコードを書き、
署名とMSIXに振り回され、
最終的にはMicrosoft Storeの審査を通るところまで来た。
なんだか随分遠くまで来てしまった気がする。
アプリはTypeNapという名前で、無料アプリとして9月前半より公開予定である。
時間のある方は、ぜひ触ってみてほしい。
また、今回の制作物についてはGitHubでも公開することにした。
GitHub URL: TypeNap
学んだこと・まとめ
まとめとして、今回学んだことを箇条書きでまとめる。
-
とりあえず作り始めるのは強い
- 最初から完璧な設計や技術選定を目指すより、まず動くものを作った方が得られるものは多かった。
-
プロトタイプと製品は別物
- 「動く」だけなら意外と早いが、一般に使える形へ持っていくにはUI、保存、バックアップ、多言語化、エラー処理など大量の追加作業が必要だった。
-
フレームワーク選定は途中で変えてもいい
- FletからTauriへ移行したように、作りたいものが明確になるにつれて技術選定を見直すのは悪いことではない。
-
GUI開発は小さな部品の積み重ね
- ボタン、タブ、ドロップダウンなど、一つ一つは小さくても、それらの統一感がアプリ全体の印象を大きく左右する。
-
分からないものは小さく分割すると理解しやすい
- React全体を理解しようとするより、「今日はボタンを作る」「今日はタブを作る」と分割した方が結果的に早く理解できた。
-
AI Agentは強力だが、設計者にはなってくれない
- 実装速度は大きく上がる一方で、曖昧な指示を積み重ねると自分の想定とコードが少しずつ乖離していく。
-
AIが書いたコードほどレビューが重要
- 「動いているから正しい」とは限らない。小さな仕様のズレが積み重なると、後になって原因不明のバグとして返ってくる。
-
新しい言語は書くだけでなく思想を理解する必要がある
- Rustでは所有権、借用、
Result、Option、traitなど、既存言語の知識だけでは理解しにくい概念が多かった。
- Rustでは所有権、借用、
-
アプリはビルドできた時点ではまだリリースできない
- 配布形式、署名、MSIX、Store登録、審査など、「作ること」と「世の中に出すこと」の間には想像以上に多くの工程がある。
-
完成を待つより、一度世に出した方がいい
- 機能はいくらでも追加できる。だからこそ、ある程度形になった時点で一度リリースし、「作品」ではなく「製品」にする経験そのものに価値がある。