はじめに
本記事はモノリシックでない分離されたアーキテクチャ(マイクロサービス)について理解を深めるため、
ミニマムなアプリを作ってみたときのまとめ記事です。
※当方初心者のため、間違いありましたら是非ともご指摘お願いいたします。
著者について
以下著者のスペック
- エンジニア一年目
- WebアプリといえばMVCしか知らない
- マイクロサービス?なにそれおいしいの
背景
基本情報などの勉強中、よくこんな図が出てきて混乱していました。
- Webアプリのアーキテクチャ?、MVCしかしらんけど?
- アプリのサーバって一つだけじゃないの?
- でもReactとかは独立してサーバーが立っているぽい、、
- どうやってバックエンドと連携させるんやろ、、?
このような疑問を持った私は、「わかんないなら触ってみればいいじゃん!」と意気込み、
フロントエンドとバックエンドの機能をサーバごとに切り離したミニマムなアプリを作ろうと決めました。
開発
概要
画面を担当するフロントサーバとロジックを担当するバックサーバの二つのサーバを立てて、
インターネットのニュースを検索できるアプリを作る。
環境
Node.js v14.15.1
- サーバサイドのJavaScript
- こちらの記事が非常にわかりやすくおすすめ
- 今回は超簡単なロジックを実装するのみに使う
Express v4.17.1
- Node.jsで動く軽量なWebフレームワーク
- Webサーバを立てるのも非常に簡単
- 今回はAPIのルーティング等に使う
Yarn v1.22.4
- npmと互換性があるパッケージ管理システム
- 一度インストールしたパッケージをキャッシュするためインストールが高速
目標
画像のような簡単なニュース検索アプリを作る。
検索条件を入れ、「Search」ボタンを押下すれば、検索条件にヒットするニュースを検索する。
構成
重要であるのはフロントサーバとバックサーバをAPIで疎結合している点です。
フロントサーバはバックサーバのAPIを呼び出し、返却されたレスポンスをもとに画面描画をします。
手順
バックサーバの実装
Node.js, Expressの解説は目的ではないため、重要な部分(独自APIを実装する部分)のみ示します。
以下はExpressでサーバを起動する部分です。
'use strict';constexpress=require('express');constapp=express();constcors=require('cors');constdotenv=require('dotenv');dotenv.config({path:'./.env'});constmorgan=require('morgan');// CORS(クロスオリジンリソース共有)を許可app.use(cors());require('./routes/news')(app);// アクセスロガーを実装app.use(morgan('dev'));// サーバをポート3000で起動app.listen(process.env.PORT,()=>console.log('listening on port '+process.env.PORT));module.exports=app;ここではCORS(クロスオリジン間リソース共有)を有効にしています。
CORSについては自分もよく理解しきれていないですがMDNに以下のような説明があります。
オリジン間リソース共有Cross-Origin Resource Sharing (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
こちらの記事が詳しいため参考にしてください。
次はインターネットからニュースの情報を取得する処理です。
ここではNews APIというAPIを本アプリ用にラップしています。
constNewsAPI=require('newsapi');constnewsapi=newNewsAPI(process.env.NEWS_API_ACCESS_KEY);constmorgam=require('morgan');constrouter=require('express').Router();module.exports=(app)=>{router.route('/').get((req,res)=>res.json({message:'This is a index page.'}));router.route('/news').get((req,res)=>{newsapi.v2.topHeadlines({// 検索条件が指定されなかった場合はデフォルトの条件を指定する。country:req.query.country||'jp',category:req.query.category||'general',q:req.query.q||'',pageSize:Number(req.query.pageSize)||30}).then(news=>res.json(news));});//bind access loggerapp.use(morgam('dev'));app.use(router);};フロントサーバの実装
こちらもReactの解説は目的でないため、重要な部分(バックサーバと通信する部分)のみ示します。
またcreate-react-appを使用してテンプレを作成しました。
以下はバックサーバのAPIを呼び出し、返却されたニュース一覧のJSONを画面上の変数に渡しています。
consthandleSubmit=asyncevent=>{// submitボタンを押すとブラウザのデフォルトでリロードされてしまうため// デフォルトの動作をさせないよう設定するevent.preventDefault();// バックサーバのAPIを呼び出すletarticlesArr=awaitaxios.get(endPoint+'/news',{// 画面に入力された検索条件を独自APIのリクエストに乗せる params:{country:country.value,category:category.value,q:keyword,pageSize:pageSize.value}})// データが返却されたら変数articlesArrにデータを代入する。.then(res=>res.data.articles);// 画面上の変数にデータを代入する。setArticles(articlesArr);};完成品
ソースは以下においてあります。
https://github.com/yasuaki640/news-api-app
※コードレビュー歓迎
終わりに
業務でも趣味でもモノリシックなアーキテクチャしか触ったことがなく、
ツイッター上でマイクロサービスなどの用語を理解するのに時間がかかりました。
※現在は完全に理解した程度
技術理解のために実際に触れてみるのはやはり強いですね、、、
本記事がどなたかのお役に立てれば幸いです。
※間違いありましたら是非ご指摘お願いいたします。

