JavaScriptを有効にしてください

実務4年目エンジニアが語る、各技術の特徴とリアルな使用感

 ·  ☕ 36 分で読めます

先日初めてiOSアプリをリリースして舞い上がっている(アプリ:隠スタディ
後、節分って昔は2月3日じゃなかった?と違和感を抱いている。近所のスーパーへ言ったら赤鬼と青鬼が生鮮食品コーナー横の従業員部屋から出てきて驚いた。高尾山から年に1回降りてくるというアナウンス。「優しい鬼ですよ」「写真をとってくれたら喜びます」。

今回は今まで自分がWebアプリ開発で選んできた・あるいは触ってきた技術の特徴、良かった点、あんましっくりこなかった点、どのフェーズに合っている技術なのかをまとめていきたい。言語化することで技術変遷の螺旋をうまく乗りこなせるようになりたい。Reactの思想から学んだが、新しいことを学ぶときは、今までと新しいこととの差分のみを見て、観察して、言語化するとワーキングメモリが減って良い。

時系列で列挙していきたい。

Python(2020年12月〜)

エンジニアになりたい!と思って触った言語。ITエンジニア=Pythonという第一想起のもと触れた言語。機械学習に用いられている、Scrapingができる言語という認識しかなかった。キノコードの講座やシリコンバレーで働いているエンジニアの講座を受けて、四則演算やbeautiful soupを使ったスクレイピングの方法を勉強した。

Ruby on Rails (2021年7月〜)

Rubyはプログラミング言語で、RailsはそのWebアプリケーションフレームワークだ。Sinatraのような軽量フレームワークでRubyのみを使ったAPI開発は経験がないため、RubyとRailsは一体で語った方が自然だと思っている。

Railsの一番の魅力は、書いていて楽しいという点に尽きる。rails newコマンド一発で、ActiveRecord(ORM)やActionController(MVCのコントローラー部分)が整備されたプロジェクトが生成され、すぐにerbテンプレートでHTMLを書くことができる。このスムーズな体験は、「自分もWebの世界に足を踏み入れた」という実感を与えてくれる。初めて動くWebページを作れたときの達成感は格別だった。

HerokuのようなPaaSを使えば、サーバー管理の知識がなくても簡単にデプロイできる。このおかげで、何も分からない状態からでもすぐに自分専用のWebページを公開できる。初学者や個人開発者にとっては、この素早いフィードバックループがとてもありがたい。さらに、gemをインストールするだけで、ページネーション、画像アップロード、テストデータの生成といった機能も簡単に追加できる。まさに「痒いところに手が届く」エコシステムだ。

ただし、動的型付け言語であるため、実行するまで型エラーが出るかどうか分からないというデメリットもある。とはいえ、これがとりあえず動かしてみるというスピード感を生む要因でもある。スタートアップなど、PMFまで早く到達する必要がある状況や、ユーザーフィードバックを迅速に反映したい場合、または資金繰りに余裕がない場合など、スピード重視の開発にはうってつけだ。

とはいえ、RSpecという強力なテストフレームワークがある。自信がない箇所や後でリファクタリングしたい部分には、単体テストや結合テストをしっかり書いておけば、テストが型の役割を補ってくれる。特にFat Controller問題に対しては、リクエストスペックを追加することで責務を明確にできる。つまり、動的型付けの弱点をテストでカバーすることで、スピードと信頼性のバランスが取れた開発が可能になるというわけだ。

Railsチュートリアルを一通りやるだけで、オブジェクト指向プログラミングの基礎、MVCモデルの理解、CRUD操作や認証・認可の実装方法、さらにWebのリクエストからHTMLレンダリングまでの流れなど、Web開発に必要な知識が一通り身につく。これ一つでWeb開発の全体像を掴めるという意味では、初心者向けとして非常に優れたフレームワークだと感じている。

https://arc.net/l/quote/qfyllbgt

実務でのRails経験も貴重な学びだった。最初に作成したアプリ(Zeroken)はRailsで開発し、フロントエンドにはVue.jsを組み合わせた。このアプリを通じてWebエンジニアとしてのキャリアをスタートさせることができた。初めて就職した会社でもRailsがメインのフレームワークだったが、アドホックなツール開発にはRuby単体を使用していた。

ここで一つの壁にぶつかった。Rubyの柔軟性は時に諸刃の剣になる。自由な書き方が許される一方で、コードがスパゲッティ化してしまうリスクがある。特にメタプログラミングが多用されている箇所は読めないコードになっていることが多かった。駆け出しの頃、Google Spreadsheetに記載された各社の情報をNotionに転記するためのRubyスクリプトを読んだ際、10個以上のコールバック関数が多段にネストされており、どの変数に何が入っているのか全く分からなかった記憶がある。debuggerを使って変数にカーソルを当てることでようやく理解できたが、当時はかなり苦労した。

クラス設計の重要性もここで学んだ。役割や属性が曖昧なまま設計されたクラスは、いざ使用する際にどのメソッドを呼び出せばいいのか分からない。自由度が高いだけに、明確な設計思想とコーディング規約がなければ、コードベースがすぐに混沌とする。とはいえ、スピード感を求めるチームや、初期フェーズのプロダクト開発には最適な技術だと感じている。戦略的に犠牲的コードを書いていくのもありだと思っている。

Vue.js(2021年10月〜)

Webエンジニアへ転身する際に作成したアプリ(Zeroken)のUIライブラリとしてVue.jsを採用した。HTMLテンプレートをそのままtemplateタグ内に書けて、ロジック部分をcomputedやmethodsに分ける構造が直感的だったこともあり、初学者でもキャッチアップしやすいと感じた。Reactを試してみたい気持ちもあったが、Vueのシンプルさと学習コストの低さが決め手となった。

Vueはその名の通り「View層」に特化した**プログレッシブフレームワーク(https://arc.net/l/quote/irzigsgf)**であるため、既存のRailsアプリで使われていたerbファイルからの移行がスムーズだった。状態管理はVuex、ルーティングはVue Router、UIコンポーネントにはVuetifyと、役割ごとにライブラリが明確に分かれているのも特徴だ。2021年当時はVue 2.xが主流で、Vue 3のComposition APIも話題になっていたが、最初はオプションAPIの方が理解しやすかった。

ライフサイクルフックMVVMパターンの採用により、基本的な使い方には困らなかったが、v-onでのイベントバインディングや、computedプロパティの再計算が走るタイミングなど、細かい挙動を理解するのには少し時間がかかった。また、transitionを用いたアニメーションの適用も最初は試行錯誤の連続だった。フロントエンドの開発に慣れてくると、Vueのリアクティブシステムの仕組みや、データバインディングの柔軟さが非常に便利だと感じるようになった。

https://ja.vuejs.org/guide/essentials/lifecycle

Vueは小規模から中規模のプロジェクトに最適で、特に迅速なプロトタイピングシンプルなSPAの構築に向いている。ただし、大規模アプリケーションになると、Reactの方がエコシステムや設計の柔軟性で優位に立つ印象がある。

Docker

AWSのEC2に自分のアプリをデプロイする際に初めてDockerを使用した。Dockerはコンテナ型仮想化プラットフォームで、開発環境と本番環境の「動作の一貫性」を保証するために生まれた。いわゆる「Works on my machine」問題を解決するため、ソフトウェアとその依存関係をパッケージ化し、どこでも同じ環境で動かせる仕組みを提供している。

実際に使ってみると、Dockerの最大のメリットは環境構築の簡略化オンボーディングの容易さだと感じた。Dockerfileとdocker-compose.ymlを用意するだけで、ローカル環境から本番環境までほぼ同じ環境で動作させることができる。また、複数のサービス(例:フロントエンド、バックエンド、DB)を一つのコンテナネットワーク内で簡単に連携させることができるため、マイクロサービスアーキテクチャにも適している。

一方で、ホストマシンのリソースを大量に消費する点はデメリットだと感じた。特に複数のコンテナを同時に立ち上げると、マシンのパフォーマンスが著しく低下することがある。また、ネットワーク設定永続ストレージの管理がやや複雑で、最初はボリュームのマウントやポートフォワーディングで苦戦した。

セキュリティ面でも注意が必要で、特にコンテナの権限管理イメージの脆弱性には気を使う必要がある。また、Docker自体はコンテナの実行を管理するだけで、オーケストレーションにはKubernetes(k8s)などの別ツールが必要になる。

プロダクトのフェーズとしては、開発初期の環境構築から本番環境のデプロイまで幅広く活用できる。特にチーム開発やCI/CDパイプラインの構築においては、Dockerの恩恵を最大限に受けることができる。環境差異を極限まで排除し、再現性の高い開発体験を提供してくれるツールだと実感している。

Heroku

Herokuは、開発者がインフラ管理に煩わされることなくコードに専念できるように作られたPaaS(Platform as a Service)である。

手間のかかるサーバー構築や設定作業を抽象化し、すぐにデプロイ可能な環境を提供することで、スタートアップや個人開発者が短期間でサービスを立ち上げられるようにすることを狙いにして作られた。

デプロイの容易さ、管理画面を通じた直感的な操作、そして多彩なアドオンによる機能拡張が可能な点がメリットとして挙げられる。一方デメリットは、利用が進むにつれてコストが嵩む可能性や、細かいインフラ調整ができないため、パフォーマンスの最適化に限界がある点だ。Herokuを使っているだけではインフラの知識はほとんど身につかないことを実感した。ただ、自分の作ったローカルアプリを初めてデプロイできた時の喜びは今でも忘れない。ありがとうHeroku。

Typescript(2022年10月~)

BIツールの導入時に初めて触れたのがTypeScriptで、現職ではフルTypeScript環境で開発しているため、今や欠かせない存在となっている。TypeScriptはJavaScriptに静的型付けを導入し、特に大規模開発長期的なメンテナンスが必要なプロジェクトで威力を発揮する。

JavaScriptはその柔軟さが魅力である一方、ランタイムエラーが多発しやすく、型の不一致によるバグが潜在的なリスクとして存在する。TypeScriptはこれを解決するために生まれた。型安全性の導入により、IDEの補完機能が強化され、コーディング中に多くのエラーを事前に検出できる点が大きなメリットだ。また、インターフェースや型エイリアスを使ってデータ構造を明示的に定義することで、コードの可読性と保守性が飛躍的に向上する。

最初は型定義やジェネリクスの概念に戸惑ったが、慣れてくると型の恩恵を強く実感する。特にAPIレスポンスの型定義や、コンポーネント間のプロップスの型チェックは、バグの発生を大幅に減少させた。Partial<T>Record<K, T>Omit<T, K>などのユーティリティ型も使いこなせるようになると、型システムの強力さを実感できる。

一方で、TypeScriptは学習コストがかかるのと、型を厳密にしすぎると開発スピードが落ちる場合がある。特に初期フェーズでは柔軟さが求められるため、型をどこまで厳密にするかのバランスが重要になる。

プロダクトのフェーズとしては、初期のプロトタイプから本格的なスケールアップを見据えた中長期的な開発に最適だ。フロントエンド(React、Vue)だけでなく、バックエンド(Node.js、NestJS)でもTypeScriptを統一することで、フルスタック開発の効率が格段に向上する。

Serverless Application Model (SAM)(2023年2月〜)

AWSが提供するServerless Application Model(SAM)は、サーバーレスアプリケーションの構築・デプロイ・管理を効率化するためのフレームワークだ。YAMLベースのtemplate.ymlファイルにLambda FunctionsAPI GatewayDynamoDBLambda Layerなどの必要なリソースを定義し、sam deploy –guidedコマンド一つで簡単にデプロイできるのが特徴だ。

内部的には、template.ymlをCloudFormationに変換して各リソースを作成しているため、CloudFormationに慣れていると理解が早い。しかし、最初にIAMロールやCloudFormationのAssume Role設定をきちんと行わないと、リソースの作成時に権限エラーが発生してつまずきやすい。この辺りのエラーは最初の壁として多くの開発者が経験するポイントだ。

ローカル開発も簡単で、sam local invokeを使えば指定のポートと環境変数ファイルを読み込んでLambdaをローカル実行できる。DB接続にはsetup関数を噛ませる必要があるものの、インフラ管理の手間がほとんどないため、アプリケーション開発に集中できる。これにより、API開発や小規模なマイクロサービスのプロトタイプ作成に最適だと感じる。

市場の反応を早く知りたい初期段階の開発に最も向いていると思う。インフラ構築のコストを最小限に抑えつつ、すぐにデプロイして動作確認ができるため、プロダクトの仮説検証には非常に有用だ。一方で、プロダクトが中規模以上に成長してくると、Lambdaの起動回数や複雑な依存関係の管理がコスト増やパフォーマンスの低下を招く可能性がある。そのタイミングで一部のLambdaをコンテナ化し、Fargateや**Kubernetes(EKS)**への移行を検討するのが自然なスケーリングパターンだろう。これにより、柔軟なスケールとより細かなリソース管理が可能になる。

Serverless技術(2023年2月〜)

サーバーレス技術全般を触ってきたが、特にAWS Lambdaを中心に活用している。サーバーレスはStateless疎結合なアーキテクチャを構築できるため、各機能の責務が明確になりやすいのが大きな利点だ。サーバー管理の負担がなく、必要な時だけコードを実行できるので、開発者はビジネスロジックに集中できる。

AWSにはイベントドリブンなサービスが豊富に用意されているため、これらを組み合わせることで柔軟で拡張性の高いアプリケーションが構築可能だ。例えば、EventBridgeでスケジュールトリガーを設定して定期的にLambdaを実行し、その結果をSNS Topicを介してSlackへ通知する。もしくは、S3のPutObjectイベントをトリガーにLambdaを実行し、アップロードされた画像のマルウェアチェックを行うといった、さまざまなパターンが考えられる。このように、AWSの各サービスを組み合わせることで複雑な処理もシンプルに管理できる。

コスト面でもサーバーレスは魅力的だ。従量課金制で、使用した分だけ料金が発生するため、常時サーバーを立ち上げる必要がないAPIやバッチ処理に最適だ。現職のプロジェクトも基本的にAPI GatewayLambdaで構成しており、インフラコストをかなり抑えることができている。

ただし、サーバーレスにもいくつかの課題がある。代表的なのがCold Start問題だ。初回のLambda実行時にInit Durationが3~4秒かかることがあり、これがユーザー体験を損なう可能性がある。特に、リアルタイム性が求められるアプリケーションでは、この遅延は無視できない問題となる。

また、Lambdaの実行時間制限は15分までなので、大規模なバッチ処理には向いていない。これに対処するためには、Step Functionsを使って複数のLambdaを組み合わせてワークフローを構築する必要がある。Step Functionsを活用すれば、長時間の処理を分割して実行できるため、より大規模なデータ処理も可能になる。

初期のプロトタイプや中小規模のサービスには最適だが、大規模なトラフィックや長時間処理を伴うシステムでは、コンテナベースのアーキテクチャ(FargateやECS、EKS)への移行を検討することが望ましい。

React(2023年2月〜)

宣言的なUIライブラリ。欲しい物を書くだけで画面に描画させることができるので、JSXやhooks, エフェクトなどの思想を覚えれば再利用しやすいコンポーネントベースのプロダクトを作ることができる。React16.8以降にhooksが導入され、ライフサイクルフックがシンプルになった。useEffectはエフェクトの管理のみを考えれば良くなり、useStateは状態の保持のみを考えれば良くなった。useRefはレンダリング外でも状態を保持したい時、例えば直接DOMをポイントしたい時や、接続中のportを再レンダリング後も保持して置きたい時などに使う。Reactはエコシステムが充実している。グローバルな状態管理やルーティング、cssライブラリ、useSWRやreact-hooks-formなど、欲しい機能は大体別ライブラリとして提供されているため、読まなければいけない公式Docは多い。ただ、コミュニティが充実しているため、英語で使い方を調べればヒットする確率が高い。create-react-appを実行するだけでローカルでサーバーが立ち上がる速さが嬉しい。最近はモジュールバンドルの速さとコンパイル速度の速さが魅力のViteに軍配が上がっている印象。スピード感と速度を求めていないのなら、VueよりReactがいいと思う。チームにReactの経験者がいる場合かつ大規模なアプリにしていきたいのなら、最初からReactを選び、JSXやhooksの思想をメンバーに啓蒙していく方が、中長期的にはチームのためになる。

Next.js(2023年2月~)

Next.jsはReactを基盤にしたフレームワークで、サーバーサイドレンダリング(SSR)や静的サイト生成(SSG)、さらにはAPIルートの提供など、Webアプリケーションの開発をトータルでサポートしてくれる。React単体では不足しがちなルーティングやデータフェッチの機能が組み込まれており、最初からプロジェクトの構成が整っているのが特徴だ。

実際に使ってみると、SSRとSSGの切り替えが柔軟にできる点が強みだと感じる。例えばSEOが重要なページにはSSRを使い、頻繁に更新が不要なページにはSSGを適用することで、パフォーマンスと開発効率の両方を高められる。ISR(インクリメンタル静的再生成)も強力で、静的サイトの恩恵を受けつつ、最新データの取得も可能になる。これは中~大規模なWebアプリにおいて特に効果を発揮する。

一方で、SSRやSSGの概念に慣れるまで時間がかかることや、ビルド時のパフォーマンスが落ちるケースもある。特にISRを多用すると、ビルド時間やキャッシュ管理が複雑になることがある。また、フロントとバックをNext.jsで一体化すると、柔軟性が失われがちで、スケール時には分離を検討する必要が出てくる。

初期段階から中規模の成長フェーズに特に向いていると思う。開発スピードを保ちつつ、SEOやパフォーマンスも両立できるため、スタートアップからエンタープライズまで幅広く使える印象。

Node.js(2023年2月〜)

Node.jsは、ChromeのV8エンジンをベースにしたサーバーサイドJavaScriptランタイムで、非同期I/Oとイベント駆動型アーキテクチャを特徴とする。JavaScriptでフロントとバックエンドの両方を開発できることから、フルスタック開発のハードルを大きく下げた存在である。

実務で使うと、非同期処理による高速なI/O操作が特に強みだと実感する。APIサーバーやリアルタイム通信(WebSocket)、ストリーミング処理など、イベント駆動型のアプリケーションには非常に相性が良い。また、npmという巨大なエコシステムがあるため、必要なライブラリはほぼ揃っており、開発のスピード感も圧倒的だ。ダウンロード数の少ないライブラリには注意した方がいい。nodeのバージョンアップの頻度がかなり早いため、メンテされていないライブラリを自分のプロダクトに入れた場合、大変なことになる。

CPU集約型のタスクには向いていない気がする。大量のデータ処理や画像・動画のエンコード処理などは苦手で、こうした処理が必要な場合はGoやRustといった他の言語が使われることが多い。また、非同期処理の設計はシンプルな反面、Promiseやasync/await、エラーハンドリングの理解が不十分だとコールバック地獄に陥りがちだ。

初期開発からスケールアウトが必要な中規模システムまで幅広く対応可能。ただし、大規模なバッチ処理や複雑な計算処理を含むシステムには、より高速に処理ができるアーキテクチャを採用した方がいい。

NestJS(2023年2月〜)

NestJSはTypeScriptベースのNode.jsフレームワークで、Angularにインスパイアされたモジュラー構造と依存性注入(DI)を特徴とする。ExpressやFastifyといった既存のHTTPサーバーフレームワークの上に構築されており、エンタープライズ向けの大規模アプリケーション開発に適している。

実際にNestJSを使ってみると、プロジェクト構成が非常に整理されており、Controller、Service、Moduleといった分離が自然に行われるのが強みだ。特にDIの仕組みは、コードの再利用性とテストのしやすさに大きく貢献する。また、デコレーターを多用したコードは直感的で読みやすく、TypeScriptとの親和性も高い。公式ドキュメントも充実しており、GraphQL、WebSocket、Microservicesなどのモジュールが最初から用意されているのも便利だ。

デメリットとしては、小規模なプロジェクトにはオーバーエンジニアリングになる可能性が高いこと。構造がしっかりしている分、学習コストも高めで、Angularの思想に慣れていないと最初は戸惑うかもしれない。自由度が高いExpressとは違い、規約に沿った開発が求められるため、柔軟性よりも秩序を重視するプロジェクト向けだ。CoCである点はRailsと似ている。

プロジェクトのスケールを見越して最初からしっかりした設計を求める中~大規模のアプリケーションに向いている。特にマイクロサービスアーキテクチャやモノリスからの段階的な移行にも適していると感じる。

Prisma(2023年2月〜)

Prismaは、Node.jsやTypeScript向けのモダンなORMとして、データベースとの型安全なやり取りを実現するために作られた。

強力な型生成、シンプルなAPI、そして自動マイグレーション機能などがあるため、開発時の型補完がありがたい。schemaファーストを選ぶとマイグレーション機能が使えないが、リリース初期の不安定なテーブルスキーマ変更に柔軟に対応できるから良い。schemaを更新したら、prisma generateを実行すれば型が生成される体験もいい。ORMの記述は直感的で、リレーションのあるテーブルとはincludeでネストするだけでいい。ただ、サブクエリやwindow関数などの複雑なクエリや特殊なデータベース機能への対応が限定的な点、そして比較的新しい技術であるため一部エコシステムが成熟していない点がデメリットとして考えられる。よく、TypeORMと比較される。Docから引用する。

TypeORM is a traditional ORM which maps tables to model classes. These model classes can be used to generate SQL migrations. Instances of the model classes then provide an interface for CRUD queries to an application at runtime.

Prisma ORM is a new kind of ORM that mitigates many problems of traditional ORMs, such as bloated model instances, mixing business with storage logic, lack of type-safety or unpredictable queries caused e.g. by lazy loading.

TypeORM は、テーブルモデルクラス にマッピングする従来型のORMである。これらのモデルクラスはSQLマイグレーションの生成に使用できる。モデルクラスのインスタンスは、実行時にアプリケーションでCRUDクエリを実行するためのインターフェースを提供する。

Prisma ORM は、新しいタイプのORMであり、従来のORMが抱える多くの問題を解決する。具体的には、肥大化したモデルインスタンス、ビジネスロジックとストレージロジックの混在、型安全性の欠如、遅延読み込みによる予測不可能なクエリなどの問題を軽減する。

https://arc.net/l/quote/rxhebgzz

Objection.js(2023年2月〜)

Objection.jsは、Knex.jsを基盤としたSQLフレンドリーなORMで、リレーショナルデータベースの操作に高い柔軟性を提供する。TypeScriptとの相性も良く、モデルクラスを自前で定義し、各モデル間のリレーションを記述することで型補完が効くのが大きな魅力だ。

Objection.jsの強みはやはりSQLに近い感覚でクエリを構築できる点にあると思う。Knexのクエリビルダーを活用して、複雑なクエリも直感的に書けるし、リレーションの管理も柔軟だ。Prismaのような抽象度の高いORMに比べて、SQLの挙動を理解した上で細かい調整が可能なのが強みだと感じる。

ただし、自由度が高い分、設計の責任が開発者に大きくのしかかる。特に、リレーションの設定ミスやwithGraphFetchedの書き忘れなど、ヒューマンエラーのリスクは常にある。また、プロジェクト全体でコーディング規約を統一しないと、コードの一貫性が失われやすい。Objection.jsはフレームワーク的なガイドラインが少ないため、チームでの運用には注意が必要だ。

プロダクトフェーズとしては、中規模以上のプロジェクトや、SQLの挙動を細かく制御したい場合に向いている。シンプルなCRUDアプリならPrismaで十分だが、複雑なビジネスロジックや最適化されたクエリが必要な場面ではObjection.jsが強みを発揮する。

GraphQL・Apollo

現職では、APIのデータクエリ言語としてGraphQLを採用し、クライアント側のデータ管理にはApollo Clientを利用している。バックエンド開発者として見ると、無理に複雑なテーブルのjoinを強いるような、責務があいまいなAPI設計に陥りやすい点が気になるが、一方でフロントエンド開発者としては、必要なデータを過不足なく取得できる点や、各フィールドをオプショナルに設定できる柔軟性に魅力を感じている。

GraphQLの最大のメリットは、Web、モバイル、IoTなど、マルチプラットフォーム間で統一したデータ通信が可能な点にあると感じている。Hasuraを挟んだり、GraphQL Federationを使ってマルチプラットフォームに対応する企業も多く見かける。いいなと思っている。同じバックエンドを複数のクライアントで共有でき、各プラットフォームに合わせた最適なレスポンスを提供できるので開発工数を大幅に削減できると思う。一方、Webアプリのみを展開するプロダクトでは、そのメリットが十分に活かされない可能性もあり、採用に対しては慎重になる面もある。

また、Apollo Serverを使えばPlaygroundでAPIのデバッグができる体験も良い。Apollo Serverのリゾルバ(https://www.apollographql.com/docs/apollo-server/data/resolvers)は、QueryとMutationに分けて記述することが必須となるため、自然と取得系と更新系の責務が分離され、コードの見通しが良くなるという利点がある。

しかし、GraphQLのエンドポイントはRESTfulな設計思想に基づかないため、エンドポイント名から直感的に役割を把握するのが難しいというデメリットがある。また、スキーマ内でフィールドの削除や名称変更など、破壊的な仕様変更を行うとGraphQL Validation Errorが発生しやすい。対応策として、スキーマ内に新旧フィールドを併存させ、古いフィールドへのリクエストがなくなった時点で削除するか、APIのバージョン管理(例:api/v2からapi/v3)を行う方法がある。こうした工夫により、GraphQLの柔軟性とマルチプラットフォーム対応という強みを最大限に活かせると考えている。

Python**(2023年12月〜2月)**

FAQボットの開発に取り組んだ際、形態素解析のサーバーとして採用したのがPythonだった。検索インデックスの考え方を応用して作った。オフィスサポートのHP(https://gmo-office.com/)右下に出てくるBotのこと。ここでの採用理由は、まず何と言っても成熟したライブラリ群、特に形態素解析用のmecab-python3がすぐに利用可能だった点にある。時間をかけずに実装できるという点は、プロジェクトの立ち上げやユーザーからのフィードバックを早急に得たい状況下では大きなアドバンテージとなった。

Pythonの大きな魅力は、シンプルで読みやすい文法と、インタプリタ型言語ならではの柔軟な開発環境にあると思っている。REPL(対話型シェル)を利用すれば、ちょっとしたアイデアを即座に試すことができるので開発速度を出せる。動的型付けのため、実行するまで型エラーに気づかないというトレードオフはあるものの、初期のプロトタイピングや実験段階では、この柔軟さがむしろ強みとなる。

また、Pythonは「バッテリー同梱」(https://docs.python.org/ja/3.13/tutorial/stdlib.html#batteries-included)の思想が根付いていることからも分かる通り、標準ライブラリだけでも充分戦える強みがある。さらに、Webアプリケーションの世界では、DjangoやFlaskといったフレームワークが存在し、Ruby on Railsのような一体型の開発体験を提供してくれる。とはいえ、今回のFAQボットプロジェクトでは、API開発やトランザクション管理、ORMの充実性といった点は直接は触れていなかったため、これらの領域については未知数な部分もある。

Ruby on Railsと比較すると、Pythonは言語自体の自由度が高く、設計や実装において開発者の裁量が大きい。これにより、プロジェクト全体の統一感を保つためには、設計思想やコーディング規約の徹底が必要となるが、その反面、柔軟なアプローチで多様な問題に対処できる点は非常に魅力的だ。特に、機械学習や自然言語処理、データサイエンスの分野では、Pythonは業界標準とも言える存在であり、ドキュメントやコミュニティも充実しているため、困った時にすぐ情報を得られるという安心感もある。

シンプルさと拡張性、そして豊富なライブラリのエコシステムがあるので、Pythonは「とりあえず動かしてみる」精神と、プロダクトの成熟度を高めるための堅牢性の両面を兼ね備えた頼もしい技術であると言える。

DevOps(2024年3月〜)

オフィスサポートの開発リードを任された時に、このプラクティスを実践し始めた。元々本番リリースを手動で行っていた。リリースする際に毎回踏み台サーバーへ入って、各モジュールのzipをデプロイするシェルスクリプトを別プロセスで立てて、デプロイの完了まで他の作業ができないという同期的な作業が辛かった。その頃DevOpsという言葉を知り、チームトポロジーやLeanとDevOpsの科学という本に出会った。DevOpsは、開発(Development)と運用(Operations)を一体化することで、リリースサイクルの短縮と品質向上を目指す一連のプラクティスである。従来の部門間の壁を取り払い、継続的インテグレーション・継続的デリバリー(CI/CD)を実現するために、ツールと文化の両面でアプローチが模索された結果として確立された。自分が所属するチームは部門が細分化されていないのでそこまで各部門間での調整は大変ではない。自分の対応範囲は広い。まずはCI/CDを改善しようという施策を推進し、Codeファミリーを使って自動化させた。DevOpsの文脈で、Four Keysという言葉も知った。DORA。具体的には、10個のプラクティスを実践し、Four Keysが改善されたかを定量的に計測するというものだ。他にも、フィーチャーフラグを導入してデプロイ頻度を増やして事業部の動作を止めないようにしたり、レビュー時のコメント規約を設定してレビュー時の心理的安全性を高めたりした。

https://speakerdeck.com/bonotake/leantodevopsnoke-xue-wokitintojie-du-suru-four-keys-dakeziyajue-dui-motutainakunaruhua?slide=29

ProtoBuffer, gRPC

ProtoBuffer(Protocol Buffers)とgRPCは、Googleが開発した効率的なデータ通信技術で、特にマイクロサービスや分散システムでの高速なデータ交換を目的としている。まだ実務で使ったことはないが、今後のプロジェクトで採用を検討している技術だ。

ProtoBufferは、高速で軽量なバイナリシリアライゼーション形式で、データをコンパクトに表現できる。これはJSONやXMLといったテキストベースのフォーマットに比べ、圧倒的に小さいデータサイズと高速な処理速度を実現する。定義ファイル(.proto)から自動的にコードが生成されるため、型安全なデータ操作が保証されるのも魅力だ。特に、異なる言語間での通信が必要な場合、ProtoBufferはその強みを発揮する。

gRPCは、このProtoBufferを利用したRPC(Remote Procedure Call)フレームワークで、HTTP/2を基盤としているため、双方向ストリーミングや効率的な接続管理が可能だ。マイクロサービス間の高速通信や、リアルタイム性が求められるアプリケーションに最適である。REST APIとは異なり、関数呼び出しのようにメソッドを直接叩く感覚でAPIを設計できるため、ビジネスロジックの構築がシンプルになる。

公式Docを読む限り、バイナリ形式による圧倒的な通信速度と帯域の節約、そして自動生成されるクライアント/サーバーコードによる開発効率の向上がメリットらしい。また、型安全性が保証されるため、エラーの発生を未然に防ぐことができる点も挙げられる。特に大規模なシステムや高トラフィックな環境では、ProtoBufferとgRPCの恩恵を最大限に受けられるんだろう。

デメリットとしては、バイナリ形式ゆえにデータが人間にとって読みにくく、デバッグが難しい点が挙げられる。また、既存のRESTfulなエコシステムに比べて導入コストが高く、学習コストもそれなりにかかる。APIの可視性が低くなるため、特に開発初期の段階ではツールの使い方やデバッグ手法をしっかりと整備しておく必要がある。

プロダクトフェーズとしては、スケールが見込まれる中~大規模システム、もしくはリアルタイム性が求められるアプリケーションでの採用が理想的だと考えている。逆に、シンプルなCRUD中心のAPIや小規模なプロジェクトであれば、JSONベースのREST APIの方が適している場合も多い。今後、マイクロサービス間の通信効率化が求められるプロジェクトがあれば、ProtoBufferとgRPCの導入を積極的に検討したい。

Go(2024年4月〜)

社内で使用しているBacklogのAPIを操作できるCLI開発をしたときに使用した。CLIはバイナリで配信したかったので、Goを採用した。go install .を開発したCLIのディレクトリで実行するとgo/bin配下にバイナリが作られるので、CLI作りに適していると感じた。denoでもいいかもしれないが、好奇心が勝ってGoを使った。cobra-cliを使った。ちなみに、開発したCLIの名前はBaliにした笑(BAcklog cLI略してBaliだ。発音はバリ島のばりと同じ。アイコンをつけるとしたらヤシの木かな)

シンプルかつ高速なコンパイル言語で、特に並行処理を効率的に扱うための設計が施されているが、まだgoroutineを活用したことがない。コンパイルが早いので、書いたコードをproductionへ持っていくまでのサイクルタイムが短い。バイナリ形式で配信ができるので、速度が求められる局面、特にマイクロサービスの開発に向いていると感じた。ProtoBufferとの相性がいい。

大規模な分散システムやクラウドサービスの開発において、シンプルさとパフォーマンス、そして並行性の管理を両立する言語が求められた結果生まれた。Goの思想を勉強することで、命名規則や見やすいドキュメントの書き方に対して知見が溜まった。スコープが狭ければ極端な話fやvなど短い変数名でも良かったり、型定義名からどんな引数を受け取るのかが分かるので仮引数は1文字でも良かったりする。ただ、メソッドの戻り値にエラーを入れる設計がかなり冗長なので、エラーハンドリングのコード量が肥大化する点はデメリットと言えそう。とにかく不要なものは削ぎ落として、後方互換性を意識した言語開発が行われているので、Ruby on Rails上がりのエンジニアにとっては物足りなさがあるかもしれない。コアなプロダクトをRailsで作って、マイクロサービスはGoで作る、というハイブリッドな戦略がモダンなのではないかという所感。

Webpack・Vite

最近までWebpackを用いてモジュールバンドルを行っていたが、Viteを移行した。Viteはモジュールの事前依存解決を行うこととコンパイラにesbuildを採用している点で爆速な開発体験をもたらしてくれた。ビルド時間は60%早くなり、ローカルの起動速度は99%速くなった笑ViteはHMRという高速なホットリロード戦略をとっている。全てのモジュール形式をECMAScript Modules形式へトランスパイルするのでブラウザは各JSファイルを非同期でダウンロードできる。そのため、アセットファイルの配信も高速化した。

Webpackは、JavaScriptのモジュールバンドラーとして複雑な依存関係を解決し、最適なバンドルを生成するために誕生した。Railsの静的アセットの配信にもWebpackは使われていた。一方、ViteはESモジュールを活用した次世代のビルドツールで、特に開発時の高速なフィードバックを重視している。Viteの特徴を調べてみたが、大きく5つあった。

依存関係の事前バンドル

本番ビルドの場合、全てのモジュールを事前に圧縮(バンドル)するため、ブラウザに配信するJSコード量が削減される
→リクエスト回数が減るため、本番でのページの読み込み速度が高速化。本番ビルドにはRollupを内部的に使用している。

開発ビルドの場合、トランスパイルのみを行っている。バンドルはブラウザで読み込んだESM上行われている
→開発中に変更したモジュールのみを再読み込みするためホットリロードが高速化(参考)。開発ビルドにはesbuildを内部的に使用している。

ホットリロードが早い

HMR(Hot Module Replacement)を採用しているため、開発中、変更のあったモジュールだけが依存解決される
→通常は全てのモジュールを再バンドルしている。

型チェックは行わない。トランスパイルのみ

コンパイラにはesbuildを使用している→初期ロード、ビルドが早い
Type Errorが発生していることをブラウザで検知したい場合は、別プロセスをたてる必要がある。tsc --noEmit --watch

全てのJSモジュールの形式をESM(ECMAScript Modules)に変換する

ESMは非同期でモジュールを読み込む設計になっているため、ページの読み込み速度が早くなる。CommonJSは同期でモジュールを読み込む設計になっていた。

古いブラウザ(IE11)では動かない可能性がある

ESMは古いブラウザだと動かない場合がある→IEは廃止されたので、考えなくても良さそう

Flutter

Wanpoというアプリの開発で初めて採用したFlutterは、Google製のクロスプラットフォームUIフレームワークとして、Dart言語を用いた開発環境を提供する。Xcodeに縛られることなく、自分の好きなIDEで作業できる点が非常に魅力的で、従来の「モバイルアプリ=Swift」という固定概念を覆してくれた。Flutterでは全てがWidgetで構成され、状態を持つWidgetと持たないWidgetに明確に分かれている設計思想は、初学者には少々ハードルがあるものの、慣れてしまえば柔軟で直感的なUI実装が可能となる。また、FirebaseやFirestore、Google PayなどのGoogleプラットフォームとの連携も充実しており、公式チュートリアルが手厚い点も安心材料だ。ホットリロードの高速な反映により、試行錯誤を繰り返しながら短期間で機能を実装・デプロイできる点は、まさにRails way的な開発スタイルを感じさせる。実務での採用を通して、Flutterはモバイル開発における新たな可能性を実感させる技術であると確信した。

React Native with expo

隠Studyというアプリ開発で採用したReact Native with expoは、個人開発者としての「熱量」を維持する上で大いに役立った。Reactの知識を背景に、expoが提供するシンプルなManaged Workflowにより、Xcodeに触れることなくカスタムネイティブライブラリも利用可能になった点が魅力だ。React Conferenceでのexpo 52リリースを機に、開発体験は大幅に向上し、eas buildコマンド一発でビルドからストア提出までこなせる手軽さは、迅速なフィードバックを得るための大きな助けとなった。さらに、ランニングコストが低いことも個人プロジェクトにとっては重要な要素だ。短期間でユーザーに届け、実際のフィードバックを元に機能改善に着手できる点は、React Nativeならではの柔軟性と効率性を実感させる。こうした体験から、今後もモバイルアプリ開発の現場でReact Nativeの採用を前向きに検討したいと考えている。

参考文献

https://dev.to/rayenmabrouk/why-nestjs-is-the-new-gold-standard-for-node-backend-development-lm

https://arc.net/l/quote/rxhebgzz

https://www.apollographql.com/docs/apollo-server/data/resolvers

https://docs.python.org/ja/3.13/tutorial/stdlib.html#batteries-included

https://speakerdeck.com/bonotake/leantodevopsnoke-xue-wokitintojie-du-suru-four-keys-dakeziyajue-dui-motutainakunaruhua?slide=29

https://protobuf.dev/

https://esbuild.github.io/faq/#why-is-esbuild-fast

https://vite.dev/guide/why

https://aws.amazon.com/what-is/python/

https://www.reddit.com/r/reactjs/comments/15t4ql9/why_would_anyone_use_react/?rdt=46426

https://findy.connpass.com/event/339334/presentation/?utm_campaign=new_event_links_to_group_member&utm_source=notifications&utm_medium=email&utm_content=detail_btn

https://www.apollographql.com/docs/react

https://zenn.dev/wsuzume/articles/280ba652dc4fc7


octpsubaru
著者
octpsubaru
Web Developer