Java21とSpring Boot3.2を採用して新規事業を開発した話

4.9K Views

October 28, 24

スライド概要

profile-image

ウェルスナビ株式会社 技術広報チームの公式アカウントです。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

Java 21とSpring Boot 3.2を採⽤して 新規事業を開発した話 村岡 将伍 JJUG CCC 2024 Fall 1

2.

⾃⼰紹介 氏名 村岡 将伍 ウェルスナビ株式会社 ロボアド開発グループ サービス機能開発チーム ウェルスナビでは ● 2024年3⽉にJoin ● 顧客向けWebアプリケーション実装を担当 ひとこと ● JJUG CCC初参加で雰囲気や温度感が分からないまま初登壇してます。 2 @2024 WealthNavi Inc.

3.

WealthNavi /ウェルスナビの紹介 資産運用ロボアドバイザー “WealthNavi” ※⼀般社団法⼈⽇本投資顧問業協会「契約資産状況(最新版)(2024年3⽉末現在) 『ラップ業務』『投資⼀任業』」を基にネット専業業者を⽐較 ウエルスアドバイザー 社調べ(2024年6⽉時点) ※画⾯はイメージです。 3 @2024 WealthNavi Inc.

4.

アジェンダ 1. 本日お話すること 2. プロジェクト立ち上げ 3. 実際に起きたこと、苦労したこと 4. 振り返り 5. さいごに 4 @2024 WealthNavi Inc.

5.

1. 本日お話すること 2. プロジェクト立ち上げ 3. 実際に起きたこと、苦労したこと 4. 振り返り 5. さいごに 5 @2024 WealthNavi Inc.

6.

本⽇お話すること 新規事業の開発に伴うあれこれ ● ● ● ● プロジェクト⽴ち上げと社内背景 コーディング規約などの開発ルール整備 SpringBoot 3.2、Java 21を採⽤してみて 実際に起きたこと、苦労したこと ● 今後のアクション 6 @2024 WealthNavi Inc.

7.

新サービスについて 7 @2024 WealthNavi Inc.

8.

1. 本日お話すること 2. プロジェクト立ち上げ 3. 実際に起きたこと、苦労したこと 4. 振り返り 5. さいごに 8 @2024 WealthNavi Inc.

9.

インフラ構成図 9 @2024 WealthNavi Inc.

10.

技術選定と社内背景 社内背景とモチベーション 技術選定理由 ● 既存プロダクトのバックエンドと技術 スタックを合わせたい ○ Java + Spring Boot ● 最新のSpring Bootを使いたい ○ 運⽤保守性 ● あえて古いバージョンを使う理由も なさそう ● なんとなく最新使ってみたい ● いずれアプデしなきゃいけない時が 来る ● ウェルスナビのサービスの軸の1つ が「⻑期運⽤」 ○ 当たり前だけどシステムも⻑期運⽤ を考えないとね 10 @2024 WealthNavi Inc.

11.

ウェルスナビにおける開発ガイドラインの準拠 設計原則 プロジェクト構成 コーディング規約 持続可能性 運⽤保守性 可⽤性 デプロイ容易性 レジリエンス 疎結合 単⼀責任 セキュリティ ディレクトリ構成 ファイル構成 パッケージ構成 命名規約 プログラミングスタイル クラスとインターフェース メソッド ラムダとストリーム 例外 コメント テストコード 11 @2024 WealthNavi Inc.

12.

ウェルスナビにおける開発ガイドラインの準拠 12 @2024 WealthNavi Inc.

13.

Qodanaの活⽤ Qodanaとは ● JetBrainsが開発している静的コード解析ツール ● 無料版(Community)もあるが、弊社ではUltimate版を使⽤ ● ローカルのIntelliJ IDEAで実⾏したり、オンラインのGitHub Actionsなどのパイプラインに組み込む ことができる ● 作成したレポートをQodana Cloud上で確認できる 採⽤理由 ● JetBrains社製であるため、IntelliJ IDEAとの親和性が⾼い ● 料⾦体系がコード⾏数ベースではなく開発者ベースのためコストメリットがある 13 @2024 WealthNavi Inc.

