AIをフル活用して「自分が本当に欲しかった麻雀練習アプリ」を作った話
この記事はChatGPTを用いて校正しています。
作ったアプリはこちら
apps.apple.comずっと「こんな麻雀の練習アプリがあったらいいのに」と思っていたのですが、とうとう自分で作ってしまいました。 しかも、アイデアからリリースまで約1ヶ月。
AI が本格的に使えるようになった今、アイデアを形にするハードルは本当に下がったんだな、と実感しました。
私は普段ソフトウェアエンジニアをしていますが、スマホアプリの開発経験はほぼゼロ。 さらに、アプリ開発って
- 企画
- デザイン
- 実装
- ストア準備
……と、とにかく幅広い作業が必要です。
正直、これを一人で全部やるのは厳しかったと思います。 今回、AI が相棒として大活躍したおかげで何とか実現できたので、そのプロセスをまとめておきます。
企画づくりは ChatGPT と一緒に
まずは ChatGPT に壁打ちするところからスタートしました。
麻雀はルールが明確なゲームだからか、返ってくる提案の精度がとても高くて驚きました。
最初のざっくりした相談がこちら:
1人でできる麻雀の練習アプリを作りたいです。ランダムな配牌からツモって上がりを目指す感じがいいのですが、どう思いますか?
すると ChatGPT からは、
「めちゃくちゃ良いです!まずは対戦相手なしの練習特化型が良いですね。必要な機能は……」
と、MVP(最小構成)から実装方針、テスト戦略まで、一気にまとめて提案してくれました。
そこからは、ChatGPT と会話しつつ
- 履歴機能が欲しい
- モバイルアプリでやりたい
- 18巡以内にテンパイできなければ終了したい
など、自分の“こうしたい”を足していき、仕様書の原型が完成していきました。
アプリ名も ChatGPT と決めた
アプリ名も一緒に考えました。
「ソロ」を入れたい 一索(イーソー)を使ったロゴにしたい
という条件を伝えたところ、
「麻雀ソロ一索」
という案が返ってきて、響きも見た目もよかったのでそのまま採用。
こういう“ネーミングの壁打ち”も AI は驚くほど便利です。
実装は Codex CLI におまかせ
企画で作った仕様書を丸ごと渡して、実装は Codex CLI にお願いしながら進めました。
基本はシンプルで、
- 仕様書を渡す
- コードを生成してもらう
- 動かしてみる
- バグがあれば直してもらう
というサイクルをひたすら回しました。
特に麻雀のアルゴリズム部分(シャンテン計算など)は テストコードを書きながら Codex に補助してもらう というスタイルが相性抜群でした。
UI デザインは “AI で方向性を探し、Figma でまとめる”スタイル
実装が進んでいく一方、UI は完全に後回しだったので、最初はかなり素っ気ないデザインでした。

「さすがにこれは…」と思い、ここでも ChatGPT に麻雀画面のサンプル画像を作ってもらい、 色味や立体感の出し方を参考にしながら Figma で整え直しました。
サンプル画像

AI が作る牌の絵柄はところどころ怪しいのですが、雰囲気作りのヒントとしては十分役に立ちました。
最終的にできたメイン画面がこちら:

自前でゼロからデザインを考えるより、圧倒的にスムーズでした。
リリース準備も全部 AI に相談しながら
アプリを App Store に出すには、実装だけでなく
- スクリーンショット
- 説明文
- プライバシーポリシー
- ライセンス表示
- 年齢レーティング
- 審査用メモ
などなど、やるべきことが山ほどあります。
ここも ChatGPT と Codex CLI に相談しつつ、一つずつ潰していきました。
例えば「何が必要か教えて」と質問すると、
- 必須の書類
- SDK バージョン
- ストア申請の手順
- ライセンス表示の作り方
などを、フェーズ分けして分かりやすく教えてくれます。
文章作成や説明文の草案も AI が作ってくれるので、非常に助かりました。
おわりに:AI 時代の「一人プロダクト開発」
今回の経験を通じて、
AI の力で「一人でプロダクトを作る」ことが本当に可能になった
と確信しました。
逆に言えば、みんなが作れるようになった分、
- どんなアイデアを形にするのか
- 何に価値があるのか
- どう差別化するのか
といった “考える力” がますます重要になっていくと思います。
今回は、そうした気づきを得られたという意味でも、とても良い体験でした。
Terraform1.5で追加されたimportブロックを試す
importブロックは宣言的に既存のリソースをTerraform管理下にできるTerraformの構文です。今まではterraform import で既存のリソースをTerraform管理下にできましたが、一つ一つのリソースしかインポートできずに面倒でした。また、今まではできなかったHCLのコードを生成することも可能になっています。
developer.hashicorp.com
実践
EC2のインスタンスをAWSマネジメントコンソールから作成し、それをimportブロックでTerraform管理下にします。
まず、importブロックのコードを書きます。toにはインポート先となるresourceブロックのIDを指定します。
idにはインポートする個々のリソースを識別するIDを設定します。これはリソースの種類によって異なります。EC2の場合はインスタンスIDになります。
imports.tf
import { to = aws_instance.example id = "i-00000000000000000" }
この状態でterraform planを実行すると、toにあたるインポート先がないためにエラーになります。そして、terraform plan -generate-config-out=generated.tfでコードを生成することができる旨のメッセージが表示されます。親切です。これに従って、HCLのコードを生成します。
EC2の場合は、コードを生成すると、設定がコンフリクトしている旨のエラーが出力されます。
│ Error: Conflicting configuration arguments │ │ with aws_instance.example, │ on generated.tf line 14: │ (source code not available) │ │ "ipv6_address_count": conflicts with ipv6_addresses ╵ ╷ │ Error: Conflicting configuration arguments │ │ with aws_instance.example, │ on generated.tf line 15: │ (source code not available) │ │ "ipv6_addresses": conflicts with ipv6_address_count
ipv6_address_countとipv6_addressesはどちらか一方あればよい値です。コード生成をした場合はどちらも出力されてしまいます。
どちらかの記述を削除して、terraform planとterraform applyを実行します。そうすると、importすることができます。
コードの生成は完璧ではありませんが、かなりの部分のコードを補完してくれるため、便利です。
感想
terraform importで行っていた既存リソースのインポートをTerraformのコードでできるようになり、操作性がよくなったと思います。また、コードの生成も便利なので、これからはimportブロックを使った書き方を採用していきたいと思います。
おわりに
Udemy講座を公開しています。AWSやTerraformの入門から実践的な内容までを学べるものになっています。ぜひ受講ください。
ローカル上のAWS LambdaのコードをTerraform化する
ローカル上のAWS LambdaのコードをTerraform化する方法について説明します。
ローカルにあるコードをTerraform化するにあたってはコードのzipファイル化が必要など、そのあたりのポイントを説明します。
説明
以下が全体のコードになります。
lambda.tf
resource "aws_lambda_function" "example" { function_name = "lambda-terraform-example" handler = "main.lambda_handler" runtime = "python3.8" filename = data.archive_file.lambda_function_payload.output_path source_code_hash = data.archive_file.lambda_function_payload.output_base64sha256 role = aws_iam_role.lambda_exec.arn } resource "aws_iam_role" "lambda_exec" { name = "lambda_exec_example" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "lambda.amazonaws.com" } } ] }) } resource "aws_iam_role_policy_attachment" "lambda_exec_basic" { policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" role = aws_iam_role.lambda_exec.name } data "archive_file" "lambda_function_payload" { type = "zip" source_dir = "${path.module}/src" output_path = "${path.module}/lambda_function_payload.zip" }
src/main.py
import json def lambda_handler(event, context): return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') }
aws_lambda_functionのリソースにfilenameとsource_code_hashのパラメータを指定しているのがポイントです。こちらにはLambda関数コードが含まれるZIPアーカイブファイルのパスとハッシュを指定します。Lambda関数のソースコードを含むZIPアーカイブは、data archive_fileブロックで作成され、filenameおよびsource_code_hashパラメータに渡されます。
aws_iam_roleリソースは、Lambda関数が使用するIAMロールを作成します。このロールには、AWS Lambdaによる関数の実行に必要なポリシーが含まれます。最後に、aws_iam_role_policy_attachmentリソースを使用して、作成したIAMロールにAWSLambdaBasicExecutionRoleポリシーをアタッチしています。これは、Lambda関数が必要な最小限の権限を持つようにするためのものです。 path.module はTerraformで使用される予約済み変数の一つで、現在のモジュールのルートディレクトリへの絶対パスを表します。
これでローカル上のAWS LambdaのコードをTerraform化することができます。
おわりに
以下のUdemy講座を公開しています。AWSやTerraformの入門から実践的な内容までを学べるものになっています。ぜひ受講ください。
