6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React + OCI Autonomous AI Databaseで簡易なTodoアプリを作る (ORDS活用)

Posted at

はじめに

Oracle Cloud Infrastructure (OCI) の Autonomous Database (ADB) には、データベースのテーブルを自動的にREST API化するORDS (Oracle REST Data Services) という機能が標準で備わっています。

今回はこれらを使って、Reactで簡易なToDoアプリを作ってみたいと思います。

構成は、全てのコンポーネントで OCI Always Free (永久無料枠) を使用するため、無料で構築可能です。

インターネットに抜ける通信料(アウトバウンド転送量)は10TB/月を超えると有償になるのでご注意ください。
(これだけだと超えることはほぼ無いと思いますが…)

アーキテクチャ

  • Database: OCI Autonomous AI Database Always Free
    • API: ORDS
  • Server: OCI Compute (Oracle Linux 8, VM.Standard.A1.Flex)
    • Frontend: React

1. OCI Autonomous Databaseの準備

まずはOCIコンソールからAutonomous Databaseを作成します。

  • ワークロード:レイクハウス(トランザクション処理でも良いです)
  • データベースハージョン:26ai
  • Always Free:チェック(忘れずに!)
  • ネットワーク・アクセス:すべての場所からの…(検証用。適宜変更ください)

image.png

Always Freeにチェックが入っていることを忘れずに確認ください!

作成が完了したら、Database Actions (SQL Developer Web) を開きます。

1-1. Todoテーブルの作成

Database Actionsの「SQL」を選択します。
image.png

以下のクエリを実行してテーブルを作成します。