14.

Qodanaの活⽤ Qodana Cloudでのレポートイメージ ● ローカルで実⾏したQodanaのレポートをCloud上にアップして共有できるのが便利 ● 客観的、標準的な評価基準を使い品質⽔準を維持しレビュアとレビュイの負担軽減を達成 14 @2024 WealthNavi Inc.

15.

1. 本日お話すること 2. プロジェクト立ち上げ 3. 実際に起きたこと、苦労したこと 4. 振り返り 5. さいごに 15 @2024 WealthNavi Inc.

16.

実際に起きたこと、苦労したこと 最適な保険を提案するためのシミュレーション(プロトタイプ) ● ウェルスナビのクォンツチーム(⾦融⼯学の専⾨家)が作成 ● このシミュレーションシートの構造をそのままモデル化し実装 16 @2024 WealthNavi Inc.

17.

シミュレーションロジックのパフォーマンス改善 17 @2024 WealthNavi Inc.

18.

シミュレーションロジックのパフォーマンス改善 問題 解決策 ● 計算シミュレーション処理に膨⼤な時 間がかかり、メモリ消費が激しく、さ らに処理がタイムアウトしてしまった ● シミュレーションの試⾏回数は維持 しつつ、マスタデータの読み込みを ⼀箇所にまとめ効率化 ○ モンテカルロシミュレーションを⽤ ● BigDecimalの精度を計算結果に影 いた数千回の試⾏ 響が出ない範囲で下げる ○ マスタデータを都度取得 ○ BigDecimalでの精度過多 (⼩数以下15桁) 18 @2024 WealthNavi Inc.

19.

シミュレーションシートの空セルの扱い問題 19 @2024 WealthNavi Inc.

20.

シミュレーションシートの空セルの扱い問題 問題 解決策 ● 当初、空セルはnullとして扱うように 実装してしていた ● nullチェックの実装 ● Optionalを利⽤した改善 (演算時のみ0として扱うように) ○ シミュレーションシート通りに実装 していたが本来は0として扱うべき だった ○ コミュニケーションロスがあった 20 @2024 WealthNavi Inc.

21.

計算クラスのテストコード 21 @2024 WealthNavi Inc.

22.

計算クラスのテストコード 巨⼤なスプシには数百を超える計算式が、、、 22 @2024 WealthNavi Inc.

23.

計算クラスのテストコード 問題 解決策 ● 計算式を含んだクラスが数百個以上〜 という絶望的なレベル ● 出⼒値のみを評価するブラックボック ス的なテスト⽅式を⽤いた ● クラス毎に単体テストを書くのは無理 ● ⼊⼒パラメータの組み合わせと期待値 のセットを数万パターン作成 ● 開発のスピードアップが要求されてお り時間もない ● Testcontainersを使って実際のマスタ データを使ったテストコードを実装 23 @2024 WealthNavi Inc.

24.

ロジックをmodelとserviceのどちらに寄せるかに関する議論 24 @2024 WealthNavi Inc.

25.

ロジックをmodelとserviceのどちらに寄せるかに関する議論 ここの保険会社ごとに異なるリダイレクトURLを設定するための ロジックですが、 ロジックは保険会社ごとのmodelにまとめた方がいいのでは? レビュイ 25 レビュア @2024 WealthNavi Inc.

26.

ロジックをmodelとserviceのどちらに寄せるかに関する議論 ここの保険会社ごとに異なるリダイレクトURLを設定するための ロジックですが、 ロジックは保険会社ごとのmodelにまとめた方がいいのでは? レビュイ レビュア modelがロジックを持ちすぎているような気がします。 modelは会社ごとのものとその元になるインターフェー スのみとして、 記載いただいたロジックはService側の責務になるかなと 思ったのですが、いかがでしょうか? 26 @2024 WealthNavi Inc.

