Reactでwebアプリの開発にチャレンジ(& GitHubActionsでSQLを定期実行)

こんにちは、@Shun_Pです。
Reactの学習を始めて4カ月ぐらい経ちました。途中で全くやらない時期があったりと、学習にはムラがありますが、仕事の合間を見つけてなんとかプログラミングコーチングJISOUのカリキュラムの半分ぐらいまで到達することができました。今日はこの2-週間ぐらい開発していた課題についてです。

## 何をやったのか
名刺交換アプリを開発しました。
学習目的なので、ユーザー認証などはなく、トップページ/名刺登録ページ/名刺ページの3つからなるシンプルなwebアプリです。

・ユーザーは、IDを使って、名刺を検索することができます
![スクリーンショット 2024-09-14 211126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3502843/79c19e22-6222-aad2-65ff-8bb6d1dffef9.png)

・ユーザーは自分の名刺を新規登録することができます
![スクリーンショット 2024-09-14 211150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3502843/c11d28dd-3436-5133-aa2f-86e282ee8b91.png)

・IDを使って検索すると名刺の詳細画面が表示されます
![スクリーンショット 2024-09-14 211349.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3502843/8678adc2-a3ad-b9b6-1e8e-e4aa4c868684.png)

## 以前と比べてどのように成長したのか
複数のページからなるwebアプリを作ったのは今回が初めてだったので、フロントエンドへの知識がさらに深まりました。
慣れないTypeScriptとReactのコンポーネントで、簡単なwebアプリでも作るには時間がかかりましたが、フロントエンドについての知見は深まってきた様に感じます。
あー全部Pythonでとっとと作りたいわーと何度も心の中で思いましたが、学習のために我慢して作りきって、大変だったものの学びもあった課題でした。


## 大変だったところや工夫したところ
前回も大変でしたが、引き続き、Jestのテストをする際にいつもエラーに遭遇し時間をかなり使ってしまいます。テストコードが難しいというよりも、設定が難しく、tsconfigやjest.config　の設定でエラーの直し方を調べるのに苦戦して大変でした。

## 工夫したところ
今回はカリキュラムの課題としてこのwebプログラムを開発しましたが、課題の中には以下のtodoがありました。

```
ユーザーの情報を次の日にすべて削除するバッチ処理をGithubActionsのクーロンジョブを使って実現することにしました
朝6時に前日のusersとuser_skillを削除するようにします

TODO
tsファイルを実行すれば前日作成したusersとuser_skillを削除できるようにする
 npx ts-node --esm ./batch/index.ts 
このコマンドを実行したら削除ができるようにする

毎朝6時にクーロンジョブが実行されるパイプラインを作成する
GithubActionsで新たなファイルを作成すること。その中では上のコマンドを実行するようにする
```
→この方法でDBの操作をするよりも、普段Pythonでデータ取得をしていたり、LookerやPowerBIでデータの可視化をしていることもあり、SQLの方がDB操作は自分は楽なので、SQLをGithub Actionsで定期実行して同様のことをできないかと考えて、以下の方法で実装しました。

まず、SQLスクリプトを用意します。古いユーザーを削除するSQLスクリプトを作ります。

```-- delete_old_users.sql
DELETE FROM user_skill;
DELETE FROM users;
```

次に、このSQLスクリプトを実行するNode.jsスクリプトを作成します。このスクリプトは、PostgreSQLデータベースに接続し、SQLファイルを実行します。
```delete_old_users.js
require('dotenv').config();
const { Client } = require('pg');
const fs = require('fs');
const path = require('path');

async function deleteOldUsers() {
  const client = new Client({
    user: process.env.DB_USER,
    host: process.env.DB_HOST,
    database: process.env.DB_NAME,
    password: process.env.DB_PASSWORD,
    port: process.env.DB_PORT,
  });

  await client.connect();

  const sql = fs.readFileSync(path.join(__dirname, 'delete_old_users.sql'), 'utf8');
  await client.query(sql);

  await client.end();
}

deleteOldUsers().catch(err => {
  console.error('Error executing query', err.stack);
  process.exit(1);
});

```

次に、GitHub Actionsのワークフローファイルを作成します。このファイルは、指定したスケジュールでNode.jsスクリプトを実行します。各種キーはGitHubにsecretとして保存しておきます。

```delete_old_users.yml
name: Delete Old Users

on:
  schedule:
    - cron: '0 6 * * *'  # 毎日午前6時に実行
  workflow_dispatch:  # 手動実行用のトリガーを追加

jobs:
  delete-old-users:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    - name: Set up Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '18'

    - name: Check for required files
      run: |
        if [ ! -f "src/scripts/delete_old_users.mts" ]; then
          echo "Error: src/scripts/delete_old_users.mts is missing"
          exit 1
        fi
        if [ ! -f "src/sql/delete_old_users.sql" ]; then
          echo "Error: src/sql/delete_old_users.sql is missing"
          exit 1
        fi

    - name: Install dependencies
      run: npm ci

    - name: Run delete_old_users script
      run: node --loader ts-node/esm src/scripts/delete_old_users.mts
      env:
        DB_USER: ${{ secrets.DB_USER }}
        DB_HOST: ${{ secrets.DB_HOST }}
        DB_NAME: ${{ secrets.DB_NAME }}
        DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
        DB_PORT: ${{ secrets.DB_PORT }}
```
このようにして、GitHub Actionsを使って定期的にSQLスクリプトを実行することができます。これにより、データベースのメンテナンスや定期的なデータ処理を自動化することができました。
今回はレコードを全部削除するという単純なクエリなので、SQLを使わないで実装した方が簡単かと思いますが、比較的複雑なクエリを実行する場合には、SQLの方が慣れていて楽なので、GitHubで定期実行する方法を知ることができて良かったです。（とはいえ、Cloud Functionsで定期実行する方がメンテや監視しやすい気もしますが...）

## 気づきなど

今回からVScodeでの開発からCursorでの開発にIDEを変えました。もともとCursorはちょっと使ったまま、なんか使いにくいなと思って触っていなかったのですが、改めて使ってみようと思って使ったところ、思った以上に快適で「Ctrl+K」と、チャット欄でのクリックでコードが修正されるUIと、もうCursorなしでは戻れない体になってしまいました。
Pythonの開発ではPycharmの方がまだ使いやすいので、フロントエンドはCursorで開発し、Pythonの開発はPycharmでなど、使い分けながら開発していこうと思っています。
Curosrの良さはいろんな人が記事にしていますが、他のAI含めて自分なりの使い方があるのでどこかで記事にしていきたいと思います。


# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからお願いします👇

https://projisou.jp