2021.01.08

【前編】Spring Bootってなにがいいの

伊藤裕一
ヴイエムウェア株式会社
このエントリーをはてなブックマークに追加

2021年11月2日:ウェビナーアーカイブ配信中!
「Springフレームワーク徹底解説 〜初心者から上級者向けセッションと事例のご紹介」

ダウンロード:「2021年 Springの現状」資料
ダウンロード:「2020年 Springの現状」資料

【前編】Spring Bootってなにがいいの←本記事です
【後編】Spring Bootで始めるマイクロサービスの開発

はじめに

はじめまして。VMwareの伊藤です。Tanzu製品のプラットフォームアーキテクトとして働いています。
開発と運用双方の経験がありますが、だいぶインフラ寄りの経歴となります。
プライベートでは書籍を執筆するほどPythonを利用しているのですが、仕事ではJavaSpringBootを使う機会が増えてきましたのでSpringBootの紹介をしたいと思います。

なお、久しぶりのJavaとなりますので、Spring Bootの比較対象がレガシーよりなJava(2010年以前のJ2EEなど)となりますがご容赦ください。新しいJava/JavaEEやフレームワークを使って開発されたアプリケーションはここで述べるほどの大きな欠点は持っていません。

私は学生時代からJavaC++を中心としてソフトウェア開発をすることが多かったのですが、2010年代以降はプラットフォーム的な制約がない限りはPythonJavaScript以外はほとんど書かなくなっていました。重厚長大なアプリケーションを書くのであればJavaなどは適した言語ですが、私が開発していたのは小規模のものが多く気軽に書けるPythonのほうが適していたという背景があります。ただ、JavaSpring Bootに関しては例外で「今までの典型的なJavaのアプリケーション開発より圧倒的に楽」というのが第一印象でした。

そういった「昔からある典型的なJavaアプリケーション開発の大変さ」という背景を踏まえた上で、「Spring Bootがなぜ素晴らしいか」という点について語りたいと思います。詳細は追って説明しますが、3行で説明するなら以下となります

  1. アプリケーションの構造がシンプルですべてがパッケージングされるため、構築が簡単で移植性に優れる
  2. Spring Bootフレームワークがアプリに必要な基礎機能をシンプルに提供。特にSpring Framework本体のDI(Dependency Injection:依存性の注入)の仕組みが優秀
  3. 成熟したコミュニティと豊富なエコシステム

典型的なレガシーJavaアプリとSpring Bootアプリの違い

まず、以下の図を見てください。

01.png
(左:典型的なレガシーJavaアプリケーションの構造 / 右:SpringBootのアプリの構造)

JavaのウェブアプリケーションはミドルウェアであるTomcatWebLogicなどの上にアプリケーション本体となるWAR(サーブレットなどが含まれる)を配置し動作させます。アプリケーション本体がApp Library(様々なJAR)を参照し、それらもミドルウェアの構成や、その下で動くJavaランタイムに依存するという構成です。

このような構成をとることで、アプリケーションが依存する様々なライブラリ(たとえばDBドライバやフレームワークなど)をアプリケーションから切り離して他のアプリでも再利用が可能となるメリットがあります。

ただ、これは中央のクラスローダーによりロードされたスタックの絵にあるように「どのライブラリのどのクラスが実際にロードされているか分かりにくい、バージョンが異なる同一ライブラリが同居する」といった問題を引き起こします。

このような構成で「ミドルウェアに脆弱性が見つかりバージョンアップの必要性が発生した」とすると、ミドルウェアをアップグレードするだけでなく足元のJava Runtimeを対応した新しいバージョンに更新し、上のアプリケーションがきちんと動作するか再テストが必要になります。再テストをしなければ、ランタイムの変更に伴うトラブルや、ライブラリのバージョン依存のトラブルなどが見つけられないためです。つまり「開発環境で作成したアプリケーションのWarが本番環境のランタイムやミドルウェアの上で動くか、かなり怪しい」という問題があるということです。

開発環境やステージング環境で実施したテストにパスしていても、本番環境でライブラリ周りのトラブルが発生しないと保証することはかなり難しいです。

一方、右側のSpring Bootの構成をみてください。

これはミドルウェア(TomcatJetty)ごとアプリケーション本体を1つのアプリケーションのパッケージ(直接実行できるJar)にまとめてしまい、それをランタイムで動作させるという構成を取っています。これは「Fat Jar」と呼ばれるもので、ミドルウェア内のライブラリーを再利用性できなくなるものの先ほど述べた変更や移植の難易度を大幅に下げます。非常に大きなJavaEE(JakartaEE)でこれを実現しようと思うとサイズが大きくなり難しくなりますが、比較的シンプルで軽量なSpring Bootであればこのような構成を簡単にとることができます。

シンプルなオールインワン構成なのでアプリケーション環境の構築に手間取らず、デプロイを繰り返すことも簡単にでき、インテグレーションテストも実施しやすいです。このSpringBootのアプリケーションはMavenGradleがある環境であれば、誰でも簡単に作成することができます。

以下のSpring公式のサイトから、SpringBootアプリケーションのテンプレートを必要なライブラリを追加した構成でダウンロードできます。ダウンロードしたプロジェクトファイルに「Hello World」的なコードを書き、ビルドするだけでJarが作成でき、ランするだけでアプリが動きます。