27.

ロジックをmodelとserviceのどちらに寄せるかに関する議論 ここの保険会社ごとに異なるリダイレクトURLを設定するための ロジックですが、 ロジックは保険会社ごとのmodelにまとめた方がいいのでは? レビュイ レビュア 開発ガイドラインを⾒る限り、 業務ロジックはmodelにもserviceにも書けると思うので、 modelにするかserviceにするかの話かと思っておりますが、 会社を判定するだけのmodelにするメリットは現時点でない ようにも思います。 27 @2024 WealthNavi Inc.

28.

ロジックをmodelとserviceのどちらに寄せるかに関する議論 開発ガイドラインでは、 model側にのみ「ソースコードが業務知識の仕様書になることを 目指します。」としています。 会社ごとに違うということがmodel側だけでわからないといけな いのではと解釈しました。 また、今後もシュミレーションが改定されることが予想されるので テスタビリティが高いmodelに実装しておけばコストも下げれるメ リットもあり、 serviceではなくmodelがいいのではと思いました。 28 レビュイ レビュア @2024 WealthNavi Inc.

29.

ロジックをmodelとserviceのどちらに寄せるかに関する議論 開発ガイドラインでは、 model側にのみ「ソースコードが業務知識の仕様書になることを 目指します。」としています。 会社ごとに違うということがmodel側だけでわからないといけな いのではと解釈しました。 また、今後もシュミレーションが改定されることが予想されるので テスタビリティが高いmodelに実装しておけばコストも下げれるメ リットもあり、 serviceではなくmodelがいいのではと思いました。 レビュイ レビュア なるほど!納得しました! 後でリファクタします! 29 @2024 WealthNavi Inc.

30.

ディレクトリ名やクラス名を⽇本語でコミット 30 @2024 WealthNavi Inc.

31.

ディレクトリ名やクラス名を⽇本語でコミット シミュレーションシートを⾒た実装者↓ 必要保障額?最低支払保証期間? なにそれ? 保険の専門用語わからん・・・。 31 @2024 WealthNavi Inc.

32.

ディレクトリ名やクラス名を⽇本語でコミット シミュレーションシートを⾒た実装者↓ このまま英数字にすると、 今後の実装や変更で混乱しそうだから 慣れるまではひとまず日本語でコミットしよ! 32 @2024 WealthNavi Inc.

33.

ディレクトリ名やクラス名を⽇本語でコミット プルリクを⾒たレビュア↓ なんか ディレクトリ名やクラス名が日本 語なんだけど大丈夫!? (心配)(ざわざわ) 後日リファクタ予定っす! 33 @2024 WealthNavi Inc.

34.

AWS ElastiCache ServerlessとSpringアプリケーションから Redisアクセスを実装したときにうまくいかない問題 34 @2024 WealthNavi Inc.

35.

ElastiCache Serverlessへの接続がうまくいかない ◾事象 SpringBootアプリケーションを作成し、Lettuceを使ったRedisへのアクセスを実装したところ、 actuatorのRedis Health CheckにてFailed ‧spring-boot-starter:3.2.2 ‧spring-data-redis:3.2.2 ‧io.lettuce:lettuce-core:6.3.1.RELEASE 35 @2024 WealthNavi Inc.

36.

ElastiCache Serverlessへの接続がうまくいかない ◾実⾏した内容 1. gradle bootRunにて起動 2. curl http://localhost:8080/actuator/health 3. エラー発⽣(stacktraceを添付、主なメッセージは下記) ‧Caused by: io.lettuce.core.RedisException: Cannot obtain initial Redis Cluster topology ‧Caused by: io.lettuce.core.cluster.topology.DefaultClusterTopologyRefresh$CannotRetrieveClusterPartitions: Cannot retrieve cluster partitions from [redis+tls://localhost:6379] ‧Caused by: io.lettuce.core.cluster.topology.DefaultClusterTopologyRefresh$CannotRetrieveClusterPartitions: Cannot retrieve cluster partitions from [redis+tls://localhost:6379] 36 @2024 WealthNavi Inc.