CREATE TABLE todos (
    id NUMBER GENERATED ALWAYS AS IDENTITY,
    title VARCHAR2(255) NOT NULL,
    is_completed NUMBER(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT todos_pk PRIMARY KEY (id)
);

更新ボタンでTODOSテーブルが表示されればOKです。

image.png

1-2. ORDS (REST API) の有効化

作成したテーブルをREST APIとして公開します。

  1. 先程のSQL画面から表示された左側のリストから TODOS テーブルを探します(表示されない場合はスキーマがあっているか確認してください)。
  2. TODOS テーブルを右クリック(またはメニューから)し、REST → 有効化 を選択します。
    image.png
  3. 設定ダイアログで以下のように設定します。
    • オブジェクト別名 (Alias): todos (これがURLの一部になります)
    • 認証が必要 (Authentication): 今回は簡易作成のためチェックを外す (※本番ではOAuth2などを設定すべきですが、デモ用としてパブリックにします)
  4. 有効化をクリックします。

たったこれでAPIが完成しました!

image.png

同じく左側のリストのTODOSを右クリックし、cURLコマンド…をクリックすることで、RESTエンドポイントURL が確認可能です。
(例: https://<unique-id>.adb.<region>.oraclecloudapps.com/ords/admin/todos/

このURLに対して標準的なHTTPメソッド(GET, POST, PUT, DELETE)を送るだけでDML操作が可能です。


2. Reactプロジェクトの作成

クライアントPC側でまずは動作確認を行います。
不要な場合は3章へ飛ばしてOKです。

フロントエンドを構築します。ビルドツールにはViteを使用します。

npm create vite@latest todo-app -- --template react
cd todo-app
npm install

2-1. 環境変数の設定

プロジェクトルートに .env ファイルを作成し、先ほどコピーしたORDSのURLを設定します。

vim ./.env
VITE_API_URL=https://<unique-id>.adb.<region>.oraclecloudapps.com/ords/admin/todos/

2-2. アプリの実装

src/App.jsx を以下のように書き換えます。

import { useState, useEffect } from 'react'

const API_URL = import.meta.env.VITE_API_URL

function App() {
  const [todos, setTodos] = useState([])
  const [newTitle, setNewTitle] = useState('')

  // Todo一覧の取得 (GET)
  const fetchTodos = async () => {
    try {
      const res = await fetch(API_URL)
      const data = await res.json()
      // ORDSのAuto-RESTは { items: [...] } の形式で返します
      setTodos(data.items)
    } catch (err) {
      console.error("Failed to fetch todos:", err)
    }
  }

  // 初回レンダリング時に取得
  useEffect(() => {
    fetchTodos()
  }, [])

  // Todoの追加 (POST)
  const addTodo = async (e) => {
    e.preventDefault()
    if (!newTitle) return

    try {
      await fetch(API_URL, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          title: newTitle
        })
      })
      setNewTitle('')
      fetchTodos() // リスト再取得
    } catch (err) {
      console.error("Failed to add todo:", err)
    }
  }

  // Todoの削除 (DELETE)
  const deleteTodo = async (id) => {
    try {
      // Auto-RESTの仕様では /endpoint/:id で削除
      await fetch(`${API_URL}${id}`, {
        method: 'DELETE'
      })
      fetchTodos()
    } catch (err) {
      console.error("Failed to delete todo:", err)
    }
  }

  // 完了状態の切り替え (PUT)
  const toggleTodo = async (todo) => {
    try {
      await fetch(`${API_URL}${todo.id}`, {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          // 更新したいフィールドのみを送ることも可能ですが、
          // Auto-RESTの場合は全カラムを送るのが安全な場合もあります。
          // ここではシンプルに更新値を送ります。
          id: todo.id,
          title: todo.title,
          is_completed: todo.is_completed === 1 ? 0 : 1
        })
      })
      fetchTodos()
    } catch (err) {
      console.error("Failed to update todo:", err)
    }
  }

  return (
    <div style={{ padding: '2rem', maxWidth: '600px', margin: '0 auto' }}>
      <h1>React + Oracle ADB Todo Apps</h1>
      
      <form onSubmit={addTodo} style={{ marginBottom: '2rem' }}>
        <input 
          type="text" 
          value={newTitle} 
          onChange={(e) => setNewTitle(e.target.value)}
          placeholder="新しいタスクを入力..."
          style={{ padding: '0.5rem', width: '70%' }}
        />
        <button type="submit" style={{ padding: '0.5rem', marginLeft: '0.5rem' }}>追加</button>
      </form>

      <ul>
        {todos.map(todo => (
          <li key={todo.id} style={{ marginBottom: '0.5rem', listStyle: 'none', display: 'flex', alignItems: 'center' }}>
            <input 
              type="checkbox" 
              checked={todo.is_completed === 1} 
              onChange={() => toggleTodo(todo)}
            />
            <span style={{ 
              marginLeft: '0.5rem', 
              textDecoration: todo.is_completed === 1 ? 'line-through' : 'none',
              flexGrow: 1
            }}>
              {todo.title}
            </span>
            <button onClick={() => deleteTodo(todo.id)} style={{ marginLeft: '1rem', color: 'red' }}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  )
}

export default App

2-3. ローカルでの動作確認

実装ができたら、まずはローカル環境で動作を確認します。

npm run dev

ブラウザで http://localhost:5173 (または表示されたURL)にアクセスします。
タスクの追加・削除・完了チェックなどの操作を行い、エラーなく動作することを確認してください。

image.png

先程ADB側で確認したDatabase ActionsのSQL側でテーブルを確認すると、実際にデータが反映されていることが分かります。

  • TODOSを右クリック → 開く
    image.png
  • データを選択することで、実際に投入したデータの確認
    image.png

3. アプリケーションのデプロイ (OCI Compute)

作成したReactアプリをローカルだけでなく、OCI上のコンピュート・インスタンス(Oracle Linux 9)にデプロイしてWebサーバーとして公開する手順を解説します。

3-1. Computeインスタンスの作成

OCIコンソールからコンピュート・インスタンスを作成します。今回はパフォーマンスが高く、かつAlways Free枠で使える Ampere A1 インスタンスを使用します。

  • イメージ: Oracle Linux 8 (aarch64)
  • シェイプ: VM.Standard.A1.Flex
    • OCPU: 1〜4 (お好みで。4 OCPUまで無料)
    • メモリ: 6〜24 GB (お好みで。24 GBまで無料)

※ VM.Standard.A1.Flex はARMアーキテクチャですが、Node.jsやNginxなどの主要なソフトウェアは通常通り動作します。

3-2. セキュリティリスト(ファイアウォール)の設定

作成したインスタンスが配置されているVCN(仮想クラウドネットワーク)のセキュリティリストを編集し、インターネットからのWebアクセス(ポート80)を許可します。

  1. OCIコンソールで該当のサブネットの詳細ページを開きます。
  2. 「セキュリティ・リスト」をクリックし、現在適用されているリストを選択します。
  3. 「イングレス・ルールの追加」をクリックし、以下を設定します。
    • ソースCIDR: 0.0.0.0/0 (全IPからのアクセスを許可)
    • IPプロトコル: TCP
    • 宛先ポート範囲: 80

3-3. サーバーのセットアップ

作成したインスタンスにSSHで接続し、Webサーバー(Nginx)とビルド用環境(Node.js)をインストールします。
ARMアーキテクチャであっても、手順はx86_64と変わりません。

# パッケージの更新
sudo dnf update -y

# Nginxのインストールと起動
sudo dnf install nginx -y
sudo systemctl enable --now nginx

# Firewalldの設定 (OSレベルでのポート開放)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

この時点で、ブラウザから http://<インスタンスのパブリックIP> にアクセスすると、Nginxのデフォルトページが表示されるはずです。

3-4. アプリケーションのビルドと配置

サーバー上でアプリケーションをビルドし、公開ディレクトリに配置します。

まず、Node.jsをインストールします(既にインストール済みの場合はスキップ)。

# Node.js 20系の有効化とインストール
sudo dnf module enable nodejs:20 -y
sudo dnf install nodejs -y

次に、ViteでReactプロジェクトの雛形を作成します。

# ホームディレクトリなどで実行
cd ~
npm create vite@latest todo-app -- --template react
cd todo-app
npm install

src/App.jsxvim 等のエディタで開き、前述の「2-2. アプリの実装」で作成したコードをコピペして上書きします。

vim src/App.jsx
# ここで中身を全て消去し、コードを貼り付けて保存 (:wq)

同様に、環境変数ファイル .env.production を作成し、ADBのURLを記述します。

vim .env.production

Content of .env.production:

VITE_API_URL=https://<unique-id>.adb.<region>.oraclecloudapps.com/ords/admin/todos/

ファイルの準備ができたら、ビルドを実行します。

# ビルド実行
npm run build

ビルドが完了すると dist ディレクトリが生成されます。
この中身をNginxのドキュメントルートにコピーします。

# Nginxのデフォルトファイルを削除
sudo rm -rf /usr/share/nginx/html/*

# ビルド成果物をドキュメントルートにコピー
sudo cp -r dist/* /usr/share/nginx/html/

# 権限の修正 (念のためNginxユーザーが読み取れるように)
sudo chown -R nginx:nginx /usr/share/nginx/html
sudo chmod -R 755 /usr/share/nginx/html

3-5. 動作確認

ブラウザで http://<インスタンスのパブリックIP> にアクセスしてください。
Reactで作ったTodoアプリが表示され、同じように追加したタスクがADBに保存されることが確認できれば成功です!
image.png

おわりに

OCI Autonomous DatabaseのORDS機能を使えば、バックエンドサーバーを構築することなくDB操作を行うことができます。
さらにOCI Computeと組み合わせることで、Webアプリケーション環境をすべてOCI上で構築することが可能です。

今回は認証なしで公開しましたが、ビジネス利用の際はADBはADMINユーザではなくユーザを作成の上テーブルを管理し、必ずORDS側でOAuth2認証などを設定し、Compute側も適切なセキュリティ対策(HTTPS化など)を実施してください。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?