見出し画像

ChatGPTに指導を受けながら初心者がwebアプリをAzure上に構築しようとした

 webアプリってやつ、作ってみたかったんですよね。
前職の情シス上司から最初に出された課外課題が、「PHPでwebアプリを作る」でした。 ローカル環境でXAMPP、Laravelでなんとなく献立作成アプリを作ってみたものの、実際にwebに公開するところまでは辿り着けず、よくわからないまま挫折していました。

 ところが、最近ではよくある話になっていることだと思いますが、GPT4のChatGPTくん登場によってアプリ作成を指導してもらえるようになりました。
例えばこんなことが手軽に体験(いろいろ実用レベルまで練られていない)できました。

  • L3スイッチ管理画面のトラフィックログを定期的にクローリングするツールをPythonで作成

  • Python + SQLiteで備品管理アプリを作成

  • 料理に合うお酒をChatGPTが提案してくれるLINE bot

  • iPhoneショートカットからChatGPTを呼び出す

  • ChatGPTが論文を要約してメールで通知してくれるGAS

 ChatGPTくんが教えてくれることが本当かどうかわからないため危険もあるのですが、ヒントをくれて背中を押してくれる存在は未経験分野に挑戦する際にとても貴重でありがたいです。
そこで、以前から気になっていた表題の件について、せっかくの連休だったのでやってみることにしました。

  • アプリをWindowsでもiOSでもAndroidでも動かしたい

  • でもOSごとに開発するのは面倒

  • Microsoft Power Apps はそれができるけど、件数の問題でデータソースを SharePoint リストや OneDrive for Business の Excel Online 以外にするには結局外部のDBMSと接続が必要(結局接続にはライセンスが必要なのでDataverseでもいいのでは?)

  • フロントエンドとバックエンドの開発、DBMSの使用、ローカルの開発環境からクラウド環境への移行、webへの公開、という流れ(要求・要件定義とか運用ルールとか保守とかはおいといて、こんな感じでいいのか?)を体験したい

テーマ選定

最初は、端末で位置情報を取得してデータベースに格納するようなアプリを作ってみようとしたのですが、、、

全体像がよくわからず、聞き方を変えました。
フロントエンドとバックエンドがあって、JavaScriptとPythonのFlask、SQLiteのセットで構築するというものを提案してくれました。

これをwebサーバにデプロイ?がよくわからなかったので、webサーバを立てるならAzureと仮定して聞き方を変えました。

いきなりクラウド上でやるものなの?というところから全くわからなかったので、聞いてみました。

翔泳社「おうちで学べるデータベースの基本」が積読してあり、この書籍中ではMySQLについて解説されていたので、ChatGPTの言ってることがわからなくても安心、と考えてDBMSをPostgreSQLから変更してもらう。

段々何の話か自分でもわからなくなってきたので、ここまででまとまってきた要素を含めてテーマから提案してもらうことにしました。
ToDoアプリを作ることになりました。

バックエンド開発

Node.jsを使用してアプリケーションを開発することになりました。
ローカルにNode.jsとnpm、MySQLをインストールし、データベースとテーブルを作成します。

ルートディレクトリにindex.jsファイルを作成し、サーバーサイドのコードを記述します。
Expressを使ってAPIエンドポイントを作成し、MySQLデータベースに接続します。

以下ChatGPT生成 index.js

const express = require('express');
const mysql = require('mysql');
const bodyParser = require('body-parser');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
app.use(bodyParser.json());

const connection = mysql.createConnection({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
});

connection.connect((err) => {
  if (err) {
    console.error('Error connecting to the database:', err);
    process.exit(1);
  }
  console.log('Connected to the database');
});

app.get('/api/todos', (req, res) => {
  connection.query('SELECT * FROM todos', (err, results) => {
    if (err) {
      res.status(500).json({ error: err });
    } else {
      res.json(results);
    }
  });
});

app.post('/api/todos', (req, res) => {
  const { title } = req.body;
  connection.query('INSERT INTO todos (title) VALUES (?)', [title], (err, result) => {
    if (err) {
      res.status(500).json({ error: err });
    } else {
      res.status(201).json({ id: result.insertId, title, completed: false });
    }
  });
});

app.put('/api/todos/:id', (req, res) => {
  const { id } = req.params;
  const { title, completed } = req.body;
  connection.query('UPDATE todos SET title = ?, completed = ? WHERE id = ?', [title, completed, id], (err) => {
    if (err) {
      res.status(500).json({ error: err });
    } else {
      res.status(204).end();
    }
  });
});