37.

ElastiCache Serverlessへの接続がうまくいかない AWSに問い合わせしてみた 下記のページを参考に試⾏錯誤してみましたが、エラー内容が変わらずだったので⼀旦現 状の実装ファイルを添付させていただきました。 https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/BestPractices. Clients-lettuce-cme.html サーバーレスではない既存の独⾃キャッシュのRedisの⽅を起動して確認することは現時 点でしておりません。サーバーレスであることで何か差異が発⽣するとは思っておりませ んが認識合っていますでしょうか? ElastiCache側に必要な設定もしくはアプリケーションの実装⽅法の過不⾜があればご教 ⽰いただきたいと思っております。 37 @2024 WealthNavi Inc.

38.

ElastiCache Serverlessへの接続がうまくいかない ‧application.yml (⼀部抜粋) spring: data: redis: host: localhost port: 6379 ‧RedisTemplateConfig.java (添付) 38 @2024 WealthNavi Inc.

39.

ElastiCache Serverlessへの接続がうまくいかない AWSからの回答 当該のエラーについてお調べしましたところ、該当するものと⾒受けられる GitHub Issueがござ 当該のエラーについてお調べしましたところ、該当するものと⾒受けられる GitHub いました。 ElastiCache は STARTTLSを⽤いておりません。 Issueがございました。 ElastiCache は STARTTLSを⽤いておりません。 つきましては、 Lettuce の設定ファイルにて STARTTLS を無効化し、状況が改善するかご確認い つきましては、 Lettuce の設定ファイルにて STARTTLS を無効化し、状況が改善するかご ただけますでしょうか。 確認いただけますでしょうか。 また、お客様は Session Manager によるポートフォワーディングを⽤いていることから、 TLS 接 また、お客様は Session Manager によるポートフォワーディングを⽤いていることか 続に際してクライアントライブラリから⾒えるドメイン名が異なるものと存じます。これによ 接続に際してクライアントライブラリから⾒えるドメイン名が異なるものと存 り、ら、 TLS TLS 証明書の検証に失敗する可能性がございます。 じます。これにより、 TLS 証明書の検証に失敗する可能性がございます。 Lettuce の TLS 証明書の検証について詳しく存じておりませんものの、証明書を検証しないよう Lettuce の TLS 証明書の検証について詳しく存じておりませんものの、証明書を検証しな 設定いただく必要もあるかと存じますので、お客様にてご確認いただくことをお勧めいたしま す。いよう設定いただく必要もあるかと存じますので、お客様にてご確認いただくことをお勧 めいたします。 39 @2024 WealthNavi Inc.

40.

ElastiCache Serverlessへの接続がうまくいかない 結局どうしたか 事象と課題 ● ElastiCache Serverlessを選択すると ○ データ転送は常にTLS通信で⾏われる ○ Redisエンジンはクラスタモードで起動する ● TLS通信で接続できてクラスタモードに対応したRedisクライアントが必要 ○ RedisクライアントとしてLettuceを利⽤していた ○ 試⾏錯誤したがTLS通信や証明書の問題を解決できる⾒込みがたたなかった 結論 ● 新規事業の開発ではデリバリーの速度を重視するため、リリースを優先し、Serverlessではな いElastiCacheを採⽤した 40 @2024 WealthNavi Inc.

41.

既存ライブラリを使おうとしてハマった件 41 @2024 WealthNavi Inc.

42.

既存ライブラリを使おうとしてハマった件 某Kディレクター→ ←⼊社したばかりの頃のぼく 42 @2024 WealthNavi Inc.

43.

