🦔

LINE API × Spring Bootで“今日はご飯作りません”を通知するアプリをAIと開発してみた

に公開

こんにちは

突然ですが、皆さんには「あ〜、今日どうしてもご飯作りたくないな…」って日、ありませんか?私はあります。頻繁に。

そんな無気力な私の気持ちを、ワンボタンで夫のLINEにだけそっと(でも確実に)伝えたい。そんな欲望から、全ては始まりました。

今回は、この超個人的な野望を叶えるWebアプリケーションを、AIペアプログラミングツールと一緒に開発した激闘の記録をお届けします。

フェーズ1:構想と爆誕(所要時間:約30分)

最初のアイデアは至ってシンプル。

  1. ローカルで動くWebページにアクセスする
  2. 「通知」ボタンをポチッと押す
  3. 夫のLINEに「今日は料理をいたしません!」と通知が飛ぶ

これだけ。なんて簡単なんでしょう。
開発環境はJavaのSpring Boot。まずはpom.xmlにLINE Messaging APIのSDKを追加します。

<dependency>
    <groupId>com.linecorp.bot</groupId>
    <artifactId>line-bot-spring-boot-webmvc</artifactId>
    <version>9.8.0</version>
</dependency>

次に、API呼び出しのためのLineServiceと、Webからのリクエストを受け付けるNotificationControllerをサクッと作成。フロントエンドは、とりあえずボタンが一つあるだけのシンプルなindex.htmlを用意しました。

フェーズ2:立ちはだかる壁とデバッグの嵐

順調に見えた開発ですが、LINE APIを使う上で避けては通れない壁にぶつかります。そう、通知先(夫)のユーザーIDがわからない問題です。

ここからが、なかなかの長丁場でした。

  1. WebhookでのID取得作戦: ngrokでローカル環境を一時的に外部公開し、LINEからのWebhookイベントを受け取るための /callback エンドポイントを実装。夫にテストメッセージを送ってもらい、コンソールに表示されたユーザーIDを無事ゲット!
  2. 謎のコンパイルエラー地獄: ユーザーIDをセットして、いざ本番の通知機能を実装!…と思いきや、ライブラリのバージョン互換性が原因でコンパイルエラーが多発。AIが光の速さでimport文を修正したり、メソッドの呼び出し方を調整したりしてくれました。
  3. Ambiguous Mappingの罠: 依存関係を整理する中で、line-bot-spring-boot-handlerという便利なライブラリを追加したところ、今度は/callbackエンドポイントが重複しているというエラーが。自動でエンドポイントを作ってくれる機能が、自前の実装とコンフリクトしてしまったようです。結局このライブラリは削除することに。
  4. 恐怖の500エラー: Webhookがなぜかサーバー内部エラーに。原因は、リクエストボディの受け取り方。SpringがよしなにやってくれるだろうとInputStreamで待ち受けていたのが間違いでした。正しくはbyte[]で受け取る必要があったのです。

このデバッグ作業、一人でやっていたら心が折れていたかもしれません。AIと「ああでもない、こうでもない」と対話しながら解決していく過程は、まさにペアプログラミングの醍醐味でした。

フェーズ3:機能は進化するよ、どこまでも

当初の目的は達成しましたが、人間の欲望は尽きません。

「通知のバリエーションが欲しいな…」

この一言で、機能は一気に拡張されます。

①ランダム通知機能

まずLineServiceにメッセージの候補をリストで持たせ、送信時にランダムで選ぶように変更。

// LineService.java
private final List<String> messages = List.of(
        "今日は料理をいたしません!",
        "外で美味しいもの食べない?",
        "疲れたからご飯作れませーん!",
        "Uberしよ!",
        "あなたの手料理が食べたいな(はぁと)"
);

public void sendRandomMessage() {
    String message = messages.get(new Random().nextInt(messages.size()));
    // (送信処理)
}

これでボタンを押すたびに違うメッセージが届く、ガチャ要素が加わりました。

②選択式通知機能

さらに、「ランダムじゃなくて、気分でメッセージを選びたい!」という要望に応え、フロントに選択ボタンを複数配置する方式に。

  • 「外食な気分」
  • 「Uberがいい」
  • 「手料理作って欲しい」
  • 「買ってきて欲しい」

ボタンごとにtypeをパラメータとして渡し、LineServiceではMapを使ってtypeに応じたメッセージを送信するようにしました。

// LineService.java
private final Map<String, String> messages = Map.of(
        "eat_out", "外で美味しいもの食べない?",
        "uber", "Uberしよ!",
        "cook_for_me", "あなたの手料理が食べたいな(はぁと)",
        "buy_and_bring", "何か美味しいもの買ってきて!"
);

