<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>個人開発 on ITフリーランスの備忘的なにか</title>
    <link>https://zac-lab.com/tags/%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BA/</link>
    <description>Recent content in 個人開発 on ITフリーランスの備忘的なにか</description>
    <generator>Hugo -- 0.143.0</generator>
    <language>ja</language>
    <lastBuildDate>Thu, 01 May 2025 13:09:53 +0900</lastBuildDate>
    <atom:link href="https://zac-lab.com/tags/%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BA/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>React Native(Expo) でAdMobを設定する</title>
      <link>https://zac-lab.com/posts/20250501/</link>
      <pubDate>Thu, 01 May 2025 13:09:53 +0900</pubDate>
      <guid>https://zac-lab.com/posts/20250501/</guid>
      <description>React NativeとExpoで開発したAndroidアプリにAdMob広告を実装する手順を解説。react-native-google-mobile-adsライブラリの設定から広告コンポーネントの実装まで、個人開発者向けの実践的なガイドです。</description>
      <content:encoded><![CDATA[<h2 id="はじめに">はじめに</h2>
<p>先日、初めてReact Nativeを触ってみたという<a href="/posts/20250418/">ポスト</a>
をしました。</p>
<p>まずはAndroidアプリを公開したいと考えており、組織アカウントとして登録するためにDUNS Numberの取得申請中でございます。
（東京商工リサーチで申請し、7営業日程たちますが、まだ音沙汰なしです。。）</p>
<p>スマホアプリで収益を得たいと考えていますが、まずは一番ハードルが低そうな広告収入を目指していきます。</p>
<p>今回は、Expoで作ったAndroidアプリに、react-native-google-mobile-adsライブラリを使ってAdMobを設置する手順をご紹介します。</p>
<h2 id="1-admobの設定手順">1. AdMobの設定手順</h2>
<h3 id="google-admobのアカウント作成とアプリ登録">Google AdMobのアカウント作成とアプリ登録</h3>
<p>AdMob（<a href="https://admob.google.com/" target="_blank">https://admob.google.com/</a>
）にアクセスし、ユーザー登録します。</p>
<p>その後、アプリを追加します。</p>
<p><img alt="新しいアプリの設定" loading="lazy" src="/posts/20250501/screen1.png"></p>
<p>プラットフォームは「Android」を選択、まだストアにアプリを公開していないので、「いいえ」を選択。</p>
<p><img alt="アプリ名の設定" loading="lazy" src="/posts/20250501/screen2.png"></p>
<p>アプリの名前を入力し、「アプリを追加」をクリック。</p>
<p><img alt="アプリ作成完了" loading="lazy" src="/posts/20250501/screen3.png"></p>
<p>アプリの作成が完了しました。「完了」をクリック。</p>
<p><img alt="アプリ作成後" loading="lazy" src="/posts/20250501/screen4.png"></p>
<h3 id="広告ユニットの作成">広告ユニットの作成</h3>
<p>次は、広告ユニットを作成します。「広告ユニットを追加」をクリック。</p>
<p><img alt="広告ユニットの作成1" loading="lazy" src="/posts/20250501/screen5.png"></p>
<p>広告のフォーマットがいくつかあります。起動時に全面表示するものだったり、全部見たら報酬を得られる系のものだったり。今回は、単純に画面の一部に広告が表示されればよいため、「バナー」を選択。</p>
<p><img alt="広告ユニットの作成2" loading="lazy" src="/posts/20250501/screen6.png"></p>
<p>広告ユニット名には、自分で識別できるように適当に名前を付けて、「広告ユニットの作成」をクリック。</p>
<p><img alt="広告ユニットの作成完了" loading="lazy" src="/posts/20250501/screen7.png"></p>
<p>広告ユニットの作成が完了したら、アプリIDと広告ユニットIDが表示されるので、コピーしておきます。
（こちらの画像の広告ユニットIDは、すでに無効となっています）</p>
<h2 id="2-expoアプリへの実装">2. Expoアプリへの実装</h2>
<h3 id="ライブラリのインストール">ライブラリのインストール</h3>
<p><code>react-native-google-mobile-ads</code>をインストールします。最新バージョン（v15）をインストールしたところ後続手順でビルドエラーが発生したため、v14でインストールするようにしました。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npx expo install react-native-google-mobile-ads@14.11.0
</span></span></code></pre></div><h3 id="appjsonの設定">app.jsonの設定</h3>
<p>react-native-google-mobile-adsをインストールすると、app.jsonに&quot;react-native-google-mobile-ads&quot;の記載が追加されていると思います。</p>
<p>その部分を、以下のように修正します。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>[
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;react-native-google-mobile-ads&#34;</span>,
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;android_app_id&#34;</span>: <span style="color:#e6db74">&#34;ca-app-pub-6970209880901801~7980726474&#34;</span>  <span style="color:#75715e">// アプリIDを設定します
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><h3 id="開発ビルドの作成">開発ビルドの作成</h3>
<p>広告を使用するには、Expo Goのみでは対応できないので、開発ビルドを行う必要があります。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npx eas-cli build --profile development
</span></span></code></pre></div><p>ビルドが完了したら、表示されているQRコードをスマホで読み取ってリンクに飛び、Installボタンを押してダウンロードおよびインストールを行います。</p>
<p>その後、<code>npx expo start</code>で開発サーバーを起動した上で、アプリを起動しておきます。</p>
<h3 id="広告コンポーネントの実装">広告コンポーネントの実装</h3>
<p>実際に、アプリに広告を配置してみます。</p>
<p>アプリの初回起動時に、SDKの初期化を行う必要があるようです。
とりあえずホーム画面においてuseEffectで初回時のみ初期化するようにしてみました。
もしかしたらもっといいやり方があるかもしれません。
参考までに。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> <span style="color:#a6e22e">mobileAds</span>, { <span style="color:#a6e22e">BannerAd</span>, <span style="color:#a6e22e">BannerAdSize</span>, <span style="color:#a6e22e">TestIds</span> } <span style="color:#66d9ef">from</span> <span style="color:#e6db74">&#39;react-native-google-mobile-ads&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// アプリの初回起動時にSDKを初期化
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">useEffect</span>(() <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">mobileAds</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">initialize</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">then</span>(() <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#39;AdMob SDK initialized&#39;</span>);
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>}, []);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// テスト広告の設定
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">adUnitId</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">TestIds</span>.<span style="color:#a6e22e">BANNER</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// バナー広告のコンポーネント
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>&lt;<span style="color:#f92672">BannerAd</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">unitId</span><span style="color:#f92672">=</span>{<span style="color:#a6e22e">adUnitId</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">size</span><span style="color:#f92672">=</span>{<span style="color:#a6e22e">BannerAdSize</span>.<span style="color:#a6e22e">MEDIUM_RECTANGLE</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">requestOptions</span><span style="color:#f92672">=</span>{{
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">requestNonPersonalizedAdsOnly</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>    }}
</span></span><span style="display:flex;"><span>/&gt;
</span></span></code></pre></div><p>開発時は、テスト広告しか表示してはいけないようです。
本番アプリではTestIds.BANNERの部分を、先ほど取得した広告ユニットIDに差し替えてください。</p>
<p>sizeには、幾つかの種類があります。<code>ANCHORED_ADAPTIVE_BANNER</code>だと横幅いっぱいに広がってくれるため、様々なサイズの端末に対応できるということでおすすめです。</p>
<p>私のアプリには高さが足りないと感じたため、もう少し存在感のある、<code>MEDIUM_RECTANGLE</code>を使ってみました。</p>
<h2 id="まとめ">まとめ</h2>
<p>React Native + Expoで構築するスマホアプリに、AdMob広告を貼る手順をご紹介しました。</p>
<p>色々試行錯誤していた時は、Bare workflowにする必要がある（ネイティブコードをいじる必要がある）という情報も転がっていたのでハマってしまいました。</p>
<p>実際にはBare workflowにする必要はなく、Managed workflowのまま開発を進められました。</p>
<p>おそらく以前は対応していなかったものが後々対されるようになったという感じでしょうかね。</p>
<p>Managed workflowのまま、広告貼れるよというお話でした。</p>
]]></content:encoded>
    </item>
    <item>
      <title>スマホアプリ開発に挑戦：React NativeとExpoで始める個人開発</title>
      <link>https://zac-lab.com/posts/20250418/</link>
      <pubDate>Fri, 18 Apr 2025 11:29:18 +0900</pubDate>
      <guid>https://zac-lab.com/posts/20250418/</guid>
      <description>React NativeとExpoを使用したスマホアプリ開発の始め方と、Google Play Consoleでのアプリ公開までの道のりを解説。個人開発者としての挑戦と課題についても紹介します。</description>
      <content:encoded><![CDATA[<h2 id="はじめに">はじめに</h2>
<p>これまでWeb開発を中心に行ってきた私が、新たな挑戦としてスマホアプリ開発に取り組むことにしました。Android StudioやKotlinでの開発経験はあるものの、コード量の多さや学習の難しさから断念した過去があります。しかし、自己啓発と収益化の可能性を考え、まずはAndroidアプリから始めてみることにしました。</p>
<h2 id="技術選定react-native-vs-flutter">技術選定：React Native vs Flutter</h2>
<p>スマホアプリ開発の主要な選択肢として、React NativeとFlutterが挙げられます。X（旧Twitter）で個人開発者の投稿を見ると、Flutterを採用している方が多い印象でした。しかし、Reactの経験がある私にとっては、React Nativeの方が学習コストが低いと判断し、Cursorと共に開発を始めることにしました。</p>
<p>Cursorに最新のReact Nativeドキュメントを読み込ませて、順に一緒にやってもらいました。余談ですが、今後新しい技術がでてきたら、とりあえずドキュメントを読ませてハンズオンを一緒にやってみるのが一番早いのかなと思ってます。</p>
<p>最新のドキュメントを読んではいたものの、古いコマンドを提案してきていたようで途中でうまく起動せず、結局ドキュメントで最新のコマンドを探して打つという・・（笑）まああるあるですね。</p>
<h2 id="react-native--expoでの開発の流れ">React Native + Expoでの開発の流れ</h2>
<p>細かい話は省略しますが、ざっくりと開発の流れを記載します。</p>
<h3 id="1-初期セットアップ">1. 初期セットアップ</h3>
<p>Expoを使用することで、開発のハードルを大幅に下げることができました。VSCodeで開発できる点も大きなメリットです。以前はAndroid Studioが必要でしたが、その重さと待ち時間の長さがネックでした。</p>
<p>プロジェクトの作成は以下のコマンドで簡単に行えます。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npx create-expo-app@latest
</span></span></code></pre></div><p>その後、以下のコマンドで開発サーバーを起動します。（tunnelオプションを付けないとExpo Goアプリがブルースクリーンになりました）</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npx expo start --tunnel
</span></span></code></pre></div><p>驚くほどReactと開発体験が似てますね。すばらしい。</p>
<h3 id="2-expo-goでの開発">2. Expo Goでの開発</h3>
<p>そしてExpo GoアプリをGoogle Play ストアから探してインストールします。
（Expoでアカウント登録もしました）</p>
<p><code>npx expo start</code> でターミナルに表示されたQRコードを、Expo Goアプリから起動したスキャナで読み取ると、デフォルトアプリが動き出します。</p>
<p>コードを修正すると、ホットリロードでスマホ側に即座に修正が反映されます。</p>
<p>以前は、実機で確認するには毎回ビルドして転送コードでファイルを転送して、というのが必要だった記憶があるので、スピーディーにできるようになりましたね。</p>
<p>開発自体も、コンポーネントをどんどん配置していくという流れがReactの開発と非常によく似ています。これほどスムーズにWebアプリ開発からスマホアプリ開発に移行できるとは。食わず嫌いせずにもっと早くやってればよかったです。</p>
<p>実際の仕様決めやコード実装は、生成AIと協働で進めていきます。まずはシンプルなアプリを作って公開するまでの一連の手順を経験してみたいと思います。</p>
<h3 id="3-開発ビルドの作成">3. 開発ビルドの作成</h3>
<p>ある程度開発が進んでくると、Expo Goだけでは対応できなくなってくるので、ちゃんとビルドして実機で動かせるようにする必要があります。
ドキュメントでは、唐突に「Development Build」を作る的な話になるので、最初は混乱しました。
要するに、Expo Goアプリというのは、Expoの開発体験をお試しできるように作られた、プレビュー用のアプリという位置付けのようです。</p>
<p>標準的な機能しか対応しておらず、ちょっとコミいったことをしようと思ったら、改めてビルドして実機にインストールして動作させる必要があります。</p>
<p>開発ビルドをゲットするには、プロジェクトに<code>expo-dev-client</code>ライブラリを追加した上で、EASというビルド用のツールを使います。</p>
<p>下記コマンドにより、Androidアプリの開発用にビルドを作成できます。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>eas build --platform android --profile development
</span></span></code></pre></div><p>ビルドの時間は10～15分程かかりました。
ビルドが終了したら、スマホでExpoの開発者ページに飛んでファイルをダウンロードして実行すると、勝手にインストールが開始されます。
（ビルドは時間が長いので、途中でターミナルを閉じても問題ないようです。しばらくしてからExpoの開発者ページに飛べば、インストールのボタンが表示されています。）</p>
<p>開発ビルドを動作させるには、Expo Goと同様、起動コマンドが必要になります。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npx expo start --tunnel
</span></span></code></pre></div><p>Expo Goの時と同じコマンドですが、プロジェクトに<code>expo-dev-client</code>がインストールされていれば、開発ビルドが使用するサーバーが自動的に立ち上がるようです。</p>
<p>ビルドの待ち時間は長いですが、開発ビルドもExpo Goと同様、基本的にはコードを修正したらホットリロードでリアルタイム反映されるので、開発体験としてそれほど変わりません。
なので、一度Expo Goでの開発を経験したら、次回からは最初からDevelopment Buildを使って開発を進めるでもいいかなと思いました。</p>
<p>ただ、アプリの設定に関わるようなこと（ロゴマークなどの変更なども含めて）を変えた場合には、毎回ビルドしなおさないと反映されないようです。</p>
<h3 id="4-内部配布用ビルドの作成">4. 内部配布用ビルドの作成</h3>
<p>内部配布用のビルドは以下のコマンドで作成できます。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>eas build --platform android --profile preview
</span></span></code></pre></div><p>上記コマンドを実行し、ビルドが完了するまで待つと、インストール用のURLが発行されます。
リンクを知っている人だけが、各自の実機にアプリをインストールできるようになるというわけです。</p>
<h3 id="5-ストア提出用ビルドの作成">5. ストア提出用ビルドの作成</h3>
<p>そして、いよいよストア提出用のビルド。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>eas build --platform android --profile production
</span></span></code></pre></div><p>同様にしばらく待つと、開発者ページにダウンロードのボタンが表示されます。</p>
<h2 id="google-play-consoleでの課題">Google Play Consoleでの課題</h2>
<p>アプリの公開を目指す中で、Google Play Consoleでの登録時に思いがけない課題に直面しました。</p>
<h3 id="個人情報の公開問題">個人情報の公開問題</h3>
<p>ストア提出用のアプリは準備OK！これをGoogle Play Consoleからアップロードして審査を通れば晴れてストアに公開できるはず、と思ったのですが、思いがけない弊害がありました。</p>
<p>まず、開発者として登録するためには最初に払いきりの$25を支払う必要があります。
これは想定していたのですが、アカウントの登録をしていると、氏名や住所が公開されるとあるじゃないですか。</p>
<p>確かに数年前にアカウント確認が厳しくなるという話は聞いていたのですが、住所まで公開されるとは把握しておらず。</p>
<p>ざっと調査したところによると、開発者アカウントは、組織アカウントか個人アカウントのいずれかを選択する必要があるようです。以下、あくまでもご参考まで。</p>
<p><strong>組織アカウントの場合：</strong></p>
<ul>
<li>氏名＋住所が公開される</li>
<li>氏名は屋号でもOK（ただし公式に政府が発行した資料、もしくは公共料金の領収証などを提出する必要がある）</li>
<li>DUNS（ダンズ）ナンバーを取得し、申請する必要がある。（ナンバーは東京商工リサーチのサイトから取得できる）</li>
</ul>
<p><strong>個人アカウントの場合：</strong></p>
<ul>
<li>有料コンテンツ販売しているアカウントであれば、氏名＋住所が公開される</li>
<li>無料のみならば、氏名と国のみ公開される</li>
<li>テスト要件が厳しくなっている。20名で14日間クローズドテストを実施しないと、アプリの申請ができないようになっているらしい。</li>
</ul>
<p>ちなみに、有料コンテンツ販売しているアカウントとは、「有料アプリやアプリ内購入が可能なアプリ」になるそうで、AdMob広告のみの場合は該当しないようです。
ただし、過去に一度でも（テストのためであっても）報酬を受け取るように有効化したアカウントについては有料扱いみたいです。</p>
<p>また、これは全く知らなかったのですが、個人アカウントだとテスト要件が厳しくなっています。
20人にインストールしてもらうとなると、かなり厳しい印象。
みんなでクローズドテストを乗り切ろう的なコミュニティはあるようですが、他人の開発した、どんな悪意あるコードが埋め込まれてるか分からないアプリなんてインストールしたくないよなぁ、と思ってしまいました。（インストールしてもらうためには、自分も協力しないとなわけで。）</p>
<h3 id="今後の対応策">今後の対応策</h3>
<p>個人開発者が締め出されているといわれていますが、皆さんブログなどで対応策を発信してくださっていて、本当にありがたい。今のところ、以下の対応をとろうと考えています。</p>
<ol>
<li>
<p><strong>バーチャルオフィスで公開用の住所を取得する</strong></p>
<ul>
<li>DMMバーチャルオフィス（郵便転送サービス付きで660円/月のミニマムプランがよさそう）を契約する</li>
</ul>
</li>
<li>
<p><strong>新規に電話番号を取得する</strong></p>
<ul>
<li>POVO2.0を契約する</li>
<li>基本的には受電のみなら0円、半年に一度数百円程度の有料トッピングを購入する必要がある</li>
<li>現在使っているスマホでデュアルSIMが対応できたので、eSIMとして追加する</li>
</ul>
</li>
<li>
<p><strong>開業届を修正申告する</strong></p>
<ul>
<li>すでに提出はしていますが、現在は屋号を使っていないので、新しく屋号を登録します</li>
<li>事業所の新設として申請します。（通常、申請する必要はないですが、あえて印鑑付きの書面が欲しいので）</li>
<li>e-Taxでもとれるけど、印鑑あった方が後々楽なので、管轄の税務署に出向こうと思います。（腰が重い…）</li>
</ul>
</li>
<li>
<p><strong>組織アカウントとして登録する</strong></p>
<ul>
<li>上記対策を実施後、組織アカウントとして登録予定</li>
</ul>
</li>
</ol>
<h2 id="さいごに">さいごに</h2>
<p>スマホアプリの開発においてはまだまだヒヨッコの開発者ですが、なんとか安全にストア公開まで持っていけるように頑張ります！
詳細な対策の進捗については、また別の記事で報告させていただきます。</p>
]]></content:encoded>
    </item>
    <item>
      <title>タロットアプリを公開しました。</title>
      <link>https://zac-lab.com/posts/20250331/</link>
      <pubDate>Mon, 31 Mar 2025 13:32:25 +0900</pubDate>
      <guid>https://zac-lab.com/posts/20250331/</guid>
      <description>Next.jsとCloudflare Pagesで開発したタロット占いアプリの制作過程を紹介。CursorエディタとGemini2.0 Flash Liteを活用した開発体験と、生成AIの実装について解説します。</description>
      <content:encoded><![CDATA[<h2 id="タロット占いアプリ">タロット占いアプリ</h2>
<p><img alt="タロット占いアプリのホーム画面" loading="lazy" src="/posts/20250331/screen.png"></p>
<p>🔗 <a href="https://tarotfortune.zac-lab.com/" target="_blank">アプリへのリンク</a>
</p>
<p>かねてより興味があったタロット占いのアプリを作ってみました。
1枚でサクッと占ったり、10枚でじっくり占うこともできます。</p>
<p>このアプリを作った経緯としましては、最近うちの子供がタロット占いにハマっておりまして、カードの意味を覚えたり、カードを組み合わせてどのように解釈するか、といったところの練習になるといいなと思い開発しました！</p>
<p>アドバイスの部分は、生成AIを使って自然な文章で提案してくれるようにしました。</p>
<h2 id="技術的なこと">技術的なこと</h2>
<p>以前公開した<a href="https://typing.zac-lab.com/" target="_blank">タイピング練習用のアプリ</a>
の基本構成と同じ、Next.js＆Cloudflare Pagesを採用しています。
ほどんと同じなので、異なる部分のみ記載したいと思います。</p>
<p>ちなみにこちらは現時点（2025年3月末時点）のものであり、まだまだ改善点がありますので変わる可能性ありです。</p>
<h3 id="nextjsのapiルート">Next.jsのAPIルート</h3>
<p><a href="https://typing.zac-lab.com/" target="_blank">タイピング練習用アプリ</a>
においては、フロントエンドのみの構成でした。
今回のアプリでは、生成AIのエンドポイントをたたく必要があったため、セキュリティのためにAPIルートを使用しました。
Cloudflare Pagesにデプロイすると、自動的にCloudflare Functionsとして動作させることができました。</p>
<p>ただ途中、ビルドがうまく通らなかったので、Next.jsのバージョンを15→14に落としました。</p>
<h3 id="cursoraiコードエディタ">Cursor（AIコードエディタ）</h3>
<p>月$20の課金をして、Cursorを導入してみました。
ものすごい速さで画面を作り上げてくれて、驚愕です。。
結構メンタルやられるレベルで速いですねww</p>
<p>バージョンは0.47.8を利用。
直近アップデートがあり、これまではComposerとChatが分かれていたところのUIが、統合されたようです。
チャットでのやり取りの中で、適宜Agent（自動でコーディングしてくれるモード）とAsk（質問モード）を使い分けられるようになっています。コンテキストが分断されることなく使い分けられるのがとてもいいですね。</p>
<h3 id="生成aigemini20-flash-lite">生成AI（Gemini2.0 Flash Lite）</h3>
<p>初めて自作アプリの中に生成AIを組み込んでみました。
今のところは無料枠で全く問題ないです。</p>
<p>使ってみた感想としては、ドメイン制限やレートリミット、入力文字のサニタイジングなど、結構考えることが多かったです。
普段の業務では、組織内で使うアプリに組み込む程度で、悪意を持ったプロンプトへの対応を想定していないことが多いため、勉強になりました。</p>
<h2 id="まとめ">まとめ</h2>
<ul>
<li><a href="https://tarotfortune.zac-lab.com/" target="_blank">タロット占いアプリ</a>
を公開しました。</li>
<li>Cursorを使った開発の速度は爆上がり！！</li>
<li>アプリに生成AIを積極的に組み込んでいきたいです。</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>個人開発アプリでデータベースを使いたい。</title>
      <link>https://zac-lab.com/posts/20250217/</link>
      <pubDate>Mon, 17 Feb 2025 16:48:16 +0900</pubDate>
      <guid>https://zac-lab.com/posts/20250217/</guid>
      <description>個人開発アプリでのデータベース選定について、個人的に視点で解説。</description>
      <content:encoded><![CDATA[<h2 id="新しく作りたいアプリについて">新しく作りたいアプリについて</h2>
<p>先日、<a href="https://typing.zac-lab.com/" target="_blank">タイピングアプリ</a>
をリリースしました。</p>
<p>こちらはこちらでまだ改善の余地ありですが、新しくアプリ作っていきたいと思います！</p>
<p>うちの子どもたちが、昨年から家庭内で会社を立ち上げまして、親を相手に商売を始めました( ´∀｀ )</p>
<p>お手伝いチケットを紙で手作りして、何枚かつづりで売ってくれます。</p>
<p>例えば、「マッサージ10分券を10枚つづりで〇円」、「夕食作り代行券を5枚つづりで〇円」、のような感じです。</p>
<p>親としてはとても助かってます✨</p>
<p>子どもとしても、前金でお金を受け取れるのでモチベーションが維持できるみたいです。</p>
<p>趣味でほしいものがあったら、あのお手伝いを〇回すれば買える・・のように逆算できるので良いですね。</p>
<p>ただ、チケットを作ったり授受したりするのが徐々に（お互いに）面倒くさくなってきたので、電子化したいという娘からの要望でした。</p>
<p>できれば通知機能とかを備えたスマホアプリ化したいのですが、一旦はMVPを備えたWebアプリとして実装してみたいと思います。</p>
<p>（スマホ用アプリは、テスト的に作ったことはありますが、実際にストアにリリースしたことはありません。おいおいやっていきたいです！）</p>
<h2 id="データベースを選ぶ">データベースを選ぶ</h2>
<p>前回のタイピングアプリではデータベースを使用しませんでした。</p>
<p>今回作るアプリではデータベースが必要になります。</p>
<p>一旦は家庭内で使うだけだけど、よさそうなら一般公開できると嬉しい。</p>
<p>個人開発で無料から始められるデータベースサービスをいくつかピックアップしてみました。</p>
<ul>
<li>
<p>Firestore（FirebaseのDB）</p>
<ul>
<li>以前使ったことがある。・・が、NoSQLのツボをいまいちつかめなかった記憶がある。</li>
</ul>
</li>
<li>
<p>Supabase</p>
<ul>
<li>Firestoreの代替サービスという位置づけらしい。最近はこちらの方が人気がある模様</li>
<li>RDBが使えるので違和感なく使えそう</li>
</ul>
</li>
<li>
<p>Neon</p>
<ul>
<li>PlanetScale（以前無料で使えてた）の代替として使っている記事がいくつかあった</li>
</ul>
</li>
<li>
<p>Cloudflare D1（CloudflareのDB）</p>
<ul>
<li>SQLiteベースのデータベース。</li>
<li>SQLiteとは、単一のファイルにどんどんデータを書き込んでいく方式のDB。簡易利用向け</li>
</ul>
</li>
</ul>
<h2 id="cloudflare-d1を使ってみる">Cloudflare D1を使ってみる</h2>
<p>アプリをCloudFlare Pagesにデプロイしようと思っているので、まずは相性のよさそうなCloudflare D1を使ってみようと思います。</p>
<p>SQLiteは以前軽く学習目的で触ったことがあって、その時はあまり意識してなったのですが、実際にアプリに組み込もうと思うと結構制約が出てきそうです。</p>
<p>大規模な集計ができなかったり、同時並行で読み書きができなかったり、あたりでしょうか。</p>
<p>実際に無料枠で使ってみて、支障があるなら別のサービスに切り替えるようにしてみます。</p>
<h3 id="課金体系と無料枠について">課金体系と無料枠について</h3>
<p>D1の使用料金は、読み書きの行数（レコード数）と、保存されているデータの容量で決まるようです。</p>
<p>また、制限を超えるとクエリが実行できなくなって、課金すれば制限を解除できるとのこと。</p>
<p>途中で勝手に課金が始まる訳ではないのは良いですね。</p>
<p>無料枠は以下の通り。</p>
<ul>
<li>読み取り行数：500万/日</li>
<li>書き込み行数：100,000/日</li>
<li>ストレージ：5GB</li>
</ul>
<p>読み取り行数は、スキャンが走ったレコードの件数がカウントされる。1000件のレコードが入ったテーブルをフルスキャンすると1000とカウントされ、結合などでスキャンが走るとその件数分カウントされる。</p>
<p>適切にインデックスをはると節約できるようですが、インデックス更新は書き込み件数にカウントされる、と。</p>
<p>最初は慣れるまで時間かかるかな。実際にテーブルいくつか作ってみただけで何回かクエリ発行されてました。</p>
<h3 id="実際に作ってみる">実際に作ってみる</h3>
<p>実際にDBとテーブルを作ってみました。</p>
<p>Cloudflareダッシュボード、「ストレージとデータベース」→「D1 SQLデータベース」→「作成」でデータベースを作成。</p>
<p>名前を入れるだけで作れました。</p>
<p>次にDBの中にテーブルを作成します。</p>
<p>列の型（タイプ）では、以下の4つしか選べませんでした！</p>
<ul>
<li>text（文字列）</li>
<li>integer（整数）</li>
<li>real（小数）</li>
<li>blob（ファイル類）</li>
</ul>
<p>日付とか、真偽値とか、もろもろtextに突っ込む形のようです。SQLiteってこんな感じなのね～。</p>
<p>これをPagesとかWorkersとかで使うとかなりシームレスに使えるのかな？</p>
<p>大きな支障がない限りはこのまま進めてみます。</p>
<p>次回へ続く。</p>
]]></content:encoded>
    </item>
    <item>
      <title>タイピングアプリを公開しました。</title>
      <link>https://zac-lab.com/posts/20250209/</link>
      <pubDate>Sun, 09 Feb 2025 09:29:49 +0900</pubDate>
      <guid>https://zac-lab.com/posts/20250209/</guid>
      <description>Next.jsとCloudflare Pagesを使用して開発したタッチタイピング学習アプリの制作過程と技術選定について解説。生成AIを活用した開発体験と、今後の展望についても紹介します。</description>
      <content:encoded><![CDATA[<h2 id="まじめに学ぶタッチタイピング">まじめに学ぶタッチタイピング</h2>
<p>🔗 <a href="https://typing.zac-lab.com" target="_blank">アプリへのリンク</a>
</p>
<p>🔗 <a href="https://typing.zac-lab.com/about" target="_blank">アプリに対する思いはこちらに記載しました。</a>
</p>
<p>このアプリは、子どもたちにタッチタイピングを効率的に習得してほしいという思いで開発しました。</p>
<p>必要最低限の内容で、スピーディーに学ぶことができます。</p>
<p>ここでタッチタイピングを習得したら、寿司打のスコアもアップするかも！？</p>
<h2 id="技術構成">技術構成</h2>
<p>アプリを公開するにあたり、以下の技術を使用しました。</p>
<h3 id="開発環境使用言語">開発環境・使用言語</h3>
<ul>
<li>Visual Studio Code</li>
<li>Next.js</li>
<li>TypeScript</li>
<li>App Router</li>
<li>Tailwind　CSS</li>
</ul>
<p>今回はフロントエンドのみの構成としました。</p>
<h3 id="ソース管理">ソース管理</h3>
<ul>
<li>Github</li>
</ul>
<h3 id="デプロイ">デプロイ</h3>
<ul>
<li>Cloudflare Pages</li>
</ul>
<p>Githubのブランチを指定すると、自動でビルド＆デプロイまでしてくれます。</p>
<p>今回初めて使いましたが、非常に便利です！！</p>
<p>個人レベルでは無料プランで十分です。</p>
<p>ビルド回数が月500回までの制限があるので、そこだけ意識しています。</p>
<p>デプロイ先の選定にあたっては、以下を考慮しました。</p>
<ul>
<li>商用利用できること（広告はったりしたい）
<ul>
<li>無料プランだと商用利用できないところが多い。</li>
</ul>
</li>
<li>従量課金ではなく定額であること
<ul>
<li>いつの間にか金額が増えてた！を気にしたくない。</li>
</ul>
</li>
</ul>
<p>上記の条件を満たしていれば課金しても良かったのですが、無料プランで対応できたのはありがたいです。</p>
<h3 id="ドメイン取得">ドメイン取得</h3>
<ul>
<li>Cloudflare Register</li>
</ul>
<p>今後アプリ増やしていきたい思いですが、アプリごとにドメインをとるか、サブドメインで分けて増やしていくかは悩んだところ。</p>
<p>一旦はサブドメインを増やしていくこととし、評判良いものができたら切り出してアプリ固有のドメインをとる方向でいくことにしました。</p>
<p>長く使っていく想定なので、ドメインを原価提供してくれているCloudflare Registerを利用することとしました。</p>
<h3 id="アクセス分析">アクセス分析</h3>
<ul>
<li>Cloudflare Web Analytics</li>
<li>Hotjar</li>
</ul>
<p>アクセス分析=Google Analytics の頭でいましたが、Cloudflare Web Analyticsというものを知り、そのまま使うこととしました。</p>
<p>こちらはあくまでサーバー側に届いたリクエストを分析するというものなので、Google Analyticsと得られる情報は異なるようです。</p>
<p>とりあえずPV数など簡易な情報が得られればよいので、採用することにしました。</p>
<p>Hotjarは、画面レコーディングやヒートマップ（画面のどこが頻繁にクリックされるか等）などを提供してくれるサービスです。</p>
<h3 id="その他">その他</h3>
<ul>
<li>
<p>今回、認証やDBは使用していません。ユーザー登録なしのシンプル構成としました。</p>
</li>
<li>
<p>アプリ内のメニューをどこまで進んだかを保存するために、ローカルストレージを使用しています。</p>
</li>
<li>
<p>ChatGPTにコード生成を助けてもらってます。課金はせずに、ブラウザの無料版のみ使用。課金するタイミング完全に見失ってる。</p>
</li>
<li>
<p>画面のスケッチとかはしないタイプの人間です。実装しながら画面作ってます。</p>
</li>
<li>
<p>アプリの中で使っている画像については、娘にお絵描きしてもらいました。</p>
</li>
</ul>
<h2 id="所要時間">所要時間</h2>
<p>2024年の年末あたりから着手し始め、お正月にぼちぼち開発していたのですが、公開までには全部合わせて1ヵ月くらいでした。</p>
<p>アプリの開発自体はAIが助けてくれたので比較的スムーズに行きましたが、デプロイ先の選定や、周辺で使うサービスの選定などに少し時間をかけました。</p>
<h2 id="今後について">今後について</h2>
<p>ちゃんと生成AIに課金して、アプリ作ってもらうのを試したいですね。</p>
<p>以下、試してみたいプロダクト。</p>
<h3 id="cursorカーソル">Cursor(カーソル)</h3>
<p>VSCodeからフォーしたエディタで、会話しながらコードを修正してくれる模様。</p>
<p>対象のソースを指定して、これに対して修正してという指示ができるのは便利そう。</p>
<p>操作感がVSCodeと変わらないのはよさそうだけど、エディタかえるのは正直ハードルが高い。</p>
<p>移行はよさそうでも、帰ってくるのがしんどそう。</p>
<h3 id="clineクライン">Cline（クライン）</h3>
<p>VSCodeの拡張機能でカーソルと同じようなことができる？という程度の理解です。</p>
<p>カーソルよりよさそうかなーという印象なので試してみたいです。</p>
<h3 id="boltnewボルト">bolt.new（ボルト）</h3>
<p>言葉でアプリの説明を定義すると、全自動で勝手に作ってくれるというものらしい。</p>
<p>良いという噂は聞くけど、どうだろう？</p>
<p>自動生成されたコードの可読性とかメンテナンス性については気になるところ。</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