02.png
(Spring公式サイト:https://start.spring.io/)

以上がSpringBootを利用する1つめのメリットである「アプリケーションの構造がシンプルですべてがパッケージングされるため、構築が簡単で移植性に優れる」となります。

Spring Bootの仕組みが開発者の生産性を高める

開発作業における開発者の生産性の定義は様々ですが、分かりやすいものでは以下が挙げられます

  • 業務時間のうちの何%をコードを書く時間にあてられているか
  • 新規のコードを決められた時間内でどれほど書けるか
  • 既存コードの更新とテストを決められた時間内でどれほどできるか

この記事の冒頭でも述べたように私はPythonでコードを書くことが多いのですが、それはレガシーなJavaに比べて以下の点が優れていたからです(あくまでも小規模開発の話です)

  • Pythonは書けば動くので、コードを書く以外の作業時間があまり必要でない
  • プログラム1行あたりに実現できる処理が多く、パッケージも豊富なので車輪の再開発が少ない
  • 言語仕様的にコンポーネントを疎結合にしやすいので、ユニットテストやDI(Dependency Injection:依存性の注入)の難易度が低い

これらの特性があれば、言語やフレームワークにさえ慣れてしまえば、普及している手法であればなんでもよいと考えています。

Javaの生のJSPServlet、およびStrutsなどの古いフレームワークは「開発のサイクルに乗る」までにやることが多いので、あまり小規模の開発には向いていません。

きちんとアプリケーションの設計をして、似たような仕組みをポンポンと大量に作れるのであれば問題ありませんが、新しい仕組みを新規に実装する場合はコード量も多く、他のコードに絡んでいるとテストなどはしにくいです。

一方、Spring BootPythonで言えばフルスタックフレームワークであるDjangoというより軽量フレームワークであるFlaskに作法が似ています。

「あるURLにアクセスが来たら、それに結び付けられた処理を呼び出す」という処理をシンプルに書けるということです。

それに加えて、SpringBoot(正確にはSpring Framework自体)のフレームワークとしてDI(Dependency Injection:依存性の注入)を使うことを「仕組みとして提供している」ので、モジュールごとに独立した疎結合なプログラムを書きやすくなります。より具体的に言えば「クラスAがクラスBを使う状況において、クラスAがクラスBに依存しにくくなる」ということです。

疎結合なコードになるということはクラスごとにユニットテストを書きやすいということなので、新規開発時にテストを書いてしまえば最初からバグが少なく、コードを更新した際も問題を再テストで検知しやすいコードを書けます。DIを導入しなければ先のクラスAのテストはクラスBの実装に依存してしまいます。

2クラス程度であれば問題ないでしょうが、より大規模になると数十のクラスが密結合しているといった状況になります。そのような状況でテストをして問題を発見したとしても、どこに問題があるか非常に分かりにくいです。

こういった問題をDIで解決することにより新規のコードを追加することも既存のコードを更新することも難易度が下がり、結果としてコードを書く生産性が上がります。もちろん自分でDIフレームワークを導入することで問題を解決できますが、最初からある「ありもののDIを使う」ことのほうが上級レベルのプログラマも初心者なプログラマにとっても簡単なはずです。

DIの機能はSpringの専売特許ではなくJavaEEでも実現できますが、Springのほうがより根幹にあり強制力が強い印象があります。

03.png

なお、開発プロジェクトによってはJavaEEを利用しない場合があるかと思いますが、そのような場合はSpringを検討いただいてもよいと思います。SpringJavaEEの一部(たとえばJPAなど)を利用することは多いですが、JavaEEAPIには依存していません。

以上がSpringBootを利用する2つめのメリットである「Spring Bootフレームワークがアプリに必要な基礎機能をシンプルに提供。特にSpring Framework本体のDI(Dependency Injection:依存性の注入)の仕組みが優秀」となります。

歴史がありつつ、新しくもあるSpring Boot

Spring Bootという名前を初めて聞いたJava開発者の方は多いと思いますが、「Spring」というフレームワークを聞いたことがないかたは少ないかもしれません。

なぜならSpring Frameworkは長い歴史があり、ユーザー数の多い円熟したフレームワークだからです。
(参照Wikipediaより:https://ja.wikipedia.org/wiki/Spring_Framework)

名前からわかるかもしれませんが、Spring BootはこのSpring Frameworkのプロジェクトの1つという立ち位置です。オリジナルのSpring Frameworkは歴史があり様々な機能を持つ一方で、仕組みが複雑化(たとえば様々なパラメーターファイル)しています。

これはトレードオフ的に仕方のないことです。そのような状況でSpring Bootプロジェクトが開始され、新規の開発者であっても簡単にSpringアプリケーションの開発ができるようになりました。新規の開発者に優しいということは、ベテランにも優しいということです。

以下にSpringエコシステムの図を記載します。これ以外にもプロジェクトは存在しています。

04.png

(図:Springエコシステム)

以上がSpringBootを利用する3つめのメリットである「成熟したコミュニティと豊富なエコシステム」となります。

最後となりますが、VMwareSpring BootおよびSpring Frameworkに対してサポートを提供しています。サポートが必要な場合は、ぜひお問い合わせください!

Springの現状について調査したレポートがございますので、ぜひダウンロードしていただきご覧ください!

関連ページ

「2021年 Springの現状」資料
「2020年 Springの現状」資料

資料のダウンロードはこちら

フォームに必要事項を記入いただくことで、資料がダウンロードできます。

この記事の著者:伊藤裕一

ヴイエムウェア株式会社

2011年よりインフラ業界でL2/L3ネットワーク及びHCIのサポート/プリセールスのエンジニアに従事。
2020年からVMwareでコンテナやKubernetesおよび開発/運用のモダン化を実現するTanzuの製品担当となる。
趣味でPythonプログラムを書いています。


DevOps Hubのアカウントをフォローして
更新情報を受け取る

  • Like on Feedly
    follow us in feedly

関連記事

このエントリーをはてなブックマークに追加

お問い合わせ

DevOpsに関することなら
お気軽にご相談ください。

Facebook、TwitterでDevOpsに関する
情報配信を行っています。