【後編1】Express+PostgreSQL連携のモックアップ

# 【後編1】Express+PostgreSQL連携のモックアップを作ろう

この記事では、「[前編](#)」で構築した**Mac (Apple Silicon)上の環境**（Node.js / PostgreSQL / PostGIS）を活用して、**簡単なデータテーブル**を用意し、**ExpressアプリからDB接続してデータをやりとりする**流れをモックアップとして作成してみます。次回「後編2」ではさらにReact+Leaflet連携やTwitter API取得を組み合わせたフロントエンドとの統合を進めましょう。

---

## ゴール

1. PostgreSQLに「ナラティブ投稿」用のテーブルを作成  
2. Express.jsのAPIサーバーからDBに接続 → データを読み書きするエンドポイントを実装  
3. 簡単なモックデータを挿入し、`/api/posts`などのエンドポイントで取得できることを確認する  

これにより、「後編2」でReactやLeafletからリクエストを送ってもDBアクセスが可能になります。

---

# 1. Postgresにテーブルを作成

## 1.1 データベースの選定

前編で `my_database` などを作成している場合を想定します。  
今回はサンプルとして `narrative_db` というDB名を使ってもOKです。

```bash
# psqlでデータベースに入る
psql -d my_database

-- あるいは
# psql -d narrative_db
```

## 1.2 テーブル作成

まずはシンプルにナラティブ投稿を保存するテーブルを設計します。

```sql
CREATE TABLE IF NOT EXISTS posts (
  id SERIAL PRIMARY KEY,
  title TEXT,
  content TEXT,
  created_at TIMESTAMP DEFAULT NOW()
);
```

- `id`: 自動採番
- `title`: 投稿のタイトル（例：公園でのエピソード、など）
- `content`: ナラティブ本文
- `created_at`: 投稿日時

> 後編2で地理情報（geom）を追加し、PostGIS機能を活用する場合は後ほど列を拡張する形になります。

---

# 2. Expressプロジェクトの骨組み

## 2.1 ディレクトリ構成

```
my-project/
 ┣ server/
 ┃   ┣ index.js
 ┃   ┣ db.js
 ┃   ┗ package.json
 ┗ (その他：frontend/ など)
```

前編で用意した`server`フォルダ内に `index.js` と `db.js` を作り、そこにDB接続やルーティングを実装します。

## 2.2 package.json

`server`ディレクトリで以下のように`npm init -y`しておき、必要な依存関係を追加します。

```bash
cd my-project/server
npm init -y
npm install express pg cors
```

- `express`: サーバー本体
- `pg`: PostgreSQL接続用
- `cors`: フロントエンドからのアクセスを許可するためのミドルウェア

### npmスクリプト例

`package.json`内に「`"start": "node index.js"`」などを設定し、起動しやすくしておく:

```jsonc
{
  "name": "server",
  "version": "1.0.0",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "pg": "^8.10.0",
    "cors": "^2.8.5"
  }
}
```

---

# 3. DB接続ロジック: `db.js`

`db.js`にはPostgreSQLへの接続プールを作るコードをまとめます。

```js
// server/db.js
const { Pool } = require('pg');

// 環境変数やハードコードなどで管理
const pool = new Pool({
  user: 'postgres',        // 例: local環境なら 'postgres'
  host: 'localhost',
  database: 'my_database', // 例: my_database
  password: 'yourpassword',
  port: 5432
});

module.exports = pool;
```

> 実運用では `.env` ファイルに接続情報を入れ、`dotenv`パッケージを使って取り込む方法がおすすめです。

---

# 4. Expressサーバー: `index.js`

## 4.1 最小限のAPIエンドポイント

```js
// server/index.js
const express = require('express');
const cors = require('cors');
const pool = require('./db');

const app = express();
app.use(cors());
app.use(express.json()); // JSONボディをパース

// テスト用: 動作確認
app.get('/api/hello', (req, res) => {
  res.json({ message: 'Hello from Express mockup!' });
});

// 1) すべての投稿を取得
app.get('/api/posts', async (req, res) => {
  try {
    const result = await pool.query('SELECT * FROM posts ORDER BY id DESC');
    res.json(result.rows);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'DB query error' });
  }
});

// 2) 新規投稿を作成
app.post('/api/posts', async (req, res) => {
  try {
    const { title, content } = req.body;
    const queryText = 'INSERT INTO posts (title, content) VALUES ($1, $2) RETURNING *';
    const values = [title, content];

    const result = await pool.query(queryText, values);
    res.json(result.rows[0]); // 作成されたレコードを返す
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'DB insert error' });
  }
});

// サーバー起動
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
  console.log(`Mockup server running on port ${PORT}`);
});
```

ここで**`/api/posts`** に対し `GET` すると、DB内の全てのレコードを取得し、  
`POST` すると `{title, content}` のJSONを受け取り、DBにINSERTします。

---

# 5. 動作確認：モックデータ追加

## 5.1 サーバー起動

```bash
cd my-project/server
npm start
# => "Mockup server running on port 4000"
```

ブラウザで `http://localhost:4000/api/hello` を開いて `{"message":"Hello from Express mockup!"}` が返ればOK。

## 5.2 POSTリクエストを投げてみる

### 方法1: curlコマンド

```bash
curl -X POST -H "Content-Type: application/json" \
  -d '{"title":"初投稿","content":"これはテスト投稿です"}' \
  http://localhost:4000/api/posts
```

返ってくるJSON例:
```json
{
  "id": 1,
  "title": "初投稿",
  "content": "これはテスト投稿です",
  "created_at": "2023-12-01T09:00:00.123Z"
}
```

### 方法2: VSCodeのREST ClientやPostman

GUI操作に慣れていれば、Postmanなどのツールで `POST`リクエストを送るのもOK。

## 5.3 GETリクエストで一覧取得

```bash
curl http://localhost:4000/api/posts
```

登録されたレコードが配列形式で返却されるはずです。

---

# 6. Mockupのまとめと次ステップ

ここまでで、**Express+PostgreSQL**を用いた**モックアップAPI**が完成しました。  
すでにテーブル`posts`を使ってデータの読み書きができているので、**後編2**ではここに**地理情報(PostGIS)**や**Twitterから取得したツイート**を含めたり、**React+Leafletのフロントエンド**から呼び出して地図に可視化する工程に進みます。

---

## よくあるトラブル

1. **DB接続エラー**: ユーザー名やパスワードが間違っている、Postgresが起動していないなど。  
2. **ポート衝突**: 他のアプリが`4000`番を使っている場合は`.env`や`package.json`で変更可能。  
3. **CORS**: フロントエンドが別ドメイン(`localhost:3000`など)になる場合、`cors()`を適切に設定する。

---

## まとめ

- **テーブル設計**と**Expressエンドポイント**により、モックデータを操作するAPIができた  
- 次回「後編2」では**地図表示（Leaflet + React）**や**Twitter APIで収集したデータをDBに格納**するフローを実装して、実際に画面上でナラティブを表示・投稿するアプリへ発展させます。

これで**後編1**は完了です。  
データベースとAPIが問題なくやり取りできることを確認したら、いよいよ**地図×SNS×ナラティブ**の本格実装に進んでみましょう。