app.delete('/api/todos/:id', (req, res) => {
  const { id } = req.params;
  connection.query('DELETE FROM todos WHERE id = ?', [id], (err) => {
    if (err) {
      res.status(500).json({ error: err });
    } else {
      res.status(204).end();
    }
  });
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

ルートディレクトリに.envファイルを作成し、MySQLデータベースの接続情報を記述します。

以下ChatGPT生成 .env

DB_HOST=localhost
DB_USER=your_database_user
DB_PASSWORD=your_database_password
DB_DATABASE=your_database_name

上記を実行すると、エラーが出たので相談します。
コードを追記してくれました。

しかしまたエラーが出た。これは、「.env」を「process.env」というファイル名で書いていたことと、.env内で「DB_HOST=localhost」のように文字列をクォーテーションでくくっていなかったことが原因で「DB_HOST='localhost'」とすると解消しました。これはChatGPTから原因をつかめず、Google先生と試行錯誤で辿り着きました。

動作確認をしましょう、と言われても動作確認方法がわからなかったので、APIの動作確認方法をききました。Postmanを提案してくれました。

フロントエンド開発

public フォルダ内に index.htmlstyles.css、および app.jsを作るそうです。

app.jsを何度か修正してもらいました。

以下ChatGPT生成 app.js

const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');

todoForm.addEventListener('submit', async (event) => {
  event.preventDefault();
  const title = todoInput.value.trim();
  if (!title) return;

  try {
    const response = await fetch('/api/todos', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ title }),
    });
    const newTodo = await response.json();
    addTodoToList(newTodo);
    todoInput.value = '';
  } catch (error) {
    console.error('Error adding todo:', error);
  }
});

async function fetchTodos() {
  try {
    const response = await fetch('/api/todos');
    const todos = await response.json();
    todos.forEach(addTodoToList);
  } catch (error) {
    console.error('Error fetching todos:', error);
  }
}

function addTodoToList(todo) {
  const listItem = document.createElement('li');
  listItem.setAttribute('id', `todo-${todo.id}`);

  const input = document.createElement('input');
  input.value = todo.title;
  input.addEventListener('change', async () => {
    try {
      await fetch(`/api/todos/${todo.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ title: input.value, completed: todo.completed }),
      });
    } catch (error) {
      console.error('Error updating todo:', error);
    }
  });
  listItem.appendChild(input);

  listItem.addEventListener('click', async (event) => {
    if (event.target === input) return;

    try {
      await fetch(`/api/todos/${todo.id}`, { method: 'DELETE' });
      listItem.remove();
    } catch (error) {
      console.error('Error deleting todo:', error);
    }
  });

  todoList.appendChild(listItem);
}

fetchTodos();

データベースと接続できないみたいでした。
ファイルの保存場所がよくわかりません。

ファイルのパスを指定できていませんでした。

やはり保存場所がおかしい?フォルダ構成を変えなくても良いように、パスを変更してくれました。

Edgeでローカルリポジトリのファイルを開くとエラーになったので、URLを指定するのだと教わり、無事開くことができました。

HTMLとCSSのUIをいい感じにしてもらおうとしました。

こんな画面になりました

Visual Studio CodeでのGitHubエラーについても教えてくれました。
・なぜかコミットできない
VSCodeのGitにGitHubのメールアドレスを登録する必要があった

コミットしてプッシュする前にプルしないといけないらしい

リモートリポジトリ側で関係ないファイルをアップして削除していたので、不整合になった

メールアドレスを非公開にしているのでVSCodeから接続できない

Azureへのデプロイ

サーバサイドのデプロイ

Azure上にアプリケーションをデプロイするには、Azure App Serviceを使用します。だそうです。
GitHubのリポジトリにあるスクリプトが自動でデプロイされる??どういうこと???

ymlファイルが生成され、それに従って自動的にデプロイされるらしい。
どこに何のファイルを格納するのかわからない。

MySQLのデプロイ

Azure Database for MySQLを使ってデータベースを作成することにしました。
どうやってテーブルや列を作成するのか?Azure Cloud Shellから接続できないのはどういうこと?

Azure Database for MySQLをVNet統合で作成したため、同じVNetからしかMySQLに接続できないようになっていました。そこで、MySQLを操作するためだけの仮想マシンを立ち上げました。
しかし、仮想マシンからどうやって接続するの?

VMから接続できました。テーブルを作成します。

テーブルの確認方法

テーブル操作ができたのでVMは停止。
ではアプリとMySQLはどうやって接続するのか?
Azure App Serviceではなんとなく「静的webアプリ」を選択してしまったがそのせいでネットワークを設定できない?そもそも「静的webアプリ」がわからない。結局、「コード」の方でデプロイしなおしたが、アプリで作成したタスクはデータベースに格納できていない。

ボタンを押すことはできてもデータベースにつながっていないので、リストの要素だけが作成され、APIの動作がかみあわない。

感想

試行錯誤の上、上記のようにwebアプリはデータベースに接続できていません。

  • 各言語とかのチュートリアルとかそのままやった方が早いのでは?

  • noteにChatGPTとのやりとりの一部を雑に貼っていく中で、エラーに対する回答は本当に優秀だと改めて感じました。「こんな質問でこんなことまでわかるの!?」の連続でした。自分一人ではもっと早く挫折していたでしょう。

この記事が気に入ったらサポートをしてみませんか?