public void sendMessageByType(String type) {
    String message = messages.getOrDefault(type, "今日も一日お疲れ様!");
    // (送信処理)
}

これで、より詳細な「今日の私」を伝えられるようになりました。

フェーズ4:UIデザインの旅 〜平成からインターネット黎明期、そして再び平成へ〜

機能が完成したら、次は見た目です。ここからの展開が、我ながら一番面白かった。

① 第一次平成レトロ化

「なんかこう、気分が上がる感じにしたい。平成中期みたいなキラキラしたやつ!」

この無茶振りをAIに投げた結果、ドット文字フォントや動くヘッダーを備えた、まさにドンピシャなUIが爆誕しました。しかし、人間の欲望は尽きません。

② なぜか阿部寛リスペクトへ

平成レトロに満足したのも束の間、「やっぱり、阿部寛のホームページは外せない」という謎の使命感に駆られます。AIは寸分の狂いもなく、テーブルレイアウトと最小限のCSSで「あの」雰囲気を完全再現。さらに「背景に『SAORI-MUKIRYOKU』って透かし文字を斜めに入れたい」という画竜点睛なリクエストにも応え、唯一無二のページが完成しました。

③ 最終形態:帰ってきた平成レトロ(全部のせ)

ブログ用に「やっぱり平成風のスクショが欲しい!」と思い立った私。
「どうせなら、もっとすごいやつを!」という天啓のもと、平成ホームページの三種の神器をすべて詰め込むことを決意しました。

  1. 左右に動くヘッダー: これぞ<marquee>タグの真骨頂!ヘッダーが画面の端で跳ね返ります。
  2. アクセスカウンター: あなたが何人目の訪問者かをお知らせ。
  3. キリ番ゲット機能: 100番ごと、そして伝説の777番を踏んだ人には祝福のメッセージが!
<!-- index.html の一部 -->
<header>
    <marquee behavior="alternate" scrollamount="8"><h1>.:*☆今日の気分☆*:.</h1></marquee>
</header>

<div class="container">
    <!-- ... コンテンツ ... -->
    <footer>
        <p>アクセスカウンター: <span id="access-counter">0</span></p>
        <p>(⊃´。・ω・。`)⊃━☆゚.*・。</p>
    </footer>
</div>

<script>
    // アクセスカウンターとキリ番機能
    window.addEventListener('load', function() {
        let count = localStorage.getItem('accessCounter');
        count = count ? parseInt(count) + 1 : 1;
        localStorage.setItem('accessCounter', count);

        document.getElementById('access-counter').textContent = count;

        if (count === 777 || count % 100 === 0) {
            alert(`☆゚・*:.。.☆† キリ番GET †☆.。.:*・゚☆\\n\\nあなたは【${count}】人目の訪問者です!`);
        }
    });
</script>

こうして、実用性とネタ要素、そして私たちの青春時代のインターネットが完璧に融合した、世界に一つだけのアプリケーションが完成したのです。

まとめ

たった一つの「めんどくさい」から始まったこのプロジェクト。振り返ってみれば、LINE APIとの連携、壮絶なデバッグ、そしてWebデザインの歴史を巡る旅と、非常に中身の濃い開発体験となりました。

AIとのペアプログラミングは、アイデアを即座に形にし、エラーの解決を高速化し、そして何より「ちょっとアホなこと」に全力で付き合ってくれる最高の相棒でした。

この「夫への連絡網」アプリが、我が家の平和に貢献してくれることを祈って。
皆さんも、日常の小さな「めんどくさい」を、アプリ開発のネタにしてみてはいかがでしょうか?

あとがき

最後までお読みいただきありがとうございました。

改めまして、HacobuでQAエンジニアをしております、さおりんごと申します。実はこの「あとがき」以外の章のブログ内容は、すべてCursor(gemini-2.5)が書いています。

「こんな機能作りたいな~」「あれもほしいかも」と話しながら気づいたら完成。「ここまでチャットでやってきたことをブログにしたい。Markdown記法で書いて」と言ったら、このブログが出力されました。暇つぶしで始めた思いつきでしたが、とても面白い経験になりました。AIも述べている通り、デバッグの嵐は一人では心が折れていたことでしょう。また気が向いたら、Cursorとともに新たな「無駄アプリ」を生み出そうと思います。

ちなみに検証中、夫に届いたLINE履歴が大変なことになっていました(申し訳ない)。

Hacobuテックブログ

Discussion