既存ライブラリを使おうとしてハマった件 ログイン後の処理の仕様を 既存のWealthNaviと同じにしたいんだよね〜 共通ID基盤ができるまでの一時的なコードなんだ けどさ〜 実装おなしゃす! 某Kディレクター↑ ←⼊社したばかりの頃のぼく 43 @2024 WealthNavi Inc.

44.

既存ライブラリを使おうとしてハマった件 ログイン後の処理の仕様を 既存のWealthNaviと同じにしたいんだよね〜 実装おなしゃす! (入社したばかりで既存プロダクトの仕様はまだ詳しくない けど、コードを読むのは好きだし既存のコードと共通化でき そうだしチョロそう!) ういっす!やります! 44 @2024 WealthNavi Inc.

45.

既存ライブラリを使おうとしてハマった件 既存プロダクトのコードがライブラリ化されてる し、 これを依存関係に追加して同じメソッド使うだけ で済みそう!? (まだよく見てない) 45 @2024 WealthNavi Inc.

46.

既存ライブラリを使おうとしてハマった件 ん?? 46 @2024 WealthNavi Inc.

47.

既存ライブラリを使おうとしてハマった件 依存関係がめちゃくちゃある・・・ クソデカライブラリやん・・・ 47 @2024 WealthNavi Inc.

48.

既存ライブラリを使おうとしてハマった件 いらないの除外したいけど多すぎる・・・ 一時的なコードとはいえ、 同じコードを量産したくないし、 何とかして既存プロダクトへの影響を最小にして 綺麗にできないかな・・・ 48 @2024 WealthNavi Inc.

49.

既存ライブラリを使おうとしてハマった件 そろそろ終わりそ? テスト進めたいんだよね〜 結構手こずってるっす! 今週中には何とか・・! (やべ、めっちゃ急かされてる〜) 49 @2024 WealthNavi Inc.

50.

結局どうしたか 既存ライブラリをどうにか使おうとすると終わりが⾒えなかったため、 結局諦めて、既存コードをコピペして実装した(速攻で終わった)。 共通ID基盤がリリースされるまでの間の⼀時的なコードだし、最終的には綺麗になりそ うだから当時はスピード優先の判断をした。 50 @2024 WealthNavi Inc.

51.

学び 同じコードを量産させないように綺麗に書きたい思いよりも 実装スピードを優先させなきゃいけない時がある(負債発⽣の瞬間でもある)。 既存プロダクトの依存関係が知れた。 51 @2024 WealthNavi Inc.

52.

最新のJavaを使って 最新のJava使って嬉しかった話、苦労した話あったっけ? 52 @2024 WealthNavi Inc.

53.

最新のJavaを使って 最新のJava使って嬉しかった話、苦労した話あったっけ? ‧‧‧。 53 @2024 WealthNavi Inc.

54.

最新のJavaを使ってみて 最新のJava使って嬉しかった話、苦労した話あったっけ? recordクラスは使ってたけどJava 17でも動くし‧‧ あ、switch⽂でパターンマッチングはやってたかな 54 @2024 WealthNavi Inc.

55.

最新のJavaを使ってみて 逆に⾔うとJava 8とか11以前で慣れてた⼈でも 違和感なく使えたという意⾒が多かった! 55 @2024 WealthNavi Inc.

56.

最新のSpringを使ってみて Spring Securityは6系になったので、 書き⽅が結構変わってエンジニアブログなどにあまりサンプルがなく 公式ドキュメントと格闘した。 56 @2024 WealthNavi Inc.

57.

Qodana関連 GitHub Actions上で起動した時に Gradleの依存関係(WealthNaviのプライベートMavenリポジトリから取得したライブラ リ)が解決されずに無駄なエラーが出るという事象はあります‧‧ 同様の?ISSUEはありそうですが、動きなし‧‧ https://youtrack.jetbrains.com/issue/QD-9039/Qodana-fails-in-GitHub-on-pull-reque st-with-file-not-found 57 @2024 WealthNavi Inc.

