Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
10年続くJavaシステムの進化を支える戦略 API・DB・キャッシュの互換性設計/cario...
Search
Cariot
May 30, 2026
85
0
Share
10年続くJavaシステムの進化を支える戦略 API・DB・キャッシュの互換性設計/cariot-jjug-ccc-2026-s
2026年5月30日に開催された『JJUG CCC 2026 Spring』の発表資料です。
https://ccc2026spring.java-users.jp/
Cariot
May 30, 2026
More Decks by Cariot
See All by Cariot
Amazon Bedrock AgentCore GatewayとSalesforceで実現する汎用クエリAIエージェント/cariot-meguro-lt
cariotinc
1
150
AWSのサービス終了に備えるシステム運用 / cariot-cloud-shokudo
cariotinc
0
140
はじめてのAI機能企画 / cariot-pm-hub-lt-night
cariotinc
0
330
車両動態管理システムCariotの リアルタイム性を実現する技術 / cariot-mobility-night2
cariotinc
0
310
【プロダクト開発部】株式会社キャリオット会社説明資料 / cariot dev hiring
cariotinc
0
680
なめらか&リアルタイムな 動態管理を支えるCariotのAWS基盤 / cariot-xtech-jaws
cariotinc
0
41
Node.jsと仲良くなって Salesforceアプリケーション開発を楽しく行う / cariot-salesforce-summer2016tokyo
cariotinc
0
38
Featured
See All Featured
The untapped power of vector embeddings
frankvandijk
2
1.7k
Writing Fast Ruby
sferik
630
63k
Site-Speed That Sticks
csswizardry
13
1.2k
Marketing to machines
jonoalderson
1
5.3k
Heart Work Chapter 1 - Part 1
lfama
PRO
7
36k
Designing Experiences People Love
moore
143
24k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
340
Unsuck your backbone
ammeep
672
58k
WCS-LA-2024
lcolladotor
0
600
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
290
Transcript
10年続くJavaシステムの進化を支える戦略 API・DB・キャッシュの互換性設計 2026/05/30 遠藤 匠 JJUG CCC 2026 Spring
2 自己紹介 遠藤 匠 (Takumi Endo) 株式会社キャリオット プロダクト開発部 部長 エンジニアリングマネージャー兼フルスタックエンジニア
15年以上エンタープライズの Javaアプリケーションの開発に関わっています
3 今回お話する対象のシステム • 自社開発・運用のJava/Spring Bootアプリケーション ◦ 最初のコミットは2015年6月15日 • Gradleマルチプロジェクト構成なモノレポ 8
→ 25 1.2 → 3.5 Java Spring Boot Amazon Aurora MySQL Amazon ElastiCache for Valkey
4 今回お伝えしたいこと • システムにまつわる問題はアプリケーション内部だけでなく、 アプリケーションと外部との「境界」で起きがち • 持続的に進化し続けるため、将来に向けて「互換性」を意識し、 最初から作り込んで開発をしよう • 主なターゲット
◦ Webアプリケーション開発の経験者 ◦ アプリケーション開発だけでなく、スキルの幅を広げたいと思っている開 発者の方(フルスタック or フルサイクルへ)
1. 互換性 2. APIの互換性設計 3. DBの互換性設計 4. キャッシュの互換性設計 5. まとめ
発表の流れ
6 互換性(Compatibility) ある要素を別のものに置き換えても、エラーなく動くこと ※ 後方互換性:新しいバージョンのシステムが古いバージョンも扱える v1.0 v1.1 利用側 v1.0 ✅
後方互換性あり ✅
7 キャッシュ アプリケーションの外(境界) Javaアプリ DB 連携サービス クライアント ユーザー API クライアント
8 キャッシュ アプリケーションの外(境界) Javaアプリ DB 連携サービス クライアント ユーザー API クライアント
① ② ③
① APIの互換性設計
10 APIの互換性(設計方針) 一貫性を保つためのポイント 選択肢(例) パスやプロパティの形式 snake / camel 認証方式 APIキー
/ Bearer Token / HMAC署名 バージョニング パス / HTTPヘッダー / クエリパラメータ 時刻の表現 UNIX秒 / UNIXミリ秒 / ISO8601 電話番号の表現 E.164 / ハイフンなしテキスト 古いバージョンのEOLポリシー 最新Nバージョン / N年間 • 一貫性を保つ • バージョニングを考慮する
11 • 新しいAPIの追加 • 内部的な不具合の修正 • 既存のAPIに新しいプロパティを追加する • 既存のAPIの削除 •
既存のAPIのプロパティの削除 • 既存のAPIのプロパティのnull/非null、値域、型の変更 バージョニング 「この変更をしたら呼び出し側が困るか?」の視点 破壊的変更をしたらバージョンを変更する 影響:小 影響:大
12 Spring Bootでの実装例 Spring Framework 6以前 @RestController @RequestMapping(value = {"/api"},
produces = MediaType.APPLICATION_JSON_VALUE) public class AlcoholCheckController { @GetMapping({"v1/alcohol_checks", "v2/alcohol_checks"}) AlcoholCheckResultDtoV1 getAlcoholChecksV1() { ... } @GetMapping({"v3/alcohol_checks", "v4/alcohol_checks"}) AlcoholCheckResultDtoV3 getAlcoholChecksV3() { ... } } 特に標準の仕組みはないので、バージョンごとに別定義
13 Spring Bootでの実装例 Spring Framework 7以降 APIバージョニングの仕組みが標準で用意されている @Configuration public class
WebConfiguration implements WebMvcConfigurer { @Override public void configureApiVersioning(ApiVersionConfigurer configurer) { configurer .usePathSegment(1) .setDefaultVersion("1.0") .addSupportedVersions("1.0", "2.0", "3.0", "4.0"); } }
② DB(永続データ)の 互換性設計
15 DBの互換性(設計方針) • データベース内のデータは大事な資産 • スキーマ変更(DDL)やデータ更新(DML)の手段は1つに絞る ◦ アプリケーションロジック外からデータを操作しない ▪ ロジックを通さない変更はデータの整合性を破壊する
DDL = Data Definition Language : 構造定義(CREATE/ALTER/DROP) DML = Data Manipulation Language : データ操作(SELECT/INSERT/UPDATE/DELETE)
16 DBの互換性(設計方針) • スキーマの変更(マイグレーション) ◦ 古くなったスキーマを新しい要件に合わせて修正し、リファクタリング ◦ マイグレーションツールの利用 ▪ 例:Flyway,
Liquibase • コードの同期 ◦ スキーマの変更を確実にコードへ反映し、不整合をゼロにする ◦ マイグレーションとコードを同一リポジトリで構成管理
17 よくある失敗と対策 失敗 対策(例) スキーマ変更をしたらテーブル全 体がロックされてしまい、アプリ ケーションが止まった • テーブルロックを伴うDDLを把握しておく(DBMS にもよるが、カラム長の増強などでも起きる)
テーブルの値を直接UPDATEしたら アプリケーションがエラーになっ た • DB内のデータの直接メンテは避ける • 想定外の値が入っていた場合にデフォルト値に フォールバック(代替)する
18 コードの同期 enumの序数の範囲外の 値が入っていると エラーになる Spring Data JPA @Column(nullable =
false, columnDefinition = "TINYINT") @Enumerated(EnumType.ORDINAL) Status status = Status.NORMAL; @Column(nullable = false, columnDefinition = "TINYINT") @Convert(converter = StatusConverter.class) Status status = Status.NORMAL; Bad Better StatusConverterの 実装により、範囲外の値を デフォルト値で代替できる
19 Expand-Contractパターン Expand Migrate Contract OLD NEW OLD NEW NEW
アプリ アプリ アプリ 段階的に古いスキーマを削除
③ キャッシュ(一時データ)の 互換性設計
21 Spring Bootのキャッシング • キャッシュがヒットしたら、キャッシュをそのまま返す • キャッシュがヒットしなかったら、メソッドを呼び出し、キャッシュを更新 @Service public class
ReportService { @Cacheable("reports") public Report generate(Long reportId) { /* ... */ } } • 使えるプロバイダーは ConcurrentHashMap, Caffeine, Valkeyなど色々
22 キャッシュ戦略 • キャッシュと実データにはズレが起きる • キャッシュ/実データへの各層でエラーが起きた時の考慮 • 設計次第だが、テストコードの複雑さも増やす (キャッシュされたデータが他のテストの結果を影響し得る) 使わないで済むなら、なるべく使わない
23 よくある失敗と対策 失敗 対策(例) いつの間にか削除(evict)されて しまっていた • キャッシュサーバも適切にモニタリング • ゴミが残り続けないように有効期限
(TTL: Time-To-Live)を必ず設定 大事なデータが失われてしまった • 消えたら困るデータはDBなどに保存 JavaやSpringのバージョンアップ 後に認証エラー(※) • デシリアライズエラーの適切なハンドリング • JSONなど互換性の高い方式でシリアライズ • バージョンアップ前のキャッシュクリア ※ セッションデータをJavaシリアライズ形式で キャッシュするためバージョン間で非互換になる
24 まとめ API DB キャッシュ 一貫性のある設計とバージョニングで クライアントとの約束を守る 変更は限られた操作に限定し、中のデータを 壊さないまま、スキーマとコードを進化させていく 使い所とリスクを把握した上で、
型安全に正しく使う
25 ふりかえって • 初期からの互換性に関する凡事徹底 • 初期からの自動テストの作り込み • 後方互換性を重視しつつ、進化しているJava言語の特性 作り直しすることなく、10年間アップデートができた要因 システムの修正コストが上がる要因
• 過去の互換性を保つため、影響範囲の調査やテストに時間がかかる
26 おわりに 互換性設計は、技術を広く知り、システムを俯瞰して見ていく 必要がある 将来どのような変更をするかは予測できないが、将来の変更に 耐え得るような設計をすべき いつでも『壊れないインターフェース設計(互換性)』に 責任をもつのはAIではなく人間
ご清聴ありがとうございました