Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
【業務アプリのモダナイズ】このまま保守・改修し続けて大丈夫ですか?
Search
Satoshi Kaneyasu
September 21, 2026
Programming
8
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
【業務アプリのモダナイズ】このまま保守・改修し続けて大丈夫ですか?
Satoshi Kaneyasu
September 21, 2026
More Decks by Satoshi Kaneyasu
See All by Satoshi Kaneyasu
今から学ぶベクトルデータベース基礎知識からAmazon Bedrock Knowledge Basesまで
satoshi256kbyte
1
3
Amazon Managed Grafana で Amazon DynamoDB のデータを可視化する Infinity Plugin + プライベート API 構成
satoshi256kbyte
1
22
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
810
AWS Transform Customによる Spring Boot 2.xから4.xへのVerUp
satoshi256kbyte
2
160
運用ダッシュボードの設計を誰も教えてくれないのだけどみなさんどうしてるんですか? - チームに監視するという文化を根付かせるための第一歩を踏みたい -
satoshi256kbyte
1
210
AWS CDK ExpressモードとCI/CDの組み合わせ
satoshi256kbyte
1
63
AWS re:Invent 2025の少し振り返り + DevOps AgentとBacklogを連携させてみた
satoshi256kbyte
3
250
Amazon_Cognito_で構築する_スケーラブルな_Web_アプリケーション__シングルページ_Web_アプリケーションに認証を組み込む
satoshi256kbyte
0
55
人間とAI、どちらが書いたコードもCI/CDでチェックしてみよう
satoshi256kbyte
0
64
Other Decks in Programming
See All in Programming
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
150
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2k
Are APIs Still Relevant in the AI Era?
soyuka
0
270
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
150
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
130
そのリトライ、死んだコネクションを使い回していませんか ── GoのHTTPクライアントとHTTP/2を実プロダクト障害から学び直す
myus4a
0
150
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
570
Webの地図
yosuke_furukawa
PRO
6
4.6k
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
6
2.3k
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
7.5k
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
730
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
500
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
Music & Morning Musume
bryan
48
7.4k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Why Our Code Smells
bkeepers
PRO
340
58k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
The SEO Collaboration Effect
kristinabergwall1
1
570
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
410
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
76k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Optimising Largest Contentful Paint
csswizardry
37
4k
Transcript
【業務アプリのモダナイズ】 このまま保守・改修し続けて大丈夫 ですか? 2026/07/23 株式会社サーバワークス アプリケーションサービス本部
Speaker Introduction 氏名:兼安 聡 所属:株式会社サーバーワークス アプリケーションサービス本部 在住:広島 担当: PM、SM、DevOps、仕様駆動開発 SNS(X):@satoshi256kbyte
• • • • • • 2026 Japan AWS Ambassadors 2024-26 Japan AWS Top Engineers 2024-26 Japan AWS All Certifications Engineers 2025-26 AWS Community Builders 認定スクラムマスター PMP 2
目次 1. モダナイズとは 2. Java+Spring Bootのモダナイズを考える 要件定義 As-Is To-Be
基本設計 技術スタック確定 実装とテスト、そして仕様駆動開発 3. 運用定着への道程 4. まとめ
モダナイズとは
モダナイズとは ⚫ 既存システムを最新のアーキテクチャ・技術要素へ刷新すること ⚫ 延命だけなく、その後の改修・拡張のしやすさまで含めて設計する ⚫ 「動いているから触らない」から「変化に強い状態を保ち続ける」への転換 5
モダナイズの効果 観点 効果 セキュリティ 古いコンポーネントの解消による脆弱性リスクの低減 俊敏性・市場投入速度 技術的負債の解消、影響範囲の局所化、 トレーサビリティの向上などによる保守性の向上 回復性・運用効率 障害耐性の向上と、手動運用作業の低減
コスト最適化 需要に応じた最適なリソース配分 ※セキュリティはモダナイズ一回でリスクゼロにすることはできません。 どうしても継続的な対応が必要になるものです。 6
本発表のモダナイズにおけるAIの役割 ⚫ 本発表では、モダナイズ全てをAI駆動開発で行うとはしていません。 ⚫ モダナイズをウォータフォール開発になぞらえて、工程ごとにAIの使い方を変えています。 工程 AIの役割 要件定義 現行資産の読解・情報収集における壁打ち相手 基本設計
移行方式・アーキテクチャの技術的な裏取り 詳細設計・実装・単体テスト 機械的な変換作業の自動化、仕様駆動開発によるコード生成 結合テスト・総合テスト テストケース・テストデータの作成、バグ分析の支援 ※本発表ではテスト工程はスキップします 運用・保守 障害発生時のインシデント調査、異常検知の支援 7
Java+Spring Bootのモダナイズを 考える
題材とするサンプルアプリケーション ⚫ 今回はJavaで実装されたシンプルな業務Webアプリケーションを題材にします。 ⚫ SPAではなくMPA(フロントエンドとバックエンドが分かれていない)構成です。 ⚫ 社員のデータを扱うWebアプリケーションで、写真のアップロード機能を有します。 クライアント Appサーバー Spring
Boot 2.7 DBサーバー MySQL5.7 9
現環境(As-Is)の技術スタック 項目 内容 言語 Java 11 フレームワーク Spring Boot 2.7系、Spring
Data JPA(Hibernate)、Thymeleaf データベース MySQL 5.7 APサーバー Embedded Tomcat(Spring Boot標準) 認証方式 フォーム認証+インメモリ管理 ログ出力方式 Logback(Spring Boot標準) ファイルストレージ ローカルストレージ 10
要件定義 As-Is To-Be
現環境(As-Is)の課題 領域 課題 セキュリティ Spring Boot 2.x(OSSサポートは2023年11月終了)、 Java 11、MySQL 5.7
のEOLによる脆弱性リスク 実装パターン WebSecurityConfigurerAdapter等、2.x時代の標準的な実装パターンが 既に非推奨化されており、放置するほど将来の書き換えコストが増える アーキテクチャ モノリシックな作りのため、影響範囲の特定や機能単位での改修が困難 インフラ 単一固定サーバーによるスケーリング限界 手動運用による設計書とサーバー設定の剥離 ※UIに関して大きな課題はないとします。 12
目指す姿(To-Be) 13
目指す姿(To-Be)(着目ポイント ) 14
目指す姿(To-Be)の技術スタック 項目 内容 言語 Java 25 フレームワーク Spring Boot 4.x系、Spring
Data JPA(Hibernate 7)、Thymeleaf データベース Amazon Aurora MySQL 8.x系 APサーバー Embedded Tomcat(Spring Boot標準) 認証方式 フォーム認証+Spring Session + Redis(Amazon ElastiCache) ログ出力方式 Logback(Spring Boot標準)+Amazon CloudWatch Logs ファイルストレージ Amazon S3 15
目指す姿(To-Be)の技術スタック(AWS)とねらい 領域 採用するAWSサービス ねらい コンテナ実行基盤 Amazon ECS(Fargate) • サーバーレスなコンテナ運用 •
ローカル開発にDockerを使用することで、 ローカルと本番の環境差を軽減 負荷分散と分岐点 Application Load Balancer • ルーティング最適化とスケーラビリティ確保 • 機能的な分岐点を設置可能へ 外部記憶媒体 Amazon S3 Amazon ElastiCache for Redis • ファイル・セッション・キャッシュの外部化 • スケーラビリティの阻害要因の排除 • リソース不足に陥る可能性を軽減 機密情報管理 AWS Secrets Manager • 設定ファイルのGitへの誤Pushリスクの軽減 • パスワードローテーション機能などの恩恵 AWS CDK • 手動作業の軽減 • 環境構築の再現性の向上 • 設計書と環境の剥離を軽減 IaC 16
コンテナ(Amazon ECS on Fargate)かAWS Lambdaか? 観点 コンテナ(ECS on Fargate) (採用)
サーバーレス(AWS Lambda) 既存コードの流用 Dockerイメージ化のみでほぼそのまま 移行可能 モノリスのままでは動かず、 関数単位への分割が前提になる 開発・本番環境の一致 ローカルのDocker Composeと本番 Fargateがほぼ同じ環境 ローカルでのLambda実行環境の再現が コンテナほど容易ではない 実行時間の制約 制約なし 最大15分(長時間処理には不向き) コールドスタート 常駐のため意識不要 JVMは初期化が重く、 SnapStart等の対策検討が必要 ⚫ Lambda Web Adapterのように既存コードをそのままLambda化できる仕組みもありますが、 「学習コスト」「サーバーレス化による新たな課題が生まれないか」を踏まえ、 今回は「コンテナ」を選択します。 17
MySQLかPostgreSQLか? 観点 Aurora MySQL(採用) Aurora PostgreSQL 既存資産との互換性 MySQL 5.7からの移行で変更 が少なく、確実性が高い
方言の違いにより、生SQLやDDLの書き換えが 必要 先進的な機能 基本的なRDBMS機能が中心 RLS(行レベルセキュリティ)や列単位のアクセ ス制御など 移行の手間・リスク 低い クエリ変換やテストの工数が増える ⚫ 業務アプリケーションにおいて現在勢いが勝っているのはPostgreSQL。 将来的に列単位のアクセス制御のような先進機能を使いたいならPostgreSQLが有利です。 ⚫ とはいえMySQLがなくなるわけではないので、確実性を重視してMySQLを選択します。 18
Amazon Cognitoを採用するか? 観点 既存のSpring Boot認証 (採用) Amazon Cognito メリット 実装済みのロジックを変更しないため、
移行コストも不具合リスクもない マネージド型のユーザー管理、 MFAなど標準機能が充実 マイクロサービスとの相性 サービスが単一(モノリス)のため、 恩恵は限定的 JWTトークンにより複数サービス間で 認証情報を共有しやすい 移行コスト 変更なし ログイン/ログアウトフローの作り直し、 ユーザーストアの移行が必要 ⚫ Cognitoは利便性が高く、マイクロサービス環境での恩恵が大きくはありますが、 今回は一般消費者向けではなく単一の業務アプリであり、移行コストに見合うだけの益がある とは言い切れません。 ⚫ そのため今回の認証はSpring Bootの既存実装のまま残し、スケーリングの妨げとなるセッシ ョンだけをElastiCache for Redisに外部化するとします。 19
モダナイズの3ステップ(段階移行アプローチ) 1) 既存構成をコンテナ化 2) AWS Transform custom による自動アップグレード 3) AWSネイティブアーキテクチャへ移行
言い換えると、1)ローカルでの作業をやりやすくし、2)AIの力でできる限り自動アップグレードし て、3)AWSに合わせつつ本格的なモダナイズをする、という3ステップです。 単純にAmazon EC2に移行し、 その後でモダナイズするやり方もありますが今回はそれはスキップします。 20
基本設計 技術スタック確定
モダナイズの3ステップによる技術的な裏取りと確定 要件定義で決めた技術スタックを、全機能に対して展開する前に 「机上の決定が実際に成立するか」を裏取りして確定させます。 ステップ 検証項目 Step1 コンテナ化 そもそもコンテナ化可能なのか? Windowsサーバーや特異なライブラリを使用している場合、 工夫が必要になる
Step2 アップグレード ①AWS Transform customでアップグレードできるか? ②アップグレードした結果が動くか? ③Transform customではアップグレードできないものを見極め →後工程(実装フェーズ)のタスクとして挙げる Step3 クラウドネイティブ検証 To-Beの構成で、小規模に動作確認する 22
Step1 コンテナ化の検証 ステップ 担当 内容 現行環境の情報収集とAIへの投入 人間 設計書の収集、サーバーへのログインによる 設定・バージョン確認 コンテナのベースイメージの選定
AI+人間 OS・JDKバージョンに応じた適切なベースイメージ を選定 依存ライブラリの取得可否確認 AI+人間 パッケージ管理でインストールできないライブラリを 洗い出し、リポジトリに同梱 Dockerfileと docker-compose.ymlの生成 AI 収集した情報を基に、コンテナ定義ファイルをAIで 生成 動作検証 人間 ローカルのdocker-compose環境で実際に起動し、 動作を確認 差分の修正 人間+AI 動かない箇所を人間が切り分け、AIに修正させる 23
Step2 AWS Transform customのスコープの見極め 一旦全体をTransform customで、自動でアップグレードできる範囲を見極めます。 ⚫ Java 11 →
25へのバージョンアップ ⚫ Spring Boot 2.x → 4.x ⚫ javax → jakarta 名前空間移行 ⚫ Spring Security DSL 更新 ⚫ 依存ライブラリの互換性修正などを一括変換 とはいえ、以下のものは高確率で対応できないので、最初から別タスクを検討しておきます。 変更点 内容 ファイルストレージのS3化 ローカルファイルパスへの直書きを、S3 SDK呼び出しに変更 セッションの持ち方 インメモリ保持から、ElastiCache for Redisへの外部化(Spring Session設定) DB接続情報の取得方法 application.ymlの固定値から、Secrets Manager経由の動的取得へ変更 画面側のパス生成 ファイルパス・画像パスの生成ロジックを、S3のURL生成に合わせて変更 ログ出力の方法 アプリコードの変更ではなく、サーバー設定側の対応で済む可能性もある 24
Step3 一部機能をクラウドネイティブ化して動作確認する ⚫ 全機能ではなく、一部の機能に絞ってTo-Beの構成上で動かしてみます。 ⚫ 検証対象に選ぶのは「認証・ファイルアップダウン・DB接続」を横断的に使う機能。 (例:ログイン後にファイルをアップロードし、DBにメタデータを保存する機能) ⚫ ALB →
ECS(Fargate)→ Aurora/S3/ElastiCache for Redis/Secrets Manager という 一連の構成が、実際に一つの機能で成立するかを確認します。 25
実装とテスト、そして仕様駆動開発
仕様駆動開発(SDD)とは ⚫ 実装とテストはできる限り仕様駆動開発(SDD)を活用するのがお勧め ⚫ AIがいきなりコードを書くのではなく、まずAIに満たすべき仕様や制約を厳密に定義させる ⚫ 厳密に定義した仕様をもとにAIにコードを書かせるので進捗・品質・再現性が安定化しやすい (注)仕様駆動開発における要件定義は、ウォーターフォール開発の要件定義とは似て非なるものです 要件の入力 要件定義
設計 実装計画 要件定義書 設計書 タスクリスト 実装 コード 人間がレビュー可能 27
実装工程のWBS-1 WBS 開発手法・アプローチ 役割分担 SDD(仕様駆動開発) • 人間が既存情報を収集 • AIがコード生成 •
人間がレビュー ローカル実行基盤の作成 (Docker Compose等) SDD(仕様駆動開発) • 人間が既存情報を収集 • AIがコード生成 • 人間がレビュー Java 11→25 アップグレード AWS Transform custom • AIが自動変換 • 人間がレビュー Spring Boot 2.x→4.x アップグレード AWS Transform custom • AIが自動変換 • 人間がレビュー Transform customで変換しきれない 箇所の修正 SDD(仕様駆動開発) • AIがコード生成 • 人間がレビュー 既存アプリのコンテナ化 28
実装工程のWBS-2 WBS 開発手法・アプローチ 役割分担 新アーキテクチャのIaC作成 (ユニットテスト込み) SDD(仕様駆動開発) • AIがコード生成 •
人間がレビュー ファイルストレージのS3化 SDD(仕様駆動開発) • AIがコード生成 • 人間がレビュー セッション・キャッシュの外部化 SDD(仕様駆動開発) • AIがコード生成 • 人間がレビュー DB接続情報の取得方法の変更 SDD(仕様駆動開発) • AIがコード生成 • 人間がレビュー 画面側のファイルパス・画像パス生成の 変更 SDD(仕様駆動開発) • AIがコード生成 • 人間がレビュー 29
テスト方針:新機能は自動テスト、既存は現新比較 ⚫ 自動テストを書くということは、コードをテスト可能な形に寄せることでもあります。 既存コード全体を今回のモダナイズでそこまで持っていくのはおそらく不可能で、 せっかく今まで動いていたコードを必要以上に変えてしまうリスクの方が高くなります。 ⚫ 既存で動いていたものは下手に変えず、旧環境と新環境の動作を比較する 「現新比較」に寄せます。 ⚫ 一方で新機能(AWSネイティブを活用する部分:S3、ElastiCache、Secrets
Manager連携等)は、 新規に書くコードだからAIでSDDを用いて自動テストを書く方に全力で寄せていきます。 30
データベース移行方針 ⚫ MySQL5.7から8.x系の移行は、AWS Database Migration Serviceを使う方法が考えられるが、 一般的な業務アプリケーションなら、ダンプ&リストアで事足りる可能性が高いです。 ⚫ MySQL 5.7から8.xへの移行では、デフォルトのソート順(ORDER
BY句なしの場合)など、 いくつかの挙動が変わっています。 ⚫ これらの挙動の変化をAIに調査&修正させつつ、テスト工程で挙動の違いに着目したテスト項目を挙 げると良いでしょう。 31
AIに生成させたDockerfile・docker-compose.ymlの例 AppサーバーDockerfile # Stage 1: Build FROM maven:3.8-eclipse-temurin-11 AS build
WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src COPY checkstyle.xml . RUN mvn package -DskipTests -B # Stage 2: Run FROM eclipse-temurin:11-jre WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"] docker-compose.yml version: '3.8' services: app: build: . ports: - "8080:8080" environment: SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/employee_db?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=Asia/Tokyo SPRING_DATASOURCE_USERNAME: app_user SPRING_DATASOURCE_PASSWORD: app_password volumes: - photo-data:/data/employee-photos depends_on: db: condition: service_healthy db: image: mysql:5.7 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root_password MYSQL_DATABASE: employee_db MYSQL_USER: app_user MYSQL_PASSWORD: app_password volumes: - db-data:/var/lib/mysql command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5 volumes: db-data: photo-data: 32
AWS Transform custom の設定ファイル(config.yaml) codeRepositoryPath: ./step1-legacy transformationName: AWS/spring-boot-version-upgrade buildCommand: mvn
clean install validationCommands: | mvn checkstyle:check mvn verify additionalPlanContext: | 途中省略 ## 実施してほしい変更(優先度順) 途中省略 ## 検証について - buildCommand・validationCommands(mvn checkstyle:check, mvn verify)を 実際に実行し、全て成功する状態まで修正を繰り返してから完了としてください。 ビルド・テストを一度も実行せずに「完了」と報告することは禁止します - checkstyle違反を消すためだけに、使っていないimport文を追加したまま 残す、あるいはテストコードを無効化・削除・skipすることで検証を 通すことは禁止します。原因そのものを修正してください (パス・リクエスト/レスポンス形式) 1. pom.xml の spring-boot-starter-parent のバージョンを 4.1.x に更新し、 java.version プロパティを 25 に変更する 2. ソースコード全体で javax.* パッケージを jakarta.* に置換する (persistence, validation, servlet の各名前空間) 3. WebSecurityConfigurerAdapter を継承するクラスを廃止し、 SecurityFilterChain を返す @Bean メソッドへ書き換える 4. antMatchers() を requestMatchers() に、authorizeRequests() を authorizeHttpRequests() に置換し、and() チェーンをラムダDSLへ書き換える 5. Jackson の ObjectMapper 利用箇所(本体コードおよびテストコード)の import を tools.jackson.databind.ObjectMapper に更新する (アノテーションの import は変更しない) 6. MySQL Connectorの依存関係を mysql:mysql-connector-java から com.mysql:mysql-connector-j へ切り替える 7. thymeleaf-extras-springsecurity5 の依存関係を thymeleaf-extras-springsecurity6 へ 切り替え、Thymeleafテンプレート内のnamespace宣言も合わせて更新する 8. Flyway の依存関係を、flyway-core の直接依存のままにせず spring-boot-starter-flyway 経由に切り替える。 Spring Boot 4.1では flyway-core を直接依存させるだけではFlyway自体が起動せず、 アプリ起動時にテーブルが1つも作成されない(Schema validation: missing table エラーになる)ため、これは必須の変更です 9. Dockerfile のビルドステージ・実行ステージのベースイメージを、pom.xmlの java.version(25)に合わせて更新する (maven:3.9-eclipse-temurin-25 / eclipse-temurin:25-jre)。 pom.xmlだけJava 25にしてDockerfileをJava 11のまま放置すると、 コンテナビルド時に「release version 25 not supported」で失敗します 右側に続く 33
AWS Transform custom の変換結果の例 @Configuration @EnableWebSecurity public class SecurityConfig extends
WebSecurityConfigurerAdapter { 変換前 @Configuration @EnableWebSecurity public class SecurityConfig { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/css/**", "/js/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/employees", true) .permitAll() .and() .httpBasic() .and() .logout() .logoutSuccessUrl("/login?logout") .permitAll() .and() .csrf() .ignoringAntMatchers("/api/**"); } } 変換後 @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize .requestMatchers("/css/**", "/js/**").permitAll() .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") .defaultSuccessUrl("/employees", true) .permitAll() ) .httpBasic(httpBasic -> { }) .logout(logout -> logout .logoutSuccessUrl("/login?logout") .permitAll() ) .csrf(csrf -> csrf .ignoringRequestMatchers("/api/**") ); return http.build(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder encoder = PasswordEncoderFactories .createDelegatingPasswordEncoder(); auth.inMemoryAuthentication() .withUser("admin") .password(encoder.encode("admin123")) .roles("ADMIN"); } } @Bean public UserDetailsService userDetailsService() { PasswordEncoder encoder = PasswordEncoderFactories .createDelegatingPasswordEncoder(); var user = User.withUsername("admin") .password(encoder.encode("admin123")) .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(user); } 34
AWS Transform custom で対応しきれなかったもの 項目 内容 指示見直し後再実行 で解消 Dockerfile Dockerfile
のベースイメージが Java 11 のままで、pom.xml の java.version: 25 と矛盾し、コンテナビルドが失敗する ◦ 未使用のインポート SecurityConfig.java に未使用の import が残り、Checkstyleが失敗す る ◦ flyway-core の直接依存 flyway-core の直接依存のままで spring-boot-starter-flyway に切り 替わっておらず、Flyway自体が起動せずテーブルが作成されない ◦ プラグインのバージョン maven-checkstyle-pluginが3.3.1のままで、includeTestSourceRoots パラメータが認識されず警告が出ていた (テストソースがCheckstyle対象から漏れる可能性があった) ⚫ 対応できなかったものは指示を具体化して再実行かけることで成功するパターンもあります。 ⚫ とはいえ、細かい部分でカバーしきれないものは存在するので100%にはなり得ません。 ⚫ Transform customで綺麗に移行することに拘るのも効率的ではないので、 初回で対応できなかったものについて指示を具体化するか、 直接修正かけるかはコスト・スケジュールとの相談となります。 35
AIと仕様駆動開発で修正したコードの例① @Service public class PhotoStorageService { 修正前 @Service public class
EmployeePhotoService { 修正後 private final String uploadDir; private final FileStorageService fileStorageService; public PhotoStorageService(@Value("${app.upload.dir}") String uploadDir) { this.uploadDir = uploadDir; } public EmployeePhotoService(FileStorageService fileStorageService) { this.fileStorageService = fileStorageService; } public String store(MultipartFile file) { if (file == null || file.isEmpty()) { throw new IllegalArgumentException("アップロードされた写真が空です"); } if (!ALLOWED_CONTENT_TYPES.contains(file.getContentType())) { throw new IllegalArgumentException( "対応していないファイル形式です(jpg/png/webpのみ): " + file.getContentType()); } public String store(MultipartFile file) { if (file == null || file.isEmpty()) { throw new IllegalArgumentException("アップロードされた写真が空です"); } if (!ALLOWED_CONTENT_TYPES.contains(file.getContentType())) { throw new IllegalArgumentException( "対応していないファイル形式です(jpg/png/webpのみ): " + file.getContentType()); } try { Path dir = Paths.get(uploadDir); Files.createDirectories(dir); String key = "employee-photos/" + UUID.randomUUID() + extractExtension(file.getOriginalFilename()); try { fileStorageService.store(key, file.getInputStream(), file.getContentType(), file.getSize()); } catch (IOException e) { throw new UncheckedIOException("写真の保存に失敗しました", e); } return key; String extension = extractExtension(file.getOriginalFilename()); String photoKey = UUID.randomUUID() + extension; Path target = dir.resolve(photoKey); } file.transferTo(target); return photoKey; } catch (IOException e) { throw new RuntimeException("写真の保存に失敗しました", e); } public InputStream load(String photoKey) { return fileStorageService.load(photoKey); } } } public InputStream load(String photoKey) { try { Path target = Paths.get(uploadDir).resolve(photoKey); return Files.newInputStream(target); } catch (IOException e) { throw new RuntimeException("写真の読み込みに失敗しました: " + photoKey, e); } } } public interface FileStorageService { void store(String key, InputStream inputStream, String contentType, long size); InputStream load(String key); void delete(String key); boolean exists(String key); } @Service @Profile("aws") public class S3FileStorageService implements FileStorageService { 36
AIと仕様駆動開発で修正したコードの例② EmployeePhotoService 呼び出し FileStorageService インターフェース 実装 実装 @Profile("local") LocalFileStorageService @Profile(”aws")
S3FileStorageService ローカル開発の時はこちら ローカルディスクに保存 本番環境はこちら Amazon S3に保存 ※事前にAIにローカル開発を意識させないと、このようなコードを書いてくれない時があります。 37
運用定着への道程
運用定着するとは? ⚫ システムの状態を観測可能になる ⚫ システムの障害調査がしやすくなる ⚫ 継続的な改善を維持できる ⚫ 体制・役割分担(誰が何を担当するか)の明確化 ⚫
ドキュメント・ナレッジ文化の定着 39
システムの状態を観測可能にし、異常を検知しやすくする ⚫ AWS Security Hubで、セキュリティの状態を継続的に可視化・一元管理します。 ⚫ 運用ダッシュボードを構築し、まずはユーザーにより近い領域のメトリクス(指標)を可視化し、 何かが起きた場合に気づきやすくなる仕組みを構築します。 今回の構成なら、 まずはここのメトリクスに着目する
40
静的閾値と異常検知(Amazon CloudWatch Anomaly Detection) ⚫ メトリクスにアラームを設定し、異常を早期検知可能にします。 ⚫ 明確に閾値が設けられるものは、静的な閾値でアラームを設定。 ⚫ 静的な閾値を設けるのが難しいものは、
CloudWatch Anomaly Detection(機械学習による異常検知)が有効です。 エラー数など静的な閾値が定められるものは静的アラーム リクエスト数など傾向から判断するしかないものはAnomaly Detection 引用:アラーム評価 - Amazon CloudWatch 引用:CloudWatch 異常検出の使用 - Amazon CloudWatch 41
システムの障害調査をしやすくする ⚫ AWS DevOps Agentを用いると、テレメトリ・コード・デプロイ履歴を横断的に関連付け、 AIに障害の原因と対策案を提示させることができます。 ⚫ これにより、開発者以外でも障害調査がやりやすくなります。 42
継続的な改善を維持する体制を整える ⚫ CI/CDパイプラインを構築し、セキュリティチェック、テスト、デプロイを自動化します。 ⚫ 基本的にテストの範囲は少しずつ広げていくのが望ましいです。 新機能から自動テストの対象を広げ、 現新比較への依存を段階的に減らしていきます。 ⚫ AWS Transform
custom をCI/CDパイプラインに組み込めば、 将来のフレームワーク・ライブラリアップグレードも継続的に自動化することができます。 Transform Custom パイプライン 月一度の定期実行 Tranform Custom による変換 変換結果を プルリクエストへ デプロイパイプライン プルリクエストのマージで発動 手動マージ リンター テスト セキュリティチェック デプロイ 43
まとめ
まとめ ⚫ モダナイズは「動いているから触らない」から「変化に強い状態を保ち続ける」への転換 ⚫ モダナイズは変化を妨げる要因の排除に注力する ⚫ 本発表では、モダナイズの工程ごとにAIの使い方を変えました 私は実作業にAIをフル活用するとしても、AIに投入する適切な単位に分けるところまでは、 AIの補助を得つつも人間主体でやるべきと考えます 工程
AIの役割 要件定義 現行資産の読解・情報収集における壁打ち相手 基本設計 移行方式・アーキテクチャの技術的な裏取り 詳細設計・実装・単体テスト 機械的な変換作業の自動化、仕様駆動開発による コード生成 運用・保守 障害発生時のインシデント調査、異常検知の支援 45
None
参考資料 ⚫ ⚫ AWSサービス関連 ⚫ データベース移行関連 AWS Transform custom
MySQL 8.0 Reference Manual: Sorting Rows AWS Transform custom: AI-driven Java modernization to reduce tech debt Removal of implicit and explicit sorting for GROUP BY Amazon ECS on AWS Fargate(ユーザーガイド) AWS Lambda Web Adapter(GitHub) Amazon Aurora MySQLについて Aurora MySQL version 3(MySQL 8.0互換) Amazon ElastiCacheとは AWS Secrets Managerとは AWS Cloud Development Kit (AWS CDK) v2 デベロッパーガイド Amazon Cognitoとは AWS Database Migration Service (DMS)とは AWS Security Hubとは AWS DevOps Agentについて ⚫ 運用監視関連 アラーム評価 - Amazon CloudWatch CloudWatch 異常検出の使用 - Amazon CloudWatch Monitoring Distributed Systems フレームワーク・言語関連 Spring Boot 2.7 Support Period Extended(Spring公式ブログ) Spring Boot 3.0 Migration Guide(Spring公式Wiki、javax→jakarta移行) Spring Security: Upgrading the Deprecated WebSecurityConfigurerAdapter(Baeldung) 47