58.

1. 本日お話すること 2. プロジェクト立ち上げ 3. 実際に起きたこと、苦労したこと 4. 振り返り 5. さいごに 58 @2024 WealthNavi Inc.

59.

振り返り 開発環境の課題 開発プロセスの課題 ● GithubActionsのCI部分に課題が残っている ○ gradle buildを無駄に実⾏している ● チームでの開発プロセスに課題があった ○ 共通部品の開発が後回しになり、いざ作 り始めるとすでに実装を始めていた個別 機能へ⼤きな影響を与えた ○ test/Qodanaの前/Dockerイメージビルド など ○ コンフリクトも多く発⽣し適⽤に苦労し た 59 @2024 WealthNavi Inc.

60.

Next Action ‧機能拡張 ‧リファクタ ‧共通ID基盤リリース ‧他の新規プロダクト開発 60 @2024 WealthNavi Inc.

61.

1. 本日お話すること 2. プロジェクト立ち上げ 3. 実際に起きたこと、苦労したこと 4. 振り返り 5. さいごに 61 @2024 WealthNavi Inc.

62.

ロボアド開発グループの紹介 ● ロボアドサービスにおける新機能開発やエンハンス開発 ● 技術的負債解消やアーキテクチャのモダナイズ ● ロボアドサービスの根幹を⽀える開発部隊 Latency Integration Container Framework Performance SQL Resillience Log Architecture Pub/Sub Cloud Java Security Event-Driven 62 @2024 WealthNavi Inc.

63.

Appendix.Ⅰ ウェルスナビでは複数の開発系ポジションで採⽤を強化しています。 ● ● ● ● バックエンド開発エンジニア エンジニアリングマネージャー データエンジニア モバイルエンジニア(Android) 採⽤情報詳細 ● 下記URL(QRコード)よりご確認ください。 https://hrmos.co/pages/wealthnavi 採⽤に関する お問い合わせ先 ● ● 「カジュアルに話を聞いてみたい」という温度感でも構いません。 ウェルスナビ採⽤チーム([email protected])までご連 絡お待ちしております。 主な採⽤中職種 63 @2024 WealthNavi Inc.

64.

Appendix.Ⅱ 定期的にWealthNavi開発(技術‧組織)に関する情報を発信しています。 開発者ブログ 公式Xアカウント 技術広報に関する お問い合わせ先 ● https://zenn.dev/p/wn_engineering ブックマーク追加や記事への「いいね」していただけると嬉しいです ● WealthNavi Developers(@WealthNavi_Tech) ● WealthNavi(ウェルスナビ)(@WealthNavi) ● ウェルスナビ技術広報チーム([email protected]) 64 @2024 WealthNavi Inc.

65.

【重要な注意事項】 ● 本資料は、断定的判断を提供するものではなく、情報を提供することのみを⽬的としており、いか なる種類の商品も勧誘するものではありません。最終的な決定は、お客様⾃⾝で判断するものと し、当社はこれに⼀切関与せず、また、⼀切の責任を負いません。 ● 本資料には将来の出来事に関する予想が含まれている場合がありますが、それらは予想であり、ま た、本資料の内容の正確性、信頼性、完全性、適時性等を⼀切保証するものではありません。本資 料に基づいて被ったいかなる損害についても、当社は⼀切の責任を負いません。また、当社は、新 しい情報や将来の出来事その他の情報について、更新⼜は訂正する義務を負いません。 ● 本資料を利⽤することによりお客様に⽣じた直接的損害、間接的損害、派⽣的損害その他いかなる 損害についても、当社は⼀切の責任を負いません。 商号等:ウェルスナビ株式会社 金融商品取引業者 関東財務局長(金商) 第2884号 加入協会:日本証券業協会 一般社団法人日本投資顧問業協会 65 @2024 WealthNavi Inc.