簡易的なwebサーバーを作ろう(node http-server axios)

## 前回の続き

前回、Rubyにてバックエンドサーバを立ち上げる記事を投稿しました。
[Rubyのサーバー構築(WEBrickってなんぞ？)](https://qiita.com/hirapg_1123/items/4b78e376e042b51d3938)
今回はフロント側(webサーバー)を簡易的ですがjavascriptで作成していきます。

## そもそもwebサーバーって？
Webサーバーとは、パソコンやスマートフォンなどの端末からHTTP/HTTPSで送られたリクエストに対してHTML、CSS、JavaScriptなどの情報を返す役割を持ったソフトウェアのことを指します。
一般的に、Webサーバーへ接続するためにはブラウザを使用します。

### webサーバーの役割
要は、見る側の要素をブラウザへ返すのを担当するサーバーになります。(ざっくり言うと)

## サーバーを作る前にweb3層構造の話
### web3層構造とは
今回作成する「WEBサーバー」に加えて、前回作成したRubyでの「バックエンドサーバー」、  
データを保管する「DBサーバー」の三つをまとめたものが『WEB３層構造』と言います。

**1.WEBサーバー(プレゼンテーション層)**
ユーザーインターフェースやユーザーに対する情報表示を担当します。
HTML、CSS、JavaScriptなどが使われ、クライアントサイドでの処理が行われます。
ブラウザ上で動作するフロントエンドがここに相当します。

**2.バックエンドサーバー(アプリケーション層)**
ビジネスロジックやアプリケーションの機能を提供します。
サーバーサイドでの処理が行われ、データの処理が行われます。
通常、バックエンドサーバーがこの層に相当します。

**3.データベースサーバー(データベース層)**
データの管理を担当します。
データベースシステムがあり、データの保存、取得、更新、削除が行われます。
### なんで分けるの？
**○ メリット**
- 負荷分散
各サーバーを１台ずつ用意すれば各処理の負荷を分散できる
※但し、１ノード(1台のPC)で構築する場合はその限りではない
- メンテナンスの容易性
故障やエラーの範囲を限定できるため，原因の特定が行いやすい
- 開発が分けられる
各層が独立しているので開発作業を層ごとに行える。
- セキュリティ
DBへのアクセスがバックエンドとBD間だけになり、不用意にユーザーからアクセスされる危険を回避できる

**× デメリット**
- 各層毎に物理マシンを用意した場合、それなりのコストが掛かる。

## 使用するライブラリ

### axios
axiosはJavaScriptでバックエンドと通信を行うライブラリになります。
以下は基本的なGetメソッドを行う記述です。
```axios.js
// axiosをインポートする
const axios = require('axios');

// GETリクエストを行う
axios.get('https://example.com/api/data') // バックエンドのエンドポイントを指定
  .then(response => {
    // リクエストが成功した場合の処理
    console.log(response.data);
  })
  .catch(error => {
    // エラーが発生した場合の処理
    console.error('Error fetching data:', error);
  });

```
### http-server
1. `npm i http-server`でライブラリをインストール
2. `http-server -p "ポート番号を指定"`でサーバーを起動できる。

## 作り方(http-server)
### ディレクトリ構成
```
front
|-js/ #ここにはHTMLで呼び出すJavaScriptファイルを置く
|-index.html
|-package.json
|-paskage-lock.json
```
※バックエンドはこれと別に、前回の記事を参考に用意して下さい

### ライブラリのインストール

- http-server
- axios

まずはこの2つをインストールします
npmが使える環境で`npm install http-server axios`でインストール

### index.htmlを記述
今回はbutton下のdivタグにバックエンドから、返ってきた要素を表示できるようにして行きます。
``` index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Frontend Example</title>
  </head>
  <body>
    <div class="container">
      <h1>Hello, Frontend!</h1>
      <button id="fetchDataButton">Click!</button>
      <div id="dataContainer"></div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js"></script>
        <script src="./js/server.js"></script> <!-- xiosを記述したjavascriptファイルを読み込みます -->
  </body>
</html>
```

### server.jsに記述
index.htmlのbuttonをクリックしたときに、データを取得してくるようにします。
`http://localhost:3000/get_data`は、今回用意したバックエンドのエンドポイントとなります。
``` server.js
// ボタンをクリックしてfetchData関数を発火させる
document.getElementById("fetchDataButton").addEventListener("click", fetchData);

function fetchData() {
  // サーバーからデータを取得
  axios
    .get("http://localhost:8000/get_data") // ここにバックエンドのエンドポイントを指定する。
    .then((response) => {
      // 指定したIDにレスポンスデータを入れて表示
      const dataContainer = document.getElementById("dataContainer");
      dataContainer.innerText = `Data from server: ${JSON.stringify(
        response.data
      )}`;
    })
    .catch((error) => {
      console.error("Error fetching data:", error.message);
    });
}
```
### バックエンドのファイルの中身
今回用意したバックエンドサーバー用の中身になります。
`http://localhost:8000/get_data`へアクセスされると、レスポンスとしてボディに`正常にバックエンドから値が返されました`が格納されフロントへ返されます。
```backend_server.rb
require 'webrick'
require 'json'

# サーバーの設定
server = WEBrick::HTTPServer.new(Port: 8000)

# 新しいサーブレットを作成
class GetData < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(request, response)
    response.status = 200
    response['Content-Type'] = 'text/plain'
    text_data =  '正常にバックエンドから値が返されました'
    response.body = text_data.to_json
    response['Access-Control-Allow-Origin'] = "http://localhost:3000"
  end
end

# 新しいエンドポイントにサーブレットをマウント
server.mount('/get_data', GetData)

# Ctrl+Cでサーバーを停止するためのシグナルハンドラを設定
trap('INT') { server.shutdown }

# サーバーを起動
server.start
```

### フロントとバックのサーバーを立ち上げる
フロント側のディレクトリに移り`http-server -p 3000`(今回はポート番号を3000で指定)でサーバーを起動します。
次にバックエンド側のディレクトリで`ruby backend_server.rb`でバックエンドサーバーを起動させます。

### データの取得
この両方が起動している状態で`http://localhost:3000`へアクセスするとindex.htmlが表示されます。
あとはボタンを押せば画面にレスポンスが表示されます。

## 感想
前回に続き、フロント側を中心に簡易的なアプリを作成する際に必要なものをまとめてみました。
今回もアプレンティスシップでチーム開発をするにあったって、ドキュメントにまとめるならと
記事にしてみましたが、良い勉強になりました。
まだCORSエラーなど必要なことが説明できていなかったりと不足感が否めませんが、機会を見つけて記事にして行きたいと思います。